▄▖ ▜ ▗ ▄▖ ▘ ▗ ▘ ▄▖▘ ▌
▙▖▀▌▌▌▐ ▜▘ ▐ ▛▌ ▌█▌▛▘▜▘▌▛▌▛▌ ▙▖▌▛▌▛▌█▌▛▘
▌ █▌▙▌▐▖▐▖ ▟▖▌▌ ▌▙▖▙▖▐▖▌▙▌▌▌ ▌ ▌▌▌▙▌▙▖▌
▙▌
本仓库是我们故障注入攻击项目的软件部分。硬件部分请查看此仓库。
本项目旨在找出程序执行中被跳过/NOP 后会导致安全问题的指令。
targets/tooling.py 脚本和 FPGA 在目标上测试这些指令。我们通过以下一种或多种方式来搜索安全问题:
为了注入故障,我们选择了撬棍毛刺(crowbar glitching)方式。这是通过带有 SI 2302 N 沟道 MOSFET 的 FGPA 实现的。这里是我们的 FPGA 工具链接。 更多信息可以在 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 模拟。在本例中,输入来自程序计数器控制步骤的输出。
binaries/sources 中包含的代码仅用于测试。它们不针对任何真实硬件,严格用于测试该工具。
要在特定设备上运行某个二进制文件,你需要以不调用简单 IO 之外的外设的方式提取二进制文件的相关部分。例如,如果你的二进制文件使用 UART,你可以将 UART 调用替换为对 binaries/stubs 中 _read 和 _write 桩函数的调用来修补该二进制文件。此外,如果需要,还可以将 GPIO 替换为对 _trigger 的调用。要使用该工具运行你的代码,你需要创建一个包含已修补二进制文件的 main 符号,然后将其与 binaries/startup.s 代码链接。这样,该工具就能启动并运行你的二进制文件。
有关具体示例,请查看 targets 目录,我们在其中演示了在 TIMSPM0L2228 上的这一过程。
你必须使用相同版本的编译器以及相同的编译标志/步骤,才能生成与目标上运行的二进制文件一致的二进制文件。如果你是在创建自己的程序并对其进行测试,这没有问题。但如果你只有所攻击目标的源代码,那么很可能无法编译出与正在运行的二进制文件完全一致的版本。因此,建议尽可能使用目标上实际运行的二进制文件。