|
prj
|
|
« Reply #31 on: April 29, 2023, 03:11:27 AM »
|
|
|
It's for SDA not DHA now.
I've only seen one file for a 2016, and I don't have any contacts where to get anything else.
|
|
|
Logged
|
|
|
|
PoleStarPete
Newbie
Karma: +3/-0
Offline
Posts: 12
|
|
« Reply #32 on: April 29, 2023, 03:12:40 AM »
|
|
|
|
|
|
Logged
|
|
|
|
dikidera
Full Member
Karma: +8/-8
Offline
Posts: 149
|
|
« Reply #33 on: April 30, 2023, 11:26:57 PM »
|
|
|
I never said that such software doesn't exist, but that it isn't readily available for us.
When I first started, without DHA, I had to manually probe the ECU PCB, attach an oscilloscope, to map what each pin does and then later try to correlate my measurements with the logic in the code. Then later on when rkam gave me a list of variables and memory addresses, even with over 100+ named variables, there were pieces of code, logic, which I don't fully understand. Which is why I could only name my variables "Related_to_<X>" and add question marks on possible behaviour.
I wonder if in such cases, it's better to write a whole system SH<x> emulator. I have done some basic boilerplating by adding a new build option for SH2 rather than the SH4 in QEMU. My next step was removing the MMU, but I still couldn't quite figure out the QEMU API. The idea was to get SH2 code executing and fixing whatever snags I hit until for instance we get to the streaming CAN data part and then finally a fully emulated ECU of a running car. Of course QEMU is not cycle accurate and I am not sure if this will be a problem or not. Hope someone has more information on this. In any case I have done nothing beyond just adding a different build option for SH2. The CPU model needs to be changed to implement various interrupts, exceptions etc. I am juggling so many things right now from fixing my entire car to family issues that I simply do not have time.
So far, with just basic emulation with GhidraEmu I have managed to further my knowledge of the Denso internals. I managed to find an opaque CAN interface which is where it was all indirectly used, along with the dynamically constructed data at address FFFF7448.
|
|
« Last Edit: May 01, 2023, 04:42:12 AM by dikidera »
|
Logged
|
|
|
|
prometey1982
|
|
« Reply #34 on: May 15, 2023, 06:17:41 AM »
|
|
|
Generate key for Denso T6 ECM reversed from Pete's PIN application: unsigned int __cdecl GenerateKey(unsigned __int8 *PinArray, unsigned __int8 *SeedArray, _BYTE *KeyArray) { char ShiftsCountForSeed; // bl unsigned int PinValue; // edx unsigned int SeedValue; // ecx unsigned int ProcessedResult; // eax char SeedValueOld; // di char IsEvenSeed; // di char ShiftsCountForPid; // cl char PinValueOld; // si char IsEvenPid; // si unsigned int result; // eax
ShiftsCountForSeed = 32; PinValue = (PinArray[2] << 8) | PinArray[1] | (PinArray[4] << 24) | (PinArray[3] << 16); SeedValue = (*PinArray << 24) | *SeedArray | (SeedArray[2] << 16) | (SeedArray[1] << 8); ProcessedResult = 0xC541A9; do { SeedValueOld = SeedValue; SeedValue >>= 1; IsEvenSeed = ProcessedResult ^ SeedValueOld; ProcessedResult >>= 1; if ( (IsEvenSeed & 1) != 0 ) ProcessedResult = (ProcessedResult | 0x800000) ^ 0x109028; --ShiftsCountForSeed; } while ( ShiftsCountForSeed ); ShiftsCountForPid = 32; do { PinValueOld = PinValue; PinValue >>= 1; IsEvenPid = ProcessedResult ^ PinValueOld; ProcessedResult >>= 1; if ( (IsEvenPid & 1) != 0 ) ProcessedResult = (ProcessedResult | 0x800000) ^ 0x109028; --ShiftsCountForPid; } while ( ShiftsCountForPid ); result = ((ProcessedResult & 0xF00000) >> 12) | ProcessedResult & 0xF000 | (unsigned __int8)(16 * ProcessedResult) | ((ProcessedResult & 0xFF0) << 12) | ((ProcessedResult & 0xF0000) >> 16); KeyArray[2] = result; *KeyArray = BYTE2(result); KeyArray[1] = BYTE1(result); return result; }
|
|
|
Logged
|
|
|
|
prometey1982
|
|
« Reply #35 on: December 23, 2023, 02:24:02 AM »
|
|
|
Algorithm described below is standard algo for Volvo P3 platform. It used for CEM and ECM ME9. Looks like other modules also use it. Tool from PoleStarPete can find PIN for ME9.
|
|
|
Logged
|
|
|
|
prometey1982
|
|
« Reply #36 on: December 23, 2023, 03:08:52 AM »
|
|
|
Slightly modified P3 hash function from vtluint32_t p3_hash(uint8_t pin[5], uint8_t seed[3]) { uint32_t n = 0xc541a9, m = 0x1212050; uint64_t k; uint8_t* in = (unsigned char*)&k;
in[0] = seed[0]; in[1] = seed[1]; in[2] = seed[2]; in[3] = pin[0]; in[4] = pin[1]; in[5] = pin[2]; in[6] = pin[3]; in[7] = pin[4];
for (size_t i = 0; i < 64; i++, n >>= 1, k >>= 1) { if ((n ^ k) & 0x1) n ^= m; } return ((n & 0xF00000) >> 12) | n & 0xF000 | (uint8_t)(16 * n) | ((n & 0xFF0) << 12) | ((n & 0xF0000) >> 16); }
// Then you can you this code to send response to ECM: const auto hash = p3_hash(pin, seed); uint8_t hash_array[4]; hash_array[0] = hash & 0xFF; hash_array[1] = (hash >> 8) & 0xFF; hash_array[2] = (hash >> 16) & 0xFF; hash_array[3] = (hash >> 24) & 0xFF; WriteDataToChannel_402420( ChannelId_40E00C, 7, 0xE0, 5, 0x27, 2, hash_array[0], hash_array[1], hash_array[2], hash_array[3], 0);
|
|
|
Logged
|
|
|
|
dikidera
Full Member
Karma: +8/-8
Offline
Posts: 149
|
|
« Reply #37 on: December 24, 2023, 09:09:53 AM »
|
|
|
If I had a P3 car I could have contributed more with a fat IDB, it would be most difficult without a DHA, but this has never stopped me into sinking hundreds even thousands of hours into reverse engineering a project.
|
|
|
Logged
|
|
|
|
prometey1982
|
|
« Reply #38 on: December 25, 2023, 02:06:35 PM »
|
|
|
ME9 is not simple as Denso T6 ECM. ME9 has 5 digit PIN code. For example here one my firmware for ME9: ROM:000029C0 pin_29C0: .byte 0x70, 8, 0, 0x82, 0x47
// This value is passed to check key function:
void __fastcall sub_90D0C(int a1, char **a2) { char *v3; // r3 int v4; // r5 int v5; // r29 int v6; // r29 int v7; // r3 char v8; // r31 unsigned __int8 v9[4]; // [sp+8h] [-10h] BYREF
if ( byte_800004 ) { v8 = 54; goto LABEL_25; } if ( byte_800005 ) { v8 = 55; goto LABEL_25; } v3 = *a2; v4 = (unsigned __int8)**a2; if ( (v4 & 1) == 0 ) { if ( v4 == 2 ) { if ( *((_WORD *)a2 + 3) == 4 ) { if ( ((HIBYTE(flt_8076FC) >> 1) & 1) != 0 ) { HIBYTE(flt_8076FC) &= 0xFDu; v9[0] = v3[1]; v9[1] = (*a2)[2]; v9[2] = (*a2)[3]; [b] if ( checkKey_9B580(pin_29C0, seed, v9) ) [/b] { sub_967C8(1); *((_BYTE *)a2 + 10) = 1; *((_WORD *)a2 + 4) = 1; return; } byte_800004 = 1; byte_800005 = 100; byte_800006 = 100; v8 = 53; } else { v8 = 36; } } else { v8 = 19; } goto LABEL_25; } goto LABEL_22; } if ( v4 != 1 ) { LABEL_22: v8 = 18; goto LABEL_25; } if ( *((_WORD *)a2 + 3) != 1 ) { v8 = 19; LABEL_25: **a2 = v8; *((_WORD *)a2 + 4) = 1; *((_BYTE *)a2 + 10) = 2; return; } if ( (unsigned __int8)sub_967EC() == 1 ) { v5 = 0; } else { v6 = seed; do { do v7 = sub_9B55C(); while ( v6 == v7 ); } while ( (v7 & 0xFFFFFF) == 0 ); v5 = v7 & 0xFFFFFF; } seed = v5; HIBYTE(flt_8076FC) |= 2u; (*a2)[1] = v5; (*a2)[2] = BYTE2(v5); (*a2)[3] = BYTE1(v5); *((_BYTE *)a2 + 10) = 1; *((_WORD *)a2 + 4) = 4; }
So it's not easy to find key by bruteforce. I found some analysis of CEM PIN code from SPA platform https://v-spa.net/forum/viewtopic.php?p=245#p245maybe ME9 ECM has similar limitations on PIN.
|
|
|
Logged
|
|
|
|
|