(tr)uSDX bootloader corruption – a smoking gun – an experiment

At (tr)uSDX bootloader corruption – a smoking gun I proposed that the (tr)uSDX (trusdx) is vulnerable to users attempting to program the initial bootloader file using the (tr)uSDX USB port and its bootloader interface because without protection, that will attempt to overlay the bootloader while it is being executed and that is likely to corrupt the bootloader.

The (tr)uSDX bootloader code is proprietary, ie secret.

This article documents an experiment that demonstrates the vulnerability, and the effect of bootloader section protection.

Below are a series of verbose AVRDUDE logs of the operations to discover / demonstrate the outcomes.

Because this experiment is conducted on a 16MHz Nano and the bootloader uses a 20MHz clock, the bootloader port speed is adjusted to 92160. If this experiment was conducted on a real (tr)uSDX, use 115200.

Take note also of the clock rate issue raised at ISP programming of the (tr)uSDX.

Above, the test jig has a Nano with USB connection and ISP connection (Atmel AVRisp MkII).

Write the (tr)uSDX bootloader using an ISP programmer

Reading fuses...
>>>: avrdude -c avrispmkII -p m328p -P usb -b 115200 -B 0.5 -vv -U hfuse:r:-:h -U lfuse:r:-:h -U efuse:r:-:h 
SUCCESS: Read high fuse
SUCCESS: Read low fuse
SUCCESS: Read extended fuse
Reading lock bits...
>>>: avrdude -c avrispmkII -p m328p -P usb -b 115200 -B 0.5 -vv -U lock:r:-:h 
SUCCESS: Read lock bits
truSDX-initial_Bootloader.hex: 32,366 / 32,768 Bytes (98.77%)
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
>>>: avrdude -c avrispmkII -p m328p -P usb -b 115200 -B 0.5 -e -vv -U flash:w:"D:\project\trusdx\truSDX-initial_Bootloader.hex":i 

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "D:/Program Files (x86)/AVRDUDESS/avrdude.conf"

             Using Port                    : usb
             Using Programmer              : avrispmkII
             Overriding Baud Rate          : 115200
             Setting bit clk period        : 0.5
avrdude.exe: usbdev_open(): Found AVRISP mkII, serno: 001D2C990079
Using p = 0.50 us for SCK (param = 2)
avrdude.exe: Skipping parameter write; parameter value already set.
             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : STK500V2
             Description     : Atmel AVR ISP mkII
             Programmer Model: AVRISP mkII
             Hardware Version: 1
             Firmware Version Master : 1.24
             Vtarget         : 4.5 V
             SCK period      : 0.50 us

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | avrdude.exe: stk500isp_read_byte(.., signature, 0x0, ...)
avrdude.exe: stk500isp_read_byte(): Sending read memory command: avrdude.exe: stk500isp_read_byte(.., signature, 0x1, ...)
avrdude.exe: stk500isp_read_byte(): Sending read memory command: ################avrdude.exe: stk500isp_read_byte(.., signature, 0x2, ...)
avrdude.exe: stk500isp_read_byte(): Sending read memory command: ################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: erasing chip
avrdude.exe: reading input file "D:\project\trusdx\truSDX-initial_Bootloader.hex"
avrdude.exe: writing flash (32768 bytes):

Writing | ################################################## | 100% 1.97s

avrdude.exe: 32768 bytes of flash written
avrdude.exe: verifying flash memory against D:\project\trusdx\truSDX-initial_Bootloader.hex:
avrdude.exe: load data flash data from input file D:\project\trusdx\truSDX-initial_Bootloader.hex:
avrdude.exe: input file D:\project\trusdx\truSDX-initial_Bootloader.hex contains 32768 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 1.28s

avrdude.exe: verifying ...
avrdude.exe: 32768 bytes of flash verified

avrdude.exe done.  Thank you.

All good.

Write application firmware using the USB connection and bootloader

Reading fuses...
>>>: avrdude -c avrispmkII -p m328p -P usb -b 115200 -B 0.5 -vv -U hfuse:r:-:h -U lfuse:r:-:h -U efuse:r:-:h 
SUCCESS: Read high fuse
SUCCESS: Read low fuse
SUCCESS: Read extended fuse
Reading lock bits...
>>>: avrdude -c avrispmkII -p m328p -P usb -b 115200 -B 0.5 -vv -U lock:r:-:h 
SUCCESS: Read lock bits


>>>: avrdude -c arduino -p m328p -P COM33 -b 92160 -B 0.5 -e -vv -U flash:w:"D:\project\trusdx\truSDX_*_Firmware.hex":i 

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "D:/Program Files (x86)/AVRDUDESS/avrdude.conf"

             Using Port                    : COM33
             Using Programmer              : arduino
             Overriding Baud Rate          : 92160
             Setting bit clk period        : 0.5
avrdude.exe: Found device at port 'COM33'
avrdude.exe: serial_baud_lookup(): Using non-standard baud rate: 92160             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : Arduino
             Description     : Arduino
             Hardware Version: 3
             Firmware Version: 7.0

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: erasing chip
avrdude.exe: reading input file "D:\project\trusdx\truSDX_*_Firmware.hex"
avrdude.exe: writing flash (31828 bytes):

Writing | ################################################## | 100% 6.80s

avrdude.exe: 31828 bytes of flash written
avrdude.exe: verifying flash memory against D:\project\trusdx\truSDX_*_Firmware.hex:
avrdude.exe: load data flash data from input file D:\project\trusdx\truSDX_*_Firmware.hex:
avrdude.exe: input file D:\project\trusdx\truSDX_*_Firmware.hex contains 31828 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 4.72s

avrdude.exe: verifying ...
avrdude.exe: 31828 bytes of flash verified

avrdude.exe done.  Thank you.

All good.

Write the bootloader hex file using the USB connection and bootloader

>>>: avrdude -c arduino -p m328p -P COM33 -b 92160 -B 0.5 -e -vv -U flash:w:"D:\project\trusdx\truSDX-initial_Bootloader.hex":i 

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "D:/Program Files (x86)/AVRDUDESS/avrdude.conf"

             Using Port                    : COM33
             Using Programmer              : arduino
             Overriding Baud Rate          : 92160
             Setting bit clk period        : 0.5
avrdude.exe: Found device at port 'COM33'
avrdude.exe: serial_baud_lookup(): Using non-standard baud rate: 92160             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : Arduino
             Description     : Arduino
             Hardware Version: 3
             Firmware Version: 7.0

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: erasing chip
avrdude.exe: reading input file "D:\project\trusdx\truSDX-initial_Bootloader.hex"
avrdude.exe: writing flash (32768 bytes):

Writing | ################################################## | 100% 6.83s

avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding
avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding
avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding
avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding
avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding
avrdude.exe: ser_recv(): programmer is not responding
avrdude.exe: stk500_recv(): programmer is not responding

AVRDUDE killed

Fail: the bootloader which is executing has been corrupted by attempting to overwrite itself (probably most directly the associated flash page erase operation).

Write the bootloader hex file using the USB connection and bootloader with LOCK=0xCF

After reloading the bootloader using ISP…

>>>: avrdude -c arduino -p m328p -P COM33 -b 92160 -B 0.5 -e -vv -U flash:w:"D:\project\trusdx\truSDX-initial_Bootloader.hex":i 

avrdude.exe: Version 7.0
             Copyright (c) Brian Dean, http://www.bdmicro.com/
             Copyright (c) Joerg Wunsch

             System wide configuration file is "D:/Program Files (x86)/AVRDUDESS/avrdude.conf"

             Using Port                    : COM33
             Using Programmer              : arduino
             Overriding Baud Rate          : 92160
             Setting bit clk period        : 0.5
avrdude.exe: Found device at port 'COM33'
avrdude.exe: serial_baud_lookup(): Using non-standard baud rate: 92160             AVR Part                      : ATmega328P
             Chip Erase delay              : 9000 us
             PAGEL                         : PD7
             BS2                           : PC2
             RESET disposition             : dedicated
             RETRY pulse                   : SCK
             Serial program mode           : yes
             Parallel program mode         : yes
             Timeout                       : 200
             StabDelay                     : 100
             CmdexeDelay                   : 25
             SyncLoops                     : 32
             PollIndex                     : 3
             PollValue                     : 0x53
             Memory Detail                 :

                                               Block Poll               Page                       Polled
               Memory Type Alias    Mode Delay Size  Indx Paged  Size   Size #Pages MinW  MaxW   ReadBack
               ----------- -------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
               eeprom                 65    20     4    0 no       1024    4      0  3600  3600 0xff 0xff
               flash                  65     6   128    0 yes     32768  128    256  4500  4500 0xff 0xff
               lfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               hfuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               efuse                   0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               lock                    0     0     0    0 no          1    1      0  4500  4500 0x00 0x00
               calibration             0     0     0    0 no          1    1      0     0     0 0x00 0x00
               signature               0     0     0    0 no          3    1      0     0     0 0x00 0x00

             Programmer Type : Arduino
             Description     : Arduino
             Hardware Version: 3
             Firmware Version: 7.0

avrdude.exe: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude.exe: Device signature = 0x1e950f (probably m328p)
avrdude.exe: erasing chip
avrdude.exe: reading input file "D:\project\trusdx\truSDX-initial_Bootloader.hex"
avrdude.exe: writing flash (32768 bytes):

Writing | ################################################## | 100% 6.82s

avrdude.exe: 32768 bytes of flash written
avrdude.exe: verifying flash memory against D:\project\trusdx\truSDX-initial_Bootloader.hex:
avrdude.exe: load data flash data from input file D:\project\trusdx\truSDX-initial_Bootloader.hex:
avrdude.exe: input file D:\project\trusdx\truSDX-initial_Bootloader.hex contains 32768 bytes
avrdude.exe: reading on-chip flash data:

Reading | ################################################## | 100% 4.74s

avrdude.exe: verifying ...
avrdude.exe: 32768 bytes of flash verified

avrdude.exe done.  Thank you.

All good. AVRDUDE completes without corrupting the memory image of the running bootloader, and the verify test shows the bootloader is still functional after the attempted overwrite.

Be be aware that the reason it appears to work is that the attempts to overwrite the bootloader section were silently ignored, and the file verified ok against the originally written part of the image. If you were actually trying to update the bootloader section to a new version, this would not have written the changes and the verify would fail.

Forensics

Above is a file comparison of a read of flash after the corruption with that before the corruption, and it can be seen that the flash page (0x80 bytes) at 0x7f00 (which is within the bootloader section) has been erased preparatory to writing the new data. The bootloader was probably executing instructions in this region when the rug was pulled from under it!

A further comparison was made of the boot section after loading and after loading the application firmware, and it appears that the application writes to the boot section starting at 0x7ff6. If that is true, one might say that the system is designed to be vulnerable.

Summary

The (tr)uSDX bootloader will happily attempt to overwrite itself, and that is likely to result in corruption of the bootloader.

If you don’t attempt to load a file that writes to the bootloader section, no problem.

An easy thing for a novice, the confused or the fatigued to do is to attempt to write the intial bootloader file using the USB bootloader interface.

The bootloader can be restored ONLY using an ISP programmer (or the like).

The hardware contains protection features which are effective in preventing overwrite of the bootloader section… if they are enabled.

The (tr)uSDX may require an unprotected boot section for its operation… in other words, a designed in vulnerability.