XORing for Keys

A project log for Chitu 3D Printer Mainboard Hacking

Studying the encryption on Chitu's 3D Print controllers

J.C. NelsonJ.C. Nelson 09/15/2019 at 18:440 Comments

This particular log will be heavy on hex dumps, low on actual progress, but again, the goal here is to record what I'm seeing, how I'm approaching it, and so on. I've been unsuccessful in my attempts to find a dead Chitu/Tronxy board to desolder. I want to see if there's anywhere I can attach SWD/SWIO, because attacking the initializers would be easier.

So I went back to looking, specifically, at the Tronxy XY-3 firmware.

As noted in previous logs, the first four bytes seems to be a signature, and the fifth byte is what I call the XOR Key. It's what zero will be XOR'd with. My theory is that it's some form of rolling encyrption that incrments a certain distance and then XORs the rest with the XOR key (why should become obvious in a bit).

I wrote a quick python script to xor firmware with the fifth byte and went scrounging for strings, and I struck gold, fragments of text matching PID Autotune references.

Now, remember that ARM architecture, there's literal pools scattered before and after functions (and sometimes in the middle), so when we see a bunch of strings that reference PID tuning together, we smile - it's likely this is the literal pool for the autotune function.

There are odd spaces in the least until I compare to the source for Repetier, around 2015.

Then, suddely, the text begins to look like this:

D=-?”²Ú̍)PID Autotune failed! Temperature too highE.	12ã?…ëQÿÂßëªá\PID Autotune failed! timeout„ W?÷[¦tPID Autotune finished ! Þp;Ÿ+4

So...odds are that Chitu's firmware is related to Repetier the same way the M200 firmware is 'related' to Marlin.

But by filling in the expected bytes, I was able to make cribs I could XOR with the source bytes to produce keys.

The following keys have zero for where I don't know the byte values.

PID Autotune finished ! Place the Kp, Ki and Kd constants in the Configuration.h or EEPROM

50494420 4175746F 74756E65 2066696E 69736865 64202120 506C6163 65207468 65204B70 2C204B69 20616E64 204B6420 636F6E73 74616E74 7320696E 20746865 20436F6E 66696775 72617469 6F6E2E68 206F7220 45455052 4F4D

Encrypted Bytes:
7A9F95F6 16E181AA A9A4B9B1 F5B3BCBB BCA6BA14 534EF44B 0DB8ECC8 92DEF1C7 A695D7D4 759075C9 D5F50F09 DF214489 CD74A6EF 83D8F2C6 7F91FFCD B1C993A1 D6F92D77 F3040177 8A094965 88C3FA86 D848D992 C2934D93 D5F0

2AD6D1D6 5794F5C5 DDD1D7D4 D5D5D5D5 D5D5D271 376ED56B 5DD48DAB F7FE85AF C3B59CA4 59B03EA0 F594616D FF6A20A9 AE1BC89C F7B99CB2 0CB196A3 91BDFBC4 F6BA4219 956D6602 F8683D0C E7ADD4EE F827ABB2 87D61DC1 9ABD

 By dialing back to the shared bytes, I can see there's a commonality in the way the bytes are XORd. :

00000000 00000000 00000000 94949494 9494D338 4EA42D79 6B979097 16D5B484 9C909695 
00000000 00000000 00000000 94949494 94949330 762E9507 46F9AD89 1B
00000000 0ADBB387 9E919695 94949494 949493C0 C6EAFDDE 3BC925CD 39C3BF81
2D7660EF 2ACBBB8C 98929795 94949494 94949390 D6176428

 And if  we go back to what we think is the NIVIC, we see:

BB31949C 93093DC7 A58E9A93 90969594 94949494 94949494

So what do we think of this?

Well, it's clear that the once we begin a run of the XOR KEY, we continue it for a while. In the lines above we see taht there's actually some sort of cycle occuring - probably a rolling XOR encryption or one that takes the location in as a parameter of its execution.

If I can get to the point where I can attack the constant initializers, I can insert all zeros, exposing the XOR values and use all FFs to make sure bits aren't carried over. It could be that smarter people will simply see the pattern in what's happening here.

And in the mean time, I'll keep digging on strings and known values.