Coder Social home page Coder Social logo

pypush's Introduction

Warning

Pypush is broken at the moment. We thank you for your continued support of the project! The Pypush demo will not work without significant modification to the code to remediate challenges posed as a response to third party iMessage clients growing in popularity.

pypush

pypush is a POC demo of my recent iMessage reverse-engineering. It can currently register as a new device on an Apple ID, set up encryption keys, and send and receive iMessages!

pypush is completely platform-independent, and does not require a Mac or other Apple device to use!

Installation

It's pretty self explanatory:

  1. git clone https://github.com/JJTech0130/pypush
  2. If on a Mac, ensure cmake is installed. Otherwise, run brew install cmake
  3. pip3 install -r requirements.txt
  4. python3 ./demo.py

Troubleshooting

If you have any issues, please join the Discord and ask for help.

Operation

pypush will generate a config.json in the repository when you run demo.py. DO NOT SHARE THIS FILE. It contains all the encryption keys necessary to log into you Apple ID and send iMessages as you.

Once it loads, it should prompt you with >>. Type help and press enter for a list of supported commands.

Special Notes

Unicorn dependency

pypush currently uses the Unicorn CPU emulator and a custom MachO loader to load a framework from an old version of macOS, in order to call some obfuscated functions.

This is only necessary during initial registration, so theoretically you can register on one device, and then copy the config.json to another device that doesn't support the Unicorn emulator. Or you could switch out the emulator for another x86 emulator if you really wanted to.

"data.plist" and Mac serial numbers

This repository contains a sample data.plist, which contains the serial number and several other identifiers from a real Mac device. If you run into issues related to rate-limiting or messages failing to deliver, you may regenerate this file by cloning nacserver and running build.sh on a non-M1 Mac. It should place the generated file in the current directory, which you can then copy to the emulated/ folder in pypush.

Licensing

This project is licensed under the terms of the SSPL. Portions of this project are based on macholibre by Aaron Stephens under the Apache 2.0 license.

This project has been purchased by Beeper, please contact them with any questions about licensing.

pypush's People

Contributors

dadoum avatar danipoak avatar eltociear avatar jjtech0130 avatar kasherpete avatar peterkw avatar pixelmonaskarion avatar spacesaver avatar thomashzhang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pypush's Issues

Fix `crontab -e` being hidden

crontab -e here is hidden because it's on the same line as ```, so the markdown parser is reading it as the syntax highlight language instead of the codeblock body.

pypush/README.md

Lines 98 to 100 in b81ae39

2. To automatically reregister every 30 minutes, execute the following:
```crontab -e
```

I'd also suggest changing it to

$ crontab -e

(adding $) for clarity that it's a terminal command and not something that goes in a file, but that's up to you (should be clear to anybody who reads the directions anyways). if you do decide to add that, should also be added to the other commands, but not terribly important.

Doesn't work on newer versions of Python

(base) bryan@Bryans-MacBook-Pro-7 pypush % python3 demo.py
Traceback (most recent call last):
  File "demo.py", line 13, in <module>
    import apns
  File "/Users/bryan/work/pypush/apns.py", line 12, in <module>
    import tlslite
  File "/Users/bryan/miniconda3/lib/python3.8/site-packages/tlslite/__init__.py", line 27, in <module>
    from tlslite.api import *
  File "/Users/bryan/miniconda3/lib/python3.8/site-packages/tlslite/api.py", line 11, in <module>
    from .tlsconnection import TLSConnection
  File "/Users/bryan/miniconda3/lib/python3.8/site-packages/tlslite/tlsconnection.py", line 71
    async=False):
    ^
SyntaxError: invalid syntax

has been no response.

For the last few days, I tried send imessage ,"is me" is my content ,But the continuous absence of a response.. and type help not show message, Any idea what could be the issue or how I could fix this?

[02:06:04] INFO Connected to APNs (5-courier.push.apple.com) apns.py:39
INFO Waiting for incoming messages... demo.py:91
Type 'help' for help

help
help (h): show this message
quit (q): quit
filter (f) [recipient]: set the current chat
effect (e): adds an iMessage effect to the next sent message
note: recipient must start with tel: or mailto: and include the country code
handle : set the current handle (for sending messages)
: escape commands (will be removed from message)
filter +18023061555
Filtering to ['tel:+18023061555']
is me
help

Send madrid 130 messages to indicate there is updated registration information

Messages with type 130 are sent to devices to notify them that there is updated registration information for them to look up.
This is for both:

  • Other accounts, so that they know to send messages to the newly added device
  • Devices on your own account, so that they can forward to other people that they know about

This would also work around a current issue in Beeper's new bridge, where it does not notice that a phone number was linked with pypush, because it only listens for the 130 (that we do not send) and does not see the ids sign in notification sent by Apple (that real iMessage and the old bridge noticed).

Unable to find the public key of the sender, cannot verify

[16:36:07] WARNING Unable to find the public key of the sender, cannot verify imessage.py:404
Traceback (most recent call last):
File "/Volumes/Code/play/pypush/./demo.py", line 158, in
msg = im.receive()
^^^^^^^^^^^^
File "/Volumes/Code/play/pypush/imessage.py", line 436, in receive
raise Exception("Failed to verify payload")
Exception: Failed to verify payload

SSPL License Issues

Hi,
I noticed on your GitHub profile you mentioned PyPush was open sourced, however according to the creators of the SSPL license (MongoDB), the SSPL license is not open sourced (source).
Are there any plans to perhaps switch the license in the future?
Thank you for creating this incredible project!

Consider making a pip package?

This is a great looking library, and I think it would help a whole lot if you made a python package.

Thanks,
Gammer0909

search_party_token always null

after run the bellow code show Logged in! message

~/pypush$ python3 ./examples/openhaystack.py

but show this error:
Error fetching locations (ratelimit?): 401

in the openhaystack.json
"search_party_token": null,

Apple 2FA not supported?

I've got 2FA enabled for my Apple account and when pypush asks for it I get this after entering the (2FA) code:

Traceback (most recent call last):
  File "/pypush/./demo.py", line 341, in <module>
    trio.run(main, args)
  File "/usr/local/lib/python3.11/dist-packages/trio/_core/_run.py", line 2251, in run
    raise runner.main_task_outcome.error
  File "/pypush/./demo.py", line 244, in main
    users.append(ids.IDSAppleUser.authenticate(conn, username, password))
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/pypush/ids/__init__.py", line 65, in authenticate
    user_id, auth_token = profile.get_auth_token(username, password, factor_callback)
                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/pypush/ids/profile.py", line 64, in get_auth_token
    raise Exception(f"Error: {result}")
Exception: Error: {'message': 'SED:3:VEN-PROD:43aa8e34-ba49-40f5-80f5-e414fe93fb55:432f9f65-bbb9-4aae-b54f-86f2f179292c:1702051751:b67a06b0-7d01-4172-84e2-42c1297a2df0:9a29965493c79209a82f585c6d278c60e87216be5b90dc433a78673066c314aa:EM', 'status': 5012}

By the way I am using the sms-forwarding branch under Debian.

install issue

$ python3 -m pip install --editable ./pypush - > $ python3 -m pip install --editable ../pypush

Cat and Mouse?

With Beeper so heavily in the news, I suspect Apple has derailed the mechanism this project uses to send and receive messages. I compiled and ran nacserver (JJTech0130/nacserver) on a valid Intel Mac and swapped out the data.plist file on my Linux box. I reran the initialization to get a new config.json but the software no longer appears to function correctly. This is too bad since it was nice to be able to ssh in from wherever I was working and send iMessages.

Steps to Replicate

  1. Clone nacserver on an Intel Mac
  2. Run build.sh
  3. Copy data.plist into emulated directory under pypush
  4. rm existing config.json
  5. Run demo.py with requirements.txt installed
  6. No Joy

No cert in response

For the last few days, I've been getting a new error. Any idea what could be the issue or how I could fix this?

./reregister
/opt/pypush /opt/pypush
[11:36:31] INFO     Connected to APNs (33-courier.push.apple.com)                                                                                                                                                                  apns.py:191
           DEBUG    Restoring new-style identity...                                                                                                                                                                                demo.py:200
[11:36:33] INFO     Generated validation data                                                                                                                                                                                       nac.py:415
Traceback (most recent call last):
  File "/opt/pypush/demo.py", line 340, in <module>
    trio.run(main, args)
  File "/opt/pypush/.venv/lib/python3.11/site-packages/trio/_core/_run.py", line 2093, in run
    raise runner.main_task_outcome.error
  File "/opt/pypush/demo.py", line 295, in main
    await reregister(conn, users)
  File "/opt/pypush/demo.py", line 125, in reregister
    register(conn, users)
  File "/opt/pypush/demo.py", line 105, in register
    users = ids.register(conn, users, vd, args.client_data or args.reg_notify)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/pypush/ids/__init__.py", line 136, in register
    certs = identity.register(
            ^^^^^^^^^^^^^^^^^^
  File "/opt/pypush/ids/identity.py", line 187, in register
    raise Exception(f"No cert in response: {r}")
Exception: No cert in response: {'services': [{'service': 'com.apple.madrid', 'users': [{'user-id': '<REDACTED>', 'message': '<REDACTED', 'status': 6001}, {'uris': [{'uri': '<REDACTED>', 'status': 0}, {'uri': '<REDACTED>', 'status': 0}], 'user-id': '<REDACTED>', 'cert': b'<REDACTED>', 'status': 0}], 'status': 0}], 'status': 0}

However it looks like there is a cert field in the response body. I've removed it here for privacy reasons but it's a string of bytes.

I'm on commit f205e86bdf1a4ea5414a78985721c721039ada97 of the sms-registration branch.

Verify TLS certificates

Apple's certificates are self-signed, so we currently just don't verify them. Eventually we would like to verify them properly.

demo stuck in Waiting for incoming messages

[03:04:10] INFO     Connected to APNs (16-courier.push.apple.com)                                                                     apns.py:40
[03:04:11] INFO     Waiting for incoming messages...                                                                                  demo.py:94
Type 'help' for help

I remove the config.json but same issue (still debugging)

Request queued messages from APNs

On iOS it currently receives missed messages on boot if device was turned off for multiple hours of time and starting up it takes a bit of time but it receives messages that were missed. This would be very useful for locally ran stuff like inside of a app or executable where it might not always be active and someone could message during that time.

Use of context on `APNSConnection.start` and its limitations

Here is some code I did to be able to use PyPush as a library.

    @classmethod
    async def from_save(
        cls,
        fp: Path
    ) -> "StoredAuthorizedUser":
        with open(fp, "r") as read:
            data = json.load(read)
        
        push_creds = apns.PushCredentials(
            private_key=data["push"]["key"],
            cert=data["push"]["cert"],
            token=base64.b64decode(data["push"]["token"])
        )

        user = data["user"]
        async with apns.APNSConnection.start(push_creds) as connection:
            user = ids.IDSUser( push_connection=connection,
                                user_id=user["id"],
                                auth_keypair=ids._helpers.KeyPair(user["auth_key"], user["auth_cert"]),
                                encryption_identity=ids.identity.IDSIdentity(user["signing_key"], user["encryption_key"]),
                                id_cert=None,
                                handles=user["handles"], )
                
            return cls(
                connection=connection,
                user=user,
                certificates=data.get("certs"),
                earliest_expiration=data.get("earliest_expiration")
            )

You can see at the end of this method that I am trying to put my connection to my __init__ method of my class. However, since the connection is in a context, I can't. When we hit return, even inside of a context, the context gets closed. So I can't use the connection outside of the context. If I do it, it will result in the following error, confirming that the connection got closed:

Capture d’écran 2023-11-25 à 22 42 38

If you try to do some of the following stuff, it won't work, or due of the limitations of trio, or due to the limitations of context manager.

connection = apns.APNSConnection.start(push_creds)
connection = await apns.APNSConnection.start(push_creds)
connection = await apns.APNSConnection.start(push_creds).__anext__()

I've also tried to return just after the yield (in the following code) to return the connection, to avoid closing it, etc ... And it just freezes the code.

pypush/apns.py

Lines 155 to 164 in bacefed

@asynccontextmanager
@staticmethod
async def start(credentials: PushCredentials = PushCredentials()):
"""Sets up a nursery and connection and yields the connection"""
async with trio.open_nursery() as nursery:
connection = APNSConnection(nursery, credentials)
await connection.connect()
yield connection
nursery.cancel_scope.cancel() # Cancel heartbeat and queue filler tasks
await connection.sock.aclose() # Close the socket

What could I do to avoid the automatic closing of my connection / How can I open it with a manual closing ? (All of this using the async version ofc)

wont run demo.py 'type' object is not subscriptable

installed all requirements

ran the command , python37 demo.py

error

Traceback (most recent call last):
File "demo.py", line 13, in
import apns
File "F:\Users\x\Documents\imessage api\pypush-main\apns.py", line 17, in
import albert
File "F:\Users\x\Documents\imessage api\pypush-main\albert.py", line 48, in
def generate_push_cert() -> tuple[str, str]:
TypeError: 'type' object is not subscriptable

Add support for named group chats

I have a group chat with two people that has a name and group chat photo. I used pypush to text these two people (made sure that the phone numbers and everything matched), and it made a new group chat rather than texting into the existing one.

ModuleNotFoundError: No module named 'rich'

(Apple Silicon. I'll try on x86 Linux)

git clone https://github.com/JJTech0130/pypush
pip3 install -r requirements.txt
python3 ./demo.py

❯❯python3 ./demo.py
Traceback (most recent call last):
File "/Users/faucherd/Downloads/pypush/./demo.py", line 11, in
from rich.logging import RichHandler
ModuleNotFoundError: No module named 'rich'

Missing iMessage features

This is a list of iMessage features that are too simple for their own issue and we're missing

  • typing indicators
  • read receipts
  • unsending messages
  • editing messages
  • replies

TODO: add more stuff here

Termux

Is it possible to do it on Termux on Android? I'm missing dependencies

Edit: Add lines to make it work
Edit: Closing as it works now

git clone -b sms-registration https://github.com/JJTech0130/pypush 
cd pypush
pkg install build-essential
pkg install binutils
#pkg install pkg_resources
pip3 install setuptools
pip3 install trio
pip3 install -r requirements.txt
#change IP address to current
#Check Gateway number, UK is +447786205094 def register(push_token: bytes, gateway = "22223333")
python3 ./demo.py
error occurred: Failed to find tool. Is `aarch64-linux-android-ar` installed?
error: `cargo rustc --lib --message-format=json-render-diagnostics --manifest-path src/rust/Cargo.toml --release -v --features pyo3/extension-module --crate-type cdylib --` failed with code 101
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for cryptography

Fix 2FA stuff

Currently very buggy, doesn’t check if account had no 2FA

Add the ability to change the 2FA mode

My apple account is connected with my home mac and some other macs (Beeper and other services), I do not have readily access to these mac's and as such using 2FA is a pain. There should in theory be a way to switch the 2FA mode to the phone number associated with the apple account. This is more of a 'nice to have' than actually being necessary, but would still be a good feature none the less.

Participant identities being mistaken as fake accounts

Hey,

I have two Apple Id users connected to each their email, and have them setup on two seperate Apple product.

I am able to use IMessage to send messages between the two devices. This worked fine with this project on the 26th of November as well, however when i returned to attempt to test it again now i get an error.

imessage.py:566 mailto:****@duck.com has no identities, this is probably not a real account
imessage.py:566 mailto:****@gmail.com has no identities, this is probably not a real account

This is from the async branch as suggested by @Cypheriel on the issue #74.

Do you guys have a stable branch or working version that i can use to develop? 🤞🏽

Basic UI needed

If not complex i think a basic UI will be helpful instead of all going through terminal that's what I think

Validation data expired!

This "IOPlatformSerialNumber" replaces multiple device codes with "raise Exception("Validation data expired!"). )
Exception: Validation data expired!”

Implement receiving app push notifications

I am not an iOS developer myself, but every now and then I have to do some testings, and one of the things it is requested is a real device to test push notifications, I wonder if this approach can be used for that as well?

Thanks!

Validation data expired

I tried to update data.plist, but I got a raise Exception("Validation data expired! ") Could you please help me solve this headache?
Also, how do I create a batch data.plist, or make it update automatically

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.