我正在用ptrace方法测试一种抗ebug溶液

int main(int argc, char **argv) {
    void *handle;
    long (*go)(enum __ptrace_request request, pid_t pid);

    // get a handle to the library that contains 'ptrace'
    handle = dlopen ("libc.so", RTLD_LAZY);

    // reference to the dynamically-resolved function 'ptrace'
    go = dlsym(handle, "ptrace");

    if (go(PTRACE_TRACEME, 0) < 0) {
        puts("being traced");
        exit(1);
    }

    puts("not being traced");

    // cleanup
    dlclose(handle);

    return 0;
}

当我执行它的时候,我总是得到一个停止的错误,
# ./a.out
not being traced

[4]+  Stopped                 ./a.out

然后我尝试像这样添加sigstop处理程序
int main(int argc, char **argv) {
    signal(SIGSTOP, SIG_IGN);

但它仍然有一个停止的错误,有什么想法吗?

最佳答案

下面是发生的事情:
handle = dlopen ("libc.so", RTLD_LAZY)将空值赋给handle。dlopen失败,因为在gnu/linux发行版(和大多数其他现代发行版)上,lib.so不是共享库,而是gnu ld脚本。
dlopen ("libc.so.6", RTLD_LAZY)会成功的。
go = dlsym(handle, "ptrace")成功(!)。对于glibc,可以将空指针作为句柄参数传递给dlsym,因为glibc碰巧使用((void *) 0)作为RTLD_DEFAULT
这在其他系统上通常不起作用。freebsd的dlsym使用((void *) -2)作为RTLD_DEFAULT,如果使用空句柄调用dlsym,它将在可执行或共享库中查找名为dlsym的符号。
go(PTRACE_TRACEME, 0)成功。
dlclose(handle)不能容忍空句柄,它会导致segfault,因此会发出SIGSEGV信号。
由于正在跟踪进程,因此接收信号会导致进程停止(挂起)。在shell中键入jobs将显示使进程停止的信号。
守则

signal(SIGSTOP, SIG_IGN);

什么都不会做。SIGSTOP是无法捕获、忽略或保持的信号之一。

10-08 19:40