前言
本篇文章將接著之前的21-自動(dòng)搶紅包UI這個(gè)項(xiàng)目,繼續(xù)實(shí)現(xiàn)自動(dòng)搶紅包的功能。根據(jù)以往所掌握的逆向知識(shí),要在WeChat中實(shí)現(xiàn)自定義的功能,有2種方式:
-
越獄機(jī)???? 創(chuàng)建tweak插件,插入代碼。 -
非越獄機(jī)???? 先重簽名,再代碼注入。
其實(shí)以上2種方式,都可以通過MonkeyDev插件實(shí)現(xiàn),我們可以使用logos語法,實(shí)現(xiàn)Hook紅包功能相關(guān)的一系列方法,那么越獄和非越獄這2個(gè)環(huán)境就可以自由切換,從而達(dá)到自動(dòng)搶紅包的目的。
一、編寫Tweak插件
接下來,我們就以越獄機(jī)的方式,編寫Tweak插件來實(shí)現(xiàn)自動(dòng)搶紅包的功能。
- 首先創(chuàng)建Tweak插件工程
XFWeChatDemo????



如何獲取WeChat的BundleID呢?直接使用OpenSSL端口鏈接(可參考22-越獄 & OpenSSH)????

然后使用cy腳本,打印APPID(可參考19-Cycript)????
有個(gè)很實(shí)用的cy腳本 ???? mjcript

- 添加自定義的代碼(包括搶紅包的2個(gè)自定義的cell)


- 修改Monkey的配置????

- 編譯


- 越獄機(jī)運(yùn)行查看

如果碰到上述問題 ???? 說明你mac的RSA密鑰對(duì)不存在,需要重新生成。解決方案????
// 1. 生成公鑰 (直接回車回車回車生成)
ssh-keygen
// 2. copy到你的越獄手機(jī)中
ssh-copy-id -i $HOME/.ssh/id_rsa.pub root@你的手機(jī)ip地址
?? 確保你的手機(jī)已經(jīng)
越獄,并且和mac是在同一個(gè)wifi下!
重新生成新的密鑰對(duì)后,再次運(yùn)行,手機(jī)會(huì)自動(dòng)重啟,打開微信設(shè)置頁面????
上圖可見,2個(gè)cell已經(jīng)展示出來了!????????????
圖片的處理
之前21-自動(dòng)搶紅包UI時(shí),是將圖片復(fù)制到app包里面,再重簽名安裝即可。那么現(xiàn)在越獄狀態(tài)下怎么將圖片copy過去呢?不難????
- OpenSSH連接手機(jī)設(shè)備????

- 搜索出
WeChat的包路徑(需先啟動(dòng)WeChat)????
ps -A | grep WeChat

地址 ???? /var/containers/Bundle/Application/27D7F5E7-E36C-435F-B1B8-8267FECF58E6/WeChat.app/,只需要到.app這個(gè)路徑即可。
- 逐個(gè)將圖片copy到手機(jī)的
WeChat的包路徑之中(先去到圖片的文件夾之中)????
scp -p 12345 ./xxx.png root@localhost:/var/containers/Bundle/Application/27D7F5E7-E36C-435F-B1B8-8267FECF58E6/WeChat.app/

- 再次運(yùn)行就有圖片了????

至此,UI方面就基本完成了。
二、定位聊天界面消息接收
接下來就是實(shí)現(xiàn)搶紅包功能了,在搶紅包之前,我們得先理清WeChat接收消息的流程。最直觀的當(dāng)然是 ???? 在聊天界面定位消息的接收,觸發(fā)了哪些方法的調(diào)用?
準(zhǔn)備工作
在定位之前,我們還要做些準(zhǔn)備工作????
- 對(duì)
WeChat包進(jìn)行砸殼class-dump???? 可參考23-應(yīng)用砸殼 -
info.plist中刪除UIDevice的配置,否則無法重簽名????

- 定位聊天界面的VC 看UI層級(jí) ???? 找到聊天信息的VC
有2種方式定位VC????
- attach to process,然后查看UI層級(jí)????


- cycript命令查看 ????

我們定位到聊天的界面VC ???? BaseMsgContentViewController
- hook VC中所有的方法 ???? 鎖定【接收紅包信息】的方法
- logos hook所有方法
pl腳本(在theos的目錄下面) 輸出xm文件????
pl腳本位置????
- logos hook所有方法
來到dump的文件夾,執(zhí)行腳本輸出????
logify.pl BaseMsgContentViewController.h > ../logMethod.xm


- 將
logMethod.xm直接拖到工程去使用????

上圖可見,就是通過%log查看調(diào)用方,參數(shù)等信息,再%orig回到原有流程。
查看源碼????

編譯前改下配置項(xiàng)????

編譯生成.mm????

將logMethod.mm拖進(jìn)工程????

然后再次編譯,會(huì)報(bào)錯(cuò)????

.mm文件過大,查看時(shí)會(huì)很卡,我們直接看.xm文件。
報(bào)錯(cuò)的方法我們就注釋掉,直至編譯成功????


??注意:此時(shí)是沒有安裝的,在安裝之前,先
殺掉當(dāng)前的微信進(jìn)程!
修改配置 ???? 編譯即安裝????

- 在
控制臺(tái)中查看信息


很明顯,這里打印的信息,就是我們之前通過logify腳本添加的代碼所輸出的。
- 定位 ????
收到消息所觸發(fā)的方法
- 首先接收一個(gè)消息,看看控制臺(tái)的輸出????

我們只看前面觸發(fā)的幾個(gè)方法,有onNewSyncStart --> findNodeDataByLocalId -->addMessageNode,其中onNewSyncStart 和findNodeDataByLocalId 的參數(shù)沒有什么實(shí)質(zhì)性內(nèi)容,我們來到addMessageNode????

上圖可見,addMessageNode方法中的入?yún)?,就有我們想要的,例如?br>
m_nsFromUsr發(fā)消息的用戶Id,m_nsToUsr接收消息的用戶Id,type可能是消息類型等。
此時(shí),我們定位到方法addMessageNode,但是,你仔細(xì)想想,如果我們定位的是聊天頁面的addMessageNode,再hook它搶紅包,這時(shí)的時(shí)機(jī)是不是太晚了?
- 接著,我們退出聊天頁面,切換到【發(fā)現(xiàn)】tab,再接收消息,看看控制臺(tái)輸出 ????

就2個(gè)方法onNewSyncStart和onNewSyncfinish。當(dāng)然我們只看onNewSyncStart,明顯它時(shí)機(jī)更早,繼續(xù),看看誰調(diào)用它?
- 下
onNewSyncStart斷點(diǎn),看函數(shù)調(diào)用棧等信息
? 首先attach process附加進(jìn)程WeChat,斷住, lldb中methods指令查看方法地址????

??注意:如果沒有
methods指令,可參考18-lldb(下)chisel & 插件中LLDB指令集插件的安裝。
我們搜索出onNewSyncStart和addMessageNode的地址????
- (void) onNewSyncStart; (0x117f32394)
- (void) addMessageNode:(id)arg1 layout:(BOOL)arg2 addMoreMsg:(BOOL)arg3; (0x117f3b850)
? b指令下斷點(diǎn)

斷住后,c指令continue繼續(xù)執(zhí)行。接收一條消息,驗(yàn)證是否成功????

? 接著,sbt指令查看調(diào)用棧信息????

frame#1 和frame#2這兩項(xiàng)沒有恢復(fù),我們繼續(xù)執(zhí)行一次看看????

frame#1 ???? 0x10e7f4418 WeChat-[MMExtensionCenter callExtension:selector:block:]`
frame#2還是沒獲取到,我們可以記錄一下地址
frame #2 : 0x10e773584 WeChat`___lldb_unnamed_symbol958446$$WeChat ... unresolved womp womp + 56
然后image list查看首地址,計(jì)算偏移地址????

那么0x10e773584 - 0x0000000104f78000 = 0x97FB584,該地址應(yīng)該在Text常量區(qū),然后我們用Hopper打開Mach-O文件,查看該地址是????


沒有什么有價(jià)值的信息。
三、定位全局消息接收
接下來定位addMesssageNode的調(diào)用棧信息,還是一樣,sbt查看????

第二次sbt恢復(fù)了調(diào)用棧的前面幾個(gè)方法的信息,得到幾個(gè)類,包括BaseMsgContentLogicController MMExtensionCenter MMContext 和CMessageMgr????
frame #1 : 0x10343b614 WeChat`-[BaseMsgContentLogicController DidAddMsg:] + 852
frame #2 : 0x10341ae24 WeChat`-[BaseMsgContentLogicController OnAddMsg:MsgWrap:] + 728
frame #3 : 0x109968418 WeChat`-[MMExtensionCenter callExtension:selector:block:] + 204
frame #4 : 0x1098fc244 WeChat`-[MMContext callExtension:selector:block:] + 168
frame #5 : 0x10135e4b8 WeChat`-[CMessageMgr MainThreadNotifyToExt:] + 836
接著逐個(gè)分析這些類中定位的方法, logos語法%log查看信息。
- 首先是
BaseMsgContentLogicController-
%log打印DidAddMsg:和OnAddMsg:MsgWrap:這兩個(gè)方法????
-

%hook BaseMsgContentLogicController
- (void)DidAddMsg:(id)arg1 {
%log;
%orig;
}
- (void)OnAddMsg:(id)arg1 MsgWrap:(id)arg2 {
%log;
%orig;
}
%end
- 同理,再看
MMExtensionCenter和MMContext這2個(gè)類的方法,貌似和message的關(guān)系不大,所以,我們繼續(xù)hookCMessageMgr的方法????
%hook CMessageMgr
- (void)MainThreadNotifyToExt:(id)arg1{
%log;
%orig;
}
%end
- 只保留上面要hook的三個(gè)方法????

僅編譯????

編譯,生成.mm ????

- 退出聊天界面,回到【發(fā)現(xiàn)】tab首頁,然后接收消息,看看控制臺(tái)的輸出????

此時(shí),我們還未進(jìn)入到聊天VC,紅框處的都是CMessageMgr類的MainThreadNotifyToExt方法輸出的日志。
再一次,我們?nèi)サ搅奶霽C,看看控制臺(tái)的輸出????

此時(shí)就有了OnAddMsg和DidAddMsg方法的打印。經(jīng)過分析,最終我們得到的方向就是????
MainThreadNotifyToExt方法不是我們研究搶紅包的唯一方法,類CMessageMgr才是重點(diǎn)的研究對(duì)象。
四、定位消息管理者
接下來重點(diǎn)研究CMessageMgr消息管理者類。
- pl腳本``hook所有方法 ????
logify.pl CMessageMgr.h > ../logMethodCMessageMgr.xm

- 將
logMethodCMessageMgr.xm文件拖入Monkey注入工程中,查看源碼????


近300行。
- 編譯,產(chǎn)出.mm,拖入工程????

然后注釋一些編譯不過的方法????

- 編譯運(yùn)行,重新接收消息,打開控制臺(tái)查看????

得到GetMsg: CheckMessageStatus: AsyncOnPreAddMsg: 和 onNewSyncAddMessage OnNewSyncAddMsgSessionArray等等很多關(guān)于消息的方法打印????
-[<CMessageMgr: 0x13fe6d300> GetMsg:Aron1101 LocalID:16 hasError:0x16f1c6d70]
-[<CMessageMgr: 0x13fe6d300> CheckMessageStatus:Aron1101 Msg:{m_uiMesLocalID=16, m_ui64MesSvrID=7818316956601146902, m_nsFromUsr=Aro*101~8, m_nsToUsr=wxi*o12~19, m_uiStatus=3, type=1, createTime=1629794366 msgSource="<msgsource><sequence_id>745337625</sequence_id></msgsource>"} ]
-[<CMessageMgr: 0x13fe6d300> onNewSyncAddMessage:{m_uiMesLocalID=16, m_ui64MesSvrID=7818316956601146902, m_nsFromUsr=Aro*101~8, m_nsToUsr=wxi*o12~19, m_uiStatus=3, type=1, createTime=1629794366 msgSource="<msgsource><sequence_id>745337625</sequence_id></msgsource>"} ]
-[<CMessageMgr: 0x13fe6d300> onNewSyncAddMsgSessionArray:{
Aron1101 = "{m_uiMesLocalID=16, m_ui64MesSvrID=7818316956601146902, m_nsFromUsr=Aro*101~8, m_nsToUsr=wxi*o12~19, m_uiStatus=3, type=1, createTime=1629794366 msgSource=\"<msgsource><sequence_id>745337625</sequence_id></msgsource>\"} ";
} withUsers:{(
Aron1101
)}]
這么多方法觸發(fā),關(guān)鍵我們是要對(duì)消息本身進(jìn)行研究,看看有哪些信息,才能準(zhǔn)確定位紅包消息。所以,最終我們鎖定到CheckMessageStatus它的參數(shù)才是我們想要的????
-[<CMessageMgr: 0x13fe6d300> CheckMessageStatus:Aron1101 Msg:{m_uiMesLocalID=16, m_ui64MesSvrID=7818316956601146902, m_nsFromUsr=Aro*101~8, m_nsToUsr=wxi*o12~19, m_uiStatus=3, type=1, createTime=1629794366 msgSource="<msgsource><sequence_id>745337625</sequence_id></msgsource>"} ]
- 接下來,我們hook
CheckMessageStatus:Msg:方法????
%hook CMessageMgr
- (void)CheckMessageStatus:(id)arg1 Msg:(id)arg2 {
%log;
%orig;
}
%end
也可以自定義打印格式????
%hook CMessageMgr
- (void)CheckMessageStatus:(id)arg1 Msg:(id)arg2 {
NSLog(@"arg1:%@\narg1 Class:%@\narg2:%@\narg2 Class:%@", arg1, [arg1 class], arg2, [arg2 class]);
%orig;
}
%end
- 編譯安裝(記得
手動(dòng)殺掉WeChat App進(jìn)程),然后接收一條消息,查看控制臺(tái)輸出????

arg1是字符串 agr2是CMessageWrap,這個(gè)就是消息model類????
arg2:
{
m_uiMesLocalID=17,
m_ui64MesSvrID=6443875340523928360,
m_nsFromUsr=Aro*101~8,
m_nsToUsr=wxi*o12~19,
m_uiStatus=3,
type=1,
createTime=1629854565
msgSource="<msgsource><sequence_id>745337629</sequence_id></msgsource>"
}
arg2 Class:CMessageWrap
可以看到,普通的文本消息type=1,消息的類class是CMessageWrap。
- 然后再接收個(gè)
紅包消息,查看輸出????

紅包消息的type=49。那么我們接下來,就能在CheckMessageStatus:Msg方法中,做一個(gè)hook????
如果接收的消息
type=49(即紅包),那么就執(zhí)行拆開紅包。
五、動(dòng)態(tài)分析拆紅包
接下來就是拆紅包了,還是一樣,需要定位所調(diào)用的方法。
需要使用工具
IDA????靜態(tài)分析搶紅包的方法。
-
attach附加viewDebug查看UI層級(jí)????

上圖可見,紅包的view類是WCRedEnvelopesReceiveHomeView,同時(shí)拆是個(gè)UIButton。
- 定位到
拆按鈕的方法 ????

拆button所對(duì)應(yīng)的方法是OnOpenRedEnvelopes。接下來就是靜態(tài)分析 ???? 如何模擬觸發(fā)OnOpenRedEnvelopes方法,這個(gè)我們?cè)诤竺娴奈恼轮欣^續(xù)講解。(30-項(xiàng)目實(shí)戰(zhàn)(2)
)
總結(jié)
本篇文章,通過Tweak插件的方式,在越獄機(jī)中演示,如何一步步地定位 ???? 接收紅包消息所觸發(fā)的方法,hook并打印這些方法的參數(shù),找到我們想要的消息model類的具體信息,進(jìn)而為我們下一步,分析拆紅包做準(zhǔn)備。

