run formatter

This commit is contained in:
JJTech0130 2023-05-02 20:53:18 -04:00
parent 0a52b2c12a
commit 618342a39f
No known key found for this signature in database
GPG key ID: 23C92EBCCF8F93D6
9 changed files with 165 additions and 132 deletions

View file

@ -79,7 +79,8 @@ def generate_push_cert() -> tuple[str, str]:
resp = requests.post(
"https://albert.apple.com/WebObjects/ALUnbrick.woa/wa/deviceActivation?device=Windows",
data={"activation-info": plistlib.dumps(body)}, verify=False,
data={"activation-info": plistlib.dumps(body)},
verify=False,
)
protocol = re.search("<Protocol>(.*)</Protocol>", resp.text).group(1)

28
apns.py
View file

@ -29,6 +29,7 @@ def _connect(private_key: str, cert: str) -> tlslite.TLSConnection:
return sock
class IncomingQueue:
def __init__(self):
self.queue = []
@ -70,6 +71,7 @@ class IncomingQueue:
time.sleep(delay)
return found
class APNSConnection:
incoming_queue = IncomingQueue()
@ -87,8 +89,8 @@ class APNSConnection:
# print("QUEUE: Got payload?")
if payload is not None:
#print("QUEUE: Received payload: " + str(payload))
#print("QUEUE: Received payload type: " + hex(payload[0]))
# print("QUEUE: Received payload: " + str(payload))
# print("QUEUE: Received payload type: " + hex(payload[0]))
self.incoming_queue.append(payload)
# print("QUEUE: Thread ended")
@ -112,7 +114,7 @@ class APNSConnection:
# def find_packet(self, finder) ->
#def replace_packet(self, payload: tuple[int, list[tuple[int, bytes]]]):
# def replace_packet(self, payload: tuple[int, list[tuple[int, bytes]]]):
# self.incoming_queue.append(payload)
def __init__(self, private_key=None, cert=None):
@ -137,11 +139,16 @@ class APNSConnection:
if token is None:
payload = _serialize_payload(
7, [(2, 0x01.to_bytes(1, 'big')), (5, flags.to_bytes(4, 'big'))]
7, [(2, 0x01.to_bytes(1, "big")), (5, flags.to_bytes(4, "big"))]
)
else:
payload = _serialize_payload(
7, [(1, token), (2, 0x01.to_bytes(1, 'big')), (5, flags.to_bytes(4, 'big'))]
7,
[
(1, token),
(2, 0x01.to_bytes(1, "big")),
(5, flags.to_bytes(4, "big")),
],
)
self.sock.write(payload)
@ -151,7 +158,7 @@ class APNSConnection:
if (
payload == None
or payload[0] != 8
or _get_field(payload[1], 1) != 0x00.to_bytes(1, 'big')
or _get_field(payload[1], 1) != 0x00.to_bytes(1, "big")
):
raise Exception("Failed to connect")
@ -194,13 +201,14 @@ class APNSConnection:
# Wait for ACK
payload = self.incoming_queue.wait_pop_find(lambda i: i[0] == 0x0B)
if payload[1][0][1] != 0x00.to_bytes(1, 'big'):
if payload[1][0][1] != 0x00.to_bytes(1, "big"):
raise Exception("Failed to send message")
def set_state(self, state: int):
self.sock.write(
_serialize_payload(
0x14, [(1, state.to_bytes(1, 'big')), (2, 0x7FFFFFFF.to_bytes(4, 'big'))]
0x14,
[(1, state.to_bytes(1, "big")), (2, 0x7FFFFFFF.to_bytes(4, "big"))],
)
)
@ -226,7 +234,7 @@ class APNSConnection:
def _serialize_field(id: int, value: bytes) -> bytes:
return id.to_bytes(1, 'big') + len(value).to_bytes(2, "big") + value
return id.to_bytes(1, "big") + len(value).to_bytes(2, "big") + value
def _serialize_payload(id: int, fields: list[(int, bytes)]) -> bytes:
@ -236,7 +244,7 @@ def _serialize_payload(id: int, fields: list[(int, bytes)]) -> bytes:
if fid is not None:
payload += _serialize_field(fid, value)
return id.to_bytes(1, 'big') + len(payload).to_bytes(4, "big") + payload
return id.to_bytes(1, "big") + len(payload).to_bytes(4, "big") + payload
def _deserialize_field(stream: bytes) -> tuple[int, bytes]:

View file

@ -45,11 +45,11 @@ if __name__ == "__main__":
# config = get_config()
# print(config)
# print(apns_init_bag_2())
#print(apns_init_bag_2() == apns_init_bag())
# print(apns_init_bag_2() == apns_init_bag())
bag = ids_bag()
for key in bag:
#print(key)
#print(bag[key])
# print(key)
# print(bag[key])
if type(bag[key]) == str:
if 'http' in bag[key]:
if "http" in bag[key]:
print(key, bag[key])

97
demo.py
View file

@ -1,8 +1,9 @@
from ids import *
import ids
import getpass
import json
import ids
from ids import *
# Open config
try:
with open("config.json", "r") as f:
@ -10,6 +11,7 @@ try:
except FileNotFoundError:
CONFIG = {}
def input_multiline(prompt):
print(prompt)
lines = []
@ -20,6 +22,7 @@ def input_multiline(prompt):
lines.append(line)
return "\n".join(lines)
def refresh_token():
# If no username is set, prompt for it
if "username" not in CONFIG:
@ -38,44 +41,48 @@ def refresh_token():
CONFIG["username"], CONFIG["password"], CONFIG["use_gsa"], factor_gen=factor_gen
)
def refresh_cert():
CONFIG["key"], CONFIG["auth_cert"] = ids._get_auth_cert(
CONFIG["user_id"], CONFIG["token"]
)
def create_connection():
conn = apns.APNSConnection()
token = conn.connect()
#conn.filter(['com.apple.madrid'])
CONFIG['push'] = {
'token': b64encode(token).decode(),
'cert': conn.cert,
'key': conn.private_key
# conn.filter(['com.apple.madrid'])
CONFIG["push"] = {
"token": b64encode(token).decode(),
"cert": conn.cert,
"key": conn.private_key,
}
return conn
def restore_connection():
conn = apns.APNSConnection(CONFIG['push']['key'], CONFIG['push']['cert'])
conn.connect(True, b64decode(CONFIG['push']['token']))
#conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi'])
conn = apns.APNSConnection(CONFIG["push"]["key"], CONFIG["push"]["cert"])
conn.connect(True, b64decode(CONFIG["push"]["token"]))
# conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi'])
return conn
def refresh_ids_cert():
info = {
"uri": "mailto:" + CONFIG["username"],
"user_id": CONFIG['user_id'],
"user_id": CONFIG["user_id"],
}
resp = None
try:
if "validation_data" in CONFIG:
resp = ids._register_request(
CONFIG['push']['token'],
CONFIG["push"]["token"],
info,
CONFIG['auth_cert'],
CONFIG['key'],
CONFIG['push']['cert'],
CONFIG['push']['key'],
CONFIG["auth_cert"],
CONFIG["key"],
CONFIG["push"]["cert"],
CONFIG["push"]["key"],
CONFIG["validation_data"],
)
except Exception as e:
@ -92,40 +99,36 @@ def refresh_ids_cert():
.replace(" ", "")
)
resp = ids._register_request(
CONFIG['push']['token'],
CONFIG["push"]["token"],
info,
CONFIG['auth_cert'],
CONFIG['key'],
CONFIG['push']['cert'],
CONFIG['push']['key'],
CONFIG["auth_cert"],
CONFIG["key"],
CONFIG["push"]["cert"],
CONFIG["push"]["key"],
validation_data,
)
CONFIG["validation_data"] = validation_data
ids_cert = x509.load_der_x509_certificate(
resp["services"][0]["users"][0]["cert"]
)
ids_cert = (
ids_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
)
ids_cert = x509.load_der_x509_certificate(resp["services"][0]["users"][0]["cert"])
ids_cert = ids_cert.public_bytes(serialization.Encoding.PEM).decode("utf-8").strip()
CONFIG["ids_cert"] = ids_cert
if not 'push' in CONFIG:
if not "push" in CONFIG:
print("No existing APNs credentials, creating new ones...")
#print("No push conn")
# print("No push conn")
conn = create_connection()
else:
print("Restoring APNs credentials...")
conn = restore_connection()
print("Connected to APNs!")
if not 'ids_cert' in CONFIG:
if not "ids_cert" in CONFIG:
print("No existing IDS certificate, creating new one...")
if not 'key' in CONFIG:
if not "key" in CONFIG:
print("No existing authentication certificate, creating new one...")
if not 'token' in CONFIG:
if not "token" in CONFIG:
print("No existing authentication token, creating new one...")
refresh_token()
print("Got authentication token!")
@ -134,34 +137,36 @@ if not 'ids_cert' in CONFIG:
refresh_ids_cert()
print("Got IDS certificate!")
ids_keypair = ids.KeyPair(CONFIG['key'], CONFIG['ids_cert'])
ids_keypair = ids.KeyPair(CONFIG["key"], CONFIG["ids_cert"])
def lookup(topic:str, users: list[str]):
def lookup(topic: str, users: list[str]):
print(f"Looking up users {users} for topic {topic}...")
resp = ids.lookup(conn, CONFIG['username'], ids_keypair, topic, users)
resp = ids.lookup(conn, CONFIG["username"], ids_keypair, topic, users)
#print(resp)
#r = list(resp['results'].values())[0]
for k, v in resp['results'].items():
# print(resp)
# r = list(resp['results'].values())[0]
for k, v in resp["results"].items():
print(f"Result for user {k} topic {topic}:")
i = v['identities']
i = v["identities"]
print(f"IDENTITIES: {len(i)}")
for iden in i:
print("IDENTITY", end=" ")
print(f"Push Token: {b64encode(iden['push-token']).decode()}", end=" ")
if 'client-data' in iden:
if "client-data" in iden:
print(f"Client Data: {len(iden['client-data'])}")
else:
print("No client data")
# Hack to make sure that the requests and responses match up
# This filter MUST contain all the topics you are looking up
#conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi', 'com.apple.private.alloy.multiplex1', 'com.apple.private.alloy.screensharing'])
#import time
#print("...waiting for queued messages... (this is a hack)")
#time.sleep(5) # Let the server send us any messages it was holding
#conn.sink() # Dump the messages
# conn.filter(['com.apple.madrid', 'com.apple.private.alloy.facetime.multi', 'com.apple.private.alloy.multiplex1', 'com.apple.private.alloy.screensharing'])
# import time
# print("...waiting for queued messages... (this is a hack)")
# time.sleep(5) # Let the server send us any messages it was holding
# conn.sink() # Dump the messages
lookup("com.apple.madrid", ["mailto:jjtech@jjtech.dev"])
lookup("com.apple.private.alloy.facetime.multi", ["mailto:jjtech@jjtech.dev"])
@ -173,7 +178,7 @@ lookup("com.apple.private.alloy.multiplex1", ["mailto:user_test2@icloud.com"])
lookup("com.apple.private.alloy.screensharing", ["mailto:user_test2@icloud.com"])
#time.sleep(4)
# time.sleep(4)
# Save config
with open("config.json", "w") as f:
json.dump(CONFIG, f, indent=4)

View file

@ -12,6 +12,6 @@ conn1.connect()
conn1.filter(["com.apple.madrid"])
#print(ids.lookup(conn1, ["mailto:jjtech@jjtech.dev"]))
# print(ids.lookup(conn1, ["mailto:jjtech@jjtech.dev"]))
print(ids.register(conn1, "user_test2@icloud.com", "wowSecure1"))

View file

@ -47,9 +47,10 @@ cert: str = None
key: str = None
import apns
import printer
import apns
outgoing_list = []
incoming_list = []
# last_outgoing = b""

View file

@ -1,10 +1,11 @@
import ids
import hashlib
from base64 import b64decode
import zlib
import plistlib
import zlib
from base64 import b64decode
with open('body.txt', 'r') as f:
import ids
with open("body.txt", "r") as f:
BODY = f.read()
CERT = "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"
@ -12,19 +13,21 @@ SIG = "AQEZs/u9Ptb8AmFpCv5XgzUsskvcleZDBxYTe5JOoshFCxpnByTwFA0mxplklHqT2rTEeF+Bu
TOKEN = "5V7AY+ikHr4DiSfq1W2UBa71G3FLGkpUSKTrOLg81yk="
NONCE = "AQAAAYeBb0XwKDMBW5PfAPM="
def extract_hash(sig: bytes, cert: str) -> str:
#sig = b64decode(SIG)[2:]
# sig = b64decode(SIG)[2:]
sig = int.from_bytes(sig)
# Get the correct hash
from cryptography.hazmat.backends import default_backend
from cryptography.x509 import load_pem_x509_certificate
#key, cert = load_keys()
# key, cert = load_keys()
cert = "-----BEGIN CERTIFICATE-----\n" + cert + "\n-----END CERTIFICATE-----"
cert = load_pem_x509_certificate(cert.encode(), default_backend())
modulus = cert.public_key().public_numbers().n
power = cert.public_key().public_numbers().e
#print(hex(pow(sig, power, modulus)))
# print(hex(pow(sig, power, modulus)))
return pow(sig, power, modulus)
# from cryptography import x509
@ -45,13 +48,14 @@ def extract_hash(sig: bytes, cert: str) -> str:
# return hash
body = plistlib.dumps(plistlib.loads(BODY.encode()))
body = zlib.compress(BODY.encode(), wbits=16+zlib.MAX_WBITS)
p = ids._create_payload('id-register', '', TOKEN, body, b64decode(NONCE))[0]
body = plistlib.dumps(plistlib.loads(BODY.encode()))
body = zlib.compress(BODY.encode(), wbits=16 + zlib.MAX_WBITS)
p = ids._create_payload("id-register", "", TOKEN, body, b64decode(NONCE))[0]
s = hashlib.sha1(p).digest()
print(s.hex())
#extract_hash(SIG, CERT)
# extract_hash(SIG, CERT)
# Loop through all POSSIBLE ranges
# sig = b64decode(SIG)
@ -71,12 +75,11 @@ print(s.hex())
# #print(hex(extract_hash(SIG, CERT)))
#CERT2 = "MIICnjCCAgegAwIBAgIKBAr40/DyW42YxjANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEVMBMGA1UECxMMQXBwbGUgaVBob25lMR8wHQYDVQQDExZBcHBsZSBpUGhvbmUgRGV2aWNlIENBMB4XDTIzMDQwNzE0MTUwNVoXDTI0MDQwNzE0MjAwNVowLzEtMCsGA1UEAxYkOUNCOTkzMTYtNkJERi00REYzLUFCRjUtNzcxNDU5MjFFQkY1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwsLiv8cifPdQZJQZtWvoD0WoTekSGwRj7KhxOi+AC1EUTdByWna8l7DDnixqww01FyA9pCBwottv0Xk9lOsrJrK05RXS+A7IieycejnUMdmRkgS7AsHIXOUSjtlkg2sfz5eYV9cqemTJnhdOvKtbqb9lYVN/8EehXD5JuogN+vwIDAQABo4GVMIGSMB8GA1UdIwQYMBaAFLL+ISNEhpVqedWBJo5zENinTI50MB0GA1UdDgQWBBQCl798/NQ3s5KywbJjoCjfjvWvmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEAYKKoZIhvdjZAYKBAQCBQAwDQYJKoZIhvcNAQEFBQADgYEAfBwkujrswCn+wtu0eKCa39Cv58YC3AhK24Aj2iwXbddHaj9B9ye6HDy1BHPG21LKNGqm4X/XEtJQ3ZY/hGr4eenmtYjOI4a/oi127mrSt7uZmoib9x5S6w68eCCKkO+DD2JqDbMr2ATUhVNUxMegrzYdju8LofYqXBKzkoZ0/nk="
#SIG2 = "AQGOTyyRBWMxoGWqEUl5bZJXssL6bkK4acxIDOCJTUy0MMavNEwtFThZkqVpQFqjB7eXNBM6PxwPtmwHmf/5IWgIkBUthIwhGJV3pLUkhDHTVX5YjbUSF7Z4y+Y39BQ2hhYjfcz1bw2KH40MByt+bnk28Xv2XaKWYuBinH9PVajp3g=="
# CERT2 = "MIICnjCCAgegAwIBAgIKBAr40/DyW42YxjANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJVUzETMBEGA1UEChMKQXBwbGUgSW5jLjEVMBMGA1UECxMMQXBwbGUgaVBob25lMR8wHQYDVQQDExZBcHBsZSBpUGhvbmUgRGV2aWNlIENBMB4XDTIzMDQwNzE0MTUwNVoXDTI0MDQwNzE0MjAwNVowLzEtMCsGA1UEAxYkOUNCOTkzMTYtNkJERi00REYzLUFCRjUtNzcxNDU5MjFFQkY1MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCwsLiv8cifPdQZJQZtWvoD0WoTekSGwRj7KhxOi+AC1EUTdByWna8l7DDnixqww01FyA9pCBwottv0Xk9lOsrJrK05RXS+A7IieycejnUMdmRkgS7AsHIXOUSjtlkg2sfz5eYV9cqemTJnhdOvKtbqb9lYVN/8EehXD5JuogN+vwIDAQABo4GVMIGSMB8GA1UdIwQYMBaAFLL+ISNEhpVqedWBJo5zENinTI50MB0GA1UdDgQWBBQCl798/NQ3s5KywbJjoCjfjvWvmDAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQEAwIFoDAgBgNVHSUBAf8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwEAYKKoZIhvdjZAYKBAQCBQAwDQYJKoZIhvcNAQEFBQADgYEAfBwkujrswCn+wtu0eKCa39Cv58YC3AhK24Aj2iwXbddHaj9B9ye6HDy1BHPG21LKNGqm4X/XEtJQ3ZY/hGr4eenmtYjOI4a/oi127mrSt7uZmoib9x5S6w68eCCKkO+DD2JqDbMr2ATUhVNUxMegrzYdju8LofYqXBKzkoZ0/nk="
# SIG2 = "AQGOTyyRBWMxoGWqEUl5bZJXssL6bkK4acxIDOCJTUy0MMavNEwtFThZkqVpQFqjB7eXNBM6PxwPtmwHmf/5IWgIkBUthIwhGJV3pLUkhDHTVX5YjbUSF7Z4y+Y39BQ2hhYjfcz1bw2KH40MByt+bnk28Xv2XaKWYuBinH9PVajp3g=="
SIG3 = "AQEZs/u9Ptb8AmFpCv5XgzUsskvcleZDBxYTe5JOoshFCxpnByTwFA0mxplklHqT2rTEeF+Bu0Bo0vEPlh9KslmIoQLo6ej25bbtFN07dnHNwd84xzQzWBa4VHLQE1gNjSpcorppxpAUon/eFRu5yRxmwQVmqo+XmmxSuFCzxUaAZAPFPDna+8tvRwd0q3kuK9b0w/kuT16X1SL166fFNzmsQGcBqob9C9xX0VlYGqSd4K975gWdYsPo/kiY0ni4Q130oc6oAANr8ATN0bEeAO6/AfVM2aqHJTGlYlekBFWf8Tp8AJLUc4cm676346IEBST+l4rYGxYYStV2PEmp9cZ+"
CERT3 = "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"
print(hex(extract_hash(b64decode(SIG)[2:], CERT)))

53
gsa.py
View file

@ -1,24 +1,25 @@
from base64 import b64encode, b64decode
from datetime import datetime
from random import randbytes
import uuid
import locale
import plistlib as plist
import json
import getpass
import hashlib
import hmac
import json
import locale
import plistlib as plist
import uuid
from base64 import b64decode, b64encode
from datetime import datetime
from random import randbytes
import pbkdf2
import requests
import srp._pysrp as srp
import pbkdf2
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
import getpass
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
# Constants
DEBUG = True # Allows using a proxy for debugging (disables SSL verification)
# Server to use for anisette generation
#ANISETTE = "https://sign.rheaa.xyz/"
#ANISETTE = 'http://45.132.246.138:6969/'
# ANISETTE = "https://sign.rheaa.xyz/"
# ANISETTE = 'http://45.132.246.138:6969/'
ANISETTE = False
# ANISETTE = 'https://sideloadly.io/anisette/irGb3Quww8zrhgqnzmrx'
# ANISETTE = "http://jkcoxson.com:2052/"
@ -35,11 +36,13 @@ urllib3.disable_warnings()
def generate_anisette() -> dict:
import objc
from Foundation import NSBundle, NSClassFromString #type: ignore
from Foundation import NSBundle, NSClassFromString # type: ignore
AOSKitBundle = NSBundle.bundleWithPath_('/System/Library/PrivateFrameworks/AOSKit.framework')
objc.loadBundleFunctions(AOSKitBundle, globals(), [("retrieveOTPHeadersForDSID", b'')]) #type: ignore
util = NSClassFromString('AOSUtilities')
AOSKitBundle = NSBundle.bundleWithPath_(
"/System/Library/PrivateFrameworks/AOSKit.framework"
)
objc.loadBundleFunctions(AOSKitBundle, globals(), [("retrieveOTPHeadersForDSID", b"")]) # type: ignore
util = NSClassFromString("AOSUtilities")
h = util.retrieveOTPHeadersForDSID_("-2")
@ -47,13 +50,13 @@ def generate_anisette() -> dict:
"X-Apple-I-MD": str(h["X-Apple-MD"]),
"X-Apple-I-MD-M": str(h["X-Apple-MD-M"]),
}
#h["X-Apple-I-MD"] = str(h["X-Apple-MD"])
#h["X-Apple-I-MD-M"] = str(h["X-Apple-MD-M"])
#print(o)
# h["X-Apple-I-MD"] = str(h["X-Apple-MD"])
# h["X-Apple-I-MD-M"] = str(h["X-Apple-MD-M"])
# print(o)
return o
#r = requests.get(ANISETTE, verify=False if DEBUG else True, timeout=5)
#r = json.loads(r.text)
#return r
# r = requests.get(ANISETTE, verify=False if DEBUG else True, timeout=5)
# r = json.loads(r.text)
# return r
class Anisette:
@ -304,7 +307,7 @@ def authenticated_request(parameters, anisette: Anisette) -> dict:
}
resp = requests.post(
#"https://17.32.194.2/grandslam/GsService2",
# "https://17.32.194.2/grandslam/GsService2",
"https://gsa.apple.com/grandslam/GsService2",
headers=headers,
data=plist.dumps(body),
@ -460,7 +463,7 @@ def authenticate(username, password, anisette: Anisette):
{
"A2k": A,
"ps": ["s2k", "s2k_fo"],
#"ps": ["s2k"],
# "ps": ["s2k"],
"u": username,
"o": "init",
},
@ -527,5 +530,5 @@ def authenticate(username, password, anisette: Anisette):
print(f"Unknown auth value {r['Status']['au']}")
return
else:
#print("Assuming 2FA is not required")
# print("Assuming 2FA is not required")
return spd

44
ids.py
View file

@ -1,8 +1,9 @@
import gzip
import plistlib
import random
import uuid
import gzip
from base64 import b64decode, b64encode
from collections import namedtuple
from datetime import datetime
import requests
@ -11,7 +12,6 @@ from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding, rsa
from cryptography.x509.oid import NameOID
from collections import namedtuple
import apns
import bags
@ -21,6 +21,7 @@ USER_AGENT = "com.apple.madrid-lookup [macOS,13.2.1,22D68,MacBookPro18,3]"
KeyPair = namedtuple("KeyPair", ["key", "cert"])
# Nonce Format:
# 01000001876bd0a2c0e571093967fce3d7
# 01 # version
@ -33,6 +34,7 @@ def generate_nonce() -> bytes:
+ random.randbytes(8)
)
def _create_payload(
bag_key: str,
query_string: str,
@ -47,13 +49,13 @@ def _create_payload(
return (
nonce
+ len(bag_key).to_bytes(4, 'big')
+ len(bag_key).to_bytes(4, "big")
+ bag_key.encode()
+ len(query_string).to_bytes(4, 'big')
+ len(query_string).to_bytes(4, "big")
+ query_string.encode()
+ len(payload).to_bytes(4, 'big')
+ len(payload).to_bytes(4, "big")
+ payload
+ len(push_token).to_bytes(4, 'big')
+ len(push_token).to_bytes(4, "big")
+ push_token,
nonce,
)
@ -78,7 +80,15 @@ def sign_payload(
# global_key, global_cert = load_keys()
def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: bytes, keypair: KeyPair, username: str) -> bytes:
def _send_request(
conn: apns.APNSConnection,
bag_key: str,
topic: str,
body: bytes,
keypair: KeyPair,
username: str,
) -> bytes:
body = gzip.compress(body, mtime=0)
push_token = b64encode(conn.token).decode()
@ -93,12 +103,12 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: byt
"x-id-nonce": b64encode(nonce).decode(),
"x-id-sig": signature,
"x-push-token": push_token,
"x-id-self-uri": 'mailto:' + username,
"x-id-self-uri": "mailto:" + username,
"User-Agent": USER_AGENT,
"x-protocol-version": "1630",
}
#print(headers)
# print(headers)
msg_id = random.randbytes(16)
@ -114,7 +124,7 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: byt
}
conn.send_message(topic, plistlib.dumps(req, fmt=plistlib.FMT_BINARY))
#resp = conn.wait_for_packet(0x0A)
# resp = conn.wait_for_packet(0x0A)
def check_response(x):
if x[0] != 0x0A:
@ -123,12 +133,12 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: byt
if resp_body is None:
return False
resp_body = plistlib.loads(resp_body)
return resp_body['U'] == msg_id
return resp_body["U"] == msg_id
# Lambda to check if the response is the one we want
#conn.incoming_queue.find(check_response)
# conn.incoming_queue.find(check_response)
payload = conn.incoming_queue.wait_pop_find(check_response)
#conn._send_ack(apns._get_field(payload[1], 4))
# conn._send_ack(apns._get_field(payload[1], 4))
resp = apns._get_field(payload[1], 3)
return plistlib.loads(resp)
@ -139,12 +149,14 @@ def _send_request(conn: apns.APNSConnection, bag_key: str, topic: str, body: byt
# keypair: a KeyPair object containing the user's private key and certificate
# topic: the IDS topic to query
# query: a list of URIs to query
def lookup(conn: apns.APNSConnection, self: str, keypair: KeyPair, topic: str, query: list[str]) -> any:
def lookup(
conn: apns.APNSConnection, self: str, keypair: KeyPair, topic: str, query: list[str]
) -> any:
conn.filter([topic])
query = {"uris": query}
resp = _send_request(conn, "id-query", topic, plistlib.dumps(query), keypair, self)
#resp = plistlib.loads(resp)
#print(resp)
# resp = plistlib.loads(resp)
# print(resp)
resp = gzip.decompress(resp["b"])
resp = plistlib.loads(resp)
return resp