我试图玩缓冲区溢出。我不明白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中包含的值
有任何解释吗?
答案 0 :(得分:1)
好的,谢谢@Wumpus Q.Wumbley,这有助于我了解事情。
完全next
leave
和ret
。 ret
是更改eip
的指令,必须等同于pop eip
。但是leave
之前修改了堆栈指针esp
和ebp
(特别是当我覆盖ebp + 4时我改变了ebp中包含的值)
TLDR:不会覆盖ebp上的值,使其成功运行。
答案 1 :(得分:0)
如果这是针对x86(而不是x86-64),通常的函数序言涉及推送ebp
,然后为其赋值esp
,这会将返回地址保留在堆栈中在ebp+4
。
看一下你的函数的反汇编,看看第一条指令是这样的:
pushl %ebp
movl %esp, %ebp
如果是这样,这就是偏移的原因。