1

I have recently started getting into assembly for the purpose of reverse engineering. I started small with understanding basic datatypes, but I want to move on to more complex datatypes and functions. I am trying to understand what is happening in both methods requestMaxPow and computePowers

Here is the source that I use

#include <stdio.h>

int requestMaxPow();
int computerPowers(int);
int main(){
    int max = requestMaxPow();
    computePowers(max);
    return 0;
}

int requestMaxPow(){
    int maxPow;

    scanf ("%d", &maxPow);
    return maxPow;
}

int computePowers(int MaxPow){
    int currentVal = 0;
    int currentPow = 0;

    for(;currentPow < MaxPow; ++currentPow){
        currentVal = currentPow * currentPow;
    }
}
Compiled with GCC with the following arguments "gcc -g -O0 morecomplex.c -o morecoplex"

The assembly below is for the requestMaxPow method, which is the hardest for me to understand. Specifically I don't understand what "gs" means at 0xc5, and I have no idea what is going on between lines 0xce - 0x50. could someone well versed explain line by line what is happening?

(gdb) disassemble 
Dump of assembler code for function requestMaxPow:
   0x080484bf <+0>: push   ebp
   0x080484c0 <+1>: mov    ebp,esp
   0x080484c2 <+3>: sub    esp,0x18
=> 0x080484c5 <+6>: mov    eax,gs:0x14
   0x080484cb <+12>:    mov    DWORD PTR [ebp-0xc],eax
   0x080484ce <+15>:    xor    eax,eax
   0x080484d0 <+17>:    sub    esp,0x8
   0x080484d3 <+20>:    lea    eax,[ebp-0x10]
   0x080484d6 <+23>:    push   eax
   0x080484d7 <+24>:    push   0x80485b0
   0x080484dc <+29>:    call   0x8048380 <__isoc99_scanf@plt>
   0x080484e1 <+34>:    add    esp,0x10
   0x080484e4 <+37>:    mov    eax,DWORD PTR [ebp-0x10]
   0x080484e7 <+40>:    mov    edx,DWORD PTR [ebp-0xc]
   0x080484ea <+43>:    xor    edx,DWORD PTR gs:0x14
   0x080484f1 <+50>:    je     0x80484f8 <requestMaxPow+57>
   0x080484f3 <+52>:    call   0x8048350 <__stack_chk_fail@plt>
   0x080484f8 <+57>:    leave  
   0x080484f9 <+58>:    ret    
End of assembler dump.

The assembly for the computePowers method is much easier to understand. I include it just in case it has relevance to my main question.

(gdb) disassemble 
Dump of assembler code for function computePowers:
   0x080484fa <+0>: push   ebp
   0x080484fb <+1>: mov    ebp,esp
   0x080484fd <+3>: sub    esp,0x10
=> 0x08048500 <+6>: mov    DWORD PTR [ebp-0x4],0x0
   0x08048507 <+13>:    mov    DWORD PTR [ebp-0x8],0x0
   0x0804850e <+20>:    jmp    0x804851e <computePowers+36>
   0x08048510 <+22>:    mov    eax,DWORD PTR [ebp-0x8]
   0x08048513 <+25>:    imul   eax,DWORD PTR [ebp-0x8]
   0x08048517 <+29>:    mov    DWORD PTR [ebp-0x4],eax
   0x0804851a <+32>:    add    DWORD PTR [ebp-0x8],0x1
   0x0804851e <+36>:    mov    eax,DWORD PTR [ebp-0x8]
   0x08048521 <+39>:    cmp    eax,DWORD PTR [ebp+0x8]
   0x08048524 <+42>:    jl     0x8048510 <computePowers+22>
   0x08048526 <+44>:    leave  
   0x08048527 <+45>:    ret    
End of assembler dump.

Edit 1 After looking at the code for a while longer I realized the xor is happening on eax to "0" it out, does that happen so that a return value can be stored into eax?

  • @GuntramBlohm Thank you for that! That makes complete sense. I looked up the Stack Canary on google and saw that it is a defense mechanism in Linux that helps make stack buffer overflows more difficult. At address 0xd7 why is a seemingly random address (0x80485b0) being pushed onto the stack? – Loligans Sep 9 '15 at 13:14
  • That's not a random address, that's the address where the compiler put the "%d" string for scanf. I changed my comment to an answer to have space to explain more. – Guntram Blohm Sep 9 '15 at 13:16
1

The code between 80484c5 and 80484ce sets up the stack canary, and 80484e7 to 80484f3 checks it. gcc omits the stack checking from your second function, since it can determine (uses no pointers, doesn't call subroutines) that there's no way to overwrite the stack here. Your xor eax, eax isn't neccesary per se (you don't need to zero registers before storing something into them), it's just that the compiler wants to make the canary value unknown as soon as possible.

Omitting the stack checking results in:

0x080484d0 <+17>:    sub    esp,0x8            // adjust stack alignment 
0x080484d3 <+20>:    lea    eax,[ebp-0x10]     // move the address of maxRow into eax
0x080484d6 <+23>:    push   eax                // and push it on the stack as the 2nd function argument
0x080484d7 <+24>:    push   0x80485b0          // Push the address of your format string as first function argument
0x080484dc <+29>:    call   0x8048380 <__isoc99_scanf@plt>  // call scanf
0x080484e1 <+34>:    add    esp,0x10           // remove the added bytes from the stack
0x080484e4 <+37>:    mov    eax,DWORD PTR [ebp-0x10]  // get the content of maxRow into eax to return it as function return value

3 things might need further explanation:

  • The lea instruction calculates an address, while mov loads a value. Thus, lea eax,[ebp-0x10] is like eax=&maxRow, and mov eax, DWORD PTR [ebp-0x10] is like eax=maxRow.
  • In C, function arguments are pushed from behind, i.e. the last argument gets pushed first. This ensures the first argument is always at the same position, which is important for varargs functions like printf and scanf.
  • Since 2 arguments are passed, which needs 8 bytes, ommiting the first sub esp,0x8 and replacing the add esp,0x10 with add esp, 0x8 would be more straightforward. The reason gcc spends these extra bytes is probably that it wants the stack pointer aligned to a multiple of 16 bytes, which speeds up certain things. Not sure about this however, since the total distance between esp at the start of your function and esp at the start of scanf doesn't seem to be a multiple of 16.
  • Okay that makes soooo much sense! My last question is how did it know where to find the address of the format string (0x80485b0)? The only thing I can think of is that the format string is a static string. – Loligans Sep 9 '15 at 13:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.