在我的 BA 论文中,我想展示一个适用于 Windows 的程序,使用各种反调试技术。
其中一个是我自己提出的(可能是众所周知的,但我没有在任何地方找到它)涉及通过使用信号处理程序来改变控制流。据我所知,当程序接收到某个信号并注册了一个函数来处理它时,主线程暂停并将执行传递给处理程序。例如,从函数返回后,主线程可以继续执行,或者甚至在传递SIGFPE
或 的情况下终止SIGSEGV
(请参阅此问题)。
但是,在这种情况下,可能会导致线程执行处理程序离开处理程序范围后没有停止。我之前提到的反调试技术利用了这一事实,并在下面介绍。
首先,我知道我将要展示的代码使用的概念不应该出现在实际程序中,应该在几乎所有情况下都应该避免并且永远不要在家里尝试:)。建立这个之后,考虑下面的程序:(我使用 GCC 目标 minGW 来编译它)
#include <csignal>
#include <windows.h>
#include <cstdio>
void handler(int)
{
asm("jmp continue"); // do not return from this function; just jump to another place in the code
}
int main()
{
signal(SIGFPE, handler); // I know that sigaction should be used instead, but it's simpler and, as far as I know it wouldn't work for Windows
// and I know, that after receiving second signal, there will be undefined behaviour, but let's assume it won't happen
int a = 1 / 0; // cause SIGFPE to happen
asm("continue:");
printf("continue execution\n");
Sleep(5000); // to show a printed message for a while, so that the console is not being closed immediately
ExitProcess(0);
}
所以我的问题来了:如何调试这样的程序,以便可以看到 printf("continue execution\n");
正在执行的行?
当我尝试使用 Code::Blocks 调试器 (GDB) 执行此操作时,仅SIGFPE
出现程序接收到的信息并且程序在不打印"continue execution"
字符串的情况下被粉碎。
另一方面,当我尝试在OllyDbg
.
在“正常”执行时,它会按预期打印字符串结束。
编辑:
我也尝试将异常传递给应用程序(使用SHIFT
+ F7
),但我只收到消息说“调试的程序无法处理异常”并且我无法继续执行。
Edit2:我不会上传二进制文件,因为当我尝试下载它时,我的防病毒软件开始抱怨它,所以如果其他人下载它,它可能会被标记为可疑。