android端的之前参考如下帖子:
https://blog.csdn.net/yy405145590/article/details/79963999
但是这个帖子出来之后,微信在pack之后又封装了一层,尝试跟踪,在tencent.mm:push进程下,java端最后断在一个req2buf函数中,但是这个函数是由so调用的,能力有限,还没调到具体调用的地方。所以试试看转战PC端。
使用微信版本2.6.4.56
首先发现这个报文是和手机端就不一样,当手机向PC发送消息时,是先发送一个不知名报文,然后PC端返回一段比较长的报文,然后才会收到真实数据报文。
通过内存断点,目前发现PC端返回的断点可能是用来给真实收到的报文解密的。
具体调试方式如下:
直接在ws2_32.dll中查找recv函数,下函数断点。因为微信是tcp的,应该不是udp,
下内存断点,查看访问数据段的地方。(这里内存断点下在靠后的部分,前面部分是一些标示位,可能进不了加密段)
而后进入一个函数,偏移为100215A0,这里修改函数备注为procecv26
共有5个参数,分析可知第一个是收到的报文,第二个是解码后的报文,第三个作为功能标示位,让函数进入不同的功能块。第四和第五个参数用来生成秘钥,用于后续加密。
调试发现第三个标识位功能大概如下:
1:处理收到的第一条通知报文吧,每次手机发消息给pc,都会现有一条很短的消息收到,处理完之后才能收到真正的消息内容。
16:解密收到的报文实际内容(17也可以这里,猜测不是单纯的判断是哪个数字,而是位操作判断进入哪个流程,这里没细看)
5:加密要发送的数据吧应该是
调试发现,该算法对称加密,加解密进入同一个流程。但是加解密跳转的地方不一样,加密待发送数据在676处
继续往上跟,进入偏移10B91740模块函数,但是这里IDA无法分析这个函数。直接从汇编层看,最终调用部分如下:
主要加密参数就是这个ebx和 esp+28h所存储。
通过ollydbg跟一遍,了解下当前代码跳转过程:分别在1790、1833、18B5发生跳转。而后算出这两个参数的由哪里得到:
ebx: 函数的第一个入参
esp+28h:函数的第一个入参+偏移0x174得到.
这里发现微信从汇编层面来看,会根据不同的cpu进入不同加密模块,应该是编译器子集优化的吧。
上述的函数如果看xmm指令较吃力的话,可以再看看偏移10026800处的一个函数,这个是在比较老的cpu上处理的解密函数,没有xmm相关模块。
通过写了一个hook dll,可以输出上述函数的所有入参和出参,具体参考以下博客:
https://blog.csdn.net/liutianheng654/article/details/83547078
这里没找到密钥生成的地方暂时。而后考虑在微信android端的pack函数在哪儿。首先查找其中标准openssl的类库,发现是ssleay32.dll。但是从中找到aes相关的函数,下断点之后,发现不管哪个函数都没有断下来,猜测腾讯可能使用了自己写的方式实现aes加密。
使用peid的kanal的插件查看,发现其中有aes加密,如图:
在dll的偏移9797b1处下断点,可以看到在接受消息时断下来了。而后往上找,找到加密部分的代码,
97B830:其中第一个入参是加密原文,返回时第二个是加密后密文。
这里发现,当发送数据较少时,直接发送原文,发送数据较多时,会先经过一步zlib压缩,一步步通过调用堆栈网上找,找到压缩部分代码:
9764E1:当前ecx带入待压缩数据,ebp-3c的地址,保存压缩后的数据。
加密环节到此走完:
反之解密流程也是先外层解密,而后aes解密,然后zlib解压缩。这里解压的时候看到了789c开头的压缩块,判断是通过zlib方式解压的,不过这里也没有写代码验证。各个函数偏移也通过逆向跟踪全部得到:
第一个外层解密函数,和外层加密函数在一起,只是根据第三个参数进入不同的分支,没有细看了就。
通常加密部分代码也离解密部分不远,通过尝试,在找到的加密函数附近的函数下断点,找到了解密函数。
解压函数是通过对aes解密后的数据块下内存访问断点,以下就进入了解压模块,但是这里太里层,跳出这个大循环就找到了解压函数。
通过编写dll注入工具,输出流程中所有的输入和输出。
代码等写完传上来。。分析过程中微信升级了。。。不过调试方式还是能用的,但是如果函数偏移的话必须得我上面指定的版本号了
https://download.csdn.net/download/liutianheng654/10788965
最后的代码,写的还是比较匆忙了。。
在现有基础上,hook的代码可以随意添加了,实现自己想要的功能,什么聊天记录保存的应该很容易了。