anti-anti-ptrace via shared library function overriding in c
i was reading the manpage of ld.so (man 8 ld.so) when i chanced upon the environment variable LD_PRELOAD
LD_PRELOAD
A whitespace-separated list of additional, user-specified, ELF
shared libraries to be loaded before all others. This can be
used to selectively override functions in other shared
libraries. For setuid/setgid ELF binaries, only libraries in
the standard search directories that are also setuid will be
loaded.
wanting to give function overriding a shot, i decided to make a program that has anti-ptrace to see if i can bypass that without resorting to manual patching. a program would call ptrace() with PTRACE_TRACEME request initiating that it wants to be traced. since only one process is allowed this technique works against ptrace() based applications like strace and gdb
#include <stdio.h>
#include <sys/ptrace.h>
int main(t, c)
{
if (ptrace(PTRACE_TRACEME, 0, 1, 0) == -1) {
printf("ptrace protection\n");
return 1;
}
printf("--- normal program procedure here ---\n");
return 0;
}
and when i ran that under gdb (and strace afterwards) i got this
steph@gdb $ file traceme Using host libthread_db library \"/lib/libthread_db.so.1\". steph@gdb $ r ptrace protection Program exited with code 01.so clearly, the anti-ptrace routine was being executed. then i made a custom ptrace() function that i hoped would override libc’s ptrace() like so.
/* fake ptrace() */
#include <stdio .h>
long ptrace(int x, int y, int z)
{
printf("--this is the ptrace clone block--\n");
return 0;
}
then made a shared library out of it.
steph@heaven ~/git/null/c/ptrace $ gcc -shared -fPIC -o fakeptrace fakeptrace.c
and then ran strace with LD_PRELOAD environment set.
steph@heaven ~/git/null/c/ptrace $ strace -E LD_PRELOAD=./fakeptrace ./traceme — snipped — write(1, "–this is the ptrace clone block"…, 35–this is the ptrace clone block–) = 35 write(1, "— normal program procedure her"…, 38— normal program procedure here —) = 38 munmap(0xb7f0f000, 4096) = 0 exit_group(0) = ?
whereas, under the normal circumstance, strace would have given me:
write(1, "ptrace protection\n", 18ptrace protection) = 18 munmap(0xb7f16000, 4096) = 0 exit_group(1)
[ protection ]
i haven’t gotten into the details about how to go about munmap()ing a specific library in memory and do plt-patching inside the program itself. so for now, i just extended the traceme program to detect LD_PRELOAD presence before the actual anti-ptrace. if LD_PRELOAD checks out bad, (that is, there are preloaded libraries) the program quits. i wouldn’t really call this protection because if anyone can defeat ptrace() tracing, what’s to prevent him/her from defeating the LD_PRELOAD detection function too? it’s pointless, but at least it didn’t hurt when i placed it.
char *preloaded;
preloaded = getenv("LD_PRELOAD");
if (preloaded) {
printf("detected pre-reloaded functions: \n");
printf("%s\n", preloaded);
return -1;
}
i’m going nowhere with the whole matter am i?
