在我以前的雇主,我们使用了第三方组件,它基本上只是一个DLL和一个头文件.该特定模块在Win32中处理打印.然而,制造该组件的公司破产了,所以我无法报告我发现的错误.
所以我决定自己修复bug并启动调试器.我很惊讶地发现几乎所有的反调试代码都是常见的IsDebuggerPresent
,但引起我注意的是:
; some twiddling with xor ; and data, result in eax jmp eax mov eax, 0x310fac09 ; rest of code here
乍一看,我刚刚跨过了被叫两次的例程,然后事情就变成了香蕉.过了一会儿,我意识到这个小小的结果总是一样的,即jmp eax总是跳到mov eax, 0x310fac09
指令中.我解剖了字节,那里是用于测量DLL中某些调用之间花费的时间0f31
的rdtsc
指令.
所以我的问题是:你最喜欢的反调试技巧是什么?
我最喜欢的技巧是为一个不起眼的微处理器编写一个简单的指令仿真器.
然后将为微处理器编译复制保护和一些核心功能(GCC在这里是一个很好的帮助)并作为二进制blob链接到程序中.
这背后的想法是,普通x86代码中不存在复制保护,因此无法进行反汇编.您无法删除整个模拟器,因为这会从程序中删除核心功能.
破解程序的唯一机会是对微处理器仿真器的工作进行逆向工程.
我已经使用MIPS32进行仿真,因为它很容易模拟(只需要500行简单的C代码).为了使事情变得更加模糊,我没有使用原始的MIPS32操作码.相反,每个操作码都与它自己的地址进行了对比.
复制保护的二进制文件看起来像垃圾数据.
强烈推荐!在裂缝出现之前花了超过6个月(这是一个游戏项目).
我一直是许多RCE社区的成员,并且在破解和破解方面做得很好.从我的时间开始,我意识到这种脆弱的技巧通常是不稳定的,而且相当无用.大多数通用的反调试技巧都是特定于操作系统的,根本不是"可移植的".
在前面提到的示例中,您可能使用内联汇编和naked
函数__declspec
,这两者在x64体系结构上进行编译时都不受MSVC支持.当然还有实现上述技巧的方法,但是任何已经反转足够长时间的人都能在几分钟内找到并击败这个技巧.
因此,我建议不要在使用IsDebuggerPresent
API进行检测之外使用反调试技巧.相反,我建议您编写存根和/或虚拟机的代码.我编写了自己的虚拟机并且已经改进了很多年了,我可以诚实地说,到目前为止,它是迄今为止我在保护代码方面做出的最佳决定.
关闭作为调试器附加到父级的子进程并修改关键变量.用于保持子进程驻留并使用调试器内存操作作为某种键操作的IPC的加值点.
在我的系统上,您无法将两个调试器附加到同一进程.
关于这一个的好处是,除非他们试图篡改任何事情没有任何破坏.