Hi, I wanted to debug a tool under linux but the coder had the beautiful idea to put anti-ptrace, approximately the looks like it : --------------------------8<-cut-here-------------------- [...] int main() { if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) { printf("FUCK OFF !!\n"); return 1; } printf("Ok\n"); return 0; } [...] --------------------------8<-cut-here-------------------- The program tries to debug itself by sending himself a debugging request. If the program is being debugged, the request that the program send to himself will faile, and so that means that there is already a debuging process on the program with ptrace. GDB uses the ptrace function so it's vulnerable to this trick. To debug the tool I will have been able to take others debugger which is not based on ptrace() but I thought that bypassing the protection would be more enriching than acknowledge itself overcome... From where this code : --------------------------8<-cut-here-------------------- /* ptracefucker - lkm ~ by santabug/EOF ptracefucker is a basic lkm which intercepts the ptrace syscall, when it is hooked, ptrace function returns 0 so anti-ptrace systems are fucked up :) So you can debug gdb even if there are anti-ptrace tricks hehe. sorry for my bad english :o santabug@zirkon:~$ sudo insmod ptracefucker.ko pid= NOTE : there are some warns during the compilation but... fuck i'm sick and lazy :), the lkm works that is the most important thing for the moment. mail : santabug@gmail.com site : http://opcodes.free.fr/ http://www.eof-project.net */ #include #include #include #include #include #include #include #include #include #include static unsigned int pid=0; int regpid; static asmlinkage long(*original_ptrace)(long,long,void*,void*); module_param(pid,int,S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); unsigned long **sys_call_table; unsigned long **grab_sys_call_table(void) { unsigned long **systable; unsigned long ptr; extern int loops_per_jiffy; systable = NULL; for (ptr = (unsigned long)&loops_per_jiffy; ptr < (unsigned long)&boot_cpu_data; ptr += sizeof(void *)) { unsigned long *p; p = (unsigned long *)ptr; if (p[__NR_close] == (unsigned long) sys_close) { systable = (unsigned long **)p; return &systable[0]; } } return NULL; } asmlinkage long my_ptrace(long request,long pid,void *addr,void *data) { if(current->pid==regpid && request==PTRACE_TRACEME) { printk("syscall hijacked !\n"); return 0; } else { original_ptrace(request,pid,addr,data); } } int init_module(void) { sys_call_table=grab_sys_call_table(); printk(KERN_INFO "-=[ ptracefucker - by santabug ]=-\n"); printk("sys_call_table located at %p\n",sys_call_table); original_ptrace=*(long(*))(sys_call_table+__NR_ptrace*sizeof(void*)); printk("ptrace located at 0x%X \n",&original_ptrace); *(long(*))(sys_call_table+__NR_ptrace*sizeof(void*))=&my_ptrace; printk("....hooked !\n"); printk("Watching pid=>%u\n",pid); printk("You can now have fun with gdb;p\n"); regpid=pid; } void cleanup_module(void) { *(long(*))(sys_call_table+__NR_ptrace*sizeof(void*))=original_ptrace; printk("Original syscall ptrace restored\n"); printk(KERN_INFO "==== Ptracefucker lkm is now unloaded ====\n"); } --------------------------8<-cut-here-------------------- santabug@zirkon:~/lkms/tests$ sudo insmod lkm.ko pid=1337 santabug@zirkon:~/lkms/tests$ sudo cat /var/log/messages [...] Jan 3 12:22:54 localhost kernel: [4303457.280000] -=[ ptracefucker - by santabug ]=- Jan 3 12:22:54 localhost kernel: [4303457.280000] sys_call_table located at d0a0fa84 Jan 3 12:22:54 localhost kernel: [4303457.280000] ptrace located at 0xD0A0FA90 Jan 3 12:22:54 localhost kernel: [4303457.280000] ....hooked ! Jan 3 12:22:54 localhost kernel: [4303457.280000] Watching pid=>1337 Jan 3 12:22:54 localhost kernel: [4303457.280000] You can now have fun with gdb;p What this lkm do ? It will hijacks ptrace() if the targeted PID corresponds to a detected syscall ptrace (to be precise with the request PTRACE_TRACEME), the function will return 0 and the anti-ptrace trick will be fucked up. However if the syscall does not correspond to the targeted PID ptrace will works normaly for exemple on the pasted output the lkm is watching the process who has as PID "1337", it hooks the syscall ptrace and if a syscall ptrace is detected for this PID , the lkm hijack the syscall as explain more over. Voila. santabug/EOF