heap 0 题解

📅 2026/7/6 13:35:48 👁️ 阅读次数 📝 编程学习
heap 0 题解

一、题目概况

heap 0 是 picoCTF 中用于引入堆溢出概念的入门题目。根据公开的 writeup 说明,本题会提供二进制文件、源代码以及远程访问实例。在源码中,存在input_datasafe_var两块堆上分配的数据。解题目标是将safe_var的值从初始的 “bico” 修改为其他任意值,从而触发程序进入打印 flag 的分支逻辑。

二、关键代码

公开 writeup 中展示的check_win函数逻辑非常直接:只要safe_var的值不等于 “bico”,程序就会打印 flag。

void check_win() {

if (strcmp(safe_var, "bico") != 0) {

printf("\nYOU WIN\n");

// read and print flag

exit(0);

} else {

printf("Looks like everything is still secure!\n");

}

}

真正的漏洞出现在数据写入函数中。scanf("%s", input_data)没有对输入长度进行任何限制,这意味着用户可以输入远超input_data所在堆块容量的数据,从而造成堆缓冲区溢出。

void write_buffer() {

printf("Data for buffer: ");

fflush(stdout);

scanf("%s", input_data);

}

heap 0 中覆盖 safe_var 的内存布局思路

三、解题过程

(1)确认目标变量。题目不需要劫持返回地址,也不需要写shellcode。目标只是改变safe_var的内容,使strcmp(safe_var, "bico") != 0成立。对于入门堆题来说,这种目标非常友好,因为我们只需要覆盖相邻数据。

(2)估算覆盖程度。公开writeup给出的内存布局示例中,input_datasafe_var的地址差为32字节。因此输入至少33字节,就能让数据越过input_data覆盖到safe_var

Heap layout example:

0x...12b0 -> input_data: "pico"

0x...12d0 -> safe_var: "bico"

0x12d0 - 0x12b0 = 0x20 = 32 bytes

(3)构造输入。payload可以非常朴素,只要长度超过边界即可。下面用Python生成33 个字符

payload = "A" * 33

print(payload)

在交互菜单中选择写入buffer的功能,输入这段payload,再触发检查flag的功能即可。公开writeup给出的flag 为:

picoCTF{my_first_heap_overflow_c3935a08}

四、复盘

heap 0的重点是把溢出不只发生在栈上这件事讲清楚。只要写入没有边界,堆上的相邻对象同样可能被覆盖;如果被覆盖的是权限位、状态变量或函数指针,影响就会迅速放大。

要点:scanf("%s", buf)不知道buf的容量,除非格式串显式限制宽度。

要点:相邻堆块之间的距离可以通过程序输出、调试器或源码推断。

要点:入门阶段先找改变量即可赢的题,再逐步过渡到tcacheUAF和函数指针劫持。