libretiny-eu / ltchiptool

Universal, easy-to-use GUI flashing/dumping tool for BK7231, RTL8710B and RTL8720C.
MIT License
67 stars 4 forks source link

Tuya Storage decryption #23

Open Verequies opened 3 months ago

Verequies commented 3 months ago

Is it possible to decrypt the Tuya Storage partition? I am certain it contains the device ID and possibly other information as flashing a Tuya storage partition from one device to another changes said device ID. It would be great to be able to edit and rebuild this partition in order to repair devices. Attached my flash.bin (added .txt in order to upload)

flash.bin.txt

Cossid commented 3 months ago

It is already supported by the UPK2ESPHome plugin for LTChipTool. It is included with the binaries in the release section, or can be installed via pip with pip install upk2esphome

Verequies commented 3 months ago

I did try this however it unfortunately did not dump the device ID at all. Device ID looks similar to bf8b7201xxxxxxb69b9ucc.

Cossid commented 3 months ago

Look at the source data.

Cossid commented 3 months ago

This particular device doesn't have an activated device id in storage (which means it wasn't joined to Smart Life at the time it was dumped).

uuid and authkey are present, which is how it communicated with Tuya's API to generate a device ID. gw_di.id would have held the device id had it been activated.

Verequies commented 3 months ago

I see, had no idea that it generated a device ID by talking to the Tuya API. Was not able to find much information on that. Thanks for the information. Yeah, this was a dump of a downlight before it was setup so it did not contain passwords etc.

Changing the UUID and authkey would therefore generate a different device ID correct?

I will analyse a dump from a configured device.

Cossid commented 3 months ago

The UUID and authkey are Tuya secrets per device, they must match, or communication will fail. The schema that is returned with the device id is attached to the uuid and authkey. The device id is generated each activation. The device has no local schema until it has been activated.

Verequies commented 3 months ago

Okay I do see the ID after analysing a dump from a configured device.

How would one go about generating a matching UUID and authkey then? I assume there would be a process when initially developing the device.

Cossid commented 3 months ago

That is a secret defined by Tuya and attached to their license, it is not something that can just be generated. Every device has a unique UUID/authkey combo. UUID and authkey are only used in communication encryption until a device id is assigned, then it switches to seckey which is attached to the device id.

Verequies commented 3 months ago

I signed up to the Tuya cloud and generated a couple of free UUID and authkey pairs. What would be the best way to update the originals with these?

Cossid commented 3 months ago

There is no easy existing way to do this. All the tools around just read storage data. You'd need to adapt them for editing, re-encrypted, writing, and crc checks. No 3rd party firmwares use Tuya's native storage for writing.

CloudCutter somewhat does this by exploit and using Tuya's SDK functions to overwrite that data, but it has limitations (cloudcutter is using smaller data fields and is limited in the size of data the exploit can carry as a payload).

Verequies commented 3 months ago

I have managed to decrypt and re-encrypt the Tuya storage partition. Doing a byte to byte comparision before and after shows no differences and it works upon flashing.

However upon modification before re-encryption it seems to crash on bootup. Looking through the bootup log shows the following:

[01-01 18:12:18 TUYA Err][lr:0xa803d] kvs_read fails gw_bi -1
[01-01 18:12:18 TUYA Err][lr:0xac82b] base read fail:-6914
[01-01 18:12:18 TUYA Err][lr:0xad16f] ERR_EXIT is Jumped!
[01-01 18:12:18 TUYA Err][lr:0x65ad5] tuya_iot_wf_soc_dev_init err:ffffe4fe
[01-01 18:12:18 TUYA Err][lr:0x65adf] smart fram init error
[01-01 18:12:18 TUYA Err][lr:0x57fb7] ret:-6914

Interestingly kvs_read fails gw_bi -1 shows up several times even when booting a working flash backup. base read fail:-6914 always shows when modified even if I edit just a single byte before re-encryption. I even recalculate the checksum and update that too.

After a lot of playing around I believe there is something else in that partition that needs updating. Here's the Tuya partition and decrypted Tuya partition. Read from offset 0x1EE000. tuya.bin.txt decrypted_tuya.bin.txt

And heres the Python scripts I've been playing with. split_tuya_storage.py.txt update_uuid_authkey.py.txt

Should be able to chuck both in a folder with the above flash.bin and run the split_tuya_storage.py. Then afterwards run update_uuid_authkey.py. That will decrypt, update, encrypt and output several files for comparison.

The update script is largely based on bk7231tools/analysis/storage.py.

Cossid commented 3 months ago

In your decrypted_tuya.bin.txt, it appears your gw_bi and user_param_key are colliding.

Verequies commented 3 months ago

Yeah, I think that's just how it looks when decrypted. Because that is unmodified, and when re-encrypting and flashing it works fine. Its just as soon as you modify it, the firmware spits out that error.

I tried editing another dump and it was the same issue. Must be some other checksum in the file/partition?