Added Level 1 STM32F103 CTF Solutions
1 parent 673e039 commit 457bc6705afa5aeab8ef832243017ddc61b0019b
root authored on 3 May
Showing 8 changed files
View
7
FaultInjection/examples/CuriousBolt/Level-1/Chall-4-Firmware/Makefile 0 → 100644
all:
arm-none-eabi-gcc -o test.o -c test.S -mthumb -mcpu=cortex-m3 -g3
arm-none-eabi-gcc -o main.o -c main.c -mthumb -mcpu=cortex-m3 -Os -g3
arm-none-eabi-gcc -o memset.o -c memset.c -mthumb -mcpu=cortex-m3 -Os -g3
arm-none-eabi-gcc -o sram.elf test.o main.o memset.o -nostartfiles -nostdlib -Tram.ld -mcpu=cortex-m3 -mthumb -g3
arm-none-eabi-objcopy -O binary sram.elf shellcode-0xRoM.bin
View
324
FaultInjection/examples/CuriousBolt/Level-1/Chall-4-Firmware/main.c 0 → 100644
#include <stdint.h>
uint32_t volatile * const rccApb2 = (uint32_t *) 0x40021018u;
uint32_t volatile * const ioAModerH = (uint32_t *) 0x40010804u;
uint32_t volatile * const uart1Ctrl = (uint32_t *) 0x40013800u;
 
void readChar( uint8_t const chr );
void writeByte( uint8_t b );
void writeStr( uint8_t const * const str );
void writeChar( uint8_t const chr );
void writeWordLe( uint32_t const word );
void writeWordBe( uint32_t const word );
void readCmd( uint8_t const * const cmd);
uint32_t hexToInt(uint8_t const * const hex);
void readMem(uint32_t const addr, uint32_t const len);
void writeMem(uint32_t const addr, uint32_t const data);
 
uint8_t const strHelp[] = "Help\r\n-----------\r\n"
"ADDR, VAL, LEN: 32-bit Hex encoded:\r\n e.g., 0A1337FF\r\n"
"-----------\r\n"
"R ADDR LEN - Read 32-bit word\r\n"
"W ADDR VAL - Write 32-bit word\r\n"
"D - Dump all flash memory\r\n"
"P - Jump into chall4 function\r\n"
"S - Reboot\r\n"
"E - Exit\r\n"
"H - Show help \r\n"
"---------------\r\n";
 
int main(void)
{
/* IOA + USART1 clock enable */
*rccApb2 = (uint32_t) 0x4004u;
 
/* USART1 TX+RX (PA9, PX10) on */
*ioAModerH = (uint32_t) 0x444444B4u;
 
/* config and enable uart */
uart1Ctrl[2] = 0x00000341u;
uart1Ctrl[3] = 0x0000200Cu;
writeStr("\r\n##############################\r\n"
"# Low-Level Shell v.0xRoM #\r\n"
"# CPU-ID: 0x");
uint32_t cpuid = *((uint32_t *) 0xe000ed00);
writeWordBe(cpuid);
writeStr( " #\r\n");
writeStr("##############################\r\n\r\n");
writeStr("> ");
 
while (1)
{
if ((uart1Ctrl[0] & 0x80u) && (0))
{
uart1Ctrl[1] = 0x33u;
}
 
if (uart1Ctrl[0] & 0x20u)
{
uint32_t data = uart1Ctrl[1];
readChar((uint8_t) data);
}
}
}
 
/* hex must have length 8 */
uint32_t hexToInt(uint8_t const * const hex)
{
uint32_t ind = 0u;
uint32_t res = 0u;
 
for (ind = 0; ind < 8; ++ind)
{
uint8_t chr = hex[ind];
uint32_t val = 0u;
 
res <<= 4u;
 
if ((chr >= '0') && (chr <= '9'))
{
val = chr - '0';
}
else if ((chr >= 'a') && (chr <= 'f'))
{
val = chr - 'a' + 0x0a;
}
else if ((chr >= 'A') && (chr <= 'F'))
{
val = chr - 'A' + 0x0a;
}
else
{
val = 0u;
}
res |= val;
}
 
return res;
}
 
void readChar( uint8_t const chr )
{
#define CMDBUF_LEN (64u)
static uint8_t cmdbuf[CMDBUF_LEN] = {0u};
static uint32_t cmdInd = 0u;
 
switch (chr)
{
case '\n':
case '\r':
cmdbuf[cmdInd] = 0u;
if (cmdInd != 0)
{
writeStr("\r\n");
}
readCmd(cmdbuf);
cmdInd = 0u;
writeStr("\r\n> ");
{
uint32_t ind = 0u;
for (ind = 0; ind<CMDBUF_LEN; ++ind)
{
cmdbuf[ind]=0x00u;
}
}
break;
 
case 8:
case 255:
case 127: /* TODO backspace */
if (cmdInd > 0u)
--cmdInd;
writeChar(chr);
break;
 
default:
if (cmdInd < (CMDBUF_LEN - 1))
{
cmdbuf[cmdInd] = chr;
++cmdInd;
writeChar(chr);
}
break;
}
}
 
void readCmd( uint8_t const * const cmd )
{
void (*chall4)(void) = (void (*)(void))0x08000ba9;
switch (cmd[0])
{
case 0:
return;
break;
 
/* chall4 function */
case 'p':
case 'P':
writeStr("time to change baudrate to 115200\r\n");
for (volatile uint32_t i = 0; i < 5000000; i++); // Crude delay
chall4();
break;
 
/* read 32-bit command */
case 'r':
case 'R':
/* r 08000000 00000100 */
readMem(hexToInt(&cmd[2]), hexToInt(&cmd[11]));
break;
 
/* write 32-bit command */
case 'w':
case 'W':
/* w 20000000 12345678 */
writeMem(hexToInt(&cmd[2]), hexToInt(&cmd[11]));
break;
 
/* Dump all flash */
case 'd':
case 'D':
writeStr("\r\n\r\n");
{
uint32_t const * addr = (uint32_t*) 0x08000000;
uint32_t br = 8u;
while (((uintptr_t) addr) < (0x08000000 + 64u * 1024u))
{
if (br == 8u)
{
writeStr("\r\n[");
writeWordBe((uint32_t) addr);
writeStr("]: ");
br = 0u;
}
 
writeWordBe(*addr);
writeChar(' ');
++addr;
++br;
}
}
writeStr("\r\n\r\n");
break;
 
/* Help command */
case 'h':
case 'H':
writeStr(strHelp);
break;
 
/* Reboot */
case 's':
case 'S':
writeStr("Rebooting...\r\n\r\n");
*((uint32_t *) 0xE000ED0C) = 0x05FA0004u;
break;
 
/* exit */
case 'e':
case 'E':
writeStr("Bye.\r\n");
while (1)
{
__asm__ volatile("wfi");
}
break;
 
 
default:
writeStr("Unknown command: ");
writeStr(cmd);
writeStr("\r\n");
break;
}
}
const uint8_t txtMap[] = "0123456789ABCDEF";
 
void writeByte( uint8_t b )
{
writeChar(txtMap[b >> 4]);
writeChar(txtMap[b & 0x0F]);
}
 
 
void writeStr( uint8_t const * const str )
{
uint32_t ind = 0u;
 
while (str[ind])
{
writeChar(str[ind]);
++ind;
}
}
 
void writeChar( uint8_t const chr )
{
while (!(uart1Ctrl[0] & 0x80u))
{
/* wait */
}
 
uart1Ctrl[1] = chr;
}
 
void writeWordLe( uint32_t const word )
{
writeByte((word & 0x000000FF));
writeByte((word & 0x0000FF00) >> 8);
writeByte((word & 0x00FF0000) >> 16);
writeByte((word & 0xFF000000) >> 24);
}
 
void writeWordBe( uint32_t const word )
{
writeByte((word & 0xFF000000) >> 24);
writeByte((word & 0x00FF0000) >> 16);
writeByte((word & 0x0000FF00) >> 8);
writeByte((word & 0x000000FF));
 
}
 
void alertCrash( uint32_t crashId )
{
writeStr("!!! EXCEPTION !!!\r\nID: ");
writeByte(crashId);
writeStr("\r\nRestart required!\r\n\r\n");
*((uint32_t *) 0xE000ED0C) = 0x05FA0004u;
while (1);
}
 
void readMem(uint32_t const addr, uint32_t const len)
{
uint32_t it = 0u;
uint32_t addrx = 0u;
uint32_t lenx = 0u;
 
lenx = len;
if (lenx == 0u)
{
lenx = 4u;
}
 
for (it = 0u; it < (lenx / 4u); ++it)
{
addrx = addr + it*4u;
writeStr("Read [");
writeWordBe(addrx);
writeStr("]: ");
writeWordBe(*((uint32_t*)addrx));
writeStr("\r\n");
}
}
 
void writeMem(uint32_t const addr, uint32_t const data)
{
writeStr("Write [");
writeWordBe(addr);
writeStr("]: ");
writeWordBe(data);
*((uint32_t*) addr) = data;
writeStr("\r\n");
}
 
View
20
FaultInjection/examples/CuriousBolt/Level-1/Chall-4-Firmware/memset.c 0 → 100644
// memset.c
void *memset(void *dest, int val, unsigned int len) {
unsigned char *ptr = dest;
unsigned int value = (unsigned char)val; // Promote to avoid unnecessary casting
 
// Use a word-by-word copy if possible
while (len >= 4) {
*(unsigned int*)ptr = value | (value << 8) | (value << 16) | (value << 24);
ptr += 4;
len -= 4;
}
 
// If any bytes are left, fill them
while (len--) {
*ptr++ = (unsigned char)value;
}
 
return dest;
}
View
FaultInjection/examples/CuriousBolt/Level-1/Chall-4_Shellcode-0xRoM.bin 0 → 100644
Not supported
View
54
FaultInjection/examples/CuriousBolt/Level-1/ConfigChall02.py 0 → 100644
######
# config to complete Level 1, Challenge 2 using "glitch-o-bolt"
######
# LEAVE THESE IMPORTS!
######
import functions
import random
from textual.widgets import Log
 
######
# config values
######
 
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 115200
 
LENGTH = 42
REPEAT = 1
DELAY = 0
 
###
# ^ = pullup, v = pulldown
###
triggers = [
['-', False], #0
['-', False], #1
['-', False], #2
['-', False], #3
['-', False], #4
['-', False], #5
['-', False], #6
['-', False], #7
]
 
###
# name, enabled, string to match in output, function to run
# if string is blank ("") doesnt show toggle, just run button
###
conditions = [
["Flag", True, "ctf", "stop_glitching"],
["Chal2", True, "Hold one of", "start_chal_02"] # requires bolt output gpio pin 0 -> challenge board chall 2 button
]
 
######
# Custom functions for conditions to trigger
######
 
def stop_glitching():
elapsed = functions.get_glitch_elapsed()
functions.glitching_switch(False)
functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})")
 
def start_chal_02():
functions.run_output_high(0, 30000000) ## can also run_output_low() if need too
View
50
FaultInjection/examples/CuriousBolt/Level-1/ConfigChall03.py 0 → 100644
######
# config to complete Level 1, Challenge 3 using "glitch-o-bolt"
######
# LEAVE THESE IMPORTS!
######
import functions
import random
from textual.widgets import Log
 
######
# config values
######
 
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 115200
 
LENGTH = 6000
REPEAT = 0
DELAY = 1098144
 
###
# ^ = pullup, v = pulldown
###
triggers = [
['-', False], #0
['v', True], #1
['-', False], #2
['-', False], #3
['-', False], #4
['-', False], #5
['-', False], #6
['-', False], #7
]
 
###
# name, enabled, string to match
###
conditions = [
['Flag', True, 'ctf', 'stop_glitching'],
]
 
######
# Custom functions for conditions to trigger
######
 
def stop_glitching():
elapsed = functions.get_glitch_elapsed()
functions.glitching_switch(False)
functions.add_text(f"[auto] glitching stopped (elapsed: {elapsed})")
View
95
FaultInjection/examples/CuriousBolt/Level-1/ConfigChall04.py 0 → 100644
######
# config to complete Level 1, Challenge 4 using "glitch-o-bolt"
######
# LEAVE THESE IMPORTS!
######
import time
import functions
 
from pyocd.core.helpers import ConnectHelper
from pyocd.flash.file_programmer import FileProgrammer
 
######
# config values
######
 
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 115200
 
LENGTH = 50
REPEAT = 1
DELAY = 1
 
###
# name, enabled, string to match
###
conditions = [
['Start', False, '', 'start_chall_04'],
['Step1', False, '', 'step_1'],
['Step2', False, '', 'step_2'],
]
 
######
# Custom functions for conditions to trigger
######
 
def start_chall_04():
functions.add_text(f"[Chall 4] enable uart switch then hold chall 4 button to load the challenge into memory.")
functions.add_text(f"[Chall 4] once loaded hold 'boot 1' button and press 'reset' button to put in bootloader mode")
functions.add_text(f"[Chall 4] then press 'Step1'")
 
def step_1():
functions.set_uart_switch(False)
 
functions.add_text(f"\n[Chall 4] uploading firmware to ram... please wait")
 
# Connect to the target board
session = ConnectHelper.session_with_chosen_probe()
session.open()
 
# Optionally halt the target
target = session.target
target.halt()
 
# Load binary file to specified address (e.g., 0x20000000)
newFirmware = "/tmp/f103-analysis/h3/rootshell/shellcode-0xRoM.bin"
programmer = FileProgrammer(session)
programmer.program(newFirmware, base_address=0x20000000, file_format='bin')
 
# Optionally resume execution
target.resume()
# Clean up
session.close()
 
with open(newFirmware, "rb") as f:
original_data = f.read()
 
# Connect to the target
session = ConnectHelper.session_with_chosen_probe()
session.open()
 
target = session.target
target.halt()
 
# Read back the memory from the target
read_data = target.read_memory_block8(0x20000000, len(original_data))
 
# Compare
if bytes(read_data) == original_data:
functions.add_text(f"[+] Shellcode loaded successfully.")
else:
functions.add_text(f"[!] Mismatch detected. Shellcode may not have loaded correctly.")
 
session.close()
 
functions.change_baudrate(9600)
functions.add_text(f"[Chall 4] hold buttons 'boot0' and 'boot1' and press the 'glitch' button")
functions.add_text(f"[Chall 4] this single glitch will boot from SRAM")
functions.add_text(f"[Chall 4] enable UART to access 'Low-level Shell' (might need to press reset)")
functions.add_text(f"[Chall 4] then press 'Step2'")
def step_2():
functions.send_uart_message("p")
time.sleep(1)
functions.change_baudrate(115200)
View
FaultInjection/examples/CuriousBolt/Level-1/glitch-o-matic.py 0 → 100644
Buy Me A Coffee