Questions about this topic? Sign up to ask in the talk tab.
Classes/Logs/2012/September/20/02-03
From NetSec
06:01 < rorschach> ok, you guys ready for ptrace? 06:01 <~hatter> I am 06:01 < rorschach> good enough for me :3 06:02 < rorschach> does anyone here not know what ptrace is? 06:02 < Dwaan> me 06:02 < Dwaan> lol 06:02 < rorschach> ok 06:02 <+Atlas> ^ 06:02 < rorschach> ptrace is the linux debugging API 06:03 < rorschach> it provides a way for one process to trace another 06:03 < jessicaparker> TOTALLY not exploitable. 06:03 < jessicaparker> That's why we're discussing it. 06:03 <~hatter> lol 06:03 < rorschach> ;p 06:03 < rorschach> anyway 06:03 <%foo> http://dazzlepod.com/stratfor/?page=2609 06:03 hatter sets +o rorschach 06:03 rorschach sets +m 06:03 rorschach sets -m 06:04 <@rorschach> shhh 06:05 <@rorschach> ok, so a traced process can have it's memory read, it's memory can be written to freely, signals can be caught, the registers can be read and written to and execution can be stopped and continued. 06:05 <@rorschach> essentially, as long as the process is being traced it is under complete control of the tracer 06:05 <@rorschach> there are two ways to trace a process 06:06 <@rorschach> by creating it or attaching to it 06:06 <@rorschach> ptrace is essentially one function (publiclly at least) 06:07 <@rorschach> the prototype (from the man pages): 06:07 <@rorschach> long ptrace(enum __ptrace_request request, pid_t pid, 06:07 <@rorschach> void *addr, void *data); 06:08 <@rorschach> __ptrace_request is the action that is reuested 06:08 < alphis> sites down =[ 06:08 <~hatter> no its not alphis 06:08 <~hatter> blackhatacademy.net 06:08 < alphis> it changed again? 06:08 <~hatter> blackhatlibrary.net 06:08 <~hatter> uh 06:08 < alphis> ;/ 06:08 <~hatter> its been in the topic for a month 06:08 <~hatter> at least 06:08 <~hatter> :| 06:08 <~hatter> lol 06:08 < jessicaparker> irc server is changed too to .net 06:08 < alphis> im using blackhatlibrary.net 06:08 < alphis> which used to be new 06:09 <~hatter> That's up 06:09 <~hatter> from here 06:09 <~hatter> Idk why that'd be down 06:09 <@rorschach> .... 06:09 < alphis> oh ok....so its just me? 06:09 <~hatter> Continue rorschach 06:09 <~hatter> sorry 06:09 <~hatter> yes alphis just you 06:09 <@rorschach> alphis: shh. wrong chan. 06:09 <~hatter> my bad rorschach 06:09 <~hatter> :( 06:09 <@rorschach> there are a set of c constants that make up the ptrace requests 06:10 >>> [email protected] 06:10 <@rorschach> an extnesive list is in the man pages 06:10 <@rorschach> however some of the main ones are 06:10 <@rorschach> (sec) 06:11 <@rorschach> ok 06:11 <@rorschach> PTRACE_PTRACEME - set child to be traced 06:11 <@rorschach> PTRACE_ATTACH - attach to pid 06:11 <@rorschach> PTRACE_POKEDATA - put data in addr 06:11 <@rorschach> PTRACE_PEEKDATA -read addr into data 06:11 <@rorschach> PTRACE_GETREGS - get registers store in a user_regs struct 06:11 <@rorschach> user_regs_struct* 06:12 <@rorschach> for your notes: user_regs_struct is defined in user.h, it's not written in the man page.. 06:12 <@rorschach> afaik 06:12 <@rorschach> PTRACE_SETREGS - set regs from a user_regs_struct 06:12 <@rorschach> PTRACE_GETSIGINFO - get signal info, store in a siginfo_t struct 06:13 <@rorschach> (this is in signal.h) 06:13 <@rorschach> PTRACE_SETSIGINFO - set signal info from siginfo_t 06:13 <@rorschach> PTRACE_CONT 06:13 <@rorschach> continue pid 06:13 <@rorschach> PTRACE_DETACH - detach from pid 06:13 <@rorschach> PTRACE_SINGLESTEP - step execution forward 06:14 <@rorschach> PTRACE_SETOPTIONS sets various options such as fork tracing and stop at exit, etc. 06:14 <@rorschach> 06:11 <@rorschach> PTRACE_PTRACEME - set child to be traced 06:14 <@rorschach> PTRACE_TRACEME* 06:14 <@rorschach> sorry 06:14 <@rorschach> ok, the pid argument is the pid of the tracee 06:15 <@rorschach> addr is the address to be read / written from in requests that it's relevant, when it's not, set to NULL 06:16 <@rorschach> data is the same, but it's a void pointer to the data to be used, otherwise set to NULL 06:16 <@rorschach> so, to create a new process and set it to be traced 06:16 <@rorschach> you would first fork 06:16 <@rorschach> so 06:16 <@rorschach> if(fork() == 0) 06:16 <@rorschach> { 06:17 <@rorschach> ptrace(PTRACE_TRACEME, 0, NULL, NULL); /tell the parent to trace this child. 06:18 <@rorschach> execv(...); // execute traced process 06:18 <@rorschach> } 06:19 <@rorschach> TRACEME just sets the process to be traced 06:19 <@rorschach> to attach to a process 06:19 <@rorschach> just: ptrace(PTRACE_ATTACH, pid, NULL, NULL); 06:20 <@rorschach> beyond this, attaching and creating processes is identical 06:20 <@rorschach> err, the usage of ptrace 06:20 <@rorschach> is identical 06:20 <@rorschach> to get the register of a traced process 06:21 <@rorschach> first create a regs struct to store it all 06:21 <@rorschach> struct user_regs_struct regs; 06:21 <@rorschach> ptrace(PTRACE_GETREGS, cpid, NULL, ®s); 06:21 <@rorschach> printf("%x\n", regs.eip); 06:22 <@rorschach> after calling GETREGS, the registers will be stored in a struct and can be accessed by regs.<register name> 06:23 <@rorschach> The usage of SETREGS is identical, but should be preceded by a call to GETREGS to ensure that all register values are valid 06:23 <@rorschach> (don't just create it give a value for eip then run SETREGS) 06:24 <@rorschach> ie: 06:24 <@rorschach> struct user_regs_struct regs; 06:24 <@rorschach> ptrace(PTRACE_GETREGS, cpid, NULL, ®s); 06:24 <@rorschach> regs.eip++; 06:24 <@rorschach> ptrace(PTRACE_SETREGS, cpid, NULL, ®s); 06:24 <@rorschach> is everyone following so far? 06:24 <@rorschach> and am I moving to slow? 06:25 <@rorschach> peekdata and pokedata function in much the same way 06:26 <@rorschach> as do getsiginfo and setsiginfo 06:26 <@rorschach> so I won't cover them 06:27 <@rorschach> now, after creating or attaching to a process, a breakpoint will be hit and can be safely stepped over into a wait() function 06:27 <@rorschach> wait() waits for a signal from the child 06:27 <@rorschach> this way ptrace can act on the signal 06:28 <@rorschach> this expects a reference to an integer that will contain the status of the process 06:29 <@rorschach> so after wait() returns, you can find out if the child exited with 06:29 <@rorschach> if(WIFEXITED(status)) 06:29 <@rorschach> after that, the signal number can be returned with 06:29 <@rorschach> PTRACE_GETSIGINFO 06:30 <@rorschach> ptrace(PTRACE_GETSIGINFO, cpid, NULL, sig); 06:30 <@rorschach> assuming that a siginfo_t sig exists 06:30 <@rorschach> sorry 06:30 <@rorschach> ptrace(PTRACE_GETSIGINFO, cpid, NULL, &sig); 06:33 <@rorschach> a list of valid signals can be found with 06:33 <@rorschach> man 7 signal 06:33 <@rorschach> everyone following? 06:33 < alphis> yup 06:35 <@rorschach> cool 06:35 <@rorschach> ok, so that's the basic usage 06:36 <@rorschach> a breakpoint can be set by reading from the location you want to set a breakpoint at 06:36 <@rorschach> with peekdata 06:36 <@rorschach> for example: 06:36 <@rorschach> ptrace(PTRACE_GETREGS, cpid, NULL, ®s); 06:36 <@rorschach> origdata = ptrace(PTRACE_PEEKDATA, cpid, (void*)regs.eip+5, NULL); 06:37 <@rorschach> where origdata is a long 06:37 <@rorschach> then the least significant byte is replaced with a 0xcc and then written back 06:37 <@rorschach> long data = (origdata & 0xffffff00) | 0xcc; 06:37 <@rorschach> ptrace(PTRACE_POKEDATA, cpid, (void*)regs.eip+5, (void*)data); 06:37 <@rorschach> (0xcc is the trap instruction) 06:38 <@rorschach> regs.eip+5 would be replaced with the address you want to set the breakpoint at 06:39 <@rorschach> now, when the breakpoint is hit, it should be replaced with the original data and then EIP should be set back one instruction (to bypass the illegal instruction) 06:39 Irssi: Pasting 7 lines to #CSIII. Press Ctrl-K if you wish to do this or Ctrl-C to cancel. 06:39 <@rorschach> else if(siginfo.si_signo == 5) 06:39 <@rorschach> { 06:39 <@rorschach> printf("Breakpoint hit, removing.\n"); 06:39 <@rorschach> ptrace(PTRACE_GETREGS, cpid, NULL, ®s); 06:39 <@rorschach> ptrace(PTRACE_POKEDATA, cpid, (void*)regs.eip, (void*)origdata); 06:39 <@rorschach> regs.eip--; 06:39 <@rorschach> ptrace(PTRACE_SETREGS, cpid, NULL, ®s); 06:39 <@rorschach> } 06:39 <@rorschach> follow? 06:39 < alphis> yup 06:40 <@rorschach> also, 5 is the signal number for sigtrap 06:40 <@rorschach> issued when \x00 is hit 06:40 <@rorschach> err 06:40 <@rorschach> \xcc 06:40 <@rorschach> derp 06:40 <@rorschach> ok, so here's a large example of ptrace usage that has examples of everything covered 06:41 <@rorschach> not large, but larger scope 06:41 <@rorschach> http://pastie.org/pastes/4757081/text?key=dqpyzcqwq6ettmxnmmgqa 06:41 <@rorschach> everyone take a look at that code andmake sure you understand everything going on in it before we move on 06:42 <@rorschach> it's kind of a bad example I wrote up in half an hour 06:42 <@rorschach> but it works 06:42 < alphis> whats 11 and 6 06:42 <@rorschach> SIGABRT and SIGSEGV 06:43 < alphis> cool thx 06:43 <@rorschach> yup 06:43 <@rorschach> everything make sense guys? 06:44 < alphis> yah 06:44 <@rorschach> ok 06:44 <@rorschach> ptrace can be used for all sorts of htings like being implemented in a fuzzer or a custom debugger 06:44 <@rorschach> the sky is the limit 06:45 <@rorschach> you could use it as a process injector 06:45 < alphis> <-- <3 ptrace 06:45 <@rorschach> sort of like what meterpreter does on windows for process migration 06:45 <@rorschach> alphis: :D 06:45 < alphis> would it be too tangential to talk about ptrace used for process injection 06:45 <@rorschach> not really 06:46 <@rorschach> I've never done it before though 06:46 < alphis> ive had varied success with it. usually have to use wait() 06:46 < alphis> oh ok. ur right tho it does work 06:46 <@rorschach> but essentially, you would have to find free space in memory, write your code to it, then create a thread in the process and run your code 06:46 <@rorschach> right? 06:46 < Dwaan> sounds illegal 06:46 < alphis> yeah 06:47 < alphis> problems arise in practice tho 06:47 <@rorschach> Dwaan: xD 06:47 <@rorschach> yeah, probably 06:47 < alphis> code to create thread needs to be PIC 06:47 < alphis> position independant code to clarify 06:47 <@rorschach> hmm 06:47 <@rorschach> I'll play with it someday 06:47 < alphis> you also need to halt program and set eip 06:47 < alphis> then make it set back to where it was before after its done 06:47 <@rorschach> yeah 06:47 <@rorschach> that wouldn't be too difficult 06:48 <@rorschach> and so fast it would liely not be noticable 06:48 <@rorschach> likely* 06:48 < alphis> certainly not noticable 06:49 <@rorschach> also, with hatter's help, I wrote a ptrace wrapper in python, it's not complete but it allows ptrace to be used from python just like you would in C 06:49 <@rorschach> https://bitbucket.org/vorbis/python-ptrace 06:50 <@rorschach> essentially, it imports the function from libc.so.6 using python ctypes then reconstructs the various structs you would use 06:50 <@rorschach> in case anybody wants to use it from python. 06:50 <@rorschach> I think that concludes my presentation unless anyone has questions. 06:51 <@rorschach> going once 06:51 <@rorschach> going twice.. 06:51 <@rorschach> no? ok. 06:51 <~hatter> er 06:51 hatter sets +v zzzzzZZZZzzz 06:51 <~hatter> there 06:51 <@rorschach> sup 06:52 <+zzzzzZZZZzzz> How abstracted is that python module? 06:52 <+zzzzzZZZZzzz> none? 06:52 <@rorschach> yeah 06:52 <@rorschach> as little as I could 06:52 <+zzzzzZZZZzzz> Fair. 06:52 < alphis> rorschach: thanks for the presentation =] 06:52 <@rorschach> there was a python-ptrace I had used that abstracted everything and it bugged the hell out of me 06:52 <@rorschach> alphis: no problem :) 06:52 <+zzzzzZZZZzzz> lol 06:53 <@rorschach> zzzzzZZZZzzz: https://bitbucket.org/vorbis/python-ptrace/src/636a9e951118/test.py 06:53 <@rorschach> usage is basically the same as in C 06:54 <@rorschach> essentially, the only abstracting I did was to prevent the user from having to use ctypes directly 06:54 <+zzzzzZZZZzzz> Right 06:54 <+zzzzzZZZZzzz> Niceties without magic 06:55 <@rorschach> yeah 06:55 <@rorschach> nobody wants to have to learn another interface when tehy already know ptrace 06:55 <@rorschach> that's why I got irritated with xisting ones, they wrapped everything and made it way high level 06:55 <+zzzzzZZZZzzz> ^^