jglim / UnlockECU

Free, open-source ECU seed-key unlocking tool.
MIT License
256 stars 55 forks source link

IC211, IC209 #12

Open VladLupashevskyi opened 2 years ago

VladLupashevskyi commented 2 years ago

Just sharing some findings about IC211 here, IC209 is gonna be similar...

Found in this video combination for IC211 https://youtu.be/DMf5G9hdKAA?t=191

SW Version: 00A9 Seed: 84 7D 94 EA 99 27 9F 96 Key: 6A E3 96 C3

I was asking the author of this video how did he get the algorithm - he said he was reverse engineering the IC firmware.

Here guy is selling the tool with all possible calculators for 203, 209, 211 instrument clusters: https://ancartech.com/sw_skctool/

VladLupashevskyi commented 2 years ago

IC164 is from the same generation, found here one more example:

https://youtu.be/ap3CYx5iMIU?t=116

SW Version: 2519021500_00E1 Seed: 93 8B 6F F8 7D 54 81 B2 Key: 1E FE 30 34

VladLupashevskyi commented 1 year ago

Hi @jglim here is the algorithm for all these clusters implemented in Rust: https://github.com/VladLupashevskyi/ki211-seed-key

It needs however different key for each SW version. Most probably there is some logic for generating those as well which is based on SW or something.

There is a table of root keys for each access level for example for 0095 SW Version:

(0) 13151416 (1) 541D378F (2) 35500E9F (3) 3DA7C96F (4) 71CFD8FF (5) 1AC9EA4F (6) 4884F65F (7) 2A58122F

If you take a look at how 8 bytes seed is used for key calculation you will see that only half of it is actually used. The other dummy bytes are actually generated based on 4 bytes seed and lvl. 2 key, so they might indicate something.

I tried to find out whether these access levels depend on each other by the same algorithm (as one root key would be seed and second a key) and actually there was match for lvl key pairs (0,1), (1,2), (2,3), but no more and the brute forced key was different always, so not sure whether it was just coincidence.

However, coming back to this issue #13, I can confirm that these algorithms are build in CBF files and I managed to emulate 171 cluster Flash procedure with Teensy, where I've got key calculated for my given seed. I have also tried to emulate 211 cluster, but it was not requesting any seed from emulated cluster, but I'm pretty sure it has those capabilities, given strings that are stored in that file. Unfortunately I'm not sure how to catch which calls it does to the c32s.dll, maybe you could help with that some day.

jglim commented 1 year ago

@VladLupashevskyi Awesome! I've added that as KIAlgo1 using your reference implementation, along with entries for 0095. Thanks for your contribution!

I've tried searching for the above constants (e.g. 541D378F, endian inverted, 8F371D54) inside KI211.CBF, but I haven't found any matches. This probably means that I'm looking at the wrong place, or the root key might be directly embedded in the flash file.

If these keys can be extracted from the CFF files, I'm okay with manually dumping them as it should hopefully be a short list (and thus less painful than figuring out the backing logic). However, I haven't been able to find a matching CFF file for the 0095 SW block. Would you be able to point me to the correct CFF filename so that I can search and download it?

On the last bit on tracing c32s.dll calls, I can recommend drltrace for bulk tracing of library calls. This tool came in handy while figuring out the internals of SMR-D/F in my other ODB project. Again, this is a bulk strategy which slows down the process a lot and generates fairly chunky logs. If you have specific functions of interest, it may be quicker to stick a debugger on them instead, or write an "injectable" library to hook them.

VladLupashevskyi commented 1 year ago

@jglim thanks for implementation :)

just couple of corrections, these clusters (except for 171) are using 27 01 for seed (which is generic for all access levels) and 27 02 for key response of all access levels and the key response is formed as follows 27 02 (access level 1 byte) (key 4 bytes) (dongle ID 2 bytes) so there shouldn't be only odd numbers for access levels and they just go 1,2,3,4,5,6,7. Effectively the only 07 makes sense since it gives the all access.

Please also take a look at test section of rust.rs file, there are also keys for other SW such as ki209 1057, ki211 0095, ki211 00A9 and 171 AEJ 07/1 (pay attention to the response for 171). I might add it later here, when I have access to my computer, but just if you faster than me :)

What can be also useful if somebody has an EEPROM programmer and some clusters is that the default access level is actually stored in EEPROM and can be changed which allows to get a firmware with potential keys table. The address in EEPROM for ki211 that I checked was 0x0DE, 0x0DF which is for default lvl 2 is 0xA2C4 and for level 7 it's 0x5779. They use some obfuscation to store it on EEPROM as you can see.

I did look those keys in cbf files, and also did find anything. I don't have any CFF files for 211 cluster, and not sure whether they actually exist. What I did however is I took some dummy CFF file with ID name of 5 characters like KI171 (or IC171 can't remember now) and replaced all occurrences with KI211 + I have patched c32s CRC check so it returns always true and that's how I was able to use any CFF file with 5 chars ID for flashing with my simulator. I cannot remember whether I have used only KI171 off file for KI171 sim or also some other patched CFF file. Need to check that again. So if it actually calculates key for non original CFF file, then we can pretty sure tell that generation is done only by CBF.

What I noticed in almost all CBF files where we know exact key and can find it in CBF, the endian inverted key is prefixed with 0x43 and 0xFE byte goes almost always after key. So I found the place in 211 cbf in Flash routine section exactly before seed key related strings and it's 0xF93197A0 which has 0x43 before and 0xFE after it. Gut feeling tells me that it might be actually used to calculate that root key for specific software version.

Thanks for pointing me to drltrace, it looks like exactly what I need for that. I will check that out as soon as I find time for that. And also I will check whether seedkey is gonna be generated for 171 if I take some dummy patched CFF file and post an update here.

jglim commented 1 year ago

Got it, thanks for taking time to explain how the levels work. The db.json definitions have been updated based on the rust tests, so there are a total of 4 entries now:

I've yet to include 171_AEJ_07_1, as the output format and length is different from the rest. I'll update that at a later date when I think of a solution.


Looking at 2 random eeprom dumps, A2 C4 can be found at address 0xDE, but 57 79 is not present anywhere in either files. I'm still unsure of the significance of these 2-byte values as I assume that root keys should be 4-bytes.

Here's a dump of the first 16 bytes, starting from 0xDE.

A2115405711:
A2 C4 00 59 47 05 11 00 02 53 02 18 63 05 02 36

A2115405611:
A2 C4 00 59 46 99 10 00 10 09 25 18 63 04 02 30

That's a creative workaround to test the algo. The pattern 43 F9 31 97 A0 FE also exists on the CBF file that I am using. Specifically, it resides within the KI211_WVC_FlashProg embedded script.

When the script is dumped into a standalone file, the F9 31 97 A0 pattern can be found at position 0x2C1D, which appears to be inside the script function "SeedKeyBerechnung". I don't know enough about the scripting engine, though it seems that you are on the right path where F93197A0 is potentially a root key. Hopefully your technique will work out!

This is the list of functions inside KI211_WVC_FlashProg (EP: entrypoint offset):

Fn: LDeleteDiagServiceIO Ordinal: 13 EP: 0x378F0009, InParam: 9 @ 0x340D, OutParam: 1 @ 0x14275
Fn: LokalSetPrepParam Ordinal: 1 EP: 0xAC, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LokalGetPresParam Ordinal: 2 EP: 0xAC, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LIsDiagServiceError Ordinal: 3 EP: 0xAE, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LokalGetPresType Ordinal: 4 EP: 0x1DE, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LCreateDiagServiceIO Ordinal: 5 EP: 0x436, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LSetPrepParam Ordinal: 6 EP: 0x49A, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LDoDiagService Ordinal: 7 EP: 0x4DA, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LGetPresParam Ordinal: 8 EP: 0x54A, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LDeleteDiagServiceIO Ordinal: 9 EP: 0x5D8, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: LDiagService Ordinal: 10 EP: 0x650, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: ProgrammingMode Ordinal: 11 EP: 0x8E6, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: Unlock Ordinal: 12 EP: 0xD4A, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: EraseRoutine Ordinal: 13 EP: 0x16FE, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: CheckRoutine Ordinal: 14 EP: 0x1A36, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: EcuReset Ordinal: 15 EP: 0x2AC6, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: SeedKeyBerechnung Ordinal: 16 EP: 0x2BA4, InParam: 0 @ 0x0, OutParam: 0 @ 0x0  <--------
Fn: FlashProg Ordinal: 17 EP: 0x6AC, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: FlashProg_Boot Ordinal: 18 EP: 0x746, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: FlashProg_Boot1 Ordinal: 19 EP: 0x7D6, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
Fn: FlashProg_Boot2 Ordinal: 20 EP: 0x85C, InParam: 0 @ 0x0, OutParam: 0 @ 0x0
VladLupashevskyi commented 1 year ago

@jglim re EEPROM, thanks for confirming that A2C4 exists on other EEPROMs, that's great news!. Sorry I might not expressed myself correctly - this value has nothing to do with root key. It's just default access level that is gonna be used after boot. On these clusters there is a function Fn_Set_sec_lvl which is basically records current access level to EEPROM, so if you do seed key challenge for lvl 7 and then execute Fn_Set_sec_lvl you will never need to do a seedkey and the cluster will be always unlocked. So for lvl 7 the value at address 0xDE gonna be 0x5779.

That's the way it gets computed:

((lvl + 3 ^ 0xF) & 0xF) << 4 | (lvl & 0xF) for 0xDE ((lvl + 1 ^ 0xF) & 0xF) << 4 | (lvl + 2) for 0xDF

So one can desolder that small EEPROM change to value 0x5779 and be able to read the firmware via diagnostics, which is located starting at 0x44800 until 0x100000.

And thanks for confirmation of the location of that 4 byte value in CBF that motivates me :)

jglim commented 1 year ago

Nice, that's the first time that I've heard of persistent security levels. Appreciate the explanation.

For what it's worth, I took a look at _MIInterpreter in c32s again; The 43 in the pattern 43 F9 31 97 A0 FE helpfully appears to be an opcode for a 32-bit immediate push instruction (something like push 0xA09731F9), so that's another good sign.

image

653310641 commented 1 year ago

I got the same answer through KI211 0095 DLL and your calculation, your algorithm is very correct

20221206213006

WSorban commented 1 year ago

If this topic is still actual, here is the list of the hashes for the sw ID's of security level 7.

"03": "0F379E18",
"06": "CF6A3B16", 
"0A": "0FC62329", 
"14": "3FB43C63", 
"22": "0F07553D", 
"23": "3FE4DE5E", 
"43": "3FF83224", 
"63": "DF49A948", 
"65": "F9319720", 
"66": "F9319720", 
"67": "F93197A0", 
"68": "F9319720", 
"69": "F93197A0", 
"6A": "C57B09A9", 
"6B": "EA62570C", 
"73": "1AF33E02",
"74": "13EE4F28",
"75": "CE2C3000",
"76": "FB137234",
"77": "EF8E7812",
"86": "4FC3814A",
"88": "6F286476",
"89": "1F769C2F",
"8A": "8FD64A72",
"93": "DFB8D13B",
"94": "3F2F6370",
"95": "2F12582A",
"A9": "BFB0046A",
"AF": "9F854122",
"B5": "DF27AC30",
"C3": "3FE4D358",
"D3": "3F04892F",
"D4": "2F7BD775",
"31": "0D76984F",
"34": "0D76984F",
"35": "0D76984F",
"3A": "0D76984F",
"3C": "0D76984F",
"42": "1A993E77",
"44": "9F841711",
"56": "FFB11339",
"72": "2F48AB50",
VladLupashevskyi commented 1 year ago

@WSorban Cool, thank you very much!!! Did you get them just from firmware or was there some logic that generates them based on SWID?

@jglim we need to reverse endianness to make it work with current implementation

VladLupashevskyi commented 1 year ago

Looks like "56": "FFB11339" is the same as for 1056 which is 209 version of cluster

WSorban commented 1 year ago

Some of them are same between different sw numbers. Also one sw number can be found in multiple ki's. For example 0x86 is found in both 211 and 164

VladLupashevskyi commented 1 year ago

Yeah, I noticed that.

Another interesting thing is that I cannot find these exact SW version numbers (2nd line on photo) in any diagnostics responses and it seems it's only obtainable from engineering menu in cluster.

image

Since diagnostic app should be able to determine the version for root key, It's possible that it actually depends on other SW version (1st line for example) that is present in diagnostic responses.

WSorban commented 1 year ago

Request 31 FB 00 then sw I'd will be on 6th index

jglim commented 1 year ago

Added, Thank you @WSorban for this huge list of keys!

VladLupashevskyi commented 1 year ago

Hey @jglim, some updates from my side.

Tried with drltrace, but somehow Vediamo hangs after startup I cannot even connect to ECU :(

As you might remember I could not get seed key calculation function to be called during flash, but using your amazing app which decodes fn offsets, I just replaced offset of function that is getting called with seed key calculation function and got this nice output in logs:

Screenshot 2022-12-08 at 14 08 18

Thanks to the person that has added such a nice output for logs :D

It does not request seed, just does calculation (and 33...33 is just some value that's stored in the memory where seed should be).

As we can see it does just exactly what I have implemented in algorithm, and nothing else to do with SW dependant key generation. In fact the value that I had gut feeling about (0xF93197A0) is actually a root key and it was shared already by @WSorban.

With KI171 it's more interesting...

First of all after running 171 cbf file trough your DSCContext loader I found that there is actually a constant which is called "Key Constant" the value is: 2FABAD10.

Then there is another constant in the beginning of seed calculation function in Flash routine: 6D4EC641. I tried to change it and resulting key was changing, however not according to the logic of the algorithm. Given a seed: 00...01 the last half of this constant (as represented in cbf, i.e values from 0x00000000 to 0x0000FFFF) just does xor with 1st and 2nd bytes of resulting key, another half does something different. Need to check it out further.

In original flash sequence before doing seed key calculation it get Boot ID via request 1A 9E and that's how it decides that it's 171 AEJ 07/1. I've tried to play with response, but it always defined it as 07/01, since I don't have real 171 cluster I cannot really get a proper response, and I think it just falls back to the last possible SW revision of the cluster, if there is nothing specific in the response.

But then I tried to do that trick with replacing fn offsets and I replaced "get boot id" function with calculate key function and the resulting key was different. I assume it took the first SW in this case which is probably: AEJ 05/1 as it stays on the first place in strings of boot id fn, however it could have just informative meaning and some different value from Boot ID response is taken to decide which flavour of algorithm to use.

For the default constant value in the beginning of the function and seed 00..01 the resulting key was 40 EA 4E 9E and I couldn't brute force root key for it. With constant reset to zeros for the same seed key was 012C0001, and I could brute force key for it: 2FF40004.

So it looks like current version of algorithm will not work for 171 cluster and it needs more digging.

However good news are that we pretty sure that the algorithm is just in CBF file and nothing is used from CFF files for these clusters at least. CFF files that I took had nothing to do with those clusters.

I have also found out that _MIInterpreter function looks for dll which has interesting name: InterpreterDebugPanel.DLL. Probably it is not possible to obtain it, but it doesn't look that it has that many functions, maybe implementing some simple wrapper could shed some light of what is getting passed there.

At last I found that DSCContext was failing when reading PAL files and I had to update on line 16 in DSCContext.cs from:

new MemoryStream(dscContainerBytes)

to

new MemoryStream(dscContainerBytes, 0, dscContainerBytes.Length, true, true)
jglim commented 1 year ago

Your function offset hack is brilliant, and makes a lot of sense in hindsight — most functions take 0 parameters and return nothing so they should be interchangeable. I'm still trying to figure out more uses for your technique, and might report back if I find anything new.

On KI171_WVC_FlashProg, I've seen the variable Key_Konstante in other CBF files too. Sometimes they are populated with a value like the KI171, many other times they are uninitialized. I'm inclined to believe that this algo is intended for firmware flashing, and might be a (new?) variant of DaimlerStandardSecurityAlgo. That being said, I'm hoping that it's something else, which would be exciting.

InterpreterDebugPanel seems to only export 3 functions. There might be more callbacks from the dll, that are returned when the panel is opened but I haven't understood enough of it. Also, there are additional checks on the PAL header to determine if debugging is enabled (e.g. before the dll is loaded). I saved some notes but never finished the dll:

// this will require a *.def file to ensure that exported names are not mangled
// the function params might not be visible in ida if they are unused

/*
unk1: c string, either "unknown" or something else depending on some field within the script's header
interpreter_context: handle to the currently running vm, allocated at MIInterpreterCreate (structure, size=0x55)
mi_debug_set_breakpoint_callback: offset to the "set breakpoint" function
mi_debug_clear_breakpoint_callback: offset to the "clear breakpoint" function
*/
__declspec(dllexport) void* __cdecl ControlPanelOpen(const char* a_unk1, void* interpreter_context, void* mi_debug_set_breakpoint_callback, void* mi_debug_clear_breakpoint_callback)
{
    // returns some sort of handle, no idea
    return 0;
}

/* 
open_result seems to be the return value of ControlPanelOpen
a2 might be an address..?
can't confirm if it returns anything. 
*/
 __declspec(dllexport) void* __cdecl ControlPanelBreakpoint(void* open_result, int a2)
{
    __asm
    {
        int 3
    }
    return 0;
}

/* 
this needs to exist even if it's probably not useful
no idea what the signature is; will definitely crash
a debugger exception should be raised *first* to find the caller
*/
__declspec(dllexport) void* __cdecl ControlPanelClose()
{
    __asm
    {
        int 3
    }
    return 0;
}
jglim commented 1 year ago

Hello again, here's a small release that might help when working with the interpreter:

I've written a dll C32NativeExtension_221215_2.zip that hooks into c32s.dll, and traces every instruction that goes through MIInterpreter. At the very least, they will show up like this, with the current opcode, program counter, PAL file offset, and the stack pointer:

OP: 0000035E  PC: 06E45EB1 F: 00000137  SP: 06041046

Some instructions may be accompanied with a description on their behavior and the values as they are used or modified:

OP: 00000003  PC: 070B43ED F: 00000C73  SP: 06E460A6
push absolute: 41C64E6D

This dll expects an exact c32s.dll, version 3.2.6.2, sha1: 59E29B37C76451A2BB63F1B5776D239D103D479D, which ships with Vediamo 04.02.02. It has to be loaded after c32s.dll, and before MIInterpreter-related functions are called.

This project was built via a vanilla vs2019. It should build without much trouble as there are few third-party dependencies.

Any dll-loading technique (e.g. injection) should be fine, though CFF Explorer is especially recommended as a tool to add C32NativeExtension.dll as an import under c32s.dll, so that it is automatically loaded whenever c32s.dll is loaded by any process. When using this method, remember to put C32NativeExtension.dll in the same directory as c32s.dll after building it.

Whenever the library is loaded, it will create/overwrite a log file c32s.txt in the same directory as c32s.dll, which will contain the instruction trace.


To understand how the trace might be helpful, A CRD3 is emulated to log its unlocking behavior (I am having difficulty emulating a KI171 as I am not sure of the messages that it expects). After initiating contact, an unlock script is run through Services › Execute Function › FN_SG_Entriegeln_9A. Given a seed of 11 22 33 44 55 66 77 88, I have first manually calculated the key 0E 66 48 A9. The next section shows a snippet of the instruction trace, while the script was doing the same.

CRD3 (CRD3S2SEC9A):

k  = 3F 9C 71 A5       3F9C71A5
kA = 41 C6 4E 6D       41C64E6D
kC = 30 39             3039

seed = 11 22 33 44 55 66 77 88     1122334455667788
key  = 0E 66 48 A9                 0E6648A9

seedA = 11223344
seedB = 55667788

intermediate1 = kA * seedA + kC
intermediate1 = 41C64E6D * 11223344 + 3039
intermediate1 = A1C68BF4 + 3039
intermediate1 = A1C6BC2D

intermediate2 = kA * seedB + kC
intermediate2 = 41C64E6D * 55667788 + 3039
intermediate2 = 903C54E8 + 3039
intermediate2 = 903C8521

seedKey = intermediate1 ^ intermediate2 ^ k;
seedKey = A1C6BC2D ^ 903C8521 ^ 3F9C71A5
seedKey = 31FA390C ^ 3F9C71A5
seedKey = 0E6648A9

https://github.com/jglim/UnlockECU/blob/main/UnlockECU/UnlockECU/Security/DaimlerStandardSecurityAlgo.cs

--------

OP: 00000003  PC: 070B43ED F: 00000C73  SP: 06E460A6
push absolute: 41C64E6D

OP: 00000003  PC: 070B43EF F: 00000C75  SP: 06E460AA
push absolute: 11223344

OP: 0000004F  PC: 070B43F1 F: 00000C77  SP: 06E460AE
mul stack 41C64E6D *= 11223344 = A1C68BF4

OP: 00000003  PC: 070B43F2 F: 00000C78  SP: 06E460AA
push absolute: 00003039

OP: 00000047  PC: 070B43F4 F: 00000C7A  SP: 06E460AE
add stack A1C68BF4 += 00003039 = A1C6BC2D

OP: 00000079  PC: 070B43F5 F: 00000C7B  SP: 06E460AA
store stage1, dest. stack absolute: 02, type: 03

OP: 00000079  PC: 070B43F7 F: 00000C7D  SP: 06E460AA
store stage2: writing unmodified value A1C6BC2D with type 03

OP: 00000003  PC: 070B43F8 F: 00000C7E  SP: 06E460A6
push absolute: 41C64E6D

OP: 00000003  PC: 070B43FA F: 00000C80  SP: 06E460AA
push absolute: 55667788

OP: 0000004F  PC: 070B43FC F: 00000C82  SP: 06E460AE
mul stack 41C64E6D *= 55667788 = 903C54E8

OP: 00000003  PC: 070B43FD F: 00000C83  SP: 06E460AA
push absolute: 00003039

OP: 00000047  PC: 070B43FF F: 00000C85  SP: 06E460AE
add stack 903C54E8 += 00003039 = 903C8521

OP: 00000079  PC: 070B4400 F: 00000C86  SP: 06E460AA
store stage1, dest. stack absolute: 06, type: 03

OP: 00000079  PC: 070B4402 F: 00000C88  SP: 06E460AA
store stage2: writing unmodified value 903C8521 with type 03

OP: 00000003  PC: 070B4403 F: 00000C89  SP: 06E460A6
push absolute: A1C6BC2D

OP: 00000003  PC: 070B4405 F: 00000C8B  SP: 06E460AA
push absolute: 903C8521

OP: 0000009F  PC: 070B4407 F: 00000C8D  SP: 06E460AE
xor stack A1C6BC2D ^= 903C8521 = 31FA390C

OP: 00000015  PC: 070B4408 F: 00000C8E  SP: 06E460AA
push absolute (negative pc): 3F9C71A5

OP: 0000009F  PC: 070B440A F: 00000C90  SP: 06E460AE
xor stack 31FA390C ^= 3F9C71A5 = 0E6648A9

The log for the entire script execution can be viewed here: c32s_SecurityAccess_9New.txt. As global variables come with names, it helpfully describes what it is doing, such as:

Many of the instructions do not come with descriptions, as I only fixed up enough for the CRD3 to produce meaningful traces. Hope this still comes in handy!


Extra stuff

"minimum" CRD3 for emulation at a j2534 level (PassThruWriteMsgs/PassThruReadMsgs)

> .. .. .. .. 10 01
< 00 00 07 E8 50 01 00 14 00 C8

> .. .. .. .. 10 03
< 00 00 07 E8 50 03 00 14 00 C8

> .. .. .. .. 3E 00
< 00 00 07 E8 7E 00

> .. .. .. .. 22 F1 00
< 00 00 07 E8 62 F1 00 02 21 31 03

> .. .. .. .. 22 F1 54
< 00 00 07 E8 62 F1 54 00 40

> .. .. .. .. 22 00 01
< 00 00 07 E8 7F 22 00 01 00 00

> .. .. .. .. 27 09
< 00 00 07 E8 67 09 11 22 33 44 55 66 77 88

> .. .. .. .. 27 0A .. .. .. ..
< 00 00 07 E8 67 0A
Feezex commented 1 year ago

Additional info on bench ki211: Build : ki211+ZGW211 ( possibly 203\209 will also work) Since theres need to get SW Version to get right seed, theres alternative for bench mode by sending raw can. Basically i emulate eis position 1, and MRM keypressing.

i havent tesded messages like 01 01 or 02 00 -because its working as is.
WSorban commented 1 year ago

Hi,

I have so far not been able to get the hash for the following sw ID: 0x10 0x82

I had this in ki209 clusters, and if memory serves me right, in ki211 as well - 2007 variants

I am wondering if anybody managed to get it (I didn't find it in the sources either, still I thought it might be worth asking.

Thanks in advance!

jglim commented 1 year ago

@WSorban Hello,

I don't have the hashes, but would like to share a tip — if you are somehow able to obtain a seed/key pair, there is a good chance of recovering the KIAlgo1 hash as it is partially reversible

KIAlgo1WF KIAlgo1WF_2023_02_20-A.zip (source) image

WSorban commented 1 year ago

Thanks, yes, I tried, but unfortunately I was not able to get any seedkey pairs for this.

AVANDGARDE commented 1 year ago

Hello. Is there an exe available for those less experienced with KI211 files? UnlockECU

Feezex commented 1 year ago
AVANDGARDE commented 1 year ago

Thank you, I saw it. Only the PC version lacks Ki 211. The artifacts are already expired.

faraz-un4given commented 1 year ago

Hello Great job, @jglim and @VladLupashevskyi can do the same and solve IC_204 hashes. Many people like me are waiting and interested for this.

thanks for your perfect job

Feezex commented 10 months ago

OK this algo grows up. So KIAlgo1 family : KI211, KI171, KI164, KI203M ,KI209. Missing level 07 (2701) for KI171, KI203M ,KI209:

KI203M_0003; 189E370F KI203M_0006; 163B6ACF KI203M_0008; 62FB90EF KI203M_000A; 2923C60F KI203M_000B; 7424CF3F KI203M_0014; 633CB43F KI203M_0022; 3D55070F KI203M_0023; 5EDEE43F KI203M_0031; 70B5349F KI203M_0043; 2432F83F KI203M_0061; 7707149F

KI209_1035; CF98760D KI209_1042; 773E991A KI209_1044; 9117849F KI209_1045; B0CFE70F KI209_1046; A53ED43F KI209_1056; B913B1FF KI209_1057; C532F3EF KI209_1063; E20CE10F KI209_1072; D0AB482F KI209_1082; 9803DC0F KI209_1090; CBB999EF KI209_10FF; CBB999EF

KI171_1714420000_0052; 7B7FC59F KI171_1714420021_0063; 48A949DF KI171_1714420121_0047; 2C0EA47F KI171_1714420200_0046; 37C55E4F KI171_1714420221_0054; 16B64D3F KI171_1714420321_0060; 3A0C660F KI171_1714420621_0073; 6377122F KI171_1714420721_0082; 6872710F KI171_1714420821_0083; 27F5163F KI171_1714420921_0093; 4340663F KI171_1714450060_C541; 789ABCDE KI171_1714450160_0043; 3287F43F KI171_1714450260_0044; 56F79B2F

653310641 commented 7 months ago

Hi, do you have KI211_00B2 permission to unlock it? 20240412114225

ID SIZE Data Comment
000 6 03 00 02 00 00 00 periodic 10ms , ignition pos 1
1A8 2 01 00 UP btn.
1A8 2 02 02 Down btn.
1A8 2 03 03 Menu in btn.
1A8 2 04 04 Menu out btn.