2

我试图玩缓冲区溢出。我不明白 eip 的值是怎么回事。

这是C代码:

void copy(char *arg) {
  char msg[256];
  strcpy(msg,arg);
}

它的组装:

0x804847d <copy+25>:    call   0x8048368 <strcpy@plt>
0x8048482 <copy+30>:    leave  
0x8048483 <copy+31>:    ret    

我输入一个像“ _ \xAA\xBB\xCC\xDD”这样的字符串作为参数,计算出的大小使得最后4个字节将是$ebp之后的4个字节(为了覆盖真正的返回地址)。它似乎有效。

在 gdb 中:

(break before strcpy)
x/2wx $ebp
0xbffffb38: 0xbffffb58  0x080484d2
n
(just after strcpy execution)
x/2wx $ebp
0xbffffb38: 0x80cdd189  0x080484b6
...
n
...
x/2wx $ebp
0xbffffb38: 0x80cdd189  0x080484b6

所以返回地址是0x080484d2,在我溢出之后它是0x080484b6,这就是我想要的。但程序退出:“无法访问地址 0x80cdd18d 的内存”。

我不知道为什么 $eip 没有设置为我的地址,并且由于 0x08048 中的代码地址...我非常有信心 $ebp+4 是包含返回地址的地方

I tried again with a string 4 bytes smaller and this time it overwrote $ebp and not $ebp+4 and after the return the $eip was set to the value contained in $ebp+4

Any explanations ?

4

2 回答 2

1

Ok, so thanks @Wumpus Q. Wumbley, this helped me understand things.

Doing next jumps leave and ret altogether. ret is the instruction that changes eip, it must be equivalent of pop eip. But leave modifies the stack pointers esp and ebp before (especially because when I am overwriting ebp+4 I change the value contained at ebp)

TLDR : Not overwriting the value at ebp makes it work successfully.

于 2013-11-03T20:12:33.420 回答
0

If this is for x86 (as opposed to x86-64), the usual function prologue involves pushing ebp and then assigning it the value of esp, which would leave the return address on the stack at ebp+4.

Take a look at a disassembly of your function, and see if the first instructions look like this:

pushl   %ebp
movl    %esp, %ebp

If so, this is the cause of the offset.

于 2013-11-03T19:12:45.983 回答