class FileRelay(object): def __init__(self, lockdown=None, serviceName="com.apple.mobile.file_relay"): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() ProductVersion = self.lockdown.getValue("", "ProductVersion") if ProductVersion[0] >= "8": raise DeviceVersionNotSupported self.service = self.lockdown.startService(serviceName) self.packet_num = 0 def stop_session(self): print "Disconecting..." self.service.close() def request_sources(self, sources=["UserDatabases"]): self.service.sendPlist({"Sources": sources}) while 1: res = self.service.recvPlist() pprint(res) if res: s = res.get("Status") if s == "Acknowledged": z = "" while True: x = self.service.recv() if not x: break z += x return z else: print res.get("Error") break return None
class FileRelay(object): def __init__(self, lockdown=None, serviceName="com.apple.mobile.file_relay"): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() ProductVersion = self.lockdown.getValue("", "ProductVersion") if ProductVersion[0] >= "8": raise DeviceVersionNotSupported self.service = self.lockdown.startService(serviceName) self.packet_num = 0 def stop_session(self): print "Disconecting..." self.service.close() def request_sources(self, sources=["UserDatabases"]): self.service.sendPlist({"Sources": sources}) while 1: res = self.service.recvPlist() if res: s = res.get("Status") if s == "Acknowledged": z = "" while True: x = self.service.recv() if not x: break z += x return z else: print res.get("Error") break return None
class MobileBackup2Client(MobileBackupClient): def __init__(self, lockdown = None,backupPath = None): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() try: self.udid = lockdown.getValue("", "UniqueDeviceID")#lockdown.udid except: self.lockdown = LockdownClient() self.udid = self.lockdown.getValue("", "UniqueDeviceID") self.service = self.lockdown.startService("com.apple.mobilebackup2") if not self.service: raise Exception("MobileBackup2Client init error : Could not start com.apple.mobilebackup2") if backupPath: self.backupPath = backupPath else: self.backupPath = "backups" #self.udid if not os.path.isdir(self.backupPath): os.makedirs(self.backupPath,0o0755) print "Starting new com.apple.mobilebackup2 service with working dir: %s" % self.backupPath self.password = "" DLMessageVersionExchange = self.service.recvPlist() #print DLMessageVersionExchange version_major = DLMessageVersionExchange[1] self.service.sendPlist(["DLMessageVersionExchange", "DLVersionsOk", version_major]) DLMessageDeviceReady = self.service.recvPlist() #print DLMessageDeviceReady if DLMessageDeviceReady and DLMessageDeviceReady[0] == "DLMessageDeviceReady": #print "Got DLMessageDeviceReady" self.version_exchange() else: raise Exception("MobileBackup2Client init error %s" % DLMessageDeviceReady) def __del__(self): if self.service: #print "Disconnecting" self.service.sendPlist(["DLMessageDisconnect", "___EmptyParameterString___"]) #print self.service.recvPlist() def internal_mobilebackup2_send_message(self, name, data): data["MessageName"] = name self.device_link_service_send_process_message(data) def internal_mobilebackup2_receive_message(self, name=None): res = self.device_link_service_receive_process_message() if res: if name and res["MessageName"] != name: print "MessageName does not match %s %s" % (name, str(res)) return res def version_exchange(self): self.internal_mobilebackup2_send_message("Hello", {"SupportedProtocolVersions": [2.0,2.1]}) return self.internal_mobilebackup2_receive_message("Response") def mobilebackup2_send_request(self, request, target, source, options={}): d = {"TargetIdentifier": target, "SourceIdentifier": source, "Options": options} #pprint(d) self.internal_mobilebackup2_send_message(request, d) def mobilebackup2_receive_message(self): return self.service.recvPlist() def mobilebackup2_send_status_response(self, status_code, status1="___EmptyParameterString___", status2={}): a = ["DLMessageStatusResponse", status_code, status1, status2] self.service.sendPlist(a) def mb2_handle_free_disk_space(self,msg): #DRK s = os.statvfs(self.backupPath) freeSpace = s.f_bsize * s.f_bavail #print "freeSpage %s" % freeSpace a = ["DLMessageStatusResponse", 0, freeSpace] self.service.sendPlist(a) def mb2_multi_status_add_file_error(self, errplist, path, error_code, error_message): errplist[path] = {"DLFileErrorCode": error_code, "DLFileErrorString": error_message} def mb2_handle_copy_item(self, msg): src = self.check_filename(msg[1]) dst = self.check_filename(msg[2]) if os.path.isfile(src): data = self.read_file(src) self.write_file(dst, data) else: os.makedirs(dst) self.mobilebackup2_send_status_response(0) def mb2_handle_send_file(self, filename, errplist): self.service.send_raw(filename) if not filename.startswith(self.udid): filename = self.udid + "/" + filename #print "Reading",self.check_filename(filename) #FIXME data = self.read_file(self.check_filename(filename)) if data != None: #print hexdump(data) print "Sending %s to device" % filename self.service.send_raw(chr(CODE_FILE_DATA) + data) self.service.send_raw(chr(CODE_SUCCESS)) else: #print "DATA %s" % hexdump(data) print "File %s requested from device not found" % filename self.service.send_raw(chr(CODE_ERROR_LOCAL)) self.mb2_multi_status_add_file_error(errplist, filename, ERROR_ENOENT, "Could not find the droid you were looking for ;)") def mb2_handle_send_files(self, msg): errplist = {} for f in msg[1]: self.mb2_handle_send_file(f, errplist) self.service.send("\x00\x00\x00\x00") if len(errplist): self.mobilebackup2_send_status_response(-13, "Multi status", errplist) else: self.mobilebackup2_send_status_response(0) def mb2_handle_list_directory(self, msg): path = msg[1] dirlist = {} self.mobilebackup2_send_status_response(0, status2=dirlist); def mb2_handle_make_directory(self, msg): dirname = self.check_filename(msg[1]) print "Creating directory %s" % dirname if not os.path.isdir(dirname): os.makedirs(dirname) self.mobilebackup2_send_status_response(0, "") def mb2_handle_receive_files(self, msg): done = 0 while not done: device_filename = self.service.recv_raw() if device_filename == "": break backup_filename = self.service.recv_raw() #print device_filename, backup_filename filedata = "" while True: stuff = self.service.recv_raw() if ord(stuff[0]) == CODE_FILE_DATA: filedata += stuff[1:] elif ord(stuff[0]) == CODE_SUCCESS: #print "Success" self.write_file(self.check_filename(backup_filename), filedata) break else: print "Unknown code", ord(stuff[0]) break self.mobilebackup2_send_status_response(0) def mb2_handle_move_files(self, msg): for k,v in msg[1].items(): print "Renaming %s to %s" % (self.check_filename(k),self.check_filename(v)) os.rename(self.check_filename(k),self.check_filename(v)) self.mobilebackup2_send_status_response(0) def mb2_handle_remove_files(self, msg): for filename in msg[1]: print "Removing ", self.check_filename(filename) try: filename = self.check_filename(filename) if os.path.isfile(filename): os.unlink(filename) except Exception, e: print e self.mobilebackup2_send_status_response(0)
class MobileBackup2(MobileBackup): service = None def __init__(self, lockdown=None, backupPath=None): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() ProductVersion = self.lockdown.getValue("", "ProductVersion") if ProductVersion[0] < "5": raise DeviceVersionNotSupported self.udid = lockdown.getValue("", "UniqueDeviceID") self.willEncrypt = lockdown.getValue("com.apple.mobile.backup", "WillEncrypt") self.service = self.lockdown.startService("com.apple.mobilebackup2") if not self.service: raise Exception( "MobileBackup2 init error : Could not start com.apple.mobilebackup2" ) if backupPath: self.backupPath = backupPath else: self.backupPath = "backups" if not os.path.isdir(self.backupPath): os.makedirs(self.backupPath, 0o0755) print "Starting new com.apple.mobilebackup2 service with working dir: %s" % self.backupPath self.password = "" DLMessageVersionExchange = self.service.recvPlist() version_major = DLMessageVersionExchange[1] self.service.sendPlist( ["DLMessageVersionExchange", "DLVersionsOk", version_major]) DLMessageDeviceReady = self.service.recvPlist() if DLMessageDeviceReady and DLMessageDeviceReady[ 0] == "DLMessageDeviceReady": self.version_exchange() else: raise Exception("MobileBackup2 init error %s" % DLMessageDeviceReady) def __del__(self): if self.service: self.service.sendPlist( ["DLMessageDisconnect", "___EmptyParameterString___"]) def internal_mobilebackup2_send_message(self, name, data): data["MessageName"] = name self.device_link_service_send_process_message(data) def internal_mobilebackup2_receive_message(self, name=None): res = self.device_link_service_receive_process_message() if res: if name and res["MessageName"] != name: print "MessageName does not match %s %s" % (name, str(res)) return res def version_exchange(self): self.internal_mobilebackup2_send_message( "Hello", {"SupportedProtocolVersions": [2.0, 2.1]}) return self.internal_mobilebackup2_receive_message("Response") def mobilebackup2_send_request(self, request, target, source, options={}): d = { "TargetIdentifier": target, "SourceIdentifier": source, "Options": options } self.internal_mobilebackup2_send_message(request, d) def mobilebackup2_receive_message(self): return self.service.recvPlist() def mobilebackup2_send_status_response( self, status_code, status1="___EmptyParameterString___", status2={}): a = ["DLMessageStatusResponse", status_code, status1, status2] self.service.sendPlist(a) def mb2_handle_free_disk_space(self, msg): s = os.statvfs(self.backupPath) freeSpace = s.f_bsize * s.f_bavail a = ["DLMessageStatusResponse", 0, freeSpace] self.service.sendPlist(a) def mb2_multi_status_add_file_error(self, errplist, path, error_code, error_message): errplist[path] = { "DLFileErrorCode": error_code, "DLFileErrorString": error_message } def mb2_handle_copy_item(self, msg): src = self.check_filename(msg[1]) dst = self.check_filename(msg[2]) if os.path.isfile(src): data = self.read_file(src) self.write_file(dst, data) else: os.makedirs(dst) self.mobilebackup2_send_status_response(0) def mb2_handle_send_file(self, filename, errplist): self.service.send_raw(filename) if not filename.startswith(self.udid): filename = self.udid + "/" + filename data = self.read_file(self.check_filename(filename)) if data != None: print "Sending %s to device" % filename self.service.send_raw(chr(CODE_FILE_DATA) + data) self.service.send_raw(chr(CODE_SUCCESS)) else: print "File %s requested from device not found" % filename self.service.send_raw(chr(CODE_ERROR_LOCAL)) self.mb2_multi_status_add_file_error( errplist, filename, ERROR_ENOENT, "Could not find the droid you were looking for ;)") def mb2_handle_send_files(self, msg): errplist = {} for f in msg[1]: self.mb2_handle_send_file(f, errplist) self.service.send("\x00\x00\x00\x00") if len(errplist): self.mobilebackup2_send_status_response(-13, "Multi status", errplist) else: self.mobilebackup2_send_status_response(0) def mb2_handle_list_directory(self, msg): path = msg[1] dirlist = {} self.mobilebackup2_send_status_response(0, status2=dirlist) def mb2_handle_make_directory(self, msg): dirname = self.check_filename(msg[1]) print "Creating directory %s" % dirname if not os.path.isdir(dirname): os.makedirs(dirname) self.mobilebackup2_send_status_response(0, "") def mb2_handle_receive_files(self, msg): done = 0 while not done: device_filename = self.service.recv_raw() if device_filename == "": break backup_filename = self.service.recv_raw() filedata = "" while True: stuff = self.service.recv_raw() if ord(stuff[0]) == CODE_FILE_DATA: filedata += stuff[1:] elif ord(stuff[0]) == CODE_SUCCESS: self.write_file(self.check_filename(backup_filename), filedata) break else: print "Unknown code", ord(stuff[0]) break self.mobilebackup2_send_status_response(0) def mb2_handle_move_files(self, msg): for k, v in msg[1].items(): print "Renaming %s to %s" % (self.check_filename(k), self.check_filename(v)) os.rename(self.check_filename(k), self.check_filename(v)) self.mobilebackup2_send_status_response(0) def mb2_handle_remove_files(self, msg): for filename in msg[1]: print "Removing ", self.check_filename(filename) try: filename = self.check_filename(filename) if os.path.isfile(filename): os.unlink(filename) except Exception, e: print e self.mobilebackup2_send_status_response(0)
self.service.sendPlist({"Command": "PostNotification",#} "Name": notification}) res = self.service.recvPlist() pprint(res) return res def observe_notification(self, notification): #Tells the device to send a notification on the specified event self.service.sendPlist({"Command": "ObserveNotification",#} "Name": notification}) res = self.service.recvPlist() pprint(res) return res def get_notification(self, notification): #Checks if a notification has been sent by the device res = self.service.recvPlist() pprint(res) return res if __name__ == "__main__": lockdown = LockdownClient() ProductVersion = lockdown.getValue("", "ProductVersion") assert ProductVersion[0] >= "4" np = NPClient() np.get_notification()
def stop_session(self): print "Disconecting..." self.service.close() def request_sources(self, sources=["UserDatabases"]): print "Downloading sources ", sources self.service.sendPlist({"Sources":sources}) res = self.service.recvPlist() if res: if res.has_key("Status"): if res["Status"] == "Acknowledged": z = "" while True: x = self.service.recv() if not x: break z += x return z return None if __name__ == "__main__": lockdown = LockdownClient() ProductVersion = lockdown.getValue("", "ProductVersion") assert ProductVersion[0] >= "4" fc = FileRelayClient() f = fc.request_sources(SRCFILES.split("\n")) #f = fc.request_sources(["SystemConfiguration"]) if f: open("fileRelayTest.gz","wb").write(f)
class MobileBackup(object): def __init__(self, lockdown=None): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() ProductVersion = self.lockdown.getValue("", "ProductVersion") if ProductVersion[0] >= "5": raise DeviceVersionNotSupported self.service = self.lockdown.startService("com.apple.mobilebackup") self.udid = self.lockdown.udid DLMessageVersionExchange = self.service.recvPlist() version_major = DLMessageVersionExchange[1] self.service.sendPlist( ["DLMessageVersionExchange", "DLVersionsOk", version_major]) DLMessageDeviceReady = self.service.recvPlist() if DLMessageDeviceReady and DLMessageDeviceReady[ 0] == "DLMessageDeviceReady": print "Got DLMessageDeviceReady" def check_filename(self, name): if name.find("../") != -1: raise Exception("HAX, sneaky dots in path %s" % name) if not name.startswith(self.backupPath): if name.startswith(self.udid): name = os.path.join(self.backupPath, name) return name name = os.path.join(self.backupPath, self.udid, name) return name return name def read_file(self, filename): filename = self.check_filename(filename) if os.path.isfile(filename): with open(filename, 'rb') as f: data = f.read() f.close() return data return None def write_file(self, filename, data): filename = self.check_filename(filename) with open(filename, 'wb') as f: f.write(data) f.close() def create_info_plist(self): root_node = self.lockdown.allValues #print pprint(root_node) info = { "BuildVersion": root_node.get("BuildVersion") or "", "DeviceName": root_node.get("DeviceName") or "", "Display Name": root_node.get("DeviceName") or "", "GUID": "---", "ProductType": root_node.get("ProductType") or "", "ProductVersion": root_node.get("ProductVersion") or "", "Serial Number": root_node.get("SerialNumber") or "", "Unique Identifier": self.udid.upper(), "Target Identifier": self.udid, "Target Type": "Device", "iTunes Version": "10.0.1" } info["ICCID"] = root_node.get("IntegratedCircuitCardIdentity") or "" info["IMEI"] = root_node.get( "InternationalMobileEquipmentIdentity") or "" info["Last Backup Date"] = datetime.datetime.now() afc = AFCClient(self.lockdown) iTunesFilesDict = {} iTunesFiles = afc.read_directory("/iTunes_Control/iTunes/") for i in iTunesFiles: data = afc.get_file_contents("/iTunes_Control/iTunes/" + i) if data: iTunesFilesDict[i] = plistlib.Data(data) info["iTunesFiles"] = iTunesFilesDict iBooksData2 = afc.get_file_contents("/Books/iBooksData2.plist") if iBooksData2: info["iBooks Data 2"] = plistlib.Data(iBooksData2) info["iTunes Settings"] = self.lockdown.getValue("com.apple.iTunes") print "Creating %s" % os.path.join(self.udid, "Info.plist") self.write_file(os.path.join(self.udid, "Info.plist"), plistlib.writePlistToString(info)) def ping(self, message): self.service.sendPlist(["DLMessagePing", message]) print "ping response", self.service.recvPlist() def device_link_service_send_process_message(self, msg): return self.service.sendPlist(["DLMessageProcessMessage", msg]) def device_link_service_receive_process_message(self): req = self.service.recvPlist() if req: assert req[0] == "DLMessageProcessMessage" return req[1] def send_file_received(self): return self.device_link_service_send_process_message( {"BackupMessageTypeKey": "kBackupMessageBackupFileReceived"}) def request_backup(self): req = { "BackupComputerBasePathKey": "/", "BackupMessageTypeKey": "BackupMessageBackupRequest", "BackupProtocolVersion": "1.6" } self.create_info_plist() self.device_link_service_send_process_message(req) res = self.device_link_service_receive_process_message() if not res: return if res["BackupMessageTypeKey"] != "BackupMessageBackupReplyOK": print res return self.device_link_service_send_process_message(res) filedata = "" f = None outpath = None while True: res = self.service.recvPlist() if not res or res[0] != "DLSendFile": if res[0] == "DLMessageProcessMessage": if res[1].get("BackupMessageTypeKey" ) == "BackupMessageBackupFinished": print "Backup finished OK !" #TODO BackupFilesToDeleteKey plistlib.writePlist( res[1]["BackupManifestKey"], self.check_filename("Manifest.plist")) break data = res[1].data info = res[2] if not f: outpath = self.check_filename(info.get("DLFileDest")) print info["DLFileAttributesKey"]["Filename"], info.get( "DLFileDest") f = open(outpath + ".mddata", "wb") f.write(data) if info.get( "DLFileStatusKey") == DEVICE_LINK_FILE_STATUS_LAST_HUNK: self.send_file_received() f.close() if not info.get("BackupManifestKey", False): plistlib.writePlist(info.get("BackupFileInfo"), outpath + ".mdinfo") f = None
class MobileBackup(object): def __init__(self, lockdown=None): if lockdown: self.lockdown = lockdown else: self.lockdown = LockdownClient() ProductVersion = self.lockdown.getValue("", "ProductVersion") if ProductVersion[0] >= "5": raise DeviceVersionNotSupported self.service = self.lockdown.startService("com.apple.mobilebackup") self.udid = self.lockdown.udid DLMessageVersionExchange = self.service.recvPlist() version_major = DLMessageVersionExchange[1] self.service.sendPlist(["DLMessageVersionExchange", "DLVersionsOk", version_major]) DLMessageDeviceReady = self.service.recvPlist() if DLMessageDeviceReady and DLMessageDeviceReady[0] == "DLMessageDeviceReady": print "Got DLMessageDeviceReady" def check_filename(self, name): if name.find("../") != -1: raise Exception("HAX, sneaky dots in path %s" % name) if not name.startswith(self.backupPath): if name.startswith(self.udid): name = os.path.join(self.backupPath, name) return name name = os.path.join(self.backupPath, self.udid, name) return name return name def read_file(self, filename): filename = self.check_filename(filename) if os.path.isfile(filename): with open(filename, "rb") as f: data = f.read() f.close() return data return None def write_file(self, filename, data): filename = self.check_filename(filename) with open(filename, "wb") as f: f.write(data) f.close() def create_info_plist(self): root_node = self.lockdown.allValues # print pprint(root_node) info = { "BuildVersion": root_node.get("BuildVersion"), "DeviceName": root_node.get("DeviceName"), "Display Name": root_node.get("DeviceName"), "GUID": "---", "ProductType": root_node.get("ProductType"), "ProductVersion": root_node.get("ProductVersion"), # "Serial Number": root_node.get("SerialNumber"), "Unique Identifier": self.udid.upper(), "Target Identifier": self.udid, "Target Type": "Device", "iTunes Version": "10.0.1", } info["ICCID"] = root_node.get("IntegratedCircuitCardIdentity") info["IMEI"] = root_node.get("InternationalMobileEquipmentIdentity") info["Last Backup Date"] = datetime.datetime.now() iTunesFiles = [ "ApertureAlbumPrefs", "IC-Info.sidb", "IC-Info.sidv", "PhotosFolderAlbums", "PhotosFolderName", "PhotosFolderPrefs", "iPhotoAlbumPrefs", "iTunesApplicationIDs", "iTunesPrefs", "iTunesPrefs.plist", ] afc = AFCClient(self.lockdown) iTunesFilesDict = {} iTunesFiles = afc.read_directory("/iTunes_Control/iTunes/") for i in iTunesFiles: data = afc.get_file_contents("/iTunes_Control/iTunes/" + i) if data: iTunesFilesDict[i] = plistlib.Data(data) info["iTunesFiles"] = iTunesFilesDict iBooksData2 = afc.get_file_contents("/Books/iBooksData2.plist") if iBooksData2: info["iBooks Data 2"] = plistlib.Data(iBooksData2) info["iTunes Settings"] = self.lockdown.getValue("com.apple.iTunes") print "Creating %s" % os.path.join(self.udid, "Info.plist") self.write_file(os.path.join(self.udid, "Info.plist"), plistlib.writePlistToString(info)) def ping(self, message): self.service.sendPlist(["DLMessagePing", message]) print "ping response", self.service.recvPlist() def device_link_service_send_process_message(self, msg): return self.service.sendPlist(["DLMessageProcessMessage", msg]) def device_link_service_receive_process_message(self): req = self.service.recvPlist() if req: assert req[0] == "DLMessageProcessMessage" return req[1] def send_file_received(self): return self.device_link_service_send_process_message( {"BackupMessageTypeKey": "kBackupMessageBackupFileReceived"} ) def request_backup(self): req = { "BackupComputerBasePathKey": "/", "BackupMessageTypeKey": "BackupMessageBackupRequest", "BackupProtocolVersion": "1.6", } self.create_info_plist() self.device_link_service_send_process_message(req) res = self.device_link_service_receive_process_message() if not res: return if res["BackupMessageTypeKey"] != "BackupMessageBackupReplyOK": print res return self.device_link_service_send_process_message(res) filedata = "" f = None outpath = None while True: res = self.service.recvPlist() if not res or res[0] != "DLSendFile": if res[0] == "DLMessageProcessMessage": if res[1].get("BackupMessageTypeKey") == "BackupMessageBackupFinished": print "Backup finished OK !" # TODO BackupFilesToDeleteKey plistlib.writePlist(res[1]["BackupManifestKey"], self.check_filename("Manifest.plist")) break data = res[1].data info = res[2] if not f: outpath = self.check_filename(info.get("DLFileDest")) print info["DLFileAttributesKey"]["Filename"], info.get("DLFileDest") f = open(outpath + ".mddata", "wb") f.write(data) if info.get("DLFileStatusKey") == DEVICE_LINK_FILE_STATUS_LAST_HUNK: self.send_file_received() f.close() if not info.get("BackupManifestKey", False): plistlib.writePlist(info.get("BackupFileInfo"), outpath + ".mdinfo") f = None