You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何SIG_IGN对PTRACE_TRACEME无效?反调试程序持续停止

解决基于ptrace TRACEME的反调试程序停止问题

这个问题的核心是你没理解PTRACE_TRACEME的底层行为——当进程调用PTRACE_TRACEME成功后,它会自动给自己发送一个SIGSTOP信号,进入停止状态等待调试器附着。如果没有调试器处理这个停止状态,进程就会一直停在那里,这就是你看到[4]+ Stopped ./a.out的原因。

直接忽略SIGSTOP是没用的,因为ptrace会优先拦截这个信号,进程根本没机会触发你的信号处理函数。下面是具体的解决思路和修改后的代码:

关键解决步骤

  • 在调用PTRACE_TRACEME成功后,必须主动让进程恢复运行,用ptrace(PTRACE_CONT, 0, NULL, NULL)命令告诉ptrace继续执行当前进程。
  • 补充完善错误处理逻辑,比如动态库加载失败、ptrace调用失败等场景,避免隐性问题。

修改后的完整代码

#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>

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

    // 加载libc库,注意不同系统可能用libc.so.6而非libc.so
    handle = dlopen("libc.so.6", RTLD_LAZY);
    if (!handle) {
        fprintf(stderr, "dlopen failed: %s\n", dlerror());
        exit(1);
    }

    // 动态获取ptrace函数指针
    go = dlsym(handle, "ptrace");
    if (!go) {
        fprintf(stderr, "dlsym failed: %s\n", dlerror());
        dlclose(handle);
        exit(1);
    }

    // 尝试设置TRACEME,失败则说明已被跟踪
    if (go(PTRACE_TRACEME, 0, NULL, NULL) < 0) {
        puts("being traced");
        dlclose(handle);
        exit(1);
    }

    // 关键:让进程从SIGSTOP状态恢复运行
    if (go(PTRACE_CONT, 0, NULL, NULL) < 0) {
        fprintf(stderr, "ptrace CONT failed\n");
        dlclose(handle);
        exit(1);
    }

    puts("not being traced");

    // 清理资源
    dlclose(handle);
    return 0;
}

编译与运行

编译时需要链接动态加载库:

gcc -o a.out your_code.c -ldl

运行后就不会再出现停止问题:

./a.out
not being traced

额外说明

  • 为什么忽略SIGSTOP无效?因为进程设置PTRACE_TRACEME后,信号处理会被ptrace接管,SIGSTOP会直接让进程进入停止状态,不会触发你注册的SIG_IGN处理逻辑。
  • 关于libc路径:如果dlopen("libc.so.6")失败,可以用ldd /bin/ls查看系统实际的libc动态库路径。

内容的提问来源于stack exchange,提问作者daisy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:59:54