前言
这篇文章来说说逆向的原理和实现。
需要用到的工具
- 微信(
3.9.12.51) - x64dbg
- Cheat Engine
- Python
逆向
首先从一些网络上搜索到的信息可以得出联系人列表是保存在内存里的,并且是全局变量不会被释放,所以我们可以通过搜索某个联系人的信息来定位
1、先定位到单个联系人
首先搜索某个好友的微信号,勾选UTF-16 (4.0不需要勾选),找一个结果比较少的,就比如下面的结果19个

然后一个一个去搜索8字节指针

将搜索的结果放到x64dbg里查看(dump 地址或者打开计算器在内存窗口转到),直到看到下面的内存结构(有wxid和v3)

这个很大概率就是联系人的内存结构了,然后搜索结构体的开始地址1D107941030,这个怎么确认哪个是开始地址呢?只能凭经验或者靠猜然后一个一个去验证,因为之前的版本开始地址就是带有wechatwin的地址

这个就是联系人链表的某个节点的数据了,前三个是指向其他节点的指针,然后下面有个wxid,最后一个就是联系人信息的头结点。
这个和之前的版本有点不一样,之前的版本没有这个wxid,直接将联系人信息放到其他节点的下面,估计是为了和4.0保持一致吧,因为4.0就是这种结构。
只要一直遍历前三个指针,就能找到下面没有wxid的一个地址,这个就是所有节点的初始节点,如果是之前的版本,可以通过在CE中右键对这个地址进行指针扫描来定位这个初始节点的基址。但是这个版本无法定位到偏移了,可能就是一个随机分配的地址。当然肯定是有规律可以查找到这个地址,不然微信内部也无法定位(没仔细研究过)。

会扫描出很多个结果,需要关闭微信重新打开,然后重新找头指针的地址,然后点指针扫描器->重新扫描内存会继续排除掉一部分,直到没几个结果。
无法定位到基址
既然无法定位到基址,那怎么自动找到这个头结点的地址呢?其实可以通过内存搜索的方法自动查找到。因为我发现每个联系人的头部都是固定的地址
000001D107941030 00007FFB177E0A98
000001D107941038 00007FFB17744A90
在IDA中可以看到这两个就是联系人相关的结构(4.0抹除了这些符号,看不到这种名称了)


所以可以通过搜索这两个地址,来定位到单个联系人信息,也可以将所有的结果都搜出来,然后进行去重就是所有联系人了。或者继续搜索这个联系人信息的头,定位到上层的结构,然后开始遍历所有的节点也能拿到所有的联系人
扫描内存
Python怎么像CE一样扫描其他进程的内存呢,暂时没搜到什么很好的工具,只能自己实现了。
首先通过GetSystemInfoAPI获取到内存的最大和最小地址,然后通过VirtualQueryEx从最小地址遍历到最大地址,获取所有指定进程的内存块。x64dbg的内存布局就是该进程的所有内存块

随便找一个联系人信息的头放到计算器里,然后选择在内存布局里查看

可以查看到内存块有什么特征:
- 不是保留地址
- 地址类型是私有内存(PRV)
- 权限是RW
- 分配的初始权限也是RW
那么我在扫描内存的时候就根据上面的条件过滤掉一些内存块,扫描内存的代码如下:
import ctypes
from ctypes

最低0.47元/天 解锁文章
1万+






