Search code examples
cassemblyx86

Explanation needed for this assembler code


This is the c code:

void test_function(int a, int b, int c, int d) 
{
int flag;
char buffer[10];
flag = 31337;
buffer[0] = 'A';
}
int main() 
{
test_function(1, 2, 3, 4);
}

Assembly of test_function:

Dump of assembler code for function test_function:
0x08048344 <test_function+0>: push ebp
0x08048345 <test_function+1>: mov ebp,esp
0x08048347 <test_function+3>: sub esp,0x28
0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69
0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41
0x08048355 <test_function+17>: leave
0x08048356 <test_function+18>: ret

End of assembler dump.
(gdb) print $ebp-12
$1 = (void *) 0xbffff7dc
(gdb) print $ebp-40
$2 = (void *) 0xbffff7c0
(gdb) x/16xw $esp
0xbffff7c0: (1)0x00000000 0x08049548 0xbffff7d8 0x08048249
0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9
0xbffff7e0: 0xb7fd6ff4 (2)0xbffff89c (3)0xbffff808 (4)0x0804838b
0xbffff7f0: (5)0x00000001 0x00000002 0x00000003 0x00000004

I'm new to these topics; therefore, some questions exist in my head.

  1. I suppose first 3 lines of the assembler code is prologue. It pushes ebp, then copies esp to ebt. However, I didn't understand why esp goes back 40 bytes in memory.
  2. It puts 31337 into ebp-12,but why is it exactly ebp-12 and does it represent the flag's memory? It seems it does not since at the bottom, (2) is designated as flag's memory.
  3. Below "x/16xw $esp", what are the other memories not including any (number) on the left since the memories with numbers represents local variables, parameters,and sfp?

Solution

  • You problem

    It pushes ebp, then copies esp to ebt
    

    ebt is wrong, there is no register that called ebt. It is should be ebp.

    push ebp
    

    the command is for preserve the stack bottom before calling the test_function function.

    mov ebp,esp
    sub esp,0x28
    

    the command is for increase the stack to allocate a new block of memory for storing values during the execution of test_function function. And the size of the stack increase is not fixed and will not always be 0x28. This value is calculated by the compiler, which ensures that the size is suitable.

    mov DWORD PTR [ebp-12],0x7a69
    

    corresponds to flag = 31337,flag address is equal to ebp-12's value. The address is assigned by the compiler. DWORD corresponds to int.The hexadecimal number 0x7a69 is equivalent to the decimal number 31337.

    And

    mov BYTE PTR [ebp-40],0x41
    

    the same as. The hexadecimal number 0x41 is equivalent to the decimal number 65. The decimal value of the ASCII code for the letter A is the decimal number 65. BYTE corresponds to char.

    Below code

    (gdb) x/16xw $esp
    0xbffff7c0: (1)0x00000000 0x08049548 0xbffff7d8 0x08048249
    0xbffff7d0: 0xb7f9f729 0xb7fd6ff4 0xbffff808 0x080483b9
    0xbffff7e0: 0xb7fd6ff4 (2)0xbffff89c (3)0xbffff808 (4)0x0804838b
    0xbffff7f0: (5)0x00000001 0x00000002 0x00000003 0x00000004
    

    Such as 0xbffff7c0: of left code is address,it' value is 0x00000000. So 0xbffff7c4(0xbffff7c4 = 0xbffff7c0 + 4) address's value is 0x08049548, because 0x00000000 occupies 4 bytes. 0xbffff7c8 address's value is 0xbffff7d8. ....

    I think below assembler code

    Dump of assembler code for function test_function:
    0x08048344 <test_function+0>: push ebp
    0x08048345 <test_function+1>: mov ebp,esp
    0x08048347 <test_function+3>: sub esp,0x28
    0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69
    0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41
    0x08048355 <test_function+17>: leave
    0x08048356 <test_function+18>: ret
    

    can convert below code(as @Peter Cordes point that "leave" is equal to "mov esp,ebp" + "pop ebp" see at https://www.felixcloutier.com/x86/leave)

    Dump of assembler code for function test_function:
    0x08048344 <test_function+0>: push ebp
    0x08048345 <test_function+1>: mov ebp,esp
    0x08048347 <test_function+3>: sub esp,0x28
    0x0804834a <test_function+6>: mov DWORD PTR [ebp-12],0x7a69
    0x08048351 <test_function+13>: mov BYTE PTR [ebp-40],0x41
                                   mov esp,ebp   // here changed
                                   pop ebp       // here changed
    0x08048356 <test_function+18>: ret
    

    Local variables are stored in the stack.

    So we can get a picture see below:

    enter image description here