
Automatisch Fault-Injection-Angriffe finden und ausführen
▄▖ ▜ ▗ ▄▖ ▘ ▗ ▘ ▄▖▘ ▌
▙▖▀▌▌▌▐ ▜▘ ▐ ▛▌ ▌█▌▛▘▜▘▌▛▌▛▌ ▙▖▌▛▌▛▌█▌▛▘
▌ █▌▙▌▐▖▐▖ ▟▖▌▌ ▌▙▖▙▖▐▖▌▙▌▌▌ ▌ ▌▌▌▙▌▙▖▌
▙▌
Dieses Repository ist die Softwareseite unseres Fault-Injection-Angriffsprojekts. Für die Hardwareseite schau dir dieses Repo an.
Das Ziel dieses Projekts ist es, Anweisungen in der Ausführung eines Programms zu finden, die, wenn sie übersprungen/NOP'd werden, Sicherheitsprobleme verursachen.
targets/tooling.py und einem FPGA testen.Flussdiagramm für die Software
Eine Präsentation, die wir für dieses Projekt gehalten haben
Wir suchen nach Sicherheitsproblemen, indem wir eine oder mehrere der folgenden Methoden anwenden:
Um Fehler zu injizieren, haben wir uns für Crowbar-Glitching entschieden. Dies wurde mit einem FPGA und einem N-Kanal-MOSFET SI 2302 erreicht. Hier ist ein Link zu unserem FPGA-Tooling. Weitere Informationen findest du in targets.
Für Trigger haben wir uns für eine GPIO-Eingabe an ein FPGA entschieden. Im Testcode schalten wir eine LED um, du könntest jedoch auch eine Leistungsanalyse für deine Trigger durchführen.
Die Abhängigkeiten sind in der requirements.txt aufgelistet. Installiere sie mit 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
Überprüft die Ausgabe, um festzustellen, ob wir unsere Angriffsziele erreicht haben.
python3 main.py ./binaries/aes_ecb.bin ./inputs/aes_ecb.bin -d 0x100045c -v -u outputs/aes_ecb
Testet das aes_ecb-Binary, um zu einer benutzerdefinierten "unerreichbaren" Funktion zu springen, und speichert die Eingaben in einem Verzeichnis.
python3 main.py ./binaries/aes_ecb.bin ./outputs/aes_ecb/solved_pc_188.bin -s 188
Führe die Unicorn-Simulation für diesen spezifischen Glitch-Zyklus und diese Eingabe aus. In diesem Fall die Ausgabe aus der Programmzähler-Kontrolle.
Der in binaries/sources enthaltene Code dient nur zu Testzwecken. Er zielt nicht auf echte Hardware ab und dient ausschließlich zum Testen des Tools.
Um ein bestimmtes Binary für ein Gerät auszuführen, musst du den relevanten Teil des Binaries so extrahieren, dass keine Aufrufe an Peripheriegeräte außerhalb einfacher IO erfolgen. Wenn dein Binary beispielsweise UART verwendet, kannst du das Binary patchen, indem du UART-Aufrufe durch Aufrufe der _read- und _write-Stubs ersetzt, die sich in binaries/stubs befinden. Zusätzlich kann GPIO bei Bedarf durch Aufrufe von _trigger ersetzt werden. Um deinen Code mit dem Tool auszuführen, erstellst du ein main-Symbol, das dein gepatchtes Binary enthält, und linkst es anschließend mit dem binaries/startup.s-Code. Auf diese Weise kann das Tool dein Binary starten und ausführen.
Ein konkretes Beispiel findest du im Verzeichnis targets, in dem wir diesen Prozess anhand des TIMSPM0L2228 zeigen.
Du musst denselben Compiler in derselben Version sowie dieselben Compiler-Flags/Schritte verwenden, um ein Binary zu erstellen, das dem auf dem Zielgerät ausgeführten Binary entspricht. Wenn du deine eigenen Programme erstellst und testest, ist das in Ordnung. Wenn du jedoch nur den Quellcode des Zielgeräts hast, das du angreifst, wirst du wahrscheinlich nicht in der Lage sein, das exakt ausgeführte Binary zu kompilieren. Daher wird empfohlen, wann immer möglich das exakte Binary zu verwenden, das auf deinem Zielgerät läuft.