Reputation: 23489
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?
Upvotes: 0
Views: 226
Reputation: 10251
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.
Upvotes: 3