This commit is contained in:
edwin 2023-07-16 16:16:34 -04:00
parent e08fe160fd
commit 0e59ab21a7
2 changed files with 193 additions and 5 deletions

View file

@ -430,10 +430,10 @@ fi
# Check for pyimg4
if ! python3 -c 'import pkgutil; exit(not pkgutil.find_loader("pyimg4"))'; then
echo '[-] pyimg4 not installed. Press any key to install it, or press ctrl + c to cancel'
if ! python3 -c 'import pkgutil; exit(not pkgutil.find_loader("fastapi") and not pkgutil.find_loader("aiohttp") and not pkgutil.find_loader("ujson") and not pkgutil.find_loader("wikitextparser") and not pkgutil.find_loader("uvicorn") and not pkgutil.find_loader("pyimg4"))'; then
echo '[-] One or more required modules are not installed. Press any key to install them, or press ctrl + c to cancel'
read -n 1 -s
python3 -m pip install pyimg4
python3 -m pip install fastapi aiohttp ujson wikitextparser uvicorn pyimg4
fi
# Update submodules
@ -552,6 +552,11 @@ if [ "$boot" = "1" ]; then # call boot in order to boot it
_boot
fi
if [[ ! "$version" = "13."* ]]; then
kernelpatcher_ios="Kernel15patcher.ios"
else
kernelpatcher_ios="Kernel13patcher.ios"
fi
# =========
# extract ipsw
@ -670,7 +675,7 @@ if [ true ]; then
remote_cp work/kcache.raw root@localhost:/mnt6/$active/System/Library/Caches/com.apple.kernelcaches/kcache.raw
remote_cp boot/"${deviceid}"/kernelcache.img4 "root@localhost:/mnt6/$active/System/Library/Caches/com.apple.kernelcaches/kernelcache"
remote_cp binaries/Kernel15Patcher.ios root@localhost:/mnt1/private/var/root/Kernel15Patcher.ios
remote_cp binaries/$kernelpatcher_ios root@localhost:/mnt1/private/var/root/Kernel15Patcher.ios
remote_cmd "/usr/sbin/chown 0 /mnt1/private/var/root/Kernel15Patcher.ios"
remote_cmd "/bin/chmod 755 /mnt1/private/var/root/Kernel15Patcher.ios"
sleep 1
@ -781,7 +786,7 @@ done
python3 -m pyimg4 im4p extract -i work/kernelcache -o work/kcache.raw
fi
remote_cp work/kcache.raw root@localhost:/mnt1/System/Library/Caches/com.apple.kernelcaches/kcache.raw
remote_cp binaries/Kernel15Patcher.ios root@localhost:/mnt1/private/var/root/kpf15.ios
remote_cp binaries/$kernelpatcher_ios root@localhost:/mnt1/private/var/root/kpf15.ios
remote_cmd "/usr/sbin/chown 0 /mnt1/private/var/root/kpf15.ios"
remote_cmd "/bin/chmod 755 /mnt1/private/var/root/kpf15.ios"
sleep 1
@ -960,6 +965,8 @@ done
echo "[*] Sucess Patching the boot files"
sleep 1
echo "[*] Executing wikiproxy.py in order to fix key issue"
python3 wikiproxy.py
set +e
"$dir"/gaster reset

181
wikiproxy.py Normal file
View file

@ -0,0 +1,181 @@
#!/usr/bin/env python3
from fastapi import FastAPI
from datetime import datetime
import aiohttp
import asyncio
import re
import time
import ujson
import wikitextparser as wtp
import uvicorn
DEVICE_REGEX = re.compile(r'(iPhone|AppleTV|iPad|iPod)[0-9]+,[0-9]+')
# Only allow 100 simultaneous HTTP requests
HTTP_SEMAPHORE = asyncio.Semaphore(100)
async def get_key_page(
session: aiohttp.ClientSession, identifier: str, buildid: str
) -> str:
params = {
'action': 'query',
'list': 'search',
'srsearch': f'Keys: {buildid} ({identifier})',
'srwhat': 'title',
'srlimit': '1',
'format': 'json',
'srnamespace': '2304',
}
async with HTTP_SEMAPHORE, session.get(
'https://theapplewiki.com/api.php', params=params
) as resp:
if resp.status != 200:
pass # raise error
else:
search = await 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,
}
async with HTTP_SEMAPHORE, session.get(
'https://theapplewiki.com/api.php', params=params
) as resp:
if resp.status != 200:
pass # raise error
data = await resp.json()
return data['parse']['wikitext']
def parse_page(data: str, identifer: str, boardconfig: str = None) -> dict:
# Have to coerce wikitextparser into recognizing it as a table for easy parsing
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
app = FastAPI()
@app.middleware('http')
async def add_process_time_header(request, call_next):
start_time = time.time()
response = await call_next(request)
response.headers['X-Process-Time'] = str(f'{time.time() - start_time:0.4f} sec')
return response
@app.get('/firmware/{identifier}/{buildid}')
async def get_firmware_keys(identifier: str, buildid: str) -> dict:
async with aiohttp.ClientSession() as session:
page = await get_key_page(session, identifier, buildid)
return parse_page(page, identifier)
@app.get('/firmware/{identifier}/{boardconfig}/{buildid}')
async def get_firmware_keys(identifier: str, boardconfig: str, buildid: str) -> dict:
async with aiohttp.ClientSession() as session:
page = await get_key_page(session, identifier, buildid)
return parse_page(page, identifier, boardconfig)
if __name__ == '__main__':
uvicorn.run(app='__main__:app', host='127.0.0.1', port='8888')