Live data from Hacker News

I bricked my Christmas lights

whizzy.org

71–80 of 85 posts

Re: I bricked my Christmas lights

#71
post #45

Earlier quoted context omitted.

Tuya is so hilarious in this regard. The protocol is just TLS over TCP, but the app happily sprays your Wi-Fi password to every STA in the area every time you add a new device. (It's how pairing is done - the app blindly broadcasts packets to 255.255.255.255 and the target device (lightbulb, power outlet, et al) just sits in promiscuous mode. The packet contents are protected by WPA2 et al, but the packet lengths are…

Very clever. IoT pairing is a tricky problem because phone/laptop devices give a very limited API for communicating with a new WiFi device that isn't yet on your WiFi network.

I've seen an iot app do it via multicast - the destination MAC isn't encrypted in the wifi frames, and the last one or two bytes of them are controlled by the sending app.

I figured this out when I tried to debug why the pairing didn't work from my phone, but did from an old Samsung A2: the iot device only had a 2.4ghz module, my new phone was on 5ghz...

Re: I bricked my Christmas lights

#72
It might be worth looking at the decompiled app code some more and seeing if it contains any clues as to the type of command you may have sent, just in case it happens to be some command used for updating the firmware or something. It probably isn't, but you never know.

That said, I suspect you're right and the order of operations was probably something like this, assuming the light controller uses a microprocessor:

1. Controller receives valid command to switch to light pattern 12.

2. Light pattern 12 is saved as user's preference (so it can be restored on power-on).

3. Controller attempts to find light pattern 12 and hits a bounds overflow in the pattern lookup table.

4. There's probably no error checking for this because this "can't happen"[0], so it tries to use the data it finds, which is garbage.

(The next steps depend on how the lookup table is formed, but for the sake of example, let's say the lookup table is an array of pointers to callback routines for each pattern.)

5. The controller remembers whatever garbage it found, treating it as a pointer.

6. The next time the controller wants to update the lights, it tries to call this garbage pointer (which is possibly just a null pointer).

7. Microprocessor tries to execute code there, but whatever it finds causes it instead to infinitely loop.

8. Dimming LEDs typically require a PWM signal, which they're no longer getting, so they go dark.

9. It's dead, Jim.

When you switch off and on again, the process restarts at step 3.

In other words, there may be a possibility for unbricking if you can factory reset, or find out how it stored your light pattern. (Though the latter will probably require at least opening it up and hoping you find a JTAG header, and a lot of patience and Zen. Don't do things willy-nilly!)

In any case, that's my best guess as to what happened here, based purely on the story and without any knowledge of the architecture or home integration ecosystem. If you attempt to fix it, good luck!

[0] http://www.catb.org/jargon/html/C/can-t-happen.html

Re: I bricked my Christmas lights

#74
post #45

Earlier quoted context omitted.

Tuya is so hilarious in this regard. The protocol is just TLS over TCP, but the app happily sprays your Wi-Fi password to every STA in the area every time you add a new device. (It's how pairing is done - the app blindly broadcasts packets to 255.255.255.255 and the target device (lightbulb, power outlet, et al) just sits in promiscuous mode. The packet contents are protected by WPA2 et al, but the packet lengths are…

Very clever. IoT pairing is a tricky problem because phone/laptop devices give a very limited API for communicating with a new WiFi device that isn't yet on your WiFi network.

Isn't this was bluetooth was supposed to be able to help with?

Re: I bricked my Christmas lights

#75
post #4

FTA: > When we try and decrypt the on and off packets we get: > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > Success! This is a lot more sensible. A fixed header, by…

And it's probably not padding, just a uint

It is padding. It was encrypted with AES, which has a block size of 128 bits. Its input needs to be padded to that amount, unless you use it in some stream modes of operation (e.g. CTR).

Re: I bricked my Christmas lights

#76
post #4

FTA: > When we try and decrypt the on and off packets we get: > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 01 00 00 00 00 00 00 00 00 00 00 > 05 54 55 52 4E 00 00 00 00 00 00 00 00 00 00 00 > Success! This is a lot more sensible. A fixed header, by…

That "54 55 52 4E" jumped right out to my eye as the uppercase alphabet. Knowing that numbers start at 0x30, uppercase letters start at 0x41, and lowercase letters start at 0x61 makes alphanumeric patterns in hex dumps easy to spot. That knowledge is good for short strings, but the canonical hexdump format is a the best way to look at packet and memory dumps.

> uppercase letters start at 0x41, and lowercase letters start at 0x61

And the reason for the 0x20 difference is that the Shift key on old teletypes turned the 0x20 bit on and off.

In the same way the Control key turned the 0x40 bit off. So Ctrl-A = 0x01 = 'A'/0x41 - 0x40.

Re: I bricked my Christmas lights

#77
This is what I was really afraid of when I reverse engineered my fireplace BLE controller last year. Especially since the "Set password" command accepts raw bytes for input but the OEM app only ever sends length-limited numeric data.

Luckily, it seems to completely forget anything that happened to it after a brief power loss.

Which is probably why most of the BLE controllers of the same brand simply stay at the default password of "0000". A power outage will eventually get you back to that. If you're really bored that'd probably make for some great BLE wardriving.

But I, too, ended up putting the results of my reverse engineering into a Home Assistant integration (https://github.com/kaechele/napoleon-efire) and documented the system and protocol (https://bonaparte.readthedocs.io/en/latest/index.html).

Re: I bricked my Christmas lights

#78
post #64

Earlier quoted context omitted.

I think about stuff like this a lot, like what technologies I'm (ab)using to do some silly gadget thing.

Even though it's way more powerful than my first computer, it uses only a fraction of the energy. So yes, in a way maybe you're abusing a pretty powerful computer to do some silly gadget thing, but there's no real negative impact. I know what you mean though. I've only recently gotten into microcontrollers, and because of the time of year I've been thinking of Christmas lights too, and felt the same thing. Then again…

Oh no negativity in the statement, I'm enjoying every second of it!

Re: I bricked my Christmas lights

#79

Earlier quoted context omitted.

And it's probably not padding, just a uint

It is padding. It was encrypted with AES, which has a block size of 128 bits. Its input needs to be padded to that amount, unless you use it in some stream modes of operation (e.g. CTR).

Eugh I hope not the padding should be at block level not at content level if this was the standard zero padding from a crypto lib you'd have 0x80 before the padding bytes (and you'd get the unpadded message when decoding it correctly)

Re: I bricked my Christmas lights

#80

Earlier quoted context omitted.

It is padding. It was encrypted with AES, which has a block size of 128 bits. Its input needs to be padded to that amount, unless you use it in some stream modes of operation (e.g. CTR).

Eugh I hope not the padding should be at block level not at content level if this was the standard zero padding from a crypto lib you'd have 0x80 before the padding bytes (and you'd get the unpadded message when decoding it correctly)

Well, they're encrypting with a statically-built-in key shared across all of their devices (and even with others). I hardly think they care about properly implementing padding!
Post reply on HN