
Trouver et exécuter automatiquement des attaques par injection de fautes
▄▖ ▜ ▗ ▄▖ ▘ ▗ ▘ ▄▖▘ ▌
▙▖▀▌▌▌▐ ▜▘ ▐ ▛▌ ▌█▌▛▘▜▘▌▛▌▛▌ ▙▖▌▛▌▛▌█▌▛▘
▌ █▌▙▌▐▖▐▖ ▟▖▌▌ ▌▙▖▙▖▐▖▌▙▌▌▌ ▌ ▌▌▌▙▌▙▖▌
▙▌
Ce dépôt constitue la partie logicielle de notre projet d'attaque par injection de défauts. Pour la partie matérielle, consultez ce dépôt.
Le but de ce projet est de trouver des instructions dans l'exécution d'un programme qui, lorsqu'elles sont sautées/NOPées, causent des problèmes de sécurité.
targets/tooling.py et un FPGA.Diagramme de flux pour le logiciel
Une présentation que nous avons donnée pour ce projet
Nous recherchons des problèmes de sécurité en effectuant une ou plusieurs des actions suivantes :
Pour injecter des défauts, nous avons choisi de faire du crowbar glitching. Cela a été réalisé en utilisant un FGPA avec un MOSFET canal N SI 2302. Voici un lien vers notre outillage FPGA. Plus d'informations peuvent être trouvées dans targets.
Pour les déclencheurs, nous avons choisi d'utiliser une entrée GPIO vers un FPGA. Dans le code de test, nous basculons une LED, bien que vous puissiez effectuer une analyse de puissance pour vos déclencheurs.
Les dépendances sont listées dans le fichier requirements.txt. Installez-les avec 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
Vérifie la sortie pour voir si nous avons atteint nos objectifs d'attaque.
python3 main.py ./binaries/aes_ecb.bin ./inputs/aes_ecb.bin -d 0x100045c -v -u outputs/aes_ecb
Teste le binaire aes_ecb pour sauter vers une fonction « inaccessible » personnalisée et stocke les entrées dans un répertoire.
python3 main.py ./binaries/aes_ecb.bin ./outputs/aes_ecb/solved_pc_188.bin -s 188
Exécute la simulation Unicorn pour ce cycle de défaut et cette entrée spécifiques. Dans ce cas, la sortie du contrôle du compteur programme.
Le code inclus dans binaries/sources est uniquement destiné aux tests. Il ne cible aucun matériel réel et sert strictement à tester l'outil.
Pour exécuter un binaire spécifique destiné à un périphérique, vous devez extraire la partie pertinente du binaire de manière à ne faire aucun appel aux périphériques en dehors des E/S simples. Par exemple, si votre binaire utilise l'UART, vous pouvez patcher le binaire en remplaçant les appels à l'UART par des appels aux stubs _read et _write trouvés dans binaries/stubs. De plus, les GPIO peuvent être remplacées par des appels à _trigger si souhaité. Pour exécuter votre code via l'outil, vous créerez un symbole main qui contient votre binaire patché, puis vous le lierez avec le code binaries/startup.s. Ainsi, l'outil pourra démarrer et exécuter votre binaire.
Pour un exemple spécifique, consultez le répertoire targets où nous montrons ce processus sur le TIMSPM0L2228.
Vous devez disposer du même compilateur de version et des mêmes indicateurs/étapes de compilation pour créer un binaire qui reflète le binaire s'exécutant sur la cible. Si vous créez vos propres programmes et les testez, cela convient. Mais si vous ne disposez que du code source de la cible que vous attaquez, il est peu probable que vous puissiez compiler jusqu'au binaire exact qui s'exécute. Il est donc recommandé d'utiliser le binaire exact s'exécutant sur votre cible chaque fois que possible.