编辑:我原来的问题不再准确,所以我重写了它。
所以我正在编写一个程序来演示C中的堆喷雾(我知道这是不寻常的)。我正在使用malloc分配一个巨大的缓冲区(100MB),但是它分配到标记为映射而不是[heap]的段中,我无法弄清楚原因。
我的代码:
int NOPSize = 960;
int ShellcodeSize = 64;
int PayloadSize = NOPSize + ShellcodeSize;
char Payload[PayloadSize];
char* HeapBuf = (char*)malloc(0x6400000); //104,857,600 (100MB)
for (int x = 0; x < PayloadSize; x++)
Payload[x] = (x <= NOPSize) ? '\x90' : '\x41';
for (int x = 0; x < 0x6400000; x++)
HeapBuf[x] = Payload[x % PayloadSize];
printf("%x\n", HeapBuf);
free(HeapBuf);
使用从调用free
时设置的断点获取的GDB-PEDA输出vmmap:
0x80000000 0x80001000 r-xp /root/Documents/a.out
0x80001000 0x80002000 r--p /root/Documents/a.out
0x80002000 0x80003000 rw-p /root/Documents/a.out
0x80003000 0x80024000 rw-p [heap]
0xb19fd000 0xb7dfe000 rw-p mapped
0xb7dfe000 0xb7faf000 r-xp /lib/i386-linux-gnu/libc-2.24.so
0xb7faf000 0xb7fb1000 r--p /lib/i386-linux-gnu/libc-2.24.so
0xb7fb1000 0xb7fb2000 rw-p /lib/i386-linux-gnu/libc-2.24.so
0xb7fb2000 0xb7fb5000 rw-p mapped
0xb7fd4000 0xb7fd7000 rw-p mapped
0xb7fd7000 0xb7fd9000 r--p [vvar]
0xb7fd9000 0xb7fdb000 r-xp [vdso]
0xb7fdb000 0xb7ffd000 r-xp /lib/i386-linux-gnu/ld-2.24.so
0xb7ffe000 0xb7fff000 r--p /lib/i386-linux-gnu/ld-2.24.so
0xb7fff000 0xb8000000 rw-p /lib/i386-linux-gnu/ld-2.24.so
0xbffdf000 0xc0000000 rw-p [stack]
printf
输出位于顶部映射段中的0xb19fd008
。
有趣的是,如果我删除对[heap]
的调用,printf
段就会消失。所以我的问题是,为什么[heap]
段的存在取决于对printf
的调用,为什么打印的地址位于映射的段中,而不是[heap]
段?感谢。
答案 0 :(得分:2)
HeapBuf
就像您在代码中拥有的任何其他int
,long
,char
一样驻留在堆栈上,因为指针本身仅仅是一个数字。但它指向的内存确实是在堆上分配的。
答案 1 :(得分:1)
我无法复制OP的结果。但是,与OP不同,我在x86-64内核和64位二进制文件上运行。
这是一个小型测试程序 test.c :
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void self_maps(void)
{
FILE *in;
int c;
in = fopen("/proc/self/maps", "r");
if (!in)
return;
/* Let the C library handle the buffering. */
while ((c = getc(in)) != EOF)
putchar(c);
fclose(in);
}
int main(void)
{
size_t NOPSize = 960;
size_t ShellcodeSize = 64;
size_t PayloadSize = NOPSize + ShellcodeSize;
size_t BufferSize = 0x6400000;
size_t i;
char Payload[PayloadSize];
char *HeapBuf;
HeapBuf = malloc(BufferSize);
if (!HeapBuf) {
fprintf(stderr, "Out of memory.\n");
return EXIT_FAILURE;
}
printf("Payload = %p\n", (void *)Payload);
printf("HeapBuf = %p\n", (void *)HeapBuf);
for (i = 0; i < NOPSize; i++)
Payload[i] = '\x90';
for (i = NOPSize; i < PayloadSize; i++)
Payload[i] = '\x41';
for (i = 0; i < BufferSize; i++)
HeapBuf[i] = Payload[i % PayloadSize];
printf("\n");
self_maps();
free(HeapBuf);
return EXIT_SUCCESS;
}
如果我使用
编译并运行它gcc -Wall -O2 test.c -o test
./test
我得到输出
Payload = 0x7fff3122b6b0
HeapBuf = 0x7f378806a010
00400000-00401000 r-xp 00000000 08:07 4587700 /.../test
00600000-00601000 r--p 00000000 08:07 4587700 /.../test
00601000-00602000 rw-p 00001000 08:07 4587700 /.../test
022c3000-022e5000 rw-p 00000000 00:00 0 [heap]
7f378806a000-7f378e46b000 rw-p 00000000 00:00 0
7f378e46b000-7f378e62a000 r-xp 00000000 08:05 1966262 /lib/x86_64-linux-gnu/libc-2.23.so
7f378e62a000-7f378e82a000 ---p 001bf000 08:05 1966262 /lib/x86_64-linux-gnu/libc-2.23.so
7f378e82a000-7f378e82e000 r--p 001bf000 08:05 1966262 /lib/x86_64-linux-gnu/libc-2.23.so
7f378e82e000-7f378e830000 rw-p 001c3000 08:05 1966262 /lib/x86_64-linux-gnu/libc-2.23.so
7f378e830000-7f378e834000 rw-p 00000000 00:00 0
7f378e834000-7f378e85a000 r-xp 00000000 08:05 1966245 /lib/x86_64-linux-gnu/ld-2.23.so
7f378ea2c000-7f378ea2f000 rw-p 00000000 00:00 0
7f378ea57000-7f378ea59000 rw-p 00000000 00:00 0
7f378ea59000-7f378ea5a000 r--p 00025000 08:05 1966245 /lib/x86_64-linux-gnu/ld-2.23.so
7f378ea5a000-7f378ea5b000 rw-p 00026000 08:05 1966245 /lib/x86_64-linux-gnu/ld-2.23.so
7f378ea5b000-7f378ea5c000 rw-p 00000000 00:00 0
7fff3120c000-7fff3122d000 rw-p 00000000 00:00 0 [stack]
7fff3126c000-7fff3126e000 r--p 00000000 00:00 0 [vvar]
7fff3126e000-7fff31270000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
因为我使用的GNU C库的版本使用大于130 kB左右的分配的内存映射,HeapBuf
是自己的映射:
7f378806a000-7f378e46b000 rw-p 00000000 00:00 0
答案 2 :(得分:1)
这里有两件事,在我进入它们之前,我必须警告你,根据地图输出中字符串/lib/i386-linux-gnu/libc-2.24.so
的存在,我推断出操作您运行程序的系统使用Linux内核和GNU C库(&#39; glibc&#39;)。我要告诉你的一些内容对这些组件非常特别。
首先:由于历史原因,有两种不同的方法可以在操作系统上分配内存,这些方法符合&#34; Unix&#34; (对于第一个订单:任何人仍然使用的所有内容,Windows除外):系统调用sbrk
和mmap
。 sbrk
更加有限;它只能在预定位置管理单个内存区域的 size ,而mmap
(及其对应munmap
)可以在任何地方分配和释放独立的内存块地址空间。 Linux的/proc/PID/maps
文件对[heap]
管理的内存区域使用sbrk
标签。分配有mmap
的独立内存块标记为&#34;映射&#34;。
第二:glibc的malloc
实施使用sbrk
进行小额分配,mmap
进行大额分配(参见M_MMAP_THRESHOLD
对0xb19fd000 0xb7dfe000 rw-p mapped
的讨论}})。 &#34; small&#34;之间的默认阈值和&#34;大&#34;是128 千字节;你分配了0x6400000字节= 100 兆字节,这显然要大得多。您的映射转储行
malloc
只比您要求的页面大一页 - 差异是由于[heap]
为其自己的簿记信息占用了一些额外空间。
当您致电printf
时会显示stdout
段,因为 - 再次,这是glibc的怪癖 - 第一次使用malloc
执行任何操作时,会在内部分配一些内存,使用sbrk
。该分配小于而不是128kB,因此它会被放入mmap
区域,并且就在那里。
(根据您正在尝试模拟的#34;堆喷和#34;攻击,要么您不在乎自己的<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width:device-width, initial-scale = 1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<style>
.affix {
top: 0;
width: 100%;
}
.affix + .container-fluid {
padding-top: 70px;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="alert alert-warning alert-dismissable fade in">
<a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
<strong>Warning!</strong> This site uses cookies
</div>
<nav class="navbar navbar-inverse" data-spy="affix" data-offset-top="197">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Something</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li><a href="#">Home</a>
</li>
<li><a href="#">Pag 1</a>
</li>
<li><a href="#">Pag 2</a>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>
<a href="#"> <span class="glyphicon glyphicon-log-in"> </span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="container-fluid" style="height:1000px">
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
<h1>Some text to enable scrolling</h1>
</div>
</body>
</html>
分配中的100MB因为您&# 39;只是试图覆盖足够的整个地址空间,野指针有很大的机会指向那里,或者你需要分配大量的小对象,每个对象的大小与易受攻击的应用程序中的一些关键数据,这样您就有可能将分配与应用程序混淆。)