正常一次最多邀請40人進群
超過40人的拉群,會變成邀請,需要對方同意
新版本修復了漏洞,但還是可以用老版本進行強制拉群
雖然官方也做了版本過低的限制,但還是有辦法繞過
要么修改版本號或者登錄幾天新版本,之后就可以登錄老版本
關鍵是,新版本的修復漏洞的方案并不徹底
深入研究發現更嚴重的漏洞,最新版本也能強制拉群
而且這個漏洞是Duilib框架層面的,影響的不只是拉群老版本強制拉群漏洞
1、正常情況
點擊主界面的添加群成員
會彈出一個選擇用戶的界面
再去點主界面的添加群成員
選擇用戶的界面還是同一個
2、異常情況
工作臺-客戶群-前往查看客戶群-添加群成員
點多少次就會出現多少個選擇用戶的界面
分析漏洞背后的原因
父界面的句柄
企業微信的界面框架是Duilib
彈出子界面之后,還能點擊父界面
第一反應是創建子界面沒有傳父界面的句柄
攔截創建界面的函數Create,發現都有傳父界面的句柄
1、正常情況
2、異常情況
好玩的是,正常和異常情況的兩個選擇用戶界面可以同時出現
因為“工作臺-客戶群-前往查看客戶群”這一步,創造新界面的時候沒有傳父窗口句柄
調用堆棧
既然都傳了父界面的句柄,那差異可能是代碼邏輯不一樣
繼續攔截創建界面的函數Create,看調用堆棧有什么差異
1、正常情況
調用堆棧有DispatchMessageW,并且窗口事件是0x403
0x403代表的是自定義消息,說明創建子界面的異步的
2、異常情況
調用堆棧有WndProc,并且窗口事件是0x202
說明是鼠標彈起之后,直接同步地創建子界面
窗口屬性
正常情況異步創建子界面,但父界面沒響應
異常情況同步創建子界面,但父界面有響應
都有父窗口句柄,說明正常情況額外加了邏輯
用spy++看一下父界面窗口的樣式屬性
1、正常情況
創建子窗口之前
創建子窗口之后
多了WS_DISABLED,因此父界面沒響應
2、異常情況
創建子窗口之前
創建子窗口之后
沒有WS_DISABLED,因此父界面有響應
漏洞的原因就定位到了:異常情況,父窗口的樣式因為沒有WS_DISABLED導致能被點擊多次
最新版本利用這個原理,正常情況點擊添加群成員,代碼去掉WS_DISABLED,可以被點擊多次
沒有WS_DISABLED是最終結果,好奇代碼層面到底是哪里出問題
對SetWindowLong下斷點,看下是不是異常情況少了這個邏輯
發現正常情況和異常情況都沒有命中SetWindowLong這個函數
影響WS_DISABLED的API還有EnableWindow,繼續下斷點
確實正常情況會調用EnableWindow,異常情況則不會
EnableWindow對應在Duilib里面是ShowModal
問題就出在:異常情況沒有調用ShowModal,導致父窗口沒有鎖定
但因為異常情況是同步創建子窗口,如果直接調用ShowModal會進入新的消息循環,同一線程的父窗口消息循環會被阻塞,自己維護一下EnableWindow會好一些
不過就像前面說的,正常情況有調用ShowModal,去掉WS_DISABLED還是能強制拉群
想要保證窗口的唯一性,還是得在邏輯代碼上加判斷,不能只是依賴Duilib框架本身的限制