微信PC端技術研究(3)-如何找到消息發送接口

微信PC端技術研究-如何找到消息發送接口
by anhkgg(公眾號:漢客兒)
2019年2月18日

0x0. 前言

準備工具:Cheat Engine,OllyDbg,IDA。

前一篇(微信PC端技術研究(2)-保存聊天語音)已經說過CE是什么,也應用CE研究了如何保存微信語音,這篇繼續使用CE和OD來研究一下微信的消息發送接口。

思路大概是這樣:在消息框中輸入內容之后,通過CE找到內容地址,然后通過內存斷點來找到發送該數據的相關代碼,從而找到消息發送接口。

0x2. 分析過程

查找關鍵數據地址

在輸入框輸入一個比較特別的文字內容(避免搜索時太多內存選項)后,使用CE搜索該內容地址。

由于已經知道確切的消息內容,很容易就能通過CE的Exact value->String來找到內容地址,修改內容多次篩選,最后留下兩個結果(詳細操作見上一篇文章)。

1.png

通過CE修改一下內存的內容,微信輸入框中內容同步改變,說明這個內存地址就是輸入框中內容地址,最終確認地址是2A1E1A8。

接著在點擊發送按鈕之后,輸入框內容會被清空,所以第一想法就是對內存地址下內存寫入斷點,可以找到發送過程中清空內容的代碼。

打開OD,掛載到WeChat.exe進程,在右下角數據窗口Ctrl+G輸入2A1E1A8,然后右鍵選擇斷點->內存寫入斷點。

2.png

F9讓OD跑起來,然后點擊微信發送按鈕,沒想到意外發生了,輸入框內容清空了,但是斷點卻沒有觸發。

怎么回事?斷點弄錯?地址找錯?暫時沒有答案。

用CE多次重復前面的操作,地址依然是這個地址,斷點就是不觸發。

通過OD查看到,在輸入框清空后,2A1E1A8的內容確實沒有變化,和發送前一樣,并且在重新輸入新的內容之后,該內存內容同步更新。

所以結論就是輸入框內容地址確實是2A1E1A8,但是清空輸入框并不是清空該內存內容,猜測編輯框可能通過控制字符串長短來控制顯示的,清空輸入框內容就是設置字符串長度為0。

找到輸入框類

清空輸入框沒有進展了,那怎么辦呢?

嘗試去找了其他數據,比如發送按鈕的發送(S),發送按鈕的提示內容不能發送空白內容等等,數據地址也可以很快找到,但是和我們的分析目標偏的太遠了。

幾番折騰后,作罷。

轉念一想,清空不行,發送總的讀取輸入框中內容吧,那換成內存訪問斷點嘗試一下。

依然是在右下角數據窗口Ctrl+G輸入2A1E1A8,然后右鍵選擇斷點->內存訪問斷點。

3.png

完成后回到微信界面,沒想到直接斷下了,我還沒點發送按鈕呢。根據以前的經驗,下意識就覺得是界面刷新顯示文字觸發了斷點,這可能會影響分析,根本沒辦法通過發送按鈕來觸發內存訪問斷點。

4.png

一般解決方法有:

  1. 條件斷點。也就是屏蔽掉刷新界面觸發的斷點,但是好像內存斷點不支持條件斷點啊,要么通過腳本來完成,好麻煩。
  2. 找其他切入點。廢話,清空那邊的路都斷了,死心吧。
  3. 其他我不知道的...

放棄了一般的解決方法,我決定看看本次斷點究竟干嘛了。

注意到斷點的位置不是微信模塊WeChatWin.dll中,而是在msftedit.dll,很少見的一個模塊。根據目錄可以看到是微軟系統的一個模塊,名字中的edit也可以看出這應該是一個編輯框相關的模塊。

可執行模塊, 條目 20
 基址=6F050000
 大小=00094000 (606208.)
 入口=6F05D53D msftedit.<ModuleEntryPoint>
 名稱=msftedit (系統)
 文件版本=5.41.21.2510
 路徑=C:\Windows\System32\msftedit.dll

好像和我們的分析目標很貼近嘛,在OD中數據窗口右鍵斷點->刪除內存斷點,然后按下Alt+F9回到用戶模塊領空,也就是跳過系統模塊的代碼,直接回到微信的模塊代碼中,省過對系統代碼的分析。

看到返回到6E20CCC2這個地址,上一行代碼就是調用msftedit.dll的函數,我們對其下一個斷點,鼠標點擊到6E20CCBF這行代碼,按下F2下一個int 3斷點,然后F9跳過本次分析。

5.png

OD繼續斷下,此次直接斷在了6E20CCBF這個位置,可以看到call調用了msftedit.6F05AD69,這是個什么函數呢?

6.png

既然msftedit.dll是微軟模塊,那么肯定是有符號的嘛,嘿嘿。

這里可以直接在OD中加載符號來分析,使用方法是:

1.在WingDbg目錄下拷貝dbgeng.dll,dbghelp.dll,srcsrv.dll,symbolcheck.dll,symsrv.dll,symsrv.yes,一共6個文件至OD目錄下。

2.打開OD,設置符號路徑。調試--->選擇符號路徑。

3.設置StrongOD的插件選項。選擇加載符號。

原文:https://blog.csdn.net/sr0ad/article/details/8253311 

但是只支持本地符號,也就是得自己下載了模塊對應符號到本地,OD設置符號文件路徑后,才能正常使用,有點麻煩。

我這時候一般就會使用IDA了,因為它會自己在線下載模塊對應的符號,很方便。

用IDA打開msftedit.dll,等待些許時間,IDA下載符號,解析等等完成后,我們去找到msftedit.6F05AD69對應的函數究竟是個什么東西。

但是這里msftedit.6F05AD69的模塊基址是6F050000,而IDA解析使用的是默認基址0x6FCD0000,要么修改IDA解析基址為6F050000,等待IDA重新解析,要么通過偏移計算對應地址。

再解析等太久,直接計算吧,所以要安利我寫的一個小工具(偏移計算工具),能夠快速計算地址,具體使用見相關文章。

7.png

再IDA中按下g,輸入6fcdad69,找到msftedit.6F05AD69對應函數為CTxtEdit::OnTxInPlaceActivate

8.png

很明顯通過名字OnTxInPlaceActivate可以看出是編輯框中文字激活狀態(顯示)下就會觸發該函數,這不是重點。

重點看CTxtEdit,不言而喻,這就是msftedit.dll中實現的編輯框的類。

如果寫過MFC相關代碼,應該很快就能想到CTxtEdit肯定還有其他讀內容、寫內容的函數,叫做GetXXX或者SetXXX。

在IDA的函數列表中翻看一下,果然很快就找到了CTxtEdit::GetTextExCTxtEdit::SetText。

9.png

但到底這兩個函數是不是編輯框讀寫內容的函數呢,我們對這兩個函數下斷點試試,通過工具算到在ID調試中這兩個函數的相應地址為6f0684376f056d37。

10.png

在OD的底部命令窗口輸入bp 6f068437bp 6f056d37,刪掉之前CTxtEdit::OnTxInPlaceActivate的斷點,然后F9跑起來。

11.png

回到微信界面,這次能夠正常顯示了,點擊發送按鈕。OD觸發斷點,斷在了6f068437也就是CTxtEdit::GetTextEx上,很明顯這是發送函數在讀取輸入框內容。

12.png

回溯找到發送函數

此時的調用堆棧是這樣的:

調用堆棧 
地址       堆棧       函數過程 / 參數                       調用來自                      結構
0026E280   6F06842D   msftedit.6F068437                     msftedit.6F068428             0026E3FC //CTxtEdit::GetTextEx
0026E400   6E20D239   包含msftedit.6F06842D                   WeChatWi.6E20D233             0026E3FC
0026E43C   6DBD38EB   包含WeChatWi.6E20D239                   WeChatWi.6DBD38E8             0026E438 //TxtEdit_GetText
0026E5AC   6DC15B65   ? WeChatWi.6DBD3860                   WeChatWi.6DC15B60             0026E5A8 //sendBtn_GetText
0026E60C   6DC15DEE   WeChatWi.6DC15B10                     WeChatWi.6DC15DE9             0026E608 //sendbtn_click
0026E618   6E20BFB8   WeChatWi.6E20BEF4                     WeChatWi.6E20BFB3             0026E614
0026E62C   6E20362E   WeChatWi.6E20BF90                     WeChatWi.6E203629             0026E628
0026E6CC   6E203589   WeChatWi.6E2035A7                     WeChatWi.6E203584             0026E6C8
0026E820   6DC53695   ? WeChatWi.6E20352E                   WeChatWi.6DC53690             0026E81C
13.png

在OD中回溯調用堆棧跟蹤返回到WeChatWi.6E20D239,看到右側堆棧窗口已經獲取到輸入框中內容,證明前面的分析沒有問題。

14.png

再次回溯兩層到WeChatWi.6DC15B60,可以看到堆棧中的參數依然是獲取到的輸入框內容。

[0026E5E4] = 0828C070
[0828C070 + 4] = 0828CAF0 => a12bcAAAAA
15.png

此時函數首地址是WeChatWi.6DC15B10,進入到IDA中對應函數100d5b10(你要問我為什么此時進入IDA查看?我只好說其實這個步驟花費了很多時間,一邊OD調試,一邊IDA輔助確認等等,過程并沒有這么順利,篇幅原因省略),然后按下x回到上層函數,看到如下代碼:

16.png

看到click很明顯可以看出這就是發送按鈕的響應函數了(相關知識可以了解duilib編程,微信界面是duilib實現的)。

到目前找到了發送消息的函數,但還并不是消息發送接口,這還只是界面的操作函數,具體發送消息接口應該在該函數內部被調用。

有技巧找到發送接口

先粗略地在OD中跟一遍WeChatWi.6DC15B10的代碼邏輯,函數很多,沒法很快確認哪個函數是消息發送接口。

截取部分代碼感受一下,大概11個函數。根據OD跟的邏輯大概是sendBtn_GetText_10093860->sub_100DD340->sub_100C50C0->sub_10094100->sub_100DD9D0->sub_100C4450->sub_10323DF0->sub_100DE120

if ( sendBtn_GetText_10093860(a1->unk_560, (int)&savedregs, a2, a3, msg) <= 0 )// 這里是獲取msg
  {                                             // x
    //省略一大段邏輯
  }
  if ( msg[0] != msg[1] )
  {                                             // x
    //省略一大段邏輯
  }
  if ( sub_100DD340() )
  {                                             // x
    //省略一大段邏輯
    sub_1047C070(&v34, v23);
    sub_100DB8C0((int)a1_, v34, v35, (int)v36, v37, (int)v38, v39, v40, (int)v41, msg_);
  }
  if ( sub_100C50C0((_DWORD *)(a1_->unk_558 + 2528), (int)msg, (int)v43) )
  {
    sub_10094100((_DWORD *)a1_->unk_560);//
    sub_100DD9D0(msg);                          
    sub_100C4450((_DWORD *)(a1_->unk_558 + 2528), (_msg *)msg);// 
    v31 = sub_10323DF0();
    sub_100DE120(v31, (int)a1_, (int)sub_100D6C40, 0, v40, (int)v41, msg_);// retn 18
    v12 = 1;
  }
  else
  {
    //省略一大段邏輯
    sub_10108D60(v30, *(&a1_->unk_558 + 1), v33, (int)v34, v35, v36, (int)v37, v38, v39, v40, v41);
  }

通常通過調試每個函數的參數、返回結果等基本可以猜測到函數功能,然后來找到消息發送接口。

但這里我偷懶了,因為參數結構復雜,一時半會沒法找到關鍵點,有點暈了。

所以我通過排除法來一一篩選函數,最多11次左右就能找到消息發送接口。舉個例子,如果sub_100DD340是消息發送接口,在我手工屏蔽其功能之后,消息肯定發不出去了,那么我就可以通過看到的結果(是否發送成功)來確認sub_100DD340是不是要找到的消息發送接口。

具體屏蔽方法:

  1. 通過IDA或OD進入sub_100DD340函數內部,找到函數結尾,找到retn xx類似代碼
  2. 用OD在sub_100DD340函數開始修改匯編代碼為retn xx,雙擊輸入retn xx即可

這樣sub_100DD340函數直接在入口就返回了,功能沒有了,也保證了函數調用時的棧平衡。

17.png

在確認sub_100DD340并沒有影響消息發送之后,通過右鍵撤銷選擇處修改恢復修改的內容。

如此重復篩選其他的函數,最終確認sub_100C4450為發送消息函數。代碼接口如下:

sub_100C4450((_DWORD *)(a1_->unk_558 + 2528), (_msg *)msg);// 

msg是發送內容,a1_->unk_558 + 2528)是當前聊天窗口的好友信息,包括wxid和名字之類的信息。

18.png

但作為接口依然不夠簡潔,需要構造好友信息,比較復雜,所以繼續深入sub_100C4450內部,看看是否能夠找到最簡單的接口,比如:

sendmsg(wxid, msg); //傳入發給誰,發什么即可

sub_100C4450內部依然很復雜,使用和前面同樣的方式,先大致跟一遍執行流程,然后通過排除法逐個篩選。

if ( !sub_100C43D0(msg_.buf, msg_.len, msg_.maxlen, wxid_) )// 是不是全是特殊字符\r\n\t等,是返回1,不是返回0
{
sub_1007D390();
msg_packet = sub_102DA4A0((int)wxid, (int)&v67, msg__, &unk, 1);// 數據打包,發送
sub_100494E0(msg_packet_, (size_t)msg_packet);//
sub_1004B550(&v67);              //
v11 = sub_102478D0();
v12 = sub_10402C10((int)v11);
v89 = (void **)v13;
if ( sub_10402C10((int)msg_packet_) != v12 || v14 != v89 )
{
    if ( sub_100C6770(this_) )        // 
    {
    sub_1004BBF0((int *)&msgpacket);//
    sub_10056940((int *)&msgpacket, (size_t)msg_packet_);// 
    sub_100C56D0(this___, (size_t)&msgpacket, 1);
    sub_10081210((LPVOID *)&msgpacket);
    v16 = sub_100C0EC0();
    sub_10247250((int **)v16, (int)path);
    }
}
}
if ( (signed int)(msg->msgend - (unsigned int)msg->msg) / 0x24 != 1 )
v9 = sub_10323DF0();
sub_10324E70(v9, msg_.len, msg_.maxlen, (int)wxid_, (int)path);
sub_100ADA10(&msg___);

這一次篩選屏蔽的方法換一種,直接在某個函數執行完成之后,通過jmp跳到sub_100C4450結尾,如果某次消息發送成功,最后執行的函數就是我們要的接口。

19.png

很幸運,這次在第三個函數就找到了消息發送函數sub_102DA4A0,看看它的參數:

sub_102DA4A0((int)wxid, (int)&v67, msg__, &unk, 1);
sub_102DA4A0@<eax>(int wxid@<edx>, int a2@<ecx>, wxstring *msg, _DWORD *a4, int a5)

下圖是調試中看到的數據,確認接口沒有問題。至于其他兩個參數,經過分析是用于接收輸出的,沒有實際作用,在此不贅述。

20.png

如此分析消息發送接口的工作完成,找到了和預期基本一致的接口函數。

0x3. 總結

篇幅好像有點長了,最后做一下此次分析的總結:

  1. ce找到編輯框中的內容內存
  2. 發送后,編輯框內容刪除,寫斷點無效,神奇,猜測通過設置長度控制顯示
  3. 改為內存訪問斷點,進入界面就會斷下,徘徊幾次后,決定分析,沒想到找到了關鍵點CTxtEdit::OnTxInPlaceActivate
  4. 知道編輯框使用了msftedit.dll的CTxtEdit的類,用ida找到符號
  5. 查詢類似getvalue的接口,找到SetText、GetTextEx等,對這兩個函數下斷點
  6. 果然斷下,回溯找到了發送的消息響應函數
  7. 詳細分析響應函數,多次通過retn、jmp排除,找到真正發送消息函數,最后分析出接口函數

此次分析中CE找到地址是第一步非常關鍵的點,直接就進入了函數調用堆棧內部,對此次分析作用非常明顯。

再就是在發送消息響應函數內部,逐個分析找到消息發送接口函數中,通過修改指令來屏蔽函數功能來確認函數功能,比每個函數去分析參數猜測確認功能來的更快,效果更明顯。

調試工具非常重要,動(OD)靜態(IDA)分析結合能夠提高分析速度。

OD適合分析函數參數、解析數據結構、確認函數功能,IDA適合分析函數邏輯、整體函數結構、代碼框架等等,各有優勢。

最后,再次安利一下開源項目https://github.com/anhkgg/SuperWeChatPC,此次分析的發送消息接口也會在后續合入到項目中,歡迎starPR。

相關文章:

  1. 微信PC端技術研究(2)-保存聊天語音

  2. 偏移計算工具

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,345評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,494評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,283評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,953評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,714評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,410評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,940評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,776評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,210評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,654評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容

  • 微信PC端技術研究-保存聊天語音by anhkgg(公眾號:漢客兒)2019年1月31日 2.6.6.28 0x0...
    anhkgg閱讀 714評論 0 0
  • Windows 常用消息大全 表A-1 Windows消息分布 消息范圍說 明 0 ~ WM_USER – 1系統...
    北風知我意閱讀 2,074評論 0 0
  • 9102年了,我想大部分人使用微信的頻率應該都會高于QQ了吧。 以前在QQ傳文件的時候,哪里會想到會有文件大小限制...
    anhkgg閱讀 8,275評論 0 0
  • 哎,真的不好說,強烈的感覺是真的中了,這種感覺,不知道為什么,身邊的人肯定會很開心,但于我而言,真的不是那么的強烈...
    馬橙澄閱讀 148評論 0 0
  • 我的寶貝又長大一歲了,她已經亭亭玉立,她已經年近芳華。都說″豆蔻梢頭二月花″,在我心里,她已燦然如夏。依記初始,那...
    安之若素_a23b閱讀 150評論 0 0