在0day安全 这本书中第152页有下面一句话:
由于调试态堆管理策略和常态堆管理策略有很大差异:
1.调试堆不使用块表,只用空表分配
2.所有堆块都被加上了多余的16字节尾部用来防止溢出,这包括8个字节的
0xAB和8个字节的0x00
3.块首的标志位不同.
通过对以上语句的拜读,再加上自己不懈的调试,发现第三条说标志位不同是指
调试态是0x14而常态是0x10.而且后四个字节有很大不同
调试中发现在调试状态下用HeapCreate堆分配的空间初始化为0xfeeefeee
而常态则是0x00000000,似乎这也可以用来检验是否被调试!!!
一般意义下可以检测分配的堆数据是否为0x00,如果不是则处于调试状态.这样可以
简单的检测程序是否被调试.
但我们可以换一种思路,在很多情况下我们的函数都会传入参数0,或者1,2等较小的数值
参数0我们可以将堆里面的数值压入,常态下压入的是0,调试态压入的则是0xfeeefeee
导致程序的运行失败.而参数1可以在0的基础上加1,然后压入堆栈,完成参数的传递,同样
在调试态下传递的是错误的参数.这样可以达到反调试的目的
但是上面的方法对于一般的调试器可以蒙混过关对于OllyICE就不行了!!!
然而这确给出了这样的一个提示,那就是HeapCreate一定是检测了某个标志判断当前是否是调试态!!!!!
如果跟踪这个函数那么可以知道究竟判断了哪个标志位,进一步可以想出反调试的方法!!!
通过跟踪发现
7C945748 8B4D 98 mov ecx, dword ptr [ebp-68]
7C94574B F6C1 10 test cl, 10
7C94574E 0F85 4C680100 jnz 7C95BFA0
以上的ecx的值不同!!!常态和调试态jnz这句执行情况不一样!!
造成这一原因的是7C945706 E8 10A8FEFF call RtlGetNtGlobalFlags
这个函数?绝对是的!!!其实在<加密与解密第三版>第15章反跟踪技术中也刚好提到了这一点!!!
(只不过在发现以上情况的时候我没有想起来这一章的内容,这一章没有怎么看)
没想到我和也可以反跟踪了^_^
另外调试态和常态用HeapAlloc实际分配的堆的大小也是不同的
调试态分配的大小是常态的2倍
调试态和常态时候HeapFree也是不同的,调试态是将原来空间用0xfeeefeee
填充,而常态原来空间的数据则不变!但唯一更改的都是紧接着块首写入8个
字节大小的指针,前四个是Flink in freelist 后四个是Blink in freelist
阿里云助力开发者!2核2G 3M带宽不限流量!6.18限时价,开
发者可享99元/年,续费同价!