【发布时间】:2013-11-14 09:57:58
【问题描述】:
我正在尝试处理缓冲区溢出。我不明白 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 中包含的值
有什么解释吗?
【问题讨论】:
-
也许访问 0x80cdd18d 的尝试是在 0x80484b6 处运行指令的结果。你怎么知道它没有跳到那里?
-
我一直在 gdb 上做“下一步”,它没有经过 0x80484b6 就进入了 0x80cdd18d
-
“无法访问内存”消息并不意味着您的程序的 %eip 去了那里。这甚至不意味着您的程序试图访问该地址!这意味着 gdb 出于某种原因想要访问下级进程的地址空间中的该地址并且不能。在行为不端的程序的 gdb 会话期间,经常会看到这种警告。你的肯定是行为不端 - 它有缓冲区溢出!尝试在 strcpy 之后使用
stepi而不是next进行单步指令,您可能会更清楚地了解发生了什么。 -
您可能会发现它对
display/i $pc(可能还有其他一些有趣的寄存器)和stepi通过返回序列很有用。 -
感谢您的 cmets,我发布了答案,问题是 $ebp 的值在覆盖期间发生了变化
标签: c assembly x86 cpu-registers buffer-overflow