Exemplo n.º 1
0
    def __init__(self, ql):
        self.swsmi_handlers = {}
        self.smbase = int(ql.os.profile.get("SMM", "smbase"), 0)
        self.smram_size = int(ql.os.profile.get("SMM", "smram_size"), 0)
        self.heap_size = int(ql.os.profile.get("SMM", "heap_size"), 0)
        self.swsmi_args = {}
        
        if self.smram_size - self.heap_size < 0x10000:
            raise RuntimeError(f"SMRAM must be at least 64kb in size")

        if ql.mem.is_available(self.smbase, self.smram_size):
            # Reserve SMRAM.
            ql.mem.map(self.smbase, self.smram_size - self.heap_size)
            # Create the SMM heap, which will occupy the upper portion of SMRAM.
            self.heap = QlMemoryHeap(ql, self.smbase + self.smram_size - self.heap_size, self.smbase + self.smram_size)
        else:
            raise RuntimeError(f"Can't allocate SMRAM at 0x{self.smbase:x}-0x{self.smbase+self.smram_size:x}, \
region is already occupied")

        # Points to an optional handler context which was specified when the
        # handler was registered.
        self.context_buffer = self.heap.alloc(self.PAGE_SIZE)

        # A pointer to a collection of data in memory that will
        # be conveyed from a non-MM environment into an MM environment.
        self.comm_buffer = self.heap.alloc(self.PAGE_SIZE)
Exemplo n.º 2
0
class UefiContext:
    def __init__(self, ql):
        self.ql = ql
        self.heap = None
        self.protocols = {}

    def init_heap(self, base, size):
        self.heap = QlMemoryHeap(self.ql, base, base + size)

    def init_stack(self, base, size):
        self.ql.mem.map(base, size)

    def install_protocol(self, proto_desc, handle, address=None):
        guid = proto_desc['guid']

        if handle not in self.protocols:
            self.protocols[handle] = {}

        if guid in self.protocols[handle]:
            logging.warning(
                f'a protocol with guid {guid} is already installed')

        if address is None:
            struct_class = proto_desc['struct']
            address = self.heap.alloc(struct_class.sizeof())

        instance = init_struct(self.ql, address, proto_desc)
        instance.saveTo(self.ql, address)

        self.protocols[handle][guid] = address
Exemplo n.º 3
0
    def __init__(self, ql):
        self.swsmi_handlers = []
        self.smbase = int(ql.os.profile.get("SMM", "smbase"), 0)
        self.smram_size = int(ql.os.profile.get("SMM", "smram_size"), 0)
        self.heap_size = int(ql.os.profile.get("SMM", "heap_size"), 0)
        self.swsmi_args = {}

        # Communication buffer
        self.comm_buffer = ql.os.heap.alloc(ctypes.sizeof(EFI_SMM_SW_CONTEXT))
        self.comm_buffer_size = ql.os.heap.alloc(ctypes.sizeof(
            ctypes.c_void_p))
        ql.mem.write(
            self.comm_buffer_size,
            ctypes.sizeof(EFI_SMM_SW_CONTEXT).to_bytes(
                ctypes.sizeof(ctypes.c_void_p), 'little'))

        if self.smram_size - self.heap_size < 0x10000:
            raise RuntimeError(f"SMRAM must be at least 64kb in size")

        if ql.mem.is_available(self.smbase, self.smram_size):
            # Reserve SMRAM and create the SMM heap. The SMM heap will occupy the upper portion of SMRAM.
            ql.mem.map(self.smbase, self.smram_size - self.heap_size)
            self.heap = QlMemoryHeap(
                ql, self.smbase + self.smram_size - self.heap_size,
                self.smbase + self.smram_size)
        else:
            raise RuntimeError(
                f"Can't allocate SMRAM at 0x{self.smbase:x}-0x{self.smbase+self.smram_size:x}, \
region is already occupied")
Exemplo n.º 4
0
    def run(self):
        self.path = self.ql.path
        self.init_dlls = [b"ntdll.dll", b"kernel32.dll", b"user32.dll"]
        self.pe_entry_point = 0
        self.sizeOfStackReserve = 0

        if self.ql.archtype == QL_ARCH.X86:
            self.stack_address = int(
                self.ql.os.profile.get("OS32", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS32", "stack_size"),
                                  16)
            self.image_address = int(
                self.ql.os.profile.get("OS32", "image_address"), 16)
            self.dll_address = int(
                self.ql.os.profile.get("OS32", "dll_address"), 16)
            self.entry_point = int(
                self.ql.os.profile.get("OS32", "entry_point"), 16)
            self.ql.os.heap_base_address = int(
                self.ql.os.profile.get("OS32", "heap_address"), 16)
            self.ql.os.heap_base_size = int(
                self.ql.os.profile.get("OS32", "heap_size"), 16)
            self.structure_last_addr = FS_SEGMENT_ADDR
        elif self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = int(
                self.ql.os.profile.get("OS64", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS64", "stack_size"),
                                  16)
            self.image_address = int(
                self.ql.os.profile.get("OS64", "image_address"), 16)
            self.dll_address = int(
                self.ql.os.profile.get("OS64", "dll_address"), 16)
            self.entry_point = int(
                self.ql.os.profile.get("OS64", "entry_point"), 16)
            self.ql.os.heap_base_address = int(
                self.ql.os.profile.get("OS64", "heap_address"), 16)
            self.ql.os.heap_base_size = int(
                self.ql.os.profile.get("OS64", "heap_size"), 16)
            self.structure_last_addr = GS_SEGMENT_ADDR

        self.dlls = {}
        self.import_symbols = {}
        self.export_symbols = {}
        self.import_address_table = {}
        self.ldr_list = []
        self.pe_image_address = 0
        self.pe_image_address_size = 0
        self.dll_size = 0
        self.dll_last_address = self.dll_address
        # compatible with ql.__enable_bin_patch()
        self.load_address = 0
        self.ql.os.heap = QlMemoryHeap(
            self.ql, self.ql.os.heap_base_address,
            self.ql.os.heap_base_address + self.ql.os.heap_base_size)
        self.ql.os.setupComponents()
        self.ql.os.entry_point = self.entry_point
        self.cmdline = bytes(((str(self.ql.os.userprofile)) + "Desktop\\" +
                              (self.ql.targetname) + "\x00"), "utf-8")

        self.load()
Exemplo n.º 5
0
class UefiContext(ABC):
    def __init__(self, ql):
        self.ql = ql
        self.heap = None
        self.protocols = {}

        # These members must be initialized before attempting to install a configuration table.
        self.conf_table_array = []
        self.conf_table_array_ptr = 0
        self.conf_table_data_ptr = 0
        self.conf_table_data_next_ptr = 0

    def init_heap(self, base, size):
        self.heap = QlMemoryHeap(self.ql, base, base + size)

    def init_stack(self, base, size):
        self.ql.mem.map(base, size)

    def install_protocol(self, proto_desc, handle, address=None):
        guid = proto_desc['guid']

        if handle not in self.protocols:
            self.protocols[handle] = {}

        if guid in self.protocols[handle]:
            self.ql.log.warning(
                f'a protocol with guid {guid} is already installed')

        if address is None:
            struct_class = proto_desc['struct']
            address = self.heap.alloc(struct_class.sizeof())

        instance = init_struct(self.ql, address, proto_desc)
        instance.saveTo(self.ql, address)

        self.protocols[handle][guid] = address

    def install_configuration_table(self, guid, table):
        guid = guid.lower()
        confs = self.conf_table_array

        # find configuration table entry by guid. if found, idx would be set to the entry index
        # in the array. if not, idx would be set to one past end of array
        if guid not in confs:
            confs.append(guid)

        idx = confs.index(guid)
        ptr = self.conf_table_array_ptr + (idx *
                                           EFI_CONFIGURATION_TABLE.sizeof())

        instance = EFI_CONFIGURATION_TABLE()
        instance.VendorGuid = str_to_guid(guid)
        instance.VendorTable = table
        instance.saveTo(self.ql, ptr)
Exemplo n.º 6
0
    def run(self):
        self.load_address = self.ql.os.entry_point  # for consistency

        self.ql.mem.map(self.ql.os.entry_point,
                        self.ql.os.code_ram_size,
                        info="[code]")
        self.ql.mem.write(self.ql.os.entry_point, self.ql.code)

        heap_address = self.ql.os.entry_point + self.ql.os.code_ram_size
        heap_size = int(self.ql.os.profile.get("CODE", "heap_size"), 16)
        self.ql.os.heap = QlMemoryHeap(self.ql, heap_address,
                                       heap_address + heap_size)

        self.ql.arch.regs.arch_sp = heap_address - 0x1000

        return
Exemplo n.º 7
0
    def __init__(self, ql):
        QlOs.__init__(self, ql)
        self.ql = ql
        self.PE_RUN = True
        self.last_error = 0
        # variables used inside hooks
        self.user_defined_api = {}
        self.hooks_variables = {}
        self.syscall_count = {}
        self.argv = self.ql.argv
        self.env = self.ql.env
        self.ql.uc = self.ql.arch.init_uc
        self.ql.hook_mem_unmapped(ql_x86_windows_hook_mem_error)

        if self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = 0x7ffffffde000
            self.stack_size = 0x40000
            self.HEAP_BASE_ADDR = 0x500000000
            self.HEAP_SIZE = 0x5000000
        elif self.ql.archtype == QL_ARCH.X86:
            self.stack_address = 0xfffdd000
            self.stack_size = 0x21000
            self.HEAP_BASE_ADDR = 0x5000000
            self.HEAP_SIZE = 0x5000000

        if self.ql.stack_address == 0:
            self.ql.stack_address = self.stack_address
        if self.ql.stack_size == 0:
            self.ql.stack_size = self.stack_size
        """
        Load Heap module
        FIXME: We need to refactor this
        """
        self.heap = QlMemoryHeap(self.ql, self.HEAP_BASE_ADDR,
                                 self.HEAP_BASE_ADDR + self.HEAP_SIZE)

        self.setupGDT()
        # hook win api
        self.ql.hook_code(self.hook_winapi)
Exemplo n.º 8
0
    def load(self):
        """
        initiate UC needs to be in loader, or else it will kill execve
        Note: This is Windows, but for the sake of same with others OS
        """
        self.ql.uc = self.ql.arch.init_uc

        self.ql.hook_mem_unmapped(ql_x86_windows_hook_mem_error)

        if self.ql.archtype == QL_X8664:
            self.stack_address = 0x7ffffffde000
            self.stack_size = 0x40000
            self.ql.code_address = 0x140000000
            self.ql.code_size = 10 * 1024 * 1024
            self.HEAP_BASE_ADDR = 0x500000000
            self.HEAP_SIZE = 0x5000000
        elif self.ql.archtype == QL_X86:
            self.stack_address = 0xfffdd000
            self.stack_size = 0x21000
            self.ql.code_address = 0x40000
            self.ql.code_size = 10 * 1024 * 1024
            self.HEAP_BASE_ADDR = 0x5000000
            self.HEAP_SIZE = 0x5000000

        if self.ql.stack_address == 0:
            self.ql.stack_address = self.stack_address
        if self.ql.stack_size == 0:
            self.ql.stack_size = self.stack_size
        """
        Load Heap module
        FIXME: We need to refactor this
        """
        self.heap = QlMemoryHeap(self.ql, self.HEAP_BASE_ADDR,
                                 self.HEAP_BASE_ADDR + self.HEAP_SIZE)

        self.setupGDT()
        # hook win api
        self.ql.hook_code(self.hook_winapi)
Exemplo n.º 9
0
    def run(self):
        self.init_dlls = [b"ntdll.dll", b"kernel32.dll", b"user32.dll"]
        self.sys_dlls = [b"ntdll.dll", b"kernel32.dll"]
        self.pe_entry_point = 0
        self.sizeOfStackReserve = 0

        if not self.ql.code:
            self.pe = pefile.PE(self.path, fast_load=True)
            self.is_driver = self.pe.is_driver()
            if self.is_driver == True:
                self.init_dlls.append(b"ntoskrnl.exe")
                self.sys_dlls.append(b"ntoskrnl.exe")

        if self.ql.archtype == QL_ARCH.X86:
            self.stack_address = int(
                self.ql.os.profile.get("OS32", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS32", "stack_size"),
                                  16)
            self.image_address = int(
                self.ql.os.profile.get("OS32", "image_address"), 16)
            self.dll_address = int(
                self.ql.os.profile.get("OS32", "dll_address"), 16)
            self.entry_point = int(
                self.ql.os.profile.get("OS32", "entry_point"), 16)
            self.ql.os.heap_base_address = int(
                self.ql.os.profile.get("OS32", "heap_address"), 16)
            self.ql.os.heap_base_size = int(
                self.ql.os.profile.get("OS32", "heap_size"), 16)
            self.structure_last_addr = FS_SEGMENT_ADDR
        elif self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = int(
                self.ql.os.profile.get("OS64", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS64", "stack_size"),
                                  16)
            self.image_address = int(
                self.ql.os.profile.get("OS64", "image_address"), 16)
            self.dll_address = int(
                self.ql.os.profile.get("OS64", "dll_address"), 16)
            self.entry_point = int(
                self.ql.os.profile.get("OS64", "entry_point"), 16)
            self.ql.os.heap_base_address = int(
                self.ql.os.profile.get("OS64", "heap_address"), 16)
            self.ql.os.heap_base_size = int(
                self.ql.os.profile.get("OS64", "heap_size"), 16)
            self.structure_last_addr = GS_SEGMENT_ADDR

        self.dlls = {}
        self.import_symbols = {}
        self.export_symbols = {}
        self.import_address_table = {}
        self.ldr_list = []
        self.pe_image_address = 0
        self.pe_image_address_size = 0
        self.dll_size = 0
        self.dll_last_address = self.dll_address
        # compatible with ql.__enable_bin_patch()
        self.load_address = 0
        self.ql.os.heap = QlMemoryHeap(
            self.ql, self.ql.os.heap_base_address,
            self.ql.os.heap_base_address + self.ql.os.heap_base_size)
        self.ql.os.setupComponents()
        self.ql.os.entry_point = self.entry_point
        cmdline = (str(
            self.ql.os.userprofile)) + "Desktop\\" + self.ql.targetname
        self.filepath = bytes(cmdline + "\x00", "utf-8")
        for arg in self.argv[1:]:
            if ' ' in arg:
                cmdline += f' "{arg}"'
            else:
                cmdline += f' {arg}'
        cmdline += "\x00"
        self.cmdline = bytes(cmdline, "utf-8")

        self.load()
Exemplo n.º 10
0
class QlLoaderPE_UEFI(QlLoader):
    def __init__(self, ql):
        super(QlLoaderPE_UEFI, self).__init__(ql)
        self.ql = ql
        self.modules = []
        self.events = {}
        self.handle_dict = {}
        self.notify_list = []
        self.next_image_base = 0x10000

    @contextmanager
    def map_memory(self, addr, size):
        self.ql.mem.map(addr, size)
        try:
            yield
        finally:
            self.ql.mem.unmap(addr, size)

    def install_loaded_image_protocol(self, image_base, image_size,
                                      entry_point):
        loaded_image_protocol = EFI_LOADED_IMAGE_PROTOCOL()
        loaded_image_protocol.Revision = int(
            self.ql.os.profile["LOADED_IMAGE_PROTOCOL"]["revision"], 16)
        loaded_image_protocol.ParentHandle = 0
        loaded_image_protocol.SystemTable = self.system_table_ptr
        loaded_image_protocol.DeviceHandle = image_base
        loaded_image_protocol.FilePath = 0  # This is a handle to a complex path object, skip it for now.
        loaded_image_protocol.LoadOptionsSize = 0
        loaded_image_protocol.LoadOptions = 0
        loaded_image_protocol.ImageBase = image_base
        loaded_image_protocol.ImageSize = image_size
        loaded_image_protocol.ImageCodeType = EfiLoaderCode
        loaded_image_protocol.ImageDataType = EfiLoaderData
        loaded_image_protocol.Unload = 0

        loaded_image_protocol_ptr = self.heap.alloc(
            ctypes.sizeof(EFI_LOADED_IMAGE_PROTOCOL))
        self.ql.mem.write(loaded_image_protocol_ptr,
                          convert_struct_to_bytes(loaded_image_protocol))
        self.handle_dict[image_base] = {
            self.loaded_image_protocol_guid: loaded_image_protocol_ptr
        }
        self.loaded_image_protocol_modules.append(image_base)

    def map_and_load(self, path, execute_now=False, callback_ctx=None):
        ql = self.ql
        pe = pefile.PE(path, fast_load=True)

        # Make sure no module will occupy the NULL page
        if self.next_image_base > pe.OPTIONAL_HEADER.ImageBase:
            IMAGE_BASE = self.next_image_base
            pe.relocate_image(IMAGE_BASE)
        else:
            IMAGE_BASE = pe.OPTIONAL_HEADER.ImageBase
        IMAGE_SIZE = ql.mem.align(pe.OPTIONAL_HEADER.SizeOfImage, 0x1000)

        while IMAGE_BASE + IMAGE_SIZE < self.heap_base_address:
            if not ql.mem.is_mapped(IMAGE_BASE, 1):
                self.next_image_base = IMAGE_BASE + 0x10000
                ql.mem.map(IMAGE_BASE, IMAGE_SIZE)
                pe.parse_data_directories()
                data = bytearray(pe.get_memory_mapped_image())
                ql.mem.write(IMAGE_BASE, bytes(data))
                ql.nprint("[+] Loading %s to 0x%x" % (path, IMAGE_BASE))
                entry_point = IMAGE_BASE + pe.OPTIONAL_HEADER.AddressOfEntryPoint
                if self.entry_point == 0:
                    # Setting entry point to the first loaded module entry point, so the debugger can break.
                    self.entry_point = entry_point
                ql.nprint("[+] PE entry point at 0x%x" % entry_point)
                self.install_loaded_image_protocol(IMAGE_BASE, IMAGE_SIZE,
                                                   entry_point)
                self.images.append(
                    self.coverage_image(
                        IMAGE_BASE,
                        IMAGE_BASE + pe.NT_HEADERS.OPTIONAL_HEADER.SizeOfImage,
                        path))
                if execute_now:
                    self.OOO_EOE_callbacks.append(callback_ctx)
                    # X64 shadow store - The caller is responsible for allocating space for parameters to the callee, and must always allocate sufficient space to store four register parameters
                    ql.reg.rsp -= pointer_size * 4
                    self.execute_module(path, IMAGE_BASE, entry_point,
                                        self.OOO_EOE_ptr)
                    ql.stack_push(
                        entry_point
                    )  # Return from here to the entry point of the loaded module.

                else:
                    self.modules.append((path, IMAGE_BASE, entry_point, pe))
                return True
            else:
                IMAGE_BASE += 0x10000
                pe.relocate_image(IMAGE_BASE)
        return False

    def unload_modules(self):
        for handle in self.loaded_image_protocol_modules:
            dic = self.handle_dict[handle]
            buf = bytes(
                self.ql.mem.read(dic[self.loaded_image_protocol_guid],
                                 ctypes.sizeof(EFI_LOADED_IMAGE_PROTOCOL)))
            buffer = ctypes.create_string_buffer(buf)
            loaded_image_protocol = EFI_LOADED_IMAGE_PROTOCOL()
            ctypes.memmove(ctypes.addressof(loaded_image_protocol), buffer,
                           ctypes.sizeof(loaded_image_protocol))
            unload_ptr = struct.unpack("Q", loaded_image_protocol.Unload)[0]
            if unload_ptr != 0:
                self.ql.stack_push(self.end_of_execution_ptr)
                self.ql.reg.rcx = handle
                self.ql.reg.rip = unload_ptr
                self.ql.nprint(
                    f'[+] Unloading module 0x{handle:x}, calling 0x{unload_ptr:x}'
                )
                self.loaded_image_protocol_modules.remove(handle)
                return True
        return False

    def execute_module(self, path, image_base, entry_point, EOE_ptr):
        self.ql.stack_push(EOE_ptr)
        self.ql.reg.rcx = image_base
        self.ql.reg.rdx = self.system_table_ptr
        self.ql.reg.rip = entry_point
        self.ql.os.entry_point = entry_point
        self.ql.nprint(f'[+] Running from 0x{entry_point:x} of {path}')

    def execute_next_module(self):
        path, image_base, entry_point, pe = self.modules.pop(0)
        self.execute_module(path, image_base, entry_point,
                            self.end_of_execution_ptr)

    def run(self):
        self.loaded_image_protocol_guid = self.ql.os.profile[
            "LOADED_IMAGE_PROTOCOL"]["guid"]
        self.loaded_image_protocol_modules = []
        self.tpl = 4  # TPL_APPLICATION
        self.user_defined_api = self.ql.os.user_defined_api
        self.user_defined_api_onenter = self.ql.os.user_defined_api_onenter
        self.user_defined_api_onexit = self.ql.os.user_defined_api_onexit

        if self.ql.archtype == QL_ARCH.X8664:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS64", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS64", "heap_size"), 16)
        elif self.ql.archtype == QL_ARCH.X86:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS32", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS32", "heap_size"), 16)

        self.heap = QlMemoryHeap(self.ql, self.heap_base_address,
                                 self.heap_base_address + self.heap_base_size)
        self.entry_point = 0
        self.load_address = 0

        if self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = int(
                self.ql.os.profile.get("OS64", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS64", "stack_size"),
                                  16)

        elif self.ql.archtype == QL_ARCH.X86:
            self.stack_address = int(
                self.ql.os.profile.get("OS32", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS32", "stack_size"),
                                  16)

        # set stack pointer
        self.ql.nprint("[+] Initiate stack address at 0x%x" %
                       self.stack_address)
        self.ql.mem.map(self.stack_address, self.stack_size)

        # Stack should not init at the very bottom. Will cause errors with Dlls
        sp = self.stack_address + self.stack_size - 0x1000

        if self.ql.archtype == QL_ARCH.X86:
            raise QlErrorArch("[!] Only 64 bit arch supported for now.")

        elif self.ql.archtype == QL_ARCH.X8664:
            self.ql.reg.rsp = sp
            self.ql.reg.rbp = sp

        else:
            raise QlErrorArch("[!] Unknown ql.arch")

        # set SystemTable to image base for now
        pointer_size = ctypes.sizeof(ctypes.c_void_p)
        system_table_heap_size = 1024 * 1024
        system_table_heap = self.heap.alloc(system_table_heap_size)
        self.ql.mem.write(system_table_heap, b'\x90' * system_table_heap_size)
        self.system_table_ptr = system_table_heap
        system_table = EFI_SYSTEM_TABLE()
        system_table_heap_ptr = system_table_heap + ctypes.sizeof(
            EFI_SYSTEM_TABLE)

        self.runtime_services_ptr = system_table_heap_ptr
        system_table.RuntimeServices = self.runtime_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_RUNTIME_SERVICES)
        system_table_heap_ptr, self.runtime_services = hook_EFI_RUNTIME_SERVICES(
            self.ql, system_table_heap_ptr)

        boot_services_ptr = system_table_heap_ptr
        system_table.BootServices = boot_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_BOOT_SERVICES)
        system_table_heap_ptr, boot_services, efi_mm_system_table = hook_EFI_BOOT_SERVICES(
            self.ql, system_table_heap_ptr)

        self.efi_configuration_table_ptr = system_table_heap_ptr
        system_table.ConfigurationTable = self.efi_configuration_table_ptr
        efi_mm_system_table.MmConfigurationTable = self.efi_configuration_table_ptr
        system_table.NumberOfTableEntries = 2
        system_table_heap_ptr += ctypes.sizeof(
            EFI_CONFIGURATION_TABLE
        ) * 100  # We don't expect more then a few entries.
        efi_configuration_table = EFI_CONFIGURATION_TABLE()

        #   0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
        efi_configuration_table.VendorGuid.Data1 = int(
            self.ql.os.profile.get("HOB_LIST", "data1"), 16)
        efi_configuration_table.VendorGuid.Data2 = int(
            self.ql.os.profile.get("HOB_LIST", "data2"), 16)
        efi_configuration_table.VendorGuid.Data3 = int(
            self.ql.os.profile.get("HOB_LIST", "data3"), 16)

        data4 = ast.literal_eval(self.ql.os.profile.get("HOB_LIST", "data4"))
        datalist = 0
        for data4_list in data4:
            efi_configuration_table.VendorGuid.Data4[datalist] = data4_list
            datalist += 1

        VendorTable_ptr = system_table_heap_ptr
        write_int64(self.ql, VendorTable_ptr,
                    int(self.ql.os.profile.get("HOB_LIST", "vendortable"), 16))
        system_table_heap_ptr += pointer_size
        efi_configuration_table.VendorTable = VendorTable_ptr
        self.efi_configuration_table = [self.ql.os.profile["HOB_LIST"]["guid"]]
        self.ql.mem.write(self.efi_configuration_table_ptr,
                          convert_struct_to_bytes(efi_configuration_table))

        self.mm_system_table_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_MM_SYSTEM_TABLE)
        self.smm_base2_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_SMM_BASE2_PROTOCOL)
        system_table_heap_ptr, smm_base2_protocol, efi_mm_system_table = install_EFI_SMM_BASE2_PROTOCOL(
            self.ql, system_table_heap_ptr, efi_mm_system_table)
        self.handle_dict[1] = {
            self.ql.os.profile.get("EFI_SMM_BASE2_PROTOCOL", "guid"):
            self.smm_base2_protocol_ptr
        }

        self.mm_access_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_MM_ACCESS_PROTOCOL)
        system_table_heap_ptr, mm_access_protocol = install_EFI_MM_ACCESS_PROTOCOL(
            self.ql, system_table_heap_ptr)
        self.handle_dict[1][self.ql.os.profile.get(
            "EFI_MM_ACCESS_PROTOCOL", "guid")] = self.mm_access_protocol_ptr

        self.smm_sw_dispatch2_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_SMM_SW_DISPATCH2_PROTOCOL)
        system_table_heap_ptr, smm_sw_dispatch2_protocol = install_EFI_SMM_SW_DISPATCH2_PROTOCOL(
            self.ql, system_table_heap_ptr)
        self.handle_dict[1][self.ql.os.profile.get(
            "EFI_SMM_SW_DISPATCH2_PROTOCOL",
            "guid")] = self.smm_sw_dispatch2_protocol_ptr

        self.dxe_services_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_DXE_SERVICES)
        system_table_heap_ptr, dxe_services = install_EFI_DXE_SERVICES(
            self.ql, system_table_heap_ptr)
        efi_configuration_table = EFI_CONFIGURATION_TABLE()
        efi_configuration_table.VendorGuid.Data1 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data1"), 16)
        efi_configuration_table.VendorGuid.Data2 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data2"), 16)
        efi_configuration_table.VendorGuid.Data3 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data3"), 16)

        data4 = ast.literal_eval(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data4"))
        datalist = 0
        for data4_list in data4:
            efi_configuration_table.VendorGuid.Data4[datalist] = data4_list
            datalist += 1

        efi_configuration_table.VendorTable = self.dxe_services_ptr
        self.ql.mem.write(
            self.efi_configuration_table_ptr +
            ctypes.sizeof(EFI_CONFIGURATION_TABLE),
            convert_struct_to_bytes(efi_configuration_table))
        self.efi_configuration_table.append(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "guid"))

        self.ql.mem.write(self.runtime_services_ptr,
                          convert_struct_to_bytes(self.runtime_services))
        self.ql.mem.write(boot_services_ptr,
                          convert_struct_to_bytes(boot_services))
        self.ql.mem.write(self.system_table_ptr,
                          convert_struct_to_bytes(system_table))
        self.ql.mem.write(self.mm_system_table_ptr,
                          convert_struct_to_bytes(efi_mm_system_table))
        self.ql.mem.write(self.smm_base2_protocol_ptr,
                          convert_struct_to_bytes(smm_base2_protocol))
        self.ql.mem.write(self.mm_access_protocol_ptr,
                          convert_struct_to_bytes(mm_access_protocol))
        self.ql.mem.write(self.smm_sw_dispatch2_protocol_ptr,
                          convert_struct_to_bytes(smm_sw_dispatch2_protocol))
        self.ql.mem.write(self.dxe_services_ptr,
                          convert_struct_to_bytes(dxe_services))

        for dependency in self.ql.argv:
            if not self.map_and_load(dependency):
                raise QlErrorFileType("Can't map dependency")

        self.ql.nprint("[+] Done with loading %s" % self.ql.path)

        #return address
        self.end_of_execution_ptr = system_table_heap_ptr
        self.ql.mem.write(self.end_of_execution_ptr, b'\xcc')
        system_table_heap_ptr += pointer_size
        self.ql.hook_address(hook_EndOfExecution, self.end_of_execution_ptr)
        self.OOO_EOE_ptr = system_table_heap_ptr
        self.ql.hook_address(hook_OutOfOrder_EndOfExecution, self.OOO_EOE_ptr)
        system_table_heap_ptr += pointer_size
        self.OOO_EOE_callbacks = []

        self.execute_next_module()

    def restore_runtime_services(self):
        self.ql.mem.write(self.runtime_services_ptr,
                          convert_struct_to_bytes(self.runtime_services))
Exemplo n.º 11
0
    def run(self):
        self.loaded_image_protocol_guid = self.ql.os.profile[
            "LOADED_IMAGE_PROTOCOL"]["guid"]
        self.loaded_image_protocol_modules = []
        self.tpl = 4  # TPL_APPLICATION
        self.user_defined_api = self.ql.os.user_defined_api
        self.user_defined_api_onenter = self.ql.os.user_defined_api_onenter
        self.user_defined_api_onexit = self.ql.os.user_defined_api_onexit

        if self.ql.archtype == QL_ARCH.X8664:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS64", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS64", "heap_size"), 16)
        elif self.ql.archtype == QL_ARCH.X86:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS32", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS32", "heap_size"), 16)

        self.heap = QlMemoryHeap(self.ql, self.heap_base_address,
                                 self.heap_base_address + self.heap_base_size)
        self.entry_point = 0
        self.load_address = 0

        if self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = int(
                self.ql.os.profile.get("OS64", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS64", "stack_size"),
                                  16)

        elif self.ql.archtype == QL_ARCH.X86:
            self.stack_address = int(
                self.ql.os.profile.get("OS32", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS32", "stack_size"),
                                  16)

        # set stack pointer
        self.ql.nprint("[+] Initiate stack address at 0x%x" %
                       self.stack_address)
        self.ql.mem.map(self.stack_address, self.stack_size)

        # Stack should not init at the very bottom. Will cause errors with Dlls
        sp = self.stack_address + self.stack_size - 0x1000

        if self.ql.archtype == QL_ARCH.X86:
            raise QlErrorArch("[!] Only 64 bit arch supported for now.")

        elif self.ql.archtype == QL_ARCH.X8664:
            self.ql.reg.rsp = sp
            self.ql.reg.rbp = sp

        else:
            raise QlErrorArch("[!] Unknown ql.arch")

        # set SystemTable to image base for now
        pointer_size = ctypes.sizeof(ctypes.c_void_p)
        system_table_heap_size = 1024 * 1024
        system_table_heap = self.heap.alloc(system_table_heap_size)
        self.ql.mem.write(system_table_heap, b'\x90' * system_table_heap_size)
        self.system_table_ptr = system_table_heap
        system_table = EFI_SYSTEM_TABLE()
        system_table_heap_ptr = system_table_heap + ctypes.sizeof(
            EFI_SYSTEM_TABLE)

        self.runtime_services_ptr = system_table_heap_ptr
        system_table.RuntimeServices = self.runtime_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_RUNTIME_SERVICES)
        system_table_heap_ptr, self.runtime_services = hook_EFI_RUNTIME_SERVICES(
            self.ql, system_table_heap_ptr)

        boot_services_ptr = system_table_heap_ptr
        system_table.BootServices = boot_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_BOOT_SERVICES)
        system_table_heap_ptr, boot_services, efi_mm_system_table = hook_EFI_BOOT_SERVICES(
            self.ql, system_table_heap_ptr)

        self.efi_configuration_table_ptr = system_table_heap_ptr
        system_table.ConfigurationTable = self.efi_configuration_table_ptr
        efi_mm_system_table.MmConfigurationTable = self.efi_configuration_table_ptr
        system_table.NumberOfTableEntries = 2
        system_table_heap_ptr += ctypes.sizeof(
            EFI_CONFIGURATION_TABLE
        ) * 100  # We don't expect more then a few entries.
        efi_configuration_table = EFI_CONFIGURATION_TABLE()

        #   0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
        efi_configuration_table.VendorGuid.Data1 = int(
            self.ql.os.profile.get("HOB_LIST", "data1"), 16)
        efi_configuration_table.VendorGuid.Data2 = int(
            self.ql.os.profile.get("HOB_LIST", "data2"), 16)
        efi_configuration_table.VendorGuid.Data3 = int(
            self.ql.os.profile.get("HOB_LIST", "data3"), 16)

        data4 = ast.literal_eval(self.ql.os.profile.get("HOB_LIST", "data4"))
        datalist = 0
        for data4_list in data4:
            efi_configuration_table.VendorGuid.Data4[datalist] = data4_list
            datalist += 1

        VendorTable_ptr = system_table_heap_ptr
        write_int64(self.ql, VendorTable_ptr,
                    int(self.ql.os.profile.get("HOB_LIST", "vendortable"), 16))
        system_table_heap_ptr += pointer_size
        efi_configuration_table.VendorTable = VendorTable_ptr
        self.efi_configuration_table = [self.ql.os.profile["HOB_LIST"]["guid"]]
        self.ql.mem.write(self.efi_configuration_table_ptr,
                          convert_struct_to_bytes(efi_configuration_table))

        self.mm_system_table_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_MM_SYSTEM_TABLE)
        self.smm_base2_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_SMM_BASE2_PROTOCOL)
        system_table_heap_ptr, smm_base2_protocol, efi_mm_system_table = install_EFI_SMM_BASE2_PROTOCOL(
            self.ql, system_table_heap_ptr, efi_mm_system_table)
        self.handle_dict[1] = {
            self.ql.os.profile.get("EFI_SMM_BASE2_PROTOCOL", "guid"):
            self.smm_base2_protocol_ptr
        }

        self.mm_access_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_MM_ACCESS_PROTOCOL)
        system_table_heap_ptr, mm_access_protocol = install_EFI_MM_ACCESS_PROTOCOL(
            self.ql, system_table_heap_ptr)
        self.handle_dict[1][self.ql.os.profile.get(
            "EFI_MM_ACCESS_PROTOCOL", "guid")] = self.mm_access_protocol_ptr

        self.smm_sw_dispatch2_protocol_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_SMM_SW_DISPATCH2_PROTOCOL)
        system_table_heap_ptr, smm_sw_dispatch2_protocol = install_EFI_SMM_SW_DISPATCH2_PROTOCOL(
            self.ql, system_table_heap_ptr)
        self.handle_dict[1][self.ql.os.profile.get(
            "EFI_SMM_SW_DISPATCH2_PROTOCOL",
            "guid")] = self.smm_sw_dispatch2_protocol_ptr

        self.dxe_services_ptr = system_table_heap_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_DXE_SERVICES)
        system_table_heap_ptr, dxe_services = install_EFI_DXE_SERVICES(
            self.ql, system_table_heap_ptr)
        efi_configuration_table = EFI_CONFIGURATION_TABLE()
        efi_configuration_table.VendorGuid.Data1 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data1"), 16)
        efi_configuration_table.VendorGuid.Data2 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data2"), 16)
        efi_configuration_table.VendorGuid.Data3 = int(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data3"), 16)

        data4 = ast.literal_eval(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "data4"))
        datalist = 0
        for data4_list in data4:
            efi_configuration_table.VendorGuid.Data4[datalist] = data4_list
            datalist += 1

        efi_configuration_table.VendorTable = self.dxe_services_ptr
        self.ql.mem.write(
            self.efi_configuration_table_ptr +
            ctypes.sizeof(EFI_CONFIGURATION_TABLE),
            convert_struct_to_bytes(efi_configuration_table))
        self.efi_configuration_table.append(
            self.ql.os.profile.get("DXE_SERVICE_TABLE", "guid"))

        self.ql.mem.write(self.runtime_services_ptr,
                          convert_struct_to_bytes(self.runtime_services))
        self.ql.mem.write(boot_services_ptr,
                          convert_struct_to_bytes(boot_services))
        self.ql.mem.write(self.system_table_ptr,
                          convert_struct_to_bytes(system_table))
        self.ql.mem.write(self.mm_system_table_ptr,
                          convert_struct_to_bytes(efi_mm_system_table))
        self.ql.mem.write(self.smm_base2_protocol_ptr,
                          convert_struct_to_bytes(smm_base2_protocol))
        self.ql.mem.write(self.mm_access_protocol_ptr,
                          convert_struct_to_bytes(mm_access_protocol))
        self.ql.mem.write(self.smm_sw_dispatch2_protocol_ptr,
                          convert_struct_to_bytes(smm_sw_dispatch2_protocol))
        self.ql.mem.write(self.dxe_services_ptr,
                          convert_struct_to_bytes(dxe_services))

        for dependency in self.ql.argv:
            if not self.map_and_load(dependency):
                raise QlErrorFileType("Can't map dependency")

        self.ql.nprint("[+] Done with loading %s" % self.ql.path)

        #return address
        self.end_of_execution_ptr = system_table_heap_ptr
        self.ql.mem.write(self.end_of_execution_ptr, b'\xcc')
        system_table_heap_ptr += pointer_size
        self.ql.hook_address(hook_EndOfExecution, self.end_of_execution_ptr)
        self.OOO_EOE_ptr = system_table_heap_ptr
        self.ql.hook_address(hook_OutOfOrder_EndOfExecution, self.OOO_EOE_ptr)
        system_table_heap_ptr += pointer_size
        self.OOO_EOE_callbacks = []

        self.execute_next_module()
Exemplo n.º 12
0
    def run(self):
        self.profile        = self.ql.profile
        stack_address      = int(self.profile.get("OS64", "stack_address"), 16)
        stack_size         = int(self.profile.get("OS64", "stack_size"), 16)
        vmmap_trap_address = int(self.profile.get("OS64", "vmmap_trap_address"), 16)
        self.heap_address = int(self.profile.get("OS64", "heap_address"), 16)
        self.heap_size = int(self.profile.get("OS64", "heap_size"), 16)        
        self.stack_address = stack_address
        self.stack_size = stack_size

        if self.ql.code:
            self.ql.mem.map(self.ql.os.entry_point, self.ql.os.code_ram_size, info="[shellcode_stack]")
            self.ql.os.entry_point  = (self.ql.os.entry_point + 0x200000 - 0x1000)
            
            self.ql.mem.write(self.entry_point, self.ql.code)

            self.ql.reg.arch_sp = self.ql.os.entry_point
            return
        
        self.ql.os.macho_task = MachoTask()
        self.ql.os.macho_fs = FileSystem(self.ql)
        self.ql.os.macho_mach_port = MachPort(2187)
        self.ql.os.macho_port_manager = MachPortManager(self.ql, self.ql.os.macho_mach_port)
        self.ql.os.macho_host_server = MachHostServer(self.ql)
        self.ql.os.macho_task_server = MachTaskServer(self.ql)
        
        self.envs = env_dict_to_array(self.env)
        self.apples = self.ql.os.transform_to_relative_path(self.ql.path)
        self.ql.os.heap = QlMemoryHeap(self.ql, self.heap_address, self.heap_address + self.heap_size)

        # FIXME: Not working due to overlarge mapping, need to fix it
        # vm_shared_region_enter(self.ql)

        map_commpage(self.ql)

        self.ql.os.thread_management = QlMachoThreadManagement(self.ql)
        self.ql.os.macho_thread = QlMachoThread(self.ql)
        self.ql.os.thread_management.cur_thread = self.ql.os.macho_thread
        self.ql.os.macho_vmmap_end = vmmap_trap_address
        self.stack_sp = stack_address + stack_size
        self.macho_file     = MachoParser(self.ql, self.ql.path)
        self.is_driver      = (self.macho_file.header.file_type == 0xb)
        self.loading_file   = self.macho_file
        self.slide          = int(self.profile.get("LOADER", "slide"), 16)
        self.dyld_slide     = int(self.profile.get("LOADER", "dyld_slide"), 16)
        self.string_align   = 8
        self.ptr_align      = 8
        self.binary_entry   = 0x0
        self.proc_entry     = 0x0
        self.argvs          = [self.ql.path]
        self.argc           = 1
        self.using_dyld     = False
        self.vm_end_addr    = 0x0
        self.ql.mem.map(self.stack_address, self.stack_size, info="[stack]")
        if self.is_driver:
            self.loadDriver(self.stack_address)
            self.ql.hook_code(hook_kernel_api)
        else:
            self.loadMacho()
        self.stack_address = (int(self.stack_sp))
        self.ql.reg.arch_sp = self.stack_address # self.stack_sp
        self.init_sp = self.ql.reg.arch_sp
        self.ql.os.macho_task.min_offset = page_align_end(self.vm_end_addr, PAGE_SIZE)
Exemplo n.º 13
0
def enable_low_heap(ql):
    """
    The low heap is guaranteed to allocate memory below the 4GB boundary.
    """
    heap_base = ql.mem.find_free_space(size=0x1024**2, max_addr=0xffffffff)
    ql.os.low_heap = QlMemoryHeap(ql, heap_base, heap_base + 0x1024**2)
Exemplo n.º 14
0
    def run(self):
        self.loaded_image_protocol_guid = self.ql.os.profile[
            "LOADED_IMAGE_PROTOCOL"]["guid"]
        self.loaded_image_protocol_modules = []
        self.tpl = 4  # TPL_APPLICATION
        self.user_defined_api = self.ql.os.user_defined_api
        if self.ql.archtype == QL_ARCH.X8664:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS64", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS64", "heap_size"), 16)
        elif self.ql.archtype == QL_ARCH.X86:
            self.heap_base_address = int(
                self.ql.os.profile.get("OS32", "heap_address"), 16)
            self.heap_base_size = int(
                self.ql.os.profile.get("OS32", "heap_size"), 16)
        self.heap = QlMemoryHeap(self.ql, self.heap_base_address,
                                 self.heap_base_address + self.heap_base_size)
        self.entry_point = 0
        self.load_address = 0

        if self.ql.archtype == QL_ARCH.X8664:
            self.stack_address = int(
                self.ql.os.profile.get("OS64", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS64", "stack_size"),
                                  16)

        elif self.ql.archtype == QL_ARCH.X86:
            self.stack_address = int(
                self.ql.os.profile.get("OS32", "stack_address"), 16)
            self.stack_size = int(self.ql.os.profile.get("OS32", "stack_size"),
                                  16)

        # set stack pointer
        self.ql.nprint("[+] Initiate stack address at 0x%x" %
                       self.stack_address)
        self.ql.mem.map(self.stack_address, self.stack_size)

        # Stack should not init at the very bottom. Will cause errors with Dlls
        sp = self.stack_address + self.stack_size - 0x1000

        if self.ql.archtype == QL_ARCH.X86:
            raise QlErrorArch("[!] Only 64 bit arch supported for now.")

        elif self.ql.archtype == QL_ARCH.X8664:
            self.ql.reg.rsp = sp
            self.ql.reg.rbp = sp

        else:
            raise QlErrorArch("[!] Unknown ql.arch")

        # set SystemTable to image base for now
        pointer_size = ctypes.sizeof(ctypes.c_void_p)
        system_table_heap_size = 1024 * 1024
        system_table_heap = self.heap.alloc(system_table_heap_size)
        self.ql.mem.write(system_table_heap, b'\x90' * system_table_heap_size)
        self.system_table_ptr = system_table_heap
        system_table = EFI_SYSTEM_TABLE()
        system_table_heap_ptr = system_table_heap + ctypes.sizeof(
            EFI_SYSTEM_TABLE)

        runtime_services_ptr = system_table_heap_ptr
        system_table.RuntimeServices = runtime_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_RUNTIME_SERVICES)
        system_table_heap_ptr, runtime_services = hook_EFI_RUNTIME_SERVICES(
            self.ql, system_table_heap_ptr)

        boot_services_ptr = system_table_heap_ptr
        system_table.BootServices = boot_services_ptr
        system_table_heap_ptr += ctypes.sizeof(EFI_BOOT_SERVICES)
        system_table_heap_ptr, boot_services = hook_EFI_BOOT_SERVICES(
            self.ql, system_table_heap_ptr)

        self.efi_configuration_table_ptr = system_table_heap_ptr
        system_table.ConfigurationTable = self.efi_configuration_table_ptr
        system_table.NumberOfTableEntries = 1
        system_table_heap_ptr += ctypes.sizeof(
            EFI_CONFIGURATION_TABLE
        ) * 100  # We don't expect more then a few entries.
        efi_configuration_table = EFI_CONFIGURATION_TABLE()

        #   0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
        efi_configuration_table.VendorGuid.Data1 = int(
            self.ql.os.profile.get("GUID", "data1"), 16)
        efi_configuration_table.VendorGuid.Data2 = int(
            self.ql.os.profile.get("GUID", "data2"), 16)
        efi_configuration_table.VendorGuid.Data3 = int(
            self.ql.os.profile.get("GUID", "data3"), 16)

        data4 = ast.literal_eval(self.ql.os.profile.get("GUID", "data4"))
        datalist = 0
        for data4_list in data4:
            efi_configuration_table.VendorGuid.Data4[datalist] = data4_list
            datalist += 1

        efi_configuration_table.VendorTable = self.ql.os.profile.getint(
            "GUID", "vendortable")
        self.efi_configuration_table = [
            self.ql.os.profile["GUID"]["configuration_table"]
        ]
        self.ql.mem.write(runtime_services_ptr,
                          convert_struct_to_bytes(runtime_services))
        self.ql.mem.write(boot_services_ptr,
                          convert_struct_to_bytes(boot_services))
        self.ql.mem.write(self.efi_configuration_table_ptr,
                          convert_struct_to_bytes(efi_configuration_table))
        self.ql.mem.write(self.system_table_ptr,
                          convert_struct_to_bytes(system_table))

        # Make sure no module will occupy the NULL page
        with self.map_memory(0, 0x1000):
            if len(self.ql.argv) > 1:
                for dependency in self.ql.argv[1:]:
                    if not self.map_and_load(dependency):
                        raise QlErrorFileType("Can't map dependency")

            # Load main module
            self.map_and_load(self.ql.path)
            self.ql.nprint("[+] Done with loading %s" % self.ql.path)

        #return address
        self.end_of_execution_ptr = system_table_heap_ptr
        self.ql.mem.write(self.end_of_execution_ptr, b'\xcc')
        system_table_heap_ptr += pointer_size
        self.ql.hook_address(hook_EndOfExecution, self.end_of_execution_ptr)
        self.notify_ptr = system_table_heap_ptr
        system_table_heap_ptr += pointer_size

        self.execute_next_module()
Exemplo n.º 15
0
 def init_heap(self, base, size):
     self.heap = QlMemoryHeap(self.ql, base, base + size)
Exemplo n.º 16
0
    def __init__(self, ql: Qiling):
        super().__init__(ql)

        self.ql = ql

        def __make_fcall_selector(
                atype: QL_ARCH) -> Callable[[int], QlFunctionCall]:
            """ [internal] Generate a fcall selection function based on the required calling
            convention. This is unique to 32-bits Windows, which may need to call both CDECL
            and STDCALL functions. The 64-bits version, on the other hand, always use MS64.

            To maintain the same behavior across Windows versions, the fcall selection function
            for 64-bit is designed to ignore the calling convention identifier and always return
            a MS64 fcall instance.
            """

            __fcall_objs = {
                fncc.STDCALL: QlFunctionCall(ql, intel.stdcall(ql.arch)),
                fncc.CDECL: QlFunctionCall(ql, intel.cdecl(ql.arch)),
                fncc.MS64: QlFunctionCall(ql, intel.ms64(ql.arch))
            }

            __selector = {
                QL_ARCH.X86: lambda cc: __fcall_objs[cc],
                QL_ARCH.X8664: lambda cc: __fcall_objs[fncc.MS64]
            }

            return __selector[atype]

        self.fcall_select = __make_fcall_selector(ql.arch.type)
        self.fcall = self.fcall_select(fncc.CDECL)

        self.stats = QlWinStats()

        ossection = f'OS{self.ql.arch.bits}'
        heap_base = self.profile.getint(ossection, 'heap_address')
        heap_size = self.profile.getint(ossection, 'heap_size')

        self.heap = QlMemoryHeap(self.ql, heap_base, heap_base + heap_size)

        sysdrv = self.profile.get('PATH', 'systemdrive')
        windir = self.profile.get('PATH', 'windir')
        username = self.profile.get('USER', 'username')

        self.windir = ntpath.join(sysdrv, windir)
        self.winsys = ntpath.join(sysdrv, windir, 'System32')
        self.userprofile = ntpath.join(sysdrv, 'Users', username)
        self.username = username

        self.PE_RUN = False
        self.last_error = 0
        # variables used inside hooks
        self.hooks_variables = {}
        self.syscall_count = {}
        self.argv = self.ql.argv
        self.env = self.ql.env
        self.pid = self.profile.getint('KERNEL', 'pid')

        self.services = {}
        self.load()

        # only after handle manager has been set up we can assign the standard streams
        self.stdin = self._stdin
        self.stdout = self._stdout
        self.stderr = self._stderr
Exemplo n.º 17
0
class UefiContext(ABC):
    def __init__(self, ql: Qiling):
        self.ql = ql
        self.heap: QlMemoryHeap
        self.top_of_stack: int
        self.protocols = {}
        self.loaded_image_protocol_modules: MutableSequence[int] = []
        self.next_image_base: int

        # These members must be initialized before attempting to install a configuration table.
        self.conf_table_data_ptr = 0
        self.conf_table_data_next_ptr = 0

        self.conftable: UefiConfTable
        self.end_of_execution_ptr: int

    # TODO: implement save state
    def save(self) -> Mapping[str, Any]:
        return {}

    # TODO: implement restore state
    def restore(self, saved_state: Mapping[str, Any]):
        pass

    def init_heap(self, base: int, size: int):
        self.heap = QlMemoryHeap(self.ql, base, base + size)

    def init_stack(self, base: int, size: int):
        self.ql.mem.map(base, size, info='[stack]')
        self.top_of_stack = (base + size - 1) & ~(CPU_STACK_ALIGNMENT - 1)

    def install_protocol(self,
                         proto_desc: Mapping,
                         handle: int,
                         address: int = None,
                         from_hook: bool = False):
        guid = proto_desc['guid']

        if handle not in self.protocols:
            self.protocols[handle] = {}

        if guid in self.protocols[handle]:
            self.ql.log.warning(
                f'a protocol with guid {guid} is already installed')

        if address is None:
            struct_class = proto_desc['struct']
            address = self.heap.alloc(struct_class.sizeof())

        instance = utils.init_struct(self.ql, address, proto_desc)
        instance.saveTo(self.ql, address)

        self.protocols[handle][guid] = address
        return self.notify_protocol(handle, guid, address, from_hook)

    def notify_protocol(self, handle: int, protocol: str, interface: int,
                        from_hook: bool):
        for (event_id, event_dic) in self.ql.loader.events.items():
            if event_dic['Guid'] == protocol:
                if event_dic['CallbackArgs'] == None:
                    # To support smm notification, we use None for CallbackArgs on SmmRegisterProtocolNotify
                    # and updare it here.
                    guid = utils.str_to_guid(protocol)
                    guid_ptr = self.heap.alloc(guid.sizeof())
                    guid.saveTo(self.ql, guid_ptr)

                    event_dic['CallbackArgs'] = [guid_ptr, interface, handle]

                # The event was previously registered by 'RegisterProtocolNotify'.
                utils.signal_event(self.ql, event_id)

        return utils.execute_protocol_notifications(self.ql, from_hook)
Exemplo n.º 18
0
class UefiContext(ABC):
	def __init__(self, ql: Qiling):
		self.ql = ql
		self.heap = None
		self.protocols = {}

		# These members must be initialized before attempting to install a configuration table.
		self.conf_table_array = []
		self.conf_table_array_ptr = 0
		self.conf_table_data_ptr = 0
		self.conf_table_data_next_ptr = 0

	def init_heap(self, base: int, size: int):
		self.heap = QlMemoryHeap(self.ql, base, base + size)

	def init_stack(self, base: int, size: int):
		self.ql.mem.map(base, size)

	def install_protocol(self, proto_desc: Mapping, handle, address: int = None, from_hook: bool = False):
		guid = proto_desc['guid']

		if handle not in self.protocols:
			self.protocols[handle] = {}

		if guid in self.protocols[handle]:
			self.ql.log.warning(f'a protocol with guid {guid} is already installed')

		if address is None:
			struct_class = proto_desc['struct']
			address = self.heap.alloc(struct_class.sizeof())

		instance = init_struct(self.ql, address, proto_desc)
		instance.saveTo(self.ql, address)

		self.protocols[handle][guid] = address
		return self.notify_protocol(handle, guid, address, from_hook)

	def notify_protocol(self, handle, protocol, interface, from_hook):
		for (event_id, event_dic) in self.ql.loader.events.items():
			if event_dic['Guid'] == protocol:
				if event_dic['CallbackArgs'] == None:
					# To support smm notification, we use None for CallbackArgs on SmmRegisterProtocolNotify 
					# and updare it here.
					guid = str_to_guid(protocol)
					guid_ptr = self.heap.alloc(guid.sizeof())
					guid.saveTo(self.ql, guid_ptr)
					event_dic['CallbackArgs'] = [guid_ptr, interface, handle]
				# The event was previously registered by 'RegisterProtocolNotify'.
				signal_event(self.ql, event_id)
		return execute_protocol_notifications(self.ql, from_hook)

	def install_configuration_table(self, guid: str, table: int):
		guid = guid.lower()
		confs = self.conf_table_array

		# find configuration table entry by guid. if found, idx would be set to the entry index
		# in the array. if not, idx would be set to one past end of array
		if guid not in confs:
			confs.append(guid)

		idx = confs.index(guid)
		ptr = self.conf_table_array_ptr + (idx * EFI_CONFIGURATION_TABLE.sizeof())

		instance = EFI_CONFIGURATION_TABLE()
		instance.VendorGuid = str_to_guid(guid)
		instance.VendorTable = table
		instance.saveTo(self.ql, ptr)