一、前言
在之前的一篇文章中我們已經詳細介紹了Android中Hook工作的一款神器Xposed工具:Xposed架構原理解析和使用案例分析 在那一篇文章中我們介紹了如何安裝Xposed架構,以及如何使用Xposed庫編寫第一個模組來做到修改系統方法功能的效果,同時也說到了一個非常重要的知識點就是:在Hook過程中最重要的一點就是如何找到Hook點,而對於這一點很多同學都會感覺到非常的困難,因為對於修改系統方法還好,因為可以簡單的去查看具體的Android源碼即可,但是如果說要去編寫一些應用和遊戲的外掛的話,那麼第一步就得先去破解對應的App找到指定Hook點,這一步是非常困難的。所以只能多嘗試多破解慢慢長點經驗即可。
二、猜想假設
本文就藉助之前的Xposed架構來介紹如何編寫微信的一個外掛功能,這個功能就是微信搖色子和剪刀石頭布的作弊器,我們用過微信這個功能都知道,是一個比較常用的功能,因為在一個群聊中會很無聊就來這種簡單的比賽,誰輸了發紅吧啥的。那麼這個功能肯定伴有隨機性,而且我們應該相信這個隨機方法肯定是在微信代碼中的某個地方,所以如果我們找到這個方法了,那麼就可以進行Hook他,然後攔截返回最大的數值即可,也就是我們想要得數值。
三、準備工作
上面大致分析了這個功能的原理使用,下面咋們就不多說了,直接進行操作,本文用了一個微信的老版本做測試的:微信6.3.9.apk ;那麼第一步咋們得逆向微信,需要做兩個工作:
第一先使用apktools反編譯apk,這個不用多說了,微信沒有對應用進行加固,所以反編譯過程很正常。
第二需要藉助可視化反編譯工具Jadx來開啟微信apk,因為微信應用很大,所以得慢慢等待一會才可以開啟。
四、逆向分析
下面在來冷靜分析一下如何我們該怎麼入手?上面反編譯成功了之後,還得尋求入口,這個入口也很簡單的,因為我們想得到這個隨機函數,那麼在我們能看到的效果是色子,我們可以選擇一個微信聊天對話方塊,然後點擊一個色子功能:
看到了,我們點擊色子之後肯定會調用這個隨機函數擷取隨機值,那麼這裡就是我們的入口,所以第一步肯定先找到這個點擊事件,如果要找到點擊事件,那麼就得先找到這個控制項的定義,那麼問題來了,如果能夠快速的找到這個控制項的定義呢?這個技術在我之前的一篇文章中已經介紹了,就是 微信的自動搶紅包功能 當時因為要找到那個紅包的點擊事件,所以就用同樣的方法來得到那個紅包的控制項定義的地方,而這個方法就是藉助AndroidSDK提供的一個工具:uiautomatorviewer.bat 這個工具位於SDK目錄的tools目錄下,我們可以點擊運行,然後就可以看到這個介面了:
我們把裝置停在聊天對話方塊中,然後使用這個工具,點擊左上方那個按鈕,可以進行當前案頭的介面布局分析,分析結果我們可以看到,這個色子是一個自訂控制項:com.tencent.mm.ui.MMImageView,然後他的id是ae7,而這個值非常關鍵,後面就是用這個值來進行一步一步的跟蹤,這裡我們再多看一眼,就是這個表情地區的詳細布局:
猜也猜到了,表情地區外面應該是一個ViewPager控制項可以進行滑動切換,然後是每一頁的控制項用的是GridView進行卡片分割,那麼這裡就會給我們一個提醒了:後面的點擊事件要麼是在GridView的適配器類的getView方法中對view進行setOnClickListener添加的,要麼是對GridView添加onItemClick事件的。
好了下面繼續跟蹤,因為有了那個色子控制項的id了,下面咋們可以直接用這個id去全域搜尋這個值了,不過這裡有個問題就是微信其實本身做了資源的混淆,而這個混淆一方面是加大安全工作,一方面是減小包的大小功能,我們可以使用解壓工具簡單的查看他的apk檔案中的res目錄,會發現全是字母檔案夾。而且從上面的id命名也可以看到,我相信微信工程師不可能會傻逼的把一個id命名成ae7了吧?到這裡我們又要藉助一個知識點了,而這個知識點在我之前的一篇文章中介紹了:Android中的應用攻防之戰 在這篇文章中介紹了,我們在反編譯apk之後,其實apk所有的資源id值都會儲存在一個public.xml檔案中,而這個檔案是放在values目錄下的,這個檔案主要存放的就是資源的id值和name,type之間的對應關係,而反編譯之後的代碼中一般不會用R.id.xxx這種樣式來訪問控制項,而是用轉化之後的id值,這個值是十進位的,所以我們得先用上面那個ae7的id值去public.xml檔案中找到對應的十六進位值:
注意:
這裡在尋找ae7的時候,會發現多個匹配項,而我們需要用額外的資訊來作區分,那就是type欄位了,type欄位有很多種值,比如layout,drawable,string,attr,id等,我們這裡因為是定義控制項的所以type=id。
找到這個項之後,就把後面id的十六進位值轉化成對應的十進位值吧:0x7f07060e=2131166734
有了這個值,就好辦了,咋們直接在Jadx中開啟的微信apk中全域搜尋這個值:
哎,可惜的是沒有找到,所以到這裡就開始蛋疼了,也是這次逆向的最大阻礙了,想了好長時間,最後才突然想起來以前 逆向微信的本地通訊錄資訊 的時候發現微信採用了分包技術,也就是微信包太大,因為Android系統中有方法數的限制所以需要對apk進行拆包操作,具體可以查看這篇文章:Android中應用拆包技術詳解 那麼我們會發現反編譯之後也沒有看到多個dex檔案,所以這時候還要猜想他應該是存在本地目錄的,在應用啟動的時候主dex功能再去載入這個次dex檔案,通過查看反編譯之後的目錄,結果在assets目錄下找到了他:
而這個是兩個從dex檔案,這裡他做了dex檔案轉成jar檔案的操作了,所以我們先用解壓工具解壓這個jar檔案,得到對應的dex檔案即可。然後咋們在開啟一個Jadx視窗開啟這個從dex檔案,然後在全域搜尋上面的那個值:
看到了,終於找到了這個控制項的定義的地方了,點擊第一個進去查看:
我們在往下面看這個類的資訊,會發現到有一個getView方法:
看到這個就可以判定了,這個類其實是一個BaseAdapter類型了,而在getView中沒有看到控制項的點擊事件,所以猜想應該是外部給GridView添加的onItemClick事件了,咋們繼續選中這個類名,然後右擊進行跟蹤這個類在哪些地方被調用了,這個功能的確很實用的:
點擊尋找之後,會有很多地方調用:
這裡從第一項的那個參數命令可以猜想到了應該就是GridView類型,而到這裡我們貌似看到了勝利的曙光了:
然後查看這個smileyGrid變數的定義:
這裡是一個SmileyGrid類型的,咋們可以全域搜尋這個類,看看他的定義:
果然不出所料,這裡是一個GridView類型,然後也看到了我們非常期待的onItemClick方法了,下面就開始分析這個onItemClick方法的邏輯了:
這裡我沒有找到一個好的辦法,也不想去深入跟蹤了,因為這裡的判斷分之不是很多,所以就順序的嘗試了每個方法,結果找到了最後一個a方法,然後點進去查看邏輯:
這裡我們就需要多想點了,從我們點擊色子之後的效果看,沒有對話方塊和toast提示,那麼這裡就只有兩個分支是最有可能執行的了,通過順序嘗試之後,發現是第一處分支的邏輯了,也就是h.a.aMZ.b()這個方法執行了,通過import匯入的類,得到這個類的路徑定義:
但是在這個dex中沒有找到這個類,所以猜想應該是在主dex中,果然找到了這個類定義,然後進入這個類進行想詳細查看:
繼續進入看看b方法的定義:
擦,這裡的b方法盡然返回的是null,那麼到這裡就要思考了,如果返回null的話,之前的點擊事件肯定是無效的,而這個又不符合實際情況,所以猜想還有哪個地方對這個iop進行賦值操作了。我們看看這個iop定義:
從定義上可以看到,極大可能在其他地方進行了賦值操作,所以咋們全域搜尋這個變數值iop:
發現搜尋結果還是我們剛剛看到的返回null的代碼,所以咋們又得繼續去另外一個dex中進行搜尋了:
這裡搜到了一個賦值操作,立馬點擊進入查看:
然後查看PD方法的定義:
繼續查看這個g類定義:
看到他的b方法,這裡有一個bb.pu這個方法比較可疑,因為最終返回的值都是和他相關的,而這個方法在這個dex中又沒有找到,所以咋們看一下他的import找到全域定義路徑,然後去另外一個dex中查看定義:
到這裡,就會非常激動了,因為我們看到了勝利了,這個非常明顯的隨機方法終於找到了,而通過這個隨機公式可以看到,這個方法的功能是返回一個0-i之間的隨機值,而對於色子應該是0-6之間的值,猜拳是0-3之間的值。所以這個方法百分百是用於隨機功能的。
五、掌握逆向技能
到這裡我們就成功的找到了我們想要Hook的地方了,從上面的逆向過程會發現微信的工程非常龐大,而對於我們逆向來說工作是非常艱難的,但是還好我們有一些強大的工具可以快速的定位問題,下面就來總結本文逆向收穫的知識:
第一、對於逆向中想得到控制項點擊事件入口,可以通過以下步驟來進行
1、使用介面分析工具得到指定控制項的id名稱
2、通過id名稱去反編譯之後的values/public.xml中尋找到指定的值,轉化成十進位
3、通過Jadx內建的全域所有功能,尋找這個十進位值即可
對於這個步驟將適用於想得到一個應用中某個控制項的點擊事件邏輯入口是非常有效,而且也是通用的方法。
第二、對於微信來說,因為工程的龐大,所以肯定會存在拆包現象,所以他不止一個dex檔案。肯定是包含多個dex檔案的,所以後面還需繼續寫微信的外掛,到時候分析都是要注意這一點。
第三、對於Jadx的強大工具在本文中起到了非常重要的功能:跟蹤方法的調用,全域尋找功能。
額外說明:
在本文中我們會發現有一個難受的地方就是多個dex檔案之間尋找相應的方法的地方,所以其實我們可以這麼幹,我們如果得到了應用所有的dex檔案之後,可以將其先轉化成對應的java類,然後進行類合并,這裡我們可以使用Beyond Compare比較工具將多個不同檔案夾合并到一起:
合并之後咋們在用工具將其轉化成一個dex檔案,也就完成了多個dex檔案合并工作了。在這個工程中,我們可以非常巧妙的藉助Jadx的另外一個強大功能,就是可以把反編譯之後的內容儲存到本地:
他有個好處就是,把apk中的dex儲存成java檔案,資源全部解碼儲存指定xml檔案,而最終的儲存樣式是一個gradle工程,而這個工程咋們就可以直接匯入到一個開發工具中了非常方便了。特別是資源檔,我們在之前會發現apktools工具並沒有反編譯xml檔案出來。而在這裡就可以了。
六、開始攔截操作
下面咋們就來進行Hook操作了,上面已經得到了這個隨機函數的名稱了:
com.tencent.mm.sdk.platformtools.bb.pu(int i)
Hook工作就非常簡單了,咋們攔截這個方法之後根據傳入的值做一次判斷是搖骰子還是猜拳操作:
首先咋們得做一次過濾操作,就是只會Hook微信應用,然後到攔截操作中,通過傳遞的參數做判斷是搖色子還是猜拳,如果是搖色子就返回一點,猜拳就返回剪刀。
編寫成功之後,就進行編譯成模組,然後重啟裝置生效,點開微信開啟一個聊天框,開始搖色子:
通過列印值可以看到,我們的猜想是正確的,看一下實際效果:
哈哈哈,所有的操作都在掌控之中,到這裡我們也成功的編寫了一個微信外掛功能,而這個外掛可能有的同學感覺用途不是那麼大,而現在主流的外掛是可以防止撤銷功能,分享視頻到朋友圈,不過這些功能都會慢慢講解的,不要著急,而對於本文以及後續的外掛內容文章,我想表達的是,結果並不重要,重要的是整個逆向過程,在每次一逆向之後我們學到了什麼,是否漲了逆向經驗,這才是我們需要得到的。
補充說明:
第一點:有的同學會發現咋們上面得到的那個方法貌似是混淆之後的,也就說如果哪天微信改了混淆機制,那麼這個Hook就失效了,本文中用到的是微信6.3.9的版本,對於其他版本我想這個方法類名應該是變了,也就說如果微信每次出一個版本咋們都得去逆向一次得到方法名,但是這個都不是難事,以為本文已經將整個逆向過程講解了,所以以後只要按照這個步驟來,尋找方法也是分分鐘的事!
第二點:本文的用意是分享逆向技巧知識點,所以也請各位同學能夠知道結果不重要,重要的是整個逆向的過程,也就是如何尋找到Hook點
嚴重聲明:本文介紹的知識點完全是從一個技術分享角度出發,絕非用於任何商務工作和用途,如果涉及到任何法律問題將由操作者本人負責。本文作者將不負責任何法律責任!也請各位同學秉著技術角度出發的原則,切勿用於商業中!
七、總結
本文主要介紹了一個微信的簡單外掛功能,就是搖色子和猜拳作弊器功能,而在整個過程中,我們可以看到找到Hook點才是最關鍵的,而最難的也是找到這個點。一般都是需要進行逆向分析微信應用找到這個點。在這個過程中我們又學習到了一些新的逆嚮應用技巧知識點,後續將會繼續帶大家一起分享其他的外掛功能知識點,敬請期待,同時也要多多支援擴散分享啦,也要多多點贊呢?寫這篇文章實屬不易呀,因為逆向的我頭都炸了!