【发布时间】:2016-02-12 06:44:22
【问题描述】:
我正在尝试在 Linux 上检测是否有调试器附加到我的二进制文件。我找到了两种解决方案。一个更简单的:
#include <stdio.h>
#include <sys/ptrace.h>
int main()
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1)
{
printf("don't trace me !!\n");
return 1;
}
// normal execution
return 0;
}
还有一个:
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
int spc_detect_ptrace(void) {
int status, waitrc;
pid_t child, parent;
parent = getpid();
if (!(child = fork())) {
/* this is the child process */
if (ptrace(PT_ATTACH, parent, 0, 0)) exit(1);
do {
waitrc = waitpid(parent, &status, 0);
} while (waitrc == -1 && errno == EINTR);
ptrace(PT_DETACH, parent, (caddr_t)1, SIGCONT);
exit(0);
}
if (child == -1) return -1;
do {
waitrc = waitpid(child, &status, 0);
} while (waitrc == -1 && errno == EINTR);
return WEXITSTATUS(status);
}
第二种方法比第一种更简单的方法更好吗?如果是,为什么?
【问题讨论】:
-
在任一示例中,是什么阻止我在检查通过后附加调试器?此外,并非所有调试器都必须使用
ptrace,因此这可能不是确定是否有人在调试您的程序的最可靠方法。 -
@tonysdg,上面的代码可以多次调用。您知道如何更好地检查吗?
-
说实话?不,不幸的是。我确实知道一个活跃的研究领域正在测试程序是否可以确定它们是否在虚拟机中(这有时是可取的,有时不是) - 我怀疑同样类型的问题也适用于此。不过,这里的目标是阻止逆向工程的尝试吗?如果是这样,可能有更好的方法来保护自己——我不确定这些是什么,但社区中的某个人可能会这样做。无论如何-不幸的是,我对这个问题没有更多帮助(很可能):(
-
第一种方法只检查一次,因此您可能需要多次调用它,而第二种方法保留附件,因此其他人无法[直接]附加到您的进程(因为它只能是一个)。当然有一些方法可以绕过它,例如在最坏的情况下修补内核,并且可以直接访问进程内存 - 可能根本不需要可附加的调试器。
-
@keltar,你确定第二个保留附件吗?声明
ptrace(PT_DETACH, parent, (caddr_t)1, SIGCONT);不分离吗?