---
title: Decoding the FVT ESC Firmware
date: 2017-08-30T08:37:03+00:00
modified: 2017-08-30T08:37:03+00:00
image:: https://kaspars.net/wp-content/uploads/2017/08/fvt-uart-traffic-vs-firmware.png
permalink: https://kaspars.net/blog/fvt-firmware
post_type: post
author:
  name: Kaspars
  avatar: https://reverse.kaspars.net/gravatar/avatar/92bfcd3a8c3a21a033a6484d32c25a40b113ec6891f674336081513d5c98ef76?s=96&d=mm&r=g
post_tag:
  - Electric Skateboard
  - Open Source
category:
  - Electronics
---

# 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](http://szfvt.com):

[![Favourite Sleeping Lion 120A ESC](https://kaspars.net/wp-content/uploads/2017/08/fvt-sleeping-lion-esc.jpg?strip=all&quality=90&resize=800,600)](https://kaspars.net/wp-content/uploads/2017/08/fvt-sleeping-lion-esc.jpg)Favourite 120A Sleeping Lion ESC for Electric Skateboards



Note that the same ESC is sold by Maytech with the [MTES 120A SBEC](http://www.maytech.cn/en/mtes120a-sbec-2/10377.html) name.

It uses a USB to UART adapter for connecting to the controller which is also used for configuring the popular [LittleBee ESC](http://fvt-littlebee.com/) for quadcopters:

![SiLabs USB to UART Adapter for Programming Favourite (FVT) ESC](https://kaspars.net/wp-content/uploads/2017/08/silabs-usb-uart-link-adapter.jpg?strip=all&quality=90&resize=800,534)SiLabs USB to UART Adapter



The LittleBee ESC uses an open source [BLHeli firmware](https://github.com/bitdump/BLHeli) which includes [a bootloader](https://github.com/bitdump/BLHeli/blob/master/BLHeli_S%20SiLabs/BLHeliBootLoad.inc) 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](https://www.saleae.com/) logic analyser during the following actions:

- reading the ESC configuration ([CSV log](https://kaspars.net/wp-content/uploads/2017/08/uart-read-settings.csv)),
- sending the configuration to ESC ([CSV log](https://kaspars.net/wp-content/uploads/2017/08/uart-send-settings.csv)), and
- sending a firmware update ([CSV log](https://kaspars.net/wp-content/uploads/2017/08/uart-firmware-update.csv)).

The CSV logs are also [available on GitHub](https://gist.github.com/kasparsd/cd132a5a0d313a249f8dcc3078f357af).

## The XOR Skywalker

The firmware update log was the most interesting because I immediately noticed the `#Skywalker20A#` string in [the plain UART traffic](https://gist.github.com/kasparsd/cd132a5a0d313a249f8dcc3078f357af#file-firmware-update-csv-L15040-L15053) which means the firmware is sent completely decoded:

![Bytes in UART Traffic During FVT Firmware Update](https://kaspars.net/wp-content/uploads/2017/08/fvt-firmware-update-uart.png?strip=all&quality=90&resize=744,362)

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](https://kaspars.net/wp-content/uploads/2017/08/E_SkateBoard_120A_170818_QuickStart.hgm) from the FVT website:

![ART Firmware Update Traffic](https://kaspars.net/wp-content/uploads/2017/08/fvt-uart-traffic-vs-firmware.png?strip=all&quality=90&resize=800,266)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](http://hackaday.com/tag/firmware/) 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](https://kaspars.net/wp-content/uploads/2017/08/fvt-170818.bin) which has the `#Skywalker20A#` along with a `BLHELI` reference right at the very end:

![FVT 120A 12S Firmware Binary](https://kaspars.net/wp-content/uploads/2017/08/fvt-firmware-decoded.png?strip=all&quality=90&resize=511,293)

## What’s Next

The `Skywalker20A` string is [a reference to the ESC layout](https://github.com/bitdump/BLHeli/blob/af20821fa9b863c3c38ea33f514b01e975e66237/SiLabs/Skywalker_20A.inc#L44) 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](https://github.com/bitdump/BLHeli/blob/d7746a65ff32d86448a391811312bab2c39cb281/BLHeli_S%20SiLabs/BLHeliBootLoad.inc#L120) in the UART traffic.
2. Check if the firmware update protocol [matches the one in the bootloader](https://github.com/bitdump/BLHeli/blob/d7746a65ff32d86448a391811312bab2c39cb281/BLHeli_S%20SiLabs/BLHeliBootLoad.inc#L134-L154).
3. Check if the C8051F310 MCU can be programmed via [the exposed C2 interface](https://www.flickr.com/photos/kasparsdambis/28427575405/).
4. Check if the pinout matches [Skywalker20A](https://github.com/bitdump/BLHeli/blob/af20821fa9b863c3c38ea33f514b01e975e66237/SiLabs/Skywalker_20A.inc) or [FVT\_20A](https://github.com/bitdump/BLHeli/blob/af20821fa9b863c3c38ea33f514b01e975e66237/Vendor%20specific%20versions/FVT/FVT_20A.inc).