无法复制堆栈缓冲区溢出漏洞利用
Trouble replicating a stack buffer overflow exploit
我无法复制 OWASP here 给出的堆栈缓冲区溢出示例。
这是我的尝试:
$ cat test.c
#include <stdio.h>
#include <string.h>
void doit(void)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
}
int main(void)
{
printf("So... The End...\n");
doit();
printf("or... maybe not?\n");
return 0;
}
$ gcc test.c -o test -fno-stack-protection -ggdb
$ objdump -d test # omitted irrelevant parts i think
000000000040054c <doit>:
40054c: 55 push %rbp
40054d: 48 89 e5 mov %rsp,%rbp
400550: 48 83 ec 10 sub [=10=]x10,%rsp
400554: 48 8d 45 f0 lea -0x10(%rbp),%rax
400558: 48 89 c7 mov %rax,%rdi
40055b: e8 d0 fe ff ff callq 400430 <gets@plt>
400560: 48 8d 45 f0 lea -0x10(%rbp),%rax
400564: 48 89 c7 mov %rax,%rdi
400567: e8 a4 fe ff ff callq 400410 <puts@plt>
40056c: c9 leaveq
40056d: c3 retq
000000000040056e <main>:
40056e: 55 push %rbp
40056f: 48 89 e5 mov %rsp,%rbp
400572: bf 4c 06 40 00 mov [=10=]x40064c,%edi
400577: e8 94 fe ff ff callq 400410 <puts@plt>
40057c: e8 cb ff ff ff callq 40054c <doit>
400581: bf 5d 06 40 00 mov [=10=]x40065d,%edi
400586: e8 85 fe ff ff callq 400410 <puts@plt>
40058b: b8 00 00 00 00 mov [=10=]x0,%eax
400590: 5d pop %rbp
400591: c3 retq # this is where i took my overflow value from
400592: 90 nop
400593: 90 nop
400594: 90 nop
400595: 90 nop
400596: 90 nop
400597: 90 nop
400598: 90 nop
400599: 90 nop
40059a: 90 nop
40059b: 90 nop
40059c: 90 nop
40059d: 90 nop
40059e: 90 nop
40059f: 90 nop
$ perl -e 'print "A"x12 ."\x91\x05\x40"' | ./test
So... The End...
AAAAAAAAAAAA▒@
or... maybe not? # this shouldn't be outputted
为什么这不起作用?我假设我应该插入的内存地址是 <main>
.
中的 retq
我的目标是弄清楚如何执行调用程序其他地方的函数的堆栈缓冲区溢出。任何帮助深表感谢。 :)
我正在使用 Windows & MSVC,但你应该明白了。
考虑以下代码:
#include <stdio.h>
void someFunc()
{
puts("wow, we should never get here :|");
}
// MSVC inlines this otherwise
void __declspec(noinline) doit(void)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
}
int main(void)
{
printf("So... The End...\n");
doit();
printf("or... maybe not?\n");
return 0;
}
(注意:我不得不用 /OPT:NOREF
编译它以强制 MSVC 不删除 "unused" 代码和 /GS-
关闭堆栈检查)
现在,让我们用我最喜欢的反汇编程序打开它:
我们想利用 gets
漏洞,以便执行跳转到 someFunc
。我们可以看到它的地址是 001D1000
,所以如果我们可以向缓冲区写入足够的字节以覆盖 return 地址,我们就可以了。我们来看看调用gets
时的栈:
正如我们所见,我们的堆栈分配缓冲区有 8 个字节(buf
),一些东西有 4 个字节(实际上是 PUSH
ed EBP),以及 return地址。因此,我们需要写入 12 字节的任何内容,然后是我们的 4 字节 return 地址 (001D1000
) 到 "hijack" 执行流。让我们这样做 - 我们将使用十六进制编辑器准备一个包含我们需要的字节的输入文件:
确实,当我们 运行 使用该输入的程序时,我们得到:
打印该行后,由于堆栈中有一些垃圾,它将因访问冲突而崩溃。然而,没有什么可以阻止您仔细分析代码并在输入中准备这样的字节,以使程序看起来正常运行(我们可以用地址 ExitProcess
覆盖下一个字节,这样 someFunc
会跳到那里)。
我无法复制 OWASP here 给出的堆栈缓冲区溢出示例。
这是我的尝试:
$ cat test.c
#include <stdio.h>
#include <string.h>
void doit(void)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
}
int main(void)
{
printf("So... The End...\n");
doit();
printf("or... maybe not?\n");
return 0;
}
$ gcc test.c -o test -fno-stack-protection -ggdb
$ objdump -d test # omitted irrelevant parts i think
000000000040054c <doit>:
40054c: 55 push %rbp
40054d: 48 89 e5 mov %rsp,%rbp
400550: 48 83 ec 10 sub [=10=]x10,%rsp
400554: 48 8d 45 f0 lea -0x10(%rbp),%rax
400558: 48 89 c7 mov %rax,%rdi
40055b: e8 d0 fe ff ff callq 400430 <gets@plt>
400560: 48 8d 45 f0 lea -0x10(%rbp),%rax
400564: 48 89 c7 mov %rax,%rdi
400567: e8 a4 fe ff ff callq 400410 <puts@plt>
40056c: c9 leaveq
40056d: c3 retq
000000000040056e <main>:
40056e: 55 push %rbp
40056f: 48 89 e5 mov %rsp,%rbp
400572: bf 4c 06 40 00 mov [=10=]x40064c,%edi
400577: e8 94 fe ff ff callq 400410 <puts@plt>
40057c: e8 cb ff ff ff callq 40054c <doit>
400581: bf 5d 06 40 00 mov [=10=]x40065d,%edi
400586: e8 85 fe ff ff callq 400410 <puts@plt>
40058b: b8 00 00 00 00 mov [=10=]x0,%eax
400590: 5d pop %rbp
400591: c3 retq # this is where i took my overflow value from
400592: 90 nop
400593: 90 nop
400594: 90 nop
400595: 90 nop
400596: 90 nop
400597: 90 nop
400598: 90 nop
400599: 90 nop
40059a: 90 nop
40059b: 90 nop
40059c: 90 nop
40059d: 90 nop
40059e: 90 nop
40059f: 90 nop
$ perl -e 'print "A"x12 ."\x91\x05\x40"' | ./test
So... The End...
AAAAAAAAAAAA▒@
or... maybe not? # this shouldn't be outputted
为什么这不起作用?我假设我应该插入的内存地址是 <main>
.
retq
我的目标是弄清楚如何执行调用程序其他地方的函数的堆栈缓冲区溢出。任何帮助深表感谢。 :)
我正在使用 Windows & MSVC,但你应该明白了。
考虑以下代码:
#include <stdio.h>
void someFunc()
{
puts("wow, we should never get here :|");
}
// MSVC inlines this otherwise
void __declspec(noinline) doit(void)
{
char buf[8];
gets(buf);
printf("%s\n", buf);
}
int main(void)
{
printf("So... The End...\n");
doit();
printf("or... maybe not?\n");
return 0;
}
(注意:我不得不用 /OPT:NOREF
编译它以强制 MSVC 不删除 "unused" 代码和 /GS-
关闭堆栈检查)
现在,让我们用我最喜欢的反汇编程序打开它:
我们想利用 gets
漏洞,以便执行跳转到 someFunc
。我们可以看到它的地址是 001D1000
,所以如果我们可以向缓冲区写入足够的字节以覆盖 return 地址,我们就可以了。我们来看看调用gets
时的栈:
正如我们所见,我们的堆栈分配缓冲区有 8 个字节(buf
),一些东西有 4 个字节(实际上是 PUSH
ed EBP),以及 return地址。因此,我们需要写入 12 字节的任何内容,然后是我们的 4 字节 return 地址 (001D1000
) 到 "hijack" 执行流。让我们这样做 - 我们将使用十六进制编辑器准备一个包含我们需要的字节的输入文件:
确实,当我们 运行 使用该输入的程序时,我们得到:
打印该行后,由于堆栈中有一些垃圾,它将因访问冲突而崩溃。然而,没有什么可以阻止您仔细分析代码并在输入中准备这样的字节,以使程序看起来正常运行(我们可以用地址 ExitProcess
覆盖下一个字节,这样 someFunc
会跳到那里)。