Home

Awesome

"NotABug" - superbird-bulkcmd

Spotify Car Thing (superbird) resources to access U-Boot shell over USB. Not a bug, it is a "feature".

Hacked Car Thing

Note: this method has been tested on the factory firmware (device never used/updated : App Version 0.24.107 - OS Version 6.3.29), but should work on all firmware versions released as of this article's writing.

Disclaimer

You are solely responsible for any damage caused to your hardware/software/keys/DRM licences/warranty/data/cat/etc...

Requirements

FAQ

Does this process void my warranty on this device?

Can I OTA afterwards?

Can I still use stock features ?

Can I go back to stock after installing custom OS's or messing up the stock image?

Files

Guide : U-Boot shell over USB (USB burning mode)

  1. Unplug the Car Thing from everything
  2. Clone/Download this repo locally, and change your shell's directory to it & ensure you libusb-dev installed
  3. Hold buttons 1 & 4 on the case, and plug the Car Thing into your PC via USB

The host should see a new USB device connection in dmesg like this one:

usb 1-1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.20
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1: Product: GX-CHIP
usb 1-1: Manufacturer: Amlogic
  1. Release the button once this device has been detected by host computer.
  2. Execute script scripts/burn-mode.sh to boot U-Boot in USB burning mode. A new USB device appears on host side :
usb 1-1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.07
usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=0
  1. Execute the following commands to enable U-Boot shell at every boot.

WARNING: This step modifies the env partition. Changes are persistent, so it shall be executed only once.

./bin/update bulkcmd 'amlmmc env'
./bin/update bulkcmd 'setenv storeargs ${storeargs} run update\;'
./bin/update bulkcmd 'env save'
  1. Reboot the device by unplugging and re-plugging the USB connection.

After this modification, the device always boots in USB burning mode (U-Boot shell over USB) when connected to USB host : you can execute U-Boot commands using the update tool, but you can't see any output (unless you open the device to connect the UART interface).

Note: if not connected to USB host, the device continues default boot sequence.

Boot kernel from USB to enable ADB access

Once the device in USB burning mode, the script scripts/upload-kernel.sh can upload a Linux kernel image and boot it. The init-ramdisk includes an initd script that starts the ADB server. System partition is not modified, so this is not persistent.

The ADB interface appears as a new USB device on the host:

usb 1-2: new high-speed USB device number 18 using xhci_hcd
usb 1-2: New USB device found, idVendor=18d1, idProduct=4e40, bcdDevice= 2.23
usb 1-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-2: Product: Superbird
usb 1-2: Manufacturer: Spotify
usb 1-2: SerialNumber: 123456

Note: There is a script that is intended to be run from a UART shell included in scripts that will enable persistent ADB, but is not reccomended, as it will remove the abillity to OTA update. You can find that script here.

Explanation

When the Car Thing launched, it largely flew under most people's radar, and comically it wasn't until Spotify deeply discounted it in late 2022, to $29.99 that it caught our eyes.

This device was designed to be a simple music selection device that mounts to your car dashboard or air-vents. It is unfortunately very underpowered, with a lower-end Amlogic chip, the S905D2, paired with 500 MB of RAM - ouch.

When the device was discounted, I (Nolen) picked up a few units for security research, and messaged Fred shortly after starting to ask about collaborating on it - and comically he had independently already started.

To start, U-boot and Linux kernel source code for this device is public but advertised nowhere by Spotify.

We discovered shortly into research, that holding buttons 1 & 4 on boot put the deivce into Amlogic's USB mode, where you can upload BL2 images! Sweet.

We were able to upload a signed BL2, and then from there, upload a signed BL33, which kicked us into Amlogic's Burn Mode.

From here we were able to execute U-Boot shell commands via Amlogic's update command, and the bulkcmd feature it houses.

At this point, it became clear UART would aid our efforts, and with some simple voltage sniffing and an educated guess, we discerned the UART has the following pin-out: Car Thing UART Pin-out

For our development case, we wanted more persistent access to the UART pins, so we removed the sticker on the rear of the device, dissasembled, removed the rear heat-shield, and then filed out part of the case, as shown below Car Thing UART Setup

Once we had UART console, we continued about, and crafted a method to enable a root shell over UART:

sudo update bulkcmd 'amlmmc env'
sudo update bulkcmd 'setenv initargs init=/sbin/pre-init'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.pstore_en=1'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.record_size=0x8000'
sudo update bulkcmd 'setenv initargs ${initargs} ramoops.console_size=0x4000'
sudo update bulkcmd 'setenv initargs ${initargs} rootfstype=ext4'
sudo update bulkcmd 'setenv initargs ${initargs} console=ttyS0,115200n8'
sudo update bulkcmd 'setenv initargs ${initargs} no_console_suspend'
sudo update bulkcmd 'setenv initargs ${initargs} earlycon=aml-uart,0xff803000'
sudo update bulkcmd 'setenv storeargs ${storeargs} setenv avb2 0\;'
sudo update bulkcmd 'setenv initargs ${initargs} ro root=/dev/mmcblk0p15'
sudo update bulkcmd 'env save'

This gave us a local root shell, but still required UART - we took note that the device happened to have adbd locally installed, but not running.

We realized it wasn't as simple as just starting the daemon, we had to disable Android Verified Boot, and configure the device's USB connection in an init.d script, as shown in scripts/enable-adb.sh.client.

At this point we had full u-boot access, as well as persistent ADB (root) access, we initially wanted to try to bring-up Android Automotive on the device, but 500 MB of RAM made Android near-impossible to port.

We also tried to get other GUI applications cough maybe doom cough running, but this device utilizes a QT feature called EGLFS, which doesn't have a window management system like X11 or Wayland, so it is hard to get additional applications running on the device, but hey, maybe someone in the community can get it working using the access we're providing!

We ended up settling on using a modified init-ramdisk loaded via USB to simplify attaining root-access for the end-user. Hope you enjoy!

Additional Scripts (for advanced use-cases)

To Be Executed from U-Boot shell

Init-Ramdisk Customizations

To Be Executed from an ADB (root) Shell on Device

Known Dangerous Actions

Disclosure Notes

Note: This writeup doesn't technically warrant disclosure, as it doesn't leverage any specific vulnerabillities, but instead chains together what we suspect to be unintentional access venues to gain root-access.

Credits

Relevant Device Source Code