-
Notifications
You must be signed in to change notification settings - Fork 24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Discussion] Further protocol reversing #16
Comments
It look's like I've found the method which validates the received packets. The comments are my interpretation - maybe it helps: private static int b(byte[] paramArrayOfbyte, int paramInt1, int paramInt2) { //Check packet!!! - paramInt1 = start of packet; paramInt2 = length
if (paramArrayOfbyte[paramInt1] == d.j && paramArrayOfbyte[paramInt1 + 3] < 100) //PING RESP with SEQ < 0x64
return d.n; //0
if (paramArrayOfbyte[paramInt1] != d.h) //!=0x6f - register changed
return d.s; //6
byte b1 = paramArrayOfbyte[paramInt1 + 1]; //length
if (b1 != paramInt2 - 2) //invalid length?
return d.s; //6
byte b2 = paramArrayOfbyte[paramInt1 + 2];
if (b2 != d.l && b2 != d.m) //ACK field has to be 0 or 1
return d.s; //6
byte b3 = paramArrayOfbyte[paramInt1 + 3];
if (b2 == d.l) { //request?
if (b3 >= d.o0 || (b3 < 0 && b3 != -64)) //> 0x37 || ( < 0 && != 0xc0(ECU Version) )
return d.r; //5
} else if (b3 >= d.P0) { //register > 0x1f
return d.q; //4
}
if (d.a(paramArrayOfbyte, paramInt1) != paramArrayOfbyte[paramInt1 + paramInt2 - 1]) //invalid checksum?
return d.p; //2
if (b2 == d.l) { //request?
g g = d.a(b3);
if (g == null) //??unknown register?
return d.r; //5
if (g.b != b1 - 3) //??register size?
return d.o; //1
}
return d.n; //0
} |
This is awesome, getting this part figured out would be a huge help to getting the protocol working reliably! I will try to get some time to try the modified app to check registration, and with some luck can get you the data needed to try and implement registration, then there is no need for the official app any more at all. Exciting! |
I've not been able to get the modified app to run :( I get the brief initial splash screen, then a blank screen. Logcat shows the following:
It repeats essentially forever. |
That is interesting:
I'll try to find and remove this check, but since I'm not getting this error, can you try purging all app data and caches? I guess the app stores a checksum somewhere on the device and validates on subsequent launches. |
@buxtronix I've published a new version which should pass the app modification test ;-) |
Here's the registration debug log: |
The XOR value is logged as |
Found it. The following code generates a byte array with the XOR values used. byte[] CalculateXorTable(int security_key)
{
var result = new byte[256];
for (int i = 0; i < result.Length; i++)
{
result[i] = (byte)i;
}
var index = 0;
for (int i = 0; i < 256; i++)
{
index += result[i];
index += security_key;
index %= 256;
var temp = result[i];
result[i] = result[index];
result[index] = temp;
}
return result;
} The The next question is, when and how a new |
phev-update-debug.txt I've attached two more debug files. One is a general refresh of the car status from the app, and the other is the log from when the parking lights are turned on from the app. Perhaps they might give more insight? |
I finally found the method which calculates (and logs) the byte CalculateSecurityKey(byte[] packet)
{
var result = (packet[4] & 0x8) >> 3;
result |= (packet[5] & 0x8) >> 2;
result |= (packet[6] & 0x8) >> 1;
result |= (packet[7] & 0x8);
result |= (packet[8] & 0x8) << 1;
result |= (packet[9] & 0x8) << 2;
result |= (packet[10] & 0x8) << 3;
result |= (packet[11] & 0x8) << 4;
return (byte)result;
} This can then be used to calculate the XOR I would say the algorithm for XOR is now well known. Next step is to understand the registration process. |
I notice a few instances where Example from one of the uploaded debugs:
I can try to fetch more from the app when ext near the car. |
This is misleading, because the app is logging multiple packets in a single row:
The relevant packet starts at byte 7: |
Ah that explains it. So I have implemented the xor algorithm in a local copy of phev2mqtt and it's looking really good at least against captured data, it all matches up. I'll try later with a live connection to the car too. This basically means that the "start" packets that were assumed are actually security key init packets. Not sure if the types and consts should be renamed... |
Tested against my MY18 and it's working! Applied these changes in 3db6f83 Certainly more reliable than the previous method of guessing, however I do still occasionally get something going out of sync, but similar to what I got before.
|
I have also opened #18 to reverse engineer the registration process. |
It's interesting, that the procotol has more features than the app. E.g. the app supports a climate timer duration of 40 minutes if reported by the car, but does not offer this option in the UI: I send the following packet to the app: I can't tell what the car would say to such a timer... |
I started to look into the protocol and stumbled upon the undetermined XOR algorithm - so I decided to dig deeper. Instead of looking at PCAPs or the responses from the car I started implementing a car simulator and connected the official app to it. As of now it looks promising, since I already found that the XOR value is only dependent on the Init connection packet (not the IP, or MAC or anything else I can think of). By modifying the Init connection packet content, I can reproducably change the XOR used by the app.
As of now, it looks like the app uses the data of the Init connection packet AND
0x00080808080808080800
while the first byte has to be0x01
and the last byte is discarded. So we get 8 relevant bits, which is the byte used for determining the initial XOR value. All three of the following init packets result in the exact same XOR value (0x66
) used by the app:After looking at the app (using my scissor ;-) I found three constants to enable debug logging in the app. The modified app can be found here.
By looking at the log output I can tell that the one byte from the init connection packet is logged directly as
security_key
and used further to create the XOR value by some kind ofKEY_MAP
lookup:So the bits are interpreted with the LSB first:
My biggest obstacle right now is that I have only remote access to a car, so it would be great if someone could trace the registration process (so I can at least add a static example to my vehicle emulator). The log output of a registered app would be helpful as well.
To create the log file, you would need to install the modified app (which may remove the registration and all the data associated with the app - at least it did for me) and enable USB debugging. The log can then be extracted with
adb logcat -s iMobile2
.The text was updated successfully, but these errors were encountered: