BA Falcon BEM EEPROM via CAN

Ford information and tools can be found here
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

Just writing notes down as I go:

00 00 FF 00 = 50 A5
00 00 F0 00 = 50 55
00 00 0F 00 = 50 55

00 00 A5 00 = 50 55
00 00 5A 00 = 50 55
00 00 C3 00 = 50 55
00 00 3C 00 = 50 55

n3 nibble = (b3 >> 4) | (b3 & 0F), plus something else ??

00 00 CF 00 = 50 95
00 00 CA 00 = 50 E5
00 00 C5 00 = 50 95
00 00 C0 00 = 50 45

00 00 FC 00 = 50 95
00 00 AC 00 = 50 E5
00 00 5C 00 = 50 95
00 00 0C 00 = 50 45

n3 nibble = ( (b3 >> 4) ^ (b3 & 0F) ), plus something else ?? -

00 00 A0 00 = 50 A5
00 00 FF 00 = 50 A5
00 00 0A 00 = 50 A5

00 00 AF 00 = 50 F5
00 00 FA 00 = 50 F5

00 00 50 00 = 50 55
00 00 05 00 = 50 55

00 00 00 00 = 50 05
00 00 84 00 = 50 05
00 00 48 00 = 50 05

00 00 04 00 = 50 65
00 00 40 00 = 50 65

00 00 21 00 = 50 15
00 00 12 00 = 50 15

00 00 11 00 = 50 85

00 00 B0 00 = 50 95
00 00 0B 00 = 50 95

00 00 43 00 = 50 75
00 00 34 00 = 50 75

00 00 32 00 = 50 35

00 00 01 00 = 50 95
00 00 10 00 = 50 95

00 00 02 00 = 50 25
00 00 20 00 = 50 25
00 00 F2 00 = 50 75
00 00 2F 00 = 50 75

00 00 03 00 = 50 15
00 00 30 00 = 50 15
00 00 F3 00 = 50 65
00 00 3F 00 = 50 65
00 00 C3 00 = 50 55
00 00 3C 00 = 50 55
00 00 0F 00 = 50 55
00 00 F0 00 = 50 55
00 00 73 00 = 50 85
00 00 37 00 = 50 85

n3 nibble = (0xA & ((b3 >> 4) ^ (b3 & 0F)) | (0x5 & (b3 >> 4) ^ (b3 & 0F)) ???
User avatar
antus
Site Admin
Posts: 9002
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by antus »

It looks to me like there is some XOR, probably against 0x05 or 0x50 as well depending which end, or ^5 and bit shifts.
EG 00 00 ^ 50 00 = 50
and 00 00 ^ 00 05 = 05
so sample
00 00 00 00 gets you 50 05.

But I think it is nibbles, not 8 bit shifts... just I think that is where the 5s come from. And if its XOR that has something to do with FFFF becoming AA as 5 is 0101 so XOR F (1111) with 5 (0101) gives A (1010). But I haven't figured out which bits are which, but it might fit in with what you have so far.

The other interesting one that has to do with those patterns is FF FF 00 00 = AA 05

Actually, 8 tests with a single 5 in a different nibble each time would be interesting. If its XOR then the ones that hit an ^5 in the algo should return all zero, and the ones that hit an ^0 should return the 5 wherever it ends up after bit shifts and anything else should return something else.

This sequence is particularly interesting for ^5. The last two make me wonder if the 84 and 48 are nibble swapped then XORd with the result to cancel each other out.

00 00 50 00 = 50 55
00 00 05 00 = 50 55

00 00 00 00 = 50 05
00 00 84 00 = 50 05
00 00 48 00 = 50 05
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

Yes I agree that makes sense.
And I think the use of A or 5 might have something to do with the non-symmetrical / "overflow" like bit that moves from the 3rd byte to 2nd nibble.
And it will probably become evident once the inner nibble calculation is worked out.
EG. if we are &ing or ^ing a nibble with A or 5, and both sides use the same A or 5, when we reverse/mirror the other stuff but keep the A or 5, we could end up with this kind of thing:

00 00 AA 00 = 51 45
00 AA 00 00 = 54 05

00 0A 0A 00 = 5A 05
00 A0 A0 00 = 5A A5

Where as other than those particular occasions, everything is perfectly mirrored:
00 BA AB 00 = 53 35
00 00 A0 00 = 50 A5
00 0A 00 00 = 5A 05
12 34 43 21 = 77 77
AB CD DC BA = E7 7E
01 2F F2 10 = 47 74

I don't believe the 3rd nibble is using the 2nd byte for its calculation. Because changing it makes no difference other than those special few examples shown above
01 00 F2 10 = 40 74
01 FF F2 10 = 4A 74
01 2F F2 10 = 47 74
01 12 F2 10 = 41 74
01 F0 F2 10 = 45 74

It's also evident the 2nd byte can effect the 1st nibble, but the same mirrored change (3rd byte effecting 4th nibble) does not happen. Again probably because of the use of A or 5:
01 BB F2 10 = 52 74
01 BB BB 10 = 53 24
01 2F BB 10 = 47 24
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

I'm pretty confident the outer most nibbles (1 and 8) of the 4 seed bytes are irrelevant

33 33 33 33 = 62 26
03 33 33 30 = 62 26
02 33 33 20 = 72 27
02 23 32 20 = 73 37
01 23 32 10 = 43 34
01 FF FF 10 = 4A A4


2nd and 7th nibble of seed map directly to 1st and 4th of key:
01 00 00 10 = 40 04
02 00 00 20 = 70 07
03 00 00 30 = 60 06
04 00 00 40 = 10 01
05 00 00 50 = 00 00
06 00 00 60 = 30 03
07 00 00 70 = 20 02
08 00 00 80 = 90 09
09 00 00 90 = 80 08
0A 00 00 A0 = F0 0F
0B 00 00 B0 = E0 0E
0C 00 00 C0 = 90 09
0D 00 00 D0 = 80 08
0E 00 00 E0 = B0 0B
0F 00 00 F0 = A0 0A
As well as when they are not the same, eg:
01 00 00 F0 = 40 0A
Changing 1st and 8th seed nibble, as well as inner 4 nibbles (bytes 2 and 3) also seems to make no difference.

The mapping for this seems to be exactly "seedNibble XOR 0x5", except for these 2:
08 00 00 80 = 90 09
09 00 00 90 = 80 08
User avatar
antus
Site Admin
Posts: 9002
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by antus »

hmmm
8 1000
9 1001

so I guess that might just be some custom logic connecting the highest and lowest bits.

It looks a bit messy but maybe it is as simple as:

nibble =^ 1 if (nibble & 0xE == 8);

Just to swap those two nibble values.

There could actually be similar to check the high bit in a nibble and carry to the next nibble in those scenarios where we see a bit change in a different nibble, rather than an overflow.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

Ok thinking about it again, I contradicted myself.

That would work perfectly well, except:
pman92 wrote: Sat Apr 19, 2025 7:02 pm It's also evident the 2nd byte can effect the 1st nibble, but the same mirrored change (3rd byte effecting 4th nibble) does not happen. ....:
01 BB F2 10 = 52 74
01 BB BB 10 = 53 24
01 2F BB 10 = 47 24
It still would work perfectly well for the RH side (which is mirrored), but not the LH

01 0A 00 10 = 4A 04
01 A0 00 10 = 4A 04
01 AA 00 10 = 54 04

00 00 00 00 = 5 0 0 5

If the LSB of nibble 2 is set, then nibble 3 and 4 (the byte to the right) both being A or B increments it:
01 00 00 00 = 4 0 0 5
01 A9 00 00 = 4 D 0 5
01 AA 00 00 = 5 4 0 5
01 AB 00 00 = 5 3 0 5
01 BA 00 00 = 5 3 0 5
01 AC 00 00 = 4 E 0 5
01 CA 00 00 = 4 E 0 5
01 AD 00 00 = 4 D 0 5
01 DA 00 00 = 4 D 0 5

05 00 00 00 = 0 0 0 5
05 AA 00 00 = 1 4 0 5
05 AB 00 00 = 1 3 0 5
05 BA 00 00 = 1 3 0 5
05 AC 00 00 = 0 E 0 5

However it doesn't happen if LSB isn't set:
02 00 00 00 = 7 0 0 5
02 AA 00 00 = 7 4 0 5
02 AB 00 00 = 7 3 0 5

And it doesn't happen with 0x5 then either:
02 00 00 00 = 7 0 0 5
02 55 00 00 = 7 0 0 5
02 56 00 00 = 7 3 0 5
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

This here is getting pretty close, at least for the first and last key nibble:

Code: Select all

calc(seed1, seed2, seed3, seed4) {
	
	sn1 = (seed1 >> 4) & 0xF;
	sn2 = seed1 & 0xF;
	sn3 = (seed2 >> 4) & 0xF;
	sn4 = seed2 & 0xF;
	sn5 = (seed3 >> 4) & 0xF;
	sn6 = seed3 & 0xF;
	sn7 = (seed4 >> 4) & 0xF;
	sn8 = seed4 & 0xF;

	kn1 = sn2 ^ ((sn2 & 0x8) ? 0x1 : 0x5);
	if( (sn2 & 0x1) && ((sn3 ^ 0xA) < 2) && ((sn4 ^ 0xA) < 2) ) {
		kn1 = (kn1 + 1) & 0xF;
	}
	
	// kn2 yet to be calculated

	// kn3 yet to be calculated
	
	kn4 = sn7 ^ ((sn7 & 0x8) ? 0x1 : 0x5);

	key1 = (kn1 << 4) | kn2;
	key2 = (kn3 << 4) | kn4;
}

29 mismatches found from 199 pairs checked against:
Key Nibble 1:
Out by +4: 8 time(s)
Out by +12: 7 time(s)
Key Nibble 4:
Out by +4: 14 time(s)
Out by +12: 12 time(s)

So the nibbles sometimes end up either 4 more or 4 less than they should be (they wrap around at 16).
Maybe a missing XOR 0x4 ?

Once I work that out I'll move on to looking at the middle nibbles. And then get a script running to pull some random pairs from forscan overnight, and then verify they all match. Probably find some edge cases, then rinse and repeat.
What I'll end up with will probably be much less elegant than how its really done, but if it works it works.
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

This logic seems to work for nibble 1 and nibble 4, at least for all the pairs I've collected to try against so far:

Code: Select all

calc(seed1, seed2, seed3, seed4) {
	
	sn1 = (seed1 >> 4) & 0xF;
	sn2 = seed1 & 0xF;
	sn3 = (seed2 >> 4) & 0xF;
	sn4 = seed2 & 0xF;
	sn5 = (seed3 >> 4) & 0xF;
	sn6 = seed3 & 0xF;
	sn7 = (seed4 >> 4) & 0xF;
	sn8 = seed4 & 0xF;

	kn1 = sn2 ^ ((sn2 & 0x8) ? 0x1 : 0x5);
	if( (sn2 & 0x1) && ((sn3 ^ 0xA) < 2) && ((sn4 ^ 0xA) < 2) ) {
		kn1 = (kn1 + 1) & 0xF;
	}
	if( sn2 >= 0xA ) {
		kn1 ^= 0x4;
	}
	
	// kn2 yet to be calculated

	// kn3 yet to be calculated
	
	kn4 = sn7 ^ ((sn7 & 0x8) ? 0x1 : 0x5);
	if( sn7 >= 0xA ) {
		kn4 ^= 0x4;
	}

	key1 = (kn1 << 4) | kn2;
	key2 = (kn3 << 4) | kn4;
}
Result: All 335 pairs matched.

Moving on to the inner nibbles.
I'm just going to start working on the LH side because the RH looks to be mirrored of it.
Might have to add additional logic if the byte to the RH side == AA or AB for the edge cases as above (For memory that's definitely the case for 3rd nibble, not sure if it applies to the 2nd as well yet)

00 00 00 00 = 50 05
00 01 00 00 = 59 05
00 10 00 00 = 59 05
00 11 00 00 = 58 05
00 0A 00 00 = 5A 05
00 A0 00 00 = 5A 05
00 AA 00 00 = 54 05
00 50 00 00 = 55 05
00 05 00 00 = 55 05
00 E0 00 00 = 56 05
00 0E 00 00 = 56 05
00 EE 00 00 = 5C 05

Only 1 nibble with a value:
(eg. can all be reversed for same result, eg. 10 20 30 40 etc)
00 01 00 00 = 59 05
00 02 00 00 = 52 05
00 03 00 00 = 51 05
00 04 00 00 = 56 05
00 03 00 00 = 51 05
00 05 00 00 = 55 05
00 06 00 00 = 58 05
00 07 00 00 = 57 05
00 08 00 00 = 58 05
00 09 00 00 = 53 05
00 0A 00 00 = 5A 05
00 0B 00 00 = 59 05
00 0C 00 00 = 54 05
00 0D 00 00 = 53 05
00 0E 00 00 = 56 05
00 0F 00 00 = 55 05

A bunch that all come up with "0" 2nd nibble:
00 00 00 00 = 50 05
00 13 00 00 = 50 05
00 31 00 00 = 50 05
00 26 00 00 = 50 05
00 62 00 00 = 50 05
00 48 00 00 = 50 05
00 84 00 00 = 50 05
00 4C 00 00 = 50 05
00 C4 00 00 = 50 05
00 55 00 00 = 50 05
00 5F 00 00 = 50 05
00 F5 00 00 = 50 05

A bunch more:
I've noticed bit 0 (LSB) of keyNibble2 = seedNibble1 LSB ^ seedNibble2 LSB
Backs up them being XOR with each other (also the order of the nibbles doesn't matter, eg. 12 produces same result as 21)

00 10 00 00 = 59 05
00 11 00 00 = 58 05
00 12 00 00 = 51 05
00 13 00 00 = 50 05
00 14 00 00 = 55 05
00 15 00 00 = 54 05
00 16 00 00 = 57 05
00 17 00 00 = 56 05
00 18 00 00 = 53 05
00 19 00 00 = 52 05
00 1A 00 00 = 59 05
00 1B 00 00 = 58 05
00 1C 00 00 = 53 05
00 1D 00 00 = 52 05
00 1E 00 00 = 55 05
00 1F 00 00 = 54 05

00 20 00 00 = 52 05
00 21 00 00 = 51 05
00 22 00 00 = 54 05
00 23 00 00 = 53 05
00 24 00 00 = 58 05
00 25 00 00 = 57 05
00 26 00 00 = 50 05
00 27 00 00 = 59 05
00 28 00 00 = 56 05
00 29 00 00 = 55 05
00 2A 00 00 = 5C 05
00 2B 00 00 = 5B 05
00 2C 00 00 = 56 05
00 2D 00 00 = 55 05
00 2E 00 00 = 58 05
00 2F 00 00 = 57 05

00 30 00 00 = 51 05
00 31 00 00 = 50 05
00 32 00 00 = 53 05
00 33 00 00 = 52 05
00 34 00 00 = 57 05
00 35 00 00 = 56 05
00 36 00 00 = 59 05
00 37 00 00 = 58 05
00 38 00 00 = 55 05
00 39 00 00 = 54 05
00 3A 00 00 = 5B 05
00 3B 00 00 = 5A 05
00 3C 00 00 = 55 05
00 3D 00 00 = 54 05
00 3E 00 00 = 57 05
00 3F 00 00 = 56 05

00 40 00 00 = 56 05
00 41 00 00 = 55 05
00 42 00 00 = 58 05
00 43 00 00 = 57 05
00 44 00 00 = 52 05
00 45 00 00 = 51 05
00 46 00 00 = 54 05
00 47 00 00 = 53 05
00 48 00 00 = 50 05
00 49 00 00 = 59 05
00 4A 00 00 = 56 05
00 4B 00 00 = 55 05
00 4C 00 00 = 50 05
00 4D 00 00 = 59 05
00 4E 00 00 = 52 05
00 4F 00 00 = 51 05

00 50 00 00 = 55 05
00 51 00 00 = 54 05
00 52 00 00 = 57 05
00 53 00 00 = 56 05
00 54 00 00 = 51 05
00 55 00 00 = 50 05
00 56 00 00 = 53 05
00 57 00 00 = 52 05
00 58 00 00 = 59 05
00 59 00 00 = 58 05
00 5A 00 00 = 55 05
00 5B 00 00 = 54 05
00 5C 00 00 = 59 05
00 5D 00 00 = 58 05
00 5E 00 00 = 51 05
00 5F 00 00 = 50 05

00 60 00 00 = 58 05
00 61 00 00 = 57 05
00 62 00 00 = 50 05
00 63 00 00 = 59 05
00 64 00 00 = 54 05
00 65 00 00 = 53 05
00 66 00 00 = 56 05
00 67 00 00 = 55 05
00 68 00 00 = 52 05
00 69 00 00 = 51 05
00 6A 00 00 = 58 05
00 6B 00 00 = 57 05
00 6C 00 00 = 52 05
00 6D 00 00 = 51 05
00 6E 00 00 = 54 05
00 6F 00 00 = 53 05
User avatar
pman92
Posts: 577
Joined: Thu May 03, 2012 10:50 pm
Location: Castlemaine, Vic
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by pman92 »

Haven't found the inner nibble calculation yet.
I've been running a python script that generates regular expressions and runs them on the full set of seed/keys from "00 00 00 00" to "00 FF 00 00".
It was taking hours per pass until chatGPT helped me setup the script to run multicore - now takes less than 40 minutes.

Matches 94 / 256 sets (36% success):
( (SN3 ^ 0xA) & (SN4 | 0x5) ) ^ SN4
or
( (SN3 | 0x5) & (SN4 ^ 0xA) ) ^ SN3

Matches 75/256 (29% success) :
"SN3 ^ 0xA ^ SN4"

I suspect I will have to break the sets up into separate sets that work / don't work with a formula, and try see if there's any way to identify them for conditional logic / branching.
EG. I already know that if both LSB/MSB's of SN3 and SN4 are clear, the formula "SN3 ^ 0xA ^ SN4" fails every time.

It's also possible I may be able to find a formula that get the top 3 bits right, and I can change the LSB using the simple SN3 ^ SN4 expression (assuming it holds true over larger data sets, which it has so far)

Assuming I'm right that the KN2 and KN3 are mirrors of each other in how they are calculated, and my calculations for the rest hold true, I'm really only searching for 4 bits off data. It wouldn't be unfeasible to implement the whole thing with a 256 byte lookup table. If the LSB really is just SN3 ^ SN4, its only 3 bits and needs a 64 byte lookup table. Since we're only looking up nibbles, store 2 in each byte and its now a 32 byte lookup table. If I run into a wall I might even implement that and then start testing with randomly generated seeds / keys.

Here's a heatmap from chatGPT showing the key nibble 2 results from 00 00 00 00 to 00 FF 00 00:
00toFF SN3 SN4 to KN2.png
User avatar
antus
Site Admin
Posts: 9002
Joined: Sat Feb 28, 2009 8:34 pm
cars: TX Gemini 2L Twincam
TX Gemini SR20 18psi
Datsun 1200 Ute
Subaru Blitzen '06 EZ30 4th gen, 3.0R Spec B
Contact:

Re: BA Falcon BEM EEPROM via CAN

Post by antus »

I reckon you'll find there is another salt in there, like an and or xor with a 3F or some other value.
Have you read the FAQ? For lots of information and links to significant threads see here: http://pcmhacking.net/forums/viewtopic.php?f=7&t=1396
Post Reply