Decoding the FVT ESC Firmware

I wanted to explore the configuration and firmware update protocol used by this electronic speed controller (ESC) for electric skateboards from Favourite (FVT) Electronics:

Favourite Sleeping Lion 120A ESC

Favourite 120A Sleeping Lion ESC for Electric Skateboards

Note that the same ESC is sold by Maytech with the MTES 120A SBEC name.

It uses a USB to UART adapter for connecting to the controller which is also used for configuring the popular LittleBee ESC for quadcopters:

SiLabs USB to UART Adapter for Programming Favourite (FVT) ESC

SiLabs USB to UART Adapter

The LittleBee ESC uses an open source BLHeli firmware which includes a bootloader with an UART based communications protocol at a fixed 19200 baud rate.

So I decided to capture the UART traffic to the ESC using the Saleae Logic 8 logic analyser during the following actions:

  • reading the ESC configuration (CSV log),
  • sending the configuration to ESC (CSV log), and
  • sending a firmware update (CSV log).

The CSV logs are also available on GitHub.

The XOR Skywalker

The firmware update log was the most interesting because I immediately noticed the #Skywalker20A# string in the plain UART traffic which means the firmware is sent completely decoded:

Bytes in UART Traffic During FVT Firmware Update

I used a bit of regex and hex-to-binary magic to extract the byte sequence from the UART traffic log:

$bin = array();
$fw = file_get_contents( $argv[1] );

// Extract byte strings from the CSV log.
preg_match_all( '#\((.*?)\)#', $fw, $bytes );

foreach ( $bytes[1] as $byte ) {
	$bin[] = hex2bin( substr( $byte, -2 ) );
}

file_put_contents(
	$argv[1] . '.bin',
	implode( '', $bin )
);

and compared it with the original firmware file E_SkateBoard_120A_170818_QuickStart.hgm from the FVT website:

ART Firmware Update Traffic

UART Bytes vs Firmware Bytes

All the 0x00 bytes in the UART traffic were clearly mapped to 0x68 in the firmware.

Having read plenty of firmware related articles on Hackaday I thought of trying to check for XOR obfuscation and with 0x68 mapping to 0x00 the XOR value is simply 0x68. Here is how to XOR all bytes of a file with PHP:

$xor = array();
$fw = file_get_contents( 'E_SkateBoard_120A_170818_QuickStart.hgm' );

for ( $i = 0; $i < mb_strlen( $fw ); $i++ ) {
	$xor[] = mb_substr($fw, $i, 1) ^ hex2bin( '68' );
}

file_put_contents(
	'E_SkateBoard_120A_170818_QuickStart.bin',
	implode( '', $xor )
);

And we get a decoded firmware file which has the #Skywalker20A# along with a BLHELI reference right at the very end:

FVT 120A 12S Firmware Binary

What’s Next

The Skywalker20A string is a reference to the ESC layout and the SiLabs C8051F310 MCU pin mapping for the BLHeli firmware. Using that as a starting point it is necessary to:

  1. Verify the version of BLHeli bootloader running on the FVT 120V ESC by looking at the boot message in the UART traffic.
  2. Check if the firmware update protocol matches the one in the bootloader.
  3. Check if the C8051F310 MCU can be programmed via the exposed C2 interface.
  4. Check if the pinout matches Skywalker20A or FVT_20A.

Leave a Reply