Skip to content

Commit

Permalink
🐛 Fixed and improved firmware keys grabber
Browse files Browse the repository at this point in the history
sunst0rm now grabs the keys directly from theapplewiki.com instead of m1stadev's wikiproxy, because wikiproxy currently seems down

(note that the source code is taken from wikiproxy itself)
  • Loading branch information
rastiqdev committed Dec 9, 2023
1 parent 3998910 commit 9b7a7eb
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 10 deletions.
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
requests
remotezip
pyimg4
datetime
wikitextparser
19 changes: 9 additions & 10 deletions utils/api.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import requests
import wiki
from remotezip import RemoteZip

def get_keys(identifier, board, buildid):
try:
f = requests.get(f"https://api.m1sta.xyz/wikiproxy/{identifier}/{board}/{buildid}").json()
f = wiki.get_firmware_keys(identifier, board, buildid)
except Exception:
if input(f"[?] Keys not found for this IPSW ({buildid}) for the board {board}. Do you want to enter keys manually? (y/n) ") == "y":
iBSS_iv = input(" - Enter the iBSS IV: ")
Expand All @@ -14,17 +14,16 @@ def get_keys(identifier, board, buildid):
else:
exit()
print("Requesting keys...")
for dev in f['keys']:
if dev['image'] == "iBSS":
iBSS_iv = dev['iv']
iBSS_key = dev['key']
if dev['image'] == "iBEC":
iBEC_iv = dev['iv']
iBEC_key = dev['key']

iBSS_iv = f['iBSSIV']
iBSS_key = f['iBSSKey']
iBEC_iv = f['iBECIV']
iBEC_key = f['iBECKey']

try:
return iBSS_iv, iBSS_key, iBEC_iv, iBEC_key
except UnboundLocalError:
print("[WARNING] Unable to get firmware keys, either the bootchain is not encrypted or the wikiproxy does not have it.")
print("[WARNING] Unable to get firmware keys, either the bootchain is not encrypted or theapplewiki.com does not have it.")
input("Continue or not? (Press ENTER to continue, Ctrl-C to quit)")

def partialzip_download(url, file, dest):
Expand Down
141 changes: 141 additions & 0 deletions utils/wiki.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
from datetime import datetime

import requests
import re
import wikitextparser as wtp

DEVICE_REGEX = re.compile(r'(iPhone|AppleTV|iPad|iPod)[0-9]+,[0-9]+')

def get_key_page(identifier: str, buildid: str) -> str:
params = {
'action': 'query',
'list': 'search',
'srsearch': f'Keys: {buildid} ({identifier})',
'srwhat': 'title',
'srlimit': '1',
'format': 'json',
'srnamespace': '2304',
}
resp = requests.get(
'https://theapplewiki.com/api.php', params=params
)
if resp.status_code != 200:
pass
else:
search = resp.json()

if search['query']['searchinfo']['totalhits'] == 0:
raise ValueError(
f'No Firmware Keys page for device: {identifier}, buildid: {buildid}.'
)

params = {
'action': 'parse',
'prop': 'wikitext',
'page': search['query']['search'][0]['title'],
'format': 'json',
'formatversion': 2,
}
resp = requests.get(
'https://theapplewiki.com/api.php', params=params
)
if resp.status_code != 200:
pass

data = resp.json()

return data['parse']['wikitext']


def parse_page(data: str, identifer: str, boardconfig: str = None) -> dict:
data = (
' '.join([x for x in data.split(' ') if x != ''])
.replace('{{', '{| class="wikitable"')
.replace('}}', '|}')
)

page = wtp.parse(data)
page_data = {}
for entry in page.tables[0].data()[0]:
key, item = entry.split(' = ')
page_data[key] = item

if boardconfig is not None:
if ('Model' not in page_data.keys()) and ('Model2' not in page_data.keys()):
return page_data

if boardconfig.lower() not in [x.lower() for x in page_data.values()]:
raise ValueError(
f'Boardconfig: {boardconfig} for device: {identifer} is not valid!'
)

if page_data['Model2'].lower() == boardconfig.lower():
for key in page_data:
if '2' in key:
page_data[key.replace('2', '')] = page_data[key]

for key in list(page_data.keys()):
if '2' in key:
del page_data[key]

response = {
'identifier': page_data['Device'],
'buildid': page_data['Build'],
'codename': page_data['Codename'],
'restoreramdiskexists': 'RestoreRamdisk' in page_data,
'updateramdiskexists': 'UpdateRamdisk' in page_data,
'keys': [],
}

for component in page_data:
if component in (
'Version',
'Build',
'Device',
'Model',
'Codename',
'Baseband',
'DownloadURL',
):
continue

if any(component.endswith(x) for x in ('Key', 'IV', 'KBAG')):
continue

image = {
'image': component,
'filename': page_data[component],
'date': datetime.now().isoformat(),
}

if any(component == x for x in ('RootFS', 'RestoreRamdisk', 'UpdateRamdisk')):
image['filename'] += '.dmg'

for key in ('IV', 'Key') if component != 'RootFS' else ('Key',):
if component + key not in page_data.keys():
continue

if all(
x not in page_data[component + key]
for x in ('Unknown', 'Not Encrypted')
):
image[key.lower()] = page_data[component + key]

if (
('iv' not in image.keys())
and ('key' not in image.keys())
and not image['filename'].endswith('.dmg')
):
continue

if 'iv' in image and 'key' in image:
image['kbag'] = image['iv'] + image['key']

response['keys'].append(image)

return response

def get_firmware_keys(identifier: str, boardconfig: str, buildid: str) -> dict:
page = get_key_page(identifier, buildid)

return parse_page(page, identifier, boardconfig)

0 comments on commit 9b7a7eb

Please sign in to comment.