Open mrmariosgithub opened 1 year ago
Can we somehow unpack the update file mentioned here? https://github.com/duhow/xiaoai-patch/issues/1#issuecomment-1371028610
There is no modified firmware yet, you can use the tools provided to download the firmware file, unpack it, update the login (somehow?) and try get console access to it.
Still I don't have any idea on how to run this, so whatever you try, ensure you have a backup done of your flash memory, and ensure to be able to access the U-boot console.
I didn't manage to get a flash backup. I tried nand read.raw
followed by md.b
afterwards, but I got some strange results. I copied two flash pages (zero and one) to RAM and printed them using md.b
. Then, to verfiy that successive read of flash pages work, I read only flash page one and printed it again. But the second read did not print the expected results, there was a gap of 0x40 bytes that were missing. In case someone wants to try it, here are the commands I used:
axg_s420_v1_gva#nand read.raw 0x02000000 0 0x1000
axg_s420_v1_gva#md.b 0x02000000 0x1000
axg_s420_v1_gva#nand read.raw 0x02000000 0x800 0x800
axg_s420_v1_gva#md.b 0x02000000 0x800
Maybe I am using the wrong aproach to dump the flash, then I would appreciate a hint how to do it correctly.
Anyways, I managed to unpack the update file and extract the boot.img file. I copied it to the flash drive and was able to boot from the flash drive using the following commands:
usb start
fatload usb 0 ${loadaddr} boot.img
bootm ${loadaddr}
Then I tried to boot a modified boot.img (with the boot commandline embedded into the boot.img patched) but that failed because of the signature check:
aml log : Sig Check 1423
Do you have any ideas what to try next?
I managed to dump the flash by dumping all nand pages and writing the result to a file. This was an incredible slow process which - fully automated - took around 23 hours.
I verified the dump by comparing the binwalk
with the output of mtdparts
:
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
1157 0x485 MySQL ISAM compressed data file Version 4
16777216 0x1000000 Android bootimg, kernel size: 6453248 bytes, kernel addr: 0x1080000, ramdisk size: 3143680 bytes, ramdisk addr: 0x1000000, product name: ""
27262976 0x1A00000 Android bootimg, kernel size: 6453248 bytes, kernel addr: 0x1080000, ramdisk size: 3602432 bytes, ramdisk addr: 0x1000000, product name: ""
39845888 0x2600000 Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 11356998 bytes, 1086 inodes, blocksize: 131072 bytes, created: 1970-01-01 00:00:00
56623104 0x3600000 Squashfs filesystem, little endian, version 4.0, compression:gzip, size: 51200242 bytes, 175 inodes, blocksize: 131072 bytes, created: 1970-01-01 00:00:00
107954016 0x66F3F60 Zlib compressed data, best compression
128057344 0x7A20000 UBI erase count header, version: 1, EC: 0x1, VID header offset: 0x800, data offset: 0x1000
axg_s420_v1_gva#mtdparts
0x000000000000-0x000000200000 : "bootloader"
0x000000800000-0x000001000000 : "tpl"
0x000001000000-0x000001a00000 : "recovery"
0x000001a00000-0x000002600000 : "boot"
0x000002600000-0x000003600000 : "system"
0x000003600000-0x000007a20000 : "chrome"
0x000007a20000-0x000007e20000 : "factory"
0x000007e20000-0x000010000000 : "data"
I extracted the data partition from the dump file using dd
:
dd if=dev_1.bin bs=1k skip=129152 count=132992 of=data.img
The extracted file seems to be a valid UBI image:
data.img: UBI image, version 1
As I can access an USB stick from u-boot, I should be able to update the nand with modified data.
For now I am out of ideas. Does anybody else know how to continue from here?
Ping @ds2k5
The boot.img
(kernel) shouldn't be needed to change.
Ideally you'll need to:
system
partition and change the init running programs: disable google assistant, run sshd ?, update /etc/inittab
to run a shell, update root password... Makefile
for the commands to generate an squashfs
file and ensure to match the same compression settings (compare with original with file
command)system
partition at the specific positionbootarg
(kernel boot options) and run a program after kernel load, but maybe this shouldn't be required.What I'm concerned is whether uboot
or the kernel
(boot.img
) will verify the system
squashfs partition with a certificate / signature or not... That means the whole system might be signed and may need another way of running this.
@mrmariosgithu
Hi,
nice thanks for sharing how did you the dump ?
could you access with adb ?
I am seaching for a friend that have a smd soldering station to try to use adb for more possibilities
Got in the paste a LINK for Firmware download:
https://cdn.cnbj1.fds.api.mi-img.com/xiaoqiang/rom/l09g/mico_l09g_6c5c9_1.44.27.bin
may you can use to compare with your dump
Before I post my updates, let my answer your questions first:
additionally, update the uboot bootarg (kernel boot options) and run a program after kernel load, but maybe this shouldn't be required.
I did not manage to start any processes using kernel boot parameters, I tried differend commandlines to spawn a shell on the serial console but without success.
how did you the dump?
I wrote a small programm that repetitively executed the nand dump
command on the u-boot shell. This way I dumped each flash page and wrote the results to a dump file. This is an increadible slow process as each flash page takes around one second to dump and there are 131072 of them. In the end it took around 23h to dump the entire flash chip that way. The binwalk
results of that files are posted above. I tried nand read
and nand read.raw
first but the results did not match the page dump results.
could you access with adb ?
No, unfortunatelly not. As it later turned out, the ADB service is disabled and cannot be activated using kernel boot parameters. And I found no other command to enable/start ADB from u-boot, which made sense to me.
Here are my new findings: TL;DR; Good news: I got SSH working Bad news: I ripped off the USB pads from the PCB Good news: I made the USB stick work again
Long story:
I managed to solder on an micro USB socket. Unfortunatelly, my soldering iron was not beefy enough to heat through the THT holes which use used to mount the micro USB socket to the board as the holes are connected to massive ground planes. So I simply glued the socket in place. Using the fastboot
command from u-boot
, I got a new USB device showing up on the hub and responding to the fastboot
tool provided by the Android platform-tools. I tried flashing the system.img
file from the mico update file but that did not went well, the device failed to boot afterwards as it could not find the binaries on the system partition. While moving the board around on my desc, I (obviously) applied to much force to the micro USB socket and ripped it off. Unfortunatelly, the solder pads were gone, too. And the test pads on the bottom of the board - where I soldered the USB A socket to - did not work anymore. Luckily I was able to solder jumper wires to the USB ESD protection device pads and got the USB A socket working again.
Now that I got the USB stick working again, I started messing aroung with the NAND flash partitions. Turns out, that replacing the boot.img
does not work because it is signed and kernel, ramdisk and second stage are encrypted. The encryption is not a problem - at least compared to the signature check. So replacing the kernel or ramdisk is a dead end (for now). However, I was able to restore the system partition using the extracted mico update file and the USB stick. Next, I tried modifying the system.img
and it turned out that it's not signed so I was able to flash a modified system partition.
I noticed, that during boot the script set_usb_serialnumber.sh
is executed which is part of the system.img
. So I used that file as an entry point to the device started exploring by adding commands to the end of the file. Here are the most interesting results I got that way:
In the init.rc
file, the SSH service is disabled, as well as ADB. But I grabbed the ssh service commandline from there and pasted it to the end of the set_usb_serialnumber.sh
file: /usr/bin/sshd -G -r /etc/rsa_host_key
Please note that I removed the -F
parameter, this way sshd
forks and is no longer a sub process of the shell script.
As I disassembled my speaker before setting it up, it still creates its own hotspot when powered on. So I connected my laptop to the hotspot and was able to login via ssh with the root
user and no password.
The question now is what to do next?
Here are some ideas:
1) Try modifying init.rc
As the rootfs is mounted RW, I could try updating the init.rc
file to enable the SSH service by default. But I doubt this will work as I am not sure if changes on the file will be written to then flash.
1) Block the speaker from phoning home
Most likely by blocking a bunch of hosts in the hosts
files. Persistance would not be needed for that as we could write that file on each boot.
1) Connecting the device to my home wifi and configuring it
I currently have no idea how to do that
1) Disable unwanted services
E.g. the updater. If changes on init.rc
are persistant, this could be done there
1) Install additional services and run them at boot
Should be no problem as we can modify the system partition now.
That's great news!! I'll need to gain some more trust to solder the USB header then... What I'd suggest is:
Using 1.44.27
firmware version as system
base image, create patches
for the l09g
model:
/data
/etc/inittab
, or other?)You could then create 2 images based from the same system
, one more "light" (less size) to boot, and other with all programs (MPD, snapcast) to be flashed at chrome
partition (large).
Maybe remount everything from /
to the chrome
partition.
I understand that "keeping Google services" may be desired, but my main objective with this project is to fully replace all the propietary software with open source alternatives, and having Home Assistant project that is promoting Assistant and Voice, I'm very confident we can come up with something for it. Also, we're here to experiment :D
I'll need to gain some more trust to solder the USB header then
Thats pretty easy, there are labeled test points on the bottom side of the PCB if you don't want to solder to the micro USB contacts. You need to solder to the bottom side anyways as you need to grab the USB supply voltage from there as the voltage pin from the micro USB socket cannot be used. Once the USB A socket is glued to the board you are good to go.
add ssh with persistence key in /data
There is no need for that, there is already a ssh key present.
remove OTA run remove chrome run (Google Assistant) allow console shell with root (/etc/inittab, or other?)
There is no inittab
in the filesystem. The file in question is the init.rc
file where changes are not presistant. Regarding the shell, there has to be a command which stops the local shell, maybe we can use that to reenable the shell.
You could then create 2 images based from the same system, one more "light" (less size) to boot, and other with all programs (MPD, snapcast) to be flashed at chrome partition (large).
I havn't looked at the chrome
partition yet, but using that for the new partitions sounds like a good idea to me.
I understand that "keeping Google services" may be desired
Nope, I also plan to remove all google services as well. The question here is: How do you configure your device afterwards? E.g. how do I configure the wifi interface?
Configuring wifi "afterwards" requires some software / script to allow doing so. That's still pending to do.
What I'm using now is the script wifi_connect I wrote, but this is meant for mico
images, not this Google one, so maybe it won't fully work for this case.
Still, you should be able to follow similar commands to configure wpa_supplicant
.
I'll need to gain some more trust to solder the USB header then...
I am currently working on a small program to flash the system partition using only the serial interface thus making the USB port obsolete. Once SSH is enabled flashing can be done wirelessly.
I initially tried to use a bash script but that was horribly slow (I estimated around 36 hours for the 9MB system partition).
Using my c program I was able to write the system partition in around 90 minutes but it turned out that I was writing data to fast and crashing the u-boot that way. I hope that I can fix the bug by combining the write and the verification process. I hope this way u-boot has enough time to process thw commands.
I‘ll keep you updated on my progress.
I finally managed to finialize and test the serial flash program. As stated before, I had to implement is in c
because the shell script was terribly slow. I also created a small script to generate a modified system.img
file with SSH enabled. I uploaded all my code to a dedicated repo: https://github.com/mrmariosgithub/l09g
Flashing the system partion takes about 6h to complete. To further speedup the process in the future we can generate a heavily stripped down system image.
The following idea just came to my mind: Why not create a minimal system.img
that contains all required binaries like the ssh server, busybox etc. (and all symlinks to busybox) that can be used to initially flash the L09G using the serial port. But, here comes the twist: besides starting the ssh server, the modified system image also checks for a custom script on the chrome partition. If the script exists, it executes that script.
That said script is our loader to start all required programs, kill google and xiaomi programs and patches things where needed. As discussed before, we want to flash the chrome partition with our programs anyways. By using this loader-on-the-chrome-partition approach, we only need to flash the system partition once and everything else can we done using ssh.
What do you think about that? If you agree, we should start with the minimal system image first before starting to work on the chrome partition. I think developing the system image should not take that long.
@mrmariosgithub I had to reimplement the same code in Python, I was facing some "line unmatch issues" (guessing due to the speed of serial processing), but got the same SSH working! 💪🏻 (root
no password, lol)
I'll spend some time investigating this and see what we can do...
Very nice, good to hear that! Feel free to ping me if you want to discuss or test something :-)
Hi, did you made any progress with the L09G?
Very nice, good to hear that! Feel free to ping me if you want to discuss or test something :-)
sorry not now ...... still waiting for a fried he will buy soldering station
hope end of june he have an can bring me the micro usb port on
@duhow Can't we use this to dump the bootrom and OPT keys to flash a modified bootloader that does not check the signatures anymore?
The article is based on the sonos one gen2 which uses the same processor as the L09G but has more DRAM, so we might need to adjust some adresses. But as we have access to u-boot, we should be able to dump the FIP and BL3X from there. And as we have root access, we could use the kernel module as well.
@mrmariosgithub as the speaker components contain propietary modules for wifi, sound, LEDs and so, I don't know if replacing the kernel / bootloader may remove this functionality. I'm still on hold for the L09G due to work, but I plan to dedicate some time this summer. My main focus for this project is to "patch base system to add new applications", but of course feel free to test anything that can improve functions or upgrade components version.
File /init.rc contains all the command run execution , but I cannot find where this file is located at.
What I've been playing so far is to execute packages
built for LX06 successfully - though Speaker (ALSA) needs some investigation work (can't get sound atm).
Also I couldn't find any A/B system partition, which may make this a little bit more complex than expected...
File /init.rc contains all the command run execution , but I cannot find where this file is located at.
The init.rc
file is part of the initramfs which is part of the bootloader. That’s why I wanted to have the possibility, to resign the bootloader or patch the signature verification.
What I've been playing so far is to execute
packages
built for LX06 successfully - though Speaker (ALSA) needs some investigation work (can't get sound atm).
Great!!
Also I couldn't find any A/B system partition, which may make this a little bit more complex than expected...
There is no A/B partition, there is just the system partition.
@mrmariosgithub
Hi, had luck my friend could soldering the micoUSB-Port to the PCB.
Now I need helping hand to check if the port is working....
Tryed with "adb" but "no devices" so How can I check in the bootloader or somthing else if the USB-Port is working ?
axg_s420_v1_gva#start usb Unknown command 'start' - try 'help' axg_s420_v1_gva#usb start (Re)start USB... USB0: USB3.0 XHCI init start Register 1000140 NbrPorts 1 Starting the controller USB XHCI 1.00 scanning bus 0 for devices... 1 USB Device(s) found scanning usb for storage devices... 0 Storage Device(s) found
@ds2k5 adb
might not be right available while the speaker is running in normal mode, but still you may be able to access it in u-boot
- also fastboot
may be available, so you can dump and flash content from USB directly.
Last, LX06 can be flashed with amlogic-flash-tool
, so you can give it a try as well: https://github.com/duhow/xiaoai-patch/blob/master/research/lx06/install.md
hi @duhow,
thanks......
I tore off the mico-USB Port..... damned
Hope got help for repair....
Using the usb start
command from uboot enables you to use USB mass storage device to load stuff from there. You can use the fastboot
command from u-boot, if your solder connections are good you should see a new USB device on your PC and you should be able to connect to uboot using the fastboot windows tool.
Unfortunately, you cannot dump the NAND flash using fastboot as u-boot misses some functions required to dump the flash. But you can flash the NAND flash using fastboot, which is a lot better than having to use an USB mass storage device.
If you ripped off the micro USB pads from the PCB, there is still hope. Next to the micro USB pads there are not populated ESD protection devices. You can use those pads to solder on jumper wires which you can then solder to an USB socket. The marked pads are labeled on the silk screen on the bottom of the PCB, so you know which pad is which. When connecting the USB socket you basically do not need the +5V connection from the socket.
I ripped off my micro USB pads too, so I am using an USB A socket now with jumper wires and a lot of hot glue to keep it in place.
@mrmariosgithub Thank you!
Any updates on this?
from my side - sorry no.... need to check after my friend holliday
Any updates?
sorry no from my side could not fix the usb-port welding
Following this ^^ thanks guys for all this information. I'm really interested. Already hacked some other devices ^^ It's just not my priority yet.
Ideally we should reflash a new entire rootfs image, uboot and so, but I'm not risking to brick another speaker... Meanwhile we do have access to part of the system via ssh, so any findings are welcome :)
I know this might be naive, because they just might give a flying fuck about the GPL, but did anybody ever request the GPL sources for this thing from Xiaomi? We should at least get u-boot and the kernel which is everything we need.
edit: Sent an email to the German Xiaomi support. I can't wait to get ignored by them!
You can try but I already know the answer. I have done it for a project and people I know for others projects and it is really really hard to get them. If there are some proprietaries drivers it's impossible.
@mrmariosgithub Would you share your "small programm that repetitively executed the nand dump command on the u-boot shell"? I have serial access but no usb stick soldered (my solder skills are really bad...), and I want a backup before I flash your modified system.img with ssh enabled. By the way: Thank you for your efforts on the L09G!
@duhow Can't we use this to dump the bootrom and OPT keys to flash a modified bootloader that does not check the signatures anymore?
The article is based on the sonos one gen2 which uses the same processor as the L09G but has more DRAM, so we might need to adjust some adresses. But as we have access to u-boot, we should be able to dump the FIP and BL3X from there. And as we have root access, we could use the kernel module as well.
@G33KatWork Nice to see you here. Did you notice the linked article? I bet you are able to apply this..Or you know some hacker friend who is 😉
@mrmariosgithub Would you share your "small programm that repetitively executed the nand dump command on the u-boot shell"?
The nand dump
command dumps flash pages, you cannot (directly) use the dump to restore the partition. However, the system partition is part of the update file and you can simply extract the update and use the system partition image from there to reflash in case something went wrong.
@G33KatWork Nice to see you here. Did you notice the linked article? I bet you are able to apply this..Or you know some hacker friend who is 😉
I tried to go that path but with no success. But I am no hacker, so someone else might succeed there.
There is an other approach to use a custom kernel module to dump the secure keys from within the booted OS. I managed to compile and load the module, but I did not manage to make it work as described.
However, there seems to be a way to patch/disable the u-boot signature verification. I first heard about that in a talk of Dennis Giese on how they hacked vacuum robots. The way it works is the following: u-boot is loaded to RAM and is executed from there. As the addresses of u-boot in RAM is fixed, the address of the signature verification routine is fixed as well. By patching a few bytes in RAM the verification can be disabled and u-boot no longer refuses to boot unsigned kernel images. Once the patch (both the bytes to patch and the address to patch) we can add the patch to one of the commands executed by u-boot at bootup and the signature validation is permanently turned off.
I will give it a try also. Same process than tegra hack (Switch)
@G33KatWork Nice to see you here. Did you notice the linked article? I bet you are able to apply this..Or you know some hacker friend who is 😉
Oh shit, I have a reputation now and people know me? 😳 Yes, I know blasty personally. I need to get an L09G first. The black ones seem to be particularly rare right now and the white ones are now 60€ compared to November when they were still 40€ according to price search engines. I'd like to scatter them around the house and use snapcast on them to realize a multi-room audio system.
However, there seems to be a way to patch/disable the u-boot signature verification. I first heard about that in a talk of Dennis Giese on how they hacked vacuum robots. The way it works is the following: u-boot is loaded to RAM and is executed from there. As the addresses of u-boot in RAM is fixed, the address of the signature verification routine is fixed as well. By patching a few bytes in RAM the verification can be disabled and u-boot no longer refuses to boot unsigned kernel images. Once the patch (both the bytes to patch and the address to patch) we can add the patch to one of the commands executed by u-boot at bootup and the signature validation is permanently turned off.
Yes. When you have a u-boot shell, u-boot is executing from RAM and not in-place from non-volatile flash and you can use memory write commands from the shell, it's game over. Just find the RSA signature check function and patch it to return true all the time. That's it. You have to do that on every boot, but if the environment is writable, the memory write command containing the patch can just be executed as part of the bootcmd
.
Ok, just made the link with @G33KatWork... I'm please to meet you ^^ I watch many times your CCC video for glitching the Switch to apply this to an old Tegra T20 but did not have all the hardware to do it. This SOC is the only one we can not get the key ^^ and Fusee Gelee does not work on it. So more skill than me on this ^^
I'm thinking of an experimental flash that can go well or too bad, so bear with me for the results...
In short, planning to flash an old L09A all
image to L09G.
https://cdn.cnbj1.fds.api.mi-img.com/xiaoqiang/rom/l09a/mico_all_d632e_1.54.0.bin
Steps involved:
bootloader
and tpl
(u-boot)meson.dtb
boot0
kernelsystem0
image to have accessu-boot
env settings to match L09A and boot kernelProblem is that mtd partition schema differs, so I'm planning to flash directly by skipping bytes. Also L09G has 2x flash size.
part size name_google size name_xiaomi
mtd0: 00200000 bootloader 00200000 bootloader
mtd1: 00800000 tpl 00800000 tpl
mtd2: 00a00000 recovery 00600000 boot0
mtd3: 00c00000 boot 00600000 boot1
mtd4: 01000000 system 02800000 system0
mtd5: 04420000 chrome 02800000 system1
mtd6: 00400000 factory 01400000 data
mtd7: 081e0000 data
Bad news. I am stuck in a booloop from u-boot.
AXG:BL1:d1dbf2:a4926f;FEAT:F0DC31BC:2000;POC:F;EMMC:800;NAND:0;READ:0;CHK:1F;READ:0;CHK:1F;READ:0;CHK:1F;READ:0;CHK:1F;READ:0;CHK:1F;READ:83;READ:0;CHK:1F;READ:0;CHK:1F;SD:800;USB:8;
Bad news. I am stuck in a booloop from u-boot.
Not sure if it's related, but seems like the updated firmware blocked serial and USB access? Last tested on LX06@1.84.39
@jingyibo123 it's unrelated, this issue is for L09G. Each speaker has different firmware versions.
At the moment I'm trying to patch the signature verification. Loading of the kernel overrides the init bootarg, with the value in boot.img. I can preload the image with imgread kernel boot 1080000
and then modify the init arg in memory and then boot with bootm 1080000
. This change then triggers the signature check, but is only temporary and lost after a reboot. U-Boot is loaded into memory by relocation to 0x1fec3000, therefore I dumped a lot of memory from there and searched in the code for the signature check. At the moment I'm able to ignore the check for the boot if I call mw.l 1fec8e40 d503201f
before bootm
. Unfortunately, this somehow bricks the decompression of the kernel image. I then get this log
aml log : R-2048 check fail with ERR = 1376
aml log : Sig Check 1376
avb2: 0
save_power_post ...
avb2: 0
## Booting Android Image at 0x01080000 ...
Kernel command line: rootfstype=ramfs init=/bin/sh console=ttyS0,115200 no_console_suspend earlycon=aml_uart,0xff803000
[store]Is good fdt check header, no need decrypt!
load dtb from 0x1000000 ......
Amlogic Multi-DTB tool
Single DTB detected
Loading Kernel Image(COMP_NONE) ... OK
kernel loaded at 0x01080000, end = 0x016a7800
Bad Linux ARM64 Image magic!(Maybe unsupported zip mode.)
If anybody has some ideas. Fixing the signature check would definitely allow us to modify the images as we please.
I can preload the image with
imgread kernel boot 1080000
and then modify the init arg in memory and then boot withbootm 1080000
.
If so, you can write a new env
run command and use it by default as persistent, right?
If so, you can write a new
env
run command and use it by default as persistent, right?
I was able to modify env variables at least in memory, I did not try saveenv yet. As I'm worried that it won't boot after that anymore.
As long as you can return back to uboot, saveenv
does not imply any risks.
Make sure to have a backup just in case, but if you're not deleting any entry should be fine :)
Hi,
I recently got my hands on a L09G and started poking around using the informations available in issue #1 and the research folder.
I managed to connect an USB stick to the board by soldering to the test pins on the underside of the board. Running
usb start
recognises the connected usb stick:I tried both
fatinfo
andfatls
to confirm, that the USB stick can be accessed correcty:But now I have no idea how to continue. Can I dump the flash to the USB stick? Or can I flash a modified firmware from the USB stick?
KInd regards Mario