为什么以下汇编代码是反调试工具?
l1: call l3 l2: ;some code l3: mov al,0c3h mov edi,offset l3 or ecx,-1 rep stosb
我知道C3h是RETN,我知道stob根据edi的偏移量将值写入al中作为操作码,并且由于rep而对ecx时间进行了修改.
我也知道,如果他们以英特尔架构预先获得原始格式,那么这个事实就是这样的.
如果我们以调试模式运行程序,则预取是不相关的,并且l2标签将运行(因为它是单步的),否则如果没有调试器,它将在l1和l3之间乒乓,我对吗?
当程序被调试(即单步)时,每个步骤刷新预取队列(发生中断时).然而,当正常执行,不会发生代表stosb.旧的处理器没有刷新它,即使有内存写入缓存区域,以支持自修改代码,除了rep movs和rep stosb. (IIRC最终在i7处理器中固定.)
这就是为什么如果有一个调试器(单步)代码将正确执行,并且代表stosb被替换为ret l2将会被执行.当没有调试器代表stosb将继续,因为ecx是最大的可能,它将最终写在某处,它不应该写,并将发生异常.
这种反调试技术在this paper中有描述.