hacks/dump-imessages/iphone-dataprotection/python_scripts/util/ramdiskclient.py

172 lines
4.7 KiB
Python

import plistlib
import struct
import socket
from datetime import datetime
from progressbar import ProgressBar, Percentage, Bar, SimpleProgress, ETA
from usbmux import usbmux
from util import sizeof_fmt
kIOAESAcceleratorEncrypt = 0
kIOAESAcceleratorDecrypt = 1
kIOAESAcceleratorGIDMask = 0x3E8
kIOAESAcceleratorUIDMask = 0x7D0
class DeviceInfo(dict):
@staticmethod
def create(dict):
try:
assert dict.has_key("dataVolumeUUID")
filename = "%s.plist" % dict.get("dataVolumeUUID")
return DeviceInfo(plistlib.readPlist(filename))
except:
return DeviceInfo(dict)
def save(self):
filename = "%s.plist" % self.get("dataVolumeUUID", "unk")
plistlib.writePlist(self, filename)
#stop doing magic stuff
#def __del__(self):
# self.save()
class RamdiskToolClient(object):
instance = None
@staticmethod
def get():
if not RamdiskToolClient.instance:
RamdiskToolClient.instance = RamdiskToolClient()
return RamdiskToolClient.instance
def __init__(self, udid=None, host="localhost", port=1999):
self.host = host
self.port = port
self.device_infos = {}
self.s = None
self.connect(udid)
self.getDeviceInfos()
def close(self):
if self.s:
self.s.close()
self.s = None
def connect(self, udid=None):
mux = usbmux.USBMux()
mux.process(1.0)
if not mux.devices:
print "Waiting for iOS device"
while not mux.devices:
mux.process(1.0)
if not mux.devices:
print "No device found"
return
dev = mux.devices[0]
print "Connecting to device : " + dev.serial
try:
self.s = mux.connect(dev, self.port)
except:
raise Exception("Connexion to device port %d failed" % self.port)
def getDeviceInfos(self):
self.device_infos = self.send_req({"Request":"DeviceInfo"})
keys = self.grabDeviceKeys()
if keys:
self.device_infos.update(keys)
return DeviceInfo.create(self.device_infos)
def downloadFile(self, path):
res = self.send_req({"Request": "DownloadFile",
"Path": path})
if type(res) == plistlib._InternalDict and res.has_key("Data"):
return res["Data"].data
def getSystemKeyBag(self):
return self.send_req({"Request":"GetSystemKeyBag"})
def bruteforceKeyBag(self, KeyBagKeys):
return self.send_req({"Request":"BruteforceSystemKeyBag",
"KeyBagKeys": plistlib.Data(KeyBagKeys)})
def getEscrowRecord(self, hostID):
return self.send_req({"Request":"GetEscrowRecord",
"HostID": hostID})
def getPasscodeKey(self, keybagkeys, passcode):
return self.send_req({"Request":"KeyBagGetPasscodeKey",
"KeyBagKeys": plistlib.Data(keybagkeys),
"passcode": passcode})
def send_msg(self, dict):
plist = plistlib.writePlistToString(dict)
data = struct.pack("<L",len(plist)) + plist
return self.s.send(data)
def recv_msg(self):
try:
l = self.s.recv(4)
if len(l) != 4:
return None
ll = struct.unpack("<L",l)[0]
data = ""
l = 0
while l < ll:
x = self.s.recv(ll-l)
if not x:
return None
data += x
l += len(x)
return plistlib.readPlistFromString(data)
except:
raise
return None
def send_req(self, dict):
start = None
self.send_msg(dict)
while True:
r = self.recv_msg()
if type(r) == plistlib._InternalDict and r.get("MessageType") == "Progress":
if not start:
pbar = ProgressBar(r.get("Total",100),[SimpleProgress(), " ", ETA(), "\n", Percentage(), " ", Bar()])
pbar.start()
start = datetime.utcnow()
pbar.update( r.get("Progress", 0))
else:
if start:
pbar.finish()
print dict.get("Request"), ":", datetime.utcnow() - start
return r
def aesUID(self, data):
return self.aes(data, kIOAESAcceleratorUIDMask, kIOAESAcceleratorEncrypt)
def aesGID(self, data):
return self.aes(data, kIOAESAcceleratorGIDMask, kIOAESAcceleratorDecrypt)
def aes(self, data, keyMask, mode):
return self.send_req({"Request":"AES",
"input": plistlib.Data(data),
"keyMask": keyMask,
"mode": mode,
"bits": 128
})
def grabDeviceKeys(self):
blobs = {"key835": "\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01",
"key899": "\xD1\xE8\xFC\xB5\x39\x37\xBF\x8D\xEF\xC7\x4C\xD1\xD0\xF1\xD4\xB0",
"key89A": "\xDB\x1F\x5B\x33\x60\x6C\x5F\x1C\x19\x34\xAA\x66\x58\x9C\x06\x61",
"key89B": "\x18\x3E\x99\x67\x6B\xB0\x3C\x54\x6F\xA4\x68\xF5\x1C\x0C\xBD\x49"
}
for k,b in blobs.items():
r = self.aesUID(b)
if not r or r.returnCode != 0 or not r.has_key("data"):
print "AES UID error"
return
blobs[k] = r.data.data.encode("hex")
return blobs
def reboot(self):
print "Rebooting device"
return self.send_req({"Request":"Reboot"})