zmrbak(赵庆明老师)
前言
2019年4月份 JieKeH的一篇文章《PC微信逆向---分析获取登录二维码的数据》一文,让不少的朋友对微信这个软件产生了浓厚的兴趣,当然也包括我。令我印象最深刻的莫过于“打开微信的Xlog日志输出”这部分内容。
虽然腾讯公司在微信的发布版本中对调试信息进行了屏蔽,但JieKeH通过IDA反汇编的伪代码与Xlog源码对比的方式找到了输出调试信息的关键点,并提供了突破屏蔽的方法。在学习了这篇文章后,本人也通过OD中的反汇编代码与Xlog源码对比的方式,同样找到了相应的关键点,之后将其录制成一个视频分享给了身边一起研究的朋友们。
新问题新对策
很不幸,该文章出现后不久,新版本的微信进行了相应的调整,JieKeH文章中所讲述的方法完全失效。身边的朋友不时告诉我,这个方法失效了,同时请教我还有什么办法可以输出这些调试信息。其实,玩过HOOK的朋友,会马上想到另一个办法,就是写一个dll注入,在dll中编写相应的逻辑实现需要的功能。我用这种方法录制了一个小视频分享之后,再也没有人问过这个问题。看来这个办法还是不错的!
更简单的方式
编写DLL,所涉及到的知识较多,涉及到编码、编译、注入等一系列操作,不但操作复杂而且修改也不容易。近日,最新正式版的微信2.8.0.106推出,我在此新版本上进程了相关的尝试,其实只是在CE中进行简单的一些设置,即可满足需求,就算是新手也不难掌握。由于剪辑视频太耗时间,而且相比于上一个视频也没多少新意,因此仅整理成文档分享给大家。部分内容,之前的视频中有讲解,这里就不再赘述,直接进入本文主题。
定位“是否启用调试”的地址
在OD中附加微信后,查询二进制代码“74 14 FF B5 EC FE FF”(为何是这个二进制代码,请参考之前的视频讲解),定位到如下代码片段,并在接下来的CALL(WeChatWi.79164604)上下一个断点:
ds:[0x79A6CA01],这个地址,就是是否启动调试的开关。计算出偏移地址:0x160CA01。在微信中,这个地址中的数据被设置成0,因此调试信息将不会输出。只要将这个地址中的数据更改为1,那么输出调试信息的开关就被打开了。但是,调试信息还有其他开关,那就是调试级别。
定位“调试级别”的地址
查询二进制代码“56 89 9D F0 FB FF FF”(为何是这个二进制代码,请参考之前的视频讲解),定位到如下代码片段:
进入 WeChatWi.79154DB0这个CALL后,到达如下代码片段:
ds:[0x79A1CD54],这个地址,就是调试级别的设置。计算出偏移地址:0x15BCD54。在微信中,这个地址中的数据被设置成2,也就是高于“kLevelDebug”的信息才会被输出。只要将这个地址中的数据更改为0,也就是“kLevelAll”或“kLevelVerbose”,也就是输出全部调试信息。
定位调试数据的代码段
在JieKeH的文章中,完成这两步设置后,调试信息即可输出,在DebugView中课捕获微信自身的调试信息。正如前文所述,随着微信版本的升级,此方法很快失效。于是,基于此设置,我再用HOOK的方式,重新让微信具备了调试信息的输出的功能。到目前最新的2.8.0.106版本,HOOK方法依然有效。当然,无论怎么做,定位调试数据这个步骤还是不能少的。
用鼠标动一动微信,OD中程序将暂停在调用“WeChatWi.79164604”处(之前下的断点处),按F7进入该函数。注意观察堆栈窗口,持续按F8,单步执行,直到堆栈顶部出现如下类似的信息。这些信息,就是原本要输出的调试信息。接下来,在HOOK中,同样把这个数据提取出来,从调试信息中输出,然后在DebugView中捕获。
这时候,观察程序运行的代码部分,计算出该代码片段中“add esp,0x4c“所在汇编代码的偏移地址:0xCE7853。其代码片段如下:
在上一个HOOK的视频中,我在这里进行了HOOK。在本文中,我使用CE来进行一小段“代码注入”即可代替编写DLL这种难度高、而且手续繁杂的工作。
定位堆栈中数据的地址
虽然数据在堆栈顶部,但是由于下来要对堆栈进行操作,如果使用ESP来取数据,还需一些手动的计算,稍显麻烦。由于EBP在堆栈操作过程中会保持不变,因此我们使用EBP加上一定的偏移量来取数据,这样就不需要额外的手动计算。
在OD堆栈窗口中,点右键选择“转到EBP“,在该行的地址上双击,变成”$==>“
然后,在OD堆栈窗口中,点右键选择“转到ESP“,记录该行相对于EBP的偏移:$-40E0。也就是说,当前的数据位于[ebp-0x40E0]这个地方,也就是ESP所指向的地方。因此,我们取到了数据存储的地址:ebp-0x40E0。
使用CE编写代码注入脚本
启动CE,附加微信。点击“手动添加地址”,分别添加“WeChatWin.dll+0x160CA01”与“WeChatWin.dll+0x15BCD54”,再分别命名为“输出调试信息”和“设置调试级别”,再将其值分别更改为1与0,如下图所示:
点击“查看内存”,定位到“WeChatWin.dll+CE7853”,并选中此行。
接下来,在“内存浏览器”窗口中依次点击“工具\自动汇编”,在弹出的新窗口中,依次点击“模板\CT表框架代码”,再依次点击“模板\代码注入”,确保弹出对话框中内容为“"WeChatWin.dll"+CE7853”(代码选中的位置),点击“OK”。
接下来,依次点击“文件\分配到当前的CT表”,然后点击关闭。CE的主窗口中将多出一行内容。将其改名为“OutPutDebug”。记得随时按Ctrl+s(保存)。
双击OutPutDebug中的数值栏中的“脚本”,在打开的新窗口中对该脚本进行编辑。在newmem与originalcode之间添加如下代码(备注:0x7747efd0,就是OutputDebugStringA函数地址。相关理论,不赘述):
pushad
push [ebp-0x40E0]
call 0x7747efd0
popad
点击“确定”。记得再按Ctrl+s保存。
开始测试
- 输出调试信息:1
- 设置调试级别:0
- OutPutDebug:启用(那个方框中间画一个叉)
以管理管身份启动“DebugView”软件,用鼠标动一动微信,即可观察到微信输出的调试信息。
源码及工具
交流QQ群:
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)