예제 #1
0
    def load_kext(self):
        self.heap.clear()

        # Setup mac_policy_list
        kern_mac_policy_list = self.ql.loader.kernel_extrn_symbols_detail[
            b"_mac_policy_list"]["n_value"]
        mac_policy_list_addr = self.heap.alloc(sizeof(mac_policy_list_t))
        self.mac_policy_list = mac_policy_list_t(self, mac_policy_list_addr)
        self.ql.mem.write(kern_mac_policy_list,
                          self.ql.pack64(mac_policy_list_addr))

        # Add initial process to allproc in kernel
        allproc = self.ql.loader.kernel_extrn_symbols_detail[b"_allproc"][
            "n_value"]
        self.ev_manager.set_allproc(allproc)
        self.ev_manager.add_process(0, "head")
        self.ev_manager.add_process(0x1337, "demigod")
        self.ev_manager.add_process(1, "tail")

        if self.ql.loader.IOKit is True:  # Handle IOKit driver
            self.ql.stack_push(0)
            self.savedrip = 0xffffff8000a163bd
            self.ql.run(begin=self.ql.loader.kext_alloc)
            self.kext_object = self.ql.arch.regs.rax
            self.ql.log.debug("Created kext object at 0x%x" % self.kext_object)

            self.ql.arch.regs.rdi = self.kext_object
            self.ql.arch.regs.rsi = 0  # NULL option
            self.savedrip = 0xffffff8000a16020
            self.ql.run(begin=self.ql.loader.kext_init)
            if self.ql.arch.regs.rax == 0:
                self.ql.log.debug("Failed to initialize kext object")
                return
            self.ql.log.debug("Initialized kext object")

            self.ql.arch.regs.rdi = self.kext_object
            # FIXME Determine provider for kext
            self.ql.arch.regs.rsi = 0  # ?
            self.savedrip = 0xffffff8000a16102
            self.ql.run(begin=self.ql.loader.kext_attach)
            if self.ql.arch.regs.rax == 0:
                self.ql.log.debug("Failed to attach kext object")
                return
            self.ql.log.debug("Attached kext object 1st time")

            self.ql.arch.regs.rdi = self.kext_object
            self.ql.arch.regs.rdi = 0
            # FIXME Determine provider for kext
            self.ql.arch.regs.rsi = 0  # ?
            tmp = self.heap.alloc(8)
            self.ql.arch.regs.rdx = tmp
            self.savedrip = 0xffffff8000a16184
            self.ql.run(begin=self.ql.loader.kext_probe)
            self.heap.free(tmp)
            self.ql.log.debug("Probed kext object")

            self.ql.arch.regs.rdi = self.kext_object
            # FIXME Determine provider for kext
            self.ql.arch.regs.rsi = 0  # ?
            self.savedrip = 0xffffff8000a16198
            self.ql.run(begin=self.ql.loader.kext_detach)
            self.ql.log.debug("Detached kext object")

            self.ql.arch.regs.rdi = self.kext_object
            # FIXME Determine provider for kext
            self.ql.arch.regs.rsi = 0  # ?
            self.savedrip = 0xffffff8000a168a3
            self.ql.run(begin=self.ql.loader.kext_attach)
            if self.ql.arch.regs.rax == 0:
                self.ql.log.debug("Failed to attach kext object")
                return
            self.ql.log.debug("Attached kext object 2nd time")

            self.ql.arch.regs.rdi = self.kext_object
            # FIXME Determine provider for kext
            self.ql.arch.regs.rsi = 0  # ?
            self.savedrip = 0xffffff8000a168ed
            self.ql.run(begin=self.ql.loader.kext_start)
        else:
            kmod_info_addr = self.heap.alloc(sizeof(kmod_info_t))
            self.ql.log.debug("Created fake kmod_info at 0x%x" %
                              kmod_info_addr)
            kmod_info = kmod_info_t(self.ql, kmod_info_addr)

            # OSKext.cpp:562
            kmod_info.next = POINTER64(0)
            kmod_info.info_version = 1
            kmod_info.id = 1
            kmod_info.name = self.ql.loader.plist["CFBundleIdentifier"].encode(
            )
            kmod_info.version = self.ql.loader.plist["CFBundleVersion"].encode(
            )
            kmod_info.reference_count = 0
            kmod_info.reference_list = POINTER64(0)
            kmod_info.address = POINTER64(self.ql.loader.slide)
            kmod_info.size = self.ql.loader.kext_size
            kmod_info.hdr_size = self.ql.loader.macho_file.header.header_size
            kmod_info.start = POINTER64(self.ql.loader.kext_start)
            kmod_info.stop = POINTER64(self.ql.loader.kext_stop)

            kmod_info.updateToMem()
            self.ql.log.debug("Initialized kmod_info")

            self.ql.arch.regs.rdi = kmod_info_addr
            self.ql.arch.regs.rsi = 0
            self.savedrip = 0xffffff80009c2c16
            self.ql.run(begin=self.ql.loader.kext_start)
예제 #2
0
파일: utils.py 프로젝트: yzz127/qiling
def IOConnectCallMethod(ql, selector, 
                        input_array, input_cnt, input_struct, input_struct_size,
                        output_array, output_cnt, output_struct, output_struct_size):

    if ql.os.IOKit is not True:
        ql.nprint("[!] Must have a IOKit driver")
        return output_array, output_struct

    args_addr = ql.os.heap.alloc(ctypes.sizeof(IOExternalMethodArguments))
    ql.dprint(D_INFO, "[+] Created IOExternalMethodArguments object at 0x%x" % args_addr)
    args_obj = IOExternalMethodArguments(ql, args_addr)

    if input_array is not None and input_cnt != 0:
        input_array_addr = ql.os.heap.alloc(input_cnt)
        ql.mem.write(input_array_addr, b''.join(struct.pack("<Q", x) for x in input_array))
        ql.dprint(D_INFO, "[+] Created input array at 0x%x" % input_array_addr)
    else:
        input_array_addr = 0

    if input_struct is not None and input_struct_size != 0:
        input_struct_addr = ql.os.heap.alloc(input_struct_size)
        ql.mem.write(input_struct_addr, bytes(input_struct))
        ql.dprint(D_INFO, "[+] Created input struct at 0x%x" % input_struct_addr)
    else:
        input_struct_addr = 0

    if output_array is not None and output_cnt != 0:
        output_array_addr = ql.os.heap.alloc(output_cnt)
        ql.mem.write(output_array_addr, b''.join(struct.pack("<Q", x) for x in output_array))
        ql.dprint(D_INFO, "[+] Created output array at 0x%x" % output_array_addr)
    else:
        output_array_addr = 0

    if output_struct is not None and output_struct_size != 0:
        output_struct_addr = ql.os.heap.alloc(output_struct_size)
        ql.mem.write(output_struct_addr, bytes(output_struct))
        ql.dprint(D_INFO, "[+] Created output struct at 0x%x" % output_struct_size)
    else:
        output_struct_addr = 0

    dispatch_addr = ql.os.heap.alloc(ctypes.sizeof(IOExternalMethodDispatch))
    ql.dprint(D_INFO, "[+] Created IOExternalMethodDispatch object at 0x%x" % dispatch_addr)
    dispatch_obj = IOExternalMethodDispatch(ql, dispatch_addr)

    args_obj.___reservedA = 0
    args_obj._version = 2
    args_obj._selector = selector
    args_obj._asyncWakePort = 0
    args_obj._asyncReference = POINTER64(0)
    args_obj._asyncReferenceCount = 0
    args_obj._structureVariableOutputData = POINTER64(0)
    args_obj._scalarInput = POINTER64(input_array_addr)
    args_obj._scalarInputCount = input_cnt
    args_obj._structureInput = POINTER64(input_struct_addr)
    args_obj._structureInputSize = input_struct_size

    # https://stackoverflow.com/questions/45432476/sending-iokit-command-with-dynamic-length
    args_obj._structureInputDescriptor = POINTER64(0)
    args_obj._structureOutputDescriptor = POINTER64(0)
    args_obj._structureOutputDescriptorSize = 0

    args_obj._scalarOutput = POINTER64(output_array_addr)
    args_obj._scalarOutputCount = output_cnt
    args_obj._structureOutput = POINTER64(output_struct_addr)
    args_obj._structureOutputSize = output_struct_size

    args_obj.updateToMem()
    ql.dprint(D_INFO, "[+] Initialized IOExternalMethodArguments object")
    ql.os.savedrip=0xffffff8000a106ba
    ql.run(begin=ql.loader.user_alloc)
    ql.os.user_object = ql.reg.rax
    ql.dprint(D_INFO, "[+] Created user object at 0x%x" % ql.os.user_object)

    ql.reg.rdi = ql.os.user_object
    ql.reg.rsi = 0x1337 # owningTask
    ql.reg.rdx = 0 # securityID
    ql.reg.rcx = 0 # type
    ql.reg.r8 = 0 # properties
    ql.stack_push(0)
    ql.os.savedrip=0xffffff8000a10728
    ql.run(begin=ql.loader.user_initWithTask)
    ql.dprint(D_INFO, "[+] Initialized user object")

    # TODO: Add some extra methods with correct order

    ql.reg.rdi = ql.os.user_object
    ql.reg.rsi = selector
    ql.reg.rdx = args_addr
    ql.reg.rcx = dispatch_addr
    ql.reg.r8 = ql.os.kext_object
    ql.reg.r9 = 0
    ql.os.savedrip=0xffffff8000a6e9c7
    ql.run(begin=ql.loader.user_externalMethod)

    args_obj.loadFromMem()
    output_array = args_obj.scalarOutput
    ql.dprint(D_INFO, "[+] Finish IOConnectCallMethod")
    return args_obj.scalarOutput, type(output_struct).from_buffer(args_obj.structureOutput)