Informatic / py9b

Ninebot/Xiaomi electric scooter communication library
GNU General Public License v3.0
5 stars 1 forks source link

Firmware 1.6.6 m365 pro flash leads to timed out #3

Open fmorett opened 4 years ago

fmorett commented 4 years ago

Steps to reproduce:

m365 pro with firmware 1.6.6

use the command fwupd.py -i tcp -a127.0.0.1:6000 esc .\firmwares\1\FIRM.bin.enc

And get the following output Pinging....retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry .retry Timed out !

HelaFaye commented 4 years ago

What are you using for your TCP to Serial Bridge?

fmorett commented 4 years ago

I tried using the nRF UART Bridge for android

HelaFaye commented 4 years ago

Also, where's the protocol argument?

HelaFaye commented 4 years ago

I tried using the nRF UART Bridge for android

Connecting to localhost? Running it on your phone? Yeah, Android doesn't allow localhost connections by default.

fmorett commented 4 years ago

Yeah forgot to mention that Ive forwarded all traffic trough adb to my Phone. TCP connection is established, connection to the scooter as well. The protocol defaults to the Xiaomi protocol as seeable in the code...

HelaFaye commented 4 years ago

NRF UART Bridge is not in active development and was made for Ninebot ESx and Xiaomi M365 originally. That's what the bleak and able (droidble) implementation were created to replace.

fmorett commented 4 years ago

were do I find these?

Informatic commented 4 years ago

nRF UART Bridge won't likely work for BLE/dashboard firmware versions newer than 0.81. (and that's what m365 Pro shipped originally with)

~You'll need to (try) using bleak link implementation using -i bleak switch for fwupd.py. That requires Python 3.5+ and extra package called bleak (pip install bleak). Keep in mind I only tested it on Linux. (link implementation itself, also didn't even try to do any fwupd)~

Just remembered that fwupd would need to be updated to support connection encryption on newer m365 BLE firmware. Also, currently, if I understand it correctly, the key recovery attack is not fetching enough keystream to do full firmware update. (we can just encrypt ~20 bytes, update packets are 128+ bytes, right?)

update: just did a little writeup on encryption scheme in another issue, you can take a look at it and play with bleak to recover further keystream and then try software update. I think that should be perfectly doable, I just don't have too much time to play more with this stuff for now. https://github.com/Informatic/py9b/issues/2#issuecomment-549683873

Informatic commented 4 years ago

OK, update: according to https://wiki.scooterhacking.org/doku.php?id=nbdocs, which documents ES2/ES4 protocol (which is very similar to m365) you might try sending an update with smaller chunks (fw_page_size variable in fwupd.py - 0x10 should work fine in our case, or even 0x20). Then you also need to do the following in order to add support for encrypted BLE communication: https://github.com/Informatic/py9b/blob/master/cli.py#L45-L46 (this fetches first 12 bytes from characteristic, and then fetches some additional keystream via key recovery)

Furthermore, I've been successfuly able to recover up to 83 bytes of keystream (which gives us up to 80 bytes of encrypted payload, if I count correctly) by moving doing a bunch of ReadRegs and moving the window back on each turn to have these 0x20 null bytes at the end of read buffer. I'll try to clean up my patch that implements this and post it here as well.

Sorry, I don't feel like risking my m365 ESC for now to actually test it. I only have tens of spare ES2/ES4 ESCs to hack on. However, considering the update checksum is verified at the end (at least from what I experienced when playing with Ninebot scooters), there's pretty low chance of breakage, as long as you send a correct binary in the first place.

fmorett commented 4 years ago

Ok thx for this very helpful response. I will definitely try this and let you know the result.

Just one more question:

Is it possible to flash the main firmware also? Cause I've just seen ESC, BLE and some other parts of the Scooter but I don't know if I'm wrong but I think the main firmware should be DRV? Or is the ESC the part that i want? (Like if i compile a firmware from one of the firmware sites. (version 1.5.5 should be the modded Version then))

OK got it: ESC is the same as DRV which is the motor control unit

Informatic commented 4 years ago

Did you manage to get it working?

fmorett commented 4 years ago

I didn't tried it yet, mainly because the downG application works with the new BLE version...

I may will in the future if I have time

dnandha commented 1 year ago

@Informatic By not requesting to read from BMS, but from ESC, I'm able to read up to 80 bytes of the key from memory (e.g. reading 0x50 bytes from register 0 of target 0x20). Further, I was able to recover 133 bytes of the key by starting a flash process with page size 128 and then sending a fw update command, with a package consisting of 128 zero bytes, encrypted with the first 12 bytes of the key (rest key = 0). To recover the key, I sniffed the UART line for the decoded 55aa command and the plain text key of length 121, giving me 12 + 121 = 133 bytes of the key in total.

Observation: For a given BLE version, the key is the same on different end devices. Therefore, the key is static and the byte values depend only on their absolute position.