如何混淆C程序中的调用堆栈,并强制编译器不在堆栈中推送返回地址



我想强制生成的可执行文件(适用于Linux和Windows(,当我调用函数/API时,不要在堆栈上推送返回地址。

那么,实现这一点最简单的方法是什么呢?假设我使用GCC或Visual Studio编译程序,并且我希望每个调用指令都能这样。我想这样做的原因是混淆我的程序。

如果在编译器级别无法做到这一点,那么我如何才能实现同样的目标?

例如,这个解决方案是什么:

我将每个函数/API调用替换为一个宏,该宏获取目标函数加法器,推送参数,加密返回地址,推送加密的返回地址,并对目标函数地址执行jmp(使用内联汇编ofc(,因此不使用调用指令;然后,在我的函数中的每个返回位置之前,我放置一个宏,用于解密推送的返回地址和jmp(再次使用内联汇编(。

所以这是最好的解决方案,对吧?

void foo()
{
...
}
int main()
{
foo(); // obfuscate this in a way that it doesn't use call, or the call somehow doesn't push the return address.
}

请注意,我只想以已知调试器无法显示调用堆栈的方式来实现这一点,例如Windbgxdbg

你不能。当你制作call时,你需要一个返回地址,这是不能以任何方式修改的。

想要使用jmp是无关紧要的。这将适用于函数A。但对于函数Bjmp将无效,因为它将再次跳回到A,而不是B

要么你把所有的代码都放在一个单一的、丑陋的、巨大的函数中(使用#define伪函数来确保内联(,那么里面只有jmp,要么你忘记了欺骗CPU机制。

即使你编写了自己的编译器,你也会面临完全相同的问题:当你有多个调用点时,你应该在函数完成后返回吗


混淆不是保护代码的好方法,它不会阻止任何了解汇编程序的人,因为最终,您必须有有效且有意义的ASM指令才能执行任何请求。所以它是可以追踪的。

您可以检查此页或此页,以了解正确的反调试技术。但是,你在代码中使用的技巧越多,你就越有可能被任何像样的防病毒软件立即杀死。

因为不要忘记:在fine中,任何黑客都可以用nop(hexa中的0x90h(替换代码中每一个令人讨厌的部分,将合适的值放在合适的寄存器/内存中以绕过所有内容,或者用条件内的jmp替换任何jz/jnz

如果你需要足够快速和强大的东西来挑战非专业黑客,请安装加密狗并通过加密狗SDK加密你的可执行文件。其他任何事情都只是浪费时间,更令人讨厌的是,被检测为恶意软件/病毒/特洛伊木马的风险很高。

而这种跨平台的操作则更加无关紧要,因为大多数反调试技术都依赖于操作系统(有时还依赖于CPU型号/版本!!(来工作。

让我们承认,你成功地构建了一个完美的反调试代码,使用加密代码和一切可能的。。。对于软件无法检测到的Lauterbach探测器或其他类似硬件调试器,您将如何处理?这不是每个人的工具,对吧,但我有几个这样的美女在工作,适用于各种CPU。。。我不是唯一一个。

最新更新