Geeoon/Fault-Injection-Finder

GitHub: Geeoon/Fault-Injection-Finder

Geeoon/Fault-Injection-Finder是一款用于自动寻找二进制程序中潜在安全漏洞的故障注入工具。

Stars: 11 | Forks: 3

# 故障注入查找器 ``` ▄▖ ▜ ▗ ▄▖ ▘ ▗ ▘ ▄▖▘ ▌ ▙▖▀▌▌▌▐ ▜▘ ▐ ▛▌ ▌█▌▛▘▜▘▌▛▌▛▌ ▙▖▌▛▌▛▌█▌▛▘ ▌ █▌▙▌▐▖▐▖ ▟▖▌▌ ▌▙▖▙▖▐▖▌▙▌▌▌ ▌ ▌▌▌▙▌▙▖▌ ▙▌ ``` ### Geeoon Chung 和 Nate Snyder 这个仓库是我们故障注入攻击项目的软件部分。对于硬件部分,请查看[这个仓库](https://github.com/Ice-Skates/voltage_glitch). ## 整体项目 这个项目的目标是找到程序执行中的指令,当跳过/NOP时,会导致安全问题。 1. 预处理 1. 加载二进制文件 2. 识别当NOP时更有可能引起安全问题的指令。 2. Unicorn 模拟 1. 运行程序,NOP第n条指令。 2. 检查程序的输出,看是否发生了安全故障。 1. 如果发生了无效的读取,将程序的输入翻转所有位。 2. 重新运行程序。 3. 如果在另一个地址发生了无效的读取,请注意。这意味着程序的输入能够影响程序计数器(即,PC的控制)。 3. Angr SMT 求解 1. 如果Unicorn模拟表明控制了PC,则使用符号输入运行程序并跳过Unicorn步骤中的指令发行。 2. 看看我们最终是否将符号变量放入PC寄存器。 3. 求解自定义PC值,看看我们需要什么输入才能将PC移动到特定地址。 4. 如果可以求解,注意导致指定PC的输入。 4. 导出有趣的指令 5. 使用`targets/tooling.py`脚本和FPGA在目标上测试指令。 [软件流程图](https://raw.githubusercontent.com/Geeoon/Fault-Injection-Finder/refs/heads/main/470_FlowChart.png) [我们为此项目做的演示](https://github.com/Geeoon/Fault-Injection-Finder/blob/main/EE%20470%20Project%20Presentation.pdf) ## 详细信息 我们通过以下一种或多种方式来寻找安全问题: 1. 检查程序的IO输出 2. 检查程序的退出代码 3. 手动将故障触发器添加到代码的“不可达”部分 4. 执行污点检查,以查看程序计数器(PC)是否能够被修改 5. 使用angr(SMT求解器)求解导致用户指定PC值的输入 ## 故障注入 为了注入故障,我们选择了使用撬棍故障注入。这是通过使用带有SI 2302 N沟道MOSFET的FPGA实现的。[这里是我们FPGA工具的链接。](https://github.com/Ice-Skates/voltage_glitch) 更多信息可以在`targets`中找到。 ## 触发器 对于触发器,我们选择使用FPGA的GPIO输入。在测试代码中,我们切换一个LED,尽管你也可以进行功率分析来作为你的触发器。 ## 使用方法 ### 依赖项 依赖项列在`requirements.txt`中。使用`pip install -r requirements.txt`安装它们。 ``` usage: main.py [-h] [-s INDEX] [-i MAX_ITERATIONS] [-o EXPECTED_OUTPUT] [-e EXPECTED_EXIT] [-d DESIRED_PC] [-v] [-n] [-t TYPES] [-b BINARY_ADDR] [-u OUTPUT_DIR] [-f BEGIN_ADDR] [-g END_ADDR] binary_path input_path Automatically finds hardware security vulnerabilities in binaries. Only support ARM. positional arguments: binary_path The binary to examine input_path The path to the input to the program options: -h, --help show this help message and exit -s, --simulate INDEX Runs a Unicorn simulation with the fault at an nth instruction issue. Ignores all other flags besides --max_iterations and --verbose. -i, --max-iterations MAX_ITERATIONS The maximum number of instructions to run in the binary before ending early -o, --expected-output EXPECTED_OUTPUT The expected output of the program on a successful security incident -e, --expected-exit EXPECTED_EXIT The expected exit of the program on a successful security incident -d, --desired-pc DESIRED_PC The program counter we desire to achieve if possible. In hex or decimal. Keep in mind that this is the absolute address, not relative to the binary. -v, --verbose Verbosity: warning, info, debug -n, --no-thumb Whether or not to run in thumb mode -t, --types TYPES Which types of instructions to focus on. 0) Brute force: every issue. 1) Recommended defaults. 2) Only conditional branches. 3) Only compare/tests. 4) Only returns. 5) Only branches, calls, returns, and compares -b, --binary-addr BINARY_ADDR The address to flash the binary to. Defaults to 0x1000000. Can be in hex or decimal. -u, --output-dir OUTPUT_DIR The directory to store faults that were found. -f, --begin-addr BEGIN_ADDR The starting address of the instructions that should be considered for skipping. (inclusive.) If set, -g must also be set. -g, --end-addr END_ADDR The ending address of the instructions that should be considered for skipping. (inclusive.) If set, -f must also be set. ``` ### 示例用法 #### 输出检查 `python3 main.py ./binaries/sha256.bin ./inputs/sha256.bin -o ./expecteds/sha256.bin -v` 检查输出,看是否达到了我们的攻击目标。 #### 程序计数器控制 `python3 main.py ./binaries/aes_ecb.bin ./inputs/aes_ecb.bin -d 0x100045c -v -u outputs/aes_ecb` 测试aes_ecb二进制文件,跳转到自定义的“不可达”函数并将输入存储到目录中。 #### 在模拟中测试故障 `python3 main.py ./binaries/aes_ecb.bin ./outputs/aes_ecb/solved_pc_188.bin -s 188` 为此特定故障周期和输入运行Unicorn模拟。在这种情况下,程序计数器控制的结果。 ## 局限性 1. 目前,此程序仅支持ARM指令集。它支持Thumb和非Thumb模式。 2. 一些二进制文件对输入执行非常复杂的操作(如哈希),这会使SMT求解器变慢。 # 备注 ## 运行二进制文件 `binaries/sources`中包含的代码仅用于测试。它们不针对任何真实硬件,仅用于测试工具。 要针对设备运行特定二进制文件,您需要以不调用任何简单IO之外的外围设备的方式提取二进制文件的相关部分。例如,如果您的二进制文件使用UART,您可以通过替换对UART的调用为对`binaries/stubs`中找到的`_read`和`_write`存根的调用来修补二进制文件。此外,如果需要,可以使用对`_trigger`的调用替换GPIO。要通过工具运行您的代码,您将创建一个包含修补二进制文件的`main`符号,然后将其与`binaries/startup.s`代码链接。这样,工具将能够启动并运行您的二进制文件。 对于特定示例,请查看`targets`目录,我们展示了这个过程在TIMSPM0L2228上的应用。 ## 从源代码编译 您必须使用相同的编译器和相同的编译标志/步骤来创建反映目标上运行的二进制的二进制文件。如果您正在创建自己的程序并对其进行测试,这没问题。但是,如果您只有要攻击的目标的源代码,您可能无法编译到运行在目标上的确切二进制文件。因此,建议尽可能使用目标上运行的精确二进制文件。