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( resp = requests.post(
"https://albert.apple.com/WebObjects/ALUnbrick.woa/wa/deviceActivation?device=Windows", "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) 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 return sock
class IncomingQueue: class IncomingQueue:
def __init__(self): def __init__(self):
self.queue = [] self.queue = []
@ -70,6 +71,7 @@ class IncomingQueue:
time.sleep(delay) time.sleep(delay)
return found return found
class APNSConnection: class APNSConnection:
incoming_queue = IncomingQueue() incoming_queue = IncomingQueue()
@ -87,8 +89,8 @@ class APNSConnection:
# print("QUEUE: Got payload?") # print("QUEUE: Got payload?")
if payload is not None: if payload is not None:
#print("QUEUE: Received payload: " + str(payload)) # print("QUEUE: Received payload: " + str(payload))
#print("QUEUE: Received payload type: " + hex(payload[0])) # print("QUEUE: Received payload type: " + hex(payload[0]))
self.incoming_queue.append(payload) self.incoming_queue.append(payload)
# print("QUEUE: Thread ended") # print("QUEUE: Thread ended")
@ -112,7 +114,7 @@ class APNSConnection:
# def find_packet(self, finder) -> # 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) # self.incoming_queue.append(payload)
def __init__(self, private_key=None, cert=None): def __init__(self, private_key=None, cert=None):
@ -137,11 +139,16 @@ class APNSConnection:
if token is None: if token is None:
payload = _serialize_payload( 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: else:
payload = _serialize_payload( 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) self.sock.write(payload)
@ -151,7 +158,7 @@ class APNSConnection:
if ( if (
payload == None payload == None
or payload[0] != 8 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") raise Exception("Failed to connect")
@ -194,13 +201,14 @@ class APNSConnection:
# Wait for ACK # Wait for ACK
payload = self.incoming_queue.wait_pop_find(lambda i: i[0] == 0x0B) 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") raise Exception("Failed to send message")
def set_state(self, state: int): def set_state(self, state: int):
self.sock.write( self.sock.write(
_serialize_payload( _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: 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: 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: if fid is not None:
payload += _serialize_field(fid, value) 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]: def _deserialize_field(stream: bytes) -> tuple[int, bytes]:

View file

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

97
demo.py
View file

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

View file

@ -12,6 +12,6 @@ conn1.connect()
conn1.filter(["com.apple.madrid"]) 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")) print(ids.register(conn1, "user_test2@icloud.com", "wowSecure1"))

View file

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

View file

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

53
gsa.py
View file

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

44
ids.py
View file

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