
Originally Posted by
marc_kriss
thanks sebas_phoenix. I am trying to break down code for a BOF program in C:-
#include<stdio.h>
void display()
{
char buff[8];
gets(buff);
puts(buff);
}
main()
{
display();
return(0);
}
### And the disassembled code for main:-
Dump of assembler code for function main:
0x080484ae <+0>: push %ebp
0x080484af <+1>: mov %esp,%ebp
0x080484b1 <+3>: call 0x8048474 <display>
0x080484b6 <+8>: mov $0x0,%eax
0x080484bb <+13>: pop %ebp
0x080484bc <+14>: ret
End of assembler dump.
### Disassembled code for display:-
Dump of assembler code for function display:
0x08048474 <+0>: push %ebp
0x08048475 <+1>: mov %esp,%ebp
0x08048477 <+3>: sub $0x10,%esp
0x0804847a <+6>: mov %gs:0x14,%eax
0x08048480 <+12>: mov %eax,-0x4(%ebp)
0x08048483 <+15>: xor %eax,%eax
0x08048485 <+17>: lea -0xc(%ebp),%eax
0x08048488 <+20>: mov %eax,(%esp)
0x0804848b <+23>: call 0x8048374 <gets@plt>
0x08048490 <+28>: lea -0xc(%ebp),%eax
0x08048493 <+31>: mov %eax,(%esp)
0x08048496 <+34>: call 0x80483a4 <puts@plt>
0x0804849b <+39>: mov -0x4(%ebp),%eax
0x0804849e <+42>: xor %gs:0x14,%eax
0x080484a5 <+49>: je 0x80484ac <display+56>
0x080484a7 <+51>: call 0x8048394 <__stack_chk_fail@plt>
0x080484ac <+56>: leave
0x080484ad <+57>: ret
End of assembler dump.
There are no issues in understanding BOF. Basically I am trying to figure out, exactly whats going on in assembly code. How the stack values are getting shifted to where. Perhaps almost done. Just some hickups remaining.
Ok lets do it one step at a time for more clarity.
Code:
0x080484ae <+0>: push %ebp
0x080484af <+1>: mov %esp,%ebp
Typical function prologue. esp is not subtracted indicating no local variables are involved(useful when you don't have the source not now).
Code:
0x080484b6 <+8>: mov $0x0,%eax
0x080484bb <+13>: pop %ebp
0x080484bc <+14>: ret
Typical function epilogue..returns 0x0 (always eax holds the return value). Now let's look at the disassembly of display()
Code:
0x08048474 <+0>: push %ebp
0x08048475 <+1>: mov %esp,%ebp
0x08048477 <+3>: sub $0x10,%esp
Again standard prologue of a function except that local variables are involved. Compiler allocates 0x10(16) bytes of memory for the local variables. Now there is something that you should note here, the 16 bytes may/may not be completely used by the local variables. Compiler can use some padding bytes to align dwords @ addresses that are multiples of 4 (I am assuming a 32-bit machine) for optimized access. Short story, dont take the 0x10 as the size of the local vars.
Code:
0x0804847a <+6>: mov %gs:0x14,%eax
0x08048480 <+12>: mov %eax,-0x4(%ebp)
gs is a segment register @ offset 0x14 you can find a global cookie value. Read about GS cookies, basically they prevent buffer overflows. How they work is that, they are inserted between the local variables and the saved frame pointer at the function prologue with a unique value that cannot be guessed by the attacker(hopefully!). Incase of a buffer overflow, the cookie value gets overwritten. The value of the cookie is check @ the function epilogue and if it is corrupted, the application crashes by calling
this code.
Code:
0x080484a7 <+51>: call 0x8048394 <__stack_chk_fail@plt>
This is where the check happens at the function epilogue
Code:
0x0804849b <+39>: mov -0x4(%ebp),%eax
0x0804849e <+42>: xor %gs:0x14,%eax
0x080484a5 <+49>: je 0x80484ac <display+56>
what this does is that it compares the stack cookie in our stack frame with the one that is stored in gs:0x14 and xor's them. Note that A (xor) A is 0. So if they both are the same, then the program proceeds as usual. Else it crashes.
I am assuming you are using a version of gcc that has stack protector enabled. To disable it , compile using -fno-stack-protector flag.
Hope that helps. Best Regards. I hope you got the buffer overflow part.
~peace