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