Android 微信搖骰子和猜拳作弊器原理解析
一、前言
在之前的一篇文章中我們已經(jīng)詳細(xì)介紹了Android中Hook工作的一款神器Xposed工具:Xposed框架原理解析和使用案例分析 在那一篇文章中我們介紹了如何安裝Xposed框架,以及如何使用Xposed庫編寫第一個模塊來做到修改系統(tǒng)方法功能的效果,同時(shí)也說到了一個非常重要的知識點(diǎn)就是:在Hook過程中最重要的一點(diǎn)就是如何找到Hook點(diǎn),而對于這一點(diǎn)很多同學(xué)都會感覺到非常的困難,因?yàn)閷τ谛薷南到y(tǒng)方法還好,因?yàn)榭梢院唵蔚娜ゲ榭淳唧w的Android源碼即可,但是如果說要去編寫一些應(yīng)用和游戲的外掛的話,那么第一步就得先去破解對應(yīng)的App找到指定Hook點(diǎn),這一步是非常困難的。所以只能多嘗試多破解慢慢長點(diǎn)經(jīng)驗(yàn)即可。
- 軟件名稱:
- 微信專用骰子插件下載
- 軟件功能:
- 控制骰子點(diǎn)數(shù)(單發(fā)或連發(fā))
- 適配機(jī)型: 安卓4.0以上和蘋果手機(jī)
- 立即下載
二、猜想假設(shè)
本文就借助之前的Xposed框架來介紹如何編寫微信的一個外掛功能,這個功能就是微信搖色子和剪刀石頭布的作弊器,我們用過微信這個功能都知道,是一個比較常用的功能,因?yàn)樵谝粋€群聊中會很無聊就來這種簡單的比賽,誰輸了發(fā)紅吧啥的。那么這個功能肯定伴有隨機(jī)性,而且我們應(yīng)該相信這個隨機(jī)方法肯定是在微信代碼中的某個地方,所以如果我們找到這個方法了,那么就可以進(jìn)行Hook他,然后攔截返回最大的數(shù)值即可,也就是我們想要得數(shù)值。
三、準(zhǔn)備工作
上面大致分析了這個功能的原理使用,下面咋們就不多說了,直接進(jìn)行操作,本文用了一個微信的老版本做測試的:微信6.3.9.apk ;那么第一步咋們得逆向微信,需要做兩個工作:
第一先使用apktools反編譯apk,這個不用多說了,微信沒有對應(yīng)用進(jìn)行加固,所以反編譯過程很正常。
第二需要借助可視化反編譯工具Jadx來打開微信apk,因?yàn)槲⑿艖?yīng)用很大,所以得慢慢等待一會才可以打開。
四、逆向分析
下面在來冷靜分析一下如何我們該怎么入手?上面反編譯成功了之后,還得尋求入口,這個入口也很簡單的,因?yàn)槲覀兿氲玫竭@個隨機(jī)函數(shù),那么在我們能看到的效果是色子,我們可以選擇一個微信聊天對話框,然后點(diǎn)擊一個色子功能:

看到了,我們點(diǎn)擊色子之后肯定會調(diào)用這個隨機(jī)函數(shù)獲取隨機(jī)值,那么這里就是我們的入口,所以第一步肯定先找到這個點(diǎn)擊事件,如果要找到點(diǎn)擊事件,那么就得先找到這個控件的定義,那么問題來了,如果能夠快速的找到這個控件的定義呢?這個技術(shù)在我之前的一篇文章中已經(jīng)介紹了,就是 微信的自動搶紅包功能 當(dāng)時(shí)因?yàn)橐业侥莻€紅包的點(diǎn)擊事件,所以就用同樣的方法來得到那個紅包的控件定義的地方,而這個方法就是借助AndroidSDK提供的一個工具:uiautomatorviewer.bat 這個工具位于SDK目錄的tools目錄下,我們可以點(diǎn)擊運(yùn)行,然后就可以看到這個界面了:

我們把設(shè)備停在聊天對話框中,然后使用這個工具,點(diǎn)擊左上角那個按鈕,可以進(jìn)行當(dāng)前桌面的界面布局分析,分析結(jié)果我們可以看到,這個色子是一個自定義控件:com.tencent.mm.ui.MMImageView,然后他的id是ae7,而這個值非常關(guān)鍵,后面就是用這個值來進(jìn)行一步一步的跟蹤,這里我們再多看一眼,就是這個表情區(qū)域的詳細(xì)布局:

猜也猜到了,表情區(qū)域外面應(yīng)該是一個ViewPager控件可以進(jìn)行滑動切換,然后是每一頁的控件用的是GridView進(jìn)行卡片分割,那么這里就會給我們一個提醒了:后面的點(diǎn)擊事件要么是在GridView的適配器類的getView方法中對view進(jìn)行setOnClickListener添加的,要么是對GridView添加onItemClick事件的。
好了下面繼續(xù)跟蹤,因?yàn)橛辛四莻€色子控件的id了,下面咋們可以直接用這個id去全局搜索這個值了,不過這里有個問題就是微信其實(shí)本身做了資源的混淆,而這個混淆一方面是加大安全工作,一方面是減小包的大小功能,我們可以使用解壓工具簡單的查看他的apk文件中的res目錄,會發(fā)現(xiàn)全是字母文件夾。而且從上面的id命名也可以看到,我相信微信工程師不可能會傻逼的把一個id命名成ae7了吧?到這里我們又要借助一個知識點(diǎn)了,而這個知識點(diǎn)在我之前的一篇文章中介紹了:Android中的應(yīng)用攻防之戰(zhàn) 在這篇文章中介紹了,我們在反編譯apk之后,其實(shí)apk所有的資源id值都會保存在一個public.xml文件中,而這個文件是放在values目錄下的,這個文件主要存放的就是資源的id值和name,type之間的對應(yīng)關(guān)系,而反編譯之后的代碼中一般不會用R.id.xxx這種樣式來訪問控件,而是用轉(zhuǎn)化之后的id值,這個值是十進(jìn)制的,所以我們得先用上面那個ae7的id值去public.xml文件中找到對應(yīng)的十六進(jìn)制值:

注意:
這里在查找ae7的時(shí)候,會發(fā)現(xiàn)多個匹配項(xiàng),而我們需要用額外的信息來作區(qū)分,那就是type字段了,type字段有很多種值,比如layout,drawable,string,attr,id等,我們這里因?yàn)槭嵌x控件的所以type=id。
找到這個項(xiàng)之后,就把后面id的十六進(jìn)制值轉(zhuǎn)化成對應(yīng)的十進(jìn)制值吧:0x7f07060e=2131166734
有了這個值,就好辦了,咋們直接在Jadx中打開的微信apk中全局搜索這個值:

哎,可惜的是沒有找到,所以到這里就開始蛋疼了,也是這次逆向的最大阻礙了,想了好長時(shí)間,最后才突然想起來以前 逆向微信的本地通訊錄信息 的時(shí)候發(fā)現(xiàn)微信采用了分包技術(shù),也就是微信包太大,因?yàn)锳ndroid系統(tǒng)中有方法數(shù)的限制所以需要對apk進(jìn)行拆包操作,具體可以查看這篇文章:Android中應(yīng)用拆包技術(shù)詳解 那么我們會發(fā)現(xiàn)反編譯之后也沒有看到多個dex文件,所以這時(shí)候還要猜想他應(yīng)該是存在本地目錄的,在應(yīng)用啟動的時(shí)候主dex功能再去加載這個次dex文件,通過查看反編譯之后的目錄,結(jié)果在assets目錄下找到了他:

而這個是兩個從dex文件,這里他做了dex文件轉(zhuǎn)成jar文件的操作了,所以我們先用解壓工具解壓這個jar文件,得到對應(yīng)的dex文件即可。然后咋們在開啟一個Jadx窗口打開這個從dex文件,然后在全局搜索上面的那個值:

看到了,終于找到了這個控件的定義的地方了,點(diǎn)擊第一個進(jìn)去查看:

我們在往下面看這個類的信息,會發(fā)現(xiàn)到有一個getView方法:

看到這個就可以判定了,這個類其實(shí)是一個BaseAdapter類型了,而在getView中沒有看到控件的點(diǎn)擊事件,所以猜想應(yīng)該是外部給GridView添加的onItemClick事件了,咋們繼續(xù)選中這個類名,然后右擊進(jìn)行跟蹤這個類在哪些地方被調(diào)用了,這個功能的確很實(shí)用的:

點(diǎn)擊查找之后,會有很多地方調(diào)用:

這里從第一項(xiàng)的那個參數(shù)命令可以猜想到了應(yīng)該就是GridView類型,而到這里我們貌似看到了勝利的曙光了:

然后查看這個smileyGrid變量的定義:

這里是一個SmileyGrid類型的,咋們可以全局搜索這個類,看看他的定義:

果然不出所料,這里是一個GridView類型,然后也看到了我們非常期待的onItemClick方法了,下面就開始分析這個onItemClick方法的邏輯了:

這里我沒有找到一個好的辦法,也不想去深入跟蹤了,因?yàn)檫@里的判斷分之不是很多,所以就順序的嘗試了每個方法,結(jié)果找到了最后一個a方法,然后點(diǎn)進(jìn)去查看邏輯:

這里我們就需要多想點(diǎn)了,從我們點(diǎn)擊色子之后的效果看,沒有對話框和toast提示,那么這里就只有兩個分支是最有可能執(zhí)行的了,通過順序嘗試之后,發(fā)現(xiàn)是第一處分支的邏輯了,也就是h.a.aMZ.b()這個方法執(zhí)行了,通過import導(dǎo)入的類,得到這個類的路徑定義:
但是在這個dex中沒有找到這個類,所以猜想應(yīng)該是在主dex中,果然找到了這個類定義,然后進(jìn)入這個類進(jìn)行想詳細(xì)查看:

繼續(xù)進(jìn)入看看b方法的定義:

擦,這里的b方法盡然返回的是null,那么到這里就要思考了,如果返回null的話,之前的點(diǎn)擊事件肯定是無效的,而這個又不符合實(shí)際情況,所以猜想還有哪個地方對這個iop進(jìn)行賦值操作了。我們看看這個iop定義:

從定義上可以看到,極大可能在其他地方進(jìn)行了賦值操作,所以咋們?nèi)炙阉鬟@個變量值iop:

發(fā)現(xiàn)搜索結(jié)果還是我們剛剛看到的返回null的代碼,所以咋們又得繼續(xù)去另外一個dex中進(jìn)行搜索了:

這里搜到了一個賦值操作,立馬點(diǎn)擊進(jìn)入查看:

然后查看PD方法的定義:

繼續(xù)查看這個g類定義:

看到他的b方法,這里有一個bb.pu這個方法比較可疑,因?yàn)樽罱K返回的值都是和他相關(guān)的,而這個方法在這個dex中又沒有找到,所以咋們看一下他的import找到全局定義路徑,然后去另外一個dex中查看定義:

到這里,就會非常激動了,因?yàn)槲覀兛吹搅藙倮?,這個非常明顯的隨機(jī)方法終于找到了,而通過這個隨機(jī)公式可以看到,這個方法的功能是返回一個0-i之間的隨機(jī)值,而對于色子應(yīng)該是0-6之間的值,猜拳是0-3之間的值。所以這個方法百分百是用于隨機(jī)功能的。
五、掌握逆向技能
到這里我們就成功的找到了我們想要Hook的地方了,從上面的逆向過程會發(fā)現(xiàn)微信的工程非常龐大,而對于我們逆向來說工作是非常艱難的,但是還好我們有一些強(qiáng)大的工具可以快速的定位問題,下面就來總結(jié)本文逆向收獲的知識:
第一、對于逆向中想得到控件點(diǎn)擊事件入口,可以通過以下步驟來進(jìn)行
1、使用界面分析工具得到指定控件的id名稱
2、通過id名稱去反編譯之后的values/public.xml中查找到指定的值,轉(zhuǎn)化成十進(jìn)制
3、通過Jadx自帶的全局所有功能,查找這個十進(jìn)制值即可
對于這個步驟將適用于想得到一個應(yīng)用中某個控件的點(diǎn)擊事件邏輯入口是非常有效的,而且也是通用的方法。
第二、對于微信來說,因?yàn)楣こ痰凝嫶?,所以肯定會存在拆包現(xiàn)象,所以他不止一個dex文件??隙ㄊ前鄠€dex文件的,所以后面還需繼續(xù)寫微信的外掛,到時(shí)候分析都是要注意這一點(diǎn)。
第三、對于Jadx的強(qiáng)大工具在本文中起到了非常重要的功能:跟蹤方法的調(diào)用,全局查找功能。
額外說明:
在本文中我們會發(fā)現(xiàn)有一個難受的地方就是多個dex文件之間查找相應(yīng)的方法的地方,所以其實(shí)我們可以這么干,我們?nèi)绻玫搅藨?yīng)用所有的dex文件之后,可以將其先轉(zhuǎn)化成對應(yīng)的java類,然后進(jìn)行類合并,這里我們可以使用Beyond Compare比較工具將多個不同文件夾合并到一起:

合并之后咋們在用工具將其轉(zhuǎn)化成一個dex文件,也就完成了多個dex文件合并工作了。在這個工程中,我們可以非常巧妙的借助Jadx的另外一個強(qiáng)大功能,就是可以把反編譯之后的內(nèi)容保存到本地:

他有個好處就是,把a(bǔ)pk中的dex保存成java文件,資源全部解碼保存指定xml文件,而最終的保存樣式是一個gradle工程,而這個工程咋們就可以直接導(dǎo)入到一個開發(fā)工具中了非常方便了。特別是資源文件,我們在之前會發(fā)現(xiàn)apktools工具并沒有反編譯xml文件出來。而在這里就可以了。
六、開始攔截操作
下面咋們就來進(jìn)行Hook操作了,上面已經(jīng)得到了這個隨機(jī)函數(shù)的名稱了:
com.tencent.mm.sdk.platformtools.bb.pu(int i)
Hook工作就非常簡單了,咋們攔截這個方法之后根據(jù)傳入的值做一次判斷是搖骰子還是猜拳操作:

首先咋們得做一次過濾操作,就是只會Hook微信應(yīng)用,然后到攔截操作中,通過傳遞的參數(shù)做判斷是搖色子還是猜拳,如果是搖色子就返回一點(diǎn),猜拳就返回剪刀。
編寫成功之后,就進(jìn)行編譯成模塊,然后重啟設(shè)備生效,點(diǎn)開微信打開一個聊天框,開始搖色子:

通過打印值可以看到,我們的猜想是正確的,看一下實(shí)際效果:

哈哈哈,所有的操作都在掌控之中,到這里我們也成功的編寫了一個微信外掛功能,而這個外掛可能有的同學(xué)感覺用途不是那么大,而現(xiàn)在主流的外掛是可以防止撤銷功能,分享視頻到朋友圈,不過這些功能都會慢慢講解的,不要著急,而對于本文以及后續(xù)的外掛內(nèi)容文章,我想表達(dá)的是,結(jié)果并不重要,重要的是整個逆向過程,在每次一逆向之后我們學(xué)到了什么,是否漲了逆向經(jīng)驗(yàn),這才是我們需要得到的。
補(bǔ)充說明:
第一點(diǎn):有的同學(xué)會發(fā)現(xiàn)咋們上面得到的那個方法貌似是混淆之后的,也就說如果哪天微信改了混淆機(jī)制,那么這個Hook就失效了,本文中用到的是微信6.3.9的版本,對于其他版本我想這個方法類名應(yīng)該是變了,也就說如果微信每次出一個版本咋們都得去逆向一次得到方法名,但是這個都不是難事,以為本文已經(jīng)將整個逆向過程講解了,所以以后只要按照這個步驟來,查找方法也是分分鐘的事!
第二點(diǎn):本文的用意是分享逆向技巧知識點(diǎn),所以也請各位同學(xué)能夠知道結(jié)果不重要,重要的是整個逆向的過程,也就是如何尋找到Hook點(diǎn)
嚴(yán)重聲明:本文介紹的知識點(diǎn)完全是從一個技術(shù)分享角度出發(fā),絕非用于任何商業(yè)活動和用途,如果涉及到任何法律問題將由操作者本人負(fù)責(zé)。本文作者將不負(fù)責(zé)任何法律責(zé)任!也請各位同學(xué)秉著技術(shù)角度出發(fā)的原則,切勿用于商業(yè)中!
七、總結(jié)
本文主要介紹了一個微信的簡單外掛功能,就是搖色子和猜拳作弊器功能,而在整個過程中,我們可以看到找到Hook點(diǎn)才是最關(guān)鍵的,而最難的也是找到這個點(diǎn)。一般都是需要進(jìn)行逆向分析微信應(yīng)用找到這個點(diǎn)。在這個過程中我們又學(xué)習(xí)到了一些新的逆向應(yīng)用技巧知識點(diǎn),后續(xù)將會繼續(xù)帶大家一起分享其他的外掛功能知識點(diǎn),敬請期待,同時(shí)也要多多支持?jǐn)U散分享啦,也要多多點(diǎn)贊呢?寫這篇文章實(shí)屬不易呀,因?yàn)槟嫦虻奈翌^都炸了!
相關(guān)文章
android編程獲取和設(shè)置系統(tǒng)鈴聲和音量大小的方法
這篇文章主要介紹了android編程獲取和設(shè)置系統(tǒng)鈴聲和音量大小的方法,實(shí)例分析了Android針對音頻的相關(guān)操作技巧,需要的朋友可以參考下2017-06-06
Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果
這篇文章主要介紹了Android 使用SwipeRefreshLayout控件仿抖音做的視頻下拉刷新效果,需要的朋友可以參考下2018-05-05
Android實(shí)現(xiàn)拖動小球跟隨手指移動效果
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)拖動小球跟隨手指移動效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
Android自定義狀態(tài)欄顏色與應(yīng)用標(biāo)題欄顏色一致
看IOS上的應(yīng)用,應(yīng)用中狀態(tài)欄的顏色總能與應(yīng)用標(biāo)題欄顏色保持一致,用戶體驗(yàn)很不錯,對于這種效果怎么實(shí)現(xiàn)的呢?下面小編給大家分享android自定義狀態(tài)欄顏色與應(yīng)用標(biāo)題欄顏色一致的實(shí)現(xiàn)方法,一起看看吧2016-09-09
Android開發(fā)RecyclerView單獨(dú)刷新使用技巧
本篇文章主要是分享下RecyclerView中子item如何單獨(dú)刷新以及子item的某一部分內(nèi)容如何實(shí)現(xiàn)單獨(dú)刷新,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09

