用Binary Ninja破解2000个CTF挑战:逆向工程与静态分析实战

本文详细介绍了如何利用Binary Ninja这一新兴静态分析平台,编写自动化脚本批量分析2000个DEFCON CTF资格赛二进制文件,并成功破解三个不同规模的挑战(334/666/1000个程序)。文章深入解析了逆向工程中的关键技术点,包括缓冲区溢出利用、金丝雀值绕过以及Binary Ninja的Python API实战技巧。

Binary Ninja如何加速CTF工作

今年的资格赛挑战重点是为网络大挑战(CGC)做准备。三分之一的挑战基于DECREE架构,部分需要CGC风格的"漏洞证明"利用。DEFCON CTF历史上首次放弃了攻防模式。

挑战#1:334个程序

第一个挑战334_cuts提供了334个DECREE二进制文件,所有文件名都与食物相关。每个挑战二进制文件都剥离了符号,具有静态堆栈缓冲区、金丝雀校验和基于堆栈的缓冲区溢出。金丝雀被复制到堆栈并与硬编码值进行比较。

通过Binary Ninja的无头分析引擎,我们编写Python脚本自动收集以下关键信息:

  1. 金丝雀字符串及其长度
  2. 要溢出的缓冲区大小
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
import binaryninja

bv = binaryninja.BinaryViewType["ELF"].open(chal)
bv.update_analysis()

# 获取金丝雀参数
canary_frame = main.get_parameter_at(bv.arch, memcmp.address, None, 0)
canary_address = main.get_parameter_at(bv.arch, memcmp.address, None, 1)
canary = bv.read(canary_address.value, canary_width.value)

# 计算缓冲区大小
buffer_size = (buffer_frame.offset - canary_frame.offset) * -1

最终构造的崩溃字符串需要:

  1. 用’a’填满缓冲区
  2. 附加金丝雀的前4字节
  3. 填充剩余的金丝雀缓冲区空间
  4. 覆盖保存的寄存器

成功提交10个崩溃字符串后获得第一个flag:baby's first crs cirvyudta

挑战#2:666个程序

与334个程序的挑战结构相同,使用相同脚本即可解决。获得flag:you think this is the real quaid DeifCokIj

挑战#3:1000个程序

同样方法处理1000个二进制文件,最终flag:do you want a thousand bandages gruanfir3

改进空间

Binary Ninja虽然表现出色,但仍需改进:

  1. 需要添加SSA(静态单赋值)形式
  2. 需要更灵活的类型系统
  3. 这些功能将有助于识别应用程序中的数据流、类型变化和堆栈槽重用

结论

从流畅的图形视图到中间语言,再到与Python的智能集成,Binary Ninja为静态二进制分析提供了出色的接口。它让我能够轻松快速地从2000个二进制文件中提取数据。

更大的启示是:我们可以通过工具增强能力,将机械效率与人类直觉相结合。事实上,这应该是我们的方向。如果我们完全依赖机器,我们不会变得更安全。相反,我们应该专注于构建能提高效率的工具,比如Binary Ninja。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计