跳到主要内容

SUID 自定义二进制静态分析

靶场里异常 SUID 程序通常是本地提权入口。它们可能检查某些触发文件、调用系统命令、拼接路径、执行备份或隐藏硬编码密钥。分析时不必一开始就上反编译器,file + strings + objdump + strace/ltrace 往往足够恢复主线。

枚举异常 SUID

find / -perm -4000 -type f 2>/dev/null

重点关注:

  • 不属于常见系统组件的名字。
  • 位于 /usr/local/bin/opt/home 的 SUID。
  • 名称暗示 root、backup、reset、admin、check。

基础信息

ls -l /usr/bin/reset_root
file /usr/bin/reset_root
strings -a /usr/bin/reset_root | head -n 100

strings 里如果出现这些内容,基本就有方向:

RESETTING ROOT PASSWORD TO:
/usr/sbin/chpasswd
access
/tmp/...
/dev/shm/...

动态观察

strace -f -o /tmp/trace.txt /usr/bin/reset_root
rg -n 'access|open|execve|stat|chpasswd|/tmp|/dev/shm' /tmp/trace.txt

如果系统有 ltrace

ltrace -o /tmp/ltrace.txt /usr/bin/reset_root

动态观察能直接暴露文件检查、命令执行和库函数调用。

反汇编主函数

objdump -d -Mintel /usr/bin/reset_root | sed -n '/<main>:/,/^$/p'

继续定位可疑函数:

objdump -d -Mintel /usr/bin/reset_root | sed -n '/<magic_cipher>:/,/^$/p'

常见模式:

  • 硬编码字节数组。
  • 固定字符串作为 key。
  • 循环 XOR 解码。
  • 解码结果传给 access()stat()system()

XOR 解码模板

python3 - <<'PY'
key = b'palebluedot'
ct = bytes.fromhex('040909070e191008051d161c045d5c555e')
pt = bytes(c ^ key[i % len(key)] for i, c in enumerate(ct))
print(pt)
PY

如果第一层解出中间 key,再用它解路径:

python3 - <<'PY'
mid = b'thebluemarble1972'
cts = [
bytes.fromhex('5b0c001443060d004e192a0b3177700275'),
bytes.fromhex('5b0c001443060d004e28155b0767006207'),
bytes.fromhex('5b1c0812431e06205125071b00'),
]
for ct in cts:
print(bytes(c ^ mid[i % len(mid)] for i, c in enumerate(ct)))
PY

构造触发条件

如果程序检查文件是否存在:

touch /dev/shm/file1 /dev/shm/file2 /tmp/file3
/usr/bin/reset_root

执行后立即验证:

id
su - root

防坑点

  • SUID 程序运行时有效 UID 是 root,但环境变量可能被清理。
  • /tmp 可能有 nosuid,生成 SUID 副本时要看挂载选项。
  • strings 看不到所有内容,简单 XOR 或编码会隐藏路径。
  • strace 在某些 SUID 程序上可能受限制,静态分析仍要会。

防御建议

  • 避免自定义 SUID 程序,优先用最小 sudo 规则或专门服务。
  • SUID 程序不要调用 shell,不要使用相对路径,不要依赖可写目录触发条件。
  • 定期审计异常 SUID:find / -perm -4000 -type f
  • 对 SUID 程序做代码审计和完整性监控。

来源案例

  • The Planets: Earth/usr/bin/reset_root 是自定义 SUID 程序,静态分析恢复触发文件路径后可重置 root 密码。