def __init__(self, udid=None, logger=None): self.logger = logger or logging.getLogger(__name__) self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.allValues = self.getValue() self.udid = self.allValues.get("UniqueDeviceID") self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.allValues.get("DevicePublicKey") self.ios_version = self.allValues.get("ProductVersion") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: raise Exception("Could not get UDID or ECID, failing") if not self.validate_pairing(): self.pair() self.c = PlistService(62078,udid) if not self.validate_pairing(): raise FatalPairingError self.paired = True return
def __init__(self, udid=None): self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" #self.udid = udid self.allValues = self.getValue() self.udid = self.allValues.get("UniqueDeviceID") self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.allValues.get("DevicePublicKey") self.ios_version = self.allValues.get("ProductVersion") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: raise Exception("Could not get UDID or ECID, failing") self.c.close() self.c = PlistService(62078, self.identifier) if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return
def startServiceWithEscrowBag(self, name, escrowBag=None): if not self.paired: self.logger.info("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag': escrowBag }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): if StartService.get("Error", "") == 'PasswordProtected': raise StartServiceError( 'your device is protected with password, please enter password in device and try again' ) raise StartServiceError(StartService.get("Error")) ssl_enabled = StartService.get("EnableServiceSSL", False) plist_service = PlistService(StartService.get("Port"), self.udid) if ssl_enabled: plist_service.ssl_start(self.sslfile, self.sslfile) return plist_service
def __init__(self, udid=None, logger=None): self.logger = logger or logging.getLogger(__name__) self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.udid = self.getValue("", "UniqueDeviceID") self.allValues = self.getValue() self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.getValue("", "DevicePublicKey") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: # print "Could not get UDID or ECID, failing" raise Exception("Could not get UDID or ECID, failing") if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return
def __init__(self, udid=None): self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.udid = udid self.allValues = self.getValue() self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.getValue("", "DevicePublicKey") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: print("Could not get UDID or ECID, failing") raise if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return
def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': print "Unable to retreive DevicePublicKey" return False print "Creating host key & certificate" certPem, privateKeyPem, DeviceCertificate = ca_do_everything( self.DevicePublicKey) pair_record = { "DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516" } pair = { "Label": self.label, "Request": "Pair", "PairRecord": pair_record } self.c = PlistService(62078, self.udid) self.c.sendPlist(pair) pair = self.c.recvPlist() if pair and pair.get("Result") == "Success" or pair.has_key( "EscrowBag"): pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.writePlistToString(pair_record)) self.paired = True return True elif pair and pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: print pair.get("Error") self.c.close() raise PairingError
def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" try: pair_record = plistlib.readPlist(folder + "%s.plist" % self.identifier) except: pair_record = None if pair_record: print "Using iTunes pair record: %s.plist" % self.identifier certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print "No iTunes pairing record found for device %s" % self.identifier print "Looking for pymobiledevice pairing record" record = readHomeFile(HOMEFOLDER, "%s.plist" % self.identifier) if record: pair_record = plistlib.readPlistFromString(record) print "Found pymobiledevice pairing record for device %s" % self.udid certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print "No pymobiledevice pairing record found for device %s" % self.identifier return False self.record = pair_record ValidatePair = {"Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record} self.c = PlistService(62078,self.udid) self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or r.has_key("Error"): pair_record = None print "ValidatePair fail", ValidatePair return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = {"Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID} self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" sslfile = writeHomeFile(HOMEFOLDER, sslfile, certPem + "\n" + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True
def startService(self, name): if not self.paired: self.logger.info("NotPaired") raise NotPairedError self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name }) startService = self.c.recvPlist() ssl_enabled = startService.get("EnableServiceSSL", False) if not startService or startService.get("Error"): raise StartServiceError(startService.get("Error")) plist_service = PlistService(startService.get("Port"), self.udid) if ssl_enabled: plist_service.ssl_start(self.sslfile, self.sslfile) return plist_service
def startService(self, name): if not self.paired: print "NotPaired" raise NotPairedError self.c.sendPlist({"Label": self.label, "Request": "StartService", "Service": name}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
def startServiceWithEscrowBag(self, name, escrowBag = None): if not self.paired: print "NotPaired" raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({"Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag':escrowBag}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): if StartService.get("Error", "") == 'PasswordProtected': raise StartServiceError('your device is protected with password, please enter password in device and try again') raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
def startServiceWithEscrowBag(self, name, escrowBag=None): if not self.paired: print("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag': plistlib.Data(escrowBag) }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': print("Unable to retreive DevicePublicKey") return False print("Creating host key & certificate") certPem, privateKeyPem, DeviceCertificate = ca_do_everything( self.DevicePublicKey) pair_record = {"DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516"} pair = {"Label": self.label, "Request": "Pair", "PairRecord": pair_record} self.c = PlistService(62078, self.udid) self.c.sendPlist(pair) pair = self.c.recvPlist() if pair and pair.get("Result") == "Success" or "EscrowBag" in pair: pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.dumps(pair_record)) self.paired = True return True elif pair and pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: print(pair.get("Error")) self.c.close() raise PairingError
class LockdownClient(object): def __init__(self, udid=None, logger=None): self.logger = logger or logging.getLogger(__name__) self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.udid = self.getValue("", "UniqueDeviceID") self.allValues = self.getValue() self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.getValue("", "DevicePublicKey") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: # print "Could not get UDID or ECID, failing" raise Exception("Could not get UDID or ECID, failing") if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return def queryType(self): self.c.sendPlist({"Request": "QueryType"}) res = self.c.recvPlist() return res.get("Type") def generate_hostID(self): hostname = platform.node() hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname) return str(hostid).upper() def enter_recovery(self): self.c.sendPlist({"Request": "EnterRecovery"}) res = self.c.recvPlist() logger.debug(res) def stop_session(self): if self.SessionID and self.c: self.c.sendPlist({ "Label": self.label, "Request": "StopSession", "SessionID": self.SessionID }) self.SessionID = None res = self.c.recvPlist() if not res or res.get("Result") != "Success": raise CannotStopSessionError return res def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" try: pair_record = plistlib.readPlist(folder + "%s.plist" % self.identifier) except: pair_record = None if pair_record: self.logger.info("Using iTunes pair record: %s.plist", self.identifier) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: self.logger.warn("No iTunes pairing record found for device %s", self.identifier) self.logger.warn("Looking for pymobiledevice pairing record") record = readHomeFile(HOMEFOLDER, "%s.plist" % self.identifier) if record: pair_record = plistlib.readPlistFromString(record) self.logger.info( "Found pymobiledevice pairing record for device %s", self.udid) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: self.logger.warn( "No pymobiledevice pairing record found for device %s", self.identifier) return False self.record = pair_record ValidatePair = { "Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record } self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or "Error" in r: pair_record = None self.logger.error("ValidatePair fail: %s", ValidatePair) return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = { "Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID } self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" sslfile = writeHomeFile(HOMEFOLDER, sslfile, certPem + "\n" + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': self.logger.error("Unable to retreive DevicePublicKey") return False self.logger.info("Creating host key & certificate") certPem, privateKeyPem, DeviceCertificate = ca_do_everything( self.DevicePublicKey) pair_record = { "DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516" } pair = { "Label": self.label, "Request": "Pair", "PairRecord": pair_record } self.c.sendPlist(pair) pair = self.c.recvPlist() if pair and pair.get("Result") == "Success" or "EscrowBag" in pair: pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.writePlistToString(pair_record)) self.paired = True return True elif pair and pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: self.logger.error(pair.get("Error")) self.c.close() raise PairingError def getValue(self, domain=None, key=None): if (isinstance(key, str) and hasattr(self, 'record') and hasattr(self.record, key)): return self.record[key] req = {"Request": "GetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key self.c.sendPlist(req) res = self.c.recvPlist() if res: r = res.get("Value") if hasattr(r, "data"): return r.data return r def setValue(self, value, domain=None, key=None): req = {"Request": "SetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key req["Value"] = value self.c.sendPlist(req) res = self.c.recvPlist() self.logger.debug(res) return res def startService(self, name): if not self.paired: self.logger.info("NotPaired") raise NotPairedError self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid) def startServiceWithEscrowBag(self, name, escrowBag=None): if not self.paired: self.logger.info("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag': escrowBag }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): if StartService.get("Error", "") == 'PasswordProtected': raise StartServiceError( 'your device is protected with password, please enter password in device and try again' ) raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
class LockdownClient(object): def __init__(self, udid=None, logger=None): self.logger = logger or logging.getLogger(__name__) self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.allValues = self.getValue() self.udid = self.allValues.get("UniqueDeviceID") self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.allValues.get("DevicePublicKey") self.ios_version = self.allValues.get("ProductVersion") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: raise Exception("Could not get UDID or ECID, failing") if not self.validate_pairing(): self.pair() self.c = PlistService(62078,udid) if not self.validate_pairing(): raise FatalPairingError self.paired = True return def queryType(self): self.c.sendPlist({"Request":"QueryType"}) res = self.c.recvPlist() return res.get("Type") def generate_hostID(self): hostname = platform.node() hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname) return str(hostid).upper() def enter_recovery(self): self.c.sendPlist({"Request": "EnterRecovery"}) res = self.c.recvPlist() logger.debug(res) def stop_session(self): if self.SessionID and self.c: self.c.sendPlist({"Label": self.label, "Request": "StopSession", "SessionID": self.SessionID}) self.SessionID = None res = self.c.recvPlist() if not res or res.get("Result") != "Success": raise CannotStopSessionError return res def read_pair_record_from_file(self,path): pair_record = None try: with open(path, 'rb') as fd: pair_record = plistlib.readPlist(fd) except IOError as e: self.logger.error("I/O error({0}): {1}".format(e.errno, e.strerror)) self.logger.error("Unable to read: %s", path) except: self.logger.error("Unable to read: %s", path) return pair_record def get_itunes_record_path(self): folder = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" return folder def get_pair_record(self): pair_record = None itune_records_folder_path = self.get_itunes_record_path() if itune_records_folder_path: path = itune_records_folder_path + "%s.plist" % self.identifier pair_record = self.read_pair_record_from_file(path) if pair_record: self.logger.info("Using iTunes pair record: %s.plist", self.identifier) else: self.logger.warning("No iTunes pairing record found for device %s", self.identifier) if pair_record == None: self.logger.warning("Looking for pymobiledevice pairing record...") path = getHomePath(HOMEFOLDER, "%s.plist" % self.identifier) pair_record = self.read_pair_record_from_file(path) if pair_record: self.logger.info("Found pymobiledevice pairing record for device %s", self.udid) else: self.logger.warning("No pymobiledevice pairing record found for device %s", self.identifier) return pair_record def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None pair_record = self.get_pair_record() if PY3: certPem = pair_record["HostCertificate"] privateKeyPem = pair_record["HostPrivateKey"] else: certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data if int(self.ios_version.split('.')[0]) < 11: ValidatePair = {"Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record} self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or r.has_key("Error"): pair_record = None self.logger.error("ValidatePair fail: %s", ValidatePair) return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = {"Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID} self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" lf = "\n" if PY3: lf = b"\n" sslfile = writeHomeFile(HOMEFOLDER, sslfile, certPem + lf + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': self.logger.error("Unable to retreive DevicePublicKey") return False self.logger.info("Creating host key & certificate") certPem, privateKeyPem, DeviceCertificate = ca_do_everything(self.DevicePublicKey) pair_record = {"DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516" } pair = {"Label": self.label, "Request": "Pair", "PairRecord": pair_record} self.c.sendPlist(pair) pair = self.c.recvPlist() print(pair) if pair: if pair.get("Result") == "Success" or pair.get("EscrowBag"): print("kikou") pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.writePlistToString(pair_record)) self.paired = True return True elif pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: self.logger.error(pair.get("Error")) self.c.close() raise PairingError def getValue(self, domain=None, key=None): if(isinstance(key, str) and hasattr(self, 'record') and hasattr(self.record, key)): return self.record[key] req = {"Request":"GetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key self.c.sendPlist(req) res = self.c.recvPlist() if res: r = res.get("Value") if hasattr(r, "data"): return r.data return r def setValue(self, value, domain=None, key=None): req = {"Request":"SetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key req["Value"] = value self.c.sendPlist(req) res = self.c.recvPlist() self.logger.debug(res) return res def startService(self, name): if not self.paired: self.logger.info("NotPaired") raise NotPairedError self.c.sendPlist({"Label": self.label, "Request": "StartService", "Service": name}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid) def startServiceWithEscrowBag(self, name, escrowBag = None): if not self.paired: self.logger.info("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({"Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag':escrowBag}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): if StartService.get("Error", "") == 'PasswordProtected': raise StartServiceError('your device is protected with password, please enter password in device and try again') raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
class LockdownClient(object): def __init__(self, udid=None): self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" #self.udid = udid self.allValues = self.getValue() self.udid = self.allValues.get("UniqueDeviceID") self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.allValues.get("DevicePublicKey") self.ios_version = self.allValues.get("ProductVersion") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: raise Exception("Could not get UDID or ECID, failing") self.c.close() self.c = PlistService(62078, self.identifier) if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return def queryType(self): self.c.sendPlist({"Request": "QueryType"}) res = self.c.recvPlist() return res.get("Type") def generate_hostID(self): hostname = platform.node() hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname) return str(hostid).upper() def enter_recovery(self): self.c.sendPlist({"Request": "EnterRecovery"}) print(self.c.recvPlist()) def stop_session(self): if self.SessionID and self.c: self.c.sendPlist({ "Label": self.label, "Request": "StopSession", "SessionID": self.SessionID }) self.SessionID = None res = self.c.recvPlist() if not res or res.get("Result") != "Success": raise CannotStopSessionError return res def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" try: pair_record = plistlib.readPlist(folder + "%s.plist" % self.identifier) except: pair_record = None if pair_record: print("Using iTunes pair record: %s.plist" % self.identifier) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: # LucaV 05.09.2018: se la data del file non corrisponde alla data odierna, richiede il pairing device_data_file = os.path.join(os.path.expanduser('~'), HOMEFOLDER, "%s.plist" % self.identifier) if os.path.isfile(device_data_file): from datetime import datetime, timedelta file_date = datetime.fromtimestamp( os.path.getmtime(device_data_file)) file_date = file_date.replace(hour=0, minute=0, second=0, microsecond=0) today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0) if today - file_date > timedelta(days=1): try: os.remove(device_data_file) except: pass print("No iTunes pairing record found for device %s" % self.identifier) print("Looking for pymobiledevice pairing record") record = readHomeFile(HOMEFOLDER, "%s.plist" % self.identifier) if record: # pair_record = plistlib.loads(record) pair_record = plistlib.readPlistFromBytes(record) print("Found pymobiledevice pairing record for device %s" % self.udid) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print("No pymobiledevice pairing record found for device %s" % self.identifier) return False self.record = pair_record try: ios_major_version = int(self.ios_version.split('.')[0]) except: print("Unable to parse ProductVersion string: %s" % self.ios_version) ios_major_version = 0 if ios_major_version < 11: ValidatePair = { "Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record } self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or "Error" in r: pair_record = None print("ValidatePair fail", ValidatePair) return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = { "Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID } self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" sslfile = writeHomeFile(HOMEFOLDER, sslfile, certPem + b"\n" + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': print("Unable to retreive DevicePublicKey") return False print("Creating host key & certificate") certPem, privateKeyPem, DeviceCertificate = ca_do_everything( self.DevicePublicKey) pair_record = { "DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516" } pair = { "Label": self.label, "Request": "Pair", "PairRecord": pair_record } self.c.sendPlist(pair) pair = self.c.recvPlist() if pair and pair.get("Result") == "Success" or "EscrowBag" in pair: pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.dumps(pair_record)) self.paired = True return True elif pair and pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: print(pair.get("Error")) self.c.close() raise PairingError def getValue(self, domain=None, key=None): if (isinstance(key, str) and hasattr(self, 'record') and hasattr(self.record, key)): return self.record[key] req = {"Request": "GetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key self.c.sendPlist(req) res = self.c.recvPlist() if res: r = res.get("Value") if hasattr(r, "data"): return r.data return r def setValue(self, value, domain=None, key=None): req = {"Request": "SetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key req["Value"] = value self.c.sendPlist(req) res = self.c.recvPlist() print(res) return res def startService(self, name): if not self.paired: print("NotPaired") raise NotPairedError self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid) def startServiceWithEscrowBag(self, name, escrowBag=None): if not self.paired: print("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag': escrowBag }) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): if StartService.get("Error", "") == 'PasswordProtected': raise StartServiceError( 'your device is protected with password, please enter password in device and try again' ) raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)
def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" try: pair_record = plistlib.readPlist(folder + "%s.plist" % self.identifier) except: pair_record = None if pair_record: print "Using iTunes pair record: %s.plist" % self.identifier certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print "No iTunes pairing record found for device %s" % self.identifier print "Looking for pymobiledevice pairing record" record = readHomeFile(HOMEFOLDER, "%s.plist" % self.identifier) if record: pair_record = plistlib.readPlistFromString(record) print "Found pymobiledevice pairing record for device %s" % self.udid certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print "No pymobiledevice pairing record found for device %s" % self.identifier return False self.record = pair_record ValidatePair = { "Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record } self.c = PlistService(62078, self.udid) self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or r.has_key("Error"): pair_record = None print "ValidatePair fail", ValidatePair return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = { "Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID } self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" sslfile = writeHomeFile(HOMEFOLDER, sslfile, certPem + "\n" + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True
class LockdownClient(object): def __init__(self, udid=None): self.paired = False self.SessionID = None self.c = PlistService(62078, udid) self.hostID = self.generate_hostID() self.SystemBUID = self.generate_hostID() self.paired = False self.label = "pyMobileDevice" assert self.queryType() == "com.apple.mobile.lockdown" self.udid = udid self.allValues = self.getValue() self.UniqueChipID = self.allValues.get("UniqueChipID") self.DevicePublicKey = self.getValue("", "DevicePublicKey") self.identifier = self.udid if not self.identifier: if self.UniqueChipID: self.identifier = "%x" % self.UniqueChipID else: print("Could not get UDID or ECID, failing") raise if not self.validate_pairing(): self.pair() if not self.validate_pairing(): raise FatalPairingError self.paired = True return def queryType(self): self.c.sendPlist({"Request": "QueryType"}) res = self.c.recvPlist() return res.get("Type") def generate_hostID(self): hostname = platform.node() hostid = uuid.uuid3(uuid.NAMESPACE_DNS, hostname) return str(hostid).upper() def enter_recovery(self): self.c.sendPlist({"Request": "EnterRecovery"}) print(self.c.recvPlist()) def stop_session(self): if self.SessionID and self.c: self.c.sendPlist({ "Label": self.label, "Request": "StopSession", "SessionID": self.SessionID}) self.SessionID = None res = self.c.recvPlist() if not res or res.get("Result") != "Success": raise CannotStopSessionError return res def validate_pairing(self): pair_record = None certPem = None privateKeyPem = None if sys.platform == "win32": folder = os.environ["ALLUSERSPROFILE"] + "/Apple/Lockdown/" elif sys.platform == "darwin": folder = "/var/db/lockdown/" elif len(sys.platform) >= 5: if sys.platform[0:5] == "linux": folder = "/var/lib/lockdown/" try: pair_record = plistlib.readPlist( folder + "%s.plist" % self.identifier) except: pair_record = None if pair_record: print("Using iTunes pair record: %s.plist" % self.identifier) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print("No iTunes pairing record found for device %s" % self.identifier) print("Looking for pymobiledevice pairing record") record = readHomeFile(HOMEFOLDER, "%s.plist" % self.identifier) if record: pair_record = plistlib.loads(record) print("Found pymobiledevice pairing record for device %s" % self.udid) certPem = pair_record["HostCertificate"].data privateKeyPem = pair_record["HostPrivateKey"].data else: print("No pymobiledevice pairing record found for device %s" % self.identifier) return False ValidatePair = {"Label": self.label, "Request": "ValidatePair", "PairRecord": pair_record} self.c = PlistService(62078, self.udid) self.c.sendPlist(ValidatePair) r = self.c.recvPlist() if not r or "Error" in r: pair_record = None print("ValidatePair fail", ValidatePair) return False self.hostID = pair_record.get("HostID", self.hostID) self.SystemBUID = pair_record.get("SystemBUID", self.SystemBUID) d = {"Label": self.label, "Request": "StartSession", "HostID": self.hostID, 'SystemBUID': self.SystemBUID} self.c.sendPlist(d) startsession = self.c.recvPlist() self.SessionID = startsession.get("SessionID") if startsession.get("EnableSessionSSL"): sslfile = self.identifier + "_ssl.txt" # print(HOMEFOLDER, sslfile, certPem, "\n", privateKeyPem) sslfile = writeHomeFile( HOMEFOLDER, sslfile, certPem + b"\n" + privateKeyPem) self.c.ssl_start(sslfile, sslfile) self.paired = True return True def pair(self): self.DevicePublicKey = self.getValue("", "DevicePublicKey") if self.DevicePublicKey == '': print("Unable to retreive DevicePublicKey") return False print("Creating host key & certificate") certPem, privateKeyPem, DeviceCertificate = ca_do_everything( self.DevicePublicKey) pair_record = {"DevicePublicKey": plistlib.Data(self.DevicePublicKey), "DeviceCertificate": plistlib.Data(DeviceCertificate), "HostCertificate": plistlib.Data(certPem), "HostID": self.hostID, "RootCertificate": plistlib.Data(certPem), "SystemBUID": "30142955-444094379208051516"} pair = {"Label": self.label, "Request": "Pair", "PairRecord": pair_record} self.c = PlistService(62078, self.udid) self.c.sendPlist(pair) pair = self.c.recvPlist() if pair and pair.get("Result") == "Success" or "EscrowBag" in pair: pair_record["HostPrivateKey"] = plistlib.Data(privateKeyPem) pair_record["EscrowBag"] = pair.get("EscrowBag") writeHomeFile(HOMEFOLDER, "%s.plist" % self.identifier, plistlib.dumps(pair_record)) self.paired = True return True elif pair and pair.get("Error") == "PasswordProtected": self.c.close() raise NotTrustedError else: print(pair.get("Error")) self.c.close() raise PairingError def getValue(self, domain=None, key=None): if( isinstance(key, str) and hasattr(self, 'record')and hasattr(self.record, key)): return self.record[key] req = {"Request": "GetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key self.c.sendPlist(req) res = self.c.recvPlist() if res: r = res.get("Value") if hasattr(r, "data"): return r.data return r def setValue(self, domain=None, key=None): req = {"Request": "SetValue", "Label": self.label} if domain: req["Domain"] = domain if key: req["Key"] = key self.c.sendPlist(req) res = self.c.recvPlist() print(res) return res def startService(self, name): if not self.paired: print("NotPaired") raise NotPairedError self.c.sendPlist( {"Label": self.label, "Request": "StartService", "Service": name}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid) def startServiceWithEscrowBag(self, name, escrowBag=None): if not self.paired: print("NotPaired") raise NotPairedError if (not escrowBag): escrowBag = self.record['EscrowBag'] self.c.sendPlist({ "Label": self.label, "Request": "StartService", "Service": name, 'EscrowBag': plistlib.Data(escrowBag)}) StartService = self.c.recvPlist() if not StartService or StartService.get("Error"): raise StartServiceError(StartService.get("Error")) return PlistService(StartService.get("Port"), self.udid)