开发者

function's return address is different from its supposed value, buffer overflow, HELP PLEASE

Good day everyone!

I am trying to understand how buffer overflow works. Right now, I’m in the process of determining the address of a function’s return address which I’m supposed to change to perform a buffer overflow attack. I’ve written a simple program based from an example I’ve read in the internet. What this program does is it creates an integer pointer to store the address of the function's return address in the stack. To do this, (granted I understand how a function/program variables get organized in the stack), I add 8 to the buffer variable’s address and set it as the value of ret. I’m not doing anything here that would change the address contained in the location of func’s return address.

UPDATE: I've modified the program a bit, so it prints the stack address of func's parameter a. As you can see, the distance between a and buffer is about 8 bytes, so that would probably mean, based from the stack layout, that saved FP and old EIP (func return address) is in between. Am I right?

Here's the program:

void func( int a){
    char buffer[3];

    int *ret;

    ret = buffer + 11; // this is the configuratio which made the whole program works..开发者_JAVA百科. This now points to the address containing func's return address

    printf (" address of a is %d\n", &a);

    printf ("address of buffer is %x\n", buffer);

    printf ("address of ret is %x\n", ret);

    printf ("value of ret is %x\n", (*ret));

}

void main(){
    int num;

    num = 0;

    func(num);

    num = 1;

    printf("Num now is %d", num);
}

Output of the program when gets excecuted:

alt text http://img20.imageshack.us/img20/2034/72783404.png

As you can see, I’m printing the address of the variables buffer and ret. I’ve added an additional statement printing the value of the ret variable (supposed location of func return address, so this should print the address of the next instruction which will get executed after func returns from execution).

Here is the dump which shows the supposed address of the instruction to be executed after func returns. (Underlined in green) As you can see, that value is way different from the value printed contained in the variable ret.

alt text http://img717.imageshack.us/img717/8273/assemblycodecopy.png

My question is, why are they different? (of course in the assumption that what I’ve done are all correct). Else, what have I done wrong? Is my understanding of the program’s runtime stack wrong? Please, help me understand this. My project is due nextweek and I’ve barely touched it yet. I’m sorry if I’m being demanding, I badly need your help.


For the following program

int main(int argc, char **argv) {
   int v[2];

   return 0;
}

The stack layout is basically the following:

 
       -------------   
           arg n 
       ------------- 
         .........
       -------------   
0x1010     arg 0 
       ------------- 
0x100C  ret address
       =============
0x1008     old fp 
       -------------
0x1004     v[1]
       -------------
0x1000     v[0]
       -------------

You can find out main's return address using v + 3.

Assuming the addresses placed on the left side of the stack, v has address 0x1000 , return adress has the address (v + 3 => 0x1000 + 4 * 3 = 0x100C)


First off, notice that the address of buffer is an odd number 0xbffffd51 and then you add 8 to it to get 0xbffffd59. I would be quite surprised if the return address on the stack was not aligned to a four byte address.

Depending on the compiler, exactly how the stack frame is layed out could vary (for example, even though buffer is first in the source code, the compiler could put ret higher in the stack), so you may need to experiment with your values. I would do a couple of things:

  1. Change buffer to be 4 bytes.
  2. Experiment with different offsets. I have a feeling that you may need to look 12 bytes or even 16 bytes up to find your return address.


Of course, you can't modify the original num unless you pass the pointer to it; so in the main, num first is 0, then it is 1, and it is never really modified by the func. Address of a (&a) in func is the address of the local copy (by value) of the argument, likely an address on the stack in most cases. And what would ret point to? You have a 3 char buffer, and you get the address beyond it; you must consider it now a pointer to garbage, even though likely your pointing to something "interesting", according to how local variables are "organized" in memory. So you can't be 100% sure it points to the return address indeed. You're assuming the following:

0  4 bytes (for char, assuming 4bytes alignment)
4  4 bytes (for whatever, maybe argument)
8  4 bytes (return address)

And it depends. It depends on the architecture; it depends on how the compiler "translate" the code of the function. Let us imagine x86. The following is a reasonable way of doing func

func:
  push ebp  ; save some regs...
  push eax  ; or with pusha?
  mov ebp, esp
  push 0   ; for char a[3]
  mov eax, ebp
  add eax, 4  ; -4 + 8
  push eax ; for int *ret
  ; -4(ebp) gives a
  ; -8(ebp) gives int *ret
  ; so ebp-4 is the pointer to a, we
  ; add 8, to obtain ebp+4, which points
  ; to saved ebp... missing the ret ptr
  ; (other code...)
  mov esp, ebp
  pop eax ; or with popa?
  pop ebp
  ret

and what if the saved regs are more? what if the order of char a[4] and int *ret is swapped? How do you can know? You can't assume anything, unless, you write the code yourself directly in asm, in this case you can controll exactly what's happening. Otherwise, a working C code to do what you want would work by chance...

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜