def test_get_device_info(self):
     udid = self._get_device()
     print('udid:%s' % udid)
     if udid is None:
         print("no real device found")
         return
     lockdown = LockdownClient(udid)
     lockdown.startService("com.apple.afc")
     info = lockdown.allValues
     print(info)
     self.assertIsInstance(info, dict, 'Query device information error')
Exemple #2
0
 def test_get_device_info(self):
     udid = self._get_device()
     print('udid:%s' % udid)
     if udid is None:
         print("no real device found")
         return
     lockdown = LockdownClient(udid)
     lockdown.startService("com.apple.afc")
     info = lockdown.allValues
     print(info)
     self.assertIsInstance(info, dict, 'Query device information error')
Exemple #3
0
def get_device_info(udid=None, keyname=None):
    '''获取iOS设备的相关属性信息
    
    :param udid: iOS设备的udid
    :type udid: str
    :param keyname: iOS设备的特定信息字段的名称
    :type keyname: str
    :returns: str - iOS设备的信息
    '''
    lockdown = LockdownClient(udid)
    lockdown.startService("com.apple.afc")
    if keyname:
        return lockdown.allValues.get(keyname)
    else:
        return lockdown.allValues
Exemple #4
0
class Syslog(object):
    def __init__(self, lockdown=None):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()
        self.c = self.lockdown.startService("com.apple.syslog_relay")
        if self.c:
            self.c.send("watch")
        else:
            sys.exit(1)

    def watch(self, procName=None, logFile=None):

        while True:
            d = self.c.recv(4096)

            if not d:
                break

            if procName:
                procFilter = re.compile(procName, re.IGNORECASE)
                if len(d.split(" ")) > 4 and not procFilter.search(d):
                    continue

            print(d.strip(b"\n\x00\x00"))

            if logFile:
                with open(logFile, 'a') as f:
                    f.write(d.replace("\x00", ""))
Exemple #5
0
class Syslog(object):

    def __init__(self, lockdown=None):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()
        self.c = self.lockdown.startService("com.apple.syslog_relay")
        if self.c:
            self.c.send("watch")
        else:
            sys.exit(1)

    def watch(self, procName=None, logFile=None):

        while True:
            d = self.c.recv(4096)

            if not d:
                break

            if procName:
                procFilter = re.compile(procName, re.IGNORECASE)
                if len(d.split(" ")) > 4 and not procFilter.search(d):
                    continue

            print(d.strip(b"\n\x00\x00"))

            if logFile:
                with open(logFile, 'a') as f:
                    f.write(d.replace("\x00", ""))
    def test_get_crash_log(self):
        mux = USBMux()
        if not mux.devices:
            mux.process(0.1)
        if len(mux.devices) == 0:
            print("no real device found")
            self.no_device = True
            return
        udid = mux.devices[0].serial

        procname = "QQ"
        lockdown = LockdownClient(udid)
        self.service = lockdown.startService("com.apple.crashreportcopymobile")
        client = AFCClient(lockdown,service=self.service)
        afc_shell = AFCShell(client=client)
        remote_crash_path = '/'
        dest_path = '/tmp'
        local_crashes =[]
        print('udid:', udid)
        for _dirname, _dirs, files in afc_shell.afc.dir_walk(remote_crash_path):

            for filename in files:
                if procname in filename:
                    remote_crash_file = os.path.join(remote_crash_path, filename)
                    data = afc_shell.afc.get_file_contents(remote_crash_file)
                    local_crash_file = os.path.join(dest_path, filename)
                    local_crashes.append(local_crash_file)
                    with open(local_crash_file, 'wb') as fp:
                        fp.write(data)
        print(local_crashes)
class screenshotr(object):

    def __init__(self, lockdown=None, serviceName='com.apple.mobile.screenshotr'):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()
        # Starting Screenshot service
        self.service = self.lockdown.startService(serviceName)

        # hand check
        DLMessageVersionExchange = self.service.recvPlist()
        #assert len(DLMessageVersionExchange) == 2
        version_major = DLMessageVersionExchange[1]
        self.service.sendPlist(
            ["DLMessageVersionExchange", "DLVersionsOk", version_major])
        DLMessageDeviceReady = self.service.recvPlist()

    def stop_session(self):
        self.service.close()

    def take_screenshot(self):
        self.service.sendPlist(
            ['DLMessageProcessMessage', {'MessageType': 'ScreenShotRequest'}])
        res = self.service.recvPlist()

        assert len(res) == 2
        assert res[0] == "DLMessageProcessMessage"

        if res[1].get('MessageType') == 'ScreenShotReply':
            data = res[1]['ScreenShotData'].data
            return data
        return None
    def test_get_crash_log(self):
        mux = USBMux()
        if not mux.devices:
            mux.process(0.1)
        if len(mux.devices) == 0:
            print("no real device found")
            self.no_device = True
            return
        udid = mux.devices[0].serial

        procname = "QQ"
        lockdown = LockdownClient(udid)
        self.service = lockdown.startService("com.apple.crashreportcopymobile")
        client = AFCClient(lockdown, service=self.service)
        afc_shell = AFCShell(client=client)
        remote_crash_path = '/'
        dest_path = '/tmp'
        local_crashes = []
        print('udid:', udid)
        for _dirname, _dirs, files in afc_shell.afc.dir_walk(
                remote_crash_path):

            for filename in files:
                if procname in filename:
                    remote_crash_file = os.path.join(remote_crash_path,
                                                     filename)
                    data = afc_shell.afc.get_file_contents(remote_crash_file)
                    local_crash_file = os.path.join(dest_path, filename)
                    local_crashes.append(local_crash_file)
                    with open(local_crash_file, 'wb') as fp:
                        fp.write(data)
        print(local_crashes)
Exemple #9
0
 def start(self):
     lockdown = LockdownClient(self.udid)
     ios_version = lockdown.allValues['ProductVersion']
     if DT.compare_version(ios_version, '11.0') >= 0:  # iOS11真机以上不支持数据分割
         self._partial_supported = False
     self.web_inspector = lockdown.startService("com.apple.webinspector")
     self._sock = self.web_inspector.s
     self._sock.setblocking(False)
     self._sock.settimeout(5)
     self.init_inspector()
Exemple #10
0
 def __init__(self, bundle_id, udid):
     super(RealDeviceProtocol, self).__init__(bundle_id, udid)
     self._partial_supported = True
     lockdown = LockdownClient(self.udid)
     ios_version = lockdown.allValues['ProductVersion']
     if DT.compare_version(ios_version, '11.0') >= 0:  # iOS11真机以上不支持数据分割
         self._partial_supported = False
     self.web_inspector = lockdown.startService("com.apple.webinspector")
     self._sock = self.web_inspector.s
     self._sock.setblocking(False)
     self._sock.settimeout(5)
class PcapClient(object):
    def __init__(self, filename, lockdown=None):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService("com.apple.pcapd")

        self.f = open(filename, "wb")
        self.f.write(
            struct.pack("<LHHLLLL", 0xa1b2c3d4, 2, 4, 0, 0, 65535,
                        LINKTYPE_ETHERNET))

        self._stop = False

    def __del__(self):
        self.stop()

    def writePacket(self, packet):
        t = time.time()
        #TODO check milisecond conversion
        pkthdr = struct.pack("<LLLL", int(t), int(t * 1000000 % 1000000),
                             len(packet), len(packet))
        data = pkthdr + packet
        self.f.write(data)
        self.f.flush()
        return True

    def capturePackets(self):
        while not self._stop:
            d = self.service.recvPlist()
            if not d:
                break
            data = d.data
            hdrsize, xxx, packet_size = struct.unpack(">LBL", data[:9])
            flags1, flags2, offset_to_ip_data, zero = struct.unpack(
                ">LLLL", data[9:0x19])
            assert hdrsize >= 0x19
            interfacetype = data[0x19:hdrsize].strip("\x00")
            t = time.time()
            print interfacetype, packet_size, t
            packet = data[hdrsize:]
            assert packet_size == len(packet)
            if offset_to_ip_data == 0:
                #add fake ethernet header for pdp packets
                packet = "\xBE\xEF" * 6 + "\x08\x00" + packet
            if not self.writePacket(packet):
                break

    def stop(self):
        self._stop = True
        self.f.close()
Exemple #12
0
class PcapClient(object):
    def __init__(self, filename, lockdown=None):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService("com.apple.pcapd")

        self.f = open(filename, "wb")
        self.f.write(struct.pack("<LHHLLLL", 0xa1b2c3d4, 2, 4, 0, 0, 65535, LINKTYPE_ETHERNET))

        self._stop = False

    def __del__(self):
        self.stop()

    def writePacket(self, packet):
        t = time.time()
        #TODO check milisecond conversion
        pkthdr = struct.pack("<LLLL", int(t), int(t*1000000 % 1000000), len(packet), len(packet))
        data = pkthdr + packet
        self.f.write(data)
        self.f.flush()
        return True

    def capturePackets(self):
        while not self._stop:
            d = self.service.recvPlist()
            if not d:
                break
            data = d.data
            hdrsize, xxx, packet_size = struct.unpack(">LBL", data[:9])
            flags1, flags2, offset_to_ip_data, zero = struct.unpack(">LLLL", data[9:0x19])
            assert hdrsize >= 0x19
            interfacetype = data[0x19:hdrsize].strip("\x00")
            t = time.time()
            print interfacetype, packet_size, t
            packet = data[hdrsize:]
            assert packet_size == len(packet)
            if offset_to_ip_data == 0:
                #add fake ethernet header for pdp packets
                packet = "\xBE\xEF" * 6 + "\x08\x00" + packet
            if not self.writePacket(packet):
                break

    def stop(self):
        self._stop = True
        self.f.close()
Exemple #13
0
def house_arrest(lockdown, applicationId):
    try:
        mis = lockdown.startService("com.apple.mobile.house_arrest")
    except:
        lockdown = LockdownClient()
        mis = lockdown.startService("com.apple.mobile.house_arrest")

    if mis == None:
        return
    mis.sendPlist({"Command": "VendDocuments", "Identifier": applicationId})
    res = mis.recvPlist()
    if res.get("Error"):
        print("Unable to Lookup the selected application: You probably trying to access to a system app...")
        return None
    return AFCClient(lockdown, service=mis)
Exemple #14
0
def house_arrest(lockdown, applicationId):
    try:
        mis = lockdown.startService("com.apple.mobile.house_arrest")
    except:
        lockdown = LockdownClient()
        mis = lockdown.startService("com.apple.mobile.house_arrest")

    if mis == None:
        return
    mis.sendPlist({"Command": "VendDocuments", "Identifier": applicationId})
    res = mis.recvPlist()
    if res.get("Error"):
        print "Unable to Lookup the selected application: You probably trying to access to a system app..."
        return None
    return AFCClient(lockdown, service=mis)
Exemple #15
0
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
Exemple #16
0
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
 def setUp(self):
     mux = USBMux()
     if not mux.devices:
         mux.process(0.1)
     if len(mux.devices) == 0:
         print("no real device found")
         self.no_device = True
         return
     udid = mux.devices[0].serial
     lockdown_client = LockdownClient(udid)
     self.service = lockdown_client.startService(
         "com.apple.mobile.house_arrest")
     self.service.sendPlist({
         "Command": "VendContainer",
         "Identifier": "com.gotohack.testapp"
     })
     status = self.service.recvPlist()
     if 'Error' in status and status['Error'] == "ApplicationLookupFailed":
         raise RuntimeWarning('ApplicationLookupFailed')
     if 'Status' in status and status['Status'] != 'Complete':
         raise RuntimeWarning('House arrest service launch failed')
     self.afc = AFCClient(lockdown_client, service=self.service)
     self.afc_shell = AFCShell(client=self.afc)
Exemple #18
0
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 installation_proxy(object):

    def __init__(self,lockdown=None):

        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService("com.apple.mobile.installation_proxy")


    def watch_completion(self,handler=None,*args):
        while True:
            z =  self.service.recvPlist()
            if not z:
                break
            completion = z.get("PercentComplete")
            if completion:
                if handler:
                    print "calling handler"
                    handler(completion,*args)
                print "%s %% Complete" % z.get("PercentComplete")
            if z.get("Status") == "Complete":
                return z.get("Status")
        return "Error"

    def send_cmd_for_bid(self,bundleID, cmd="Archive", options=None, handler=None, *args):
        cmd = {"Command": cmd, "ApplicationIdentifier": bundleID }
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        #print "%s : " % (cmd, bundleID)
        print "%s : %s\n" % (cmd, self.watch_completion(handler, *args))


    def uninstall(self,bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Uninstall", options, handler, args)

    def install_or_upgrade(self, ipaPath, cmd="Install", options=None, handler=None, *args):
        afc = AFCClient(self.lockdown)
        afc.set_file_contents("/" + os.path.basename(ipaPath), open(ipaPath,"rb").read())
        cmd = {"Command":cmd, "PackagePath": os.path.basename(ipaPath)}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
#         print "%s : " % (cmd, bundleID)
        print "%s : %s\n" % (cmd, self.watch_completion(handler, args))


    def install(self,ipaPath, options=None, handler=None, *args):
        return self.install_or_upgrade(ipaPath, "Install", client_options, handler, args)


    def upgrade(self,ipaPath, options=None, handler=None, *args):
        return self.install_or_upgrade(ipaPath, "Upgrade", client_options, handler, args)


    def apps_info(self):
        self.service.sendPlist({"Command": "Lookup"})
        return self.service.recvPlist().get('LookupResult')


    def archive(self,bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Archive", options, handler, args)


    def restore_archive(self,bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Restore", client_options, handler, args)


    def remove_archive(self,bundleID, options={}, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "RemoveArchive", options, handler, args)


    def archives_info(self):
        return self.service.sendRequest({"Command": "LookupArchive"}).get("LookupResult")


    def search_path_for_bid(self, bid):
        path = None
        for a in self.get_apps(appTypes=["User","System"]):
            if a.get("CFBundleIdentifier") == bid:
                path = a.get("Path")+"/"+a.get("CFBundleExecutable")
        return path


    def get_apps(self,appTypes=["User"]):
        return [app for app in self.apps_info().values()
                if app.get("ApplicationType") in appTypes]


    def print_apps(self, appType=["User"]):
        for app in self.get_apps(appType):
            print ("%s : %s => %s" %  (app.get("CFBundleDisplayName"),
                                      app.get("CFBundleIdentifier"),
                                      app.get("Path") if app.get("Path")
                                      else app.get("Container"))).encode('utf-8')


    def get_apps_bid(self,appTypes=["User"]):
        return [app["CFBundleIdentifier"]
                for app in self.get_apps()
                if app.get("ApplicationType") in appTypes]


    def close(self):
        self.service.close()

    def __del__(self):
        self.close()
Exemple #20
0
def get_lockdown_and_service(udid):
    from pymobiledevice.lockdown import LockdownClient
    lockdown = LockdownClient(udid)
    service = lockdown.startService("com.apple.mobile.installation_proxy")
    return lockdown, service
Exemple #21
0
class NPClient(object):

    def __init__(self, lockdown=None, serviceName="com.apple.mobile.notification_proxy"):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()
        self.service = self.lockdown.startService(serviceName)

    def stop_session(self):
        print("Disconecting...")
        self.service.close()

    def post_notification(self, notification):
        # Sends a notification to the device's notification_proxy.

        self.service.sendPlist({"Command": "PostNotification",
                                "Name": notification})

        self.service.sendPlist({"Command": "Shutdown"})
        res = self.service.recvPlist()
        pprint(res)
        if res:
            if res.get("Command") == "ProxyDeath":
                return res.get("Command")
            else:
                print("Got unknown NotificationProxy command %s" %
                      res.get("Command"))
                pprint(res)
        return None

    def observe_notification(self, notification):
        # Tells the device to send a notification on the specified event

        print("Observing %s" % notification)
        self.service.sendPlist({"Command": "ObserveNotification",
                                "Name": notification})

    def get_notification(self, notification):
        # Checks if a notification has been sent by the device

        res = self.service.recvPlist()
        if res:
            if res.get("Command") == "RelayNotification":
                if res.get("Name"):
                    return res.get("Name")

            elif res.get("Command") == "ProxyDeath":
                print("NotificationProxy died!")
            else:
                print("Got unknown NotificationProxy command %s" %
                      res.get("Command"))
                pprint(res)
        return None

    def notifier(self, name, args=None):

        if args == None:
            return None

        self.observe_notification(args.get("notification"))

        while args.get("running") == True:
            np_name = self.get_notification(args.get("notification"))
            if np_name:
                userdata = args.get("userdata")
                try:
                    _thread.start_new_thread(
                        args.get("callback"), (np_name, userdata, ))
                except:
                    print("Error: unable to start thread")

    def subscribe(self, notification, cb, data=None):

        np_data = {
            "running": True,
            "notification": notification,
            "callback": cb,
            "userdata": data,
        }

        try:
            _thread.start_new_thread(
                self.notifier, ("NotificationProxyNotifier_" + notification, np_data, ))
        except:
            print("Error: unable to start thread")

        while(1):
            time.sleep(1)
Exemple #22
0
    (options, args) = parser.parse_args()
    if sys.platform == "win32":
        import win32pipe, win32file
        output = Win32Pipe()

    else:
        if options.output:
            path = options.output
        else:
            _, path = mkstemp(prefix="device_dump_", suffix=".pcap", dir=".")
        print("Recording data to: %s" % path)
        output = PcapOut(path)

    logging.basicConfig(level=logging.INFO)
    lockdown = LockdownClient(options.device_udid)
    pcap = lockdown.startService("com.apple.pcapd")

    while True:
        d = pcap.recvPlist()
        if not d:
            break
        if not PY3:
            d = d.data
        hdrsize, xxx, packet_size = struct.unpack(">LBL", d[:9])
        flags1, flags2, offset_to_ip_data, zero = struct.unpack(
            ">LLLL", d[9:0x19])

        assert hdrsize >= 0x19
        if PY3:
            interfacetype = d[0x19:hdrsize].strip(b"\x00")
        else:
class InstallationProxyTest(unittest.TestCase):

    def setUp(self):
        mux = USBMux()
        if not mux.devices:
            mux.process(0.1)
        if len(mux.devices) == 0:
            print("no real device found")
            self.no_device = True
            return
        self.udid = mux.devices[0].serial
        self.lockdownclient = LockdownClient(self.udid)
        self.service = self.lockdownclient.startService("com.apple.mobile.installation_proxy")

    def wait_completion(self, handler=None, *args):
        while True:
            z = self.service.recvPlist()
            print(type(z), z)
            if not z:
                break
            completion = z.get("PercentComplete")
            if completion:
                if handler:
                    handler(completion, *args)
                print("%s: %s%% Complete" % (z.get("Status"), completion))
            else:
                if z.get("Status") == "Complete" or ("Status" not in z and "CFBundleIdentifier" in z):
                    return (True, "")
                else:
                    return (False, z.get("ErrorDescription"))

    def test_install_app(self):
        if self.no_device:
            return
        ipa_path = os.path.join(os.path.expanduser("~"), "Downloads/app/DemoApp.ipa")
        tmp_ipa = "/t%d.ipa" % time.time()
        with open(ipa_path, "rb") as f:
            ipa_content = f.read()
            afc = AFCClient(self.lockdownclient)
            afc.set_file_contents(tmp_ipa, ipa_content)
            print("Upload completed")
        print("Starting installation")
        cmd = {"Command":"Install", "PackagePath": tmp_ipa}
        self.lockdownclient = LockdownClient(self.udid)
        self.service = self.lockdownclient.startService("com.apple.mobile.installation_proxy")
        self.service.sendPlist(cmd)
        result, err = self.wait_completion()
        self.assertTrue(result, 'install_app failed: %s' % err)

    def test_uninstall_app(self):
        if self.no_device:
            return
        bundle_id = "com.gotohack.test.demo"
        cmd = {"Command": "Uninstall", "ApplicationIdentifier": bundle_id}
        self.service.sendPlist(cmd)
        result, err = self.wait_completion()
        self.assertTrue(result, 'uninstall_app failed: %s' % err)

    def test_apps_info(self):
        if self.no_device:
            return
        self.service.sendPlist({"Command": "Lookup"})
        print(self.service.recvPlist())

    def test_list_apps(self, app_type='user'):
        if self.no_device:
            return
        options = {}
        if app_type == 'system':
            options["ApplicationType"] = "System"
        elif app_type == 'user':
            options["ApplicationType"] = "User"
        options["ReturnAttributes"] = ["CFBundleIdentifier",
                                       "CFBundleName", ]
        self.service.sendPlist({"Command": "Browse", "ClientOptions": options})
        apps = []
        while True:
            z = self.service.recvPlist()
            if z.get("Status") == "BrowsingApplications":
                apps.extend(z["CurrentList"])
            elif z.get("Status") == "Complete":
                break
            else:
                raise Exception(z.get("ErrorDescription"))
        print(apps)

    def tearDown(self):
        if not self.no_device and self.service:
            self.service.close()
Exemple #24
0
class AFCClient(object):
    def __init__(self,
                 lockdown=None,
                 serviceName="com.apple.afc",
                 service=None,
                 udid=None,
                 logger=None):
        self.logger = logger or logging.getLogger(__name__)
        self.serviceName = serviceName
        self.lockdown = lockdown if lockdown else LockdownClient(udid=udid)
        self.service = service if service else self.lockdown.startService(
            self.serviceName)
        self.packet_num = 0

    def stop_session(self):
        self.logger.info("Disconecting...")
        self.service.close()

    def dispatch_packet(self, operation, data, this_length=0):
        afcpack = Container(magic=AFCMAGIC,
                            entire_length=40 + len(data),
                            this_length=40 + len(data),
                            packet_num=self.packet_num,
                            operation=operation)
        if this_length:
            afcpack.this_length = this_length
        header = AFCPacket.build(afcpack)
        self.packet_num += 1
        self.service.send(header + data)

    def receive_data(self):
        res = self.service.recv(40)
        status = AFC_E_SUCCESS
        data = ""
        if res:
            res = AFCPacket.parse(res)
            assert res["entire_length"] >= 40
            length = res["entire_length"] - 40
            data = self.service.recv_exact(length)
            if res.operation == AFC_OP_STATUS:
                if length != 8:
                    self.logger.error("Status length != 8")
                status = struct.unpack("<Q", data[:8])[0]
            elif res.operation != AFC_OP_DATA:
                pass  #print "error ?", res
        return status, data

    def do_operation(self, opcode, data=""):
        try:
            self.dispatch_packet(opcode, data)
            return self.receive_data()
        except:
            self.lockdown = LockdownClient()
            self.service = self.lockdown.startService(self.serviceName)
            return self.do_operation(opcode, data)

    def list_to_dict(self, d):
        t = d.split("\x00")
        t = t[:-1]

        assert len(t) % 2 == 0
        res = {}
        for i in xrange(len(t) / 2):
            res[t[i * 2]] = t[i * 2 + 1]
        return res

    def get_device_infos(self):
        status, infos = self.do_operation(AFC_OP_GET_DEVINFO)
        if status == AFC_E_SUCCESS:
            return self.list_to_dict(infos)

    def read_directory(self, dirname):
        status, data = self.do_operation(AFC_OP_READ_DIR, dirname)
        if status == AFC_E_SUCCESS:
            return filter(lambda x: x != "", data.split("\x00"))
        return []

    def make_directory(self, dirname):
        status, data = self.do_operation(AFC_OP_MAKE_DIR, dirname)
        return status

    def remove_directory(self, dirname):
        info = self.get_file_info(dirname)
        if not info or info.get("st_ifmt") != "S_IFDIR":
            self.logger.info("remove_directory: %s not S_IFDIR", dirname)
            return

        for d in self.read_directory(dirname):
            if d == "." or d == ".." or d == "":
                continue

            info = self.get_file_info(dirname + "/" + d)
            if info.get("st_ifmt") == "S_IFDIR":
                self.remove_directory(dirname + "/" + d)
            else:
                self.logger.info("%s/%s", dirname, d)
                self.file_remove(dirname + "/" + d)
        assert len(self.read_directory(dirname)) == 2  #.. et .
        return self.file_remove(dirname)

    def get_file_info(self, filename):
        status, data = self.do_operation(AFC_OP_GET_FILE_INFO, filename)
        if status == AFC_E_SUCCESS:
            return self.list_to_dict(data)

    def make_link(self, target, linkname, type=AFC_SYMLINK):
        status, data = self.do_operation(
            AFC_OP_MAKE_LINK,
            struct.pack("<Q", type) + target + "\x00" + linkname + "\x00")
        self.logger.info("make_link: %s", status)
        return status

    def file_open(self, filename, mode=AFC_FOPEN_RDONLY):
        status, data = self.do_operation(
            AFC_OP_FILE_OPEN,
            struct.pack("<Q", mode) + filename + "\x00")
        return struct.unpack("<Q", data)[0] if data else None

    def file_close(self, handle):
        status, data = self.do_operation(AFC_OP_FILE_CLOSE,
                                         struct.pack("<Q", handle))
        return status

    def file_remove(self, filename):
        status, data = self.do_operation(AFC_OP_REMOVE_PATH, filename + "\x00")
        return status

    def file_rename(self, old, new):
        status, data = self.do_operation(AFC_OP_RENAME_PATH,
                                         old + "\x00" + new + "\x00")
        return status

    def file_read(self, handle, sz):
        MAXIMUM_READ_SIZE = 1 << 16
        data = ""
        while sz > 0:
            if sz > MAXIMUM_READ_SIZE:
                toRead = MAXIMUM_READ_SIZE
            else:
                toRead = sz
            try:
                self.dispatch_packet(AFC_OP_READ,
                                     struct.pack("<QQ", handle, toRead))
                s, d = self.receive_data()
            except:
                self.lockdown = LockdownClient()
                self.service = self.lockdown.startService("com.apple.afc")
                return self.file_read(handle, sz)

            if s != AFC_E_SUCCESS:
                break
            sz -= toRead
            data += d
        return data

    def file_write(self, handle, data):
        MAXIMUM_WRITE_SIZE = 1 << 15
        hh = struct.pack("<Q", handle)
        segments = len(data) / MAXIMUM_WRITE_SIZE
        try:
            for i in xrange(segments):
                self.dispatch_packet(
                    AFC_OP_WRITE,
                    hh +
                    data[i * MAXIMUM_WRITE_SIZE:(i + 1) * MAXIMUM_WRITE_SIZE],
                    this_length=48)
                s, d = self.receive_data()
                if s != AFC_E_SUCCESS:
                    self.logger.error("file_write error: %d", s)
                    break
            if len(data) % MAXIMUM_WRITE_SIZE:
                self.dispatch_packet(AFC_OP_WRITE,
                                     hh + data[segments * MAXIMUM_WRITE_SIZE:],
                                     this_length=48)
                s, d = self.receive_data()
        except:
            self.lockdown = LockdownClient()
            self.service = self.lockdown.startService(self.serviceName)
            self.file_write(handle, data)
        return s

    def get_file_contents(self, filename):
        info = self.get_file_info(filename)
        if info:
            if info['st_ifmt'] == 'S_IFLNK':
                filename = info['LinkTarget']

            if info['st_ifmt'] == 'S_IFDIR':
                self.logger.info("%s is directory...", filename)
                return

            self.logger.info("Reading: %s", filename)
            h = self.file_open(filename)
            if not h:
                return
            d = self.file_read(h, int(info["st_size"]))
            self.file_close(h)
            return d
        return

    def set_file_contents(self, filename, data):
        h = self.file_open(filename, AFC_FOPEN_WR)
        if not h:
            return
        d = self.file_write(h, data)
        self.file_close(h)

    def dir_walk(self, dirname):
        dirs = []
        files = []
        for fd in self.read_directory(dirname):
            if fd in ('.', '..', ''):
                continue
            infos = self.get_file_info(posixpath.join(dirname, fd))
            if infos and infos.get('st_ifmt') == 'S_IFDIR':
                dirs.append(fd)
            else:
                files.append(fd)

        yield dirname, dirs, files

        if dirs:
            for d in dirs:
                for walk_result in self.dir_walk(posixpath.join(dirname, d)):
                    yield walk_result
Exemple #25
0
class installation_proxy(object):
    def __init__(self, lockdown=None):

        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService(
            "com.apple.mobile.installation_proxy")

    def watch_completion(self, handler=None, *args):
        while True:
            z = self.service.recvPlist()
            if not z:
                break
            completion = z.get("PercentComplete")
            if completion:
                if handler:
                    print "calling handler"
                    handler(completion, *args)
                print "%s %% Complete" % z.get("PercentComplete")
            if z.get("Status") == "Complete":
                return z.get("Status")
        return "Error"

    def send_cmd_for_bid(self,
                         bundleID,
                         cmd="Archive",
                         options=None,
                         handler=None,
                         *args):
        cmd = {"Command": cmd, "ApplicationIdentifier": bundleID}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        #print "%s : " % (cmd, bundleID)
        print "%s : %s\n" % (cmd, self.watch_completion(handler, *args))

    def uninstall(self, bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Uninstall", options, handler, args)

    def install_or_upgrade(self,
                           ipaPath,
                           cmd="Install",
                           options=None,
                           handler=None,
                           *args):
        afc = AFCClient(self.lockdown)
        afc.set_file_contents("/" + os.path.basename(ipaPath),
                              open(ipaPath, "rb").read())
        cmd = {"Command": cmd, "PackagePath": os.path.basename(ipaPath)}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        #         print "%s : " % (cmd, bundleID)
        print "%s : %s\n" % (cmd, self.watch_completion(handler, args))

    def install(self, ipaPath, options=None, handler=None, *args):
        return self.install_or_upgrade(ipaPath, "Install", client_options,
                                       handler, args)

    def upgrade(self, ipaPath, options=None, handler=None, *args):
        return self.install_or_upgrade(ipaPath, "Upgrade", client_options,
                                       handler, args)

    def apps_info(self):
        self.service.sendPlist({"Command": "Lookup"})
        return self.service.recvPlist().get('LookupResult')

    def archive(self, bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Archive", options, handler, args)

    def restore_archive(self, bundleID, options=None, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "Restore", client_options, handler,
                              args)

    def remove_archive(self, bundleID, options={}, handler=None, *args):
        self.send_cmd_for_bid(bundleID, "RemoveArchive", options, handler,
                              args)

    def archives_info(self):
        return self.service.sendRequest({
            "Command": "LookupArchive"
        }).get("LookupResult")

    def search_path_for_bid(self, bid):
        path = None
        for a in self.get_apps(appTypes=["User", "System"]):
            if a.get("CFBundleIdentifier") == bid:
                path = a.get("Path") + "/" + a.get("CFBundleExecutable")
        return path

    def get_apps(self, appTypes=["User"]):
        return [
            app for app in self.apps_info().values()
            if app.get("ApplicationType") in appTypes
        ]

    def print_apps(self, appType=["User"]):
        for app in self.get_apps(appType):
            print("%s : %s => %s" %
                  (app.get("CFBundleDisplayName"),
                   app.get("CFBundleIdentifier"), app.get("Path") if
                   app.get("Path") else app.get("Container"))).encode('utf-8')

    def get_apps_bid(self, appTypes=["User"]):
        return [
            app["CFBundleIdentifier"] for app in self.get_apps()
            if app.get("ApplicationType") in appTypes
        ]

    def close(self):
        self.service.close()

    def __del__(self):
        self.close()
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.dumps(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
Exemple #27
0
class InstallationProxy(object):
    def __init__(self, udid=None):
        self.udid = udid
        self.lockdown = LockdownClient(udid)
        self.service = self.lockdown.startService(
            "com.apple.mobile.installation_proxy")

    def wait_completion(self, handler=None, *args):
        while True:
            z = self.service.recvPlist()
            if not z:
                break
            completion = z.get("PercentComplete")
            if completion:
                if handler:
                    print "calling handler"
                    handler(completion, *args)


#                 print "%s: %s%% Complete" % (z.get("Status"), completion)
            else:
                if z.get("Status") == "Complete":
                    print "安装成功"
                    return (True, "")
                else:
                    return (False, z.get("ErrorDescription"))

    def send_cmd_for_bid(self,
                         bundle_id,
                         cmd="Archive",
                         options=None,
                         handler=None,
                         *args):
        cmd = {"Command": cmd, "ApplicationIdentifier": bundle_id}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        return self.wait_completion(handler, *args)

    def install(self, ipa_path, options=None, handler=None, *args):
        '''安装应用程序
        
        :param ipa_path: 安装包的路径
        :type ipa_path: str
        :return: boolean - 安装是否成功
        '''
        print "上传安装包..."
        afc_client = AFCClient()
        tmp_ipa = "t%d.ipa" % time.time()
        with open(ipa_path, "rb") as f:
            ipa_content = f.read()
            afc_client.set_file_contents("/" + tmp_ipa, ipa_content)
            print "上传完毕"
        print "开始安装"
        cmd = {"Command": "Install", "PackagePath": tmp_ipa}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        return self.wait_completion(handler, args)

    def uninstall(self, bundle_id, options=None, handler=None, *args):
        '''卸载应用程序
    
        :param bundle_id: 应用程序的bundle id
        :type bundle_id: str
        :return: boolean - 卸载是否成功
        '''
        return self.send_cmd_for_bid(bundle_id, "Uninstall", options, handler,
                                     args)

    def apps_info(self):
        self.service.sendPlist({"Command": "Lookup"})
        return self.service.recvPlist()

    def __del__(self):
        self.close()
Exemple #28
0
    (options, args) = parser.parse_args()
    if sys.platform == "win32":
        import win32pipe
        import win32file
        output = Win32Pipe()

    else:
        if options.output:
            path = options.output
        else:
            _, path = mkstemp(prefix="device_dump_", suffix=".pcap", dir=".")
        print("Recording data to: %s" % path)
        output = PcapOut(path)

    lockdown = LockdownClient()
    pcap = lockdown.startService("com.apple.pcapd")

    while True:
        d = pcap.recvPlist()
        if not d:
            break
        data = d.data
        hdrsize, xxx, packet_size = struct.unpack(">LBL", data[:9])
        flags1, flags2, offset_to_ip_data, zero = struct.unpack(">LLLL", data[
                                                                9:0x19])

        assert hdrsize >= 0x19
        interfacetype = data[0x19:hdrsize].strip("\x00")
        t = time.time()
        print(interfacetype, packet_size, t)
Exemple #29
0
class DIAGClient(object):
    def __init__(self, lockdown=None, serviceName="com.apple.mobile.diagnostics_relay"):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService(serviceName)
        self.packet_num = 0

    def stop_session(self):
        print("Disconecting...")
        self.service.close()

    def query_mobilegestalt(self, MobileGestalt=MobileGestaltKeys.split("\n")):
        self.service.sendPlist({"Request": "MobileGestalt",
                                "MobileGestaltKeys": MobileGestalt})

        res = self.service.recvPlist()
        d = res.get("Diagnostics")
        if d:
            return d.get("MobileGestalt")
        return None

    def action(self, action="Shutdown", flags=None):
        self.service.sendPlist({"Request": action})
        res = self.service.recvPlist()
        return res.get("Diagnostics")

    def restart(self):
        return self.action("Restart")

    def shutdown(self):
        return self.action("Shutdown")

    def diagnostics(self, diagType="All"):
        self.service.sendPlist({"Request": diagType})
        res = self.service.recvPlist()
        if res:
            return res.get("Diagnostics")
        return None

    def ioregistry_entry(self, name=None, ioclass=None):
        d = {}
        if name:
            d["EntryName"] = name

        if ioclass:
            d["EntryClass"] = ioclass

        d["Request"] = "IORegistry"

        self.service.sendPlist(d)
        res = self.service.recvPlist()
        pprint(res)
        if res:
            return res.get("Diagnostics")
        return None

    def ioregistry_plane(self, plane=""):
        d = {}
        if plane:
            d["CurrentPlane"] = plane

        else:
            d["CurrentPlane"] = ""
        d["Request"] = "IORegistry"

        self.service.sendPlist(d)
        res = self.service.recvPlist()
        dd = res.get("Diagnostics")
        if dd:
            return dd.get("IORegistry")
        return None
Exemple #30
0
class AFCClient(object):
    def __init__(self, lockdown=None, serviceName="com.apple.afc", service=None):
        self.serviceName = serviceName
        self.lockdown = lockdown if lockdown else LockdownClient()
        self.service = service if service else self.lockdown.startService(self.serviceName)
        self.packet_num = 0


    def stop_session(self):
        print "Disconecting..."
        self.service.close()


    def dispatch_packet(self, operation, data, this_length=0):
        afcpack = Container(magic=AFCMAGIC,
                   entire_length=40 + len(data),
                   this_length=40 + len(data),
                   packet_num=self.packet_num,
                   operation=operation)
        if this_length:
            afcpack.this_length = this_length
        header = AFCPacket.build(afcpack)
        self.packet_num += 1
        self.service.send(header + data)


    def receive_data(self):
        res = self.service.recv(40)
        status = AFC_E_SUCCESS
        data = ""
        if res:
            res = AFCPacket.parse(res)
            assert res["entire_length"] >= 40
            length = res["entire_length"] - 40
            data = self.service.recv_exact(length)
            if res.operation == AFC_OP_STATUS:
                if length != 8:
                    print "Status length != 8"
                status = struct.unpack("<Q", data[:8])[0]
            elif res.operation != AFC_OP_DATA:
                pass#print "error ?", res
        return status, data


    def do_operation(self, opcode, data=""):
        try:
            self.dispatch_packet(opcode, data)
            return self.receive_data()
        except:
            self.lockdown = LockdownClient()
            self.service = self.lockdown.startService(self.serviceName)
            return  self.do_operation(opcode, data)


    def list_to_dict(self, d):
        t = d.split("\x00")
        t = t[:-1]

        assert len(t) % 2 == 0
        res = {}
        for i in xrange(len(t)/2):
            res[t[i*2]] = t[i*2 + 1]
        return res


    def get_device_infos(self):
        status, infos = self.do_operation(AFC_OP_GET_DEVINFO)
        if status == AFC_E_SUCCESS:
            return self.list_to_dict(infos)


    def read_directory(self, dirname):
        status, data = self.do_operation(AFC_OP_READ_DIR, dirname)
        if status == AFC_E_SUCCESS:
            return filter(lambda x:x!="", data.split("\x00"))
        return []


    def make_directory(self, dirname):
        status, data = self.do_operation(AFC_OP_MAKE_DIR, dirname)
        return status


    def remove_directory(self, dirname):
        info = self.get_file_info(dirname)
        if not info or info.get("st_ifmt") != "S_IFDIR":
            print "remove_directory: %s not S_IFDIR" % dirname
            return

        for d in self.read_directory(dirname):
            if d == "." or d == ".." or d == "":
                continue

            info = self.get_file_info(dirname + "/" + d)
            if info.get("st_ifmt") == "S_IFDIR":
                self.remove_directory(dirname + "/" + d)
            else:
                print dirname + "/" + d
                self.file_remove(dirname + "/" + d)
        assert len(self.read_directory(dirname)) == 2 #.. et .
        return self.file_remove(dirname)


    def get_file_info(self, filename):
        status, data = self.do_operation(AFC_OP_GET_FILE_INFO, filename)
        if status == AFC_E_SUCCESS:
            return self.list_to_dict(data)


    def make_link(self, target, linkname, type=AFC_SYMLINK):
        status, data = self.do_operation(AFC_OP_MAKE_LINK, struct.pack("<Q", type) + target + "\x00" + linkname + "\x00")
        print "make_link", status
        return status


    def file_open(self, filename, mode=AFC_FOPEN_RDONLY):
        status, data = self.do_operation(AFC_OP_FILE_OPEN, struct.pack("<Q", mode) + filename + "\x00")
        return struct.unpack("<Q", data)[0] if data else None


    def file_close(self, handle):
        status, data = self.do_operation(AFC_OP_FILE_CLOSE, struct.pack("<Q", handle))
        return status


    def file_remove(self, filename):
        status, data = self.do_operation(AFC_OP_REMOVE_PATH, filename + "\x00")
        return status


    def file_rename(self, old, new):
        status, data = self.do_operation(AFC_OP_RENAME_PATH, old + "\x00" + new + "\x00")
        return status


    def file_read(self, handle, sz):
        MAXIMUM_READ_SIZE = 1 << 16
        data = ""
        while sz > 0:
            if sz > MAXIMUM_READ_SIZE:
                toRead = MAXIMUM_READ_SIZE
            else:
                toRead = sz
            try:
                self.dispatch_packet(AFC_OP_READ, struct.pack("<QQ", handle, toRead))
                s, d = self.receive_data()
            except:
                self.lockdown = LockdownClient()
                self.service = self.lockdown.startService("com.apple.afc")
                return  self.file_read(handle, sz)

            if s != AFC_E_SUCCESS:
                break
            sz -= toRead
            data += d
        return data


    def file_write(self, handle, data):
        MAXIMUM_WRITE_SIZE = 1 << 15
        hh = struct.pack("<Q", handle)
        segments = len(data) / MAXIMUM_WRITE_SIZE
        try:
            for i in xrange(segments):
                self.dispatch_packet(AFC_OP_WRITE,
                                 hh + data[i*MAXIMUM_WRITE_SIZE:(i+1)*MAXIMUM_WRITE_SIZE],
                                     this_length=48)
                s, d = self.receive_data()
                if s != AFC_E_SUCCESS:
                    print "file_write error %d" % s
                    break
            if len(data) % MAXIMUM_WRITE_SIZE:
                self.dispatch_packet(AFC_OP_WRITE,
                                     hh + data[segments*MAXIMUM_WRITE_SIZE:],
                                     this_length=48)
                s, d = self.receive_data()
        except:
            self.lockdown = LockdownClient()
            self.service = self.lockdown.startService(self.serviceName)
            self.file_write(handle,data)
        return s


    def get_file_contents(self, filename):
        info = self.get_file_info(filename)
        if info:
            if info['st_ifmt'] == 'S_IFLNK':
                filename =  info['LinkTarget']

            if info['st_ifmt'] == 'S_IFDIR':
                print "%s is directory..." % filename
                return

            print "Reading %s" % filename
            h = self.file_open(filename)
            if not h:
                return
            d = self.file_read(h, int(info["st_size"]))
            self.file_close(h)
            return d
        return


    def set_file_contents(self, filename, data):
        h = self.file_open(filename, AFC_FOPEN_WR)
        if not h:
            return
        d = self.file_write(h, data)
        self.file_close(h)


    def dir_walk(self, dirname):
        dirs = []
        files = []
        for fd in self.read_directory(dirname):
            if fd in ('.', '..', ''):
                continue
            infos = self.get_file_info(posixpath.join(dirname, fd))
            if infos and infos.get('st_ifmt') == 'S_IFDIR':
                dirs.append(fd)
            else:
                files.append(fd)

        yield dirname, dirs, files

        if dirs:
            for d in dirs:
                for walk_result in self.dir_walk(posixpath.join(dirname, d)):
                    yield walk_result
class DIAGClient(object):
    def __init__(self, lockdown=None, serviceName="com.apple.mobile.diagnostics_relay"):
        if lockdown:
            self.lockdown = lockdown
        else:
            self.lockdown = LockdownClient()

        self.service = self.lockdown.startService(serviceName)
        self.packet_num = 0


    def stop_session(self):
        print "Disconecting..."
        self.service.close()


    def query_mobilegestalt(self, MobileGestalt=MobileGestaltKeys.split("\n")):
        self.service.sendPlist({"Request": "MobileGestalt",
                                "MobileGestaltKeys": MobileGestalt})

        res = self.service.recvPlist()
        d = res.get("Diagnostics")
        if d:
            return d.get("MobileGestalt")
        return None


    def action(self, action="Shutdown", flags=None):
        self.service.sendPlist({"Request": action })
        res = self.service.recvPlist()
        return res.get("Diagnostics")


    def restart(self):
        return self.action("Restart")


    def shutdown(self):
        return self.action("Shutdown")


    def diagnostics(self, diagType="All"):
        self.service.sendPlist({"Request": diagType})
        res = self.service.recvPlist()
        if res:
            return res.get("Diagnostics")
        return None


    def ioregistry_entry(self, name=None, ioclass=None):
        d = {}
        if name:
            d["EntryName"] = name

        if ioclass:
            d["EntryClass"] = ioclass

        d["Request"] = "IORegistry"

        self.service.sendPlist(d)
        res = self.service.recvPlist()
        pprint(res)
        if res:
            return res.get("Diagnostics")
        return None


    def ioregistry_plane(self, plane=""):
        d = {}
        if plane:
            d["CurrentPlane"] = plane

        else:
            d["CurrentPlane"] = ""
        d["Request"] = "IORegistry"

        self.service.sendPlist(d)
        res = self.service.recvPlist()
        dd = res.get("Diagnostics")
        if dd:
            return dd.get("IORegistry")
        return None
Exemple #32
0
class InstallationProxy(object):
    def __init__(self, udid=None):
        self.udid = udid
        self.lockdown = LockdownClient(udid)
        self.service = self.lockdown.startService(
            "com.apple.mobile.installation_proxy")

    def wait_completion(self, handler=None, *args):
        while True:
            z = self.service.recvPlist()
            if not z:
                break
            completion = z.get("PercentComplete")
            if completion:
                if handler:
                    print "calling handler"
                    handler(completion, *args)


#                 print "%s: %s%% Complete" % (z.get("Status"), completion)
            else:
                if z.get("Status") == "Complete" or (
                        "Status" not in z and "CFBundleIdentifier" in z):
                    return (True, "")
                else:
                    return (False, z.get("ErrorDescription"))

    def send_cmd_for_bid(self,
                         bundle_id,
                         cmd="Archive",
                         options=None,
                         handler=None,
                         *args):
        cmd = {"Command": cmd, "ApplicationIdentifier": bundle_id}
        if options:
            cmd.update(options)
        self.service.sendPlist(cmd)
        return self.wait_completion(handler, *args)

    def install(self, ipa_path, options=None, handler=None, *args):
        '''安装应用程序
        
        :param ipa_path: 安装包的路径
        :type ipa_path: str
        :return: boolean - 安装是否成功
        '''
        print "上传安装包..."
        afc_client = AFCClient(self.lockdown)
        tmp_ipa = "t%d.ipa" % time.time()
        with open(ipa_path, "rb") as f:
            ipa_content = f.read()
            afc_client.set_file_contents("/" + tmp_ipa, ipa_content)
            print "上传完毕"
        print "开始安装"
        cmd = {"Command": "Install", "PackagePath": tmp_ipa}
        if options:
            cmd.update(options)
        self.lockdown = LockdownClient(self.udid)
        self.service = self.lockdown.startService(
            "com.apple.mobile.installation_proxy")
        self.service.sendPlist(cmd)
        ret = self.wait_completion(handler, args)
        if ret[0]:
            print "安装成功"
        else:
            print "安装失败:%s" % ret[1]
        return ret

    def uninstall(self, bundle_id, options=None, handler=None, *args):
        '''卸载应用程序
    
        :param bundle_id: 应用程序的bundle id
        :type bundle_id: str
        :return: boolean - 卸载是否成功
        '''
        ret = self.send_cmd_for_bid(bundle_id, "Uninstall", options, handler,
                                    args)
        if ret[0]:
            print "卸载成功"
        else:
            print "卸载失败:%s" % ret[1]
        return ret

    def apps_info(self):
        self.service.sendPlist({"Command": "Lookup"})
        return self.service.recvPlist()

    def list_apps(self, app_type='all'):
        options = {}
        if app_type == 'system':
            options["ApplicationType"] = "System"
        elif app_type == 'user':
            options["ApplicationType"] = "User"
        options["ReturnAttributes"] = [
            "CFBundleIdentifier",
            #                                        "CFBundleDisplayName",
            #                                        "CFBundleVersion",
            "CFBundleName",
        ]
        self.service.sendPlist({"Command": "Browse", "ClientOptions": options})
        apps = []
        while True:
            z = self.service.recvPlist()
            if z.get("Status") == "BrowsingApplications":
                apps.extend(z["CurrentList"])
            elif z.get("Status") == "Complete":
                break
            else:
                raise Exception(z.get("ErrorDescription"))
        apps = [{
            app["CFBundleIdentifier"]: app["CFBundleName"]
        } for app in apps]
        return apps

    def __del__(self):
        if hasattr(self, "service"):
            self.service.close()