Non-persistently enable access to all the system features on the Fire TV 2nd gen Cube. This includes all u-boot & fastboot commands, Amlogic burn mode, TWRP, FireOS with ADB root and selinux permissive, Magisk support, and booting alternative OS's from USB. As this tool is non-persistent, it will need to be reloaded from a connected computer after any reboot.
This expoit is based on a vulnerability in the Amlogic bootrom that allows for us to run unverified code in the ensuing boot stage (Bl2). To pause the automatic boot up process, before the Cube's saved Bl2 is loaded, we rely on Amlogic's device firmware upgrade mode (DFU). In DFU, only the boot code from the s922x SOC (Bl1) has been loaded into memory. We now use the vulnerability to load our modified Bl2, breaking the 'chain of trust', and disabling secure boot so that we can make modifications to the bootloader downstream. The last stage of the bootloader is U-Boot (Bl33) which hands off the startup process to the boot.img. Bl33 is modified to unlock any restrictions on U-Boot and fastboot commands, giving us full access to all system features. We can then use fastboot boot to load our modified boot images (TWRP, magisk-patched boot.img), into memory without modifying the Cube.
You are solely responsible for any potential damage(s) caused to your device by this exploit.
libusb-dev
installed1Amazon began rolling out firmware version 7.2.7.3/2625 in February/March 2022, which burned efuses to disable USB boot, and bar DFU entry needed by this exploit. As of May 2022, new 2nd gen Cubes are still shipped with firmware version 7.2.2.9/1856 and can be prevented from updating to the newest firmware during the registration process by following this guide.
2To put the 2nd gen Cube into device firmware upgrade (DFU) mode we need to pass a 'boot@usb' command, to the Cube's Amlogic s922x SOC, through its I2C bus within the HDMI port. This was first described in the FireFU exploit for the 1st gen Cube & Pendant. Since then there are a few more options for devices to accmplish this:
-
Arduino sketch to boot into DFU, compatible with ARM-based Arduino boards (Due, Teensy, Genuino)
https://www.exploitee.rs/index.php/FireFU_Exploit#Preparing_HDMI_dongle -
I2C emulator for Mega boards (Arduino Duemilanove, ATmega48/88/168/328)
https://github.com/tchebb/amlogic-hdmiboot-avr -
DIY modified dummy HDMI dongle. Fully self-contained, and powered by the HDMI port.
https://github.com/superna9999/linux/wiki/Amlogic-HDMI-Boot-Dongle
-
Download and unzip this repository. Unzip the images file into the "raven_boot/images" folder that corresponds to your Cube FireOS version:
"images_7242-2906.zip" for FireOS 7242/2906+
"images_7212-1333.zip" for any version earlier than 7242/2906 -
Power off the Cube
-
Connect the HDMI dongle / board (DFU entry device) to the Cube's HDMI port, and computer to the Cube's micro-USB port.
-
Power on the Cube, type 'lsusb' in the terminal. Confirm 'ID 1b8e:c003 Amlogic, Inc.' is listed, indicating the Cube is in DFU mode.
-
Reconnect the Cube and TV with HDMI cable.
-
Type 'bash menu' in the terminal, and choose your boot mode.
To switch boot modes, repeat steps 3-7.
For bash menu option '3) booting with Magisk support', install the Magisk Manager APK (v24.3+ recommended) from within FireOS. https://github.com/topjohnwu/Magisk/releases, ignore the notice about required additional steps.
IMPORTANT: This exploit is non-persistent and will require reconnecting your computer after a reboot. The exploit is run entirely in memory, and will not modify your Cube. DO NOT FLASH ANY MODIFIED IMAGES, OR INSTALL MAGISK THROUGH TWRP! This will cause an authentication error / soft brick when rebooting without the exploit present.
In late 2020 security researcher Frederic Basse discovered a critical bug in the USB stack of the Amlogic S905D3 & S905D3G SOCs that allows for the execution of unsigned code by the bootrom. As proof of concept he demonstrated that secure boot could be bypassed on the Google Chromecast to boot a custom OS like Ubuntu through the USB interface. This was further built upon to release a persistent bootloader unlock method for the Google Chromecast (Sabrina).
In spring 2022 I came across this work while researching potential vulnerabilities in the 2nd gen Cube. The Cube uses an S922X SOC which is part of the G12B Amlogic SOC family, and closely related to both the G12A and SM1 (S905D3) families. Considering their similar architerture, I had a hunch there was a good chance the same S905D3 vulnerability would be present in the S922X. I got in contact with Frederic, Nolan (Sabrina unlock) and Zenofex (1st gen Cube FireFu unlock) which led me down the path of replicating and adapting the previous S905D3 methods and tools to the S922X. To use the amlogic-usbdl exploit tool and payloads written for the S905D3, we would need to obtain the S922X bootrom to update a few of the hardware addresses that are specific to the S922X SOC.
We take advantage of Frederic's previous article on how to dump the S905D3 bootrom. The guide utilizes a mini Bl2 bootloader script that can be loaded with Amlogic's update tool to dump the bootrom code over UART. However, running the Bl2 script requires executing code in secure world, which is not possible with secure boot enabled on the Cube. Instead we need a device like Khadas' VIM3L that has secure boot disabled, but with an S922X SOC like Hardkernel's Odroid N2+. With the Odroid N2+, we follow the S905D3 guide to a tee, only using the aml_encrypt_g12b
tool, rather than aml_encrypt_g12a
during the build process.
The Bl2 code is built using GNU C cross-compiler for the arm64 architecture (packages gcc-aarch64-linux-gnu binutils-aarch64-linux-gnu on Debian) :
sudo aarch64-linux-gnu-gcc -O3 -nostdlib -Wl,--build-id=none -o S922X_dump_bootrom.elf S922X_dump_bootrom.c
sudo aarch64-linux-gnu-objcopy -O binary -j .text S922X_dump_bootrom.elf S922X_dump_bootrom.bin
Then, the binary is packaged as a regular BL2 image for this target using the aml_encrypt_g12b tool from khadas-uboot repository:
sudo ./khadas-uboot/fip/g12b/aml_encrypt_g12b --bl2sig --input ./S922X_dump_bootrom.bin --
To determine whether the S922X is vulnerable to Frederic's exploit we attempt to re-extract the bootrom, but this time using the amlogic-usbdl
exploit tool. Amlogic-usbdl
is used attempt to execute unsigned code with instructions to dump the bootrom to UART. The unsigned code is contained in the amlogic-usbdl
payload dump_bootrom_uart_s922x.S
, but first we need to update the payload which was written for the S905D3, with the UART hardware address for the S922X:
_uart_putc: .dword 0xffff25f4
Next, we have to find an address for the download buffer pointer (TARGET_RA_PTR
) within the 0xFFFE3600-0xFFFE3800
stack buffer range that will work with the S922X SOC. After trying a long list of addresses within the stack buffer without success, we discover that by modifying the bulk_transfer_size
in addition to TARGET_RA_PTR
we are finally able to get some UART output. Analysis of the UART output confirms it is the bootrom code, and that the USB stack buffer bug is present in the S922X as well. In testing, the bulk_transfer_size
could be decreased to as little as 0x6
, increasing the maximum payload size to 65530 bytes. We settle on 0xFE
for the bulk_transfer_size
to keep things similar to the S905D3 exploit for simplicity, and 0xFFFE3678
for the buffer pointer address.
Note: S922X modificatied amlogic-usbdl
program and payloads can be found here:
https://github.com/Pro-me3us/amlogic-usbdl_S922X
Knowing that the download buffer bug is replicable on the Cube, we obtain the Cube bootloader image (7.2.7.3/2625) from the FireTV OTA update bin, so that it can be modified to give us unrestricted access to the device. OTA updates come with a signed and unsigned bootloader. The unsigned bootloader will not boot on a device with verify boot enabled in the bootrom, which is every consumer Cube. Presumably this unsigned bootloader is for non-secure Cubes provided to developers by Amazon. Instead we narrow our focus on the signed bootloader (u-boot.bin.signed
).
The signed bootloaders are encrypted, and we need to decrypt it in order to make any edits. Frederic had previously found an AES-256-CBC key in SRAM 0xFFFE0020
to decrypt the Chromecast bootloader. To check this address on the Cube, we update the memdump_over_usb.c payload to dump SRAM. There is no key at 0xFFFE0020
but with further analysis a key is discovered further down at 0xFFFE7C20
(48 bytes, 32 byte key + 16 byte IV)! Surprisingly, the AES key only decrypts Bl2 & Bl30, and we need to keep searching for another key to decrypt the rest of the bootloader. Making the assumption that the key has to either be in the SOC or the decrypted portion of bootloader, three more AES keys are discovered in the decrypted Bl30 code at 0x1061C
, 0x10A84
, and 0x10EEC
(again at 0x11354
) that each decrypt a different segment of the signed bootloader. In addition to the three AES keys, we also find a fourth 48 byte string and potential AES-256-CBC key that we were unable to determine the purpose of.
AES-256-CBC key locations for decrypting the bootloader
[SRAM]
1) 0xFFFE7C20
- decrypts Bl2 + Bl30
[Bootloader Bl30]
2) 0x1061C
3) 0x10A84
4) 0x10EEC
and 0x11354
5) 0x101b4
unknown 48byte value, potential 5th AES key
With the signed bootloader decrypted, Bl2 can now be edited to remove verification checks on the later bootloader stages. Bl2 is the first 65536 bytes of the bootloader (u-boot.bin.signed
), and the last few hundred bytes of that is just padding (0's) added to meet the 65k size requirement. We crop off the first 65280 bytes of the bootloader which contains all the Bl2 code, and keeps the file size small enough to fit the 65280 byte maximum payload limit of amlogic-usbdl
.
sudo dd if=u-boot.bin.signed of=bl2.bin bs=1 count=65280 skip=0
The trimmed Bl2.bin is then edited in disassembly, patching out a serious of signature checks that verifies the rest of the bootloader.
--- [Original bl2.bin]
+++ [Patched bl2.bin]
-00008de0 60 ca 41 79 ldrh w0,[x19, #0xe4]=>DAT_0001136c
-00008de4 01 04 00 51 sub w1,w0,#0x1
-00008de8 61 ca 01 79 strh w1,[x19, #0xe4]=>DAT_0001136c
-00008dec c0 00 00 34 cbz w0,LAB_00008e04
-00008df0 20 00 00 b0 adrp x0,0xd000
-00008df4 00 60 2b 91 add x0=>s_FIP_hdr_check_fail,_retry!_0000dad8,x0,#
-00008df8 86 0e 00 94 bl FUN_0000c810
-00008dfc 20 00 82 52 mov w0,#0x1001
-00008e00 16 00 00 14 b LAB_00008e58
+00008de0 00 00 80 52 mov w0,#0x0
+00008de4 1f 20 03 d5 nop
+00008de8 1f 20 03 d5 nop
+00008dec c0 00 00 34 cbz w0,LAB_00008e04
+00008df0 1f 20 03 d5 nop
+00008df4 1f 20 03 d5 nop
+00008df8 1f 20 03 d5 nop
+00008dfc 1f 20 03 d5 nop
+00008e00 1f 20 03 d5 nop
-00008ffc 20 00 00 b0 adrp x0,0xd000
-00009000 00 dc 2e 91 add x0=>s_DDR_fip_hdr_check_fail,_retry!_0000dbb7,
-00009004 03 0e 00 94 bl FUN_0000c810
-00009008 a0 00 82 52 mov w0,#0x1005
-0000900c 93 ff ff 17 b LAB_00008e58
+00008ffc 00 00 80 52 mov w0,#0x0
+00009000 1f 20 03 d5 nop
+00009004 1f 20 03 d5 nop
+00009008 1f 20 03 d5 nop
+0000900c 1f 20 03 d5 nop
-0000bbcc 9c 02 00 94 bl FUN_0000c63c
+0000bbcc 00 00 80 52 mov w0,#0x0
With the bootloader signature checks removed from Bl2.bin, we are now free to make edits to Bl33/U-Boot where Amazon has placed all the device restrictions. Moving forward there are two possible paths for editing U-Boot 1) either continue to edit the bootloader obtained from the OTA update in disassembly or 2) use Amazon's GPL library to edit and compile our own U-Boot image and insert that into the signed bootloader image. Analyzing the bootloader indicates U-Boot is LZ4 compressed with a custom U-Boot LZ4 header, and that it can't be decompressed with the standard LZ4 program. Rather than try to reconstruct the standard LZ4 header to decompress the code, we decide to take the easier path and use the GPL repository to compile our own U-Boot image.
While attempting to use Amazon's bootloader compiler we quickly find out that it's broken. Testing various versions it's determined that FireTVCubeGen2-7.2.2.9-20201118.tar.bz2 is the last version that will fully compile, but because the fastboot boot function is broken, we have to go all the way back to the release build FireTVCubeGen2-7.2.0.4-20191004.tar.bz2.
The 2nd Gen Cube is actually shipped with an unlocked bootloader, and it's Amazon's included security layer that applies all the user restrictions. Several files in the bootloader source are edited to remove restrictions on the U-Boot and fastboot commandlines, and have our Cube classified as an 'engineering device' for greater freedom. The newly compiled U-Boot/Bl33 image is then merged into the signed bootloader. The details of the bootloader edits, compilation, and merging can be found here:
https://github.com/Pro-me3us/Raven_Bootloader_Builder/
With both a patched Bl2 image to use as a payload for amlogic-usbdl, and bootloader image with Bl33/U-Boot patched to remove all user restrictions, it's time load them together.
-
Boot the patched Bl2 image
sudo ./amlogic-usbdl bl2.bin
-
Continue the bootup proccess by loading the rest of the patched bootloader
sudo ./update bl2_boot bootloader.img
The boot mode is set in main.c (Bl33). Boot modes include fastboot, Amlogic burn mode (update) and U-Boot console.
Burn mode can be used to transmit (RX) U-Boot console commands over USB, but UART is still required to visualize the output (TX).
sudo ./update bulkcmd "u-boot command"
Additionally, the various eMMC partitions from the Cube can be downloaded or flashed in this mode. To download a parition, specify the partition name, size, and output file name. We want to extract the boot partition to use with fastboot and to use for TWRP and Magisk.
./update mread store boot normal 0x001800000 backups/boot.img
Booting to fastboot gives us access to Amazon's IDME settings.
fastboot oem idme ?
There are a number of fields that can be edited, but of particular note are the dev_flags and fos_flags. The fos_flags value can be modified to add mulitple useful features.
FOS Flags Hex Value (bitmask)
none (default) = 0x000
ADB on = 0x001
ADB root = 0x002
Console on = 0x004 (enables uart output from the kernel)
Ramdump on = 0x008
Verbosity on = 0x010
ADB auth disable = 0x020
DM-verity off = 0x080
Boot dexopt = 0x100
Example of enabling multiple features, ADB on (0x001) + ADB root (0x002) + Console on (0x004) + DM-Verity off (0x080):
fastboot oem idme fos_flags 0x87
There are also a couple device specific flags, dev_flags.
DEV Flags Hex Value (bitmask)
SElinux=enforcing (default) = 0x0032
SElinux=permissive = 0x0064
ADB USB on = 0x1000
After turning DM-verity off with the fos_flags value, the Cube can boot the extracted boot.img with fastboot. Additional commands can be added to the kernel boot commandline with fastboot -c
fastboot boot images/boot.img -c "rootfstype=ext4 ro rootwait skip_initramfs OTG_mode=DEVICE androidboot.selinux=permissive"
Setting the dev_flags value to permissive still requires also adding the permissive setting to the kernel commandline. "rootfstype=ext4 ro rootwait skip_initramfs" is added to properly mount the eMMC. "OTG_mode=DEVICE" keeps the Cube connected to our computer as a peripheral.
The boot image can also be used to compile a TWRP recovery image for the Cube. Our TWRP configuration files are available here.
To use Magisk and gain superuser status with FireOS loaded, we install Magisk Manager in FireOS (must be at least v24.310, canary build) and patch the boot.img using the recovery mode option, leaving VBmeta unchecked.
Both TWRP and Magisk images can then be loaded with fastboot boot.
TWRP recovery
fastboot boot images/twrp.img
FireOS with Magisk support
fastboot boot images/magisk_boot.img
A bash script menu with options to boot to the most common boot modes is included with this repository.
bash menu
Pro-me3us
Zenofex
Nolen Johnson
Frederic Basse
Tchebb - a bottomless encyclopedia of Amlogic knowledge, answering countless questions & troubleshooting
k4y0z - helping get TWRP and Magisk working
roligov - providing photos, additional FireOS updates, and testing