逆向WeChat (二)

bbqz007發表於2024-05-17

本篇在部落格園的地址https://www.cnblogs.com/bbqzsl/p/18187099

回顧一下現時網上的資源。

原生 https://github.com/duilib,

Ultimate https://github.com/qdtroy/DuiLib_Ultimate

騰訊 https://github.com/tencentyun/TIMSDK/tree/master/cross-platform/Windows/IMApp/Basic/duilib

網易 https://github.com/netease-im/NIM_Duilib_Framework/tree/master/duilib

主體框架2019年截止。

騰訊cross-platform/Windows/IMApp/Basic/duilib止於2019年開放的5.4.666版的TIMSDK。只能透過tag切換舊舊舊版。

最後一個開放的5.6.12版在路徑Windows/Demo/Basic/duilib,時間止於2021年8月31日。

網易開源版也止於2019年。

比較了一下,網易版對原生 改動很大,去除了CDuiString,全部用std::wstring。騰訊在TIMSDK的版本是基於DuiLib_Ultimate而不是原生的duilib。根據我逆向的CControlUI結構,現在WeChat使用的duilib是基於原生版的。DuiLib_Ultimate與原生兩個版區別的最大特徵在於,CControlUI結構使用了5個EventSource還是7個EventSource。

透過WeChat的日誌跟蹤路徑,WeChat不與其它產品共享程式碼,他們有一個專門子專案WeUIEngine,而非TIMSDK。架構應該可以參考網易的NIM_Duilib_Framework框架。注意是框架設計不是程式碼。

WeChat版的duilib,改動CControlUI成一個大而累贅的龐物,從CContainerUI的RTTI資訊可以看到,CControlUI是一個2816位元組的大基類。CDuiString的確是一個累贅,尤其Unicode下,大小是132位元組。而且這個基類一共使用了17個CDuiString。大廠的我不懂。後面的繼承類如CLabelUI就更加趨向於使用std::wstring。反正現在的電腦沒有16GB記憶體都不算電腦。

經過逆向後就可以對UI進行操作了。

WeChat使用了Chromium::base的MessagePumpForUI,簡單來說就相當於用win32有視窗訊息實現仿如iOS的dispatcher, 如我們熟悉的這個呼叫dispatch_async(dispatch_get_main_queue(), ^{ // update UI })。Chromium這專案,每個版本系列的程式碼都不同程式的重構,所以可以透過一些類來確認出WeChat所使用的版本是6系列的。也可以推斷出WeUIEngine開發的年份。現在這年,Chromium或cef的多執行緒任務框架也應該是用到爛大街的了吧。

有這個東西,就等於方便我使用,於是我就不客氣使用它向UI主執行緒投遞程式碼執行。進行測試,執行MessageBox顯示當前執行緒的ID。所以我已經先逆向了需要的東西。下面演示一下。

it works。訊息框在主執行緒376中執行了。

那麼WeChat是怎麼用它的呢,我原本以為WeChat會用它大作為一下,我的意思是有多一點用途,沒想到卻只是為了完成一個單一的UI功能,動畫,或者說是動畫的計時器。

先來找出dispatch任務的地方,只要跟蹤這裡,就可是知道WeChat都向這裡Post了些什麼程式碼。無它,將DebugBreak作為任務PostTask到MessagePumpForUI。透過呼叫棧就可以找出來了。再透過逆向分析出繫結的執行地址。

繫結的執行地址是base::RepeatingTimer,全部都只有定時任務。下面再來逆向分析都是些什麼定時任務。我也想知道重新整理掃碼,工作執行緒有沒有使用MessagePumpForUI將請求結果更新到UI。

定時器任務只有一個, 就是CPaintManagerUI::DelayPaint,名字是我起的,功能就是Paint,目的是動畫,還有增加或減少Paint的頻度。即使我重新整理了幾次重新掃碼,也沒有收到別的任務。也就是工作執行緒沒有透過Chromium::base的任務框架進行dispatch_async(ui_update)。

今期先到這裡。

我還有逆向通達信系列

相關文章