如何防止 angr 花费数十小时和 GB 内存来解决(看似)简单的 CTF 问题

逆向工程 愤怒
2021-06-20 14:38:34

我最近正在研究一个(看似)简单的 CTF 挑战,其中输入是一个 base64 编码的文件,二进制文件将检查一个函数调用的正确性。问题是检查函数大约有 88k 个基本块长,但完全是线性的。因此,每个块将检查单个字节,如果不正确,将分支到一个较小的块,该块将调用退出函数。每个块中的操作很简单:

if(RANDOM_CONST0 == mem[i] ^ RANDOM_CONST1){
    goto next_basic_block;
}else{
    exiting_function()    //no return
}

每个基本块使用的常数不同。因此,它似乎是 angr 的绝佳目标!

尝试(使用call_state):

1)

  • 用途 SimulationManager.explore
  • 每一步后的丢弃avoiddeadended状态(使用step_func
  • 约 10 分钟后内存耗尽 (8GB)

2)

  • 用途 SimulationManager.step
  • 在每一步之后手动修剪“坏”状态(例如导致调用退出函数的状态)
  • 在每个块之后评估解决方案的单个字节
    • 将内存设置为具体值 0(用于减少内存)
  • 20 小时后仍然搅动(65k 字节的解决方案)
    • 此时显着放缓——大约 1 字节/3 秒
  • 用于SimulationManager.simplify减少每一步的内存开销

其他杂项:

  • 对符号内存绝对没有限制(包含解决方案)
  • 缓冲区约为 88k,仅对这么多内存的限制就消耗了大量 RAM

问题:

  • 为什么要占用这么多内存?
    • 唯一的符号寄存器是eax在每个基本块(因为它从存储器读取的符号字节),但它确实不复杂化合物与每个步骤(它被在下一基本块设置为另一符号值)
  • 为什么 angr 的速度如此之快?

我在这里为感兴趣的人上传了 CTF 二进制文件

在此处输入图片说明

0个回答
没有发现任何回复~