Skip to content

Temporary unlock, root, TWRP & Magisk use on the FireTV 2nd gen Cube

Notifications You must be signed in to change notification settings

Pro-me3us/raven-root

Repository files navigation

Temporary unlock: FireTV 2nd gen Cube

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.

Discussion & questions

XDA Forum

About the exploit

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.

Standard Disclaimer

You are solely responsible for any potential damage(s) caused to your device by this exploit.

Requirements

  • FireTV 2nd gen Cube with FireOS version earlier than 7.2.7.31
  • Micro-USB cable
  • Device to put Cube into device firmware upgrade (DFU) mode2
  • Linux installation or live-system (Ubuntu 20+ recommended)
  • libusb-dev installed

  • 1Amazon 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:

    1. 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

    2. I2C emulator for Mega boards (Arduino Duemilanove, ATmega48/88/168/328)
      https://github.com/tchebb/amlogic-hdmiboot-avr

    3. DIY modified dummy HDMI dongle. Fully self-contained, and powered by the HDMI port.
      https://github.com/superna9999/linux/wiki/Amlogic-HDMI-Boot-Dongle

    Instructions

    1. 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

    2. Power off the Cube

    3. Connect the HDMI dongle / board (DFU entry device) to the Cube's HDMI port, and computer to the Cube's micro-USB port.

    4. Power on the Cube, type 'lsusb' in the terminal. Confirm 'ID 1b8e:c003 Amlogic, Inc.' is listed, indicating the Cube is in DFU mode.

    5. Reconnect the Cube and TV with HDMI cable.

    6. 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.




    Explanation

    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.

    Dumping S922X bootrom

    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.

    Build Bl2 bootrom dump script

    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 --

    Updating amlogic-usbdl & payloads

    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

    Bootloader decryption

    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

    Creating a patched Bl2 payload

    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
    

    Patching and Compiling U-Boot

    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/

    Booting the modified bootloader

    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.

    1. Boot the patched Bl2 image
      sudo ./amlogic-usbdl bl2.bin

    2. 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.

    Amlogic burn mode

    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
    

    Fastboot mode

    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

    Contributors

    Pro-me3us
    Zenofex
    Nolen Johnson
    Frederic Basse

    Extra thanks

    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

    About

    Temporary unlock, root, TWRP & Magisk use on the FireTV 2nd gen Cube

    Resources

    Stars

    Watchers

    Forks

    Releases

    No releases published

    Packages

    No packages published