arn*_*app 11 c stack-overflow buffer overflow fortify-source
我正在尝试缓冲区溢出,并尝试使用一定的fgets输入覆盖堆栈的返回地址
这是代码:
void foo()
{
fprintf(stderr, "You did it.\n");
}
void bar()
{
char buf[20];
puts("Input:");
fgets(buf, 24, stdin);
printf("Your input:.\n", strlen(buf));
}
int main(int argc, char **argv)
{
bar();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在正常执行时,程序只返回您的输入.我希望它输出foo()而不修改代码.
我的想法是buf
通过进入20 'A'
秒来溢出缓冲区.这会起作用并导致分段错误.我的下一个想法是找出其中的地址并将foo()
其\x4006cd
附加到20 'A'
秒.
根据我的理解,这应该覆盖堆栈的返回地址并使其跳转到foo
.但它只会导致段错误.
我究竟做错了什么?
更新:汇编程序转储主要
Dump of assembler code for function main:
0x000000000040073b <+0>: push %rbp
0x000000000040073c <+1>: mov %rsp,%rbp
0x000000000040073f <+4>: sub $0x10,%rsp
0x0000000000400743 <+8>: mov %edi,-0x4(%rbp)
0x0000000000400746 <+11>: mov %rsi,-0x10(%rbp)
0x000000000040074a <+15>: mov $0x0,%eax
0x000000000040074f <+20>: callq 0x4006f1 <bar>
0x0000000000400754 <+25>: mov $0x0,%eax
0x0000000000400759 <+30>: leaveq
0x000000000040075a <+31>: retq
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
FOO
Dump of assembler code for function foo:
0x00000000004006cd <+0>: push %rbp
0x00000000004006ce <+1>: mov %rsp,%rbp
0x00000000004006d1 <+4>: mov 0x200990(%rip),%rax # 0x601068 <stderr@@GLIBC_2.2.5>
0x00000000004006d8 <+11>: mov %rax,%rcx
0x00000000004006db <+14>: mov $0x15,%edx
0x00000000004006e0 <+19>: mov $0x1,%esi
0x00000000004006e5 <+24>: mov $0x400804,%edi
0x00000000004006ea <+29>: callq 0x4005d0 <fwrite@plt>
0x00000000004006ef <+34>: pop %rbp
0x00000000004006f0 <+35>: retq
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
酒吧:
Dump of assembler code for function bar:
0x00000000004006f1 <+0>: push %rbp
0x00000000004006f2 <+1>: mov %rsp,%rbp
0x00000000004006f5 <+4>: sub $0x20,%rsp
0x00000000004006f9 <+8>: mov $0x40081a,%edi
0x00000000004006fe <+13>: callq 0x400570 <puts@plt>
0x0000000000400703 <+18>: mov 0x200956(%rip),%rdx # 0x601060 <stdin@@GLIBC_2.2.5>
0x000000000040070a <+25>: lea -0x20(%rbp),%rax
0x000000000040070e <+29>: mov $0x18,%esi
0x0000000000400713 <+34>: mov %rax,%rdi
0x0000000000400716 <+37>: callq 0x4005b0 <fgets@plt>
0x000000000040071b <+42>: lea -0x20(%rbp),%rax
0x000000000040071f <+46>: mov %rax,%rdi
0x0000000000400722 <+49>: callq 0x400580 <strlen@plt>
0x0000000000400727 <+54>: mov %rax,%rsi
0x000000000040072a <+57>: mov $0x400821,%edi
0x000000000040072f <+62>: mov $0x0,%eax
0x0000000000400734 <+67>: callq 0x400590 <printf@plt>
0x0000000000400739 <+72>: leaveq
0x000000000040073a <+73>: retq
End of assembler dump.
Run Code Online (Sandbox Code Playgroud)
你没有计算内存对齐。我稍微更改了代码,以便更容易找到正确的位置。
\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n\nint **x;\nint z;\n\nvoid foo()\n{\n fprintf(stderr, "You did it.\\n");\n}\n\nvoid bar()\n{\n char buf[2];\n //puts("Input:");\n //fgets(buf, 70, stdin);\n x = (int**) buf;\n for(z=0;z<8;z++)\n printf("%d X=%x\\n", z, *(x+z));\n *(x+3) = foo;\n printf("Your input: %d %s\\n", strlen(buf), buf);\n}\n\n\nint main(int argc, char **argv)\n{\n printf("Foo: %x\\n", foo);\n printf("Main: %x\\n", main);\n bar();\n return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n对于较小的缓冲区(在我的示例中为 2),我发现返回地址距缓冲区开头 24 个字节(x+3,对于 8 字节指针;64 位,无调试,无优化...)。该位置可以根据缓冲区大小、体系结构等进行更改。在本示例中,我设法将 bar 的返回地址更改为 foo。无论如何,您将在 foo 返回时遇到分段错误,因为它没有正确设置为返回到 main。
\n\n我将 x 和 z 添加为全局变量,以不更改 bar 的堆栈大小。该代码将显示一个类似指针的值数组,从 buf[0] 开始。就我而言,我在 main 中的位置 3 中找到了地址。这就是为什么最终代码有 *(x+3) = foo。正如我所说,这个位置可以根据编译选项、机器等而改变。要找到正确的位置,请在地址列表上找到 main 的地址(在调用 bar 之前打印)。
\n\n需要注意的是,我说的是 main 中的地址,而不是 main 的地址,因为返回地址被设置为调用 bar 之后的行,而不是 main 的开头。所以,就我而言,它是 0x4006af 而不是 0x400668。
\n\n在您的示例中,据我所知,对于 20 字节缓冲区,它与 32 字节(0x20)对齐。
\n\n如果你想对 fgets 做同样的事情,你必须弄清楚如何输入 foo 的地址,但如果你运行的是 x86/x64 机器,请记住将其添加到小尾数中。您可以更改代码以按字节显示值,这样您就可以按正确的顺序获取它们并使用 ALT+数字键入它们。请记住,按住 ALT 时键入的数字是十进制数字。有些终端不会友好地处理 0x00。
\n\n我的输出看起来像:
\n\n$ gcc test.c -o test\ntest.c: In function \xe2\x80\x98bar\xe2\x80\x99:\ntest.c:21: warning: assignment from incompatible pointer type\n$ ./test\nFoo: 400594\nMain: 400668\n0 X=9560e9f0\n1 X=95821188\n2 X=889350f0\n3 X=4006af\n4 X=889351d8\n5 X=0\n6 X=0\n7 X=95a1ed1d\nYour input: 5 \xe2\x96\x92\xe2\x96\x92`\xe2\x96\x929\nYou did it.\nSegmentation fault\n
Run Code Online (Sandbox Code Playgroud)\n