为什么eip在此缓冲区溢出尝试中没有改变?

时间:2013-11-03 18:46:00

标签: c assembly x86 cpu-registers buffer-overflow

我试图玩缓冲区溢出。我不明白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个字节为4个字节在$ ebp之后(为了覆盖真实的返回地址)。它似乎有效。

在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是包含返回地址的地方

我再次尝试使用4字节更小的字符串,这次它覆盖了$ ebp而不是$ ebp + 4,并且在返回之后将$ eip设置为$ ebp + 4中包含的值

有任何解释吗?

2 个答案:

答案 0 :(得分:1)

好的,谢谢@Wumpus Q.Wumbley,这有助于我了解事情。

完全next leaveretret是更改eip的指令,必须等同于pop eip。但是leave之前修改了堆栈指针espebp(特别是当我覆盖ebp + 4时我改变了ebp中包含的值)

TLDR:不会覆盖ebp上的值,使其成功运行。

答案 1 :(得分:0)

如果这是针对x86(而不是x86-64),通常的函数序言涉及推送ebp,然后为其赋值esp,这会将返回地址保留在堆栈中在ebp+4

看一下你的函数的反汇编,看看第一条指令是这样的:

pushl   %ebp
movl    %esp, %ebp

如果是这样,这就是偏移的原因。