问题背景
在渗透测试中,测试目标程序的栈缓冲区溢出漏洞时,需要构造大量字符(如 3000+ 个 A)作为输入,观察程序是否会崩溃或触发保护机制。
但有些精简的嵌入式系统(BusyBox、纯 Shell 环境)没有安装 python 或 perl,无法用简单的方式生成测试数据:
# 这些命令在精简系统上不存在
python3 -c "print(A*3000)"
perl -e "print Ax3000"
解决方案
方法一:dd + tr(最推荐)
这是最通用的方法,dd 和 tr 是 POSIX 标准命令,几乎所有 Linux 系统都有。
dd if=/dev/zero bs=3000 count=1 2>/dev/null | tr "\0" "A"
参数解读:
dd if=/dev/zero– 从零设备读取字节bs=3000– 每次读写 3000 字节count=1– 只读取 1 次tr \0 A– 把所有零字符转换为 A
方法二:纯 Shell 循环
如果系统没有 tr 命令,可以用 Shell 内置循环:
i=0
while [ $i -lt 2000 ]; do
printf "A"
i=$((i+1))
done
方法三:bash 大括号扩展
注意:ash/dash 等精简 shell 不支持此语法
printf A%.0s {1..3000}
实际测试案例
场景:测试程序是否有栈保护(Canary)
目标:检查 /bin/busybox 是否有栈溢出保护
步骤 1:生成超长字符串
PAYLOAD=$(dd if=/dev/zero bs=5000 count=1 2>/dev/null | tr "\0" "A")
echo "Payload 长度: ${#PAYLOAD}"
步骤 2:执行测试
# 方法1:作为命令行参数传入
./busybox "$PAYLOAD"
# 方法2:通过管道传入
echo "$PAYLOAD" | ./busybox
步骤 3:判断结果
| 输出结果 | 结论 |
|---|---|
| *** stack smashing detected *** | ✅ 有栈保护 (Canary) |
| *** stack protector aborted *** | ✅ 有栈保护 |
| Segmentation fault (core dumped) | ❌ 无栈保护,存在漏洞 |
| 程序正常运行 | 参数未触发溢出,尝试增加长度 |
场景:测试命令注入过滤
测试目标程序是否对超长输入做了长度限制:
PAYLOAD=$(dd if=/dev/zero bs=10000 count=1 2>/dev/null | tr "\0" "A")
./vulnerable_program "$PAYLOAD"
观察输出:
- 被截断 → 可能有长度过滤
- 完整输出 → 可能存在溢出
完整检测脚本
#!/bin/sh
# 二进制栈保护检测脚本 - 适用于无 python/perl 的精简系统
TARGET=${1:-"./test_program"}
echo "=== 栈溢出测试 ==="
echo "目标: $TARGET"
# 生成 5000 个字符的测试数据
PAYLOAD=$(dd if=/dev/zero bs=5000 count=1 2>/dev/null | tr "\0" "A")
echo "测试 payload 长度: ${#PAYLOAD}"
# 执行并捕获输出
OUTPUT=$(timeout 2 "$TARGET" "$PAYLOAD" 2>&1)
RESULT=$?
echo "执行结果码: $RESULT"
# 分析输出
if echo "$OUTPUT" | grep -q "stack smashing"; then
echo "✅ 结果: 程序有栈保护 (Canary enabled)"
echo " 攻击者需先绕过 Canary 才能利用溢出"
exit 0
elif echo "$OUTPUT" | grep -qi "segmentation fault"; then
echo "❌ 结果: 程序无栈保护 (No Canary)"
echo " 存在栈溢出漏洞,可尝试提权"
exit 1
elif [ $RESULT -eq 139 ] || [ $RESULT -eq 136 ]; then
echo "❌ 结果: 程序崩溃 (信号 $RESULT)"
echo " 可能存在漏洞,需进一步分析"
exit 1
else
echo "⚠️ 结果: 未触发崩溃"
echo " 尝试增加 payload 长度 (修改 bs=5000 为 bs=10000)"
fi
使用方法:
chmod +x test_canary.sh
./test_canary.sh /path/to/target_binary
常见问题
Q: 生成多长的字符串合适?
A: 从 1000 开始,如果没触发溢出,逐步增加到 5000、10000。不同漏洞触发所需长度不同。
Q: 除了 A 还能用什么字符?
A:
- 测试英文程序:用 A 或 x
- 测试中文处理:用中文测试时注意编码
- 测试特殊字符:用 printf 生成换行符、制表符等
Q: 程序崩溃但没有明显输出?
A: 使用 $? 查看退出码,139 通常表示段错误 (Segmentation Fault)。
总结:渗透测试中测试栈溢出时,精简系统没有 python 用 dd + tr 组合是最可靠的方法。生成超长字符串后执行目标程序,观察是否触发 stack smashing 来判断是否存在漏洞。
核心命令:
dd if=/dev/zero bs=5000 count=1 2>/dev/null | tr "\0" "A"
0