PC微信端读取联系人有三种常规方法:javascript
其实前两种方法只是利用微信启动后已经读取联系人放到内存。第一种是拦截过程,第二种是直接获取内存的结果。java
找CALL请看:https://blog.csdn.net/qq_3847...c++
我就不复述了,我也是小白,也是一步一步按照博客来操做的。我就直接给当前最新版本(2.8.0.121)的须要hook的地址偏移:0x479F07,若是不想本身找CALL的话,能够直接用OD跳转到 WeChatWin.dll + 0x479F07
这个地址。已经知道须要hook的地址,只须要用c++写dll而后注入到微信进程就能够获得全部的联系人信息了(这个call会在登陆时被调用屡次,因此须要登陆前就注入dll)数据库
成品软件和dll(软件是用aardio写的,dll是用c++写的):https://www.lanzous.com/iakfpch微信
效果图:spa
相比于第一种方法,这个更简单,连写dll注入都不须要。只要读内存中的数据就行。.net
首先咱们须要找到二叉树的根节点地址,方法请看:https://www.jianshu.com/p/b55... (环境声太吵,人说话声音有点小,不过讲的不错)3d
最新版本(2.8.0.121)二叉树根节点的地址:[[WeChatwin.dll + 0x161CF54]+0x28+0x84] + 0x4
,中括号表示取地址里面的值。这个地址的偏移也是经过第一个方法的call找出来的,并且第一个方法中的call进去的代码就是经过传入的wxid来循环遍历二叉树来获取该wxid对应的好友数据。code
咱们看一下call里面的汇编代码段:
而后用aardio来实现就是:orm
import process; import console; getBTree = function(prcs, esi){ //前面不加var表示全局变量 if (!prcs.readNumber(esi + 0xD, "byte")){ //cmp byte ptr ds:[esi+0xD],0x0 //wxid wxidAddr = prcs.readNumber(esi + 0x10) //获取wxid地址 wxidLen = prcs.readNumber(esi + 0x14) //获取wxid长度 wxid = prcs.readStringUtf16(wxidAddr, wxidLen) // 读取Unicode字符串 wxid = string.fromUnicode(wxid) //将Unicode字符串转换为utf-8 //微信号 微信号地址 = prcs.readNumber(esi + 0x44) 微信号长度 = prcs.readNumber(esi + 0x48) 微信号 = prcs.readStringUtf16(微信号地址, 微信号长度) 微信号 = string.fromUnicode(微信号) //昵称 昵称地址 = prcs.readNumber(esi + 0x8C) 昵称长度 = prcs.readNumber(esi + 0x8C + 0x4) 昵称 = prcs.readStringUtf16(昵称地址, 昵称长度) 昵称 = string.fromUnicode(昵称) //备注 备注地址 = prcs.readNumber(esi + 0x78) 备注长度 = prcs.readNumber(esi + 0x78 + 0x4) 备注 = prcs.readStringUtf16(备注地址, 备注长度) 备注 = string.fromUnicode(备注) //v1 v1Addr = prcs.readNumber(esi + 0x58) v1Len = prcs.readNumber(esi + 0x5C) v1 = prcs.readStringUtf16(v1Addr, v1Len) v1 = string.fromUnicode(v1) //未知a1 a1Addr = prcs.readNumber(esi + 0xCC) a1Len = prcs.readNumber(esi + 0xD0) a1 = prcs.readStringUtf16(a1Addr, a1Len) //未知a2 a2Addr = prcs.readNumber(esi + 0xE0) a2Len = prcs.readNumber(esi + 0xE4) a2 = prcs.readStringUtf16(a2Addr, a2Len) console.writeText(string.format("%s | %s | %s | %s", tostring(wxid), tostring(微信号), tostring(昵称), tostring(备注)) + '\n') 左节点地址 = prcs.readNumber(esi) getBTree(prcs, 左节点地址) 右节点地址 = prcs.readNumber(esi + 0x8) getBTree(prcs, 右节点地址) } } var readData = function(){ console.open() prcs = process.find("WeChat.exe") if (null == prcs){ console.writeText('未找到微信进程,请先打开微信登陆后操做!') return } wechatwinAddr = prcs.getModuleBaseAddress('WeChatWin.dll') ecx = prcs.readNumber(wechatwinAddr + 0x161CF54) + 0x28 + 0x84 ebx = prcs.readNumber(ecx) //mov ebx,dword ptr ds:[ecx] esi = prcs.readNumber(ebx + 0x4) //mov esi,dword ptr ds:[ebx+0x4] esi也就是二叉树的根节点 getBTree(prcs, esi) console.pause('按任意键关闭!') } readData()
汇编代码中作了不少比较,是由于它要对比传入的微信ID和内存中的数据,而咱们全都要则不须要对比,直接递归读取二叉树的左右节点便可。效果就不放了,本身下载aardio运行一遍就行。