Linux 堆栈溢出-奇数返回地址
我正在通过“外壳编码器手册”中的一个例子进行研究。然而,事情并不是那么顺利。我正在运行Debian2.6.32-5-686内核i386 以下演练将引导读者了解发生缓冲区溢出时发生的情况 该方案:Linux 堆栈溢出-奇数返回地址,linux,gcc,stack,Linux,Gcc,Stack,我正在通过“外壳编码器手册”中的一个例子进行研究。然而,事情并不是那么顺利。我正在运行Debian2.6.32-5-686内核i386 以下演练将引导读者了解发生缓冲区溢出时发生的情况 该方案: include <stdio.h> include <string.h> void return_input(void) { char array[30]; gets (array); printf("%s\n", array); } int main
include <stdio.h>
include <string.h>
void return_input(void)
{
char array[30];
gets (array);
printf("%s\n", array);
}
int main ()
{
return_input();
return 0;
}
我运行gdb测试
并开始调查:
(gdb) disas return_input
Dump of assembler code for function return_input:
0x080483f4 <return_input+0>: push %ebp
0x080483f5 <return_input+1>: mov %esp,%ebp
0x080483f7 <return_input+3>: sub $0x24,%esp
0x080483fa <return_input+6>: lea -0x1e(%ebp),%eax
0x080483fd <return_input+9>: mov %eax,(%esp)
0x08048400 <return_input+12>: call 0x804830c <gets@plt>
0x08048405 <return_input+17>: lea -0x1e(%ebp),%eax
0x08048408 <return_input+20>: mov %eax,(%esp)
0x0804840b <return_input+23>: call 0x804832c <puts@plt>
0x08048410 <return_input+28>: leave
0x08048411 <return_input+29>: ret
End of assembler dump.
(gdb) break *0x08048400
Breakpoint 1 at 0x8048400: file test.c, line 7.
(gdb) break *0x08048411
Breakpoint 2 at 0x8048411: file test.c, line 9.
这就是堆栈在调用之前的样子。我已经用星号(0x0804841a
)标记了回信地址。让我们覆盖以下内容:
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
Breakpoint 2, 0x08048411 in return_input () at test.c:9
9 }
(gdb) x/20x 0xbffff3ac
0xbffff3ac: 0xbffff3b2 0x4141a304 0x41414141 0x41414141
0xbffff3bc: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff3cc: 0x43434343 0x44444444 *0x44444444* 0xbf004444
0xbffff3dc: 0xb7e9ec76 0x00000001 0xbffff484 0xbffff48c
0xbffff3ec: 0xb7fe18c8 0xbffff440 0xffffffff 0xb7ffeff4
上面是堆栈在从函数返回之前的样子。正如你所看到的,我们已经用那些多余的“D”覆盖了返回地址。后果让我们结束:
(gdb) x/li $eip
0x8048411 <return_input+29>: ret
(gdb) stepi
Cannot access memory at address 0x44444448
(gdb)x/li$eip
0x8048411:ret
(gdb)stepi
无法访问地址为0x4448的内存
嗯,嗯??这个0x4448
不知从何而来。不知何故,gcc在我们返回之前修改了返回地址。谢谢
有什么想法吗?我是否正确地假设gcc已经做了自己的内部检查返回地址是否有效。如果不是的话,它会在里面放一些垃圾来阻止我们设计一个肮脏的回信地址
有办法吗?我在这里什么都试过了。相同的结果。这是预期的结果—页面错误。您的程序被操作系统停止,因为您正在访问未分配给任何物理内存的虚拟内存
您看到的消息只是调试器通知您这一事实。这是预期的结果—页面错误。您的程序被操作系统停止,因为您正在访问未分配给任何物理内存的虚拟内存
您看到的消息只是调试器通知您这一事实。在调试gcc时,gcc什么都不做。在调试gcc时,gcc什么都不做。call
将eip
推到堆栈上,以便在调用ret
时,它知道返回到哪里。在此示例中,eip
已被0x4444
覆盖。这是书中明确指出的。公平地说,这是一个页面错误,但是在eip
中添加4与文本相矛盾(或者至少看起来是矛盾的)。事实上,文本的下一节假设了这一点,并继续将返回地址修改为上面的return\u input
函数的返回地址。这样:printf“aaaaaaaaaaaaaabbbbbbbbbbccccccccccccccccccddd\xed\x83\x04\x08”|./test
其中函数的地址为0x080483ed
。这会导致函数运行两次。但当然,这在机器上不起作用。@tbh1:您是对的,ret
将直接跳转到堆栈上的地址(在这种情况下,0x4444
)。所以我给了你错误的线索。页面错误可能不是由程序直接引起的,而是由调试器引起的。调试器修改程序,使其在每条指令后停止。它通过在每条指令后插入中断指令来实现。因此,在执行ret
之前,它会尝试访问地址0x4448
,以插入中断指令。如果你在没有调试器的情况下运行你的程序,它会在正确的地址出现页面错误。啊哈,你说得对!非常微妙,谢谢你,麦基。我让程序调用return\u input
函数两次。在文本中,它使用了我在上述评论中给出的printf
。然而,这对我来说不起作用。工作是printf“aaaaaaaaaaaaaabbbbbbbbccccccccccccccdd\xed\x83\x04\x08DD”|/测试
。结果。call
将eip
推到堆栈上,以便在调用ret
时,它知道返回到哪里。在此示例中,eip
已被0x4444
覆盖。这是书中明确指出的。公平地说,这是一个页面错误,但是在eip
中添加4与文本相矛盾(或者至少看起来是矛盾的)。事实上,文本的下一节假设了这一点,并继续将返回地址修改为上面的return\u input
函数的返回地址。这样:printf“aaaaaaaaaaaaaabbbbbbbbbbccccccccccccccccccddd\xed\x83\x04\x08”|./test
其中函数的地址为0x080483ed
。这会导致函数运行两次。但当然,这在机器上不起作用。@tbh1:您是对的,ret
将直接跳转到堆栈上的地址(在这种情况下,0x4444
)。所以我给了你错误的线索。页面错误可能不是由程序直接引起的,而是由调试器引起的。调试器修改程序,使其在每条指令后停止。它通过在每条指令后插入中断指令来实现。因此,在执行ret
之前,它会尝试访问地址0x4448
,以插入中断指令。如果你在没有调试器的情况下运行你的程序,它会在正确的地址出现页面错误。啊哈,你说得对!非常微妙,谢谢你,麦基。我让程序调用return\u input
函数两次。在文本中,它使用了我在上述评论中给出的printf
。然而,这对我来说不起作用。工作是printf“aaaaaaaaaaaaaabbbbbbbbccccccccccccccdd\xed\x83\x04\x08DD”|/测试
。后果
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
Breakpoint 2, 0x08048411 in return_input () at test.c:9
9 }
(gdb) x/20x 0xbffff3ac
0xbffff3ac: 0xbffff3b2 0x4141a304 0x41414141 0x41414141
0xbffff3bc: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff3cc: 0x43434343 0x44444444 *0x44444444* 0xbf004444
0xbffff3dc: 0xb7e9ec76 0x00000001 0xbffff484 0xbffff48c
0xbffff3ec: 0xb7fe18c8 0xbffff440 0xffffffff 0xb7ffeff4
(gdb) x/li $eip
0x8048411 <return_input+29>: ret
(gdb) stepi
Cannot access memory at address 0x44444448