Open YeapGuy opened 10 months ago
How technically feasible is it to modify this project to work with official AirTags or other Find My devices?
Its impossible, you need the private key and you won't get it from official devices.
Already working AirTag clones are being sold for $2-4 a piece on Aliexpress, so I don't see a point in spending a lot of time messing with flashing, firmwares and all of that stuff, when I can just buy a working "AirTag" for so cheap.
These Tags working with the official Findmy SDK, "our" Tags are working with reverse engineering, nothing official. The China ones are also only working with Apple Hardware, "our" Tags are not working official with ios (but with a workaround).
I think I can retrieve the private key from the macOS application. Is that all I need?
The private key is all you need indeed, but that's stored in the Secure Enclave as far as I know. To my knowledge nobody knows how to get that, but if you have ideas please have a crack at it! (and report back here if you succeed)
I successfully retrieved the keys from the macOS Find My application. What's next?
the generate_keys.py
script generates a random key here:
https://github.com/biemster/FindMy/blob/8c2ce60f77f39ea8eca32a012ce319c13dc27b59/generate_keys.py#L28
If you change that line and put there the private key you found for your device, then the script generates a .keys
file for it. Let me know if that works, and also how you retrieved the key please!
On top of that, in case you did find the correct key but you still get zero reports back, it's possible that your fake tag also implemented the key rolling as per spec so you should check if the advertised key from the tag is the same as the advertised key you generated.
@YeapGuy any luck on this? I just stumbled by accident on your swift gist https://gist.github.com/YeapGuy/f473de53c2a4e8978bc63217359ca1e4, did you by any chance use this?
Yep, I used that to get the keys out of the macOS Find My app. See here for what I (or rather, Malmeloo) managed to do with this: https://github.com/malmeloo/FindMy.py/issues/4 Honestly, I'm quite lost in all of this Find My-related stuff, so I can't give a concise explanation. Best to read the linked issue for yourself, you'll probably understand better what's going on 😄
No you can't, trust me. The Code is rolling every 10 Minutes.
He can!
@YeapGuy Is it possible to pull the reports of a device on the network that is not tied to your apple ID?
I successfully retrieved the keys from the macOS Find My application.
Do you mind sharing how you did that?
Not abandoned :) actually the iOS17 issue (#40) seems to be just resolved, so I'm going to put a bit more time into this again.
Awesome that you managed to decrypt the .record
files, I'm planning on adding a script for that here (although @malmeloo in https://github.com/malmeloo/FindMy.py seems to have picked up the ball and did wonderful things on this already)
Your comment is very hard to read, does the public key sent out by your tag in lost mode match the one in the request from request_reports.py
?
Hi @biemster, I hope you're well and haven't abandoned this project yet. I decrypted the .record file of an air tag that's already been added to icloud, got a decrypted.plist which contain:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>batteryLevel</key>
<integer>1</integer>
<key>cloudKitMetadata</key>
<data>
%MASKED%
</data>
<key>identifier</key>
<string>%MASKED%</string>
<key>isZeus</key>
<false/>
<key>model</key>
<string></string>
<key>pairingDate</key>
<date>2024-03-24T11:28:16Z</date>
<key>privateKey</key>
<dict>
<key>key</key>
<dict>
<key>data</key>
<data>
%MASKED%
</data>
</dict>
</dict>
<key>productId</key>
<integer>21760</integer>
<key>publicKey</key>
<dict>
<key>key</key>
<dict>
<key>data</key>
<data>
%MASKED%
</data>
</dict>
</dict>
<key>secondarySharedSecret</key>
<dict>
<key>key</key>
<dict>
<key>data</key>
<data>
%MASKED%
</data>
</dict>
</dict>
<key>sharedSecret</key>
<dict>
<key>key</key>
<dict>
<key>data</key>
<data>
%MASKED%
</data>
</dict>
</dict>
<key>stableIdentifier</key>
<array>
<string>%MASKED%</string>
</array>
<key>systemVersion</key>
<string>2.0.61</string>
<key>vendorId</key>
<integer>76</integer>
</dict>
</plist>
I've bit changed generation in the generate_keys.py file like this
5a6
> from math import ceil
25c26
< priv = random.getrandbits(224)
---
> priv = int.from_bytes(base64.b64decode('%MASKED%'))
28,29c29,33
< priv_bytes = int.to_bytes(priv, 28, 'big')
< adv_bytes = int.to_bytes(adv, 28, 'big')
---
> priv_length = ceil(priv.bit_length() / 8)
> adv_length = ceil(adv.bit_length() / 8)
>
> priv_bytes = int.to_bytes(priv, priv_length, 'big')
> adv_bytes = int.to_bytes(adv, adv_length, 'big')
generate a valid .keys file with a matching private key, but still can't get the location after executing request_reports.py. What am I doing wrong?
generate a valid .keys file with a matching private key, but still can't get the location after executing request_reports.py. What am I doing wrong?
did you confirm with something like nRF connect
that your tag is broadcasting the same key as in the .keys
file?
Your comment is very hard to read
Sorry about that, was posting a comment from my phone and the layout broke, I fixed the post
does the public key sent out by your tag in lost mode match the one in the request from
request_reports.py
?
Unfortunately, no
It doesn't match or you didn't test? Sorry I did not read my own question well enough
did you confirm with something like
nRF connect
that your tag is broadcasting the same key as in the.keys
file?
In my case it's not possible, the tag is already far away from me and I can't just sniff signal
It doesn't match or you didn't test?
The public key from the decrypted.plist does not match the public key I got from .keys file running _generatekeys.py, that's what I meant
It doesn't match or you didn't test?
The public key from the decrypted.plist does not match the public key I got from .keys file running _generatekeys.py, that's what I meant
Ok, are you able to craft a request with the public key from the decrypted plist? That should return reports.
I think there is a bit of logic involved to generate derived public keys from the root private key you got from the .record
. I did not work with that yet, but @malmeloo did so you'll probably find an answer if you ask in his repository.
Ok, are you able to craft a request with the public key from the decrypted plist? That should return reports.
Yes. I'll give it try and let you know
You will not be able to directly retrieve reports using that key. The "shared secret" values in the plist you have are used as a seed which can be used to generate a sequence of keys for the AirTag; it then rotates through these keys on a timed interval to prevent other people from tracking you.
My library has a feature to find possible private keys for a given time period; you can check out an example here. You'll probably need to request location reports for all of the keys it generates in order to get an accurate location history.
Hi, How technically feasible is it to modify this project to work with official AirTags or other Find My devices? Already working AirTag clones are being sold for $2-4 a piece on Aliexpress, so I don't see a point in spending a lot of time messing with flashing, firmwares and all of that stuff, when I can just buy a working "AirTag" for so cheap. The only issue for me is that I have an Android phone (I was able to set the tags up using a friend's iPhone), so I need to get something similar to this project working.