Part 2, Topic 3: Voltage Glitching to Dump Memory (MAIN)¶
NOTE: This lab references some (commercial) training material on ChipWhisperer.io. You can freely execute and use the lab per the open-source license (including using it in your own courses if you distribute similarly), but you must maintain notice about this source location. Consider joining our training course to enjoy the full experience.
SUMMARY: In the previous labs, we learned how voltage glitching can be used for a similar function as clock glitching. We also learned about how it has fewer limitations, but can be less reliable for certain target setups. It also changes a great deal based on the properties of the glitch circuit itself - even changing a wire can have a huge effect.
In this lab, we'll use what we learned in the last lab to again attack the vulnerable serial printing of the bootloader
LEARNING OUTCOMES:
- Applying previous glitch settings to new firmware
- Checking for success and failure when glitching
- Understanding how compiler optimizations can cause devices to behave in strange ways
The Situation¶
You should already know the situation from your previous attempts at glitching this bootloader (as well as what the flaw is). No need to do big long searches for parameters to try glitching at the beginning of the loop, just use values that worked well for the previous tutorial.
Be careful that you don't accidentally put the spot we're trying to glitch outside of glitch_spots
- if you used a repeat > 1, the actual spot being glitched might be at the end or in the middle of the repeat!
Like with the clock glitching version of this lab, we'll be using SimpleSerial V2 to speed up glitching
SCOPETYPE = 'OPENADC'
PLATFORM = 'CWLITEXMEGA'
SS_VER='SS_VER_2_1'
VERSION = 'HARDWARE'
CRYPTO_TARGET = 'TINYAES128C'
allowable_exceptions = None
%%bash -s "$PLATFORM" "$SS_VER"
cd ../../../firmware/mcu/bootloader-glitch
make PLATFORM=$1 CRYPTO_TARGET=NONE -j SS_VER=$2
SS_VER set to SS_VER_2_1
SS_VER set to SS_VER_2_1
avr-gcc (GCC) 5.4.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
mkdir -p objdir-CWLITEXMEGA
.
Welcome to another exciting ChipWhisperer target build!!
.
.
.
Compiling:
Compiling:
Compiling:
-en bootloader.c ...
-en decryption.c ...
-en .././simpleserial/simpleserial.c ...
.
.
Compiling:
Compiling:
.
-en .././hal//xmega/XMEGA_AES_driver.c ...
-en .././hal//xmega/uart.c ...
Compiling:
-e Done!
-en .././hal//xmega/usart_driver.c ...
.
-e Done!
Compiling:
-e Done!
-en .././hal//xmega/xmega_hal.c ...
-e Done!
-e Done!
-e Done!
-e Done!
.
LINKING:
-en bootloader-CWLITEXMEGA.elf ...
-e Done!
.
.
.
Creating load file for Flash: bootloader-CWLITEXMEGA.hex
Creating load file for Flash: bootloader-CWLITEXMEGA.bin
avr-objcopy -O ihex -R .eeprom -R .fuse -R .lock -R .signature bootloader-CWLITEXMEGA.elf bootloader-CWLITEXMEGA.hex
Creating load file for EEPROM: bootloader-CWLITEXMEGA.eep
avr-objcopy -O binary -R .eeprom -R .fuse -R .lock -R .signature bootloader-CWLITEXMEGA.elf bootloader-CWLITEXMEGA.bin
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 --no-change-warnings -O ihex bootloader-CWLITEXMEGA.elf bootloader-CWLITEXMEGA.eep || exit 0
.
.
Creating Extended Listing: bootloader-CWLITEXMEGA.lss
avr-objdump -h -S -z bootloader-CWLITEXMEGA.elf > bootloader-CWLITEXMEGA.lss
Creating Symbol Table: bootloader-CWLITEXMEGA.sym
avr-nm -n bootloader-CWLITEXMEGA.elf > bootloader-CWLITEXMEGA.sym
Size after:
text data bss dec hex filename
2414 124 202 2740 ab4 bootloader-CWLITEXMEGA.elf
+--------------------------------------------------------
+ Default target does full rebuild each time.
+ Specify buildtarget == allquick == to avoid full rebuild
+--------------------------------------------------------
+--------------------------------------------------------
+ Built for platform CW-Lite XMEGA with:
+ CRYPTO_TARGET = NONE
+ CRYPTO_OPTIONS = AES128C
+--------------------------------------------------------
#!/usr/bin/env python
# coding: utf-8
# In[ ]:
import chipwhisperer as cw
try:
if not scope.connectStatus:
scope.con()
except NameError:
scope = cw.scope(hw_location=(5, 4))
try:
if SS_VER == "SS_VER_2_1":
target_type = cw.targets.SimpleSerial2
elif SS_VER == "SS_VER_2_0":
raise OSError("SS_VER_2_0 is deprecated. Use SS_VER_2_1")
else:
target_type = cw.targets.SimpleSerial
except:
SS_VER="SS_VER_1_1"
target_type = cw.targets.SimpleSerial
try:
target = cw.target(scope, target_type)
except:
print("INFO: Caught exception on reconnecting to target - attempting to reconnect to scope first.")
print("INFO: This is a work-around when USB has died without Python knowing. Ignore errors above this line.")
scope = cw.scope(hw_location=(5, 4))
target = cw.target(scope, target_type)
print("INFO: Found ChipWhisperer😍")
# In[ ]:
if "STM" in PLATFORM or PLATFORM == "CWLITEARM" or PLATFORM == "CWNANO":
prog = cw.programmers.STM32FProgrammer
elif PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA":
prog = cw.programmers.XMEGAProgrammer
elif "neorv32" in PLATFORM.lower():
prog = cw.programmers.NEORV32Programmer
elif PLATFORM == "CW308_SAM4S" or PLATFORM == "CWHUSKY":
prog = cw.programmers.SAM4SProgrammer
else:
prog = None
# In[ ]:
import time
time.sleep(0.05)
scope.default_setup()
def reset_target(scope):
if PLATFORM == "CW303" or PLATFORM == "CWLITEXMEGA":
scope.io.pdic = 'low'
time.sleep(0.1)
scope.io.pdic = 'high_z' #XMEGA doesn't like pdic driven high
time.sleep(0.1) #xmega needs more startup time
elif "neorv32" in PLATFORM.lower():
raise IOError("Default iCE40 neorv32 build does not have external reset - reprogram device to reset")
elif PLATFORM == "CW308_SAM4S" or PLATFORM == "CWHUSKY":
scope.io.nrst = 'low'
time.sleep(0.25)
scope.io.nrst = 'high_z'
time.sleep(0.25)
else:
scope.io.nrst = 'low'
time.sleep(0.05)
scope.io.nrst = 'high_z'
time.sleep(0.05)
INFO: Found ChipWhisperer😍
scope.gain.mode changed from low to high scope.gain.gain changed from 0 to 30 scope.gain.db changed from 5.5 to 24.8359375 scope.adc.basic_mode changed from low to rising_edge scope.adc.samples changed from 24400 to 5000 scope.adc.trig_count changed from 10946674 to 22061823 scope.clock.adc_src changed from clkgen_x1 to clkgen_x4 scope.clock.adc_freq changed from 128000003 to 30842983 scope.clock.adc_rate changed from 128000003.0 to 30842983.0 scope.clock.clkgen_div changed from 1 to 26 scope.clock.clkgen_freq changed from 192000000.0 to 7384615.384615385 scope.io.tio1 changed from serial_tx to serial_rx scope.io.tio2 changed from serial_rx to serial_tx scope.io.hs2 changed from None to clkgen scope.io.tio_states changed from (1, 0, 0, 0) to (1, 1, 0, 0) scope.glitch.mmcm_locked changed from True to False
fw_path = "../../../firmware/mcu/bootloader-glitch/bootloader-{}.hex".format(PLATFORM)
cw.program_target(scope, prog, fw_path)
XMEGA Programming flash...
XMEGA Reading flash...
Verified flash OK, 2537 bytes
def reboot_flush():
reset_target(scope)
#Flush garbage too
target.flush()
scope.clock.adc_src = "clkgen_x1"
reboot_flush()
scope.adc.samples = 24000
Again, we're going to use a higher frequency on non-Husky ChipWhisperers. We'll also use the trigger length to get our ext_offset
range:
scope.clock.adc_src = "clkgen_x1"
def reboot_flush():
reset_target(scope)
#Flush garbage too
target.flush()
scope.clock.adc_src = "clkgen_x1"
reboot_flush()
scope.adc.samples = 24000
if PLATFORM == "CWLITEXMEGA":
scope.clock.clkgen_freq = 32E6
if SS_VER=='SS_VER_2_1':
target.baud = 230400*32/7.37
else:
target.baud = 38400*32/7.37
elif (PLATFORM == "CWLITEARM") or ("F3" in PLATFORM):
scope.clock.clkgen_freq = 24E6
if SS_VER=='SS_VER_2_1':
target.baud = 230400*24/7.37
else:
target.baud = 38400*24/7.37
reboot_flush()
scope.arm()
target.write("p516261276720736265747267206762206f686c207a76797821\n")
ret = scope.capture()
trig_count = scope.adc.trig_count
print(trig_count)
cw.plot(scope.get_last_trace())
1636