存在Canary但无法获取其值时,如何利用BOF漏洞?
带Canary保护的BOF漏洞利用方案探讨
题目代码
#include <stdio.h> #include <string.h> #include <stdlib.h> void func(int key){ char overflowme[32]; printf("overflow me : "); gets(overflowme); // smash me! if(key == 0xcafebabe){ system("/bin/sh"); } else{ printf("Nah..\n"); } } int main(int argc, char* argv[]){ func(0xdeadbeef); return 0; }
问题描述
这段代码中的gets()函数存在明显的缓冲区溢出漏洞,但目标二进制编译时开启了Canary保护,无法直接溢出缓冲区。在没有格式化字符串泄露的情况下,除了暴力破解外,还有哪些可行的方法可以获取Canary值以完成漏洞利用?
可行的替代方案
1. 逐字节爆破Canary(高效版暴力破解)
这是CTF中最常用的方案,比全量暴力破解效率高得多:
- Canary的最后一个字节固定为
0x00(用于终止字符串,避免被strcpy等函数泄露),所以实际需要爆破的字节数为3个(32位程序)或7个(64位程序)。 - 构造溢出 payload,每次覆盖Canary的一个字节,尝试所有可能的256个值,如果程序没有崩溃(说明猜中了该字节),就固定这个字节,继续爆破下一个字节。
- 如果程序采用fork子进程处理请求的架构,爆破过程不会导致主进程崩溃,完全可以通过脚本自动化完成,耗时极短。
2. 栈帧重叠利用
如果程序存在重复调用目标函数(func)的机会(比如循环结构、可重复触发的交互逻辑),可以利用栈帧的重叠特性:
- 第一次调用时,构造溢出覆盖Canary的部分字节,记录不崩溃的情况;第二次调用时,栈帧的位置可能和第一次重叠,基于之前的结果继续爆破剩余字节,逐步拼接完整的Canary值。
3. 堆内存关联泄露
如果程序存在堆操作(malloc/free)且有堆泄露漏洞,可尝试寻找栈Canary到堆内存的拷贝路径:
- 某些场景下,栈上的Canary会被意外复制到堆内存中(比如结构体拷贝、字符串操作时的内存复制)。如果能泄露堆中的对应内存区域,就可以提取出Canary值。不过这种方法依赖程序的具体实现,通用性较弱。
4. 异常上下文泄露
如果程序未正确处理内存错误信号(如SIGSEGV),可以构造溢出触发崩溃,从异常上下文(寄存器值、崩溃快照)中提取Canary:
- 部分环境下,程序崩溃时会输出寄存器或栈内存的部分信息,若Canary恰好出现在这些信息中,就能直接获取。但这种方法受限于目标环境的配置,在严格的CTF场景中可用性较低。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

