在我尝试理解缓冲区溢出时,我编写了示例C / C ++程序。程序会要求您输入密码,然后根据您是否输入正确的密码显示两条不同的消息。我打开代码并将其拆解以找到我可以跳转到的一点,以便我可以覆盖正确或不正确的密码。我写了一个快速的python脚本,用“A”填充缓冲区,然后返回地址回到我希望代码执行的位置。
这种方法在GDB调试器中运行得很好,但是当我在调试器外运行相同的东西时,我会遇到分段错误。有谁知道为什么会这样?
以下是代码:
#include <stdio.h>
#include <string.h>
int checkpw();
int main(int argc, char* argv[])
{
int r = checkpw();
if(r==0)
{
printf("Congrats, you have been granted access to the program");
}
else
{
printf("That is the incorret password. Please exit immediately.");
}
return 0;
}
int checkpw()
{
char buffer[10];
gets(buffer);
return strcmp(buffer,"password");
}
我使用此行g++ -z execstack -g -fno-stack-protector main.cpp -o main
这会产生这两个反汇编的代码段,第一个代表main
函数...
0x00000000004005bd <+0>: push %rbp
0x00000000004005be <+1>: mov %rsp,%rbp
0x00000000004005c1 <+4>: sub $0x20,%rsp
0x00000000004005c5 <+8>: mov %edi,-0x14(%rbp)
0x00000000004005c8 <+11>: mov %rsi,-0x20(%rbp)
0x00000000004005cc <+15>: callq 0x400601 <checkpw()>
0x00000000004005d1 <+20>: mov %eax,-0x4(%rbp)
0x00000000004005d4 <+23>: cmpl $0x0,-0x4(%rbp)
0x00000000004005d8 <+27>: jne 0x4005eb <main(int, char**)+46>
0x00000000004005da <+29>: mov $0x4006b8,%edi
0x00000000004005df <+34>: mov $0x0,%eax
0x00000000004005e4 <+39>: callq 0x400480 <printf@plt>
0x00000000004005e9 <+44>: jmp 0x4005fa <main(int, char**)+61>
0x00000000004005eb <+46>: mov $0x4006f0,%edi
0x00000000004005f0 <+51>: mov $0x0,%eax
0x00000000004005f5 <+56>: callq 0x400480 <printf@plt>
0x00000000004005fa <+61>: mov $0x0,%eax
0x00000000004005ff <+66>: leaveq
0x0000000000400600 <+67>: retq
现在是checkpw()
功能...
0x0000000000400601 <+0>: push %rbp
0x0000000000400602 <+1>: mov %rsp,%rbp
0x0000000000400605 <+4>: sub $0x10,%rsp
0x0000000000400609 <+8>: lea -0x10(%rbp),%rax
0x000000000040060d <+12>: mov %rax,%rdi
0x0000000000400610 <+15>: callq 0x4004c0 <gets@plt>
0x0000000000400615 <+20>: lea -0x10(%rbp),%rax
0x0000000000400619 <+24>: mov $0x400728,%esi
0x000000000040061e <+29>: mov %rax,%rdi
0x0000000000400621 <+32>: callq 0x4004a0 <strcmp@plt>
0x0000000000400626 <+37>: leaveq
0x0000000000400627 <+38>: retq
在运行调试器之前,我将此命令输入到终端python -c 'print "AAAAAAAAAAAAAAAA\x40\xdf\xff\xff\xff\x7f\x00\x00\xda\x05\x40\x00\x00\x00\x00\x00"' > /tmp/input1
中,它创建了一个充满“A”的文件,更重要的是将返回地址写入打印出的代码的开头。访问该计划。 \xda\x05\x40\x00\x00\x00\x00\x00
这完美无缺。我运行gdb main
然后在调试器中输入run < /tmp/input1
和“恭喜,您已被授予访问程序的权限”将被打印到屏幕上。
所以我在调试器外部尝试这个尝试失败了。我从终端运行这个命令......
python -c 'print "AAAAAAAAAAAAAAAA\x40\xdf\xff\xff\xff\x7f\x00\x00\xda\x05\x40\x00\x00\x00\x00\x00"' | ./main
我收到了一个段错误。