各位大佬请指正,一时思考,并未做更多详细研究。
很久没碰wx了,最近想写个东西,就重新拿了起来,最新版本2.6.8.65(此时已经2.6.8.68)。
找到以前分析过的发送文本消息接口,发现函数大变样,很明显的vm痕迹。
当时也没在意,仔细看接口参数并没有变化,就直接拿来用了。
结果发现接口不能用了,并没有成功发送文本信息。
擦,难道vm里面藏了什么玄机,做了防止函数调用的保护??
...
正整备大干一场的时候,重新测试给别人发送消息是ok的。
这是一次美丽的误会,测试时是给自己的微信发送消息,结果证明该接口是不能给自己发的,所以没成功。
...
然后就继续说说先前自以为的wx在函数中可能做的防止调用的保护吧。
按照自己思考的防止别人调用函数的思路,其实就是检查调用源,那么肯定是从调用栈入手:
大概实现代码就是:
所以能够想到的对抗方式就是在调用TestAntiCall的时候,修改调用栈返回地址,让TestAntiCall误以为确实是正常调用。
这里分析只考虑检查一层返回地址。
比如如下正常调用代码,00003就是返回地址,在合法模块内,即可正常调用。
而我的调用TestAntiCall函数(在我的模块内)如下,add esp, 4;
为TestAntiCall拿到的返回地址,这个地址肯定在我的模块内,调用失败。
然后尝试欺骗TestAntiCall
,我们修改一下调用栈的返回地址(本来应该是MyRetAddr)。
通过push+jmp
来替换通常的call
,这样返回地址由我们自己压入,这里压入正常调用的返回地址g_SendTextMsgRetAddr
。
当然,就这么简单的调用,肯定会出问题的,因为jmp pfnWxSendTextMsg
之后,就会返回到Right_TestAntiCall
的00003
,如此显然导致栈破坏,会出现崩溃。
所以为了让程序正常执行,还需要多两个处理步骤。
为了拿到MyRetAddr的地址,通过call+pop的方法完成,如下:
上面拿到retaddr和MyRetAddr明显不是同一个,所以在fakeAntiTestCall
中减去一个偏移24拿到MyRetAddr
。
偏移值通过下面的字节码可以计算出来10024E1E
- 10024E06
= 24。
如此可以正常完成一次调用,但是还有问题,因为会反复修改Right_TestAntiCall
的指令,可能在多线程中执行时出现问题。
所以更好的方法时在Right_TestAntiCall
的模块中找一个不用(零值)的内存,用来保护临时指令,不细讲了,大家自行探索吧。
(完)
欢迎关注:汉客儿
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)