seemoo-lab / openhaystack

Build your own 'AirTags' šŸ· today! Framework for tracking personal Bluetooth devices via Apple's massive Find My network.
https://owlink.org
GNU Affero General Public License v3.0
8.27k stars 447 forks source link

Tracking on non-Macs #63

Open AwesomestCode opened 3 years ago

AwesomestCode commented 3 years ago

Problem The problem: it's limiting to not be able to track things on non-Mac computers.

Solution Reverse-engineer either the local Find My API or the Find My web app and allow for tracking on non-Macs

Alternatives

Additional context I understand that this is an long term goal and that either way it's easier said then done. It may be worthwhile to try seeing how auth is done for the Find My web app and then MITM'ing the connection to see how it requests the location.

Astu04 commented 2 years ago

Has anyone gotten Dadoum/Provision to work? When trying their 'X-Apple-I-MD' and 'X-Apple-I-MD-M' I always get a 401 Unauthorized on the https://gateway.icloud.com/acsnservice/fetch endpoint.

vekexasia commented 2 years ago

This is interesting guys. I'm following th openhaystack project for a while now. but i don't own a mac. I guess my only way to integrate is to use proxmox right? I have a low end mini-pc i could use for this but i am not sure performance wise it willl work.

darthnithin commented 2 years ago

This is interesting guys. Iā€™m following th openhaystack project for a while now. but i donā€™t own a mac. I guess my only way to integrate is to use proxmox right? I have a low end mini-pc i could use for this but i am not sure performance wise it willl work.

Yea thatā€™s why non-mac is something a lot of people want, you canā€™t exactly run macos on a raspberry pi šŸ˜…

vekexasia commented 2 years ago

For those landing here. I solved my issue by installing monterey on a proxmox installation of mine and set up this. Then I adapted the mobile app to run on windows and linux which is my main OSes.

mrx23dot commented 1 year ago

Are there any limitations on the Apple API, like rate limit, limited set of public key hashes etc? Do they know if I query for more than 16 allowed devices per account?

biemster commented 1 year ago

I remember there being no rate limit, and a maximum of 256 hashes per request, but I can't seem to find anymore the source of this so take it with a grain of salt.

bluegizmo83 commented 1 year ago

@Sn0wfreezeDev would it be possible for you to compile a release of your private fork app that has the simple-server? It appears the 0.3.3 release version in your private fork doesn't have the server in it, and I can't compile it myself because my MacOS VM I'm running is only running BigSur (11.6.6) and the Xcode tools from the app store needed to compile from source require MacOS 12.5 or later...

dakhnod commented 11 months ago

So, would anyone please share how to limit the number of received location reports? I do not even need limiting by timestamp, but just receiving a limited number of newest reports, as few as possible.

Itheras commented 11 months ago

So, would anyone please share how to limit the number of received location reports? I do not even need limiting by timestamp, but just receiving a limited number of newest reports, as few as possible.

remove the timestamp attribute completely from the request. that will limit the result to the newest 20.

dakhnod commented 11 months ago

So I removed search.startDate and search.endDate, and I do still get heaps of report. Do you mean 20 reports per hash or 20 reports in total?

Itheras commented 11 months ago

Sorry you are right you actually get 20 latest per hash. That is the minimum i think we can get without figuring out why the start and end parameters are not working as expected. Without them it seems the default is 20 per hash.

JJTech0130 commented 11 months ago

If people are still interested in this, it is definitely possible. I've released https://github.com/JJTech0130/pypush, and while it only reverses the iMessage API, the same can certainly be done for OpenHaystack. As far as I can tell, you need two things:

  1. "Anisette Data"
  2. search party token

The first is simply an obfuscated algorithm, it can be easily emulated as demonstrated in several projects like Dadoum's Provision, SideStore's omnisette

The second is a token tied to your Apple ID as far as I'm aware, but I think I've seen it go by as I captured login requests to iCloud. I could probably take a look, I don't think it's too hard if you just need the token...?

JJTech0130 commented 11 months ago

Has anyone gotten Dadoum/Provision to work? When trying their 'X-Apple-I-MD' and 'X-Apple-I-MD-M' I always get a 401 Unauthorized on the https://gateway.icloud.com/acsnservice/fetch endpoint.

That's interesting... I can see two possibilities. Either Apple is embedding the device type that generated the data in the encrypted headers (which is totally plausible, Provision emulates the version from Apple Music for Android), or Apple is simply remembering which devices have logged into a particular iCloud Account (which they already do, as anisette header's primary purpose is to bypass the 2FA code on "trusted devices".

EDIT: I have no issue using anisette data from Provision with this. Seems like the whole point is moot.

biemster commented 11 months ago

There are people very interested in this still! I'm using macOS in a VM at the moment to get the anisette data and the search party token, but some lighter setup would be highly preferable. The latter should indeed be passed on when logging in to iCloud, so a nice combined solution for both anisette data and this token would be awesome.

biemster commented 11 months ago

@JJTech0130 just to confirm, SideStore's omnisette needs to run on a mac? We have already several good solutions to get this data from a running mac, only a fully non-Mac solution is still not found.

biemster commented 11 months ago

@JJTech0130 appologies I started typing without looking at pypush, that looks awesome! So you can do a full appleID login in pure python? Then it would probably be just a small step to also get the data needed for OpenHaystack indeed! If you could look into this would be great, I can help out with testing and stuff too if needed.

vekexasia commented 11 months ago

subscribing to this. running a VM just for having a mac running is a pain :)

mrx23dot commented 11 months ago

is there a way to get the current mail token from iphone? then it's just a matter of calling the http endpoint from ANY device.

Or someone could host a MAC server behind a custom API and rate limiting to 1/sec, returning the encrypted location. (if MAC server is already running might as well share it), we could also have a list of backup servers, never owned a MAC, but I can help with the API.

JJTech0130 commented 11 months ago

@JJTech0130 just to confirm, SideStore's omnisette needs to run on a mac? We have already several good solutions to get this data from a running mac, only a fully non-Mac solution is still not found.

Nope, SideStoreā€™s omnisette is emulated just like Provision, can run on Linux etc.

JJTech0130 commented 11 months ago

Ok, I figured out how to get the search party token from scratch (along with tons of other tokens). Not really that hard, it's returned in the login request, I already had it implemented just needed to add mobileme (iCloud) to the list of "delegates" we wanted to log into.

Right now I just query a linux server for anisette data as it's easier that way.

I'll publish the script later today, it's not that much on top of pypush, just like 60 lines of code. Note that I haven't actually tested the token in OpenHaystack (never used it myself), but it's a token called searchPartyToken that's really long so I assume it's right.

JJTech0130 commented 11 months ago

https://github.com/beeper/pypush/blob/openhaystack/examples/openhaystack.py

Here it is! šŸŽ‰ Instructions:

  1. git clone https://github.com/beeper/pypush -b async
  2. pip3 install -r ./requirements.txt
  3. python3 ./examples/openhaystack.py

Should prompt you for username, password, and 2FA code. It may show you logging in in the location of SideStore's Linux server, since the location is based on Anisette data.

Note that it will not work if you have only SMS 2FA on your account and not trusted devices, due to me not bothering to implement that. Maybe I will do so soon if it becomes necessary.

Please report back if it works, I've not tested it with OpenHaystack. I can now confirm that it can fetch location reports. I haven't used it with actual OpenHaystack yet.

Also, please note some things about the ways this works:

EDIT: I just updated openhaystack.py so that it should save the dsPrsId and searchPartyToken it needs to openhaystack.json for later use. I also had it make a sample request for location data and print that, so that you can verify it works. This could be used in place of ReportsFetcher directly if a simple API was put in front of it (I think such a thing already exists, but not sure how to implement it?) EDIT 2: I have now merged it into the async branch of pypush. Once that branch is done, it will be merged into main.

JJTech0130 commented 11 months ago

@Sn0wfreezeDev I'm just wondering what your opinion is, legally, on my current method of using extracted binaries from macOS to emulate the obfuscated algorithms. If it helps, the binary can be extracted from an old macOS Mountain Lion patch update, which is < 100MB, but that requires parsing the update file which I never bothered to do.

I'm assuming that using a binary directly embedded in the repo opens me up to more legal risk? We am looking into deobfuscating it, I have a friend who has written some purpose built tools, but that's still a ways off.

biemster commented 11 months ago

This is absolutely awesome! I'll try this today, with my own python implementation of OpenHaystack (https://github.com/biemster/FindMy), I could even create a PR to add this functionality to pypush? It's all python already anyway. ~One thing I'd be curious to see, is that I was under the impression that the search-party-token and the anisette data are somehow connected (I think there is a hardware serial involved at some point in the creation of either). But I guess I'll find out later today.~ EDIT alright I did not read your update to the post, using anisette data from another machine does not seem to be an issue :partying_face:

biemster commented 11 months ago

This is brilliant. Although needs some polishing: asn1crypto is a requirement now, and on my python 3.11 I'm getting an error in HMAC which I can fix by importing from Crypto.Hash import SHA256 and use that instead in encrypt_password's PBKDF2. Last thing for me to solve is the MOBILEME_TERMS_OF_SERVICE_UPDATE instead of a search party token.

biemster commented 11 months ago
  • I use a server for anisette, but it could be emulated in a similar manner to the validation data if necessary, or using omnisette or another standard anisette server.

Emulation like the validation data would definitely have my preference, and I am more than willing to help out if it's a lot of work. This should go via retrieveOTPHeadersForDSID in AOSKit right @JJTech0130 ? Do you already know how to emulate that framework?

mrx23dot commented 11 months ago

@JJTech0130 we could also store the 2FA seed in the config. Since we use burner accounts, that way if we are logged out it could auto login.

biemster commented 11 months ago

Since we use burner accounts

We can use burner accounts for this? How to set that up? But yeah if its possible to store the seed that would be great, this 2FA is really a bother.

mrx23dot commented 11 months ago

I wouldn't use my main appleID account just in case it would be flagged up violating ratelimit whatnot. This looks promising https://github.com/pyauth/pyotp

JJTech0130 commented 11 months ago
  • I use a server for anisette, but it could be emulated in a similar manner to the validation data if necessary, or using omnisette or another standard anisette server.

Emulation like the validation data would definitely have my preference, and I am more than willing to help out if it's a lot of work. This should go via retrieveOTPHeadersForDSID in AOSKit right @JJTech0130 ? Do you already know how to emulate that framework?

We actually emulate at a library lower then that, you need to make several calls and perform some HTTP requests to set it up. It's much easier to emulate the library from Android Apple Music (which is what the server is doing, so we know it works), however, my emulation code was written to parse mach-o binaries so it would be a pain to adapt.

JJTech0130 commented 11 months ago

This is brilliant. Although needs some polishing: asn1crypto is a requirement now, and on my python 3.11 I'm getting an error in HMAC which I can fix by importing from Crypto.Hash import SHA256 and use that instead in encrypt_password's PBKDF2. Last thing for me to solve is the MOBILEME_TERMS_OF_SERVICE_UPDATE instead of a search party token.

Hrm. I thought I fixed the MOBILEME_TERMS_OF_SERVICE_UPDATE by changing the X-Mme-Client-Info... does it happen for all accounts for you? I'll look into it.

biemster commented 11 months ago

I only have one account (and I only use it for this). I've seen this before, and assumed it was related to the anisette data and search-party-token not matching, but that was just a wild guess from me at the time. Although I do remember reading about it but can't for the life of me find the source anymore.

JJTech0130 commented 11 months ago

Can you join the pypush discord (https://discord.gg/BVvNukmfTC)? Itā€™s easier for me to help debug there.

biemster commented 11 months ago

yes I'm there already

JJTech0130 commented 10 months ago

The MOBILEME_TERMS_OF_SERVICE_UPDATE has been fixed by using an older API endpoint. I've also merged this into the async branch of pypush. Once I've got all the async rewrite work done that will be merged into main.

biemster commented 10 months ago

@JJTech0130 we could also store the 2FA seed in the config. Since we use burner accounts, that way if we are logged out it could auto login.

@mrx23dot How do these TOTP numbers work? Are they tied to a device or an Apple ID? I've looked into this for a couple days now but can't find such a seed anywhere, neither device or appleID tied ones.

JJTech0130 commented 10 months ago

They're definitely tied to the device, the prompts are sent as APNs notifications with a placeholder for the code... it's probably something with GrandSlam considering the ability to generate codes shows up on the devices page...

Honestly though I don't know if it's worth it... if you have the same anisette data (by emulating rather than using a server) that will bypass 2FA on subsequent logins, easier to fix that.

biemster commented 10 months ago

Yeah emulating anisette data is the way to go here, but that seemed more complicated with my set of skills than extracting a totp seed and I wanted to work on freeing myself from my macOS VM :) So while the anisette emulation is still boiling, I'll see what I can do on the totp seed which would also be fun to have, thanks for this info!

biemster commented 10 months ago

I went with https://github.com/Dadoum/anisette-v3-server for the anisette data, works like a charm nice and lean. I'll be refactoring https://github.com/biemster/FindMy around this and https://github.com/beeper/pypush/tree/openhaystack the coming days.

Jaykob commented 10 months ago

Thanks for your awesome work @biemster Can you notify us here when you're done?

biemster commented 10 months ago

biemster/FindMy is now fully relying on anisette-v3-server and pypush, but that's a bit of an intermediate solution. I'll pop back in when the anisette stuff is a full python solution, that should enable us to remove the anisette-v3-server requirement.

vekexasia commented 10 months ago

Just to be clear, this means I can finally ditch the Monterey VM?

On Tue, Nov 14, 2023, 15:38 biemster @.***> wrote:

biemster/FindMy is now fully relying on anisette-v3-server and pypush, but that's a bit of an intermediate solution. I'll pop back in when the anisette stuff is a full python solution, that should enable us to remove the anisette-v3-server requirement.

ā€” Reply to this email directly, view it on GitHub https://github.com/seemoo-lab/openhaystack/issues/63#issuecomment-1810348852, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABQ6S7AQNXYRMNAK54ILSTYEN67PAVCNFSM45VELK42U5DIOJSWCZC7NNSXTN2JONZXKZKDN5WW2ZLOOQ5TCOBRGAZTIOBYGUZA . You are receiving this because you commented.Message ID: @.***>

biemster commented 10 months ago

You'll need the VM as the initial trusted device to get your anisette server trusted, but after that you can ditch it. (when pypush implements SMS 2FA you'd not need it at all anymore, not even for first auth)

niggowai commented 10 months ago

You'll need the VM as the initial trusted device to get your anisette server trusted, but after that you can ditch it. (when pypush implements SMS 2FA you'd not need it at all anymore, not even for first auth)

If you got yourself an iPhone or iPad, I think you may already purge the VM, but I can't test it

btw. I created a fork of headless-haystack in which I used code of @biemster's FindMy to use the web-app/Android-App without the need to run a mac all the time in the background

olivluca commented 10 months ago

You'll need the VM as the initial trusted device to get your anisette server trusted, but after that you can ditch it. (when pypush implements SMS 2FA you'd not need it at all anymore, not even for first auth)

Are you sure once the anisette server is trusted it will never ask for 2FA again? I'll keep the VM around, just in case.

biemster commented 10 months ago

Yeah not fully sure, only time will tell.. (I also keep the VM on disk)

niggowai commented 10 months ago

Yes me too, but I don't care since I'm tinkering a lot around, a device for 2fa is still good to have. But it wasn't a problem for me to transfer the anisette data to another device and there I could also login to the same account without 2fa

rkreutz commented 10 months ago

Maybe this could help with the 2FA SMS on pypush https://github.com/fastlane/fastlane/blob/master/spaceship/lib/spaceship/two_step_or_factor_client.rb

JJTech0130 commented 10 months ago

If I'm remembering this correctly, that is using the IDMSA API, which is an OAuth/Web wrapper around the raw GSA/HSA authentication pypush is using? Not certain on that though. In any case, SMS 2FA shouldn't be hard, it just requires me (or someone else) to sit down and work on it, which I haven't had time to do.

rkreutz commented 10 months ago

Makes sense, it does seem to be using IDMS. I remember a while ago having similar issues, and a workaround it was doing the 2FA step from a browser, for instance do the login on pypush, then when 2FA is requested you login to AppleID from a browser, that would send the SMS and you can just use that second factor on pypush, this used to work in the past not sure if they patched this behaviour in recent years

biemster commented 10 months ago

That's a great idea, I got stuck in the raw GSA route because it keeps telling me I don't have trusted phone numbers. I'll try to use the normal trusteddevice code path, and implant some call(s) to idmsa somewhere when it asks for 2fa.