逆向WeChat(三)

bbqz007發表於2024-05-23

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

上篇回顧,物件是WEUIEngine。WeUIEngine使用了chrome::base框架,但只用來實現了單一的功能,只為了DUI的動畫計時器。

chrome::base框架沒有用作主執行緒的dispatcher,所有多執行緒並不向chrome::base框架投遞執行程式碼。win32執行緒的訊息佇列是一個優先順序佇列,PostMessage除了manual文件的官方用途外,往往也用作deferred佇列來使用。chrome::base框架使用的也就是這個佇列,只是用了一個專門的視窗。既然chrome::base在wechat中只是一個花架子,那麼一定需要一個等價物。

是的,這就是EventCenter。看名字,我就情不自禁地想起iOS的[NSNotificationCenter defaultCenter]。兩個主要的函式[[NSNotificationCenter defaultCenter] addObserverForName:object:queue:usingBlock:]註冊, [[NSNotificationCenter defaultCenter] postNotificationName:userInfo:]傳送事件。

事實也是這樣,WeChat定義了一個EventCenter,依附在UI主執行緒。專案之初應該是這個設計思路的。因為在早期的事件,會在一個專門的表註冊它的名字,這樣就可以透過名字來註冊觀察者或傳送事件。但是根據逆向分析,實際應用卻將名字擱置在一邊,不知道是多年來改版後擱置的,還是一開始就沒有在用。後面的開發見沒有用,就乾脆不註冊名字了。

觀察者必須使用EventHandler介面來註冊到EventCenter。EventCenter依附在UI主執行緒的一個deferred佇列,有獨立的視窗,作用就是依附線上程的訊息佇列。如字面意思,EventCenter在UI主執行緒分派事件處理器。EventCenter作為全域性單件,任意執行緒的任意程式碼都可以使用它postEvent來傳送事件。

下面是一些逆向的佐證。

透過列出當前EventCenter在案登記了處理器的事件,比對事件名字表,可以發現,每個類別早期編號的事件,都遵從起名字,並註冊名字。後期就懶得這樣做了。

下圖是透過LoginWnd向EventCenter查詢在案登記的事件。然後再向名字表查詢事件的名字。高興的是,早期的事件還可以知道名字。可惜的是,後期的事件沒有名字可以查。

下圖演示一個應用場景,在點重新掃描後,跟蹤傳送事件。可以看到是WinMarsWrap::OnTaskEnd在傳送事件ON_SCENE_NET_RESPONSE。既然事件傳送者已經引出來了,後面自然就是會對Mars進行逆向一下。

下圖演示,透過EventCenter列出所在在案登記的處理器物件,並列出它們的類名字。每個處理器對應著獨立的功能,基本上所有功能都依賴了這個EventCenter。到這裡wechat的基本結構脈胳也有了一個比較清晰的圖了。

綜上所述,將EventCenter的應用場景換作iOS,就是

[[NSNotificationCenter defaultCenter] addObserverForName:@“ON_SCENE_NET_RESPONSE” object:nil queue:[NSOperationQueue mainQueue] usingBlock:^{ loginwnd->processEvent(); }]

[[NSNotificationCenter defaultCenter] postNotificationName:@“ON_SCENE_NET_RESPONSE” userInfo:response]

本篇到這裡,下一篇再見。

我還有逆向通達信系列

我還有一個K線技術工具專案KTL可以用C++14進行公式,QT,資料分析等開發。

相關文章