PC微信逆向:使用HOOK获取好友列表和群列表
文章目錄
- 獲取好友列表的切入點
- 定位查詢好友信息的函數
- 定位微信號的地址
- 一次錯誤的嘗試
- 再次查找目標函數
- 成功定位獲取好友信息的函數
- 定位獲取好友列表的函數
- 示例代碼
- 實際效果
- 預告
獲取好友列表目前有三種方法,第一種就是二叉樹遍歷,通過一層一層的往下讀取來拿到所有的好友列表。第二種是通過在內存里面找好友的地址列表。第三種就是通過查找微信數據庫來獲取列表
獲取好友列表的切入點
要想獲取微信的好友列表,就必須找到微信讀取好友列表的地方。突破口在于微信在點擊個人名片時,會獲取當前聯系人的詳細信息,然后顯示在右側。
那么我們可以大膽猜測 微信在登陸的時候,需要先調用這個call,循環拿到所有好友的詳細信息,然后再顯示到右側
第一步:我們首先要找到微信獲取好友詳細信息的函數。這個函數在讀取好友列表時必然會被調用,第二步,再通過這個函數找到獲取好友列表的地方。
另外還有一種方法就是通過好友的數量,先搜索當前好友的數量,然后刪除一個,再次搜索。直到找到保存好友數量的地址。
定位查詢好友信息的函數
那么如何找到查詢好友信息的函數呢?突破口在于當前窗口的微信號,只要找到微信號的地址,然后對微信號下內存寫入斷點,棧回溯分析就能找到我們需要的函數。
定位微信號的地址
首先搜索當前的微信號,勾選Unicode
接著切換聯系人,再次掃描
最終會剩下五個結果,我們需要逐個排查每一個結果
一次錯誤的嘗試
隨便找一個地址,下內存寫入斷點。然后切換當前聯系人窗口,斷點斷下。刪除內存斷點。
我們需要找到一個地址,地址里面包含聯系人的所有信息
在堆棧的地址中我們發現了一個返回地址,返回地址下面有微信的個人數據。那么這個有可能就是我們需要的call
切換當前窗口聯系人,等待斷點斷下
此時,堆棧和eax寄存器中保存了當前聯系人的所有數據
繼續往下拉會發現eax中保存有簽名和國家等信息。也就是說這個call里面保存了當前聊天窗口的好友的所有信息。
接著我們刪除好友,讓好友列表刷新,看看這個地方會不會斷下來。如果會斷下來,那么這個地方就有可能保存了所有好友的信息。
刪除之后,斷點并未斷下,那么這個call就不是我們想要的
再次查找目標函數
繼續找另外一個地址,下內存寫入斷點
此時再次搜索返回地址,你會發現在壓入返回地址前的一個參數中有一個完整的好友信息
這個call將一個完整的好友信息壓入堆棧,那么說明這個call之前好友信息已經被查詢出來了。我們需要繼續往上找, 反匯編窗口跟隨這個call
在函數頭部的位置下斷點
等程序斷下時在堆棧中找到返回地址
然后在找到的上一層函數下斷點,斷下之后按F8單步步過,看看這個函數的作用是什么
在這個call執行完畢之后,edi里面保存的就是好友的所有信息。那么說明這個call的作用就是查詢當前好友的詳細信息!
成功定位獲取好友信息的函數
接著我們F7進入這個函數,看看好友的詳細信息具體是從哪里個函數中查詢出來的
單步到這里我們發現在進入臨界區之后有一個函數,這個函數將微信ID的指針壓入棧,我們F8步過函數查看一下返回值
此時eax里保存了當前好友的所有詳細信息。通過參數和返回值也就可以猜到這個call的作用是通過微信ID獲取詳細信息。那么我們第一步就算是大功告成了。
定位獲取好友列表的函數
我們重新載入微信,然后在找到的獲取好友詳細信息的函數下斷點
登錄微信,此時斷點斷下,接著按F8步過
此時eax寄存器中保存有聯系人的數據,這個函數會調用多次,每調用一次查詢一個好友信息。
事實上獲取好友列表的call不止這一個地方,但是這個地方拿到的數據是最多的。可以拿到所有的好友列表和群列表以及公眾號
函數已經找到了,那么我們只要寫一個dll,注入到微信的進程空間中,利用Inline HOOK就能獲取到所有的好友列表了
示例代碼
部分示例代碼如下:
開始HOOK:
VOID StartHook(DWORD hookAdd, LPVOID jmpAdd) {BYTE JmpCode[HOOK_LEN] = { 0 };//我們需要組成一段這樣的數據// E9 11051111(這里是跳轉的地方這個地方不是一個代碼地址 而是根據hook地址和跳轉的代碼地址的距離計算出來的)JmpCode[0] = 0xE9;//計算跳轉的距離公式是固定的//計算公式為 跳轉的地址(也就是我們函數的地址) - hook的地址 - hook的字節長度*(DWORD *)&JmpCode[1] = (DWORD)jmpAdd - hookAdd - HOOK_LEN;//hook第二步 先備份將要被我們覆蓋地址的數據 長度為我們hook的長度 HOOK_LEN 5個字節//獲取進程句柄HANDLE hWHND = OpenProcess(PROCESS_ALL_ACCESS, NULL, GetCurrentProcessId());//備份數據if (ReadProcessMemory(hWHND, (LPVOID)hookAdd, backCode, HOOK_LEN, NULL) == 0) {MessageBox(NULL, "hook地址的數據讀取失敗", "讀取失敗", MB_OK);return;}//真正的hook開始了 把我們要替換的函數地址寫進去 讓他直接跳到我們函數里面去然后我們處理完畢后再放行吧!if (WriteProcessMemory(hWHND, (LPVOID)hookAdd, JmpCode, HOOK_LEN, NULL) == 0) {MessageBox(NULL, "hook寫入失敗,函數替換失敗", "錯誤", MB_OK);return;}}顯示好友列表
//顯示好友列表 VOID insertUserLists(DWORD userData) {/*eax + 0x10 wxid 群eax + 0x30 wxid 群eax + 0x44 微信號eax + 0x58 V1數據eax + 0x8C 昵稱eax + 0x11C 小頭像eax + 0x130 大頭像eax + 0x144 未知md5數據eax + 0x1C8 國籍eax + 0x1DC 省份eax + 0x1F0 城市eax + 0x204 添加來源eax + 0x294 朋友圈壁紙*/DWORD wxidAdd = userData + 0x10;DWORD wxuserIDAdd = userData + 0x44;DWORD wxidV1Add = userData + 0x58;DWORD wxNickAdd = userData + 0x8C;DWORD headPicAdd = userData + 0x11C;//DWORD wxNickAdd = userData + 0x8C;wchar_t wxid[0x100] = {0};if ((LPVOID *)wxidAdd) {swprintf_s(wxid, L"%s", *((LPVOID *)wxidAdd));}wchar_t nick[0x100] = { 0 };if ((LPVOID *)wxNickAdd) {swprintf_s(nick, L"%s", *((LPVOID *)wxNickAdd));}wchar_t wxuserID[0x100] = { 0 };if ((LPVOID *)wxuserIDAdd) {swprintf_s(wxuserID, L"%s", *((LPVOID *)wxuserIDAdd));}if (oldWxid[0] == 0 && newWxid[0] == 0) {swprintf_s(newWxid, L"%s", *((LPVOID *)wxidAdd));}if (oldWxid[0] == 0 && newWxid[0] != 0) {swprintf_s(oldWxid, L"%s", newWxid);swprintf_s(newWxid, L"%s", *((LPVOID *)wxidAdd));}if (oldWxid[0] != 0 && newWxid[0] != 0) {swprintf_s(oldWxid, L"%s", newWxid);swprintf_s(newWxid, L"%s", *((LPVOID *)wxidAdd));}if (wcscmp(oldWxid,newWxid) != 0) {LVITEM item = { 0 };item.mask = LVIF_TEXT;item.iSubItem = 0;item.pszText = UnicodeToANSI(wxid);ListView_InsertItem(gHwndList, &item);wxuserIDitem.iSubItem = 1;item.pszText = UnicodeToANSI(wxuserID);ListView_SetItem(gHwndList, &item);item.iSubItem = 2;item.pszText = UnicodeToANSI(nick);ListView_SetItem(gHwndList, &item);} }實際效果
預告
最后,預告下一期,我的微信助手成品即將完成,現已完成大部分功能,再添加幾個功能就全部完成了,屆時將開放成品和所有源代碼
目前微信機器人的成品已經發布,需要代碼請移步Github。還請親們幫忙點個star
https://github.com/TonyChen56/WeChatRobot
總結
以上是生活随笔為你收集整理的PC微信逆向:使用HOOK获取好友列表和群列表的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mathtype使用小技巧
- 下一篇: 因路径乱码使InstallShield