Skip to content

Instantly share code, notes, and snippets.

@m1stadev
Last active September 3, 2024 15:43
Show Gist options
  • Save m1stadev/f1130b066fb1334dccc8bcb596c5b336 to your computer and use it in GitHub Desktop.
Save m1stadev/f1130b066fb1334dccc8bcb596c5b336 to your computer and use it in GitHub Desktop.
iOS/tvOS nonce setter
#!/usr/bin/env python3
from pathlib import Path
from remotezip import RemoteZip
import argparse
import plistlib
import requests
import subprocess
import tempfile
import time
import shutil
import sys
def check_device() -> dict:
args = (
'irecovery',
'-q',
)
try:
irecv = subprocess.check_output(
args,
stderr=subprocess.DEVNULL,
universal_newlines=True,
)
except subprocess.CalledProcessError:
sys.exit('[ERROR] Failed to find a device in Pwned DFU mode. Exiting.')
device_data = dict()
for l in irecv.splitlines():
x, y = l.split(': ')
device_data[x.lower()] = y
device_data['ecid'] = hex(int(device_data['ecid'], 16))
for i in ('cpid', 'cprv', 'bdid', 'cpfm', 'scep', 'ibfl'):
device_data[i] = int(device_data[i], 16)
if ('pwnd' not in device_data.keys()) or (device_data['mode'] != 'DFU'):
sys.exit('[ERROR] Device is not in Pwned DFU mode. Exiting.')
api = requests.get('https://api.ipsw.me/v4/devices').json()
for d in api:
for board in d['boards']:
if (board['cpid'] == device_data['cpid']) and (
board['bdid'] == device_data['bdid']
):
device_data['identifier'] = d['identifier']
device_data['boardconfig'] = board['boardconfig']
return device_data
sys.exit('[ERROR] Device does not exist?!?!??!?!')
def unpack(img: Path, iv: str, key: str) -> Path:
args = (
'img4tool',
'-e',
'--iv',
iv,
'--key',
key,
'-o',
str(img.with_suffix('.raw')),
str(img),
)
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to unpack image: {img}.')
return img.with_suffix('.raw')
def patch(patcher: Path, img: Path) -> Path:
args = (str(patcher), str(img), str(img.with_suffix('.pwn')), '-n')
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to patch image: {img}. Exiting.')
return img.with_suffix('.pwn')
def verify_shsh(shsh: Path) -> str:
if (not shsh.exists()) or (not shsh.is_file()):
sys.exit(f'[ERROR] SHSH blob does not exist: {shsh}. Exiting.')
with shsh.open('rb') as f:
try:
im4m = plistlib.loads(f.read())
except plistlib.InvalidFileException:
sys.exit(f'[ERROR] SHSH Blob is invalid: {shsh}. Exiting.')
if not any(_ in im4m.keys() for _ in ('ApImg4Ticket', 'generator')):
sys.exit(f'[ERROR] SHSH Blob is invalid: {shsh}. Exiting.')
if (not im4m['generator'].startswith('0x')) or (len(im4m['generator']) != 18):
sys.exit(
f"[ERROR] Generator inside SHSH blob is invalid: {im4m['generator']}. Exiting."
)
try:
int(im4m['generator'], 16)
except:
sys.exit(
f"[ERROR] Generator inside SHSH blob is invalid: {im4m['generator']}. Exiting."
)
return im4m['generator']
def repack(img: Path, tag: str, shsh: Path) -> Path:
args = (
'img4tool',
'-c',
str(img.with_suffix('.im4p')),
'-t',
tag,
str(img),
)
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to repack image: {img}. Exiting.')
args = (
'img4tool',
'-c',
str(img.with_suffix('.img4')),
'-p',
str(img.with_suffix('.im4p')),
'-s',
str(shsh),
)
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f"[ERROR] Failed to sign image: {img.with_suffix('.im4p')}. Exiting.")
return img.with_suffix('.img4')
def send_bootchain(ibss: Path, ibec: Path, cpid: int) -> None:
args = (
'irecovery',
'-r',
)
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit('[ERROR] Failed to reset device connection. Exiting.')
args = ('irecovery', '-f', str(ibss))
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to send image: {ibss}. Exiting.')
time.sleep(2)
args = ('irecovery', '-f', str(ibec))
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to send image: {ibec}. Exiting.')
time.sleep(2)
if 0x8010 <= cpid:
irecv_cmd('go')
time.sleep(3)
args = ('irecovery', '-m')
try:
mode = subprocess.check_output(
args,
stderr=subprocess.STDOUT,
universal_newlines=True,
)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Device failed to load bootchain. Exiting.')
if 'Recovery Mode' not in mode:
sys.exit('[ERROR] Device failed to load bootchain. Exiting.')
def irecv_cmd(cmd: str) -> None:
args = ('irecovery', '-c', cmd)
try:
subprocess.check_call(args, stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
except subprocess.CalledProcessError:
sys.exit(f'[ERROR] Failed to send command to device: {cmd}. Exiting.')
def main() -> None:
print('iOS/tvOS nonce setter\n')
parser = argparse.ArgumentParser(
description='iOS/tvOS nonce setter',
usage=f'{sys.argv[0]} -s SHSH blob',
)
parser.add_argument(
'-s', '--shsh', help='Path to SHSH blob', nargs=1, required=True, type=Path
)
args = parser.parse_args()
shsh = args.shsh[0]
for x in ('img4tool', 'irecovery'):
if shutil.which(x) is None:
sys.exit(f'[ERROR] Required tool is not installed: {x}. Exiting.')
for x in ('iBoot64Patcher', 'Kairos'):
if shutil.which(x):
patcher = Path(x)
break
else:
sys.exit(f'[ERROR] Neither Kairos nor iBoot64Patcher are installed. Exiting.')
print('Verifying SHSH blob...')
generator = verify_shsh(shsh)
device_data = check_device()
os_type = 'iOS' if 'AppleTV' not in device_data['identifier'] else 'tvOS'
api = requests.get(
f"https://api.ipsw.me/v4/device/{device_data['identifier']}"
).json()
try:
firm = next(
_
for _ in api['firmwares']
if 12 <= int(_['version'].split('.')[0]) <= 15
)
except StopIteration:
sys.exit(
f"[ERROR] {device_data['identifier']} doesn't support any firmwares between {os_type} 10-14. Exiting."
)
print(f"Grabbing build manifest from {os_type} {firm['version']}...")
with RemoteZip(firm['url']) as rz:
manifest = plistlib.loads(
rz.read(next(f for f in rz.namelist() if 'BuildManifest' in f))
)
print(f"Grabbing bootchain from {os_type} {firm['version']}...")
with tempfile.TemporaryDirectory() as tmpdir:
tmp = Path(tmpdir)
ibss_path = next(
i['Manifest']['iBSS']['Info']['Path']
for i in manifest['BuildIdentities']
if i['Info']['DeviceClass'].lower() == device_data['boardconfig'].lower()
)
ibec_path = next(
i['Manifest']['iBEC']['Info']['Path']
for i in manifest['BuildIdentities']
if i['Info']['DeviceClass'].lower() == device_data['boardconfig'].lower()
)
ibss = tmp / 'ibss.im4p'
ibec = tmp / 'ibec.im4p'
with RemoteZip(firm['url']) as rz:
with ibss.open('wb') as f:
f.write(rz.read(ibss_path))
with ibec.open('wb') as f:
f.write(rz.read(ibec_path))
print('Unpacking bootchain...')
if (
len(
[
board
for board in api['boards']
if board['boardconfig'].lower().endswith('ap')
]
)
== 1
):
wiki_url = f"https://api.m1sta.xyz/wikiproxy/{device_data['identifier']}/{firm['buildid']}"
else:
wiki_url = f"https://api.m1sta.xyz/wikiproxy/{device_data['identifier']}/{device_data['boardconfig']}/{firm['buildid']}"
wikiproxy = requests.get(wiki_url).json()
ibss_keys = next(_ for _ in wikiproxy['keys'] if _['image'] == 'iBSS')
ibss = unpack(ibss, ibss_keys['iv'], ibss_keys['key'])
ibec_keys = next(_ for _ in wikiproxy['keys'] if _['image'] == 'iBEC')
ibec = unpack(ibec, ibec_keys['iv'], ibec_keys['key'])
print('Patching bootchain...')
ibss = patch(patcher, ibss)
ibec = patch(patcher, ibec)
print('Repacking bootchain...')
ibss = repack(ibss, 'ibss', shsh)
ibec = repack(ibec, 'ibec', shsh)
print('Sending bootchain...')
send_bootchain(ibss, ibec, device_data['cpid'])
print(f'Setting generator to {generator}...')
irecv_cmd(f'setenv com.apple.System.boot-nonce {generator}')
irecv_cmd('saveenv')
print('Disabling auto-boot...')
irecv_cmd('setenv auto-boot false')
irecv_cmd('saveenv')
print('Rebooting device into recovery mode...')
irecv_cmd('reboot')
print(f"\nDone! Your device's generator is set to {generator}.")
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment