歡迎光臨
每天分享高質量文章

PC 端微信技術研究之儲存聊天語言

來自:信安之路(微信號:xazlsec)

本文作者:anhkgg(信安之路病毒分析小組成員 & 個人公眾號:漢客兒)

 

雖然一直知道 CE,也用過一段時間,但一直用不好,可能太笨。

最近又學習了某位大佬用 CE 的方法,大佬的一句話有點醍醐灌頂,然後有了新的感覺,然後開始嘗試實踐這篇文章。

自己總結一下 CE 用法的核心思路:通過各種技巧搜索找到記憶體中關鍵資料,然後結合動態除錯找到運算元據的函式。

準備工具:

Cheat Engine,OllyDbg,IDA。

瞭解 CE

官網:

https://www.cheatengine.org/

看看來自百科的介紹:

Cheat Engine 是一款記憶體修改編輯工具 ,它允許你修改你的游戲或軟體記憶體資料,以得到一些其他功能。它包括16進制編輯,反彙編程式,記憶體查找工具。與同類修改工具相比,它具有強大的反彙編功能,且自身附帶了外掛製作工具,可以用它直接生成外掛。

在我看來,CE 做的最好的就是各種策略的記憶體搜索能力。

1、支持準確資料(整數、字串、十六進制、浮點數、位元組陣列等等)搜索,針對標的資料明確效果顯著,比如金幣數。

2、支持資料範圍的搜索,比如大於某個值,小於某個值等等。比如想找到沒有顯示數值的血量資料。

3、支持多組資料同時搜索,針對資料結構複雜的情況

4、支持搜索結果的多次過濾(圖中框選的Next Scan),最終找到標的資料。比如血量未知時,通過加血、減血多次搜索最終找到血量地址。

說到底 CE 記憶體搜索的能力就是通過各種策略幫助你找到游戲中需要修改的資料(比如血量、分數、金幣等等),然後通過記憶體修改能力(直接改血量)打破游戲平衡,外掛製作工具生成外掛,助你超神!

更多CE的高級應用可以訪問:

https://blog.csdn.net/cgs___/article/details/77799091

https://blog.csdn.net/zhaobisheng1/article/details/79259460

分析

進入正題,本文是要拿到微信聊天的語音訊息,然後 dump 儲存下來。

要按以前我的思路,會通過網絡通信找到接受訊息的函式,然後找到語音資料,看起來很簡單,但是有點難。

因為函式真的很多,網絡訊息也會受到很多干擾。

現在用 CE 了,應該怎麼辦呢?

找到關鍵資料

關鍵資料肯定是語音訊息了,但是怎麼搜索呢,肯定搜語音內容不現實,所以轉了彎,先看看文字訊息,找到接受文字訊息處理函式之後,猜測語音處理函式會相同或者在不同分支

接著,如何搜索文字訊息呢?已經收到的顯示在聊天視窗的內容當然可以通過CE找到,但是沒用啊,它和接受文字訊息處理函式已經沒關係了,流程已經處理完成了。

那麼在測試中肯定知道發送的訊息內容,通過CE來搜索可以嗎?

額,我覺得不行,還沒收到訊息呢,記憶體中也沒有這個文字訊息,搜索不到(如果可以,請大佬指點一下)。

能想到的是,在接受到訊息某一點通過除錯器斷下來,然後 CE 搜索,這樣可以,但是這個斷點找不到阿,放棄。

那怎麼辦呢?

看到左側聊天串列中顯示的最新一條訊息,有了新的思路。

每次收到新訊息後,都會在串列中顯示最新訊息內容(圖中綠框指示位置、註意是 unicode 字符)。

那麼,先用 CE(First Scan)搜索當前搜到的訊息內容,找到可能的記憶體地址。多次接受不同訊息後,Next Scan按鈕搜索每次新的訊息內容,最終確定聊天串列中顯示的最新訊息內容的記憶體地址。

多次刷選之後,留下兩個地址,通過 CE 修改內容,在界面中查看是否改變,最終確認第二個地址就是我們的標的,暫把該地址記錄為 MsgAddr。

分析訊息接收函式

關鍵資料地址已經找到,下麵的工作複雜也不複雜,就看微信是如何實現的了。

猜測微信實現訊息顯示的流程是這樣的:

1、recv 收到訊息,組裝完整包後,分發給訊息處理函式

2、根據 wxid 找到要顯示訊息的串列項,如果不在已聊天訊息串列,就新建一個項

3、在串列中顯示訊息,如果是表情顯示[文字],語音顯示為[語音],訊息插入 wxid 對應訊息佇列,或者存入資料庫

步驟 3 中肯定要寫前面找到的 MsgAddr 記憶體,把最新訊息顯示到界面中,這個流程肯定在訊息處理函式內部。

So,通過 OD 對 MsgAddr 下記憶體寫入斷點,回溯堆棧就可以找到訊息處理函式。

具體操作如下:

OD 掛載 Wechat.exe 行程後,在左下角記憶體視窗處 Ctrl+G,輸入找到的 MsgAddr(11A11F34)回車,定位到該資料,然後再 HEX 資料處,右鍵彈出選單,選擇斷點->記憶體寫入:

斷點設置完成後,測試發送文字訊息,OD 斷住,代碼視窗顯示的就是修改 MsgAddr 的代碼位置,如上圖 10CE412C 處。

Alt+K 查看當前堆棧:

呼叫堆棧

看到這個呼叫棧是不是感覺好少,分析起來肯定簡單。但,其實是 OD 顯示的並不全,此時真的很想用 windbg。

在 OD 的右下角堆棧視窗,可以看到當前呼叫棧的引數和預覽資料。F8 單步(或者 Alt+F8 執行到傳回)逐步的回溯每層堆棧。關註 MsgAddr 的資料是如何生成的,也就是找到資料來源,然後找到訊息處理函式。

跟蹤過程不贅述(需要熟悉彙編知識),直到看到的最頂層的 WeChatWi.10206460 處,發現是界面操作函式把收到的訊息內容顯示到聊天串列處的一個功能函式。

那這裡不是可以拿到訊息了嗎,是的,普通文字訊息已經可以拿到,但是語音內容不行。

通過觀察記憶體視窗的資料,整理 WeChatWi.10206460 處的關於訊息引數的大致結構。

//聊天串列框信息
struct chat_list_msg {
DWORD unk;//
wstring wxid;//
//wchar_t* wxid;//4
//int len;//8
//int maxlen;//c
DWORD unk1;//10
DWORD unk2;//14
wstring name;
//wchar_t* name;//18微信名
//int len;//1c
//int maxlen;//20

wstring msg; //
//wchar_t* msg;//3c
//int len;//
//int maxlen;
}

wstring msg 欄位就是文字訊息內容,而語音訊息則是預覽中看到的[語音]兩字,並沒有實際能夠聽到的語音資料,所以還得繼續往前找。

繼續往上回溯了 3 層左右,進入了 102DDC50,找到了語音訊息的新信息:

struct msg_xx

{
char unk[0x40];//
wstring wxid1;//40
wstring wxid2;//4c
char unk1[0x10];//58
wstring msg;//68 
char unk2[0x10];//74
;//84
}

在 wstring msg 處就是普通文字訊息內容,而語音訊息並不是我想象的就是直接語音的資料,而是…如下:

<msg><voicemsg endflag="1" cancelflag="0" forwardflag="0" voiceformat="4" voicelength="1176" length="1334" bufid="147445261304397871" clientmsgid="416261363964373964444633636200230013013119fdd53b1f494102" fromusername="wxid_xxxxxxxxx" />msg>

真是一波三折,還不是語音的資料,而是關於語音信息的 xml,有語音的大小,來自誰,在語音緩衝區中的id(bufid)等等信息。

繼續往前找唄,最後回溯到了所有訊息處理的分發函式 10323FF0 中。這個函式處理邏輯很複雜,我並沒有很快就找到如何生成語音訊息的 xml,以及處理語音資料的函式。

一度卡住,重覆分析了很多次。

後來又回神想到了逆向神器 IDA,xml 中資料如 voicemsg 肯定是模塊中會在代碼中用到,看看有沒有有用的信息。

用 IDA 打開 Wechatwin.dll,shift+F12 分析出所有字串,Ctrl+F 找到關鍵字 voicemsg,看來有戲。

真的是柳暗花明又一村。

點擊字串跳到代碼視窗,按下 x,跳到取用該資料的位置。

找到瞭解析語音 xml 資料和解碼語音資料的關鍵函式。

函式 103148E0 解析 xml 拿到幾個欄位的內容,傳回上層函式呼叫一個語音解碼的函式進行處理,而這個解碼函式就會直接操作語音資料。

函式 103148E0 回溯再看看,進入了分發函式 10323FF0 中,在一個迴圈中處理了多種流程,包括顯示界面最新訊息的流程和解碼語音的流程。所以前面找的方向並沒有問題,只是缺少認真分析資料和代碼的耐心。

不過,目的都達到了,找到了資料處理函式,最後通過 hook 這個函式就能拿到語音資料。

另外可以看到語音資料中包含 SILK_V3 的字符,這種編碼音頻格式是 Skpye 曾經使用的一種編碼方式,後來開源了。目前播放器並不能直接播放該編碼音頻檔案,所以需要轉碼為 MP3 等格式。不過可喜的是已經有大佬完成了這個工作,並開源了工具 silk-v3-decoder:

https://github.com/kn007/silk-v3-decoder

所以把代碼拿來整合一下,就可以完整的實現實時 dump 語音聊天資料,轉換為 mp3 進行儲存,完美。

總結

這是第一次比較成功的應用 CE,整個看來,確實省下來很多定位資料和函式的工作。

但CE並不是萬能的,要找對方法,找對標的資料才可能成功,對於某些沒有明顯資料的功能,可能也是無能為力。

最終還是得提高對大型軟體的逆向能力,總體實現思路的猜測以及除錯驗證。

最後,由於時間倉促,還沒有把儲存語音的功能加入到 SuperWeChatPC 專案中,後續會慢慢加入,歡迎持續關註:

https://github.com/anhkgg/SuperWeChatP

    赞(0)

    分享創造快樂