├── README.md ├── bin ├── aml_encrypt_g12a ├── amlogic-usbdl └── update ├── bootloader ├── sabrina.BL33.encv12 ├── sabrina.bl2.noSB.noARB.img ├── sabrina.bootloader.bin ├── sabrina.bootloader.burnmode.bin ├── sabrina.bootloader.enc.img ├── sabrina.bootloader.factory.2020-07-13.img ├── sabrina.bootloader.plain.img └── u-boot.bin ├── custom-images ├── disabled_vbmeta.img ├── lineage_dtb.img ├── lineage_dtbo.img ├── lineage_recovery.img ├── magisk_boot.img └── super_empty_all.img ├── repair.sh ├── repair ├── boot.img ├── dtb.img ├── dtbo.img └── recovery.img ├── scripts ├── decrypt_bootloader.sh ├── ota_to_factory_convert.sh └── repack_bootloader.sh └── unlock.sh /README.md: -------------------------------------------------------------------------------- 1 | # sabrina-unlock: Bootloader unlock for the Chromecast with Google TV 2 | 3 | An exploit chain intended to allow one to run a custom OS/unsigned code on the Chromecast with Google TV (CCwGTV). 4 | 5 | This uses [a bootROM bug in the SoC](https://fredericb.info/2021/02/amlogic-usbdl-unsigned-code-loader-for-amlogic-bootrom.html) by security researcher Frederic Basse (frederic). 6 | 7 | Frederic also did a great amount of work to temporarily boot a custom OS from USB [here](https://github.com/frederic/sabrina-custom-os). 8 | 9 | Security researchers Jan Altensen (Stricted) and Nolen Johnson (npjohnson) took the vulnerability and provided tools and customized a u-boot image to take advantage of the provided secure-execution environment to fully bootloader unlock the device. 10 | 11 | # Standard Disclaimer 12 | 13 | You are solely responsible for any potential damage(s) caused to your device by this exploit. 14 | 15 | # Requirements 16 | 17 | - Chromecast With Google TV (sabrina) without USB password mitigation1 18 | - Either a USB A to C, or a C to C cable 19 | - A PC running some flavor of 64-bit GNU Linux 20 | - `libusb-dev` installed 21 | - `fastboot` & `mke2fs` installed from the [SDK Platform tools](https://developer.android.com/studio/releases/platform-tools) 22 | 23 | 1: The USB password mitigation has been enabled on units manufactured in December 2020 and after. For units manufactured before, the mitigation was enabled by software update in February 2021. To discern this, look at the `MFP` date on the bar-code sticker on the bottom of your device's box. If you've powered it on and OTA'd, your firmware version needs to be below the February 2021 patch level. 24 | It's not possible to disable/change the password since it's burnt into the chip (efuses). 25 | 26 | # FAQ 27 | 28 | Does unlocking the bootloader void my warranty on this device? 29 | 30 | - Probably, assume so. Or just flash stock and lock your bootloader before RMA. The exploit itself leaves no traces. 31 | 32 | Does unlocking the bootloader break DRM in any way? 33 | 34 | - Nope, just like unlocking a Pixel device officially. 35 | 36 | Can I OTA afterwards? 37 | 38 | - NO - It will relock your bootloader, and if you've made any modifications, brick you pretty hard. If you manage to do this, re-running the exploit won't be possible either, as OTA's both relock the bootloader and set a burn-mode password. 39 | 40 | Can I use stock? 41 | 42 | - Yes, but you'd need to remove the `SetupWraith` application, or block Google's OTA servers via your router's DNS, as it will forcibly OTA you to a newer build during setup. 43 | 44 | Can I go back to stock after installing custom OS's? 45 | 46 | - Yeah, totally, here's a "[Factory Image](https://drive.google.com/file/d/1FbbXk5l4liDAyCwZhxQ8k3vQkJmYLPAi/view?usp=sharing)" I made in the style of Pixel Factory Images. The patch level of this build is `2020-06-05`. 47 | 48 | Can I relock the bootloader? 49 | 50 | - If you flashed the factory image above, sure, but you run the risk of not being able to unlock again. 51 | 52 | I've run the exploit 10 times and it isn't working yet! 53 | 54 | - Swap USB ports/cables, and keep trying, for some people it takes only one attempt, for others it takes several attempts. 55 | 56 | # Content 57 | - /bin/: prebuilt set of required tools 58 | - [amlogic-usbdl](https://github.com/frederic/amlogic-usbdl): Tool to exploit bootROM bug to gain arbitrary code execution 59 | - [update](https://github.com/khadas/utils/blob/master/aml-flash-tool/tools/linux-x86/update): Client for the USB Burning protocol implemented in Amlogic bootloaders 60 | - /bootloader/: prebuilt bootloader image to upload via USB 61 | - sabrina.bl2.noSB.noARB.img: BL2 customized to remove Secure Boot check on BL33 and anti-rollback check 62 | - sabrina.bootloader.bin: bootloaders (BL3x, DDR, etc...) repacked with our customized `sabrina.bl2.noSB.noARB.img` and `u-boot.bin` 63 | - sabrina.bootloader.factory.2020-07-13.img: bootloaders (BL3x, DDR, etc.) 64 | - u-boot.bin: u-boot image built from this [repo](https://github.com/npjohnson/sabrina-unlock) 65 | - /scripts/: Scripts used to create the images in this repo 66 | - /unlock.sh: Bash script to bootloader unlock CCwGTV devices 67 | 68 | # Guide 69 | 1. Unplug the CCwGTV from everything 70 | 2. Clone/Download this repo locally, and change your shell's directory to it & ensure you `libusb-dev` installed. 71 | 3. Hold the button location on the rear of the CCwGTV case, and plug the CCwGTV into your PC via USB 72 | 73 | The host should see a new USB device connection in `dmesg` like this one: 74 | ```text 75 | [10504.840173] usb 1-4.3.1: new high-speed USB device number 16 using xhci_hcd 76 | [10504.979469] usb 1-4.3.1: New USB device found, idVendor=1b8e, idProduct=c003, bcdDevice= 0.20 77 | [10504.979495] usb 1-4.3.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0 78 | [10504.979514] usb 1-4.3.1: Product: GX-CHIP 79 | [10504.979525] usb 1-4.3.1: Manufacturer: Amlogic 80 | ``` 81 | 4. Release the button once this device has been detected by host computer. 82 | 5. Execute script **unlock.sh** to load and follow the instructions it provides. 83 | 84 | # Notices 85 | This exploit chain modifies the content of the `env` partition to unlock the bootloader. Therefore, it would be ill advised to do any of the following: 86 | - Modify contents of the `env` partition 87 | - Don't OTA! Each OTA relocks the device's bootloader upon install. Additionally, the February update enforces a password to interact with Amlogic's burn-mode, which effectively mitigates this exploit, as we can't interact with the device while it's in burn-mode. 88 | 89 | # Explanation 90 | When the CCwGTV launched, a lot of us in the Android community were excited to see a proper successor to the Asus Nexus Player. A new Android TV to develop on! 91 | 92 | Or not. When the CCwGTV launched, no kernel/modules/u-boot source was provided, and the bootloader was intentionally made non-unlockable. 93 | 94 | Inquiring with Google ultimately led to the legally required GPL license releases of kernel/modules/u-boot source code. 95 | 96 | Late last year Frederic found a [a bootROM bug](https://fredericb.info/2021/02/amlogic-usbdl-unsigned-code-loader-for-amlogic-bootrom.html) that enabled booting custom BL2/BL33 images on Amlogic S905* series chipsets. 97 | 98 | He used it to temporarily boot Ubuntu on the device as a proof-of-concept, however, upon reboot, the device would boot back into its stock OS, and any attempts to modify the OS from the live custom environment would result in Android Verified Boot locking you out of the system. 99 | 100 | Earlier this month, Jan and I found Frederic's work and began to theorize methods to permanently unlock the device using the access provided by the existing exploit. 101 | 102 | After procuring several vulnerable devices from eBay by looking at the `MFP` date printed on the barcode located on the bottom of the device's box, we set to work. 103 | 104 | The first hurdle to overcome is that all the CCwGTV's bootloader images are encrypted with an AES key and IV. To statically analyze these, we'd need that key. The easiest way to do this is to dump the memory on the device when it's in the earliest possible execution stage. Conveniently, as mentioned above, we have easy access to burn-mode, which is one of the earliest/most privileged execution contexts. 105 | 106 | First, we dumped the device's memory while in burn-mode using the payload Frederic provides [here](https://github.com/frederic/amlogic-usbdl/blob/main/payloads/memdump_over_usb.c). We then got in contact with Frederic, who gave us the pointer that the AES key used to encrypt the bootloader lies at `0xFFFE0020`. By changing the [BOOTROM_ADDR](https://github.com/frederic/amlogic-usbdl/blob/cf66e63fbcef81163954acb4f4aef1a7246ec8e7/payloads/memdump_over_usb.c#L8) variable to the address we were given, we were able to dump the AES key in question by reading out the first 48 bytes of the dump using `hexdump`, of which the first 32 bytes were the key, and last 16 bytes were the IV. 107 | 108 | From there, we used Frederic’s scripts [here](https://github.com/frederic/sabrina-custom-os/tree/main/scripts) in combination with the AES key we dumped to extract/decrypt sabrina's existing u-boot image. 109 | 110 | We can verify this is the correct AES key/IV combo by running `strings` on the output u-boot image and parsing for valid strings we'd expect in u-boot, like the build string, and sure enough there it was `U-Boot 2015.01-g77f62c30a0 (Jul 13 2020 - 08:25:23)`. 111 | 112 | Awesome, now we just need to craft a u-boot image that unlocks the device... which while you may think would be one of the hardest parts, u-boot runs in EL3, which is a highly trusted context, meaning we can arbitrarily read/write most things. 113 | 114 | Google released the u-boot source-code for the latest CCwGTV build [here](https://drive.google.com/drive/u/0/folders/1ovzrq6uadjeUuA4GmGnE1vqjaUEznQYq?resourcekey=0-0Ck8UYZ7NIHJLdsK7WO4ZA), and it served as an invaluable reference to analyze how bootloader locking on these devices is handled. 115 | 116 | Amlogic handles most of their persistent u-boot and general environment variables by storing them in a partition called `env`. Initially, we thought we'd have to modify the variable responsible for determining `is_unlockable`, but quickly it became apparent that simply writing directly to the `lock` variable was the most effective way to attain our goal. 117 | 118 | To figure out what that should be, we can look at the following [line of code](https://android.googlesource.com/platform/external/u-boot/+/31fc67387a6d78371f0e8e20fe9cba76ad6357b2/drivers/usb/gadget/f_fastboot.c#1310): 119 | ``` 120 | sprintf(lock_d, "%d%d%d0%d%d%d0", info->version_major, info->version_minor, info->unlock_ability, info->lock_state, info->lock_critical_state, info->lock_bootloader); 121 | ``` 122 | Translating this, the digits of this variable correspond to `00`, which handles rollback version values, lock state, and unlock ability. 123 | 124 | This data is all fed into [this struct](https://github.com/npjohnson/android_external_u-boot/blob/d06eb014d79649241c3018df114234fa52efb43b/include/emmc_partitions.h#L238): 125 | ``` 126 | typedef struct LockData { 127 | uint8_t version_major; 128 | uint8_t version_minor; 129 | uint8_t unlock_ability; 130 | /* Padding to eight bytes. */ 131 | uint8_t reserved1; 132 | /* 0: unlock 1: lock*/ 133 | uint8_t lock_state; 134 | /* 0: unlock 1: lock*/ 135 | uint8_t lock_critical_state; 136 | /* 0: enable bootloader version rollback 1: prevent bootloader version rollback*/ 137 | uint8_t lock_bootloader; 138 | uint8_t reserved2[1]; 139 | } LockData_t; 140 | ``` 141 | 142 | Given this, simply inserting the following code block into `common/main.c` within u-boot source before `run_preboot_environment_command` which sets all these variables would (in theory) unlock the device: 143 | ``` 144 | run_command("mmc dev 1; setenv lock 10100000; save; reboot fastboot", 0); 145 | ``` 146 | Translating this `mmc dev 1` just puts the eMMC module in a state that u-boot can write to it, `setenv lock 10100000` directly changes `lock` status from `10001110`, then `save` simply saves the environment. `reboot fastboot` isn't necessary strictly, but it is the easiest way to have the user confirm if they're unlocked. 147 | 148 | We rolled our own u-boot with this integrated: 149 | ``` 150 | export CROSS_COMPILE=/home/$redacted/bin/toolchains/gcc-linaro-aarch64-none-elf/bin/aarch64-none-elf- 151 | export CROSS_COMPILE_T32=/home/$redacted/bin/toolchains/gcc-linaro-arm-none-eabi/bin/arm-none-eabi- 152 | make sm1_sabrina_v1_defconfig 153 | make 154 | ``` 155 | We then used Frederic's `repack_bootloader.sh` to repack our customized u-boot and his customized BL2 image that ignores BL33 (u-boot) signature and nulls out the anti-rollback check. 156 | 157 | Unfortunately, as things often are, this was not as easy as it would seem. The new image didn't boot at all. 158 | 159 | Turns out, we needed to follow Frederic's example, and first enable [UART console](https://github.com/npjohnson/android_external_u-boot/commit/845ca51750f55f202f5c97288a1197cfd8d133d1) and configure it to debug the issue further. The awesome people over at [Exploiteers](https://www.exploitee.rs/) already did the leg work identifying RX/TX pads on the board, and the awesome PCBite tools from the people over at SensePeek made it easy to get UART logs up and printing. 160 | 161 | ![Here's a photo of my setup.](https://i.imgur.com/WI5sS0W.jpeg) 162 | 163 | For convenience's sake, we also removed the `0` second boot-delay and flags that [disable update mode](https://github.com/npjohnson/android_external_u-boot/commit/1a9aba0693614c3bb1a0420c529c000645f6427d), and removed a few other small restrictions to debug the issue. 164 | 165 | The issue turned out to be that we were getting tossed into burn mode - which was quickly discovered to be easily bypassed by disabling the config that [forces it](https://github.com/G12-Development/android_external_u-boot/commit/e398d184d4f4db422d83bf5e44fbe96b30b9f18c)! 166 | 167 | With this in place, it was as simple as re-building u-boot, repacking the bootloader image, and then re-running the exploit to upload the custom bootloader. 168 | 169 | UART logs then showed that our u-boot was not only executed, but `env` modified just as we intended, saved to the block device, and then the device (tried) to reboot to `fastbootd` mode, however, likely due to lingering effects of the exploit, it booted back to burn mode. Simple unplugging the device and re-plugging it in let it fire up, detect the persistent boot-reason variable, and kicked us to `fastbootd` mode. 170 | 171 | We then ran `fastboot getvar unlocked` to grab the lock status and... success! 172 | 173 | ``` 174 | unlocked: yes 175 | Finished. Total time: 0.001s 176 | ``` 177 | 178 | Now, because Android isn't stupid, and at least tries to maintain user-data security, attempting to reboot will dump us into Android Recovery saying the "System is corrupt and can't boot", simply using the button on the device, and short pressing to highlight "Factory Data Reset", then long pressing it to select, and confirming your selection, then rebooting will remedy the situation, and your device will boot into the stock OS, freshly unlocked. 179 | 180 | This was an extremely fun process and goes to show that releasing your vulnerability research can lead to even cooler discoveries! 181 | 182 | # Demo 183 | Demo video: [Chromecast with Google TV Bootloader Unlock](https://youtu.be/HWa9mraQVSo) 184 | 185 | # Credits 186 | - Nolen Johnson (npjohnson): The writeup, helping debug/develop/theorize the unlock method 187 | - Jan Altensen (Stricted): The initial concept, u-boot side unlock implementation, debugging/developing the unlock method, and being a wealth of information when it comes to Amlogic devices 188 | - Frederic Basse (frederic): The initial exploit and the AES key tip 189 | 190 | # Special Thanks 191 | - Ryan Grachek (oscardagrach): Being an awesome mentor, teaching me a fair chunk of what I know about hardware security, and being a massive wealth of knowledge about most random things. 192 | - Chris Dibona: Being an awesome advocate of OSS software and helping ensure that we got all the source-code pertinent to the device. 193 | - Pierre-Hugues Husson (phh): For pointing me down the Amlogic road to begin with by letting me know Google had decided to make the ADT-3 bootloader unlockable. 194 | - XDA users @p0werpl & @JJ2017, who both helped experiment and find a combination of images that allowed us to skip the forced OTA in SUW. 195 | 196 | # Contribute to FOSS development on this device 197 | - U-Boot: [sabrina-uboot](https://github.com/npjohnson/android_external_u-boot) 198 | - Android: [android_device_google_sabrina](https://github.com/LineageOS/android_device_google_sabrina) 199 | - GNU/Linux: [sabrina-linux](https://github.com/frederic/sabrina-linux) 200 | 201 | -------------------------------------------------------------------------------- /bin/aml_encrypt_g12a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bin/aml_encrypt_g12a -------------------------------------------------------------------------------- /bin/amlogic-usbdl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bin/amlogic-usbdl -------------------------------------------------------------------------------- /bin/update: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bin/update -------------------------------------------------------------------------------- /bootloader/sabrina.BL33.encv12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.BL33.encv12 -------------------------------------------------------------------------------- /bootloader/sabrina.bl2.noSB.noARB.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bl2.noSB.noARB.img -------------------------------------------------------------------------------- /bootloader/sabrina.bootloader.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bootloader.bin -------------------------------------------------------------------------------- /bootloader/sabrina.bootloader.burnmode.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bootloader.burnmode.bin -------------------------------------------------------------------------------- /bootloader/sabrina.bootloader.enc.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bootloader.enc.img -------------------------------------------------------------------------------- /bootloader/sabrina.bootloader.factory.2020-07-13.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bootloader.factory.2020-07-13.img -------------------------------------------------------------------------------- /bootloader/sabrina.bootloader.plain.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/sabrina.bootloader.plain.img -------------------------------------------------------------------------------- /bootloader/u-boot.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/bootloader/u-boot.bin -------------------------------------------------------------------------------- /custom-images/disabled_vbmeta.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/disabled_vbmeta.img -------------------------------------------------------------------------------- /custom-images/lineage_dtb.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/lineage_dtb.img -------------------------------------------------------------------------------- /custom-images/lineage_dtbo.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/lineage_dtbo.img -------------------------------------------------------------------------------- /custom-images/lineage_recovery.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/lineage_recovery.img -------------------------------------------------------------------------------- /custom-images/magisk_boot.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/magisk_boot.img -------------------------------------------------------------------------------- /custom-images/super_empty_all.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/custom-images/super_empty_all.img -------------------------------------------------------------------------------- /repair.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BLDRED="\033[1m""\033[31m" 4 | RST="\033[0m" 5 | 6 | echo -e "${BLDRED}" 7 | echo -e "---------------------------------------" 8 | echo -e "This script will attempt to repair your ChromeCast with Google TV (sabrina)." 9 | echo -e "Proceed at your own risk, no warranty is implied/provided." 10 | echo -e "---------------------------------------" 11 | echo -e "${RST}" 12 | 13 | read -r -p "Please type 'I Understand' and press enter to proceed"$'\n' confirm 14 | if [ "$confirm" != "I Understand" ] 15 | then 16 | exit 1 17 | else 18 | printf "\n" 19 | fi 20 | 21 | command -v fastboot >/dev/null 2>&1 || { echo >&2 "fastboot is not in PATH, please ensure the SDK platform tools (https://developer.android.com/studio/releases/platform-tools) are in PATH."; exit 1; } 22 | command -v mke2fs >/dev/null 2>&1 || { echo >&2 "mke2fs is not in PATH, please ensure the SDK platform tools (https://developer.android.com/studio/releases/platform-tools) are in PATH."; exit 1; } 23 | ldconfig -p | grep libusb-0.1.so.4 >/dev/null 2>&1 || { echo >&2 "libusb-0.1-4 is not found, please install: libusb-dev (Debian-based) / libusb-compat (Arch-based)."; exit 1; } 24 | 25 | echo -e "\e[36m" 26 | echo -e "---------------------------------------" 27 | echo -e "Please plug unplug your CCWGTV from HDMI/USB. Please also have a USB-A to USB-C cable ready and attached to your host machine." 28 | echo -e "This exploit may take a few tries to succeed, you will be walked through retying it if necessary." 29 | echo -e "---------------------------------------" 30 | echo -e "${RST}" 31 | 32 | until [ "$success_status" == "yes" ] || [ "$success_status" == "Yes" ] 33 | do 34 | echo -e "\e[36m" 35 | echo -e "---------------------------------------" 36 | echo -e "Now, hold the button on the rear of the device down while plugging the USB-C cable into the device. You should see 'Product: GX-CHIP' in your 'dmesg' upon connection." 37 | echo -e "---------------------------------------" 38 | echo -e "${RST}" 39 | 40 | read -n 1 -r -s -p $'Press enter to continue...\n' 41 | 42 | DIR=$(dirname "$(realpath "$0")") 43 | sudo "$DIR/bin/amlogic-usbdl" "$DIR/bootloader/sabrina.bl2.noSB.noARB.img" 44 | sudo "$DIR/bin/update" bl2_boot "$DIR/bootloader/sabrina.bootloader.burnmode.bin" 45 | sleep 5s 46 | sudo "$DIR/bin/update" bulkcmd "mmc dev 1" 47 | sudo "$DIR/bin/update" mwrite "repair/dtb.img" mem dtb normal 48 | sudo "$DIR/bin/update" partition _aml_dtb "repair/dtb.img" 49 | sudo "$DIR/bin/update" partition dtbo "repair/dtbo.img" 50 | sudo "$DIR/bin/update" partition boot "repair/boot.img" 51 | sudo "$DIR/bin/update" partition recovery "repair/recovery.img" 52 | sudo "$DIR/bin/update" partition vbmeta "custom-images/disabled_vbmeta.img" 53 | 54 | echo -e "\e[36m" 55 | echo -e "---------------------------------------" 56 | echo -e "Now, unplug the device and re-plug it in while holding the button on the rear of the device. You should see 'Product: GX-CHIP' in your 'dmesg' upon connection." 57 | echo -e "---------------------------------------" 58 | echo -e "${RST}" 59 | 60 | read -n 1 -r -s -p $'Press enter to continue...\n' 61 | 62 | sudo "$DIR/bin/amlogic-usbdl" "$DIR/bootloader/sabrina.bl2.noSB.noARB.img" 63 | sudo "$DIR/bin/update" bl2_boot "$DIR/bootloader/sabrina.bootloader.bin" 64 | 65 | 66 | echo -e "\e[36m" 67 | echo -e "---------------------------------------" 68 | echo -e "Now, unplug the device and re-plug it in." 69 | echo -e "---------------------------------------" 70 | echo -e "${RST}" 71 | 72 | read -r -p "Did the device boot to 'fastbootd'?"$'\n' success_status 73 | 74 | done 75 | 76 | echo -e "\e[32m" 77 | echo -e "---------------------------------------" 78 | fastboot getvar unlocked 79 | echo "If the above returned 'unlocked: yes', congratulations, your CCWGTV is now bootloader unlocked and repaired." 80 | echo "If it did not return 'yes', please contact one of the authors of this exploit with details, as your setup/device configuration is an outlier." 81 | echo -e "---------------------------------------" 82 | echo -e "${RST}" 83 | 84 | 85 | echo -e "\e[36m" 86 | echo -e "---------------------------------------" 87 | echo -e "Now, in order to prevent SetupWizard from auto-updating the device, a specific much newer factory image can to be flashed. Alternatively you can flash anything from fastbootd at this point." 88 | echo -e "Would you like to proceed flashing the modified stock image? It will wipe userdata, and requires an internet connection." 89 | echo -e "---------------------------------------" 90 | echo -e "${RST}" 91 | 92 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' factory_image 93 | if [ "$factory_image" != "Yes" ] && [ "$factory_image" != "yes" ] 94 | then 95 | printf "\n" 96 | else 97 | wget -O sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip https://download.ods.ninja/Android/firmware/sabrina/sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip 98 | unzip -o sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip 99 | fastboot reboot bootloader 100 | fastboot flash bootloader sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/bootloader.img 101 | fastboot flash dtb sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/dt.img 102 | fastboot flash dtbo sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/dtbo.img 103 | fastboot reboot bootloader 104 | fastboot flash boot sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/boot.img 105 | fastboot flash logo sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/logo.img 106 | fastboot flash recovery sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/recovery.img 107 | fastboot -w 108 | fastboot reboot fastboot 109 | fastboot wipe-super sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/super_empty_all.img 110 | fastboot flash odm sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/odm.img 111 | fastboot flash product sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/product.img 112 | fastboot flash system sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/system.img 113 | fastboot flash vendor sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/vendor.img 114 | fastboot flash vendor sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/vbmeta.img 115 | fi 116 | 117 | echo -e "\e[36m" 118 | echo -e "---------------------------------------" 119 | echo -e "Would you like to flash the stock VBMeta image?" 120 | echo -e "This will prevent the device from _actually_ applying an OTA when it tries to." 121 | echo -e "---------------------------------------" 122 | echo -e "${RST}" 123 | 124 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' custom_vbmeta 125 | if [ "$custom_vbmeta" != "Yes" ] && [ "$custom_vbmeta" != "yes" ] 126 | then 127 | printf "\n" 128 | else 129 | fastboot flash vbmeta custom-images/disabled_vbmeta.img 130 | fi 131 | 132 | echo -e "\e[36m" 133 | echo -e "---------------------------------------" 134 | echo -e "Would you like to flash a Magisk patched boot image?" 135 | echo -e "This will root your device and allow you to install the Magisk APK" 136 | echo -e "---------------------------------------" 137 | echo -e "${RST}" 138 | 139 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' magisk_boot 140 | if [ "$magisk_boot" != "Yes" ] && [ "$success_status" != "yes" ] 141 | then 142 | printf "\n" 143 | else 144 | fastboot flash boot custom-images/magisk_boot.img 145 | fi 146 | 147 | echo -e "\e[36m" 148 | echo -e "---------------------------------------" 149 | echo -e "Would you like to flash LineageOS Recovery?" 150 | echo -e "It is a custom recovery that allows you to flash ROMs, zip files, etc." 151 | echo -e "---------------------------------------" 152 | echo -e "${RST}" 153 | 154 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' custom_recovery 155 | if [ "$custom_recovery" != "Yes" ] && [ "$success_status" != "yes" ] 156 | then 157 | printf "\n" 158 | else 159 | fastboot flash recovery custom-images/lineage_recovery.img 160 | fastboot flash dtbo custom-images/lineage_dtbo.img 161 | fastboot reboot bootloader 162 | fastboot flash dtb custom-images/lineage_dtb.img 163 | fastboot boot custom-images/lineage_recovery.img 164 | fi 165 | 166 | if [ "$factory_image" != "Yes" ] && [ "$factory_image" != "yes" ] 167 | then 168 | echo -e "\e[36m" 169 | echo -e "---------------------------------------" 170 | echo -e "All done! Your device is in fastbootd, enjoy!!" 171 | echo -e "---------------------------------------" 172 | echo -e "${RST}" 173 | else 174 | echo -e "\e[36m" 175 | echo -e "---------------------------------------" 176 | echo -e "All done! Your device will reboot to the stock OS shortly. You CAN NOT update the device, it will either fail or brick your device. Beyond that, enjoy!" 177 | echo -e "---------------------------------------" 178 | echo -e "${RST}" 179 | fastboot reboot 180 | fi 181 | 182 | rm -Rf sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys* 183 | 184 | exit 185 | -------------------------------------------------------------------------------- /repair/boot.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/repair/boot.img -------------------------------------------------------------------------------- /repair/dtb.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/repair/dtb.img -------------------------------------------------------------------------------- /repair/dtbo.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/repair/dtbo.img -------------------------------------------------------------------------------- /repair/recovery.img: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oddsolutions/sabrina-unlock/ba2ae1507dcdfb9d360faa5d9346c3898128f208/repair/recovery.img -------------------------------------------------------------------------------- /scripts/decrypt_bootloader.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # decrypt bootloader partition, excluding BL2 [0x200:0x10000] 4 | # note : AES key not provided 5 | # Source : sabrina.bootloader.factory.2020-07-13.img - sha1:0b4a6f37fbd0744c0d19d8fae71e8d2c05acfafb - size:4194304 - version: 08:25:40, Jul 13 2020. g12a gfbd79d3 - mosaic-role@agent-us-east1-c-11.c.catabuilder-prod.internal 6 | 7 | DIR=$(dirname $(realpath $0)) 8 | dd if=$DIR/../bootloader/sabrina.bootloader.factory.2020-07-13.img of=$DIR/../bootloader/sabrina.bootloader.enc.img skip=258 count=6314 bs=256 9 | openssl enc -aes-256-cbc -nopad -d -K 7F9381074A7D1B42A7407EE83B112D9D9F6EAA74E402321C52734BDAA954511C -iv CE68BBE61FC7B79146E2C32ABF0E0A9B -in $DIR/../bootloader/sabrina.bootloader.enc.img -out $DIR/../bootloader/sabrina.bootloader.plain.img 10 | -------------------------------------------------------------------------------- /scripts/ota_to_factory_convert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for partition in odm product system vendor 4 | do 5 | brotli --decompress --output=$partition.new.dat $partition.new.dat.br 6 | sdat2img $partition.transfer.list $partition.new.dat $partition.img 7 | done 8 | -------------------------------------------------------------------------------- /scripts/repack_bootloader.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # repack bootloader partition with custom BL33 (u-boot.bin) 4 | # note : AES key not provided 5 | # this script requires to run (once) decrypt_bootloader.sh first to create file sabrina.bootloader.plain.img 6 | DIR=$(dirname $(realpath $0)) 7 | 8 | $DIR/../bin/aml_encrypt_g12a --bl3sig --input $DIR/../bootloader/u-boot.bin --compress lz4 --output $DIR/../bootloader/sabrina.BL33.encv12 --level v3 --type bl33 9 | IN_OFFSET=`grep --byte-offset --only-matching --text LZ4C $DIR/../bootloader/sabrina.BL33.encv12 | head -1 | cut -d: -f1` 10 | OUT_OFFSET=`grep --byte-offset --only-matching --text LZ4C $DIR/../bootloader/sabrina.bootloader.plain.img | head -1 | cut -d: -f1` 11 | dd if=$DIR/../bootloader/sabrina.BL33.encv12 of=$DIR/../bootloader/sabrina.bootloader.plain.img skip=$IN_OFFSET seek=$OUT_OFFSET bs=1 conv=notrunc 12 | openssl enc -aes-256-cbc -nopad -e -K 7F9381074A7D1B42A7407EE83B112D9D9F6EAA74E402321C52734BDAA954511C -iv CE68BBE61FC7B79146E2C32ABF0E0A9B -in $DIR/../bootloader/sabrina.bootloader.plain.img -out $DIR/../bootloader/sabrina.bootloader.enc.img 13 | dd if=$DIR/../bootloader/sabrina.bootloader.enc.img of=$DIR/../bootloader/sabrina.bootloader.bin seek=4096 bs=16 conv=notrunc 14 | -------------------------------------------------------------------------------- /unlock.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | BLDRED="\033[1m""\033[31m" 4 | RST="\033[0m" 5 | 6 | echo -e "${BLDRED}" 7 | echo -e "---------------------------------------" 8 | echo -e "This script will attempt to unlock your ChromeCast with Google TV (sabrina)." 9 | echo -e "Proceed at your own risk, no warranty is implied/provided." 10 | echo -e "---------------------------------------" 11 | echo -e "${RST}" 12 | 13 | read -r -p "Please type 'I Understand' and press enter to proceed"$'\n' confirm 14 | if [ "$confirm" != "I Understand" ] 15 | then 16 | exit 1 17 | else 18 | printf "\n" 19 | fi 20 | 21 | command -v fastboot >/dev/null 2>&1 || { echo >&2 "fastboot is not in PATH, please ensure the SDK platform tools (https://developer.android.com/studio/releases/platform-tools) are in PATH."; exit 1; } 22 | command -v mke2fs >/dev/null 2>&1 || { echo >&2 "mke2fs is not in PATH, please ensure the SDK platform tools (https://developer.android.com/studio/releases/platform-tools) are in PATH."; exit 1; } 23 | ldconfig -p | grep libusb-0.1.so.4 >/dev/null 2>&1 || { echo >&2 "libusb-0.1-4 is not found, please install: libusb-dev (Debian-based) / libusb-compat (Arch-based)."; exit 1; } 24 | 25 | echo -e "\e[36m" 26 | echo -e "---------------------------------------" 27 | echo -e "Please plug unplug your CCWGTV from HDMI/USB. Please also have a USB-A to USB-C cable ready and attached to your host machine." 28 | echo -e "This exploit may take a few tries to succeed, you will be walked through retying it if necessary." 29 | echo -e "---------------------------------------" 30 | echo -e "${RST}" 31 | 32 | until [ "$success_status" == "yes" ] || [ "$success_status" == "Yes" ] 33 | do 34 | echo -e "\e[36m" 35 | echo -e "---------------------------------------" 36 | echo -e "Now, hold the button on the rear of the device down while plugging the USB-C cable into the device. You should see 'Product: GX-CHIP' in your 'dmesg' upon connection." 37 | echo -e "---------------------------------------" 38 | echo -e "${RST}" 39 | 40 | read -n 1 -r -s -p $'Press enter to continue...\n' 41 | 42 | DIR=$(dirname "$(realpath "$0")") 43 | sudo "$DIR/bin/amlogic-usbdl" "$DIR/bootloader/sabrina.bl2.noSB.noARB.img" 44 | sudo "$DIR/bin/update" bl2_boot "$DIR/bootloader/sabrina.bootloader.bin" 45 | 46 | echo -e "\e[36m" 47 | echo -e "---------------------------------------" 48 | echo -e "Now, unplug the device and re-plug it in. If it boots to the OS, the exploit failed. If it boots to a screen that says 'fastbootd', the exploit likely succeded." 49 | echo -e "---------------------------------------" 50 | echo -e "${RST}" 51 | 52 | read -r -p "Did the device boot to 'fastbootd'?"$'\n' success_status 53 | 54 | done 55 | 56 | echo -e "\e[32m" 57 | echo -e "---------------------------------------" 58 | fastboot getvar unlocked 59 | echo "If the above returned 'unlocked: yes', congratulations, your CCWGTV is now bootloader unlocked. Do not OTA the stock firmware! It will mitigate the underlying vulnerabillity used by this exploit and make recovery much harder." 60 | echo "If it did not return 'yes', please contact one of the authors of this exploit with details, as your setup/device configuration is an outlier." 61 | echo -e "---------------------------------------" 62 | echo -e "${RST}" 63 | 64 | 65 | echo -e "\e[36m" 66 | echo -e "---------------------------------------" 67 | echo -e "Now, in order to prevent SetupWizard from auto-updating the device, a specific much newer factory image has to be flashed." 68 | echo -e "Would you like to proceed flashing this image? It will wipe userdata, and requires an internet connection." 69 | echo -e "---------------------------------------" 70 | echo -e "${RST}" 71 | 72 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' factory_image 73 | if [ "$factory_image" != "Yes" ] && [ "$factory_image" != "yes" ] 74 | then 75 | printf "\n" 76 | else 77 | wget -O sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip https://download.ods.ninja/Android/firmware/sabrina/sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip 78 | unzip -o sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys.zip 79 | fastboot reboot bootloader 80 | fastboot flash bootloader sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/bootloader.img 81 | fastboot flash dtb sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/dt.img 82 | fastboot flash dtbo sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/dtbo.img 83 | fastboot reboot bootloader 84 | fastboot flash boot sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/boot.img 85 | fastboot flash logo sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/logo.img 86 | fastboot flash recovery sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/recovery.img 87 | fastboot -w 88 | fastboot reboot fastboot 89 | fastboot wipe-super sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/super_empty_all.img 90 | fastboot flash odm sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/odm.img 91 | fastboot flash product sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/product.img 92 | fastboot flash system sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/system.img 93 | fastboot flash vendor sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/vendor.img 94 | fastboot flash vendor sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys/vbmeta.img 95 | fi 96 | 97 | echo -e "\e[36m" 98 | echo -e "---------------------------------------" 99 | echo -e "Would you like to flash the stock VBMeta image?" 100 | echo -e "This will prevent the device from _actually_ applying an OTA when it tries to." 101 | echo -e "---------------------------------------" 102 | echo -e "${RST}" 103 | 104 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' custom_vbmeta 105 | if [ "$custom_vbmeta" != "Yes" ] && [ "$custom_vbmeta" != "yes" ] 106 | then 107 | printf "\n" 108 | else 109 | fastboot flash vbmeta custom-images/disabled_vbmeta.img 110 | fi 111 | 112 | echo -e "\e[36m" 113 | echo -e "---------------------------------------" 114 | echo -e "Would you like to flash LineageOS Recovery?" 115 | echo -e "It is a custom recovery that allows you to flash ROMs, zip files, etc." 116 | echo -e "---------------------------------------" 117 | echo -e "${RST}" 118 | 119 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' custom_recovery 120 | if [ "$custom_recovery" != "Yes" ] && [ "$custom_recovery" != "yes" ] 121 | then 122 | printf "\n" 123 | else 124 | fastboot flash recovery custom-images/lineage_recovery.img 125 | fi 126 | 127 | echo -e "\e[36m" 128 | echo -e "---------------------------------------" 129 | echo -e "Would you like to flash a Magisk patched boot image?" 130 | echo -e "This will root your device and allow you to install the Magisk APK" 131 | echo -e "---------------------------------------" 132 | echo -e "${RST}" 133 | 134 | read -r -p "Please type 'Yes' and press enter to flash it, or 'No' to proceed"$'\n' magisk_boot 135 | if [ "$magisk_boot" != "Yes" ] && [ "$magisk_boot" != "yes" ] 136 | then 137 | printf "\n" 138 | else 139 | fastboot flash boot custom-images/magisk_boot.img 140 | fi 141 | 142 | fastboot reboot 143 | 144 | rm -Rf sabrina_prod_stable-12-STTL.240508.005-12011027-release-keys* 145 | 146 | echo -e "---------------------------------------" 147 | echo -e "All done! Your device will reboot to the stock OS shortly. You CAN NOT update the device, it will either fail or brick your device. Beyond that, enjoy!" 148 | echo -e "---------------------------------------" 149 | 150 | exit 151 | --------------------------------------------------------------------------------