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