malmeloo / FindMy.py

🍏 + 🎯 + 🐍 = Everything you need to work with Apple's FindMy network!
http://docs.mikealmel.ooo/FindMy.py/
MIT License
59 stars 7 forks source link

Some location reports are not decodable #27

Open malmeloo opened 2 months ago

malmeloo commented 2 months ago

Context: https://github.com/malmeloo/FindMy.py/issues/4#issuecomment-2074623370

There has been at least one case where a location report from a real AirTag was not decodable. Maybe this an issue on Apple's side?

In any case, this edge case should be handled better than straight up crashing.

Example:

2bd8e645000504dee6a88ab4580e4c90dcacc62e0efae57a003a1bac1212ba670398be61cb648e08417cf3714ee0429f961793aa645600a7f69807e215292da3a6bda511953cb15b4840de16e26c17651eef760e77fa4b2ca5
faceless2 commented 2 months ago

Some other payloads that I've been unable to decrypt:

2bd7b26900010468fa7f5fa00df3fc86cc4755d130e5f537ae03d5121743dc262f52c5cd63ca7a2db12b4aa600cdae3c2fd8a840a046f0bb54cf27106c0312023fe1e6b6366c5be42e0bd2e7a0cdd3412e5aa9f730a4121b76
2bd7b2d40003043f47398bbf9e5a782e467213d5117c54dbacb9b33f21a300db53b7d56252ecce50f083b33bce8783b053fc98ab05dcc6dd0797877f6a35858e3390bb5094fe0a9a3bf55f7b773e91c39cdc96c1d67b3317e6
2bd7b0da000204065c7c4452eb311f0c6098554eb408184bad5b959170ef6be409f9dd3caa86809703cec89526f8c1d1929148e40c8e9a5d6ade8c54fbf4f21306b56595471b29d93b88340943f18a4a9108bfc4813bd3648f

These are from an iPhone, not an airtag, but it indicates that maybe a try/except around the _decrypt_payload isn't a bad idea, at least until the format of these is better understood.

EDIT: the payload from the original issue, so it's all in one place, was

2bd8e645000504dee6a88ab4580e4c90dcacc62e0efae57a003a1bac1212ba670398be61cb648e08417cf3714ee0429f961793aa645600a7f69807e215292da3a6bda511953cb15b4840de16e26c17651eef760e77fa4b2ca5
malmeloo commented 2 months ago

I currently don't have access to any decodable report payloads because my custom tag broke, but from what I can tell the payload is one byte too long. If I leave out that 0x04 in position 6, the EC point is at least decodable, so it looks like some reports simply have an asn.1 null prepended to their key values for some reason.

Could you try adding the following to the top of _decrypt_payload and see if that fixes the problem?

if payload[6] == 0x04:
    payload = payload[:6] + payload[7:]
faceless2 commented 2 months ago

Doesn't help sorry, because I was wrong about ASN.1 - it's just coincidence that 0x04 means an octet-string. EC keys are typically stored as specified in X9.62 (helpful: https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TR03111/BSI-TR-03111_V-2-1_pdf.pdf, sect 3.2.1), which has an uncompressed format that is 0x04 then the x and y values, but I'm not even convinced that's being used here.

Based solely on the packets seen so far I think we have a format like this:

Which I appreciate leaves quite a bit undefined, but at least it explains what we're seeing. It's definitely not X9.62 because when byte 5 is 2 or 3, it's not followed by a compressed EC key - both because the rust_openssl.ec.from_public_bytes can't parse it, and because the packet is too long.

Anyway. This is going to be a real rabbit hole, clearly, so I'm going to back off. I'd guess explicitly checking for byte 5 == 4 and length=88 before trying to decode makes sense.

ubertao commented 2 months ago

I'm having this issue too:

Example payload from an AirTag clone cannot be decoded:

2bda2c4200090431ae73c2dc41ed1e6f24235c9ebf9bfeeb804f454f4b5301ddb0f61c875fdfd216d34dc6326a05a5315113b36dea3fe092c1277a21ed79f6662b4d428764732c504f9b2f17dae44d0e515edbe4eb0a6277c2
malmeloo commented 2 months ago

Thanks to the both of you! In my previous comment I actually messed up the byte position (5 instead of 6). From those samples it almost looks like that extra byte means something else entirely, because the 6th byte is always 0x04, which is the expected value. Maybe Apple has introduced a new payload format?

Once I get a hold of my stlink (next week?) I'll fix my tag and poke at this issue a bit more. For now, #28 includes a fix to skip invalid reports entirely, so that should at least make it functional again.

Informatic commented 2 weeks ago

FYI changing 5:62 to -16 - 10 - 57 : -16 - 10, 62:72 to -16 - 10 : -16 and 72: to -16: respectively (as used in other openhaystack-derivative projects) in findmy/reports/reports.py:_decrypt_payload fixes decryption of new report formats.

robertsmd commented 5 days ago

https://github.com/seemoo-lab/openhaystack/pull/250/commits/422328339dfab99c4daefe9e803332e1d009e012

openhaystack has updated their parsing of 89 byte reports by removing the 6th byte. See MR #47 for fix