Search code examples
linuxsignalsptrace

SIG_IGN does not work with PTRACE_TRACEME?


I'm testing an antidebug solution with ptrace method

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;
}

When I execute it, I'm always getting a stopped error,

# ./a.out
not being traced

[4]+  Stopped                 ./a.out

Then I tried to add the SIGSTOP handler like this

int main(int argc, char **argv) {
    signal(SIGSTOP, SIG_IGN);

And it's still getting a stopped error, any ideas?


Solution

  • Here's what's happening:

    • handle = dlopen ("libc.so", RTLD_LAZY) assigns NULL to handle. Dlopen fails because on your GNU/Linux distro (and most other modern distros) lib.so isn't a shared library - it's a GNU ld script.
      dlopen ("libc.so.6", RTLD_LAZY) would have succeeded.

    • go = dlsym(handle, "ptrace") succeeds(!). With glibc, it's OK to pass a NULL pointer as the handle argument to dlsym because glibc happens to use ((void *) 0) as RTLD_DEFAULT.
      This generally won't work on other systems. FreeBSD's dlsym uses ((void *) -2) as RTLD_DEFAULT, and if you call dlsym with a NULL handle, it will look for the symbol within the executable or shared library that called dlsym.

    • go(PTRACE_TRACEME, 0) succeeds.

    • dlclose(handle) can't tolerate a NULL handle, and it causes a segfault, so the SIGSEGV signal is raised.

    • since the process is being traced, receiving a signal results in it being stopped (suspended). Typing jobs to your shell will show the signal that made the process stop.


    The code

    signal(SIGSTOP, SIG_IGN);
    

    won't really do anything. SIGSTOP is one of the signals that cannot be caught, ignored, or held.