3
votes

I'm researching buffer overflows (on IA32 architecture) and I would like to clarify one particular thing with this example program:

int main(int argc, char **argv) {
  char array[512];
  if(argc > 1)
    strcpy(array, argv[1]);
}

I followed the ebp,esp register change during execution of the assembly code: Dump of assembler code for function main:

   0x080483c4 <+0>:     push   ebp
   0x080483c5 <+1>:     mov    ebp,esp
   0x080483c7 <+3>:     sub    esp,0x208
   0x080483cd <+9>:     cmp    DWORD PTR [ebp+0x8],0x1
   0x080483d1 <+13>:    jle    0x80483ed <main+41>
   0x080483d3 <+15>:    mov    eax,DWORD PTR [ebp+0xc]
   0x080483d6 <+18>:    add    eax,0x4
   0x080483d9 <+21>:    mov    eax,DWORD PTR [eax]
   0x080483db <+23>:    mov    DWORD PTR [esp+0x4],eax
   0x080483df <+27>:    lea    eax,[ebp-0x200]
   0x080483e5 <+33>:    mov    DWORD PTR [esp],eax
   0x080483e8 <+36>:    call   0x80482f4 <strcpy@plt>
   0x080483ed <+41>:    leave
   0x080483ee <+42>:    ret

The esp,ebp register values were:

program start
  esp: 0xbffff24c
  ebp: 0xbffff2c8

push ebp
  esp: 0xbffff248
  ebp: 0xbffff2c8

mov ebp,esp
  esp: 0xbffff248
  ebp: 0xbffff248

sub esp,0x208
  esp: 0xbffff040
  ebp: 0xbffff248

strcpy call (ebp is overwritten)
  esp: 0xbffff250
  ebp: 0x41414141

when I inputed 520 characters 'a', which resulted in EBP, EIP being overflown. And the memory looks like this:

Lower Memory Addresses
0xbffff070:     0xbffff078      0xbffff492      0xaaaaaaaa      0xaaaaaaaa
0xbffff080:     0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa
0xbffff090:     0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa
0xbffff0a0:     0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa
0xbffff0b0:     0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa
...
0xbffff270:     0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa      0xaaaaaaaa
Higher Memory Addresses

The thing that interests me is: Why do buffer start at address 0xbffff078, if the ESP points at address 0xbffff040 (when the place for local variable - buffer - is reserved on the stack). The buffer should have been saved at 0xbffff040 address. Can anybody explain why it is not?

1
How did your 'a' characters get turned into 0xaaaaaaaa? Are you showing us the whole program?Carl Norum
Are you sure the address of array was 0xbffff078, not 0xbffff048? Maybe the postlude of strcpy attempted to do some stack things which overwrote the 8 bytes at 0xbffff070?aschepler
Is the memory dump from the same invocation of the program as the register trace?aaz
Hi, I think I solved it: aaz your answer helped me. Of course what am I thinking, the answer was so obvious. The outputs are not from the same invocation of the program: one is from the gdb run, and the other is directly from bash, so of course it wasn't the same, since gdb uses more space on the stack, so it's addresses for local variables were lower on from the bash invocation. I would mark as: problem solved. Thankseleanor

1 Answers

5
votes

The compiler decided to allocate space for both the local variable and the parameters passed to strcpy() on the stack at the same time.

sub    esp,0x208                # 0x200 for array, 8 for 2 pointers
...
mov    DWORD PTR [esp+0x4],eax  # argv[1], not push
mov    DWORD PTR [esp],eax      # array

So the array is actually at esp+8 (or ebp-0x200, as the compiler refers to it).

Edit:
esp is different between invocations of the program, especially depending on the number of arguments. 0xbffff040 or 0xbffff070.

The buffer is at 0xbffff048, not 0xbffff040. Or at 0xbffff078, not 0xbffff070. Ask the debugger where it is to check.

In the memory dump the buffer has 0xaa (I guess this is uninitialized memory before the call). In front of this you can see the two pointers that are passed to strcpy().