用Binary Ninja实现2000次精准漏洞挖掘:CTF挑战中的静态分析突破

本文详细介绍了如何利用Binary Ninja这一新型静态分析平台,通过Python脚本自动化分析2000个DEFCON CTF二进制文件,精准提取金丝雀值和缓冲区尺寸,实现大规模漏洞利用的突破性方法。

2000次Binary Ninja精准切割 - Trail of Bits博客

Binary Ninja如何加速CTF工作

今年的资格赛挑战重点围绕网络大挑战(CGC)准备参赛者。整整三分之一的挑战基于DECREE架构,多个挑战要求CGC风格的"漏洞证明"利用。今年决赛将基于DECREE,使得获胜的CGC机器人能够与人类选手"对战"。DEFCON CTF在其历史上首次放弃了攻防模式。

挑战一:334次切割

第一个挑战334 cuts没有提供太多方向指引。我首先连接挑战服务:

1
$ nc 334_cuts_22ffeb97cf4f6ddb1802bf64c03e2aab.quals.shallweplayaga.me 10334

服务要求发送base64编码的崩溃字符串。解压tarball后发现334个DECREE挑战二进制文件,全部采用食物相关命名。

Binary Ninja分析流程

每个挑战二进制文件都被剥离符号,包含静态栈缓冲区、金丝雀保护和基于栈的缓冲区溢出。金丝雀被复制到栈中并与硬编码值进行比对。所有334个挑战仅在四个方面存在差异:

  • 溢出缓冲区的大小
  • 金丝雀字符串及其长度
  • recvmsg函数中的栈缓冲区大小
  • writemsg函数在每次写入循环迭代中处理的数据量

自动化信息收集

通过Python脚本导入binaryninja并创建二进制视图:

1
2
3
import binaryninja
bv = binaryninja.BinaryViewType["ELF"].open(chal)
bv.update_analysis()

通过程序入口点定位main函数,使用LowLevelIL分析调用指令。通过get_parameter_at()函数查询memcmp调用的参数,提取金丝雀值和缓冲区大小:

1
2
canary = bv.read(canary_address.value, canary_width.value)
buffer_size = (buffer_frame.offset - canary_frame.offset) * -1

构建崩溃字符串

1
2
3
4
crash_string = "a" * buffer_size
crash_string += canary[:4]
crash_string += "a" * ((canary_frame.offset * -1) - 4)
crash_string += 'eeee' + '\n'

该脚本成功处理334个挑战后获得第一个flag。

挑战二:666次切割

采用相同方法处理666个挑战二进制文件,修改脚本连接新服务后获得第二个flag。

挑战三:1000次切割

使用相同脚本处理1000个挑战后获得最终flag。

改进空间

Binary Ninja显示出巨大潜力,但仍需完善。未来版本希望增加SSA和灵活的类型系统。SSA的加入将更容易识别应用程序中的数据流,判断类型变化时间,以及确定栈槽重用情况。

结论

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

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

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