DEF CON Quals 2026 - shelldiet
I'm on a seed-only diet, except shells
Challenge Overview
shelldiet 是 DEF CON CTF Quals 2026 的一道 King of the Hill
题目。服务器运行一个 C 程序,读取用户提供的
shellcode,计算所有字节之和(称为 "diet level"),然后执行
shellcode。flag 文件位于 /flag,需要通过 shellcode
读取并输出。KoTH 排名基于 diet level:sum 越低排名越高,"Eat-clean
diet"(榜首)需要 sum=0。
Given Files
chal.c-- 挑战二进制源码Dockerfile/compose.yml/nsjail.cfg-- 部署配置flag-- 占位 flag(shelldiet{fake_flag})chal-- 编译好的二进制launch/handout-- 启动脚本
关键源码
1 |
|
关键特征:
- shellcode 位于固定地址
0x1337000,RWX 权限 - 所有通用寄存器在执行前被清零,除了
rax = 0x1337000(指向 shellcode 起始地址) - diet level 是所有读入字节的简单累加(
int类型) - diet level 写入
/diet-level(一个 FIFO pipe),评分系统从此读取
Solution
尝试 1:sendfile 方式(失败)
最初尝试用 sendfile(1, fd, NULL, 100) 直接将
/flag 内容发送到 stdout:
1 | BITS 64 |
可以正常执行(diet-level 正确输出),但 /flag
输出为空。可能是 nsjail 的 seccomp 过滤了 sendfile
系统调用。
尝试 2:read/write 轮询(超时)
1 | BITS 64 |
同样只输出 diet-level 和 "NOT YET SCORED",没有 flag 内容。
最终方案:直接弹 shell
当复杂 shellcode 不工作时,最可靠的方式是直接
execve("/bin/sh") 获取交互式 shell,然后手动探索。
1 | BITS 64 |
汇编后 23 bytes,sum=3031:
1 | nasm -f bin -o shell_shell.bin shell_shell.asm |
连接服务器,通过 PoW 验证,发送 shellcode,获得 shell:
1 | $ ncat --ssl shelldiet.ctfwithbirds.com 1337 |
Why sendfile / read Failed
/diet-level 是一个 FIFO
pipe(prw-r--r--),评分系统通过它异步读取 diet level。"NOT
YET SCORED" 消息来自 kCTF 基础设施,不是表示
/flag 不可用。flag 文件一直存在且可读。
sendfile 失败的可能原因: - nsjail 的 seccomp profile 未放行
SYS_sendfile (40) - FIFO 的读端阻塞导致某些 fd 操作异常