sueppchen / PixMob_waveband

reverse engineering pixmob RF enabled waveband
MIT License
12 stars 1 forks source link

6b8b encoding question #1

Closed Serge-45 closed 4 months ago

Serge-45 commented 6 months ago

Hi Sueppchen ! Congratulation for your investigations on PixMob, very impressive ! I'm starting also in discovering this device. I've got a question about the 6b8b encoding. I cannot match the dictTable you use in advanced.ino with the description of the 6b8b encoding (found at https://en.wikipedia.org/wiki/6b/8b_encoding for instance). Is this another encoding ? Do you include the BigEndian transformation prior to the 6b8b encoding or after ? Thanks for your help ! Serge

sueppchen commented 6 months ago

Hi Serge, the 6b8b is not the standard DC-balanced linecode you find in the web. They wrote their own encoding scheme.

when I started investigatin the pixmob-batch, I switched to BigEndian in transmition. whitch one you use does not matter. the plain values are encoded and directly send. If you like LE encoding more, you 'll have to change the dictTable to { 0x84, 0xac ... }, change the preamble from 0x55 to 0xaa and reverse the for-loop in transmitByte. but keep in mind - that does not change anything.

Sueppchen

Serge-45 commented 6 months ago

Hi Sueppchen, Thanks for your answers. Ok for their own 6b8b encoding. I wonder how you manage to get the translation table ? Ok for BE/LE, I'm keeping the BE encoding in order to align with the notation in the blue_xx.txt files. I'm trying to find a bit of logic in the CRC values, but no discovery so far... Serge

sueppchen commented 6 months ago

i got the table with a mixture of the given values at daniel Weidmanns site, guessing and some bruteforcing... th blue_xx.txt files are only a stage - lets call it collection. the final files are the blue_x.list files. all values in that files are proofed to work. you don't need the 6b8b encoded values... for crc calculations I create them by dictTable. that will save space... I got 27 different RGB-triplets with all the same 47,49 (0x2f + 0x31) CRC... but I didn't get any checksum - algorithm which has the same behavior.

Serge-45 commented 6 months ago

For CRC, they may use different strategies, knowing that the input message is made of 7x6 bits, and the transmitted CRC is 2x6 bits :

Another approach would be to input the 7x6 bits in a CRC-12 calculation, and split the result as 6+6 bits. I think this approach is less probable, as the necessary programing is more complex and less usual.

sueppchen commented 6 months ago

i Wrote a python script what did all this... ...I will upload it in /crcBrute it can do following things with the complete frame:

it can do following things with each byte bevor CRC is calculated:

then CRC16 is calculated with various options (init value, key, reflect input, reflect output, xor the output...)

the result is processed:

maybe lower bits could be cut..

I think it is not to complicated. things like crc12 must be written in code. A crc16 engine is in the processor implemented to check the uploaded code. that is cheep. stitching all bits together to a long number is complicated... and the result is 54 bit long (or 42 bit if shorted)

I had implemented this function but I do not find the file... so...later.

sueppchen commented 6 months ago

ok, done... it was already in the file. so I added some comments to find the place to change.next time I add shift one bit and cut one bit and other crazy stuff in the output section... ideas welcome :-)

Serge-45 commented 6 months ago

Great ! In the meantime, I did some testing with an Arduino directly connected to the P03 of the MCU, no RF module. The bit transmission duration can be shortened to 440µs, and the gap between two messages can be reduced to 3ms. This may increase a bit the testing rate. As well, I'm sending a "StayAlive" command only every 64 tested values, as the MCU is falling asleep after about 1.5 minute with no message or wrong message.

sueppchen commented 6 months ago

yes, that is possible to speed things up, but the processor needs time to settle up the PWM pins. so... have you tested how far away you are from real checksum (I was between 1 and 2)? official time for ,,background color" is 60sec until it disappears. The stay-alive-message is background color: black.

Serge-45 commented 6 months ago

Great achievement ! Based on the data you got, I've been able to calculate the CRC value for given G, R and B values. See attached code.

Serge-45 commented 6 months ago

New version, including calculation for all BLUE values, and for some values of ATTACK/RANDOM. New function setCRC(byte *message). crc.ino.txt

Serge-45 commented 6 months ago

Last version with all values for RELEASE/HOLD values ! crc.ino.txt

sueppchen commented 6 months ago

hej, nice job. I will update the readme and the files as soon as possible.

Serge-45 commented 6 months ago

I've created diagrams explaining the pulse shape and the use of the background color (when RELEASE = 0). Feel free to add them in the file list. pulse shape ATTACK and RELEASE phases cannot be interrupted by a new incoming message, but HOLD phase can be.

background color Background timeout range is from about 0.5 second to about 60 seconds according to the HOLD value (from 0 to 7) in the message setting the background color.

sueppchen commented 6 months ago

ok... your tables are great... how did you get there?

I took them to the python-ckeck-value-script and let it only test the ,,not found" values.
most of them are crcA odd and crcB 63 or crcA even and crcB 5 ... surprise. the Question is, why this values can not be found by the normal bruteforce method.

I think they don't do it with tables in the processor in most cases there are the basic bit and byte manipuation operands: shift left, shift right, swap, rotate left, rotate right, and, or, xor. all that could be done with plain values(6 byte or 8 byte), or 6b8b values (LE or BE) possible scenario is:

take an initial value for example 0xEE

now [manipulate] the result xor with next byte userdata and store the result

repeat everything between dashes until all bytes are received

when the checksum algorithm is found, I will continue with group and eeprom storage. but without knowing the checksum it is impossible to guess what is right and what will possible fry the batch.

nice diagram, attack is running before led lights up and is also running when the hold value is reached... when I checked the attack and release values with the logic analyzer, I wondered why there where values of 86ms and 48 ms and so on until I tested without A and R ramps

Serge-45 commented 6 months ago

Well, here are some info from what I discovered:

Let's continue!

Serge-45 commented 6 months ago

Updated crc.ino file, able to manage MOD=2 and GRP=1 crc.ino.txt

Serge-45 commented 6 months ago

Here is the com.ino file used for sending messages and detecting activity on an Arduino UNO board. See comments for PINs connections. com.ino.txt

Serge-45 commented 6 months ago

For information, if you play with background color, it could be usefull to reset to "no background". For this, I use {0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02} // set black color as background I also use this message as a "keep-alive" message during long bruteforce scanning.

Serge-45 commented 6 months ago

Hi! Thanks for the invitation to contribute. May I create some folders and files to keep trace of my discoveries ? Let me know how you would like to organize it.

sueppchen commented 6 months ago

I changed your tables to be 0 based (so my initial-Value is 32 02) for the modus have a look @ https://github.com/danielweidman/pixmob-ir-reverse-engineering/issues/8 for a description of the mode byte. maybe they didn't change that for the RF.

also the initial 0xEE would give an matrix of 8x8 bit user data

I think, the behavior of your mode 2 and mode 4 is same saved value in eeprom. did you read it? I have 3 example files in /eeprom

maybe I will do some tests today evening

sueppchen commented 6 months ago

I adopted your tables into my script and... used mod=2: when message arrives, eeprom is read. in my case
mode=0 --> normal operation mode seems to be divided into bits: bit0: unknown bit1: is memory mode

memory mode: byte 2 = 0xEESSSS (end end start start start start) maybe the missing 2 End-bits are coded into mode itself
byte 3 = Attack + random byte 4 = release + hold byte 5 = unknown changing the value has no effect byte 6 = same like byte 5 byte 7 = could be group there are 16 memorys each containing 4 bytes from 0x10 to 0x4F it is always played from start to end (if start is after end all 16 are played)

when you get mode 4 working, you could reverse the byte5 and byte7 table values - because its not group and random anymore