[Public version] iMessage phone number registration on Android devices, without a separate SIM card! Special thanks to itsjunetime and ericmigi for Objective-C help and advice!
Also, if you need a version for 10.x, 9.x, 8.x, or 7.x, check out VintagePNR, which does the same thing as SIMLessPNRGateway, but for these older iOS versions. 8.x and 7.x might take some minor tweaking to work, but I've tested it on 10.3.3 and it works great.
This is version 2 of the older PNRGatewayTweak and PNRGatewayClient.
This tweak/Android app system allows you to register an Android phone number to iMessage! You'll need a jailbroken iPhone (I have a 5S on 12.5.7, results may vary by device and iOS version), but it doesn't need to have its own SIM card anymore! This is more of a demo version, so there's still a fair amount of manual copy/pasting to/from the iPhone, Android phone, etc. If you're interested in a standalone solution, PNRGateway Version 1 (linked above) requires you to have an active phone plan and SIM card in the iPhone (I used a cheap IoT SIM plan for $2ish/month), but is more stable and will work automatically. Version 2 right now requires lots of manual copying/pasting, so it's more intended for use in an existing application where you can send the data back and forth over the internet using something like Firebase or HTTP.
- Install theos if you haven't already
- Install MRYIPC for Theos following the first step under "How to use": (copy
MRYIPCCenter.h
to$THEOS/include
andusr/lib/libmryipc.dylib
to$THEOS/lib
) cd
into the project directory- Run
make package
. This creates a.deb
file in thepackages
directory--transfer that to your iOS device and install it. - Alternatively to step (3), if you have SSH enabled on your iPhone, open the Makefile and change
THEOS_DEVICE_IP
to your iPhone's IP Address, and then runmake package install
. You'll have to enter your iPhone password twice (the default password is alpine)
You'll need an iPhone 5S running iOS 12.5.7 (the lastest version as of writing). Other iPhones and versions may work but are untested.
You'll also need to have PNRGatewayClientV2 installed on your Android phone, with notification and SMS permissions.
You'll also need a way to view your iPhone's logs. The Console app on Mac appears to be the easiest way to do that
It's also super helpful to have a quick way to send snippets of text between your computer and Android phone. Any messaging app installed on both will do just fine
- Ensure FaceTime and iMessage are both turned off in the iPhone settings. Also make sure you're SSHed into your iPhone
- On your iPhone, make a text file in the root directory:
/pnr_android_number.txt
, and set its contents to your Android phone's number in international format (ex.+11234567890
) - Make sure your gateway address is set correctly in the Android app. This is the Apple phone number that your phone talks to to receive the SMS. This varies by carrier--on AT&T it's
28818773
, on T-Mobile MVNOs (like Google Fi) it's22223333
, and on lots of other carriers it's+447786205094
. If you're unsure, you can usually find it on your iPhone in/System/Library/Carrier Bundles/iPhone/[your carrier]/carrier.bundle
underPhoneNumberRegistrationGatewayAddress
. - Modify
ANDROID_PHONE_NUMBER
at the top ofpnrsender/Tweak.x
to your Android phone's number (in international format) - Install Theos and run
make package
inside bothpnrsender
andreceivepnr
and install the .deb to your device. You could also usemake package install
if Theos and your iPhone are set up with SSH - At this stage, I like to SSH into my iPhone and
killall identityservicesd
for good measure - Open the Console app on your Mac and filter for "PNRGateway". (All the log messages start with PNRGateway so it's easy to filter for them)
- Open Settings on the iPhone and select "Messages". Switch iMessage on. If no log messages appear,
killall identityservicesd
, turn off iMessage, and try again. - In the Console app on your Mac, you should see a log message like
>>>> PNRGateway: Push Token Received!
Copy this entire log message and paste it into the PNRGatewayClientV2 Android app. Don't click Send just yet! - Make sure you can see a log message that says
>>>>> PNRGateway: Device tried to send SMS Identification!
. Once you can, click "Send REG-REQ SMS!" in the Android app - You should see a notification on your Android phone that says "REG-RESP Message Received!" Click Copy, which will copy the "REG-RESP?v=3..." message to your clipboard
- On the SSH session on your computer, run
ReceivePNR "[REG-RESP message you copied earlier]"
, pasting in the REG-RESP message you copied from the Android phone - That's it! With a little luck, your iPhone should show your Android phone's number as registered for iMessage, and you should be able to send iMessages to your phone number while keeping your SIM in your Android phone!
If you'd like to understand how the phone number registration process works, I highly recommend reading my write-up of how the original PNRGateway worked, as it has lots of background of how the iMessage registration system works.
Basically, version 1 modified IDSPhoneNumberValidationStateMachine
(among other libraries) on the iPhone such that it sends the REG-REQ
SMS first to the Android phone, before the Android phone sends it off to Apple's registration phone number. This would cause Apple to see the iPhone's request SMS as originating from the Android phone's number, thus tricking the iPhone into registering for iMessage on the Android phone's number.
SIMLessPNRGateway essentially does the same thing, except it's modified such that the iPhone can still register without a SIM card in it at all.
Most of the code in the tweak is just overriding lots of methods in identityservicesd to convince the iPhone it has a SIM card in it, but here's how the actual registration process differs from that of Version 1--it involves a much deeper understanding of the contents of the REG-REQ
and REG-RESP
SMS messages
- The iPhone skips the preflight entirely--A call to
- (void)_sendPreflightVerificationIfNeeded
will now just start the SMS registration process with[self _sendSMSVerificationWithMechanism:nil];
- Instead of the iPhone sending the SMS itself, we extract the push token and generate the
REG-REQ
SMS on the Android side.- The REG-REQ message has the format
REG-REQ?v=3;t=76AAFD15711EF157CF1B8F90FAF21B561CB12EFCE9DE861D8AAE6816CF4A8A71;r=8875166862
- The
v=3
indicates the version of Phone Number Registration to use. On my iPhone it's always 3, on older phones it might use an older version - The
t=76AA...
is the iMessage push token of your device. This is how Apple identifies your device on the iMessage network. It acts a lot like a "shell" user ID that your phone numbers/emails/etc are attached to. Thus, when others type your phone number or email into their iPhone, it'll look up your push token in Apple's big database and send an iMessage to it. - The
r=
is the request number (the REG-RESP message will contain a matching number). Appears to be random--the PNRGatewayClientV2 Android app just generates this randomly and that appears to be fine
- The REG-REQ message has the format
- The Android phone receives the
REG-RESP
SMS from Apple- In version 1 of PNRGateway, it just sends this back via SMS so the iPhone can process it. In version 2 this isn't possible (the iPhone can't receive SMS message anymore), so it just shows a notification and leaves transporting the SMS as an exercise to the user. If you're integrating this into an app, of course, you'll want to use some sort of push notification delivery system to send this over the internet. (Adding push notification support into the tweak was out of the scope of this proof-of-concept, but I wish you the best of luck!)
- The
ReceivePNR
.deb is just a command-line tool. There's no technical requirement for it to be a spearate tweak (and if you're integrating push notifications it'll probably make more sense to just make one), but I split it out as a separate command line tool to make it easy to paste in the REG-RESP message over SSH. - Also, some fun information about the contents of the REG-RESP message!
- The REG-RESP message has this format:
REG-RESP?v=3;r=72325403;n=+11234567890;s=CA21C50C645469B25F4B65C38A7DCEC56592E038F39489F35C7CD6972D
- The
v=3
is the version number, just like in the REG-REQ message - The
r=72327403
is the request number, which is exactly the same as in the REG-REQ message - The
n=+11234567890
is the phone number Apple thinks you have. In this example it's+1 (123) 456-7890
- The
s=CA21C5...
is a digital signature, which is how Apple verifies that your phone number and push token are linked. Apple appears to be running a certificate authority over SMS, where it signs push tokens alongside the phone number they come from (which is just bonkers).
- The REG-RESP message has this format:
That's about it as far as major technical differences go--most of the rest of the tweak is just playing whack-a-mole on which methods tell identityservicesd whether it has an active SIM in the phone or not, as well as a little state modification so the iPhone is able to accept the REG-RESP SMS when we pipe it in. I tried to put in some helpful block comments throughout the tweak, so hopefully those will make sense.
I also learned a little bit about the different stages of registration. If you've unredacted the iOS logs, you should see lots of log messages displaying a registration info that looks like this:
Registration info (0x1013cd720): [Status: Waiting for Authentication Response] [Type: Phone Number]...
There are five different statuses that I've observed
Status | Description |
---|---|
Unregistered | Device has not sent the registration SMS. The preflight message is part of this stage |
Waiting for Authentication Response | The SMS message has been sent and the device is waiting for a REG-RESP response |
Authenticated | The iPhone has received the REG-RESP SMS with the digitally signed phone number and push token, but has not applied to be in Apple's iMessage database. In this stage, your iPhone has a signature for its own phone number, but Apple's database doesn't have it yet. |
HTTP Registering | The device sends its signature to Apple to add itself to Apple’s database of registered iMessage users |
Registered | Apple accepts the signature as valid and you're now active on the iMessage network |
I hope this was at least a little helpful. Happy hacking!