From 8c401695250b41cd37be5757de3075d1999e06f0 Mon Sep 17 00:00:00 2001 From: elicn Date: Thu, 1 Sep 2022 02:57:29 +0300 Subject: [PATCH 01/15] Remove memory accessors --- qiling/os/uefi/bs.py | 26 ++++---- qiling/os/uefi/context.py | 8 +-- .../uefi/protocols/EfiSmmAccess2Protocol.py | 23 ++++--- .../os/uefi/protocols/EfiSmmBase2Protocol.py | 7 +-- .../protocols/EfiSmmSwDispatch2Protocol.py | 5 +- qiling/os/uefi/protocols/common.py | 17 +++--- qiling/os/uefi/rt.py | 16 ++--- qiling/os/uefi/smm.py | 3 +- qiling/os/uefi/smst.py | 18 +++--- qiling/os/uefi/utils.py | 60 +------------------ 10 files changed, 62 insertions(+), 121 deletions(-) diff --git a/qiling/os/uefi/bs.py b/qiling/os/uefi/bs.py index 91e139254..dca296cd6 100644 --- a/qiling/os/uefi/bs.py +++ b/qiling/os/uefi/bs.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -40,7 +40,7 @@ def hook_AllocatePages(ql: Qiling, address: int, params): alloc_size = params["Pages"] * PAGE_SIZE if params['type'] == EFI_ALLOCATE_TYPE.AllocateAddress: - address = read_int64(ql, params["Memory"]) + address = ql.mem.read_ptr(params["Memory"]) # TODO: check the range [address, address + alloc_size] is available first ql.mem.map(address, alloc_size) @@ -51,7 +51,7 @@ def hook_AllocatePages(ql: Qiling, address: int, params): if address == 0: return EFI_OUT_OF_RESOURCES - write_int64(ql, params["Memory"], address) + ql.mem.write_ptr(params["Memory"], address) return EFI_SUCCESS @@ -87,7 +87,7 @@ def hook_AllocatePool(ql: Qiling, address: int, params): Buffer = params["Buffer"] address = ql.loader.dxe_context.heap.alloc(Size) - write_int64(ql, Buffer, address) + ql.mem.write_ptr(Buffer, address) return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES @@ -304,7 +304,7 @@ def hook_GetNextMonotonicCount(ql: Qiling, address: int, params): out = params["Count"] ql.os.monotonic_count += 1 - write_int64(ql, out, ql.os.monotonic_count) + ql.mem.write_ptr(out, ql.os.monotonic_count, 8) return EFI_SUCCESS @@ -386,19 +386,19 @@ def hook_ProtocolsPerHandle(ql: Qiling, address: int, params): }) def hook_LocateHandleBuffer(ql: Qiling, address: int, params): buffer_size, handles = common.LocateHandles(ql.loader.dxe_context, params) - write_int64(ql, params["NoHandles"], len(handles)) + ql.mem.write_ptr(params["NoHandles"], len(handles)) if len(handles) == 0: return EFI_NOT_FOUND address = ql.loader.dxe_context.heap.alloc(buffer_size) - write_int64(ql, params["Buffer"], address) + ql.mem.write_ptr(params["Buffer"], address) if address == 0: return EFI_OUT_OF_RESOURCES for handle in handles: - write_int64(ql, address, handle) + ql.mem.write_ptr(address, handle) address += ql.arch.pointersize return EFI_SUCCESS @@ -416,7 +416,7 @@ def hook_LocateProtocol(ql: Qiling, address: int, params): # ... }) def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): - handle = read_int64(ql, params["Handle"]) + handle = ql.mem.read_ptr(params["Handle"]) if handle == 0: handle = ql.loader.dxe_context.heap.alloc(ql.arch.pointersize) @@ -437,7 +437,7 @@ def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): ql.loader.dxe_context.protocols[handle] = dic execute_protocol_notifications(ql, True) - write_int64(ql, params["Handle"], handle) + ql.mem.write_ptr(params["Handle"], handle) return EFI_SUCCESS @@ -477,8 +477,8 @@ def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): "Crc32" : POINTER # PTR(UINT32) }) def hook_CalculateCrc32(ql: Qiling, address: int, params): - data = bytes(ql.mem.read(params['Data'], params['DataSize'])) - write_int32(ql, params['Crc32'], crc32(data)) + data = ql.mem.read(params['Data'], params['DataSize']) + ql.mem.write_ptr(params['Crc32'], crc32(data), 4) return EFI_SUCCESS @@ -530,7 +530,7 @@ def CreateEvent(ql: Qiling, params): event_dic["EventGroup"] = params["EventGroup"] ql.loader.events[event_id] = event_dic - write_int64(ql, params["Event"], event_id) + ql.mem.write_ptr(params["Event"], event_id) return EFI_SUCCESS diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index 830995080..7d719f79d 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -62,7 +62,7 @@ def notify_protocol(self, handle: int, protocol: str, interface: int, 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 + # 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()) @@ -119,19 +119,19 @@ def system_table(self) -> int: def baseptr(self) -> int: addr = self.system_table + self.__arrptr_off - return utils.read_int64(self.ql, addr) + return self.ql.mem.read_ptr(addr) @property def nitems(self) -> int: addr = self.system_table + self.__nitems_off - return utils.read_int64(self.ql, addr) # UINTN + return self.ql.mem.read_ptr(addr) # UINTN @nitems.setter def nitems(self, value: int): addr = self.system_table + self.__nitems_off - utils.write_int64(self.ql, addr, value) + self.ql.mem.write_ptr(addr, value) def install(self, guid: str, table: int): ptr = self.find(guid) diff --git a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py index 186f4803b..9e34fe807 100644 --- a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -10,15 +10,14 @@ from ..ProcessorBind import * from ..UefiBaseType import * from ..PiMultiPhase import * -from .. import utils # @see: MdePkg\Include\Pi\PiMultiPhase.h class EFI_MMRAM_DESCRIPTOR(STRUCT): _fields_ = [ - ('PhysicalStart', EFI_PHYSICAL_ADDRESS), - ('CpuStart', EFI_PHYSICAL_ADDRESS), - ('PhysicalSize', UINT64), - ('RegionState', UINT64) + ('PhysicalStart', EFI_PHYSICAL_ADDRESS), + ('CpuStart', EFI_PHYSICAL_ADDRESS), + ('PhysicalSize', UINT64), + ('RegionState', UINT64) ] # @see: MdePkg\Include\Protocol\MmAccess.h @@ -28,11 +27,11 @@ class EFI_SMM_ACCESS2_PROTOCOL(STRUCT): _fields_ = [ ('Open', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))), - ('Close', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))), + ('Close', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))), ('Lock', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL))), - ('GetCapabilities', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL), PTR(UINTN), PTR(EFI_MMRAM_DESCRIPTOR))), - ('LockState', BOOLEAN), - ('OpenState', BOOLEAN) + ('GetCapabilities', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_ACCESS2_PROTOCOL), PTR(UINTN), PTR(EFI_MMRAM_DESCRIPTOR))), + ('LockState', BOOLEAN), + ('OpenState', BOOLEAN) ] @dxeapi(params = { @@ -108,7 +107,7 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): size = len(chunks) * EFI_SMRAM_DESCRIPTOR.sizeof() MmramMapSize = params["MmramMapSize"] - if utils.read_int64(ql, MmramMapSize) < size: + if ql.mem.read_ptr(MmramMapSize) < size: # since the caller cannot predict how much memory would be required for storing # the memory map, this method is normally called twice. the first one passes a # zero size only to determine the expected size, then the caller allocates the @@ -124,7 +123,7 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): # have, to compensate on the coming allocation. extra = 2 * EFI_SMRAM_DESCRIPTOR.sizeof() - utils.write_int64(ql, MmramMapSize, size + extra) + ql.mem.write_ptr(MmramMapSize, size + extra) return EFI_BUFFER_TOO_SMALL MmramMap = params["MmramMap"] diff --git a/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py b/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py index 1817862a7..a6a567d1c 100644 --- a/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -8,7 +8,6 @@ from ..const import EFI_SUCCESS, EFI_INVALID_PARAMETER from ..fncc import * -from ..utils import * from ..ProcessorBind import * from ..UefiBaseType import * from ..smst import * @@ -29,7 +28,7 @@ class EFI_SMM_BASE2_PROTOCOL(STRUCT): def hook_InSmm(ql: Qiling, address: int, params): ql.log.debug(f'InSmram = {ql.os.smm.active}') - write_int8(ql, params["InSmram"], int(ql.os.smm.active)) + ql.mem.write_ptr(params["InSmram"], int(ql.os.smm.active), 1) return EFI_SUCCESS @@ -43,7 +42,7 @@ def hook_GetSmstLocation(ql: Qiling, address: int, params): if Smst == 0: return EFI_INVALID_PARAMETER - write_int64(ql, Smst, ql.loader.gSmst) + ql.mem.write_ptr(Smst, ql.loader.gSmst) return EFI_SUCCESS diff --git a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py index d26b66b9d..008db407a 100644 --- a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -9,7 +9,6 @@ from ..fncc import * from ..ProcessorBind import * from ..UefiBaseType import * -from .. import utils MAXIMUM_SWI_VALUE = 0xff @@ -81,7 +80,7 @@ def hook_Register(ql: Qiling, address: int, params): # allocate handle and return it through out parameter Handle = ql.loader.smm_context.heap.alloc(ql.arch.pointersize) - utils.write_int64(ql, DispatchHandle, Handle) + ql.mem.write_ptr(DispatchHandle, Handle) args = { 'DispatchHandle' : Handle, diff --git a/qiling/os/uefi/protocols/common.py b/qiling/os/uefi/protocols/common.py index 60cb013dd..00abefa6f 100644 --- a/qiling/os/uefi/protocols/common.py +++ b/qiling/os/uefi/protocols/common.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # from qiling.os.uefi.const import EFI_SUCCESS, EFI_NOT_FOUND, EFI_UNSUPPORTED, EFI_BUFFER_TOO_SMALL, EFI_INVALID_PARAMETER -from qiling.os.uefi.utils import read_int64, write_int64 from qiling.os.uefi.UefiSpec import EFI_LOCATE_SEARCH_TYPE def LocateHandles(context, params): @@ -25,7 +24,7 @@ def LocateHandles(context, params): return len(handles) * context.ql.arch.pointersize, handles def InstallProtocolInterface(context, params): - handle = read_int64(context.ql, params["Handle"]) + handle = context.ql.mem.read_ptr(params["Handle"]) if handle == 0: handle = context.heap.alloc(1) @@ -35,7 +34,7 @@ def InstallProtocolInterface(context, params): dic[params["Protocol"]] = params["Interface"] context.protocols[handle] = dic - write_int64(context.ql, params["Handle"], handle) + context.ql.mem.write_ptr(params["Handle"], handle) context.notify_protocol(params['Handle'], params['Protocol'], params['Interface'], True) return EFI_SUCCESS @@ -81,7 +80,7 @@ def HandleProtocol(context, params): supported = context.protocols[handle] if protocol in supported: - write_int64(context.ql, interface, supported[protocol]) + context.ql.mem.write_ptr(interface, supported[protocol]) return EFI_SUCCESS @@ -95,16 +94,16 @@ def LocateHandle(context, params): ret = EFI_BUFFER_TOO_SMALL - if read_int64(context.ql, params["BufferSize"]) >= buffer_size: + if context.ql.mem.read_ptr(params["BufferSize"]) >= buffer_size: ptr = params["Buffer"] for handle in handles: - write_int64(context.ql, ptr, handle) + context.ql.mem.write_ptr(ptr, handle) ptr += context.ql.arch.pointersize ret = EFI_SUCCESS - write_int64(context.ql, params["BufferSize"], buffer_size) + context.ql.mem.write_ptr(params["BufferSize"], buffer_size) return ret @@ -117,7 +116,7 @@ def LocateProtocol(context, params): if protocol in guid_dic: # write protocol address to out variable Interface - write_int64(context.ql, params['Interface'], guid_dic[protocol]) + context.ql.mem.write_ptr(params['Interface'], guid_dic[protocol]) return EFI_SUCCESS return EFI_NOT_FOUND diff --git a/qiling/os/uefi/rt.py b/qiling/os/uefi/rt.py index 67d95f5d0..a9d7889dc 100644 --- a/qiling/os/uefi/rt.py +++ b/qiling/os/uefi/rt.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -93,12 +93,12 @@ def hook_GetVariable(ql: Qiling, address: int, params): if name in ql.env: var = ql.env[name] - read_len = read_int64(ql, params['DataSize']) + read_len = ql.mem.read_ptr(params['DataSize']) if params['Attributes'] != 0: - write_int64(ql, params['Attributes'], 0) + ql.mem.write_ptr(params['Attributes'], 0, 4) - write_int64(ql, params['DataSize'], len(var)) + ql.mem.write_ptr(params['DataSize'], len(var)) if read_len < len(var): return EFI_BUFFER_TOO_SMALL @@ -124,7 +124,7 @@ def hook_GetNextVariableName(ql: Qiling, address: int, params): if (var_name_size == 0) or (var_name == 0): return EFI_INVALID_PARAMETER - name_size = read_int64(ql, var_name_size) + name_size = ql.mem.read_ptr(var_name_size) last_name = ql.os.utils.read_wstring(var_name) vars = ql.env['Names'] # This is a list of variable names in correct order. @@ -145,7 +145,7 @@ def hook_GetNextVariableName(ql: Qiling, address: int, params): new_name = ''.join(f'{c}\x00' for c in new_name) if len(new_name) > name_size: - write_int64(ql, var_name_size, len(new_name)) + ql.mem.write_ptr(var_name_size, len(new_name)) return EFI_BUFFER_TOO_SMALL ql.mem.write(var_name, new_name.encode('ascii')) @@ -170,7 +170,9 @@ def hook_GetNextHighMonotonicCount(ql: Qiling, address: int, params): ql.os.monotonic_count += 0x0000000100000000 hmc = ql.os.monotonic_count hmc = (hmc >> 32) & 0xffffffff - write_int32(ql, params["HighCount"], hmc) + + ql.mem.write_ptr(params["HighCount"], hmc, 4) + return EFI_SUCCESS @dxeapi(params={ diff --git a/qiling/os/uefi/smm.py b/qiling/os/uefi/smm.py index 2e0ff61a2..b85a59e82 100644 --- a/qiling/os/uefi/smm.py +++ b/qiling/os/uefi/smm.py @@ -8,7 +8,6 @@ from qiling import Qiling from qiling.os.const import POINTER from qiling.os.memory import QlMemoryHeap -from qiling.os.uefi import utils from qiling.os.uefi.context import SmmContext from qiling.os.uefi.protocols.EfiSmmCpuProtocol import EFI_SMM_SAVE_STATE_REGISTER from qiling.os.uefi.protocols.EfiSmmSwDispatch2Protocol import EFI_SMM_SW_REGISTER_CONTEXT, EFI_SMM_SW_CONTEXT @@ -230,7 +229,7 @@ def invoke_swsmi(self, cpu: int, idx: int, entry: int, args: Mapping[str, Any], SmmSwContext.saveTo(ql, CommBuffer) # setup CommBufferSize - utils.ptr_write64(ql, CommBufferSize, SmmSwContext.sizeof()) + ql.mem.write_ptr(CommBufferSize, SmmSwContext.sizeof(), 8) # clean up handler resources def __cleanup(ql: Qiling): diff --git a/qiling/os/uefi/smst.py b/qiling/os/uefi/smst.py index ec78727a7..5de88fb99 100644 --- a/qiling/os/uefi/smst.py +++ b/qiling/os/uefi/smst.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -92,7 +92,7 @@ def hook_SmmAllocatePages(ql: Qiling, address: int, params): alloc_size = params["Pages"] * PAGE_SIZE if params['type'] == EFI_ALLOCATE_TYPE.AllocateAddress: - address = read_int64(ql, params["Memory"]) + address = ql.mem.read_ptr(params["Memory"]) # TODO: check the range [address, address + alloc_size] is available first ql.mem.map(address, alloc_size) @@ -103,7 +103,7 @@ def hook_SmmAllocatePages(ql: Qiling, address: int, params): if address == 0: return EFI_OUT_OF_RESOURCES - write_int64(ql, params["Memory"], address) + ql.mem.write_ptr(params["Memory"], address) return EFI_SUCCESS @@ -126,7 +126,7 @@ def hook_SmmFreePages(ql: Qiling, address: int, params): def hook_SmmAllocatePool(ql: Qiling, address: int, params): # TODO: allocate memory acording to "PoolType" address = ql.loader.smm_context.heap.alloc(params["Size"]) - write_int64(ql, params["Buffer"], address) + ql.mem.write_ptr(params["Buffer"], address) return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES @@ -181,12 +181,14 @@ def hook_SmmRegisterProtocolNotify(ql: Qiling, address: int, params): event_id = len(ql.loader.events) event_dic = { "NotifyFunction": params["Function"], - "CallbackArgs" : None, - "Guid" : params["Protocol"], - "Set" : False + "CallbackArgs" : None, + "Guid" : params["Protocol"], + "Set" : False } + ql.loader.events[event_id] = event_dic - ptr_write64(ql, params["Registration"], event_id) + ql.mem.write_ptr(params["Registration"], event_id, 8) + return EFI_SUCCESS @dxeapi(params = { diff --git a/qiling/os/uefi/utils.py b/qiling/os/uefi/utils.py index 3c02e7499..95958c71f 100644 --- a/qiling/os/uefi/utils.py +++ b/qiling/os/uefi/utils.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -63,64 +63,6 @@ def __notify_next(ql: Qiling): return True -def ptr_read8(ql: Qiling, addr: int) -> int: - """Read BYTE data from a pointer - """ - - return ql.mem.read_ptr(addr, 1) - -def ptr_write8(ql: Qiling, addr: int, val: int) -> None: - """Write BYTE data to a pointer - """ - - ql.mem.write_ptr(addr, val, 1) - -def ptr_read16(ql: Qiling, addr: int) -> int: - """Read WORD data from a pointer - """ - - return ql.mem.read_ptr(addr, 2) - -def ptr_write16(ql: Qiling, addr: int, val: int) -> None: - """Write WORD data to a pointer - """ - - ql.mem.write_ptr(addr, val, 2) - -def ptr_read32(ql: Qiling, addr: int) -> int: - """Read DWORD data from a pointer - """ - - return ql.mem.read_ptr(addr, 4) - -def ptr_write32(ql: Qiling, addr: int, val: int) -> None: - """Write DWORD data to a pointer - """ - - ql.mem.write_ptr(addr, val, 4) - -def ptr_read64(ql: Qiling, addr: int) -> int: - """Read QWORD data from a pointer - """ - - return ql.mem.read_ptr(addr, 8) - -def ptr_write64(ql: Qiling, addr: int, val: int) -> None: - """Write QWORD data to a pointer - """ - - ql.mem.write_ptr(addr, val, 8) - -# backward comptability -read_int8 = ptr_read8 -write_int8 = ptr_write8 -read_int16 = ptr_read16 -write_int16 = ptr_write16 -read_int32 = ptr_read32 -write_int32 = ptr_write32 -read_int64 = ptr_read64 -write_int64 = ptr_write64 - def init_struct(ql: Qiling, base: int, descriptor: Mapping): struct_class = descriptor['struct'] struct_fields = descriptor.get('fields', []) From 50447df5ad946667dc4fd3d897d1ecd180ef7138 Mon Sep 17 00:00:00 2001 From: elicn Date: Thu, 8 Sep 2022 12:12:13 +0300 Subject: [PATCH 02/15] Read integer values properly from profile --- qiling/loader/pe_uefi.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/qiling/loader/pe_uefi.py b/qiling/loader/pe_uefi.py index a20bf9444..11f50fdf8 100644 --- a/qiling/loader/pe_uefi.py +++ b/qiling/loader/pe_uefi.py @@ -223,19 +223,19 @@ def __init_dxe_environment(self, ql: Qiling) -> DxeContext: context = DxeContext(ql) # initialize and locate heap - heap_base = int(profile['heap_address'], 0) - heap_size = int(profile['heap_size'], 0) + heap_base = profile.getint('heap_address') + heap_size = profile.getint('heap_size') context.init_heap(heap_base, heap_size) ql.log.info(f'DXE heap at {heap_base:#010x}') # initialize and locate stack - stack_base = int(profile['stack_address'], 0) - stack_size = int(profile['stack_size'], 0) + stack_base = profile.getint('stack_address') + stack_size = profile.getint('stack_size') context.init_stack(stack_base, stack_size) ql.log.info(f'DXE stack at {context.top_of_stack:#010x}') # base address for next image - context.next_image_base = int(profile['image_address'], 0) + context.next_image_base = profile.getint('image_address') # statically allocating 4 KiB for ST, RT, BS, DS and about 100 configuration table entries. # the actual size needed was rounded up to the nearest page boundary. @@ -272,23 +272,23 @@ def __init_smm_environment(self, ql: Qiling) -> SmmContext: context = SmmContext(ql) # set smram boundaries - context.smram_base = int(profile["smram_base"], 0) - context.smram_size = int(profile["smram_size"], 0) + context.smram_base = profile.getint('smram_base') + context.smram_size = profile.getint('smram_size') # initialize and locate heap - heap_base = int(profile["heap_address"], 0) - heap_size = int(profile["heap_size"], 0) + heap_base = profile.getint('heap_address') + heap_size = profile.getint('heap_size') context.init_heap(heap_base, heap_size) ql.log.info(f"SMM heap at {heap_base:#010x}") # initialize and locate stack - stack_base = int(profile['stack_address'], 0) - stack_size = int(profile['stack_size'], 0) + stack_base = profile.getint('stack_address') + stack_size = profile.getint('stack_size') context.init_stack(stack_base, stack_size) ql.log.info(f'SMM stack at {context.top_of_stack:#010x}') # base address for next image - context.next_image_base = int(profile['image_address'], 0) + context.next_image_base = profile.getint('image_address') # statically allocating 4 KiB for SMM ST and about 100 configuration table entries # the actual size needed was rounded up to the nearest page boundary. From 6b5dd55f6087956d74aa5eb7deda3d085cb1abb3 Mon Sep 17 00:00:00 2001 From: elicn Date: Sun, 11 Sep 2022 04:19:16 +0300 Subject: [PATCH 03/15] Align memory info with other OS --- qiling/loader/pe_uefi.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qiling/loader/pe_uefi.py b/qiling/loader/pe_uefi.py index 11f50fdf8..e510cb6d1 100644 --- a/qiling/loader/pe_uefi.py +++ b/qiling/loader/pe_uefi.py @@ -3,6 +3,7 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +import os from pefile import PE from typing import Any, Mapping, Optional, Sequence @@ -105,7 +106,7 @@ def map_and_load(self, path: str, context: UefiContext, exec_now: bool=False): pe.parse_data_directories() data = bytes(pe.get_memory_mapped_image()) - ql.mem.map(image_base, image_size, info="[module]") + ql.mem.map(image_base, image_size, info=os.path.basename(path)) ql.mem.write(image_base, data) ql.log.info(f'Module {path} loaded to {image_base:#x}') @@ -120,7 +121,7 @@ def map_and_load(self, path: str, context: UefiContext, exec_now: bool=False): self.install_loaded_image_protocol(image_base, image_size) # this would be used later be loader.find_containing_image - self.images.append(Image(image_base, image_base + image_size, path)) + self.images.append(Image(image_base, image_base + image_size, os.path.abspath(path))) # update next memory slot to allow sequencial loading. its availability # is unknown though From 195d6e0b5ec44e35adb00f94bbcdaee915a0c426 Mon Sep 17 00:00:00 2001 From: elicn Date: Sun, 31 Dec 2023 21:57:22 +0200 Subject: [PATCH 04/15] Add more typing annotations --- qiling/os/uefi/bs.py | 7 ++++++- qiling/os/uefi/context.py | 6 +++--- qiling/os/uefi/protocols/common.py | 22 ++++++++++++++-------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/qiling/os/uefi/bs.py b/qiling/os/uefi/bs.py index dca296cd6..5c00cc51e 100644 --- a/qiling/os/uefi/bs.py +++ b/qiling/os/uefi/bs.py @@ -3,9 +3,10 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations +from typing import TYPE_CHECKING from binascii import crc32 -from qiling.const import QL_ENDIAN from qiling.os.const import * from qiling.os.uefi import guids_db from qiling.os.uefi.const import * @@ -15,6 +16,10 @@ from qiling.os.uefi.UefiSpec import * from qiling.os.uefi.protocols import common +if TYPE_CHECKING: + from qiling import Qiling + + @dxeapi(params = { "NewTpl" : ULONGLONG # EFI_TPL }) diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index 7d719f79d..391982f39 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Any, Mapping, MutableSequence, Optional, Tuple +from typing import Any, Mapping, Dict, MutableSequence, Optional, Tuple from qiling import Qiling from qiling.os.memory import QlMemoryHeap @@ -13,7 +13,7 @@ def __init__(self, ql: Qiling): self.ql = ql self.heap: QlMemoryHeap self.top_of_stack: int - self.protocols = {} + self.protocols: Dict[int, Dict[str, int]] = {} self.loaded_image_protocol_modules: MutableSequence[int] = [] self.next_image_base: int @@ -39,7 +39,7 @@ 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): + def install_protocol(self, proto_desc: Mapping, handle: int, address: Optional[int] = None, from_hook: bool = False): guid = proto_desc['guid'] if handle not in self.protocols: diff --git a/qiling/os/uefi/protocols/common.py b/qiling/os/uefi/protocols/common.py index 00abefa6f..e5cb7988a 100644 --- a/qiling/os/uefi/protocols/common.py +++ b/qiling/os/uefi/protocols/common.py @@ -3,10 +3,16 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations +from typing import TYPE_CHECKING + from qiling.os.uefi.const import EFI_SUCCESS, EFI_NOT_FOUND, EFI_UNSUPPORTED, EFI_BUFFER_TOO_SMALL, EFI_INVALID_PARAMETER from qiling.os.uefi.UefiSpec import EFI_LOCATE_SEARCH_TYPE -def LocateHandles(context, params): +if TYPE_CHECKING: + from qiling.os.uefi.context import UefiContext + +def LocateHandles(context: UefiContext, params): SearchType = params["SearchType"] Protocol = params["Protocol"] @@ -23,7 +29,7 @@ def LocateHandles(context, params): return len(handles) * context.ql.arch.pointersize, handles -def InstallProtocolInterface(context, params): +def InstallProtocolInterface(context: UefiContext, params): handle = context.ql.mem.read_ptr(params["Handle"]) if handle == 0: @@ -39,7 +45,7 @@ def InstallProtocolInterface(context, params): return EFI_SUCCESS -def ReinstallProtocolInterface(context, params): +def ReinstallProtocolInterface(context: UefiContext, params): handle = params["Handle"] if handle not in context.protocols: @@ -55,7 +61,7 @@ def ReinstallProtocolInterface(context, params): return EFI_SUCCESS -def UninstallProtocolInterface(context, params): +def UninstallProtocolInterface(context: UefiContext, params): handle = params["Handle"] if handle not in context.protocols: @@ -71,7 +77,7 @@ def UninstallProtocolInterface(context, params): return EFI_SUCCESS -def HandleProtocol(context, params): +def HandleProtocol(context: UefiContext, params): handle = params["Handle"] protocol = params["Protocol"] interface = params['Interface'] @@ -86,7 +92,7 @@ def HandleProtocol(context, params): return EFI_UNSUPPORTED -def LocateHandle(context, params): +def LocateHandle(context: UefiContext, params): buffer_size, handles = LocateHandles(context, params) if len(handles) == 0: @@ -107,7 +113,7 @@ def LocateHandle(context, params): return ret -def LocateProtocol(context, params): +def LocateProtocol(context: UefiContext, params): protocol = params['Protocol'] for handle, guid_dic in context.protocols.items(): @@ -121,7 +127,7 @@ def LocateProtocol(context, params): return EFI_NOT_FOUND -def InstallConfigurationTable(context, params): +def InstallConfigurationTable(context: UefiContext, params): guid = params["Guid"] table = params["Table"] From f893d4aa45a87f4f53d6da2618e60854745b63b8 Mon Sep 17 00:00:00 2001 From: elicn Date: Sun, 31 Dec 2023 21:58:18 +0200 Subject: [PATCH 05/15] Avoid using obsolete binascii --- qiling/os/uefi/utils.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/qiling/os/uefi/utils.py b/qiling/os/uefi/utils.py index 95958c71f..fdd35d5be 100644 --- a/qiling/os/uefi/utils.py +++ b/qiling/os/uefi/utils.py @@ -3,8 +3,6 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -import binascii - from uuid import UUID from typing import Optional, Mapping @@ -116,7 +114,7 @@ def install_configuration_table(context, key: str, table: Optional[int]): # if pointer to table data was not specified, load table data # from profile and have table pointing to it if table is None: - data = binascii.unhexlify(cfgtable['TableData']) + data = bytes.fromhex(cfgtable['TableData']) table = context.conf_table_data_next_ptr context.ql.mem.write(table, data) From 78a81f9f924ba2cbd85040808a010043a682e506 Mon Sep 17 00:00:00 2001 From: elicn Date: Mon, 1 Jan 2024 21:15:36 +0200 Subject: [PATCH 06/15] Adjust indentation after convertion to spaces --- qiling/os/uefi/PiMultiPhase.py | 28 +- qiling/os/uefi/UefiBaseType.py | 24 +- qiling/os/uefi/UefiMultiPhase.py | 12 +- qiling/os/uefi/UefiSpec.py | 296 +++++++-------- qiling/os/uefi/bs.py | 356 +++++++++--------- qiling/os/uefi/const.py | 70 ++-- qiling/os/uefi/ds.py | 170 ++++----- qiling/os/uefi/hob.py | 14 +- .../uefi/protocols/EfiLoadedImageProtocol.py | 36 +- .../uefi/protocols/EfiSmmAccess2Protocol.py | 16 +- .../os/uefi/protocols/EfiSmmBase2Protocol.py | 16 +- qiling/os/uefi/protocols/EfiSmmCpuProtocol.py | 190 +++++----- .../protocols/EfiSmmSwDispatch2Protocol.py | 30 +- qiling/os/uefi/protocols/PcdProtocol.py | 302 +++++++-------- qiling/os/uefi/rt.py | 114 +++--- qiling/os/uefi/smm.py | 96 ++--- qiling/os/uefi/smst.py | 196 +++++----- qiling/os/uefi/st.py | 12 +- 18 files changed, 989 insertions(+), 989 deletions(-) diff --git a/qiling/os/uefi/PiMultiPhase.py b/qiling/os/uefi/PiMultiPhase.py index ba9906f96..c2bbe7f87 100644 --- a/qiling/os/uefi/PiMultiPhase.py +++ b/qiling/os/uefi/PiMultiPhase.py @@ -1,25 +1,25 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from .UefiBaseType import * -from .ProcessorBind import * +from .UefiBaseType import EFI_PHYSICAL_ADDRESS +from .ProcessorBind import UINT64, STRUCT -EFI_SMRAM_OPEN = 0x00000001 -EFI_SMRAM_CLOSED = 0x00000002 -EFI_SMRAM_LOCKED = 0x00000004 -EFI_CACHEABLE = 0x00000008 -EFI_ALLOCATED = 0x00000010 -EFI_NEEDS_TESTING = 0x00000020 -EFI_NEEDS_ECC_INITIALIZATION = 0x00000040 +EFI_SMRAM_OPEN = 0x00000001 +EFI_SMRAM_CLOSED = 0x00000002 +EFI_SMRAM_LOCKED = 0x00000004 +EFI_CACHEABLE = 0x00000008 +EFI_ALLOCATED = 0x00000010 +EFI_NEEDS_TESTING = 0x00000020 +EFI_NEEDS_ECC_INITIALIZATION = 0x00000040 class EFI_SMRAM_DESCRIPTOR(STRUCT): _fields_ = [ - ('PhysicalStart', EFI_PHYSICAL_ADDRESS), - ('CpuStart', EFI_PHYSICAL_ADDRESS), - ('PhysicalSize', UINT64), - ('RegionState', UINT64) + ('PhysicalStart', EFI_PHYSICAL_ADDRESS), + ('CpuStart', EFI_PHYSICAL_ADDRESS), + ('PhysicalSize', UINT64), + ('RegionState', UINT64) ] __all__ = [ diff --git a/qiling/os/uefi/UefiBaseType.py b/qiling/os/uefi/UefiBaseType.py index 5f9d87fbe..b3702d47f 100644 --- a/qiling/os/uefi/UefiBaseType.py +++ b/qiling/os/uefi/UefiBaseType.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -23,17 +23,17 @@ class EFI_GUID(STRUCT): class EFI_TIME(STRUCT): _fields_ = [ - ('Year', UINT16), - ('Month', UINT8), - ('Day', UINT8), - ('Hour', UINT8), - ('Minute', UINT8), - ('Second', UINT8), - ('Pad1', UINT8), - ('Nanosecond', UINT32), - ('TimeZone', UINT16), - ('Daylight', UINT8), - ('Pad2', UINT8) + ('Year', UINT16), + ('Month', UINT8), + ('Day', UINT8), + ('Hour', UINT8), + ('Minute', UINT8), + ('Second', UINT8), + ('Pad1', UINT8), + ('Nanosecond', UINT32), + ('TimeZone', UINT16), + ('Daylight', UINT8), + ('Pad2', UINT8) ] __all__ = [ diff --git a/qiling/os/uefi/UefiMultiPhase.py b/qiling/os/uefi/UefiMultiPhase.py index 7e44b1d92..4a67b1d93 100644 --- a/qiling/os/uefi/UefiMultiPhase.py +++ b/qiling/os/uefi/UefiMultiPhase.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -8,11 +8,11 @@ # @see: MdePkg\Include\Uefi\UefiMultiPhase.h class EFI_TABLE_HEADER(STRUCT): _fields_ = [ - ('Signature', UINT64), - ('Revision', UINT32), - ('HeaderSize', UINT32), - ('CRC32', UINT32), - ('Reserved', UINT32) + ('Signature', UINT64), + ('Revision', UINT32), + ('HeaderSize', UINT32), + ('CRC32', UINT32), + ('Reserved', UINT32) ] class EFI_RESET_TYPE(ENUM): diff --git a/qiling/os/uefi/UefiSpec.py b/qiling/os/uefi/UefiSpec.py index 7c236d0ab..2259e8c35 100644 --- a/qiling/os/uefi/UefiSpec.py +++ b/qiling/os/uefi/UefiSpec.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -48,62 +48,62 @@ class EFI_TIME_CAPABILITIES(STRUCT): _pack_ = 8 _fields_ = [ - ('Resolution', UINT32), - ('Accuracy', UINT32), - ('SetsToZero', BOOLEAN), + ('Resolution', UINT32), + ('Accuracy', UINT32), + ('SetsToZero', BOOLEAN), ] class EFI_MEMORY_DESCRIPTOR(STRUCT): _pack_ = 8 _fields_ = [ - ('Type', UINT32), - ('PhysicalStart', EFI_PHYSICAL_ADDRESS), - ('VirtualStart', EFI_VIRTUAL_ADDRESS), - ('NumberOfPages', UINT64), - ('Attribute', UINT64) + ('Type', UINT32), + ('PhysicalStart', EFI_PHYSICAL_ADDRESS), + ('VirtualStart', EFI_VIRTUAL_ADDRESS), + ('NumberOfPages', UINT64), + ('Attribute', UINT64) ] class EFI_CAPSULE_HEADER(STRUCT): _fields_ = [ - ('CapsuleGuid', EFI_GUID), - ('HeaderSize', UINT32), - ('Flags', UINT32), - ('CapsuleImageSize', UINT32) + ('CapsuleGuid', EFI_GUID), + ('HeaderSize', UINT32), + ('Flags', UINT32), + ('CapsuleImageSize', UINT32) ] -EFI_GET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME), PTR(EFI_TIME_CAPABILITIES)) -EFI_SET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME)) -EFI_GET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, PTR(BOOLEAN), PTR(BOOLEAN), PTR(EFI_TIME)) -EFI_SET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, BOOLEAN, PTR(EFI_TIME)) -EFI_SET_VIRTUAL_ADDRESS_MAP = FUNCPTR(EFI_STATUS, UINTN, UINTN, UINT32, PTR(EFI_MEMORY_DESCRIPTOR)) -EFI_CONVERT_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(PTR(VOID))) -EFI_GET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), PTR(UINT32), PTR(UINTN), PTR(VOID)) -EFI_GET_NEXT_VARIABLE_NAME = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(CHAR16), PTR(EFI_GUID)) -EFI_SET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), UINT32, UINTN, PTR(VOID)) -EFI_GET_NEXT_HIGH_MONO_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT32)) -EFI_RESET_SYSTEM = FUNCPTR(VOID, EFI_RESET_TYPE, EFI_STATUS, UINTN, PTR(VOID)) -EFI_UPDATE_CAPSULE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, EFI_PHYSICAL_ADDRESS) -EFI_QUERY_CAPSULE_CAPABILITIES = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, PTR(UINT64), PTR(EFI_RESET_TYPE)) -EFI_QUERY_VARIABLE_INFO = FUNCPTR(EFI_STATUS, UINT32, PTR(UINT64), PTR(UINT64), PTR(UINT64)) +EFI_GET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME), PTR(EFI_TIME_CAPABILITIES)) +EFI_SET_TIME = FUNCPTR(EFI_STATUS, PTR(EFI_TIME)) +EFI_GET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, PTR(BOOLEAN), PTR(BOOLEAN), PTR(EFI_TIME)) +EFI_SET_WAKEUP_TIME = FUNCPTR(EFI_STATUS, BOOLEAN, PTR(EFI_TIME)) +EFI_SET_VIRTUAL_ADDRESS_MAP = FUNCPTR(EFI_STATUS, UINTN, UINTN, UINT32, PTR(EFI_MEMORY_DESCRIPTOR)) +EFI_CONVERT_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(PTR(VOID))) +EFI_GET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), PTR(UINT32), PTR(UINTN), PTR(VOID)) +EFI_GET_NEXT_VARIABLE_NAME = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(CHAR16), PTR(EFI_GUID)) +EFI_SET_VARIABLE = FUNCPTR(EFI_STATUS, PTR(CHAR16), PTR(EFI_GUID), UINT32, UINTN, PTR(VOID)) +EFI_GET_NEXT_HIGH_MONO_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT32)) +EFI_RESET_SYSTEM = FUNCPTR(VOID, EFI_RESET_TYPE, EFI_STATUS, UINTN, PTR(VOID)) +EFI_UPDATE_CAPSULE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, EFI_PHYSICAL_ADDRESS) +EFI_QUERY_CAPSULE_CAPABILITIES = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_CAPSULE_HEADER)), UINTN, PTR(UINT64), PTR(EFI_RESET_TYPE)) +EFI_QUERY_VARIABLE_INFO = FUNCPTR(EFI_STATUS, UINT32, PTR(UINT64), PTR(UINT64), PTR(UINT64)) class EFI_RUNTIME_SERVICES(STRUCT): _fields_ = [ - ('Hdr', EFI_TABLE_HEADER), - ('GetTime', EFI_GET_TIME), - ('SetTime', EFI_SET_TIME), - ('GetWakeupTime', EFI_GET_WAKEUP_TIME), - ('SetWakeupTime', EFI_SET_WAKEUP_TIME), - ('SetVirtualAddressMap', EFI_SET_VIRTUAL_ADDRESS_MAP), - ('ConvertPointer', EFI_CONVERT_POINTER), - ('GetVariable', EFI_GET_VARIABLE), - ('GetNextVariableName', EFI_GET_NEXT_VARIABLE_NAME), - ('SetVariable', EFI_SET_VARIABLE), - ('GetNextHighMonotonicCount', EFI_GET_NEXT_HIGH_MONO_COUNT), - ('ResetSystem', EFI_RESET_SYSTEM), - ('UpdateCapsule', EFI_UPDATE_CAPSULE), - ('QueryCapsuleCapabilities', EFI_QUERY_CAPSULE_CAPABILITIES), - ('QueryVariableInfo', EFI_QUERY_VARIABLE_INFO) + ('Hdr', EFI_TABLE_HEADER), + ('GetTime', EFI_GET_TIME), + ('SetTime', EFI_SET_TIME), + ('GetWakeupTime', EFI_GET_WAKEUP_TIME), + ('SetWakeupTime', EFI_SET_WAKEUP_TIME), + ('SetVirtualAddressMap', EFI_SET_VIRTUAL_ADDRESS_MAP), + ('ConvertPointer', EFI_CONVERT_POINTER), + ('GetVariable', EFI_GET_VARIABLE), + ('GetNextVariableName', EFI_GET_NEXT_VARIABLE_NAME), + ('SetVariable', EFI_SET_VARIABLE), + ('GetNextHighMonotonicCount', EFI_GET_NEXT_HIGH_MONO_COUNT), + ('ResetSystem', EFI_RESET_SYSTEM), + ('UpdateCapsule', EFI_UPDATE_CAPSULE), + ('QueryCapsuleCapabilities', EFI_QUERY_CAPSULE_CAPABILITIES), + ('QueryVariableInfo', EFI_QUERY_VARIABLE_INFO) ] EFI_EVENT_NOTIFY = FUNCPTR(VOID, EFI_EVENT, PTR(VOID)) @@ -112,109 +112,109 @@ class EFI_RUNTIME_SERVICES(STRUCT): class EFI_DEVICE_PATH_PROTOCOL(STRUCT): _fields_ = [ ('Type', UINT8), - ('SubType', UINT8), - ('Length', UINT8 * 2) + ('SubType', UINT8), + ('Length', UINT8 * 2) ] class EFI_OPEN_PROTOCOL_INFORMATION_ENTRY(STRUCT): _fields_ = [ - ('AgentHandle', EFI_HANDLE), - ('ControllerHandle',EFI_HANDLE), - ('Attributes', UINT32), + ('AgentHandle', EFI_HANDLE), + ('ControllerHandle', EFI_HANDLE), + ('Attributes', UINT32), ('OpenCount', UINT32) ] -EFI_RAISE_TPL = FUNCPTR(EFI_TPL, EFI_TPL) -EFI_RESTORE_TPL = FUNCPTR(VOID, EFI_TPL) -EFI_ALLOCATE_PAGES = FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS)) -EFI_FREE_PAGES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN) -EFI_GET_MEMORY_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(EFI_MEMORY_DESCRIPTOR), PTR(UINTN), PTR(UINTN), PTR(UINT32)) -EFI_ALLOCATE_POOL = FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID))) -EFI_FREE_POOL = FUNCPTR(EFI_STATUS, PTR(VOID)) -EFI_CREATE_EVENT = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_EVENT)) -EFI_SET_TIMER = FUNCPTR(EFI_STATUS, EFI_EVENT, EFI_TIMER_DELAY, UINT64) -EFI_WAIT_FOR_EVENT = FUNCPTR(EFI_STATUS, UINTN, PTR(EFI_EVENT), PTR(UINTN)) -EFI_SIGNAL_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) -EFI_CLOSE_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) -EFI_CHECK_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) -EFI_INSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID)) -EFI_REINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID), PTR(VOID)) -EFI_UNINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID)) -EFI_HANDLE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID))) -EFI_REGISTER_PROTOCOL_NOTIFY = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_EVENT, PTR(PTR(VOID))) -EFI_LOCATE_HANDLE = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE)) -EFI_LOCATE_DEVICE_PATH = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)), PTR(EFI_HANDLE)) -EFI_INSTALL_CONFIGURATION_TABLE = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID)) -EFI_IMAGE_LOAD = FUNCPTR(EFI_STATUS, BOOLEAN, EFI_HANDLE, PTR(EFI_DEVICE_PATH_PROTOCOL), PTR(VOID) , UINTN, PTR(EFI_HANDLE)) -EFI_IMAGE_START = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(UINTN), PTR(PTR(CHAR16))) -EFI_EXIT = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_STATUS, UINTN, PTR(CHAR16)) -EFI_IMAGE_UNLOAD = FUNCPTR(EFI_STATUS, EFI_HANDLE) -EFI_EXIT_BOOT_SERVICES = FUNCPTR(EFI_STATUS, EFI_HANDLE, UINTN) -EFI_GET_NEXT_MONOTONIC_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT64)) -EFI_STALL = FUNCPTR(EFI_STATUS, UINTN) -EFI_SET_WATCHDOG_TIMER = FUNCPTR(EFI_STATUS, UINTN, UINT64, UINTN, PTR(CHAR16)) -EFI_CONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_HANDLE), PTR(EFI_DEVICE_PATH_PROTOCOL), BOOLEAN) -EFI_DISCONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_HANDLE, EFI_HANDLE) -EFI_OPEN_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)), EFI_HANDLE, EFI_HANDLE, UINT32) -EFI_CLOSE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), EFI_HANDLE, EFI_HANDLE) -EFI_OPEN_PROTOCOL_INFORMATION = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)), PTR(UINTN)) -EFI_PROTOCOLS_PER_HANDLE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(PTR(PTR(EFI_GUID))), PTR(UINTN)) -EFI_LOCATE_HANDLE_BUFFER = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(PTR(EFI_HANDLE))) -EFI_LOCATE_PROTOCOL = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID))) -EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE)) # ... -EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, EFI_HANDLE) # ... -EFI_CALCULATE_CRC32 = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(UINT32)) -EFI_COPY_MEM = FUNCPTR(VOID, PTR(VOID), PTR(VOID), UINTN) -EFI_SET_MEM = FUNCPTR(VOID, PTR(VOID), UINTN, UINT8) -EFI_CREATE_EVENT_EX = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_GUID), PTR(EFI_EVENT)) +EFI_RAISE_TPL = FUNCPTR(EFI_TPL, EFI_TPL) +EFI_RESTORE_TPL = FUNCPTR(VOID, EFI_TPL) +EFI_ALLOCATE_PAGES = FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS)) +EFI_FREE_PAGES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN) +EFI_GET_MEMORY_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(EFI_MEMORY_DESCRIPTOR), PTR(UINTN), PTR(UINTN), PTR(UINT32)) +EFI_ALLOCATE_POOL = FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID))) +EFI_FREE_POOL = FUNCPTR(EFI_STATUS, PTR(VOID)) +EFI_CREATE_EVENT = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_EVENT)) +EFI_SET_TIMER = FUNCPTR(EFI_STATUS, EFI_EVENT, EFI_TIMER_DELAY, UINT64) +EFI_WAIT_FOR_EVENT = FUNCPTR(EFI_STATUS, UINTN, PTR(EFI_EVENT), PTR(UINTN)) +EFI_SIGNAL_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) +EFI_CLOSE_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) +EFI_CHECK_EVENT = FUNCPTR(EFI_STATUS, EFI_EVENT) +EFI_INSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID)) +EFI_REINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID), PTR(VOID)) +EFI_UNINSTALL_PROTOCOL_INTERFACE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(VOID)) +EFI_HANDLE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID))) +EFI_REGISTER_PROTOCOL_NOTIFY = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_EVENT, PTR(PTR(VOID))) +EFI_LOCATE_HANDLE = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE)) +EFI_LOCATE_DEVICE_PATH = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)), PTR(EFI_HANDLE)) +EFI_INSTALL_CONFIGURATION_TABLE = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID)) +EFI_IMAGE_LOAD = FUNCPTR(EFI_STATUS, BOOLEAN, EFI_HANDLE, PTR(EFI_DEVICE_PATH_PROTOCOL), PTR(VOID) , UINTN, PTR(EFI_HANDLE)) +EFI_IMAGE_START = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(UINTN), PTR(PTR(CHAR16))) +EFI_EXIT = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_STATUS, UINTN, PTR(CHAR16)) +EFI_IMAGE_UNLOAD = FUNCPTR(EFI_STATUS, EFI_HANDLE) +EFI_EXIT_BOOT_SERVICES = FUNCPTR(EFI_STATUS, EFI_HANDLE, UINTN) +EFI_GET_NEXT_MONOTONIC_COUNT = FUNCPTR(EFI_STATUS, PTR(UINT64)) +EFI_STALL = FUNCPTR(EFI_STATUS, UINTN) +EFI_SET_WATCHDOG_TIMER = FUNCPTR(EFI_STATUS, UINTN, UINT64, UINTN, PTR(CHAR16)) +EFI_CONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_HANDLE), PTR(EFI_DEVICE_PATH_PROTOCOL), BOOLEAN) +EFI_DISCONNECT_CONTROLLER = FUNCPTR(EFI_STATUS, EFI_HANDLE, EFI_HANDLE, EFI_HANDLE) +EFI_OPEN_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(VOID)), EFI_HANDLE, EFI_HANDLE, UINT32) +EFI_CLOSE_PROTOCOL = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), EFI_HANDLE, EFI_HANDLE) +EFI_OPEN_PROTOCOL_INFORMATION = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID), PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)), PTR(UINTN)) +EFI_PROTOCOLS_PER_HANDLE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(PTR(PTR(EFI_GUID))), PTR(UINTN)) +EFI_LOCATE_HANDLE_BUFFER = FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(PTR(EFI_HANDLE))) +EFI_LOCATE_PROTOCOL = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID))) +EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE)) # ... +EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES = FUNCPTR(EFI_STATUS, EFI_HANDLE) # ... +EFI_CALCULATE_CRC32 = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(UINT32)) +EFI_COPY_MEM = FUNCPTR(VOID, PTR(VOID), PTR(VOID), UINTN) +EFI_SET_MEM = FUNCPTR(VOID, PTR(VOID), UINTN, UINT8) +EFI_CREATE_EVENT_EX = FUNCPTR(EFI_STATUS, UINT32, EFI_TPL, EFI_EVENT_NOTIFY, PTR(VOID), PTR(EFI_GUID), PTR(EFI_EVENT)) class EFI_BOOT_SERVICES(STRUCT): _fields_ = [ - ('Hdr', EFI_TABLE_HEADER), - ('RaiseTPL', EFI_RAISE_TPL), - ('RestoreTPL', EFI_RESTORE_TPL), - ('AllocatePages', EFI_ALLOCATE_PAGES), - ('FreePages', EFI_FREE_PAGES), - ('GetMemoryMap', EFI_GET_MEMORY_MAP), - ('AllocatePool', EFI_ALLOCATE_POOL), - ('FreePool', EFI_FREE_POOL), - ('CreateEvent', EFI_CREATE_EVENT), - ('SetTimer', EFI_SET_TIMER), - ('WaitForEvent', EFI_WAIT_FOR_EVENT), - ('SignalEvent', EFI_SIGNAL_EVENT), - ('CloseEvent', EFI_CLOSE_EVENT), - ('CheckEvent', EFI_CHECK_EVENT), - ('InstallProtocolInterface', EFI_INSTALL_PROTOCOL_INTERFACE), - ('ReinstallProtocolInterface', EFI_REINSTALL_PROTOCOL_INTERFACE), - ('UninstallProtocolInterface', EFI_UNINSTALL_PROTOCOL_INTERFACE), - ('HandleProtocol', EFI_HANDLE_PROTOCOL), - ('Reserved', PTR(VOID)), - ('RegisterProtocolNotify', EFI_REGISTER_PROTOCOL_NOTIFY), - ('LocateHandle', EFI_LOCATE_HANDLE), - ('LocateDevicePath', EFI_LOCATE_DEVICE_PATH), - ('InstallConfigurationTable', EFI_INSTALL_CONFIGURATION_TABLE), - ('LoadImage', EFI_IMAGE_LOAD), - ('StartImage', EFI_IMAGE_START), - ('Exit', EFI_EXIT), - ('UnloadImage', EFI_IMAGE_UNLOAD), - ('ExitBootServices', EFI_EXIT_BOOT_SERVICES), - ('GetNextMonotonicCount', EFI_GET_NEXT_MONOTONIC_COUNT), - ('Stall', EFI_STALL), - ('SetWatchdogTimer', EFI_SET_WATCHDOG_TIMER), - ('ConnectController', EFI_CONNECT_CONTROLLER), - ('DisconnectController', EFI_DISCONNECT_CONTROLLER), - ('OpenProtocol', EFI_OPEN_PROTOCOL), - ('CloseProtocol', EFI_CLOSE_PROTOCOL), - ('OpenProtocolInformation', EFI_OPEN_PROTOCOL_INFORMATION), - ('ProtocolsPerHandle', EFI_PROTOCOLS_PER_HANDLE), - ('LocateHandleBuffer', EFI_LOCATE_HANDLE_BUFFER), - ('LocateProtocol', EFI_LOCATE_PROTOCOL), - ('InstallMultipleProtocolInterfaces', EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES), - ('UninstallMultipleProtocolInterfaces', EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES), - ('CalculateCrc32', EFI_CALCULATE_CRC32), - ('CopyMem', EFI_COPY_MEM), - ('SetMem', EFI_SET_MEM), - ('CreateEventEx', EFI_CREATE_EVENT_EX) + ('Hdr', EFI_TABLE_HEADER), + ('RaiseTPL', EFI_RAISE_TPL), + ('RestoreTPL', EFI_RESTORE_TPL), + ('AllocatePages', EFI_ALLOCATE_PAGES), + ('FreePages', EFI_FREE_PAGES), + ('GetMemoryMap', EFI_GET_MEMORY_MAP), + ('AllocatePool', EFI_ALLOCATE_POOL), + ('FreePool', EFI_FREE_POOL), + ('CreateEvent', EFI_CREATE_EVENT), + ('SetTimer', EFI_SET_TIMER), + ('WaitForEvent', EFI_WAIT_FOR_EVENT), + ('SignalEvent', EFI_SIGNAL_EVENT), + ('CloseEvent', EFI_CLOSE_EVENT), + ('CheckEvent', EFI_CHECK_EVENT), + ('InstallProtocolInterface', EFI_INSTALL_PROTOCOL_INTERFACE), + ('ReinstallProtocolInterface', EFI_REINSTALL_PROTOCOL_INTERFACE), + ('UninstallProtocolInterface', EFI_UNINSTALL_PROTOCOL_INTERFACE), + ('HandleProtocol', EFI_HANDLE_PROTOCOL), + ('Reserved', PTR(VOID)), + ('RegisterProtocolNotify', EFI_REGISTER_PROTOCOL_NOTIFY), + ('LocateHandle', EFI_LOCATE_HANDLE), + ('LocateDevicePath', EFI_LOCATE_DEVICE_PATH), + ('InstallConfigurationTable', EFI_INSTALL_CONFIGURATION_TABLE), + ('LoadImage', EFI_IMAGE_LOAD), + ('StartImage', EFI_IMAGE_START), + ('Exit', EFI_EXIT), + ('UnloadImage', EFI_IMAGE_UNLOAD), + ('ExitBootServices', EFI_EXIT_BOOT_SERVICES), + ('GetNextMonotonicCount', EFI_GET_NEXT_MONOTONIC_COUNT), + ('Stall', EFI_STALL), + ('SetWatchdogTimer', EFI_SET_WATCHDOG_TIMER), + ('ConnectController', EFI_CONNECT_CONTROLLER), + ('DisconnectController', EFI_DISCONNECT_CONTROLLER), + ('OpenProtocol', EFI_OPEN_PROTOCOL), + ('CloseProtocol', EFI_CLOSE_PROTOCOL), + ('OpenProtocolInformation', EFI_OPEN_PROTOCOL_INFORMATION), + ('ProtocolsPerHandle', EFI_PROTOCOLS_PER_HANDLE), + ('LocateHandleBuffer', EFI_LOCATE_HANDLE_BUFFER), + ('LocateProtocol', EFI_LOCATE_PROTOCOL), + ('InstallMultipleProtocolInterfaces', EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES), + ('UninstallMultipleProtocolInterfaces', EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES), + ('CalculateCrc32', EFI_CALCULATE_CRC32), + ('CopyMem', EFI_COPY_MEM), + ('SetMem', EFI_SET_MEM), + ('CreateEventEx', EFI_CREATE_EVENT_EX) ] class EFI_CONFIGURATION_TABLE(STRUCT): @@ -235,19 +235,19 @@ class EFI_SYSTEM_TABLE(STRUCT): _pack_ = 8 _fields_ = [ - ('Hdr', EFI_TABLE_HEADER), - ('FirmwareVendor', PTR(CHAR16)), - ('FirmwareRevision', UINT32), - ('ConsoleInHandle', EFI_HANDLE), - ('ConIn', PTR(EFI_SIMPLE_TEXT_INPUT_PROTOCOL)), - ('ConsoleOutHandle', EFI_HANDLE), - ('ConOut', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)), - ('StandardErrorHandle', EFI_HANDLE), - ('StdErr', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)), - ('RuntimeServices', PTR(EFI_RUNTIME_SERVICES)), - ('BootServices', PTR(EFI_BOOT_SERVICES)), - ('NumberOfTableEntries', UINTN), - ('ConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)) + ('Hdr', EFI_TABLE_HEADER), + ('FirmwareVendor', PTR(CHAR16)), + ('FirmwareRevision', UINT32), + ('ConsoleInHandle', EFI_HANDLE), + ('ConIn', PTR(EFI_SIMPLE_TEXT_INPUT_PROTOCOL)), + ('ConsoleOutHandle', EFI_HANDLE), + ('ConOut', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)), + ('StandardErrorHandle', EFI_HANDLE), + ('StdErr', PTR(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL)), + ('RuntimeServices', PTR(EFI_RUNTIME_SERVICES)), + ('BootServices', PTR(EFI_BOOT_SERVICES)), + ('NumberOfTableEntries', UINTN), + ('ConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)) ] __all__ = [ diff --git a/qiling/os/uefi/bs.py b/qiling/os/uefi/bs.py index 5c00cc51e..793198995 100644 --- a/qiling/os/uefi/bs.py +++ b/qiling/os/uefi/bs.py @@ -17,11 +17,11 @@ from qiling.os.uefi.protocols import common if TYPE_CHECKING: - from qiling import Qiling + from qiling import Qiling @dxeapi(params = { - "NewTpl" : ULONGLONG # EFI_TPL + "NewTpl": ULONGLONG # EFI_TPL }) def hook_RaiseTPL(ql: Qiling, address: int, params): prev_tpl = ql.loader.tpl @@ -30,16 +30,16 @@ def hook_RaiseTPL(ql: Qiling, address: int, params): return prev_tpl @dxeapi(params = { - "OldTpl": ULONGLONG # EFI_TPL + "OldTpl": ULONGLONG # EFI_TPL }) def hook_RestoreTPL(ql: Qiling, address: int, params): ql.loader.tpl = params["OldTpl"] @dxeapi(params = { - "type" : INT, # EFI_ALLOCATE_TYPE - "MemoryType": INT, # EFI_MEMORY_TYPE - "Pages" : ULONGLONG, # UINTN - "Memory" : POINTER # PTR(EFI_PHYSICAL_ADDRESS) + "type": INT, # EFI_ALLOCATE_TYPE + "MemoryType": INT, # EFI_MEMORY_TYPE + "Pages": ULONGLONG, # UINTN + "Memory": POINTER # PTR(EFI_PHYSICAL_ADDRESS) }) def hook_AllocatePages(ql: Qiling, address: int, params): alloc_size = params["Pages"] * PAGE_SIZE @@ -61,8 +61,8 @@ def hook_AllocatePages(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Memory" : ULONGLONG, # EFI_PHYSICAL_ADDRESS - "Pages" : ULONGLONG # UINTN + "Memory": ULONGLONG, # EFI_PHYSICAL_ADDRESS + "Pages": ULONGLONG # UINTN }) def hook_FreePages(ql: Qiling, address: int, params): address = params["Memory"] @@ -72,19 +72,19 @@ def hook_FreePages(ql: Qiling, address: int, params): return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER @dxeapi(params = { - "MemoryMapSize" : POINTER, # PTR(UINTN) - "MemoryMap" : POINTER, # PTR(EFI_MEMORY_DESCRIPTOR) - "MapKey" : POINTER, # PTR(UINTN) - "DescriptorSize" : POINTER, # PTR(UINTN) - "DescriptorVersion" : POINTER # PTR(UINT32) + "MemoryMapSize": POINTER, # PTR(UINTN) + "MemoryMap": POINTER, # PTR(EFI_MEMORY_DESCRIPTOR) + "MapKey": POINTER, # PTR(UINTN) + "DescriptorSize": POINTER, # PTR(UINTN) + "DescriptorVersion": POINTER # PTR(UINT32) }) def hook_GetMemoryMap(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "PoolType" : INT, # EFI_MEMORY_TYPE - "Size" : INT, # UINTN - "Buffer" : POINTER # PTR(PTR(VOID)) + "PoolType": INT, # EFI_MEMORY_TYPE + "Size": INT, # UINTN + "Buffer": POINTER # PTR(PTR(VOID)) }) def hook_AllocatePool(ql: Qiling, address: int, params): # TODO: allocate memory acording to "PoolType" @@ -97,7 +97,7 @@ def hook_AllocatePool(ql: Qiling, address: int, params): return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES @dxeapi(params = { - "Buffer": POINTER # PTR(VOID) + "Buffer": POINTER # PTR(VOID) }) def hook_FreePool(ql: Qiling, address: int, params): Buffer = params["Buffer"] @@ -107,33 +107,33 @@ def hook_FreePool(ql: Qiling, address: int, params): return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER @dxeapi(params = { - "Type" : UINT, # UINT32 - "NotifyTpl" : UINT, # EFI_TPL - "NotifyFunction": POINTER, # EFI_EVENT_NOTIFY - "NotifyContext" : POINTER, # PTR(VOID) - "Event" : POINTER # PTR(EFI_EVENT) + "Type": UINT, # UINT32 + "NotifyTpl": UINT, # EFI_TPL + "NotifyFunction": POINTER, # EFI_EVENT_NOTIFY + "NotifyContext": POINTER, # PTR(VOID) + "Event": POINTER # PTR(EFI_EVENT) }) def hook_CreateEvent(ql: Qiling, address: int, params): return CreateEvent(ql, params) @dxeapi(params = { - "Event" : POINTER, # EFI_EVENT - "Type" : ULONGLONG, # EFI_TIMER_DELAY - "TriggerTime" : ULONGLONG # UINT64 + "Event": POINTER, # EFI_EVENT + "Type": ULONGLONG, # EFI_TIMER_DELAY + "TriggerTime": ULONGLONG # UINT64 }) def hook_SetTimer(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { "NumberOfEvents": ULONGLONG, # UINTN - "Event" : POINTER, # PTR(EFI_EVENT) - "Index" : POINTER, # PTR(UINTN) + "Event": POINTER, # PTR(EFI_EVENT) + "Index": POINTER, # PTR(UINTN) }) def hook_WaitForEvent(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Event": POINTER # EFI_EVENT + "Event": POINTER # EFI_EVENT }) def hook_SignalEvent(ql: Qiling, address: int, params): event_id = params["Event"] @@ -146,7 +146,7 @@ def hook_SignalEvent(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Event": POINTER # EFI_EVENT + "Event": POINTER # EFI_EVENT }) def hook_CloseEvent(ql: Qiling, address: int, params): event_id = params["Event"] @@ -159,7 +159,7 @@ def hook_CloseEvent(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Event": POINTER # EFI_EVENT + "Event": POINTER # EFI_EVENT }) def hook_CheckEvent(ql: Qiling, address: int, params): event_id = params["Event"] @@ -167,19 +167,19 @@ def hook_CheckEvent(ql: Qiling, address: int, params): return EFI_SUCCESS if ql.loader.events[event_id]["Set"] else EFI_NOT_READY @dxeapi(params = { - "Handle" : POINTER, # PTR(EFI_HANDLE) - "Protocol" : GUID, # PTR(EFI_GUID) - "InterfaceType" : ULONGLONG, # EFI_INTERFACE_TYPE - "Interface" : POINTER, # PTR(VOID) + "Handle": POINTER, # PTR(EFI_HANDLE) + "Protocol": GUID, # PTR(EFI_GUID) + "InterfaceType": ULONGLONG, # EFI_INTERFACE_TYPE + "Interface": POINTER, # PTR(VOID) }) def hook_InstallProtocolInterface(ql: Qiling, address: int, params): return common.InstallProtocolInterface(ql.loader.dxe_context, params) @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "OldInterface" : POINTER, # PTR(VOID) - "NewInterface" : POINTER # PTR(VOID) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "OldInterface": POINTER, # PTR(VOID) + "NewInterface": POINTER # PTR(VOID) }) def hook_ReinstallProtocolInterface(ql: Qiling, address: int, params): handle = params["Handle"] @@ -198,25 +198,25 @@ def hook_ReinstallProtocolInterface(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "Interface" : POINTER # PTR(VOID) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "Interface": POINTER # PTR(VOID) }) def hook_UninstallProtocolInterface(ql: Qiling, address: int, params): return common.UninstallProtocolInterface(ql.loader.dxe_context, params) @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "Interface" : POINTER # PTR(PTR(VOID)) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "Interface": POINTER # PTR(PTR(VOID)) }) def hook_HandleProtocol(ql: Qiling, address: int, params): return common.HandleProtocol(ql.loader.dxe_context, params) @dxeapi(params = { - "Protocol" : GUID, # PTR(EFI_GUID) - "Event" : POINTER, # EFI_EVENT - "Registration" : POINTER # PTR(PTR(VOID)) + "Protocol": GUID, # PTR(EFI_GUID) + "Event": POINTER, # EFI_EVENT + "Registration": POINTER # PTR(PTR(VOID)) }) def hook_RegisterProtocolNotify(ql: Qiling, address: int, params): event = params['Event'] @@ -230,54 +230,54 @@ def hook_RegisterProtocolNotify(ql: Qiling, address: int, params): return EFI_INVALID_PARAMETER @dxeapi(params = { - "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE - "Protocol" : GUID, # PTR(EFI_GUID) - "SearchKey" : POINTER, # PTR(VOID) - "BufferSize": POINTER, # PTR(UINTN) - "Buffer" : POINTER # PTR(EFI_HANDLE) + "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE + "Protocol": GUID, # PTR(EFI_GUID) + "SearchKey": POINTER, # PTR(VOID) + "BufferSize": POINTER, # PTR(UINTN) + "Buffer": POINTER # PTR(EFI_HANDLE) }) def hook_LocateHandle(ql: Qiling, address: int, params): return common.LocateHandle(ql.loader.dxe_context, params) @dxeapi(params = { - "Protocol" : GUID, # PTR(EFI_GUID) - "DevicePath": POINTER, # PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)) - "Device" : POINTER # PTR(EFI_HANDLE) + "Protocol": GUID, # PTR(EFI_GUID) + "DevicePath": POINTER, # PTR(PTR(EFI_DEVICE_PATH_PROTOCOL)) + "Device": POINTER # PTR(EFI_HANDLE) }) def hook_LocateDevicePath(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Guid" : GUID, # PTR(EFI_GUID) - "Table" : POINTER # PTR(VOID) + "Guid": GUID, # PTR(EFI_GUID) + "Table": POINTER # PTR(VOID) }) def hook_InstallConfigurationTable(ql: Qiling, address: int, params): return common.InstallConfigurationTable(ql.loader.dxe_context, params) @dxeapi(params = { - "BootPolicy" : BOOL, # BOOLEAN - "ParentImageHandle" : POINTER, # EFI_HANDLE - "DevicePath" : POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL) - "SourceBuffer" : POINTER, # PTR(VOID) - "SourceSize" : ULONGLONG, # UINTN - "ImageHandle" : POINTER # PTR(EFI_HANDLE) + "BootPolicy": BOOL, # BOOLEAN + "ParentImageHandle": POINTER, # EFI_HANDLE + "DevicePath": POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL) + "SourceBuffer": POINTER, # PTR(VOID) + "SourceSize": ULONGLONG, # UINTN + "ImageHandle": POINTER # PTR(EFI_HANDLE) }) def hook_LoadImage(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ImageHandle" : POINTER, # EFI_HANDLE - "ExitDataSize" : POINTER, # PTR(UINTN) - "ExitData" : POINTER # PTR(PTR(CHAR16)) + "ImageHandle": POINTER, # EFI_HANDLE + "ExitDataSize": POINTER, # PTR(UINTN) + "ExitData": POINTER # PTR(PTR(CHAR16)) }) def hook_StartImage(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ImageHandle" : POINTER, # EFI_HANDLE - "ExitStatus" : ULONGLONG, # EFI_STATUS - "ExitDataSize" : ULONGLONG, # UINTN - "ExitData" : POINTER # PTR(CHAR16) + "ImageHandle": POINTER, # EFI_HANDLE + "ExitStatus": ULONGLONG, # EFI_STATUS + "ExitDataSize": ULONGLONG, # UINTN + "ExitData": POINTER # PTR(CHAR16) }) def hook_Exit(ql: Qiling, address: int, params): ql.emu_stop() @@ -285,25 +285,25 @@ def hook_Exit(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ImageHandle" : POINTER # EFI_HANDLE + "ImageHandle": POINTER # EFI_HANDLE }) def hook_UnloadImage(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ImageHandle" : POINTER, # EFI_HANDLE - "MapKey" : ULONGLONG # UINTN + "ImageHandle": POINTER, # EFI_HANDLE + "MapKey": ULONGLONG # UINTN }) def hook_ExitBootServices(ql: Qiling, address: int, params): ql.emu_stop() - # TODO: cleanup BS tableas and data, and notify signal list gEfiEventExitBootServicesGuid + # TODO: cleanup BS tables and data, and notify signal list gEfiEventExitBootServicesGuid # @see: MdeModulePkg\Core\Dxe\DxeMain\DxeMain.c, CoreExitBootServices return EFI_SUCCESS @dxeapi(params = { - "Count": POINTER # PTR(UINT64) + "Count": POINTER # PTR(UINT64) }) def hook_GetNextMonotonicCount(ql: Qiling, address: int, params): out = params["Count"] @@ -314,80 +314,80 @@ def hook_GetNextMonotonicCount(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Microseconds": ULONGLONG # UINTN + "Microseconds": ULONGLONG # UINTN }) def hook_Stall(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Timeout" : ULONGLONG, # UINTN - "WatchdogCode" : ULONGLONG, # UINT64 - "DataSize" : ULONGLONG, # UINTN - "WatchdogData" : POINTER # PTR(CHAR16) + "Timeout": ULONGLONG, # UINTN + "WatchdogCode": ULONGLONG, # UINT64 + "DataSize": ULONGLONG, # UINTN + "WatchdogData": POINTER # PTR(CHAR16) }) def hook_SetWatchdogTimer(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ControllerHandle" : POINTER, # EFI_HANDLE - "DriverImageHandle" : POINTER, #PTR(EFI_HANDLE) - "RemainingDevicePath" : POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL) - "Recursive" : BOOL # BOOLEAN + "ControllerHandle": POINTER, # EFI_HANDLE + "DriverImageHandle": POINTER, #PTR(EFI_HANDLE) + "RemainingDevicePath": POINTER, # PTR(EFI_DEVICE_PATH_PROTOCOL) + "Recursive": BOOL # BOOLEAN }) def hook_ConnectController(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "ControllerHandle" : POINTER, # EFI_HANDLE - "DriverImageHandle" : POINTER, # EFI_HANDLE - "ChildHandle" : POINTER # EFI_HANDLE + "ControllerHandle": POINTER, # EFI_HANDLE + "DriverImageHandle": POINTER, # EFI_HANDLE + "ChildHandle": POINTER # EFI_HANDLE }) def hook_DisconnectController(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "Interface" : POINTER, # PTR(PTR(VOID)) - "AgentHandle" : POINTER, # EFI_HANDLE - "ControllerHandle" : POINTER, # EFI_HANDLE - "Attributes" : UINT # UINT32 + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "Interface": POINTER, # PTR(PTR(VOID)) + "AgentHandle": POINTER, # EFI_HANDLE + "ControllerHandle": POINTER, # EFI_HANDLE + "Attributes": UINT # UINT32 }) def hook_OpenProtocol(ql: Qiling, address: int, params): return common.LocateProtocol(ql.loader.dxe_context, params) @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "AgentHandle" : POINTER, # EFI_HANDLE - "ControllerHandle" : POINTER # EFI_HANDLE + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "AgentHandle": POINTER, # EFI_HANDLE + "ControllerHandle": POINTER # EFI_HANDLE }) def hook_CloseProtocol(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "EntryBuffer" : POINTER, # PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)) - "EntryCount" : POINTER # PTR(UINTN) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "EntryBuffer": POINTER, # PTR(PTR(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY)) + "EntryCount": POINTER # PTR(UINTN) }) def hook_OpenProtocolInformation(ql: Qiling, address: int, params): return EFI_NOT_FOUND @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "ProtocolBuffer" : POINTER, # PTR(PTR(PTR(EFI_GUID))) - "ProtocolBufferCount" : POINTER # PTR(UINTN) + "Handle": POINTER, # EFI_HANDLE + "ProtocolBuffer": POINTER, # PTR(PTR(PTR(EFI_GUID))) + "ProtocolBufferCount": POINTER # PTR(UINTN) }) def hook_ProtocolsPerHandle(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE - "Protocol" : GUID, # PTR(EFI_GUID) - "SearchKey" : POINTER, # PTR(VOID) - "NoHandles" : POINTER, # PTR(UINTN) - "Buffer" : POINTER # PTR(PTR(EFI_HANDLE)) + "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE + "Protocol": GUID, # PTR(EFI_GUID) + "SearchKey": POINTER, # PTR(VOID) + "NoHandles": POINTER, # PTR(UINTN) + "Buffer": POINTER # PTR(PTR(EFI_HANDLE)) }) def hook_LocateHandleBuffer(ql: Qiling, address: int, params): buffer_size, handles = common.LocateHandles(ql.loader.dxe_context, params) @@ -409,15 +409,15 @@ def hook_LocateHandleBuffer(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Protocol" : GUID, # PTR(EFI_GUID) - "Registration" : POINTER, # PTR(VOID) - "Interface" : POINTER # PTR(PTR(VOID)) + "Protocol": GUID, # PTR(EFI_GUID) + "Registration": POINTER, # PTR(VOID) + "Interface": POINTER # PTR(PTR(VOID)) }) def hook_LocateProtocol(ql: Qiling, address: int, params): return common.LocateProtocol(ql.loader.dxe_context, params) @dxeapi(params = { - "Handle" : POINTER # PTR(EFI_HANDLE) + "Handle": POINTER # PTR(EFI_HANDLE) # ... }) def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): @@ -447,7 +447,7 @@ def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Handle" : POINTER # EFI_HANDLE + "Handle": POINTER # EFI_HANDLE # ... }) def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): @@ -477,9 +477,9 @@ def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Data" : POINTER, # PTR(VOID) - "DataSize" : ULONGLONG, # UINTN - "Crc32" : POINTER # PTR(UINT32) + "Data": POINTER, # PTR(VOID) + "DataSize": ULONGLONG, # UINTN + "Crc32": POINTER # PTR(UINT32) }) def hook_CalculateCrc32(ql: Qiling, address: int, params): data = ql.mem.read(params['Data'], params['DataSize']) @@ -488,9 +488,9 @@ def hook_CalculateCrc32(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Destination" : POINTER, # PTR(VOID) - "Source" : POINTER, # PTR(VOID) - "Length" : SIZE_T # UINTN + "Destination": POINTER, # PTR(VOID) + "Source": POINTER, # PTR(VOID) + "Length": SIZE_T # UINTN }) def hook_CopyMem(ql: Qiling, address: int, params): dst = params["Destination"] @@ -500,9 +500,9 @@ def hook_CopyMem(ql: Qiling, address: int, params): ql.mem.write(dst, bytes(ql.mem.read(src, length))) @dxeapi(params = { - "Buffer": POINTER, # PTR(VOID) - "Size" : SIZE_T, # UINTN - "Value" : BYTE # UINT8 + "Buffer": POINTER, # PTR(VOID) + "Size": SIZE_T, # UINTN + "Value": BYTE # UINT8 }) def hook_SetMem(ql: Qiling, address: int, params): buffer = params["Buffer"] @@ -512,12 +512,12 @@ def hook_SetMem(ql: Qiling, address: int, params): ql.mem.write(buffer, bytes([value]) * size) @dxeapi(params = { - "Type" : UINT, # UINT32 - "NotifyTpl" : ULONGLONG,# EFI_TPL - "NotifyFunction": POINTER, # EFI_EVENT_NOTIFY - "NotifyContext" : POINTER, # PTR(VOID) - "EventGroup" : GUID, # PTR(EFI_GUID) - "Event" : POINTER # PTR(EFI_EVENT) + "Type": UINT, # UINT32 + "NotifyTpl": ULONGLONG, # EFI_TPL + "NotifyFunction": POINTER, # EFI_EVENT_NOTIFY + "NotifyContext": POINTER, # PTR(VOID) + "EventGroup": GUID, # PTR(EFI_GUID) + "Event": POINTER # PTR(EFI_EVENT) }) def hook_CreateEventEx(ql: Qiling, address: int, params): return CreateEvent(ql, params) @@ -526,9 +526,9 @@ def CreateEvent(ql: Qiling, params): event_id = len(ql.loader.events) event_dic = { "NotifyFunction": params["NotifyFunction"], - "CallbackArgs" : [event_id, params["NotifyContext"]], - "Guid" : "", - "Set" : False + "CallbackArgs": [event_id, params["NotifyContext"]], + "Guid": "", + "Set": False } if "EventGroup" in params: @@ -543,51 +543,51 @@ def initialize(ql: Qiling, gBS: int): descriptor = { 'struct' : EFI_BOOT_SERVICES, 'fields' : ( - ('Hdr', None), - ('RaiseTPL', hook_RaiseTPL), - ('RestoreTPL', hook_RestoreTPL), - ('AllocatePages', hook_AllocatePages), - ('FreePages', hook_FreePages), - ('GetMemoryMap', hook_GetMemoryMap), - ('AllocatePool', hook_AllocatePool), - ('FreePool', hook_FreePool), - ('CreateEvent', hook_CreateEvent), - ('SetTimer', hook_SetTimer), - ('WaitForEvent', hook_WaitForEvent), - ('SignalEvent', hook_SignalEvent), - ('CloseEvent', hook_CloseEvent), - ('CheckEvent', hook_CheckEvent), - ('InstallProtocolInterface', hook_InstallProtocolInterface), - ('ReinstallProtocolInterface', hook_ReinstallProtocolInterface), - ('UninstallProtocolInterface', hook_UninstallProtocolInterface), - ('HandleProtocol', hook_HandleProtocol), - ('Reserved', None), - ('RegisterProtocolNotify', hook_RegisterProtocolNotify), - ('LocateHandle', hook_LocateHandle), - ('LocateDevicePath', hook_LocateDevicePath), - ('InstallConfigurationTable', hook_InstallConfigurationTable), - ('LoadImage', hook_LoadImage), - ('StartImage', hook_StartImage), - ('Exit', hook_Exit), - ('UnloadImage', hook_UnloadImage), - ('ExitBootServices', hook_ExitBootServices), - ('GetNextMonotonicCount', hook_GetNextMonotonicCount), - ('Stall', hook_Stall), - ('SetWatchdogTimer', hook_SetWatchdogTimer), - ('ConnectController', hook_ConnectController), - ('DisconnectController', hook_DisconnectController), - ('OpenProtocol', hook_OpenProtocol), - ('CloseProtocol', hook_CloseProtocol), - ('OpenProtocolInformation', hook_OpenProtocolInformation), - ('ProtocolsPerHandle', hook_ProtocolsPerHandle), - ('LocateHandleBuffer', hook_LocateHandleBuffer), - ('LocateProtocol', hook_LocateProtocol), - ('InstallMultipleProtocolInterfaces', hook_InstallMultipleProtocolInterfaces), - ('UninstallMultipleProtocolInterfaces', hook_UninstallMultipleProtocolInterfaces), - ('CalculateCrc32', hook_CalculateCrc32), - ('CopyMem', hook_CopyMem), - ('SetMem', hook_SetMem), - ('CreateEventEx', hook_CreateEventEx) + ('Hdr', None), + ('RaiseTPL', hook_RaiseTPL), + ('RestoreTPL', hook_RestoreTPL), + ('AllocatePages', hook_AllocatePages), + ('FreePages', hook_FreePages), + ('GetMemoryMap', hook_GetMemoryMap), + ('AllocatePool', hook_AllocatePool), + ('FreePool', hook_FreePool), + ('CreateEvent', hook_CreateEvent), + ('SetTimer', hook_SetTimer), + ('WaitForEvent', hook_WaitForEvent), + ('SignalEvent', hook_SignalEvent), + ('CloseEvent', hook_CloseEvent), + ('CheckEvent', hook_CheckEvent), + ('InstallProtocolInterface', hook_InstallProtocolInterface), + ('ReinstallProtocolInterface', hook_ReinstallProtocolInterface), + ('UninstallProtocolInterface', hook_UninstallProtocolInterface), + ('HandleProtocol', hook_HandleProtocol), + ('Reserved', None), + ('RegisterProtocolNotify', hook_RegisterProtocolNotify), + ('LocateHandle', hook_LocateHandle), + ('LocateDevicePath', hook_LocateDevicePath), + ('InstallConfigurationTable', hook_InstallConfigurationTable), + ('LoadImage', hook_LoadImage), + ('StartImage', hook_StartImage), + ('Exit', hook_Exit), + ('UnloadImage', hook_UnloadImage), + ('ExitBootServices', hook_ExitBootServices), + ('GetNextMonotonicCount', hook_GetNextMonotonicCount), + ('Stall', hook_Stall), + ('SetWatchdogTimer', hook_SetWatchdogTimer), + ('ConnectController', hook_ConnectController), + ('DisconnectController', hook_DisconnectController), + ('OpenProtocol', hook_OpenProtocol), + ('CloseProtocol', hook_CloseProtocol), + ('OpenProtocolInformation', hook_OpenProtocolInformation), + ('ProtocolsPerHandle', hook_ProtocolsPerHandle), + ('LocateHandleBuffer', hook_LocateHandleBuffer), + ('LocateProtocol', hook_LocateProtocol), + ('InstallMultipleProtocolInterfaces', hook_InstallMultipleProtocolInterfaces), + ('UninstallMultipleProtocolInterfaces', hook_UninstallMultipleProtocolInterfaces), + ('CalculateCrc32', hook_CalculateCrc32), + ('CopyMem', hook_CopyMem), + ('SetMem', hook_SetMem), + ('CreateEventEx', hook_CreateEventEx) ) } diff --git a/qiling/os/uefi/const.py b/qiling/os/uefi/const.py index b4d0704a3..cc95b07ec 100644 --- a/qiling/os/uefi/const.py +++ b/qiling/os/uefi/const.py @@ -1,46 +1,46 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # EFI_MAX_BIT = (1 << 63) EFI_SUCCESS = 0 -EFI_LOAD_ERROR = EFI_MAX_BIT | 1 -EFI_INVALID_PARAMETER = EFI_MAX_BIT | 2 -EFI_UNSUPPORTED = EFI_MAX_BIT | 3 -EFI_BAD_BUFFER_SIZE = EFI_MAX_BIT | 4 -EFI_BUFFER_TOO_SMALL = EFI_MAX_BIT | 5 -EFI_NOT_READY = EFI_MAX_BIT | 6 -EFI_DEVICE_ERROR = EFI_MAX_BIT | 7 -EFI_WRITE_PROTECTED = EFI_MAX_BIT | 8 -EFI_OUT_OF_RESOURCES = EFI_MAX_BIT | 9 -EFI_VOLUME_CORRUPTED = EFI_MAX_BIT | 10 -EFI_VOLUME_FULL = EFI_MAX_BIT | 11 -EFI_NO_MEDIA = EFI_MAX_BIT | 12 -EFI_MEDIA_CHANGED = EFI_MAX_BIT | 13 -EFI_NOT_FOUND = EFI_MAX_BIT | 14 -EFI_ACCESS_DENIED = EFI_MAX_BIT | 15 -EFI_NO_RESPONSE = EFI_MAX_BIT | 16 -EFI_NO_MAPPING = EFI_MAX_BIT | 17 -EFI_TIMEOUT = EFI_MAX_BIT | 18 -EFI_NOT_STARTED = EFI_MAX_BIT | 19 -EFI_ALREADY_STARTED = EFI_MAX_BIT | 20 -EFI_ABORTED = EFI_MAX_BIT | 21 -EFI_ICMP_ERROR = EFI_MAX_BIT | 22 -EFI_TFTP_ERROR = EFI_MAX_BIT | 23 -EFI_PROTOCOL_ERROR = EFI_MAX_BIT | 24 -EFI_INCOMPATIBLE_VERSION = EFI_MAX_BIT | 25 -EFI_SECURITY_VIOLATION = EFI_MAX_BIT | 26 -EFI_CRC_ERROR = EFI_MAX_BIT | 27 -EFI_END_OF_MEDIA = EFI_MAX_BIT | 28 -EFI_END_OF_FILE = EFI_MAX_BIT | 31 -EFI_INVALID_LANGUAGE = EFI_MAX_BIT | 32 +EFI_LOAD_ERROR = EFI_MAX_BIT | 1 +EFI_INVALID_PARAMETER = EFI_MAX_BIT | 2 +EFI_UNSUPPORTED = EFI_MAX_BIT | 3 +EFI_BAD_BUFFER_SIZE = EFI_MAX_BIT | 4 +EFI_BUFFER_TOO_SMALL = EFI_MAX_BIT | 5 +EFI_NOT_READY = EFI_MAX_BIT | 6 +EFI_DEVICE_ERROR = EFI_MAX_BIT | 7 +EFI_WRITE_PROTECTED = EFI_MAX_BIT | 8 +EFI_OUT_OF_RESOURCES = EFI_MAX_BIT | 9 +EFI_VOLUME_CORRUPTED = EFI_MAX_BIT | 10 +EFI_VOLUME_FULL = EFI_MAX_BIT | 11 +EFI_NO_MEDIA = EFI_MAX_BIT | 12 +EFI_MEDIA_CHANGED = EFI_MAX_BIT | 13 +EFI_NOT_FOUND = EFI_MAX_BIT | 14 +EFI_ACCESS_DENIED = EFI_MAX_BIT | 15 +EFI_NO_RESPONSE = EFI_MAX_BIT | 16 +EFI_NO_MAPPING = EFI_MAX_BIT | 17 +EFI_TIMEOUT = EFI_MAX_BIT | 18 +EFI_NOT_STARTED = EFI_MAX_BIT | 19 +EFI_ALREADY_STARTED = EFI_MAX_BIT | 20 +EFI_ABORTED = EFI_MAX_BIT | 21 +EFI_ICMP_ERROR = EFI_MAX_BIT | 22 +EFI_TFTP_ERROR = EFI_MAX_BIT | 23 +EFI_PROTOCOL_ERROR = EFI_MAX_BIT | 24 +EFI_INCOMPATIBLE_VERSION = EFI_MAX_BIT | 25 +EFI_SECURITY_VIOLATION = EFI_MAX_BIT | 26 +EFI_CRC_ERROR = EFI_MAX_BIT | 27 +EFI_END_OF_MEDIA = EFI_MAX_BIT | 28 +EFI_END_OF_FILE = EFI_MAX_BIT | 31 +EFI_INVALID_LANGUAGE = EFI_MAX_BIT | 32 -EFI_WARN_UNKNOWN_GLYPH = EFI_MAX_BIT | 1 -EFI_WARN_DELETE_FAILURE = EFI_MAX_BIT | 2 -EFI_WARN_WRITE_FAILURE = EFI_MAX_BIT | 3 -EFI_WARN_BUFFER_TOO_SMALL = EFI_MAX_BIT | 4 +EFI_WARN_UNKNOWN_GLYPH = EFI_MAX_BIT | 1 +EFI_WARN_DELETE_FAILURE = EFI_MAX_BIT | 2 +EFI_WARN_WRITE_FAILURE = EFI_MAX_BIT | 3 +EFI_WARN_BUFFER_TOO_SMALL = EFI_MAX_BIT | 4 # @see: MdePkg\Include\Base.h EFI_ERROR = lambda status: (status & EFI_MAX_BIT) != 0 diff --git a/qiling/os/uefi/ds.py b/qiling/os/uefi/ds.py index ada10b1d7..5665ecbcf 100644 --- a/qiling/os/uefi/ds.py +++ b/qiling/os/uefi/ds.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -28,13 +28,13 @@ class EFI_GCD_MEMORY_SPACE_DESCRIPTOR(STRUCT): _pack_ = 8 _fields_ = [ - ('BaseAddress', EFI_PHYSICAL_ADDRESS), - ('Length', UINT64), - ('Capabilities', UINT64), - ('Attributes', UINT64), - ('GcdMemoryType', EFI_GCD_MEMORY_TYPE), - ('ImageHandle', EFI_HANDLE), - ('DeviceHandle', EFI_HANDLE) + ('BaseAddress', EFI_PHYSICAL_ADDRESS), + ('Length', UINT64), + ('Capabilities', UINT64), + ('Attributes', UINT64), + ('GcdMemoryType', EFI_GCD_MEMORY_TYPE), + ('ImageHandle', EFI_HANDLE), + ('DeviceHandle', EFI_HANDLE) ] class EFI_GCD_IO_TYPE(ENUM): @@ -49,11 +49,11 @@ class EFI_GCD_IO_SPACE_DESCRIPTOR(STRUCT): _pack_ = 8 _fields_ = [ - ('BaseAddress', EFI_PHYSICAL_ADDRESS), - ('Length', UINT64), - ('GcdIoType', EFI_GCD_IO_TYPE), - ('ImageHandle', EFI_HANDLE), - ('DeviceHandle', EFI_HANDLE) + ('BaseAddress', EFI_PHYSICAL_ADDRESS), + ('Length', UINT64), + ('GcdIoType', EFI_GCD_IO_TYPE), + ('ImageHandle', EFI_HANDLE), + ('DeviceHandle', EFI_HANDLE) ] class EFI_GCD_ALLOCATE_TYPE(ENUM): @@ -66,46 +66,46 @@ class EFI_GCD_ALLOCATE_TYPE(ENUM): 'EfiGcdMaxAllocateType' ] -EFI_ADD_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_MEMORY_TYPE, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) -EFI_ALLOCATE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_MEMORY_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE) -EFI_FREE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) -EFI_REMOVE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) -EFI_GET_MEMORY_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)) -EFI_SET_MEMORY_SPACE_ATTRIBUTES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) -EFI_GET_MEMORY_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR))) -EFI_ADD_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_IO_TYPE, EFI_PHYSICAL_ADDRESS, UINT64) -EFI_ALLOCATE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_IO_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE) -EFI_FREE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) -EFI_REMOVE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) -EFI_GET_IO_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_IO_SPACE_DESCRIPTOR)) -EFI_GET_IO_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_IO_SPACE_DESCRIPTOR))) -EFI_DISPATCH = FUNCPTR(EFI_STATUS) -EFI_SCHEDULE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID)) -EFI_TRUST = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID)) -EFI_PROCESS_FIRMWARE_VOLUME = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(EFI_HANDLE)) -EFI_SET_MEMORY_SPACE_CAPABILITIES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) +EFI_ADD_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_MEMORY_TYPE, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) +EFI_ALLOCATE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_MEMORY_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE) +EFI_FREE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) +EFI_REMOVE_MEMORY_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) +EFI_GET_MEMORY_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR)) +EFI_SET_MEMORY_SPACE_ATTRIBUTES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) +EFI_GET_MEMORY_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_MEMORY_SPACE_DESCRIPTOR))) +EFI_ADD_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_IO_TYPE, EFI_PHYSICAL_ADDRESS, UINT64) +EFI_ALLOCATE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_GCD_ALLOCATE_TYPE, EFI_GCD_IO_TYPE, UINTN, UINT64, PTR(EFI_PHYSICAL_ADDRESS), EFI_HANDLE, EFI_HANDLE) +EFI_FREE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) +EFI_REMOVE_IO_SPACE = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64) +EFI_GET_IO_SPACE_DESCRIPTOR = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, PTR(EFI_GCD_IO_SPACE_DESCRIPTOR)) +EFI_GET_IO_SPACE_MAP = FUNCPTR(EFI_STATUS, PTR(UINTN), PTR(PTR(EFI_GCD_IO_SPACE_DESCRIPTOR))) +EFI_DISPATCH = FUNCPTR(EFI_STATUS) +EFI_SCHEDULE = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID)) +EFI_TRUST = FUNCPTR(EFI_STATUS, EFI_HANDLE, PTR(EFI_GUID)) +EFI_PROCESS_FIRMWARE_VOLUME = FUNCPTR(EFI_STATUS, PTR(VOID), UINTN, PTR(EFI_HANDLE)) +EFI_SET_MEMORY_SPACE_CAPABILITIES = FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINT64, UINT64) class EFI_DXE_SERVICES(STRUCT): _fields_ = [ - ('Hdr', EFI_TABLE_HEADER), - ('AddMemorySpace', EFI_ADD_MEMORY_SPACE), - ('AllocateMemorySpace', EFI_ALLOCATE_MEMORY_SPACE), - ('FreeMemorySpace', EFI_FREE_MEMORY_SPACE), - ('RemoveMemorySpace', EFI_REMOVE_MEMORY_SPACE), - ('GetMemorySpaceDescriptor', EFI_GET_MEMORY_SPACE_DESCRIPTOR), - ('SetMemorySpaceAttributes', EFI_SET_MEMORY_SPACE_ATTRIBUTES), - ('GetMemorySpaceMap', EFI_GET_MEMORY_SPACE_MAP), - ('AddIoSpace', EFI_ADD_IO_SPACE), - ('AllocateIoSpace', EFI_ALLOCATE_IO_SPACE), - ('FreeIoSpace', EFI_FREE_IO_SPACE), - ('RemoveIoSpace', EFI_REMOVE_IO_SPACE), - ('GetIoSpaceDescriptor', EFI_GET_IO_SPACE_DESCRIPTOR), - ('GetIoSpaceMap', EFI_GET_IO_SPACE_MAP), - ('Dispatch', EFI_DISPATCH), - ('Schedule', EFI_SCHEDULE), - ('Trust', EFI_TRUST), - ('ProcessFirmwareVolume', EFI_PROCESS_FIRMWARE_VOLUME), - ('SetMemorySpaceCapabilities', EFI_SET_MEMORY_SPACE_CAPABILITIES) + ('Hdr', EFI_TABLE_HEADER), + ('AddMemorySpace', EFI_ADD_MEMORY_SPACE), + ('AllocateMemorySpace', EFI_ALLOCATE_MEMORY_SPACE), + ('FreeMemorySpace', EFI_FREE_MEMORY_SPACE), + ('RemoveMemorySpace', EFI_REMOVE_MEMORY_SPACE), + ('GetMemorySpaceDescriptor', EFI_GET_MEMORY_SPACE_DESCRIPTOR), + ('SetMemorySpaceAttributes', EFI_SET_MEMORY_SPACE_ATTRIBUTES), + ('GetMemorySpaceMap', EFI_GET_MEMORY_SPACE_MAP), + ('AddIoSpace', EFI_ADD_IO_SPACE), + ('AllocateIoSpace', EFI_ALLOCATE_IO_SPACE), + ('FreeIoSpace', EFI_FREE_IO_SPACE), + ('RemoveIoSpace', EFI_REMOVE_IO_SPACE), + ('GetIoSpaceDescriptor', EFI_GET_IO_SPACE_DESCRIPTOR), + ('GetIoSpaceMap', EFI_GET_IO_SPACE_MAP), + ('Dispatch', EFI_DISPATCH), + ('Schedule', EFI_SCHEDULE), + ('Trust', EFI_TRUST), + ('ProcessFirmwareVolume', EFI_PROCESS_FIRMWARE_VOLUME), + ('SetMemorySpaceCapabilities', EFI_SET_MEMORY_SPACE_CAPABILITIES) ] @dxeapi(params={ @@ -122,9 +122,9 @@ def hook_AddMemorySpace(ctx, address, params): "a1": ULONGLONG, "a2": ULONGLONG, "a3": ULONGLONG, - "a4": POINTER, #POINTER_T(ctypes.c_uint64) - "a5": POINTER, #POINTER_T(None) - "a6": POINTER, #POINTER_T(None) + "a4": POINTER, # POINTER_T(ctypes.c_uint64) + "a5": POINTER, # POINTER_T(None) + "a6": POINTER, # POINTER_T(None) }) def hook_AllocateMemorySpace(ctx, address, params): return EFI_OUT_OF_RESOURCES @@ -145,7 +145,7 @@ def hook_RemoveMemorySpace(ctx, address, params): @dxeapi(params={ "a0": ULONGLONG, - "a1": POINTER, #POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR) + "a1": POINTER, # POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR) }) def hook_GetMemorySpaceDescriptor(ctx, address, params): return EFI_UNSUPPORTED @@ -159,8 +159,8 @@ def hook_SetMemorySpaceAttributes(ctx, address, params): return EFI_UNSUPPORTED @dxeapi(params={ - "a0": POINTER, #POINTER_T(ctypes.c_uint64) - "a1": POINTER, #POINTER_T(POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR)) + "a0": POINTER, # POINTER_T(ctypes.c_uint64) + "a1": POINTER, # POINTER_T(POINTER_T(struct_EFI_GCD_MEMORY_SPACE_DESCRIPTOR)) }) def hook_GetMemorySpaceMap(ctx, address, params): return EFI_UNSUPPORTED @@ -178,9 +178,9 @@ def hook_AddIoSpace(ctx, address, params): "a1": ULONGLONG, "a2": ULONGLONG, "a3": ULONGLONG, - "a4": POINTER, #POINTER_T(ctypes.c_uint64) - "a5": POINTER, #POINTER_T(None) - "a6": POINTER, #POINTER_T(None) + "a4": POINTER, # POINTER_T(ctypes.c_uint64) + "a5": POINTER, # POINTER_T(None) + "a6": POINTER, # POINTER_T(None) }) def hook_AllocateIoSpace(ctx, address, params): return EFI_OUT_OF_RESOURCES @@ -201,14 +201,14 @@ def hook_RemoveIoSpace(ctx, address, params): @dxeapi(params={ "a0": ULONGLONG, - "a1": POINTER, #POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR) + "a1": POINTER, # POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR) }) def hook_GetIoSpaceDescriptor(ctx, address, params): return EFI_NOT_FOUND @dxeapi(params={ - "a0": POINTER, #POINTER_T(ctypes.c_uint64) - "a1": POINTER, #POINTER_T(POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR)) + "a0": POINTER, # POINTER_T(ctypes.c_uint64) + "a1": POINTER, # POINTER_T(POINTER_T(struct_EFI_GCD_IO_SPACE_DESCRIPTOR)) }) def hook_GetIoSpaceMap(ctx, address, params): return EFI_OUT_OF_RESOURCES @@ -219,23 +219,23 @@ def hook_Dispatch(ctx, address, params): return EFI_SUCCESS @dxeapi(params={ - "a0": POINTER, #POINTER_T(None) + "a0": POINTER, # POINTER_T(None) "a1": GUID, }) def hook_Schedule(ctx, address, params): return EFI_SUCCESS @dxeapi(params={ - "a0": POINTER, #POINTER_T(None) + "a0": POINTER, # POINTER_T(None) "a1": GUID, }) def hook_Trust(ctx, address, params): return EFI_NOT_FOUND @dxeapi(params={ - "a0": POINTER, #POINTER_T(None) + "a0": POINTER, # POINTER_T(None) "a1": ULONGLONG, - "a2": POINTER, #POINTER_T(POINTER_T(None)) + "a2": POINTER, # POINTER_T(POINTER_T(None)) }) def hook_ProcessFirmwareVolume(ctx, address, params): return EFI_OUT_OF_RESOURCES @@ -252,25 +252,25 @@ def initialize(ql: Qiling, gDS: int): descriptor = { 'struct' : EFI_DXE_SERVICES, 'fields' : ( - ('Hdr', None), - ('AddMemorySpace', hook_AddMemorySpace), - ('AllocateMemorySpace', hook_AllocateMemorySpace), - ('FreeMemorySpace', hook_FreeMemorySpace), - ('RemoveMemorySpace', hook_RemoveMemorySpace), - ('GetMemorySpaceDescriptor', hook_GetMemorySpaceDescriptor), - ('SetMemorySpaceAttributes', hook_SetMemorySpaceAttributes), - ('GetMemorySpaceMap', hook_GetMemorySpaceMap), - ('AddIoSpace', hook_AddIoSpace), - ('AllocateIoSpace', hook_AllocateIoSpace), - ('FreeIoSpace', hook_FreeIoSpace), - ('RemoveIoSpace', hook_RemoveIoSpace), - ('GetIoSpaceDescriptor', hook_GetIoSpaceDescriptor), - ('GetIoSpaceMap', hook_GetIoSpaceMap), - ('Dispatch', hook_Dispatch), - ('Schedule', hook_Schedule), - ('Trust', hook_Trust), - ('ProcessFirmwareVolume', hook_ProcessFirmwareVolume), - ('SetMemorySpaceCapabilities', hook_SetMemorySpaceCapabilities) + ('Hdr', None), + ('AddMemorySpace', hook_AddMemorySpace), + ('AllocateMemorySpace', hook_AllocateMemorySpace), + ('FreeMemorySpace', hook_FreeMemorySpace), + ('RemoveMemorySpace', hook_RemoveMemorySpace), + ('GetMemorySpaceDescriptor', hook_GetMemorySpaceDescriptor), + ('SetMemorySpaceAttributes', hook_SetMemorySpaceAttributes), + ('GetMemorySpaceMap', hook_GetMemorySpaceMap), + ('AddIoSpace', hook_AddIoSpace), + ('AllocateIoSpace', hook_AllocateIoSpace), + ('FreeIoSpace', hook_FreeIoSpace), + ('RemoveIoSpace', hook_RemoveIoSpace), + ('GetIoSpaceDescriptor', hook_GetIoSpaceDescriptor), + ('GetIoSpaceMap', hook_GetIoSpaceMap), + ('Dispatch', hook_Dispatch), + ('Schedule', hook_Schedule), + ('Trust', hook_Trust), + ('ProcessFirmwareVolume', hook_ProcessFirmwareVolume), + ('SetMemorySpaceCapabilities', hook_SetMemorySpaceCapabilities) ) } diff --git a/qiling/os/uefi/hob.py b/qiling/os/uefi/hob.py index a1a07f0f9..c0df98e33 100644 --- a/qiling/os/uefi/hob.py +++ b/qiling/os/uefi/hob.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -9,20 +9,20 @@ from qiling.os.uefi.UefiBaseType import STRUCT, EFI_GUID, UINT32, UINT16 EFI_HOB_TYPE_HANDOFF = 0x0001 -EFI_HOB_TYPE_GUID_EXTENSION = 0x0004 +EFI_HOB_TYPE_GUID_EXTENSION = 0x0004 EFI_HOB_TYPE_END_OF_HOB_LIST = 0xffff class EFI_HOB_GENERIC_HEADER(STRUCT): _fields_ = [ - ('HobType', UINT16), - ('HobLength', UINT16), - ('Reserved', UINT32) + ('HobType', UINT16), + ('HobLength', UINT16), + ('Reserved', UINT32) ] class EFI_HOB_GUID_TYPE(STRUCT): _fields_ = [ - ('Header', EFI_HOB_GENERIC_HEADER), - ('Name', EFI_GUID) + ('Header', EFI_HOB_GENERIC_HEADER), + ('Name', EFI_GUID) ] def GetHobList(ql: Qiling, context: UefiContext) -> int: diff --git a/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py b/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py index f422cdf5a..ef4245260 100644 --- a/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py +++ b/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -14,17 +14,17 @@ class EFI_LOADED_IMAGE_PROTOCOL(STRUCT): _fields_ = [ ('Revision', UINT32), ('ParentHandle', EFI_HANDLE), - ('SystemTable', PTR(EFI_SYSTEM_TABLE)), + ('SystemTable', PTR(EFI_SYSTEM_TABLE)), ('DeviceHandle', EFI_HANDLE), ('FilePath', PTR(EFI_DEVICE_PATH_PROTOCOL)), - ('Reserved', PTR(VOID)), - ('LoadOptionsSize', UINT32), - ('LoadOptions', PTR(VOID)), - ('ImageBase', PTR(VOID)), - ('ImageSize', UINT64), - ('ImageCodeType', EFI_MEMORY_TYPE), - ('ImageDataType', EFI_MEMORY_TYPE), - ('Unload', EFI_IMAGE_UNLOAD) + ('Reserved', PTR(VOID)), + ('LoadOptionsSize', UINT32), + ('LoadOptions', PTR(VOID)), + ('ImageBase', PTR(VOID)), + ('ImageSize', UINT64), + ('ImageCodeType', EFI_MEMORY_TYPE), + ('ImageDataType', EFI_MEMORY_TYPE), + ('Unload', EFI_IMAGE_UNLOAD) ] def make_descriptor(fields): @@ -34,16 +34,16 @@ def make_descriptor(fields): "fields" : ( ('Revision', 0x1000), ('ParentHandle', 0), - ('SystemTable', fields['gST']), + ('SystemTable', fields['gST']), ('DeviceHandle', fields['image_base']), ('FilePath', 0), # This is a handle to a complex path object, skip it for now. - ('LoadOptionsSize', 0), - ('LoadOptions', 0), - ('ImageBase', fields['image_base']), - ('ImageSize', fields['image_size']), - ('ImageCodeType', EFI_MEMORY_TYPE.EfiLoaderCode), - ('ImageDataType', EFI_MEMORY_TYPE.EfiLoaderData), - ('Unload', 0) + ('LoadOptionsSize', 0), + ('LoadOptions', 0), + ('ImageBase', fields['image_base']), + ('ImageSize', fields['image_size']), + ('ImageCodeType', EFI_MEMORY_TYPE.EfiLoaderCode), + ('ImageDataType', EFI_MEMORY_TYPE.EfiLoaderData), + ('Unload', 0) ) } diff --git a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py index 9e34fe807..3bf81e61d 100644 --- a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py @@ -35,7 +35,7 @@ class EFI_SMM_ACCESS2_PROTOCOL(STRUCT): ] @dxeapi(params = { - "This" : POINTER + "This": POINTER }) def hook_Open(ql: Qiling, address: int, params): ql.loader.smm_context.tseg_open = True @@ -43,7 +43,7 @@ def hook_Open(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "This" : POINTER + "This": POINTER }) def hook_Close(ql: Qiling, address: int, params): ql.loader.smm_context.tseg_open = False @@ -51,7 +51,7 @@ def hook_Close(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "This" : POINTER + "This": POINTER }) def hook_Lock(ql: Qiling, address: int, params): ql.loader.smm_context.tseg_locked = True @@ -80,9 +80,9 @@ def _coalesce(seq): return res @dxeapi(params = { - "This" : POINTER, # PTR(EFI_SMM_ACCESS2_PROTOCOL) - "MmramMapSize" : POINTER, # IN OUT PTR(UINTN) - "MmramMap" : POINTER # OUT PTR(EFI_MMRAM_DESCRIPTOR) + "This": POINTER, # PTR(EFI_SMM_ACCESS2_PROTOCOL) + "MmramMapSize": POINTER, # IN OUT PTR(UINTN) + "MmramMap": POINTER # OUT PTR(EFI_MMRAM_DESCRIPTOR) }) def hook_GetCapabilities(ql: Qiling, address: int, params): heap = ql.loader.smm_context.heap @@ -148,8 +148,8 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): "struct" : EFI_SMM_ACCESS2_PROTOCOL, "fields" : ( ("Open", hook_Open), - ("Close", hook_Close), + ("Close", hook_Close), ("Lock", hook_Lock), - ("GetCapabilities", hook_GetCapabilities) + ("GetCapabilities", hook_GetCapabilities) ) } diff --git a/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py b/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py index a6a567d1c..7b2c80847 100644 --- a/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmBase2Protocol.py @@ -17,13 +17,13 @@ class EFI_SMM_BASE2_PROTOCOL(STRUCT): EFI_SMM_BASE2_PROTOCOL = STRUCT _fields_ = [ - ('InSmm', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(BOOLEAN))), - ('GetSmstLocation', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(PTR(EFI_SMM_SYSTEM_TABLE2)))), + ('InSmm', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(BOOLEAN))), + ('GetSmstLocation', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_BASE2_PROTOCOL), PTR(PTR(EFI_SMM_SYSTEM_TABLE2)))), ] @dxeapi(params = { - "This" : POINTER, - "InSmram" : POINTER + "This": POINTER, + "InSmram": POINTER }) def hook_InSmm(ql: Qiling, address: int, params): ql.log.debug(f'InSmram = {ql.os.smm.active}') @@ -33,8 +33,8 @@ def hook_InSmm(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "This" : POINTER, - "Smst" : POINTER + "This": POINTER, + "Smst": POINTER }) def hook_GetSmstLocation(ql: Qiling, address: int, params): Smst = params["Smst"] @@ -50,7 +50,7 @@ def hook_GetSmstLocation(ql: Qiling, address: int, params): "guid" : "f4ccbfb7-f6e0-47fd-9dd4-10a8f150c191", "struct" : EFI_SMM_BASE2_PROTOCOL, "fields" : ( - ("InSmm", hook_InSmm), - ("GetSmstLocation", hook_GetSmstLocation) + ("InSmm", hook_InSmm), + ("GetSmstLocation", hook_GetSmstLocation) ) } diff --git a/qiling/os/uefi/protocols/EfiSmmCpuProtocol.py b/qiling/os/uefi/protocols/EfiSmmCpuProtocol.py index 3b24ea8ec..d225fa409 100644 --- a/qiling/os/uefi/protocols/EfiSmmCpuProtocol.py +++ b/qiling/os/uefi/protocols/EfiSmmCpuProtocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -12,96 +12,96 @@ # @see: MdePkg/Include/Protocol/MmCpu.h class EFI_SMM_SAVE_STATE_REGISTER(ENUM_UC): _members_ = { - # note: members names were shorten from 'EFI_SMM_SAVE_STATE_REGISTER_regname' to just 'regname' - 'GDTBASE' : 4, - 'IDTBASE' : 5, - 'LDTBASE' : 6, - 'GDTLIMIT' : 7, - 'IDTLIMIT' : 8, - 'LDTLIMIT' : 9, - 'LDTINFO' : 10, - - 'ES' : 20, - 'CS' : 21, - 'SS' : 22, - 'DS' : 23, - 'FS' : 24, - 'GS' : 25, - 'LDTR_SEL' : 26, - 'TR_SEL' : 27, - 'DR7' : 28, - 'DR6' : 29, - 'R8' : 30, - 'R9' : 31, - 'R10' : 32, - 'R11' : 33, - 'R12' : 34, - 'R13' : 35, - 'R14' : 36, - 'R15' : 37, - 'RAX' : 38, - 'RBX' : 39, - 'RCX' : 40, - 'RDX' : 41, - 'RSP' : 42, - 'RBP' : 43, - 'RSI' : 44, - 'RDI' : 45, - 'RIP' : 46, - - 'RFLAGS' : 51, - 'CR0' : 52, - 'CR3' : 53, - 'CR4' : 54, - - 'FCW' : 256, - 'FSW' : 257, - 'FTW' : 258, - 'OPCODE' : 259, - 'FP_EIP' : 260, - 'FP_CS' : 261, + # note: members names were shorten from 'EFI_SMM_SAVE_STATE_REGISTER_regname' to just 'regname' + 'GDTBASE': 4, + 'IDTBASE': 5, + 'LDTBASE': 6, + 'GDTLIMIT': 7, + 'IDTLIMIT': 8, + 'LDTLIMIT': 9, + 'LDTINFO': 10, + + 'ES': 20, + 'CS': 21, + 'SS': 22, + 'DS': 23, + 'FS': 24, + 'GS': 25, + 'LDTR_SEL': 26, + 'TR_SEL': 27, + 'DR7': 28, + 'DR6': 29, + 'R8': 30, + 'R9': 31, + 'R10': 32, + 'R11': 33, + 'R12': 34, + 'R13': 35, + 'R14': 36, + 'R15': 37, + 'RAX': 38, + 'RBX': 39, + 'RCX': 40, + 'RDX': 41, + 'RSP': 42, + 'RBP': 43, + 'RSI': 44, + 'RDI': 45, + 'RIP': 46, + + 'RFLAGS': 51, + 'CR0': 52, + 'CR3': 53, + 'CR4': 54, + + 'FCW': 256, + 'FSW': 257, + 'FTW': 258, + 'OPCODE': 259, + 'FP_EIP': 260, + 'FP_CS': 261, 'DATAOFFSET': 262, - 'FP_DS' : 263, - 'MM0' : 264, - 'MM1' : 265, - 'MM2' : 266, - 'MM3' : 267, - 'MM4' : 268, - 'MM5' : 269, - 'MM6' : 270, - 'MM7' : 271, - 'XMM0' : 272, - 'XMM1' : 273, - 'XMM2' : 274, - 'XMM3' : 275, - 'XMM4' : 276, - 'XMM5' : 277, - 'XMM6' : 278, - 'XMM7' : 279, - 'XMM8' : 280, - 'XMM9' : 281, - 'XMM10' : 282, - 'XMM11' : 283, - 'XMM12' : 284, - 'XMM13' : 285, - 'XMM14' : 286, - 'XMM15' : 287, - - 'IO' : 512, - 'LMA' : 513, - 'PROCESSOR_ID' : 514 + 'FP_DS': 263, + 'MM0': 264, + 'MM1': 265, + 'MM2': 266, + 'MM3': 267, + 'MM4': 268, + 'MM5': 269, + 'MM6': 270, + 'MM7': 271, + 'XMM0': 272, + 'XMM1': 273, + 'XMM2': 274, + 'XMM3': 275, + 'XMM4': 276, + 'XMM5': 277, + 'XMM6': 278, + 'XMM7': 279, + 'XMM8': 280, + 'XMM9': 281, + 'XMM10': 282, + 'XMM11': 283, + 'XMM12': 284, + 'XMM13': 285, + 'XMM14': 286, + 'XMM15': 287, + + 'IO': 512, + 'LMA': 513, + 'PROCESSOR_ID': 514 } -# EFI_SUCCESS The register was written from Save State -# EFI_NOT_FOUND The register is not defined for the Save State of Processor -# EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct +# EFI_SUCCESS The register was written from Save State +# EFI_NOT_FOUND The register is not defined for the Save State of Processor +# EFI_INVALID_PARAMETER ProcessorIndex or Width is not correct @dxeapi(params = { - "This" : POINTER, # EFI_SMM_CPU_PROTOCOL - "Width" : ULONGLONG,# UINTN - "Register" : INT, # EFI_SMM_SAVE_STATE_REGISTER - "CpuIndex" : ULONGLONG,# UINTN - "Buffer" : POINTER # PTR(VOID) + "This": POINTER, # EFI_SMM_CPU_PROTOCOL + "Width": ULONGLONG, # UINTN + "Register": INT, # EFI_SMM_SAVE_STATE_REGISTER + "CpuIndex": ULONGLONG, # UINTN + "Buffer": POINTER # PTR(VOID) }) def hook_SmmReadSaveState(ql: Qiling, address: int, params): Width = params['Width'] @@ -119,11 +119,11 @@ def hook_SmmReadSaveState(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "This" : POINTER, # EFI_SMM_CPU_PROTOCOL - "Width" : ULONGLONG,# UINTN - "Register" : INT, # EFI_SMM_SAVE_STATE_REGISTER - "CpuIndex" : ULONGLONG,# UINTN - "Buffer" : POINTER # PTR(VOID) + "This": POINTER, # EFI_SMM_CPU_PROTOCOL + "Width": ULONGLONG, # UINTN + "Register": INT, # EFI_SMM_SAVE_STATE_REGISTER + "CpuIndex": ULONGLONG, # UINTN + "Buffer": POINTER # PTR(VOID) }) def hook_SmmWriteSaveState(ql: Qiling, address: int, params): Width = params['Width'] @@ -144,15 +144,15 @@ class EFI_SMM_CPU_PROTOCOL(STRUCT): EFI_SMM_CPU_PROTOCOL = STRUCT _fields_ = [ - ('SmmReadSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))), - ('SmmWriteSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))) + ('SmmReadSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))), + ('SmmWriteSaveState', FUNCPTR(PTR(EFI_SMM_CPU_PROTOCOL), UINTN, EFI_SMM_SAVE_STATE_REGISTER, UINTN, PTR(VOID))) ] descriptor = { "guid" : "eb346b97-975f-4a9f-8b22-f8e92bb3d569", "struct" : EFI_SMM_CPU_PROTOCOL, "fields" : ( - ("SmmReadSaveState", hook_SmmReadSaveState), - ("SmmWriteSaveState", hook_SmmWriteSaveState) + ("SmmReadSaveState", hook_SmmReadSaveState), + ("SmmWriteSaveState", hook_SmmWriteSaveState) ) } diff --git a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py index 008db407a..4596dc162 100644 --- a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py @@ -16,9 +16,9 @@ class EFI_SMM_SW_CONTEXT(STRUCT): _pack_ = 8 _fields_ = [ - ('SwSmiCpuIndex', UINTN), # index of the cpu which generated the swsmi - ('CommandPort', UINT8), # port number used to trigger the swsmi - ('DataPort', UINT8) # irrelevant + ('SwSmiCpuIndex', UINTN), # index of the cpu which generated the swsmi + ('CommandPort', UINT8), # port number used to trigger the swsmi + ('DataPort', UINT8) # irrelevant ] # @file: MdePkg\Include\Protocol\SmmSwDispatch2.h @@ -35,15 +35,15 @@ class EFI_SMM_SW_DISPATCH2_PROTOCOL(STRUCT): _fields_ = [ ('Register', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_SMM_HANDLER_ENTRY_POINT2, PTR(EFI_SMM_SW_REGISTER_CONTEXT), PTR(EFI_HANDLE))), - ('UnRegister', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_HANDLE)), - ('MaximumSwiValue', UINTN) + ('UnRegister', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL), EFI_HANDLE)), + ('MaximumSwiValue', UINTN) ] @dxeapi(params = { - "This" : POINTER, # PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL) - "DispatchFunction" : POINTER, # EFI_SMM_HANDLER_ENTRY_POINT2 - "RegisterContext" : POINTER, # PTR(EFI_SMM_SW_REGISTER_CONTEXT) - "DispatchHandle" : POINTER # PTR(EFI_HANDLE) + "This": POINTER, # PTR(EFI_SMM_SW_DISPATCH2_PROTOCOL) + "DispatchFunction": POINTER, # EFI_SMM_HANDLER_ENTRY_POINT2 + "RegisterContext": POINTER, # PTR(EFI_SMM_SW_REGISTER_CONTEXT) + "DispatchHandle": POINTER # PTR(EFI_HANDLE) }) def hook_Register(ql: Qiling, address: int, params): DispatchFunction: int = params['DispatchFunction'] @@ -83,8 +83,8 @@ def hook_Register(ql: Qiling, address: int, params): ql.mem.write_ptr(DispatchHandle, Handle) args = { - 'DispatchHandle' : Handle, - 'RegisterContext' : SwRegisterContext + 'DispatchHandle': Handle, + 'RegisterContext': SwRegisterContext } handlers[idx] = (DispatchFunction, args) @@ -92,8 +92,8 @@ def hook_Register(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "This" : POINTER, - "DispatchHandle" : POINTER + "This": POINTER, + "DispatchHandle": POINTER }) def hook_UnRegister(ql: Qiling, address: int, params): DispatchHandle: int = params['DispatchHandle'] @@ -116,7 +116,7 @@ def hook_UnRegister(ql: Qiling, address: int, params): "struct" : EFI_SMM_SW_DISPATCH2_PROTOCOL, "fields" : ( ("Register", hook_Register), - ("UnRegister", hook_UnRegister), - ('MaximumSwiValue', MAXIMUM_SWI_VALUE) + ("UnRegister", hook_UnRegister), + ('MaximumSwiValue', MAXIMUM_SWI_VALUE) ) } diff --git a/qiling/os/uefi/protocols/PcdProtocol.py b/qiling/os/uefi/protocols/PcdProtocol.py index e1eaafab9..f8ef5d6a0 100644 --- a/qiling/os/uefi/protocols/PcdProtocol.py +++ b/qiling/os/uefi/protocols/PcdProtocol.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -10,287 +10,287 @@ PCD_PROTOCOL_CALLBACK = FUNCPTR(VOID, PTR(EFI_GUID), UINTN, PTR(VOID), UINTN) -PCD_PROTOCOL_SET_SKU = FUNCPTR(VOID, UINTN) +PCD_PROTOCOL_SET_SKU = FUNCPTR(VOID, UINTN) PCD_PROTOCOL_GET8 = FUNCPTR(UINT8, UINTN) -PCD_PROTOCOL_GET16 = FUNCPTR(UINT16, UINTN) -PCD_PROTOCOL_GET32 = FUNCPTR(UINT32, UINTN) -PCD_PROTOCOL_GET64 = FUNCPTR(UINT64, UINTN) -PCD_PROTOCOL_GET_POINTER = FUNCPTR(PTR(VOID), UINTN) -PCD_PROTOCOL_GET_BOOLEAN = FUNCPTR(BOOLEAN, UINTN) +PCD_PROTOCOL_GET16 = FUNCPTR(UINT16, UINTN) +PCD_PROTOCOL_GET32 = FUNCPTR(UINT32, UINTN) +PCD_PROTOCOL_GET64 = FUNCPTR(UINT64, UINTN) +PCD_PROTOCOL_GET_POINTER = FUNCPTR(PTR(VOID), UINTN) +PCD_PROTOCOL_GET_BOOLEAN = FUNCPTR(BOOLEAN, UINTN) PCD_PROTOCOL_GET_SIZE = FUNCPTR(UINTN, UINTN) PCD_PROTOCOL_GET_EX_8 = FUNCPTR(UINT8, PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_16 = FUNCPTR(UINT16, PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_32 = FUNCPTR(UINT32, PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_64 = FUNCPTR(UINT64, PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_POINTER = FUNCPTR(PTR(VOID), PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_BOOLEAN = FUNCPTR(BOOLEAN, PTR(EFI_GUID), UINTN) -PCD_PROTOCOL_GET_EX_SIZE = FUNCPTR(UINTN, PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_16 = FUNCPTR(UINT16, PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_32 = FUNCPTR(UINT32, PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_64 = FUNCPTR(UINT64, PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_POINTER = FUNCPTR(PTR(VOID), PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_BOOLEAN = FUNCPTR(BOOLEAN, PTR(EFI_GUID), UINTN) +PCD_PROTOCOL_GET_EX_SIZE = FUNCPTR(UINTN, PTR(EFI_GUID), UINTN) PCD_PROTOCOL_SET8 = FUNCPTR(EFI_STATUS, UINTN, UINT8) -PCD_PROTOCOL_SET16 = FUNCPTR(EFI_STATUS, UINTN, UINT16) -PCD_PROTOCOL_SET32 = FUNCPTR(EFI_STATUS, UINTN, UINT32) -PCD_PROTOCOL_SET64 = FUNCPTR(EFI_STATUS, UINTN, UINT64) -PCD_PROTOCOL_SET_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(UINTN), PTR(VOID)) -PCD_PROTOCOL_SET_BOOLEAN = FUNCPTR(EFI_STATUS, UINTN, BOOLEAN) +PCD_PROTOCOL_SET16 = FUNCPTR(EFI_STATUS, UINTN, UINT16) +PCD_PROTOCOL_SET32 = FUNCPTR(EFI_STATUS, UINTN, UINT32) +PCD_PROTOCOL_SET64 = FUNCPTR(EFI_STATUS, UINTN, UINT64) +PCD_PROTOCOL_SET_POINTER = FUNCPTR(EFI_STATUS, UINTN, PTR(UINTN), PTR(VOID)) +PCD_PROTOCOL_SET_BOOLEAN = FUNCPTR(EFI_STATUS, UINTN, BOOLEAN) PCD_PROTOCOL_SET_EX_8 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT8) -PCD_PROTOCOL_SET_EX_16 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT16) -PCD_PROTOCOL_SET_EX_32 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT32) -PCD_PROTOCOL_SET_EX_64 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT64) -PCD_PROTOCOL_SET_EX_POINTER = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PTR(UINTN), PTR(VOID)) -PCD_PROTOCOL_SET_EX_BOOLEAN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, BOOLEAN) -PCD_PROTOCOL_CALLBACK_ONSET = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK) -PCD_PROTOCOL_CANCEL_CALLBACK= FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK) -PCD_PROTOCOL_GET_NEXT_TOKEN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(UINTN)) +PCD_PROTOCOL_SET_EX_16 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT16) +PCD_PROTOCOL_SET_EX_32 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT32) +PCD_PROTOCOL_SET_EX_64 = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, UINT64) +PCD_PROTOCOL_SET_EX_POINTER = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PTR(UINTN), PTR(VOID)) +PCD_PROTOCOL_SET_EX_BOOLEAN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, BOOLEAN) +PCD_PROTOCOL_CALLBACK_ONSET = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK) +PCD_PROTOCOL_CANCEL_CALLBACK = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), UINTN, PCD_PROTOCOL_CALLBACK) +PCD_PROTOCOL_GET_NEXT_TOKEN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(UINTN)) PCD_PROTOCOL_GET_NEXT_TOKENSPACE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_GUID))) class PCD_PROTOCOL(STRUCT): _fields_ = [ - ('SetSku', PCD_PROTOCOL_SET_SKU), - ('Get8', PCD_PROTOCOL_GET8), - ('Get16', PCD_PROTOCOL_GET16), - ('Get32', PCD_PROTOCOL_GET32), - ('Get64', PCD_PROTOCOL_GET64), - ('GetPtr', PCD_PROTOCOL_GET_POINTER), - ('GetBool', PCD_PROTOCOL_GET_BOOLEAN), - ('GetSize', PCD_PROTOCOL_GET_SIZE), - ('Get8Ex', PCD_PROTOCOL_GET_EX_8), - ('Get16Ex', PCD_PROTOCOL_GET_EX_16), - ('Get32Ex', PCD_PROTOCOL_GET_EX_32), - ('Get64Ex', PCD_PROTOCOL_GET_EX_64), - ('GetPtrEx', PCD_PROTOCOL_GET_EX_POINTER), - ('GetBoolEx', PCD_PROTOCOL_GET_EX_BOOLEAN), - ('GetSizeEx', PCD_PROTOCOL_GET_EX_SIZE), - ('Set8', PCD_PROTOCOL_SET8), - ('Set16', PCD_PROTOCOL_SET16), - ('Set32', PCD_PROTOCOL_SET32), - ('Set64', PCD_PROTOCOL_SET64), - ('SetPtr', PCD_PROTOCOL_SET_POINTER), - ('SetBool', PCD_PROTOCOL_SET_BOOLEAN), - ('Set8Ex', PCD_PROTOCOL_SET_EX_8), - ('Set16Ex', PCD_PROTOCOL_SET_EX_16), - ('Set32Ex', PCD_PROTOCOL_SET_EX_32), - ('Set64Ex', PCD_PROTOCOL_SET_EX_64), - ('SetPtrEx', PCD_PROTOCOL_SET_EX_POINTER), - ('SetBoolEx', PCD_PROTOCOL_SET_EX_BOOLEAN), - ('CallbackOnSet', PCD_PROTOCOL_CALLBACK_ONSET), - ('CancelCallback', PCD_PROTOCOL_CANCEL_CALLBACK), - ('GetNextToken', PCD_PROTOCOL_GET_NEXT_TOKEN), - ('GetNextTokenSpace', PCD_PROTOCOL_GET_NEXT_TOKENSPACE) + ('SetSku', PCD_PROTOCOL_SET_SKU), + ('Get8', PCD_PROTOCOL_GET8), + ('Get16', PCD_PROTOCOL_GET16), + ('Get32', PCD_PROTOCOL_GET32), + ('Get64', PCD_PROTOCOL_GET64), + ('GetPtr', PCD_PROTOCOL_GET_POINTER), + ('GetBool', PCD_PROTOCOL_GET_BOOLEAN), + ('GetSize', PCD_PROTOCOL_GET_SIZE), + ('Get8Ex', PCD_PROTOCOL_GET_EX_8), + ('Get16Ex', PCD_PROTOCOL_GET_EX_16), + ('Get32Ex', PCD_PROTOCOL_GET_EX_32), + ('Get64Ex', PCD_PROTOCOL_GET_EX_64), + ('GetPtrEx', PCD_PROTOCOL_GET_EX_POINTER), + ('GetBoolEx', PCD_PROTOCOL_GET_EX_BOOLEAN), + ('GetSizeEx', PCD_PROTOCOL_GET_EX_SIZE), + ('Set8', PCD_PROTOCOL_SET8), + ('Set16', PCD_PROTOCOL_SET16), + ('Set32', PCD_PROTOCOL_SET32), + ('Set64', PCD_PROTOCOL_SET64), + ('SetPtr', PCD_PROTOCOL_SET_POINTER), + ('SetBool', PCD_PROTOCOL_SET_BOOLEAN), + ('Set8Ex', PCD_PROTOCOL_SET_EX_8), + ('Set16Ex', PCD_PROTOCOL_SET_EX_16), + ('Set32Ex', PCD_PROTOCOL_SET_EX_32), + ('Set64Ex', PCD_PROTOCOL_SET_EX_64), + ('SetPtrEx', PCD_PROTOCOL_SET_EX_POINTER), + ('SetBoolEx', PCD_PROTOCOL_SET_EX_BOOLEAN), + ('CallbackOnSet', PCD_PROTOCOL_CALLBACK_ONSET), + ('CancelCallback', PCD_PROTOCOL_CANCEL_CALLBACK), + ('GetNextToken', PCD_PROTOCOL_GET_NEXT_TOKEN), + ('GetNextTokenSpace', PCD_PROTOCOL_GET_NEXT_TOKENSPACE) ] @dxeapi(params = { - "SkuId" : UINT + "SkuId": UINT }) def hook_SetSku(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_Get8(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_Get16(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_Get32(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_Get64(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_GetPtr(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_GetBool(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT + "TokenNumber": UINT }) def hook_GetSize(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_Get8Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_Get16Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_Get32Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_Get64Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_GetPtrEx(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_GetBoolEx(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT + "Guid": GUID, + "TokenNumber": UINT }) def hook_GetSizeEx(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "Value" : INT + "TokenNumber": UINT, + "Value": INT }) def hook_Set8(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "Value" : INT + "TokenNumber": UINT, + "Value": INT }) def hook_Set16(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "Value" : INT + "TokenNumber": UINT, + "Value": INT }) def hook_Set32(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "Value" : INT + "TokenNumber": UINT, + "Value": INT }) def hook_Set64(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "SizeOfValue" : POINTER, - "Buffer" : POINTER + "TokenNumber": UINT, + "SizeOfValue": POINTER, + "Buffer": POINTER }) def hook_SetPtr(ql, address, params): pass @dxeapi(params = { - "TokenNumber" : UINT, - "Value" : INT + "TokenNumber": UINT, + "Value": INT }) def hook_SetBool(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "Value" : INT + "Guid": GUID, + "TokenNumber": UINT, + "Value": INT }) def hook_Set8Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "Value" : INT + "Guid": GUID, + "TokenNumber": UINT, + "Value": INT }) def hook_Set16Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "Value" : INT + "Guid": GUID, + "TokenNumber": UINT, + "Value": INT }) def hook_Set32Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "Value" : INT + "Guid": GUID, + "TokenNumber": UINT, + "Value": INT }) def hook_Set64Ex(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "SizeOfValue" : POINTER, - "Buffer" : POINTER + "Guid": GUID, + "TokenNumber": UINT, + "SizeOfValue": POINTER, + "Buffer": POINTER }) def hook_SetPtrEx(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "Value" : INT + "Guid": GUID, + "TokenNumber": UINT, + "Value": INT }) def hook_SetBoolEx(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "CallBackFunction" : POINTER + "Guid": GUID, + "TokenNumber": UINT, + "CallBackFunction": POINTER }) def hook_CallbackOnSet(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : UINT, - "CallBackFunction" : POINTER + "Guid": GUID, + "TokenNumber": UINT, + "CallBackFunction": POINTER }) def hook_CancelCallback(ql, address, params): pass @dxeapi(params = { - "Guid" : GUID, - "TokenNumber" : POINTER + "Guid": GUID, + "TokenNumber": POINTER }) def hook_GetNextToken(ql, address, params): pass @dxeapi(params = { - "Guid" : POINTER + "Guid": POINTER }) def hook_GetNextTokenSpace(ql, address, params): pass @@ -299,36 +299,36 @@ def hook_GetNextTokenSpace(ql, address, params): "guid" : "11b34006-d85b-4d0a-a290-d5a571310ef7", "struct" : PCD_PROTOCOL, "fields" : ( - ('SetSku', hook_SetSku), - ('Get8', hook_Get8), - ('Get16', hook_Get16), - ('Get32', hook_Get32), - ('Get64', hook_Get64), - ('GetPtr', hook_GetPtr), - ('GetBool', hook_GetBool), - ('GetSize', hook_GetSize), - ('Get8Ex', hook_Get8Ex), - ('Get16Ex', hook_Get16Ex), - ('Get32Ex', hook_Get32Ex), - ('Get64Ex', hook_Get64Ex), - ('GetPtrEx', hook_GetPtrEx), - ('GetBoolEx', hook_GetBoolEx), - ('GetSizeEx', hook_GetSizeEx), - ('Set8', hook_Set8), - ('Set16', hook_Set16), - ('Set32', hook_Set32), - ('Set64', hook_Set64), - ('SetPtr', hook_SetPtr), - ('SetBool', hook_SetBool), - ('Set8Ex', hook_Set8Ex), - ('Set16Ex', hook_Set16Ex), - ('Set32Ex', hook_Set32Ex), - ('Set64Ex', hook_Set64Ex), - ('SetPtrEx', hook_SetPtrEx), - ('SetBoolEx', hook_SetBoolEx), - ('CallbackOnSet', hook_CallbackOnSet), - ('CancelCallback', hook_CancelCallback), - ('GetNextToken', hook_GetNextToken), - ('GetNextTokenSpace', hook_GetNextTokenSpace) + ('SetSku', hook_SetSku), + ('Get8', hook_Get8), + ('Get16', hook_Get16), + ('Get32', hook_Get32), + ('Get64', hook_Get64), + ('GetPtr', hook_GetPtr), + ('GetBool', hook_GetBool), + ('GetSize', hook_GetSize), + ('Get8Ex', hook_Get8Ex), + ('Get16Ex', hook_Get16Ex), + ('Get32Ex', hook_Get32Ex), + ('Get64Ex', hook_Get64Ex), + ('GetPtrEx', hook_GetPtrEx), + ('GetBoolEx', hook_GetBoolEx), + ('GetSizeEx', hook_GetSizeEx), + ('Set8', hook_Set8), + ('Set16', hook_Set16), + ('Set32', hook_Set32), + ('Set64', hook_Set64), + ('SetPtr', hook_SetPtr), + ('SetBool', hook_SetBool), + ('Set8Ex', hook_Set8Ex), + ('Set16Ex', hook_Set16Ex), + ('Set32Ex', hook_Set32Ex), + ('Set64Ex', hook_Set64Ex), + ('SetPtrEx', hook_SetPtrEx), + ('SetBoolEx', hook_SetBoolEx), + ('CallbackOnSet', hook_CallbackOnSet), + ('CancelCallback', hook_CancelCallback), + ('GetNextToken', hook_GetNextToken), + ('GetNextTokenSpace', hook_GetNextTokenSpace) ) } diff --git a/qiling/os/uefi/rt.py b/qiling/os/uefi/rt.py index a9d7889dc..dae97b2bf 100644 --- a/qiling/os/uefi/rt.py +++ b/qiling/os/uefi/rt.py @@ -15,8 +15,8 @@ from .UefiSpec import * @dxeapi(params={ - "Time" : POINTER, # OUT PTR(EFI_TIME) - "Capabilities" : POINTER # OUT PTR(EFI_TIME_CAPABILITIES) + "Time": POINTER, # OUT PTR(EFI_TIME) + "Capabilities": POINTER # OUT PTR(EFI_TIME_CAPABILITIES) }) def hook_GetTime(ql: Qiling, address: int, params): Time = params['Time'] @@ -45,48 +45,48 @@ def hook_GetTime(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "Time": POINTER # IN PTR(EFI_TIME) + "Time": POINTER # IN PTR(EFI_TIME) }) def hook_SetTime(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "Enabled" : POINTER, # OUT PTR(BOOLEAN) - "Pending" : POINTER, # OUT PTR(BOOLEAN) - "Time" : POINTER # OUT PTR(EFI_TIME) + "Enabled": POINTER, # OUT PTR(BOOLEAN) + "Pending": POINTER, # OUT PTR(BOOLEAN) + "Time": POINTER # OUT PTR(EFI_TIME) }) def hook_GetWakeupTime(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "Enable": BOOL, # BOOLEAN - "Time" : POINTER # PTR(EFI_TIME) + "Enable": BOOL, # BOOLEAN + "Time": POINTER # PTR(EFI_TIME) }) def hook_SetWakeupTime(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "MemoryMapSize" : UINT, # UINTN - "DescriptorSize" : UINT, # UINTN - "DescriptorVersion" : UINT, # UINT32 - "VirtualMap" : POINTER # PTR(EFI_MEMORY_DESCRIPTOR) + "MemoryMapSize": UINT, # UINTN + "DescriptorSize": UINT, # UINTN + "DescriptorVersion": UINT, # UINT32 + "VirtualMap": POINTER # PTR(EFI_MEMORY_DESCRIPTOR) }) def hook_SetVirtualAddressMap(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "DebugDisposition" : UINT, # UINTN - "Address" : POINTER # OUT PTR(PTR(VOID)) + "DebugDisposition": UINT, # UINTN + "Address": POINTER # OUT PTR(PTR(VOID)) }) def hook_ConvertPointer(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "VariableName" : WSTRING, # PTR(CHAR16) - "VendorGuid" : GUID, # PTR(EFI_GUID) - "Attributes" : POINTER, # OUT PTR(UINT32) - "DataSize" : POINTER, # IN OUT PTR(UINTN) - "Data" : POINTER # OUT PTR(VOID) + "VariableName": WSTRING, # PTR(CHAR16) + "VendorGuid": GUID, # PTR(EFI_GUID) + "Attributes": POINTER, # OUT PTR(UINT32) + "DataSize": POINTER, # IN OUT PTR(UINTN) + "Data": POINTER # OUT PTR(VOID) }) def hook_GetVariable(ql: Qiling, address: int, params): name = params['VariableName'] @@ -113,9 +113,9 @@ def hook_GetVariable(ql: Qiling, address: int, params): return EFI_NOT_FOUND @dxeapi(params={ - "VariableNameSize" : POINTER, # IN OUT PTR(UINTN) - "VariableName" : POINTER, # IN OUT PTR(CHAR16) - "VendorGuid" : GUID # IN OUT PTR(EFI_GUID) + "VariableNameSize": POINTER, # IN OUT PTR(UINTN) + "VariableName": POINTER, # IN OUT PTR(CHAR16) + "VendorGuid": GUID # IN OUT PTR(EFI_GUID) }) def hook_GetNextVariableName(ql: Qiling, address: int, params): var_name_size = params["VariableNameSize"] @@ -153,11 +153,11 @@ def hook_GetNextVariableName(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "VariableName" : WSTRING, # PTR(CHAR16) - "VendorGuid" : GUID, # PTR(EFI_GUID) - "Attributes" : UINT, # UINT32 - "DataSize" : UINT, # UINTN - "Data" : POINTER # PTR(VOID) + "VariableName": WSTRING, # PTR(CHAR16) + "VendorGuid": GUID, # PTR(EFI_GUID) + "Attributes": UINT, # UINT32 + "DataSize": UINT, # UINTN + "Data": POINTER # PTR(VOID) }) def hook_SetVariable(ql: Qiling, address: int, params): ql.env[params['VariableName']] = bytes(ql.mem.read(params['Data'], params['DataSize'])) @@ -176,10 +176,10 @@ def hook_GetNextHighMonotonicCount(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "ResetType" : INT, # EFI_RESET_TYPE - "ResetStatus" : INT, # EFI_STATUS - "DataSize" : UINT, # UINTN - "ResetData" : POINTER # PTR(VOID) + "ResetType": INT, # EFI_RESET_TYPE + "ResetStatus": INT, # EFI_STATUS + "DataSize": UINT, # UINTN + "ResetData": POINTER # PTR(VOID) }) def hook_ResetSystem(ql: Qiling, address: int, params): ql.emu_stop() @@ -187,27 +187,27 @@ def hook_ResetSystem(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER)) - "CapsuleCount" : UINT, # UINTN - "ScatterGatherList" : ULONGLONG # EFI_PHYSICAL_ADDRESS + "CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER)) + "CapsuleCount": UINT, # UINTN + "ScatterGatherList": ULONGLONG # EFI_PHYSICAL_ADDRESS }) def hook_UpdateCapsule(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER)) - "CapsuleCount" : UINT, # UINTN - "MaximumCapsuleSize": POINTER, # OUT PTR(UINT64) - "ResetType" : POINTER # OUT PTR(EFI_RESET_TYPE) + "CapsuleHeaderArray": POINTER, # PTR(PTR(EFI_CAPSULE_HEADER)) + "CapsuleCount": UINT, # UINTN + "MaximumCapsuleSize": POINTER, # OUT PTR(UINT64) + "ResetType": POINTER # OUT PTR(EFI_RESET_TYPE) }) def hook_QueryCapsuleCapabilities(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params={ - "Attributes" : UINT, # UINT32 - "MaximumVariableStorageSize" : POINTER, # OUT PTR(UINT64) - "RemainingVariableStorageSize" : POINTER, # OUT PTR(UINT64) - "MaximumVariableSize" : POINTER # OUT PTR(UINT64) + "Attributes": UINT, # UINT32 + "MaximumVariableStorageSize": POINTER, # OUT PTR(UINT64) + "RemainingVariableStorageSize": POINTER, # OUT PTR(UINT64) + "MaximumVariableSize": POINTER # OUT PTR(UINT64) }) def hook_QueryVariableInfo(ql: Qiling, address: int, params): return EFI_SUCCESS @@ -216,21 +216,21 @@ def initialize(ql: Qiling, gRT: int): descriptor = { 'struct' : EFI_RUNTIME_SERVICES, 'fields' : ( - ('Hdr', None), - ('GetTime', hook_GetTime), - ('SetTime', hook_SetTime), - ('GetWakeupTime', hook_GetWakeupTime), - ('SetWakeupTime', hook_SetWakeupTime), - ('SetVirtualAddressMap', hook_SetVirtualAddressMap), - ('ConvertPointer', hook_ConvertPointer), - ('GetVariable', hook_GetVariable), - ('GetNextVariableName', hook_GetNextVariableName), - ('SetVariable', hook_SetVariable), - ('GetNextHighMonotonicCount', hook_GetNextHighMonotonicCount), - ('ResetSystem', hook_ResetSystem), - ('UpdateCapsule', hook_UpdateCapsule), - ('QueryCapsuleCapabilities', hook_QueryCapsuleCapabilities), - ('QueryVariableInfo', hook_QueryVariableInfo) + ('Hdr', None), + ('GetTime', hook_GetTime), + ('SetTime', hook_SetTime), + ('GetWakeupTime', hook_GetWakeupTime), + ('SetWakeupTime', hook_SetWakeupTime), + ('SetVirtualAddressMap', hook_SetVirtualAddressMap), + ('ConvertPointer', hook_ConvertPointer), + ('GetVariable', hook_GetVariable), + ('GetNextVariableName', hook_GetNextVariableName), + ('SetVariable', hook_SetVariable), + ('GetNextHighMonotonicCount', hook_GetNextHighMonotonicCount), + ('ResetSystem', hook_ResetSystem), + ('UpdateCapsule', hook_UpdateCapsule), + ('QueryCapsuleCapabilities', hook_QueryCapsuleCapabilities), + ('QueryVariableInfo', hook_QueryVariableInfo) ) } diff --git a/qiling/os/uefi/smm.py b/qiling/os/uefi/smm.py index b85a59e82..824148f6c 100644 --- a/qiling/os/uefi/smm.py +++ b/qiling/os/uefi/smm.py @@ -18,46 +18,46 @@ class SaveStateArea: # # see: Intel SDM vol. 3 chapter 30.4.1.1 offsets = { - EFI_SMM_SAVE_STATE_REGISTER.GDTBASE : 0x7E8C, - EFI_SMM_SAVE_STATE_REGISTER.IDTBASE : 0x7E94, - EFI_SMM_SAVE_STATE_REGISTER.LDTBASE : 0x7E9C, + EFI_SMM_SAVE_STATE_REGISTER.GDTBASE: 0x7E8C, + EFI_SMM_SAVE_STATE_REGISTER.IDTBASE: 0x7E94, + EFI_SMM_SAVE_STATE_REGISTER.LDTBASE: 0x7E9C, EFI_SMM_SAVE_STATE_REGISTER.GDTLIMIT: 0x7DD0, EFI_SMM_SAVE_STATE_REGISTER.IDTLIMIT: 0x7DD8, EFI_SMM_SAVE_STATE_REGISTER.LDTLIMIT: 0x7DD4, - # EFI_SMM_SAVE_STATE_REGISTER.LDTINFO : ?, - - EFI_SMM_SAVE_STATE_REGISTER.ES : 0x7FA8, - EFI_SMM_SAVE_STATE_REGISTER.CS : 0x7FAC, - EFI_SMM_SAVE_STATE_REGISTER.SS : 0x7FB0, - EFI_SMM_SAVE_STATE_REGISTER.DS : 0x7FB4, - EFI_SMM_SAVE_STATE_REGISTER.FS : 0x7FB8, - EFI_SMM_SAVE_STATE_REGISTER.GS : 0x7FBC, + # EFI_SMM_SAVE_STATE_REGISTER.LDTINFO: ?, + + EFI_SMM_SAVE_STATE_REGISTER.ES: 0x7FA8, + EFI_SMM_SAVE_STATE_REGISTER.CS: 0x7FAC, + EFI_SMM_SAVE_STATE_REGISTER.SS: 0x7FB0, + EFI_SMM_SAVE_STATE_REGISTER.DS: 0x7FB4, + EFI_SMM_SAVE_STATE_REGISTER.FS: 0x7FB8, + EFI_SMM_SAVE_STATE_REGISTER.GS: 0x7FBC, EFI_SMM_SAVE_STATE_REGISTER.LDTR_SEL: 0x7FC0, - EFI_SMM_SAVE_STATE_REGISTER.TR_SEL : 0x7FC4, - EFI_SMM_SAVE_STATE_REGISTER.DR7 : 0x7FC8, - EFI_SMM_SAVE_STATE_REGISTER.DR6 : 0x7FD0, - EFI_SMM_SAVE_STATE_REGISTER.R8 : 0x7F54, - EFI_SMM_SAVE_STATE_REGISTER.R9 : 0x7F4C, - EFI_SMM_SAVE_STATE_REGISTER.R10 : 0x7F44, - EFI_SMM_SAVE_STATE_REGISTER.R11 : 0x7F3C, - EFI_SMM_SAVE_STATE_REGISTER.R12 : 0x7F34, - EFI_SMM_SAVE_STATE_REGISTER.R13 : 0x7F2C, - EFI_SMM_SAVE_STATE_REGISTER.R14 : 0x7F24, - EFI_SMM_SAVE_STATE_REGISTER.R15 : 0x7F1C, - EFI_SMM_SAVE_STATE_REGISTER.RAX : 0x7F5C, - EFI_SMM_SAVE_STATE_REGISTER.RBX : 0x7F74, - EFI_SMM_SAVE_STATE_REGISTER.RCX : 0x7F64, - EFI_SMM_SAVE_STATE_REGISTER.RDX : 0x7F6C, - EFI_SMM_SAVE_STATE_REGISTER.RSP : 0x7F7C, - EFI_SMM_SAVE_STATE_REGISTER.RBP : 0x7F84, - EFI_SMM_SAVE_STATE_REGISTER.RSI : 0x7F8C, - EFI_SMM_SAVE_STATE_REGISTER.RDI : 0x7F94, - EFI_SMM_SAVE_STATE_REGISTER.RIP : 0x7FD8, - - EFI_SMM_SAVE_STATE_REGISTER.RFLAGS : 0x7FE8, - EFI_SMM_SAVE_STATE_REGISTER.CR0 : 0x7FF8, - EFI_SMM_SAVE_STATE_REGISTER.CR3 : 0x7FF0, - EFI_SMM_SAVE_STATE_REGISTER.CR4 : 0x7E40 + EFI_SMM_SAVE_STATE_REGISTER.TR_SEL: 0x7FC4, + EFI_SMM_SAVE_STATE_REGISTER.DR7: 0x7FC8, + EFI_SMM_SAVE_STATE_REGISTER.DR6: 0x7FD0, + EFI_SMM_SAVE_STATE_REGISTER.R8: 0x7F54, + EFI_SMM_SAVE_STATE_REGISTER.R9: 0x7F4C, + EFI_SMM_SAVE_STATE_REGISTER.R10: 0x7F44, + EFI_SMM_SAVE_STATE_REGISTER.R11: 0x7F3C, + EFI_SMM_SAVE_STATE_REGISTER.R12: 0x7F34, + EFI_SMM_SAVE_STATE_REGISTER.R13: 0x7F2C, + EFI_SMM_SAVE_STATE_REGISTER.R14: 0x7F24, + EFI_SMM_SAVE_STATE_REGISTER.R15: 0x7F1C, + EFI_SMM_SAVE_STATE_REGISTER.RAX: 0x7F5C, + EFI_SMM_SAVE_STATE_REGISTER.RBX: 0x7F74, + EFI_SMM_SAVE_STATE_REGISTER.RCX: 0x7F64, + EFI_SMM_SAVE_STATE_REGISTER.RDX: 0x7F6C, + EFI_SMM_SAVE_STATE_REGISTER.RSP: 0x7F7C, + EFI_SMM_SAVE_STATE_REGISTER.RBP: 0x7F84, + EFI_SMM_SAVE_STATE_REGISTER.RSI: 0x7F8C, + EFI_SMM_SAVE_STATE_REGISTER.RDI: 0x7F94, + EFI_SMM_SAVE_STATE_REGISTER.RIP: 0x7FD8, + + EFI_SMM_SAVE_STATE_REGISTER.RFLAGS: 0x7FE8, + EFI_SMM_SAVE_STATE_REGISTER.CR0: 0x7FF8, + EFI_SMM_SAVE_STATE_REGISTER.CR3: 0x7FF0, + EFI_SMM_SAVE_STATE_REGISTER.CR4: 0x7E40 } def __init__(self, ql: Qiling): @@ -88,14 +88,14 @@ def write(self, regidx: EFI_SMM_SAVE_STATE_REGISTER, data: bytes) -> None: class SmmEnv: SSA_REG_MAP = { - UC_X86_REG_ES : (4, EFI_SMM_SAVE_STATE_REGISTER.ES), - UC_X86_REG_CS : (4, EFI_SMM_SAVE_STATE_REGISTER.CS), - UC_X86_REG_SS : (4, EFI_SMM_SAVE_STATE_REGISTER.SS), - UC_X86_REG_DS : (4, EFI_SMM_SAVE_STATE_REGISTER.DS), - UC_X86_REG_FS : (4, EFI_SMM_SAVE_STATE_REGISTER.FS), - UC_X86_REG_GS : (4, EFI_SMM_SAVE_STATE_REGISTER.GS), - UC_X86_REG_R8 : (8, EFI_SMM_SAVE_STATE_REGISTER.R8), - UC_X86_REG_R9 : (8, EFI_SMM_SAVE_STATE_REGISTER.R9), + UC_X86_REG_ES : (4, EFI_SMM_SAVE_STATE_REGISTER.ES), + UC_X86_REG_CS : (4, EFI_SMM_SAVE_STATE_REGISTER.CS), + UC_X86_REG_SS : (4, EFI_SMM_SAVE_STATE_REGISTER.SS), + UC_X86_REG_DS : (4, EFI_SMM_SAVE_STATE_REGISTER.DS), + UC_X86_REG_FS : (4, EFI_SMM_SAVE_STATE_REGISTER.FS), + UC_X86_REG_GS : (4, EFI_SMM_SAVE_STATE_REGISTER.GS), + UC_X86_REG_R8 : (8, EFI_SMM_SAVE_STATE_REGISTER.R8), + UC_X86_REG_R9 : (8, EFI_SMM_SAVE_STATE_REGISTER.R9), UC_X86_REG_R10 : (8, EFI_SMM_SAVE_STATE_REGISTER.R10), UC_X86_REG_R11 : (8, EFI_SMM_SAVE_STATE_REGISTER.R11), UC_X86_REG_R12 : (8, EFI_SMM_SAVE_STATE_REGISTER.R12), @@ -213,10 +213,10 @@ def invoke_swsmi(self, cpu: int, idx: int, entry: int, args: Mapping[str, Any], self.enter() - DispatchHandle = args['DispatchHandle'] - Context = heap.alloc(EFI_SMM_SW_REGISTER_CONTEXT.sizeof()) - CommBuffer = heap.alloc(EFI_SMM_SW_CONTEXT.sizeof()) - CommBufferSize = heap.alloc(ql.arch.pointersize) + DispatchHandle = args['DispatchHandle'] + Context = heap.alloc(EFI_SMM_SW_REGISTER_CONTEXT.sizeof()) + CommBuffer = heap.alloc(EFI_SMM_SW_CONTEXT.sizeof()) + CommBufferSize = heap.alloc(ql.arch.pointersize) # setup Context args['RegisterContext'].saveTo(ql, Context) diff --git a/qiling/os/uefi/smst.py b/qiling/os/uefi/smst.py index 5de88fb99..39018b5ef 100644 --- a/qiling/os/uefi/smst.py +++ b/qiling/os/uefi/smst.py @@ -33,14 +33,14 @@ class EFI_MM_IO_ACCESS(STRUCT): EFI_SMM_CPU_IO2_PROTOCOL = STRUCT _fields_ = [ - ('Read', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))), - ('Write', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))), + ('Read', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))), + ('Write', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_CPU_IO2_PROTOCOL), EFI_MM_IO_WIDTH, UINT64, UINTN, PTR(VOID))), ] class EFI_SMM_CPU_IO2_PROTOCOL(STRUCT): _fields_ = [ - ('Mem', EFI_MM_IO_ACCESS), - ('Io', EFI_MM_IO_ACCESS) + ('Mem', EFI_MM_IO_ACCESS), + ('Io', EFI_MM_IO_ACCESS) ] class EFI_SMM_SYSTEM_TABLE2(STRUCT): @@ -48,45 +48,45 @@ class EFI_SMM_SYSTEM_TABLE2(STRUCT): _pack_ = 8 _fields_ = [ - ('Hdr', EFI_TABLE_HEADER), - ('SmmFirmwareVendor', PTR(CHAR16)), - ('SmmFirmwareRevision', UINT32), - ('SmmInstallConfigurationTable', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SYSTEM_TABLE2), PTR(EFI_GUID), PTR(VOID), UINTN)), - ('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL), - ('SmmAllocatePool', FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))), - ('SmmFreePool', FUNCPTR(EFI_STATUS, PTR(VOID))), - ('SmmAllocatePages', FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))), - ('SmmFreePages', FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)), - ('SmmStartupThisAp', FUNCPTR(EFI_STATUS, FUNCPTR(VOID, PTR(VOID)), UINTN, PTR(VOID))), - ('CurrentlyExecutingCpu', UINTN), - ('NumberOfCpus', UINTN), - ('CpuSaveStateSize', PTR(UINTN)), - ('CpuSaveState', PTR(PTR(VOID))), - ('NumberOfTableEntries', UINTN), - ('SmmConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)), - ('SmmInstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))), - ('SmmUninstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(VOID))), - ('SmmHandleProtocol', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(PTR(VOID)))), - ('SmmRegisterProtocolNotify', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_MM_NOTIFY_FN, PTR(PTR(VOID)))), - ('SmmLocateHandle', FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))), - ('SmmLocateProtocol', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))), - ('SmiManage', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(VOID), PTR(UINTN))), - ('SmiHandlerRegister', FUNCPTR(EFI_STATUS, EFI_MM_HANDLER_ENTRY_POINT, PTR(EFI_GUID), PTR(EFI_HANDLE))), - ('SmiHandlerUnRegister', FUNCPTR(EFI_STATUS, EFI_HANDLE)), + ('Hdr', EFI_TABLE_HEADER), + ('SmmFirmwareVendor', PTR(CHAR16)), + ('SmmFirmwareRevision', UINT32), + ('SmmInstallConfigurationTable', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SYSTEM_TABLE2), PTR(EFI_GUID), PTR(VOID), UINTN)), + ('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL), + ('SmmAllocatePool', FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))), + ('SmmFreePool', FUNCPTR(EFI_STATUS, PTR(VOID))), + ('SmmAllocatePages', FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))), + ('SmmFreePages', FUNCPTR(EFI_STATUS, EFI_PHYSICAL_ADDRESS, UINTN)), + ('SmmStartupThisAp', FUNCPTR(EFI_STATUS, FUNCPTR(VOID, PTR(VOID)), UINTN, PTR(VOID))), + ('CurrentlyExecutingCpu', UINTN), + ('NumberOfCpus', UINTN), + ('CpuSaveStateSize', PTR(UINTN)), + ('CpuSaveState', PTR(PTR(VOID))), + ('NumberOfTableEntries', UINTN), + ('SmmConfigurationTable', PTR(EFI_CONFIGURATION_TABLE)), + ('SmmInstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(EFI_HANDLE), PTR(EFI_GUID), EFI_INTERFACE_TYPE, PTR(VOID))), + ('SmmUninstallProtocolInterface', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(VOID))), + ('SmmHandleProtocol', FUNCPTR(EFI_STATUS, PTR(VOID), PTR(EFI_GUID), PTR(PTR(VOID)))), + ('SmmRegisterProtocolNotify', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), EFI_MM_NOTIFY_FN, PTR(PTR(VOID)))), + ('SmmLocateHandle', FUNCPTR(EFI_STATUS, EFI_LOCATE_SEARCH_TYPE, PTR(EFI_GUID), PTR(VOID), PTR(UINTN), PTR(EFI_HANDLE))), + ('SmmLocateProtocol', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(PTR(VOID)))), + ('SmiManage', FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(VOID), PTR(VOID), PTR(UINTN))), + ('SmiHandlerRegister', FUNCPTR(EFI_STATUS, EFI_MM_HANDLER_ENTRY_POINT, PTR(EFI_GUID), PTR(EFI_HANDLE))), + ('SmiHandlerUnRegister', FUNCPTR(EFI_STATUS, EFI_HANDLE)), ] @dxeapi(params = { - "Guid" : GUID, # PTR(EFI_GUID) - "Table" : POINTER # PTR(VOID) + "Guid": GUID, # PTR(EFI_GUID) + "Table": POINTER # PTR(VOID) }) def hook_SmmInstallConfigurationTable(ql: Qiling, address: int, params): return common.InstallConfigurationTable(ql.loader.smm_context, params) @dxeapi(params = { - "type" : INT, # EFI_ALLOCATE_TYPE - "MemoryType": INT, # EFI_MEMORY_TYPE - "Pages" : ULONGLONG, # UINTN - "Memory" : POINTER # PTR(EFI_PHYSICAL_ADDRESS) + "type": INT, # EFI_ALLOCATE_TYPE + "MemoryType": INT, # EFI_MEMORY_TYPE + "Pages": ULONGLONG, # UINTN + "Memory": POINTER # PTR(EFI_PHYSICAL_ADDRESS) }) def hook_SmmAllocatePages(ql: Qiling, address: int, params): alloc_size = params["Pages"] * PAGE_SIZE @@ -108,8 +108,8 @@ def hook_SmmAllocatePages(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "Memory" : ULONGLONG, # EFI_PHYSICAL_ADDRESS - "Pages" : ULONGLONG # UINTN + "Memory": ULONGLONG, # EFI_PHYSICAL_ADDRESS + "Pages": ULONGLONG # UINTN }) def hook_SmmFreePages(ql: Qiling, address: int, params): address = params["Memory"] @@ -119,9 +119,9 @@ def hook_SmmFreePages(ql: Qiling, address: int, params): return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER @dxeapi(params = { - "PoolType" : INT, # EFI_MEMORY_TYPE - "Size" : INT, # UINTN - "Buffer" : POINTER # PTR(PTR(VOID)) + "PoolType": INT, # EFI_MEMORY_TYPE + "Size": INT, # UINTN + "Buffer": POINTER # PTR(PTR(VOID)) }) def hook_SmmAllocatePool(ql: Qiling, address: int, params): # TODO: allocate memory acording to "PoolType" @@ -131,7 +131,7 @@ def hook_SmmAllocatePool(ql: Qiling, address: int, params): return EFI_SUCCESS if address else EFI_OUT_OF_RESOURCES @dxeapi(params = { - "Buffer": POINTER # PTR(VOID) + "Buffer": POINTER # PTR(VOID) }) def hook_SmmFreePool(ql: Qiling, address: int, params): address = params["Buffer"] @@ -140,50 +140,50 @@ def hook_SmmFreePool(ql: Qiling, address: int, params): return EFI_SUCCESS if ret else EFI_INVALID_PARAMETER @dxeapi(params = { - "Procedure" : POINTER, - "CpuNumber" : INT, - "ProcArguments" : POINTER + "Procedure": POINTER, + "CpuNumber": INT, + "ProcArguments": POINTER }) def hook_SmmStartupThisAp(ql: Qiling, address: int, params): return EFI_INVALID_PARAMETER @dxeapi(params = { - "Handle" : POINTER, # PTR(EFI_HANDLE) - "Protocol" : GUID, # PTR(EFI_GUID) - "InterfaceType" : ULONGLONG, # EFI_INTERFACE_TYPE - "Interface" : POINTER, # PTR(VOID) + "Handle": POINTER, # PTR(EFI_HANDLE) + "Protocol": GUID, # PTR(EFI_GUID) + "InterfaceType": ULONGLONG, # EFI_INTERFACE_TYPE + "Interface": POINTER, # PTR(VOID) }) def hook_SmmInstallProtocolInterface(ql: Qiling, address: int, params): return common.InstallProtocolInterface(ql.loader.smm_context, params) @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "Interface" : POINTER # PTR(VOID) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "Interface": POINTER # PTR(VOID) }) def hook_SmmUninstallProtocolInterface(ql: Qiling, address: int, params): return common.UninstallProtocolInterface(ql.loader.smm_context, params) @dxeapi(params = { - "Handle" : POINTER, # EFI_HANDLE - "Protocol" : GUID, # PTR(EFI_GUID) - "Interface" : POINTER # PTR(PTR(VOID)) + "Handle": POINTER, # EFI_HANDLE + "Protocol": GUID, # PTR(EFI_GUID) + "Interface": POINTER # PTR(PTR(VOID)) }) def hook_SmmHandleProtocol(ql: Qiling, address: int, params): return common.HandleProtocol(ql.loader.smm_context, params) @dxeapi(params = { - "Protocol" : GUID, # PTR(EFI_GUID) - "Function" : POINTER, # EFI_MM_NOTIFY_FN - "Registration" : POINTER # PTR(PTR(VOID)) + "Protocol": GUID, # PTR(EFI_GUID) + "Function": POINTER, # EFI_MM_NOTIFY_FN + "Registration": POINTER # PTR(PTR(VOID)) }) def hook_SmmRegisterProtocolNotify(ql: Qiling, address: int, params): event_id = len(ql.loader.events) event_dic = { "NotifyFunction": params["Function"], - "CallbackArgs" : None, - "Guid" : params["Protocol"], - "Set" : False + "CallbackArgs": None, + "Guid": params["Protocol"], + "Set": False } ql.loader.events[event_id] = event_dic @@ -192,35 +192,35 @@ def hook_SmmRegisterProtocolNotify(ql: Qiling, address: int, params): return EFI_SUCCESS @dxeapi(params = { - "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE - "Protocol" : GUID, # PTR(EFI_GUID) - "SearchKey" : POINTER, # PTR(VOID) - "BufferSize": POINTER, # PTR(UINTN) - "Buffer" : POINTER # PTR(EFI_HANDLE) + "SearchType": INT, # EFI_LOCATE_SEARCH_TYPE + "Protocol": GUID, # PTR(EFI_GUID) + "SearchKey": POINTER, # PTR(VOID) + "BufferSize": POINTER, # PTR(UINTN) + "Buffer": POINTER # PTR(EFI_HANDLE) }) def hook_SmmLocateHandle(ql: Qiling, address: int, params): return common.LocateHandle(ql.loader.smm_context, params) @dxeapi(params = { - "Protocol" : GUID, # PTR(EFI_GUID) - "Registration" : POINTER, # PTR(VOID) - "Interface" : POINTER # PTR(PTR(VOID)) + "Protocol": GUID, # PTR(EFI_GUID) + "Registration": POINTER, # PTR(VOID) + "Interface": POINTER # PTR(PTR(VOID)) }) def hook_SmmLocateProtocol(ql: Qiling, address: int, params): return common.LocateProtocol(ql.loader.smm_context, params) @dxeapi(params = { - "HandlerType" : GUID, - "Context" : POINTER, - "CommBuffer" : POINTER, + "HandlerType": GUID, + "Context": POINTER, + "CommBuffer": POINTER, "CommBufferSize": POINTER }) def hook_SmiManage(ql: Qiling, address: int, params): return EFI_NOT_FOUND @dxeapi(params = { - "Handler" : POINTER, - "HandlerType" : GUID, + "Handler": POINTER, + "HandlerType": GUID, "DispatchHandle": POINTER }) def hook_SmiHandlerRegister(ql: Qiling, address: int, params): @@ -243,31 +243,31 @@ def initialize(ql: Qiling, context, gSmst: int): descriptor = { 'struct' : EFI_SMM_SYSTEM_TABLE2, 'fields' : ( - ('Hdr', None), - ('SmmFirmwareVendor', None), - ('SmmFirmwareRevision', None), - ('SmmInstallConfigurationTable', hook_SmmInstallConfigurationTable), - ('SmmIo', None), - ('SmmAllocatePool', hook_SmmAllocatePool), - ('SmmFreePool', hook_SmmFreePool), - ('SmmAllocatePages', hook_SmmAllocatePages), - ('SmmFreePages', hook_SmmFreePages), - ('SmmStartupThisAp', hook_SmmStartupThisAp), - ('CurrentlyExecutingCpu', None), - ('NumberOfCpus', None), - ('CpuSaveStateSize', None), - ('CpuSaveState', None), - ('NumberOfTableEntries', 0), - ('SmmConfigurationTable', cfg), - ('SmmInstallProtocolInterface', hook_SmmInstallProtocolInterface), - ('SmmUninstallProtocolInterface', hook_SmmUninstallProtocolInterface), - ('SmmHandleProtocol', hook_SmmHandleProtocol), - ('SmmRegisterProtocolNotify', hook_SmmRegisterProtocolNotify), - ('SmmLocateHandle', hook_SmmLocateHandle), - ('SmmLocateProtocol', hook_SmmLocateProtocol), - ('SmiManage', hook_SmiManage), - ('SmiHandlerRegister', hook_SmiHandlerRegister), - ('SmiHandlerUnRegister', hook_SmiHandlerUnRegister), + ('Hdr', None), + ('SmmFirmwareVendor', None), + ('SmmFirmwareRevision', None), + ('SmmInstallConfigurationTable', hook_SmmInstallConfigurationTable), + ('SmmIo', None), + ('SmmAllocatePool', hook_SmmAllocatePool), + ('SmmFreePool', hook_SmmFreePool), + ('SmmAllocatePages', hook_SmmAllocatePages), + ('SmmFreePages', hook_SmmFreePages), + ('SmmStartupThisAp', hook_SmmStartupThisAp), + ('CurrentlyExecutingCpu', None), + ('NumberOfCpus', None), + ('CpuSaveStateSize', None), + ('CpuSaveState', None), + ('NumberOfTableEntries', 0), + ('SmmConfigurationTable', cfg), + ('SmmInstallProtocolInterface', hook_SmmInstallProtocolInterface), + ('SmmUninstallProtocolInterface', hook_SmmUninstallProtocolInterface), + ('SmmHandleProtocol', hook_SmmHandleProtocol), + ('SmmRegisterProtocolNotify', hook_SmmRegisterProtocolNotify), + ('SmmLocateHandle', hook_SmmLocateHandle), + ('SmmLocateProtocol', hook_SmmLocateProtocol), + ('SmiManage', hook_SmiManage), + ('SmiHandlerRegister', hook_SmiHandlerRegister), + ('SmiHandlerUnRegister', hook_SmiHandlerUnRegister), ) } diff --git a/qiling/os/uefi/st.py b/qiling/os/uefi/st.py index 5e0199ddb..4175100ca 100644 --- a/qiling/os/uefi/st.py +++ b/qiling/os/uefi/st.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # @@ -19,19 +19,19 @@ # | NumberOfTableEntries | # | ConfigurationTable* -> (4) | # +-----------------------------+ -# (1) +-- EFI_RUNTIME_SERVICES -----+ +# (1) +-- EFI_RUNTIME_SERVICES -----+ # | | # | ... | # +-----------------------------+ -# (2) +-- EFI_BOOT_SERVICES --------+ +# (2) +-- EFI_BOOT_SERVICES --------+ # | | # | ... | # +-----------------------------+ -# (3) +-- EFI_DXE_SERVICES ---------+ +# (3) +-- EFI_DXE_SERVICES ---------+ # | | # | ... | # +-----------------------------+ -# (4) +-- EFI_CONFIGURATION_TABLE --+ of HOB_LIST +# (4) +-- EFI_CONFIGURATION_TABLE --+ of HOB_LIST # | VendorGuid | # | VendorTable* -> (5) | # +-----------------------------+ @@ -44,7 +44,7 @@ # dynamically allocated (context.conf_table_data_ptr): # -# (5) +-- VOID* --------------------+ +# (5) +-- VOID* --------------------+ # | ... | # +-----------------------------+ From 0ff009702fd38d7e0ef79d14a65f4b2b8e7a64fe Mon Sep 17 00:00:00 2001 From: elicn Date: Tue, 2 Jan 2024 19:04:30 +0200 Subject: [PATCH 07/15] Improve GetVariable / SetVariable compatibility --- qiling/os/uefi/PiMultiPhase.py | 19 +++- qiling/os/uefi/ProcessorBind.py | 42 +++++--- qiling/os/uefi/UefiBaseType.py | 6 +- qiling/os/uefi/UefiMultiPhase.py | 8 +- .../uefi/protocols/EfiLoadedImageProtocol.py | 9 +- qiling/os/uefi/protocols/PcdProtocol.py | 8 +- qiling/os/uefi/rt.py | 98 ++++++++++++++----- 7 files changed, 144 insertions(+), 46 deletions(-) diff --git a/qiling/os/uefi/PiMultiPhase.py b/qiling/os/uefi/PiMultiPhase.py index c2bbe7f87..e39b3c060 100644 --- a/qiling/os/uefi/PiMultiPhase.py +++ b/qiling/os/uefi/PiMultiPhase.py @@ -4,7 +4,8 @@ # from .UefiBaseType import EFI_PHYSICAL_ADDRESS -from .ProcessorBind import UINT64, STRUCT +from .ProcessorBind import UINT64, STRUCT, ENUM_UC + EFI_SMRAM_OPEN = 0x00000001 EFI_SMRAM_CLOSED = 0x00000002 @@ -14,6 +15,7 @@ EFI_NEEDS_TESTING = 0x00000020 EFI_NEEDS_ECC_INITIALIZATION = 0x00000040 + class EFI_SMRAM_DESCRIPTOR(STRUCT): _fields_ = [ ('PhysicalStart', EFI_PHYSICAL_ADDRESS), @@ -22,8 +24,23 @@ class EFI_SMRAM_DESCRIPTOR(STRUCT): ('RegionState', UINT64) ] + +class EFI_VARIABLE(ENUM_UC): + _members_ = { + 'NON_VOLATILE': 0x00000001, + 'BOOTSERVICE_ACCESS': 0x00000002, + 'RUNTIME_ACCESS': 0x00000004, + 'HARDWARE_ERROR_RECORD': 0x00000008, + 'AUTHENTICATED_WRITE_ACCESS': 0x00000010, + 'TIME_BASED_AUTHENTICATED_WRITE_ACCESS': 0x00000020, + 'APPEND_WRITE': 0x00000040, + 'ENHANCED_AUTHENTICATED_ACCESS': 0x00000080 + } + + __all__ = [ 'EFI_SMRAM_DESCRIPTOR', + 'EFI_VARIABLE', 'EFI_SMRAM_OPEN', 'EFI_SMRAM_CLOSED', 'EFI_SMRAM_LOCKED', diff --git a/qiling/os/uefi/ProcessorBind.py b/qiling/os/uefi/ProcessorBind.py index 73a6e7bf1..3f6bf8553 100644 --- a/qiling/os/uefi/ProcessorBind.py +++ b/qiling/os/uefi/ProcessorBind.py @@ -1,31 +1,38 @@ #!/usr/bin/env python3 -# +# # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations + import ctypes from contextlib import contextmanager -from typing import Mapping, MutableMapping, Sequence, Optional +from functools import lru_cache +from typing import TYPE_CHECKING, Mapping, Sequence, Union, Optional + +if TYPE_CHECKING: + from qiling import Qiling -from qiling import Qiling bits = 64 psize = bits // 8 -dummy_ptr_type = { - 32 : ctypes.c_uint32, - 64 : ctypes.c_uint64 -}[bits] - -_pointer_type_cache: MutableMapping[str, type] = {} +@lru_cache(maxsize=None) +def PTR(ptype: Union[type, None]) -> type: + """Generate a ctypes pointer type. + """ -def PTR(ptype: Optional[type]) -> type: pname = 'c_void' if ptype is None else ptype.__name__ - if pname not in _pointer_type_cache: - _pointer_type_cache[pname] = type(f'LP_{psize}_{pname}', (dummy_ptr_type,), {}) + return type(f'LP_{psize}_{pname}', (ctypes.c_void_p,), {}) + + +def FUNCPTR(rettype: Union[type, None], *argtypes: type) -> type: + """Generate a ctypes function pointer type. + """ + + return PTR(ctypes.CFUNCTYPE(rettype, *argtypes)) - return _pointer_type_cache[pname] VOID = None INT8 = ctypes.c_int8 @@ -44,12 +51,12 @@ def PTR(ptype: Optional[type]) -> type: CHAR8 = UINT8 CHAR16 = UINT16 -FUNCPTR = lambda *args: PTR(ctypes.CFUNCTYPE(*args)) UNION = ctypes.Union CPU_STACK_ALIGNMENT = 16 PAGE_SIZE = 0x1000 + class STRUCT(ctypes.LittleEndianStructure): """An abstract class for C structures. """ @@ -109,10 +116,12 @@ def memberat(cls, offset: int) -> Optional[str]: return next((fname for fname, *_ in cls._fields_ if cls.offsetof(fname) == offset), None) + class EnumMeta(type(ctypes.c_int)): def __getattr__(self, key): return self._members_.index(key) + class ENUM(ctypes.c_int, metaclass=EnumMeta): """An abstract class for continuous C enums. """ @@ -121,10 +130,12 @@ class ENUM(ctypes.c_int, metaclass=EnumMeta): # names will be enumerate by their corresponding index in the list _members_: Sequence[str] = [] + class EnumUCMeta(type(ctypes.c_int)): def __getattr__(self, key): return self._members_[key] + class ENUM_UC(ctypes.c_int, metaclass=EnumUCMeta): """An abstract class for uncontinuous C enums. """ @@ -133,6 +144,7 @@ class ENUM_UC(ctypes.c_int, metaclass=EnumUCMeta): # names will be enumerate by their paired value _members_: Mapping[str, int] = {} + __all__ = [ 'VOID', 'INT8', @@ -158,4 +170,4 @@ class ENUM_UC(ctypes.c_int, metaclass=EnumUCMeta): 'CPU_STACK_ALIGNMENT', 'PAGE_SIZE' -] \ No newline at end of file +] diff --git a/qiling/os/uefi/UefiBaseType.py b/qiling/os/uefi/UefiBaseType.py index b3702d47f..08057dae2 100644 --- a/qiling/os/uefi/UefiBaseType.py +++ b/qiling/os/uefi/UefiBaseType.py @@ -3,7 +3,8 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from qiling.os.uefi.ProcessorBind import * +from qiling.os.uefi.ProcessorBind import VOID, UINT8, UINT16, UINT32, UINT64, UINTN, STRUCT, PTR + class EFI_GUID(STRUCT): _fields_ = [ @@ -13,6 +14,7 @@ class EFI_GUID(STRUCT): ('Data4', UINT8 * 8) ] + EFI_STATUS = UINTN EFI_HANDLE = PTR(VOID) EFI_EVENT = PTR(VOID) @@ -21,6 +23,7 @@ class EFI_GUID(STRUCT): EFI_PHYSICAL_ADDRESS = UINT64 EFI_VIRTUAL_ADDRESS = UINT64 + class EFI_TIME(STRUCT): _fields_ = [ ('Year', UINT16), @@ -36,6 +39,7 @@ class EFI_TIME(STRUCT): ('Pad2', UINT8) ] + __all__ = [ 'EFI_GUID', 'EFI_STATUS', diff --git a/qiling/os/uefi/UefiMultiPhase.py b/qiling/os/uefi/UefiMultiPhase.py index 4a67b1d93..587ec13d2 100644 --- a/qiling/os/uefi/UefiMultiPhase.py +++ b/qiling/os/uefi/UefiMultiPhase.py @@ -3,7 +3,8 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from .ProcessorBind import * +from .ProcessorBind import UINT32, UINT64, STRUCT, ENUM + # @see: MdePkg\Include\Uefi\UefiMultiPhase.h class EFI_TABLE_HEADER(STRUCT): @@ -15,6 +16,7 @@ class EFI_TABLE_HEADER(STRUCT): ('Reserved', UINT32) ] + class EFI_RESET_TYPE(ENUM): _members_ = [ 'EfiResetCold', @@ -23,6 +25,7 @@ class EFI_RESET_TYPE(ENUM): 'EfiResetPlatformSpecific', ] + class EFI_MEMORY_TYPE(ENUM): _members_ = [ 'EfiReservedMemoryType', @@ -43,8 +46,9 @@ class EFI_MEMORY_TYPE(ENUM): 'EfiMaxMemoryType' ] + __all__ = [ 'EFI_TABLE_HEADER', 'EFI_RESET_TYPE', 'EFI_MEMORY_TYPE' -] \ No newline at end of file +] diff --git a/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py b/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py index ef4245260..775622d93 100644 --- a/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py +++ b/qiling/os/uefi/protocols/EfiLoadedImageProtocol.py @@ -3,11 +3,12 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from ..ProcessorBind import * -from ..UefiBaseType import * +from ..ProcessorBind import VOID, UINT32, UINT64, PTR, STRUCT +from ..UefiBaseType import EFI_HANDLE from ..UefiSpec import EFI_SYSTEM_TABLE, EFI_DEVICE_PATH_PROTOCOL, EFI_IMAGE_UNLOAD from ..UefiMultiPhase import EFI_MEMORY_TYPE + class EFI_LOADED_IMAGE_PROTOCOL(STRUCT): _pack_ = 8 @@ -27,6 +28,7 @@ class EFI_LOADED_IMAGE_PROTOCOL(STRUCT): ('Unload', EFI_IMAGE_UNLOAD) ] + def make_descriptor(fields): descriptor = { "guid" : "5b1b31a1-9562-11d2-8e3f-00a0c969723b", @@ -49,7 +51,8 @@ def make_descriptor(fields): return descriptor + __all__ = [ 'EFI_LOADED_IMAGE_PROTOCOL', 'make_descriptor' -] \ No newline at end of file +] diff --git a/qiling/os/uefi/protocols/PcdProtocol.py b/qiling/os/uefi/protocols/PcdProtocol.py index f8ef5d6a0..8fdba9aed 100644 --- a/qiling/os/uefi/protocols/PcdProtocol.py +++ b/qiling/os/uefi/protocols/PcdProtocol.py @@ -4,9 +4,10 @@ # from qiling.os.const import * -from ..fncc import * +from ..fncc import dxeapi from ..ProcessorBind import * -from ..UefiBaseType import * +from ..UefiBaseType import EFI_GUID, EFI_STATUS + PCD_PROTOCOL_CALLBACK = FUNCPTR(VOID, PTR(EFI_GUID), UINTN, PTR(VOID), UINTN) @@ -42,6 +43,7 @@ PCD_PROTOCOL_GET_NEXT_TOKEN = FUNCPTR(EFI_STATUS, PTR(EFI_GUID), PTR(UINTN)) PCD_PROTOCOL_GET_NEXT_TOKENSPACE = FUNCPTR(EFI_STATUS, PTR(PTR(EFI_GUID))) + class PCD_PROTOCOL(STRUCT): _fields_ = [ ('SetSku', PCD_PROTOCOL_SET_SKU), @@ -77,6 +79,7 @@ class PCD_PROTOCOL(STRUCT): ('GetNextTokenSpace', PCD_PROTOCOL_GET_NEXT_TOKENSPACE) ] + @dxeapi(params = { "SkuId": UINT }) @@ -295,6 +298,7 @@ def hook_GetNextToken(ql, address, params): def hook_GetNextTokenSpace(ql, address, params): pass + descriptor = { "guid" : "11b34006-d85b-4d0a-a290-d5a571310ef7", "struct" : PCD_PROTOCOL, diff --git a/qiling/os/uefi/rt.py b/qiling/os/uefi/rt.py index dae97b2bf..fbf19a089 100644 --- a/qiling/os/uefi/rt.py +++ b/qiling/os/uefi/rt.py @@ -11,6 +11,7 @@ from .utils import * from .fncc import * from .ProcessorBind import * +from .PiMultiPhase import EFI_VARIABLE from .UefiBaseType import EFI_TIME from .UefiSpec import * @@ -89,28 +90,42 @@ def hook_ConvertPointer(ql: Qiling, address: int, params): "Data": POINTER # OUT PTR(VOID) }) def hook_GetVariable(ql: Qiling, address: int, params): - name = params['VariableName'] + var_name = params["VariableName"] + vendor_guid = params["VendorGuid"] + attr_ptr = params["Attributes"] + data_size_ptr = params["DataSize"] + data_ptr = params["Data"] - if name in ql.env: - var = ql.env[name] - read_len = ql.mem.read_ptr(params['DataSize']) + if (not var_name) or (not vendor_guid) or (not data_size_ptr): + return EFI_INVALID_PARAMETER - if params['Attributes'] != 0: - ql.mem.write_ptr(params['Attributes'], 0, 4) + if var_name not in ql.env: + return EFI_NOT_FOUND - ql.mem.write_ptr(params['DataSize'], len(var)) + var_data = ql.env[var_name] + data_size = len(var_data) + buff_size = ql.mem.read_ptr(data_size_ptr) - if read_len < len(var): - return EFI_BUFFER_TOO_SMALL + if attr_ptr: + # FIXME: until we manage variables with their attributes, provide a default set + attributes = ( + EFI_VARIABLE.NON_VOLATILE | + EFI_VARIABLE.BOOTSERVICE_ACCESS | + EFI_VARIABLE.RUNTIME_ACCESS + ) - if params['Data'] != 0: - ql.mem.write(params['Data'], var) + ql.mem.write_ptr(attr_ptr, attributes, 4) - return EFI_SUCCESS + ql.mem.write_ptr(data_size_ptr, data_size) - ql.log.warning(f'variable with name {name} not found') + if buff_size < data_size: + return EFI_BUFFER_TOO_SMALL + + if data_ptr: + ql.mem.write(data_ptr, var_data) + + return EFI_SUCCESS - return EFI_NOT_FOUND @dxeapi(params={ "VariableNameSize": POINTER, # IN OUT PTR(UINTN) @@ -120,26 +135,27 @@ def hook_GetVariable(ql: Qiling, address: int, params): def hook_GetNextVariableName(ql: Qiling, address: int, params): var_name_size = params["VariableNameSize"] var_name = params["VariableName"] + vendor_guid = params["VendorGuid"] - if (var_name_size == 0) or (var_name == 0): + if (not var_name_size) or (not var_name) or (not vendor_guid): return EFI_INVALID_PARAMETER name_size = ql.mem.read_ptr(var_name_size) - last_name = ql.os.utils.read_wstring(var_name) + last_name = ql.os.utils.read_wstring(var_name, name_size) - vars = ql.env['Names'] # This is a list of variable names in correct order. + nvvars = ql.env['Names'] # This is a list of variable names in correct order. - if last_name not in vars: + if last_name not in nvvars: return EFI_NOT_FOUND - idx = vars.index(last_name) + idx = nvvars.index(last_name) # make sure it is not the last one (i.e. we have a next one to pull) - if idx == len(vars) - 1: + if idx == len(nvvars) - 1: return EFI_NOT_FOUND # get next var name, and add null terminator - new_name = vars[idx + 1] + '\x00' + new_name = nvvars[idx + 1] + '\x00' # turn it into a wide string new_name = ''.join(f'{c}\x00' for c in new_name) @@ -160,7 +176,45 @@ def hook_GetNextVariableName(ql: Qiling, address: int, params): "Data": POINTER # PTR(VOID) }) def hook_SetVariable(ql: Qiling, address: int, params): - ql.env[params['VariableName']] = bytes(ql.mem.read(params['Data'], params['DataSize'])) + var_name = params["VariableName"] + vendor_guid = params["VendorGuid"] + attributes = params["Attributes"] + data_size = params["DataSize"] + data_ptr = params["Data"] + + if not var_name: + return EFI_INVALID_PARAMETER + + # deprecated + if attributes & EFI_VARIABLE.AUTHENTICATED_WRITE_ACCESS: + return EFI_UNSUPPORTED + + append = attributes & EFI_VARIABLE.APPEND_WRITE + auth = attributes & ( + EFI_VARIABLE.TIME_BASED_AUTHENTICATED_WRITE_ACCESS | + EFI_VARIABLE.ENHANCED_AUTHENTICATED_ACCESS + ) + + # TODO: manage variables with namespaces (guids) + # TODO: manage variables according to their access attributes + + # when data size is set to zero and this is not auth or append access, delete the var + if data_size == 0 and not (auth or append): + if var_name not in ql.env: + return EFI_NOT_FOUND + + del ql.env[var_name] + + data = bytes(ql.mem.read(data_ptr, data_size)) + + if append: + if var_name not in ql.env: + return EFI_NOT_FOUND + + data = ql.env[var_name] + data + + ql.env[var_name] = data + return EFI_SUCCESS @dxeapi(params={ From ea5bd5853e27a496a1a1b99d2e182180f0509cb3 Mon Sep 17 00:00:00 2001 From: elicn Date: Tue, 2 Jan 2024 19:19:40 +0200 Subject: [PATCH 08/15] Manage TSEG properties with struct data --- qiling/os/uefi/context.py | 6 ---- .../uefi/protocols/EfiSmmAccess2Protocol.py | 29 ++++++++++++++----- 2 files changed, 22 insertions(+), 13 deletions(-) diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index 391982f39..c87617560 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -90,12 +90,6 @@ def __init__(self, ql: Qiling): self.smram_base: int self.smram_size: int - # assume tseg is inaccessible to non-smm - self.tseg_open = False - - # assume tseg is locked - self.tseg_locked = True - # registered sw smi handlers self.swsmi_handlers: Mapping[int, Tuple[int, Mapping]] = {} diff --git a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py index 3bf81e61d..7215265c5 100644 --- a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py @@ -38,7 +38,10 @@ class EFI_SMM_ACCESS2_PROTOCOL(STRUCT): "This": POINTER }) def hook_Open(ql: Qiling, address: int, params): - ql.loader.smm_context.tseg_open = True + this = params["This"] + + with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + struct.OpenState = True return EFI_SUCCESS @@ -46,7 +49,10 @@ def hook_Open(ql: Qiling, address: int, params): "This": POINTER }) def hook_Close(ql: Qiling, address: int, params): - ql.loader.smm_context.tseg_open = False + this = params["This"] + + with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + struct.OpenState = False return EFI_SUCCESS @@ -54,7 +60,10 @@ def hook_Close(ql: Qiling, address: int, params): "This": POINTER }) def hook_Lock(ql: Qiling, address: int, params): - ql.loader.smm_context.tseg_locked = True + this = params["This"] + + with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + struct.LockState = True return EFI_SUCCESS @@ -126,11 +135,14 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): ql.mem.write_ptr(MmramMapSize, size + extra) return EFI_BUFFER_TOO_SMALL - MmramMap = params["MmramMap"] + this = params["This"] + struct = EFI_SMM_ACCESS2_PROTOCOL.loadFrom(ql, this) state = EFI_CACHEABLE - state |= EFI_SMRAM_OPEN if ql.loader.smm_context.tseg_open else EFI_SMRAM_CLOSED - state |= EFI_SMRAM_LOCKED if ql.loader.smm_context.tseg_locked else 0 + state |= EFI_SMRAM_OPEN if struct.OpenState else EFI_SMRAM_CLOSED + state |= EFI_SMRAM_LOCKED if struct.LockState else 0 + + MmramMap = params["MmramMap"] for i, ch in enumerate(chunks): desc = EFI_SMRAM_DESCRIPTOR() @@ -143,6 +155,7 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): return EFI_SUCCESS + descriptor = { "guid" : "c2702b74-800c-4131-8746-8fb5b89ce4ac", "struct" : EFI_SMM_ACCESS2_PROTOCOL, @@ -150,6 +163,8 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): ("Open", hook_Open), ("Close", hook_Close), ("Lock", hook_Lock), - ("GetCapabilities", hook_GetCapabilities) + ("GetCapabilities", hook_GetCapabilities), + ("LockState", True), # lock tseg + ("OpenState", False) # make tseg inaccessible to non-smm ) } From fdec54794704a72a3df446a31212f49c08201a0c Mon Sep 17 00:00:00 2001 From: elicn Date: Mon, 8 Jan 2024 13:50:10 +0200 Subject: [PATCH 09/15] Avoid unrecommended inspect.currentframe --- qiling/os/uefi/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/qiling/os/uefi/__init__.py b/qiling/os/uefi/__init__.py index 0e68ec3c5..0d05b43b2 100644 --- a/qiling/os/uefi/__init__.py +++ b/qiling/os/uefi/__init__.py @@ -1,13 +1,14 @@ import csv -from typing import Mapping import inspect + +from typing import Mapping from pathlib import Path def __init_guids_db() -> Mapping[str, str]: """Initialize GUIDs dictionary from a local database. """ - csv_path = Path(inspect.getfile(inspect.currentframe())).parent / 'guids.csv' + csv_path = Path(inspect.getfile(__init_guids_db)).parent / 'guids.csv' with csv_path.open('r') as guids_file: guids_reader = csv.reader(guids_file) From 334fe70c583087c1d2ee1e50f4d90489f520b60f Mon Sep 17 00:00:00 2001 From: elicn Date: Mon, 8 Jan 2024 14:05:04 +0200 Subject: [PATCH 10/15] Fine-tune imports and type annotations --- qiling/loader/pe_uefi.py | 4 ++-- qiling/os/uefi/__init__.py | 5 +++-- qiling/os/uefi/context.py | 4 ++-- .../uefi/protocols/EfiSmmAccess2Protocol.py | 15 +++++++++---- qiling/os/uefi/rt.py | 17 +++++++++----- qiling/os/uefi/smst.py | 18 ++++++++++----- qiling/os/uefi/uefi.py | 22 ++++++++++--------- 7 files changed, 54 insertions(+), 31 deletions(-) diff --git a/qiling/loader/pe_uefi.py b/qiling/loader/pe_uefi.py index e510cb6d1..9d500e3b3 100644 --- a/qiling/loader/pe_uefi.py +++ b/qiling/loader/pe_uefi.py @@ -4,8 +4,8 @@ # import os -from pefile import PE from typing import Any, Mapping, Optional, Sequence +from pefile import PE from qiling import Qiling from qiling.const import QL_ARCH @@ -326,7 +326,7 @@ def run(self): raise QlErrorArch("Unsupported architecture") # x86-64 arch only - if ql.arch.type != QL_ARCH.X8664: + if ql.arch.type is not QL_ARCH.X8664: raise QlErrorArch("Only 64-bit modules are supported at the moment") self.loaded_image_protocol_guid = ql.os.profile["LOADED_IMAGE_PROTOCOL"]["Guid"] diff --git a/qiling/os/uefi/__init__.py b/qiling/os/uefi/__init__.py index 0d05b43b2..224ae35a6 100644 --- a/qiling/os/uefi/__init__.py +++ b/qiling/os/uefi/__init__.py @@ -1,10 +1,11 @@ import csv import inspect -from typing import Mapping +from typing import Dict from pathlib import Path -def __init_guids_db() -> Mapping[str, str]: + +def __init_guids_db() -> Dict[str, str]: """Initialize GUIDs dictionary from a local database. """ diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index c87617560..ef9faced6 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -61,9 +61,9 @@ def install_protocol(self, proto_desc: Mapping, handle: int, address: Optional[i 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: + if event_dic['CallbackArgs'] is None: # To support smm notification, we use None for CallbackArgs on SmmRegisterProtocolNotify - # and updare it here. + # and update it here. guid = utils.str_to_guid(protocol) guid_ptr = self.heap.alloc(guid.sizeof()) guid.saveTo(self.ql, guid_ptr) diff --git a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py index 7215265c5..ef6841066 100644 --- a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py @@ -3,14 +3,21 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from qiling import Qiling -from qiling.os.const import * +from __future__ import annotations +from typing import TYPE_CHECKING + +from qiling.os.const import POINTER from qiling.os.uefi.const import * -from ..fncc import * +from ..fncc import dxeapi from ..ProcessorBind import * -from ..UefiBaseType import * +from ..UefiBaseType import EFI_PHYSICAL_ADDRESS, EFI_STATUS from ..PiMultiPhase import * + +if TYPE_CHECKING: + from qiling import Qiling + + # @see: MdePkg\Include\Pi\PiMultiPhase.h class EFI_MMRAM_DESCRIPTOR(STRUCT): _fields_ = [ diff --git a/qiling/os/uefi/rt.py b/qiling/os/uefi/rt.py index fbf19a089..58289bb65 100644 --- a/qiling/os/uefi/rt.py +++ b/qiling/os/uefi/rt.py @@ -3,17 +3,24 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations +from typing import TYPE_CHECKING + import time -from qiling import Qiling from qiling.os.const import * from .const import * -from .utils import * -from .fncc import * +from .utils import init_struct +from .fncc import dxeapi from .ProcessorBind import * from .PiMultiPhase import EFI_VARIABLE from .UefiBaseType import EFI_TIME -from .UefiSpec import * +from .UefiSpec import EFI_UNSPECIFIED_TIMEZONE, EFI_RUNTIME_SERVICES + + +if TYPE_CHECKING: + from qiling import Qiling + @dxeapi(params={ "Time": POINTER, # OUT PTR(EFI_TIME) @@ -293,4 +300,4 @@ def initialize(ql: Qiling, gRT: int): __all__ = [ 'initialize' -] \ No newline at end of file +] diff --git a/qiling/os/uefi/smst.py b/qiling/os/uefi/smst.py index 39018b5ef..aa561af25 100644 --- a/qiling/os/uefi/smst.py +++ b/qiling/os/uefi/smst.py @@ -3,19 +3,25 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from qiling.const import * -from qiling.os.const import * +from __future__ import annotations +from typing import TYPE_CHECKING + +from qiling.os.const import GUID, POINTER, INT, ULONGLONG from qiling.os.uefi.const import EFI_SUCCESS, EFI_NOT_FOUND, EFI_OUT_OF_RESOURCES, EFI_INVALID_PARAMETER -from qiling.os.uefi.utils import * -from qiling.os.uefi.fncc import * +from qiling.os.uefi.utils import init_struct, install_configuration_table +from qiling.os.uefi.fncc import dxeapi from qiling.os.uefi.ProcessorBind import * from qiling.os.uefi.UefiBaseType import * from qiling.os.uefi.UefiMultiPhase import * -from qiling.os.uefi.UefiSpec import * +from qiling.os.uefi.UefiSpec import EFI_ALLOCATE_TYPE, EFI_CONFIGURATION_TABLE, EFI_INTERFACE_TYPE, EFI_LOCATE_SEARCH_TYPE, EFI_RUNTIME_SERVICES from qiling.os.uefi.protocols import common from qiling.os.uefi import rt +if TYPE_CHECKING: + from qiling import Qiling + + # @see: MdePkg\Include\Pi\PiSmmCis.h class EFI_MM_IO_WIDTH(ENUM): @@ -52,7 +58,7 @@ class EFI_SMM_SYSTEM_TABLE2(STRUCT): ('SmmFirmwareVendor', PTR(CHAR16)), ('SmmFirmwareRevision', UINT32), ('SmmInstallConfigurationTable', FUNCPTR(EFI_STATUS, PTR(EFI_SMM_SYSTEM_TABLE2), PTR(EFI_GUID), PTR(VOID), UINTN)), - ('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL), + ('SmmIo', EFI_SMM_CPU_IO2_PROTOCOL), ('SmmAllocatePool', FUNCPTR(EFI_STATUS, EFI_MEMORY_TYPE, UINTN, PTR(PTR(VOID)))), ('SmmFreePool', FUNCPTR(EFI_STATUS, PTR(VOID))), ('SmmAllocatePages', FUNCPTR(EFI_STATUS, EFI_ALLOCATE_TYPE, EFI_MEMORY_TYPE, UINTN, PTR(EFI_PHYSICAL_ADDRESS))), diff --git a/qiling/os/uefi/uefi.py b/qiling/os/uefi/uefi.py index e01b628bb..8418cf1ec 100644 --- a/qiling/os/uefi/uefi.py +++ b/qiling/os/uefi/uefi.py @@ -4,13 +4,13 @@ # import re -from typing import Any, Callable, Iterable, Mapping, MutableSequence, Sequence, Tuple +from typing import Any, Callable, Iterable, Mapping, List, Sequence, Tuple from unicorn import UcError from qiling import Qiling from qiling.cc import QlCC, intel from qiling.const import QL_INTERCEPT, QL_OS -from qiling.os.const import * +from qiling.os.const import POINTER, STRING, WSTRING, GUID from qiling.os.memory import QlMemoryHeap from qiling.os.os import QlOs, QlOsUtils from qiling.os.fcall import QlFunctionCall, TypedArg @@ -30,8 +30,8 @@ def __init__(self, ql: Qiling): self.smm: SmmEnv self.heap: QlMemoryHeap # Will be initialized by the loader. - self.on_module_enter: MutableSequence[Callable[[str], bool]] = [] - self.on_module_exit: MutableSequence[Callable[[int], bool]] = [] + self.on_module_enter: List[Callable[[str], bool]] = [] + self.on_module_exit: List[Callable[[int], bool]] = [] cc: QlCC = { 32: intel.cdecl, @@ -41,12 +41,14 @@ def __init__(self, ql: Qiling): self.fcall = QlFunctionCall(ql, cc) def save(self): - saved_state = super(QlOsUefi, self).save() + saved_state = super().save() saved_state['entry_point'] = self.entry_point + return saved_state def restore(self, saved_state): - super(QlOsUefi, self).restore(saved_state) + super().restore(saved_state) + self.entry_point = saved_state['entry_point'] def process_fcall_params(self, targs: Iterable[TypedArg]) -> Sequence[Tuple[str, str]]: @@ -70,10 +72,10 @@ def fallback(v): return super(QlOsUefi, self).process_fcall_params([(None, '', v)])[0][1] ahandlers: Mapping[Any, Callable[[Any], str]] = { - POINTER : lambda v: f'{v:#010x}' if v else 'NULL', - STRING : lambda v: QlOsUtils.stringify(v), - WSTRING : lambda v: f'L{QlOsUtils.stringify(v)}', - GUID : lambda v: guids_db.get(v.upper(), v) if v else 'NULL' + POINTER: lambda v: f'{v:#010x}' if v else 'NULL', + STRING: lambda v: QlOsUtils.stringify(v), + WSTRING: lambda v: f'L{QlOsUtils.stringify(v)}', + GUID: lambda v: guids_db.get(v.upper(), v) if v else 'NULL' } return tuple((aname, ahandlers.get(atype, fallback)(avalue)) for atype, aname, avalue in targs) From b5477ec10e9c4d52a115ec702d9a99fb7a42311c Mon Sep 17 00:00:00 2001 From: elicn Date: Fri, 9 Feb 2024 15:54:10 +0200 Subject: [PATCH 11/15] Align UEFI structures with all other OS --- qiling/loader/pe_uefi.py | 2 +- qiling/os/uefi/ProcessorBind.py | 63 +------------------ qiling/os/uefi/bs.py | 4 +- qiling/os/uefi/context.py | 16 ++--- qiling/os/uefi/ds.py | 2 +- qiling/os/uefi/hob.py | 18 +++--- .../uefi/protocols/EfiSmmAccess2Protocol.py | 21 +++---- .../protocols/EfiSmmSwDispatch2Protocol.py | 6 +- qiling/os/uefi/rt.py | 31 +++++---- qiling/os/uefi/smm.py | 14 ++--- qiling/os/uefi/smst.py | 2 +- qiling/os/uefi/st.py | 13 ++-- 12 files changed, 66 insertions(+), 126 deletions(-) diff --git a/qiling/loader/pe_uefi.py b/qiling/loader/pe_uefi.py index 9d500e3b3..5be9dd294 100644 --- a/qiling/loader/pe_uefi.py +++ b/qiling/loader/pe_uefi.py @@ -161,7 +161,7 @@ def unload_modules(self, context: UefiContext) -> bool: for handle in context.loaded_image_protocol_modules: struct_addr = context.protocols[handle][self.loaded_image_protocol_guid] - loaded_image_protocol = EfiLoadedImageProtocol.EFI_LOADED_IMAGE_PROTOCOL.loadFrom(self.ql, struct_addr) + loaded_image_protocol = EfiLoadedImageProtocol.EFI_LOADED_IMAGE_PROTOCOL.load_from(self.ql.mem, struct_addr) unload_ptr = loaded_image_protocol.Unload.value diff --git a/qiling/os/uefi/ProcessorBind.py b/qiling/os/uefi/ProcessorBind.py index 3f6bf8553..5bef2a5a8 100644 --- a/qiling/os/uefi/ProcessorBind.py +++ b/qiling/os/uefi/ProcessorBind.py @@ -10,6 +10,8 @@ from functools import lru_cache from typing import TYPE_CHECKING, Mapping, Sequence, Union, Optional +from qiling.os.struct import BaseStructEL + if TYPE_CHECKING: from qiling import Qiling @@ -51,72 +53,13 @@ def FUNCPTR(rettype: Union[type, None], *argtypes: type) -> type: CHAR8 = UINT8 CHAR16 = UINT16 +STRUCT = BaseStructEL UNION = ctypes.Union CPU_STACK_ALIGNMENT = 16 PAGE_SIZE = 0x1000 -class STRUCT(ctypes.LittleEndianStructure): - """An abstract class for C structures. - """ - - # Structures are packed by default; when needed, padding should be added - # manually through placeholder fields - _pack_ = 1 - - def __init__(self): - pass - - def saveTo(self, ql: Qiling, address: int) -> None: - """Store self contents to a specified memory address. - """ - - data = bytes(self) - - ql.mem.write(address, data) - - @classmethod - def loadFrom(cls, ql: Qiling, address: int) -> 'STRUCT': - """Construct an instance of the structure from saved contents. - """ - - data = bytes(ql.mem.read(address, cls.sizeof())) - - return cls.from_buffer_copy(data) - - @classmethod - @contextmanager - def bindTo(cls, ql: Qiling, address: int): - instance = cls.loadFrom(ql, address) - - try: - yield instance - finally: - instance.saveTo(ql, address) - - @classmethod - def sizeof(cls) -> int: - """Get the C structure size in bytes. - """ - - return ctypes.sizeof(cls) - - @classmethod - def offsetof(cls, fname: str) -> int: - """Get the offset of a field in the C structure. - """ - - return getattr(cls, fname).offset - - @classmethod - def memberat(cls, offset: int) -> Optional[str]: - """Get the member name at a given offset. - """ - - return next((fname for fname, *_ in cls._fields_ if cls.offsetof(fname) == offset), None) - - class EnumMeta(type(ctypes.c_int)): def __getattr__(self, key): return self._members_.index(key) diff --git a/qiling/os/uefi/bs.py b/qiling/os/uefi/bs.py index 793198995..ddb834e3d 100644 --- a/qiling/os/uefi/bs.py +++ b/qiling/os/uefi/bs.py @@ -594,8 +594,8 @@ def initialize(ql: Qiling, gBS: int): ql.os.monotonic_count = 0 instance = init_struct(ql, gBS, descriptor) - instance.saveTo(ql, gBS) + instance.save_to(ql.mem, gBS) __all__ = [ 'initialize' -] \ No newline at end of file +] diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index ef9faced6..5e35fd7f8 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -53,7 +53,7 @@ def install_protocol(self, proto_desc: Mapping, handle: int, address: Optional[i address = self.heap.alloc(struct_class.sizeof()) instance = utils.init_struct(self.ql, address, proto_desc) - instance.saveTo(self.ql, address) + instance.save_to(self.ql.mem, address) self.protocols[handle][guid] = address return self.notify_protocol(handle, guid, address, from_hook) @@ -66,7 +66,7 @@ def notify_protocol(self, handle: int, protocol: str, interface: int, from_hook: # and update it here. guid = utils.str_to_guid(protocol) guid_ptr = self.heap.alloc(guid.sizeof()) - guid.saveTo(self.ql, guid_ptr) + guid.save_to(self.ql.mem, guid_ptr) event_dic['CallbackArgs'] = [guid_ptr, interface, handle] @@ -135,10 +135,10 @@ def install(self, guid: str, table: int): ptr = self.baseptr + self.nitems * EFI_CONFIGURATION_TABLE.sizeof() append = True - instance = EFI_CONFIGURATION_TABLE() - instance.VendorGuid = utils.str_to_guid(guid) - instance.VendorTable = table - instance.saveTo(self.ql, ptr) + EFI_CONFIGURATION_TABLE( + VendorGuid = utils.str_to_guid(guid), + VendorTable = table + ).save_to(self.ql.mem, ptr) if append: self.nitems += 1 @@ -149,7 +149,7 @@ def find(self, guid: str) -> Optional[int]: efi_guid = utils.str_to_guid(guid) for _ in range(nitems): - entry = EFI_CONFIGURATION_TABLE.loadFrom(self.ql, ptr) + entry = EFI_CONFIGURATION_TABLE.load_from(self.ql.mem, ptr) if utils.CompareGuid(entry.VendorGuid, efi_guid): return ptr @@ -162,7 +162,7 @@ def get_vendor_table(self, guid: str) -> Optional[int]: ptr = self.find(guid) if ptr is not None: - entry = EFI_CONFIGURATION_TABLE.loadFrom(self.ql, ptr) + entry = EFI_CONFIGURATION_TABLE.load_from(self.ql.mem, ptr) return entry.VendorTable.value diff --git a/qiling/os/uefi/ds.py b/qiling/os/uefi/ds.py index 5665ecbcf..9b1a6eb65 100644 --- a/qiling/os/uefi/ds.py +++ b/qiling/os/uefi/ds.py @@ -275,7 +275,7 @@ def initialize(ql: Qiling, gDS: int): } instance = init_struct(ql, gDS, descriptor) - instance.saveTo(ql, gDS) + instance.save_to(ql.mem, gDS) __all__ = [ 'EFI_DXE_SERVICES', diff --git a/qiling/os/uefi/hob.py b/qiling/os/uefi/hob.py index c0df98e33..f2b537666 100644 --- a/qiling/os/uefi/hob.py +++ b/qiling/os/uefi/hob.py @@ -36,7 +36,7 @@ def GetHobList(ql: Qiling, context: UefiContext) -> int: return hoblist_vend -def CreateHob(ql: Qiling, context: UefiContext, hob) -> int: +def CreateHob(ql: Qiling, context: UefiContext, hob: STRUCT) -> int: """Add a HOB to the end of the HOB list. """ @@ -48,15 +48,15 @@ def CreateHob(ql: Qiling, context: UefiContext, hob) -> int: # overwrite end marker with the hob pHob = hoblist - hob.saveTo(ql, pHob) + hob.save_to(ql.mem, pHob) hoblist += hob.sizeof() # create a new end marker istead, following the hob - marker = EFI_HOB_GENERIC_HEADER() - marker.HobType = EFI_HOB_TYPE_END_OF_HOB_LIST - marker.HobLength = 0x0000 - marker.Reserved = 0x00000000 - marker.saveTo(ql, hoblist) + EFI_HOB_GENERIC_HEADER( + HobType = EFI_HOB_TYPE_END_OF_HOB_LIST, + HobLength = 0x0000, + Reserved = 0x00000000 + ).save_to(ql.mem, hoblist) # return the address the hob was written to; it might be useful return pHob @@ -68,7 +68,7 @@ def GetNextHob(ql: Qiling, hobtype: int, hoblist: int) -> int: hobaddr = hoblist while True: - header = EFI_HOB_GENERIC_HEADER.loadFrom(ql, hobaddr) + header = EFI_HOB_GENERIC_HEADER.load_from(ql.mem, hobaddr) # found the hob? if header.HobType == hobtype: @@ -95,7 +95,7 @@ def GetNextGuidHob(ql: Qiling, guid: str, hoblist: int) -> int: if not hobaddr: return 0 - hob = EFI_HOB_GUID_TYPE.loadFrom(ql, hobaddr) + hob = EFI_HOB_GUID_TYPE.load_from(ql.mem, hobaddr) if CompareGuid(hob.Name, hobguid): break diff --git a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py index ef6841066..ffb7031b5 100644 --- a/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmAccess2Protocol.py @@ -47,7 +47,7 @@ class EFI_SMM_ACCESS2_PROTOCOL(STRUCT): def hook_Open(ql: Qiling, address: int, params): this = params["This"] - with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct: struct.OpenState = True return EFI_SUCCESS @@ -58,7 +58,7 @@ def hook_Open(ql: Qiling, address: int, params): def hook_Close(ql: Qiling, address: int, params): this = params["This"] - with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct: struct.OpenState = False return EFI_SUCCESS @@ -69,7 +69,7 @@ def hook_Close(ql: Qiling, address: int, params): def hook_Lock(ql: Qiling, address: int, params): this = params["This"] - with EFI_SMM_ACCESS2_PROTOCOL.bindTo(ql, this) as struct: + with EFI_SMM_ACCESS2_PROTOCOL.ref(ql.mem, this) as struct: struct.LockState = True return EFI_SUCCESS @@ -143,7 +143,7 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): return EFI_BUFFER_TOO_SMALL this = params["This"] - struct = EFI_SMM_ACCESS2_PROTOCOL.loadFrom(ql, this) + struct = EFI_SMM_ACCESS2_PROTOCOL.load_from(ql.mem, this) state = EFI_CACHEABLE state |= EFI_SMRAM_OPEN if struct.OpenState else EFI_SMRAM_CLOSED @@ -152,13 +152,12 @@ def hook_GetCapabilities(ql: Qiling, address: int, params): MmramMap = params["MmramMap"] for i, ch in enumerate(chunks): - desc = EFI_SMRAM_DESCRIPTOR() - desc.PhysicalStart = ch[0] - desc.CpuStart = ch[0] - desc.PhysicalSize = ch[1] - ch[0] - desc.RegionState = state | (EFI_ALLOCATED if ch[2] else 0) - - desc.saveTo(ql, MmramMap + (i * desc.sizeof())) + EFI_SMRAM_DESCRIPTOR( + PhysicalStart = ch[0], + CpuStart = ch[0], + PhysicalSize = ch[1] - ch[0], + RegionState = state | (EFI_ALLOCATED if ch[2] else 0) + ).save_to(ql.mem, MmramMap + (i * EFI_SMRAM_DESCRIPTOR.sizeof())) return EFI_SUCCESS diff --git a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py index 4596dc162..f7124c9ea 100644 --- a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py @@ -55,7 +55,7 @@ def hook_Register(ql: Qiling, address: int, params): handlers = ql.loader.smm_context.swsmi_handlers - SwRegisterContext = EFI_SMM_SW_REGISTER_CONTEXT.loadFrom(ql, RegisterContext) + SwRegisterContext = EFI_SMM_SW_REGISTER_CONTEXT.load_from(ql.mem, RegisterContext) idx = SwRegisterContext.SwSmiInputValue # a value of -1 indicates that the swsmi index for this handler is flexible and @@ -67,10 +67,10 @@ def hook_Register(ql: Qiling, address: int, params): return EFI_OUT_OF_RESOURCES SwRegisterContext.SwSmiInputValue = idx - SwRegisterContext.saveTo(ql, RegisterContext) + SwRegisterContext.save_to(ql.mem, RegisterContext) else: - This = EFI_SMM_SW_DISPATCH2_PROTOCOL.loadFrom(ql, params['This']) + This = EFI_SMM_SW_DISPATCH2_PROTOCOL.load_from(ql.mem, params['This']) if idx in handlers: return EFI_INVALID_PARAMETER diff --git a/qiling/os/uefi/rt.py b/qiling/os/uefi/rt.py index 58289bb65..5dd5280f6 100644 --- a/qiling/os/uefi/rt.py +++ b/qiling/os/uefi/rt.py @@ -34,21 +34,20 @@ def hook_GetTime(ql: Qiling, address: int, params): localtime = time.localtime() - efitime = EFI_TIME() - efitime.Year = localtime.tm_year - efitime.Month = localtime.tm_mon - efitime.Day = localtime.tm_mday - efitime.Hour = localtime.tm_hour - efitime.Minute = localtime.tm_min - efitime.Second = localtime.tm_sec - efitime.Nanosecond = 0 - - # tz and dst settings are stored in the "RtcTimeSettings" nvram variable. - # we just use the default settings instead - efitime.TimeZone = EFI_UNSPECIFIED_TIMEZONE - efitime.Daylight = 0 - - efitime.saveTo(ql, Time) + EFI_TIME( + Year = localtime.tm_year, + Month = localtime.tm_mon, + Day = localtime.tm_mday, + Hour = localtime.tm_hour, + Minute = localtime.tm_min, + Second = localtime.tm_sec, + Nanosecond = 0, + + # tz and dst settings are stored in the "RtcTimeSettings" nvram variable. + # we just use the default settings instead + TimeZone = EFI_UNSPECIFIED_TIMEZONE, + Daylight = 0 + ).save_to(ql.mem, Time) return EFI_SUCCESS @@ -296,7 +295,7 @@ def initialize(ql: Qiling, gRT: int): } instance = init_struct(ql, gRT, descriptor) - instance.saveTo(ql, gRT) + instance.save_to(ql.mem, gRT) __all__ = [ 'initialize' diff --git a/qiling/os/uefi/smm.py b/qiling/os/uefi/smm.py index 824148f6c..f8815c39a 100644 --- a/qiling/os/uefi/smm.py +++ b/qiling/os/uefi/smm.py @@ -219,17 +219,17 @@ def invoke_swsmi(self, cpu: int, idx: int, entry: int, args: Mapping[str, Any], CommBufferSize = heap.alloc(ql.arch.pointersize) # setup Context - args['RegisterContext'].saveTo(ql, Context) + args['RegisterContext'].save_to(ql.mem, Context) # setup CommBuffer - SmmSwContext = EFI_SMM_SW_CONTEXT() - SmmSwContext.SwSmiCpuIndex = cpu - SmmSwContext.CommandPort = idx - SmmSwContext.DataPort = 0 - SmmSwContext.saveTo(ql, CommBuffer) + EFI_SMM_SW_CONTEXT( + SwSmiCpuIndex = cpu, + CommandPort = idx, + DataPort = 0 + ).save_to(ql.mem, CommBuffer) # setup CommBufferSize - ql.mem.write_ptr(CommBufferSize, SmmSwContext.sizeof(), 8) + ql.mem.write_ptr(CommBufferSize, EFI_SMM_SW_CONTEXT.sizeof(), 8) # clean up handler resources def __cleanup(ql: Qiling): diff --git a/qiling/os/uefi/smst.py b/qiling/os/uefi/smst.py index aa561af25..080243401 100644 --- a/qiling/os/uefi/smst.py +++ b/qiling/os/uefi/smst.py @@ -278,7 +278,7 @@ def initialize(ql: Qiling, context, gSmst: int): } instance = init_struct(ql, gSmst, descriptor) - instance.saveTo(ql, gSmst) + instance.save_to(ql.mem, gSmst) install_configuration_table(context, "HOB_LIST", None) install_configuration_table(context, "SMM_RUNTIME_SERVICES_TABLE", gSmmRT) diff --git a/qiling/os/uefi/st.py b/qiling/os/uefi/st.py index 4175100ca..22260786f 100644 --- a/qiling/os/uefi/st.py +++ b/qiling/os/uefi/st.py @@ -67,13 +67,12 @@ def initialize(ql: Qiling, context: UefiContext, gST: int): rt.initialize(ql, gRT) ds.initialize(ql, gDS) - instance = EFI_SYSTEM_TABLE() - instance.RuntimeServices = gRT - instance.BootServices = gBS - instance.NumberOfTableEntries = 0 - instance.ConfigurationTable = cfg - - instance.saveTo(ql, gST) + EFI_SYSTEM_TABLE( + RuntimeServices = gRT, + BootServices = gBS, + NumberOfTableEntries = 0, + ConfigurationTable = cfg + ).save_to(ql.mem, gST) install_configuration_table(context, "HOB_LIST", None) install_configuration_table(context, "DXE_SERVICE_TABLE", gDS) From 152d51a9669eb3f1a4e74c680193536633178de6 Mon Sep 17 00:00:00 2001 From: elicn Date: Fri, 9 Feb 2024 15:57:13 +0200 Subject: [PATCH 12/15] Minor enhancements and styling changes --- qiling/os/uefi/ProcessorBind.py | 6 ++-- qiling/os/uefi/bs.py | 16 ++++----- qiling/os/uefi/const.py | 3 +- qiling/os/uefi/context.py | 36 +++++++++---------- .../protocols/EfiSmmSwDispatch2Protocol.py | 20 +++++++---- qiling/os/uefi/st.py | 6 ++-- qiling/os/uefi/utils.py | 11 ++++-- 7 files changed, 53 insertions(+), 45 deletions(-) diff --git a/qiling/os/uefi/ProcessorBind.py b/qiling/os/uefi/ProcessorBind.py index 5bef2a5a8..8d3c4a449 100644 --- a/qiling/os/uefi/ProcessorBind.py +++ b/qiling/os/uefi/ProcessorBind.py @@ -21,16 +21,16 @@ @lru_cache(maxsize=None) def PTR(ptype: Union[type, None]) -> type: - """Generate a ctypes pointer type. + """Generate a pseudo pointer type. """ pname = 'c_void' if ptype is None else ptype.__name__ - return type(f'LP_{psize}_{pname}', (ctypes.c_void_p,), {}) + return type(f'LP_{psize}_{pname}', (UINTN,), {}) def FUNCPTR(rettype: Union[type, None], *argtypes: type) -> type: - """Generate a ctypes function pointer type. + """Generate a pseudo function pointer type. """ return PTR(ctypes.CFUNCTYPE(rettype, *argtypes)) diff --git a/qiling/os/uefi/bs.py b/qiling/os/uefi/bs.py index ddb834e3d..bd9c0dd85 100644 --- a/qiling/os/uefi/bs.py +++ b/qiling/os/uefi/bs.py @@ -431,13 +431,13 @@ def hook_InstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): # process elipsiss arguments index = 1 while ql.os.fcall.cc.getRawParam(index) != 0: - GUID_ptr = ql.os.fcall.cc.getRawParam(index) + guid_ptr = ql.os.fcall.cc.getRawParam(index) protocol_ptr = ql.os.fcall.cc.getRawParam(index + 1) - GUID = str(ql.os.utils.read_guid(GUID_ptr)) - dic[GUID] = protocol_ptr + guid = str(ql.os.utils.read_guid(guid_ptr)) + dic[guid] = protocol_ptr - ql.log.info(f'Installing protocol interface {guids_db.get(GUID.upper(), GUID)} to {protocol_ptr:#x}') + ql.log.info(f'Installing protocol interface {guids_db.get(guid.upper(), guid)} to {protocol_ptr:#x}') index += 2 ql.loader.dxe_context.protocols[handle] = dic @@ -464,14 +464,14 @@ def hook_UninstallMultipleProtocolInterfaces(ql: Qiling, address: int, params): GUID_ptr = ql.os.fcall.cc.getRawParam(index) protocol_ptr = ql.os.fcall.cc.getRawParam(index + 1) - GUID = str(ql.os.utils.read_guid(GUID_ptr)) + guid = str(ql.os.utils.read_guid(GUID_ptr)) - if GUID not in dic: + if guid not in dic: return EFI_INVALID_PARAMETER - del dic[GUID] + del dic[guid] - ql.log.info(f'Uninstalling protocol interface {guids_db.get(GUID.upper(), GUID)} from {protocol_ptr:#x}') + ql.log.info(f'Uninstalling protocol interface {guids_db.get(guid.upper(), guid)} from {protocol_ptr:#x}') index += 2 return EFI_SUCCESS diff --git a/qiling/os/uefi/const.py b/qiling/os/uefi/const.py index cc95b07ec..fa4581670 100644 --- a/qiling/os/uefi/const.py +++ b/qiling/os/uefi/const.py @@ -43,4 +43,5 @@ EFI_WARN_BUFFER_TOO_SMALL = EFI_MAX_BIT | 4 # @see: MdePkg\Include\Base.h -EFI_ERROR = lambda status: (status & EFI_MAX_BIT) != 0 +def EFI_ERROR(status: int) -> bool: + return (status & EFI_MAX_BIT) != 0 diff --git a/qiling/os/uefi/context.py b/qiling/os/uefi/context.py index 5e35fd7f8..e7643d4a6 100644 --- a/qiling/os/uefi/context.py +++ b/qiling/os/uefi/context.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from typing import Any, Mapping, Dict, MutableSequence, Optional, Tuple +from typing import Any, Mapping, Dict, MutableSequence, Optional, Tuple, Type from qiling import Qiling from qiling.os.memory import QlMemoryHeap @@ -8,6 +8,7 @@ from qiling.os.uefi.smst import EFI_SMM_SYSTEM_TABLE2 from qiling.os.uefi import utils + class UefiContext(ABC): def __init__(self, ql: Qiling): self.ql = ql @@ -75,12 +76,14 @@ def notify_protocol(self, handle: int, protocol: str, interface: int, from_hook: return utils.execute_protocol_notifications(self.ql, from_hook) + class DxeContext(UefiContext): def __init__(self, ql: Qiling): super().__init__(ql) self.conftable = DxeConfTable(ql) + class SmmContext(UefiContext): def __init__(self, ql: Qiling): super().__init__(ql) @@ -93,16 +96,13 @@ def __init__(self, ql: Qiling): # registered sw smi handlers self.swsmi_handlers: Mapping[int, Tuple[int, Mapping]] = {} -class UefiConfTable: - _struct_systbl: STRUCT - _fname_arrptr: str - _fname_nitems: str - def __init__(self, ql: Qiling): +class UefiConfTable: + def __init__(self, ql: Qiling, systbl_type: Type[STRUCT], fname_arrptr: str, fname_nitems: str): self.ql = ql - self.__arrptr_off = self._struct_systbl.offsetof(self._fname_arrptr) - self.__nitems_off = self._struct_systbl.offsetof(self._fname_nitems) + self.__arrptr_off = systbl_type.offsetof(fname_arrptr) + self.__nitems_off = systbl_type.offsetof(fname_nitems) @property @abstractmethod @@ -129,20 +129,16 @@ def nitems(self, value: int): def install(self, guid: str, table: int): ptr = self.find(guid) - append = ptr is None - if append: + if ptr is None: ptr = self.baseptr + self.nitems * EFI_CONFIGURATION_TABLE.sizeof() - append = True + self.nitems += 1 EFI_CONFIGURATION_TABLE( VendorGuid = utils.str_to_guid(guid), VendorTable = table ).save_to(self.ql.mem, ptr) - if append: - self.nitems += 1 - def find(self, guid: str) -> Optional[int]: ptr = self.baseptr nitems = self.nitems @@ -169,19 +165,19 @@ def get_vendor_table(self, guid: str) -> Optional[int]: # not found return None + class DxeConfTable(UefiConfTable): - _struct_systbl = EFI_SYSTEM_TABLE - _fname_arrptr = 'ConfigurationTable' - _fname_nitems = 'NumberOfTableEntries' + def __init__(self, ql: Qiling): + super().__init__(ql, EFI_SYSTEM_TABLE, 'ConfigurationTable', 'NumberOfTableEntries') @property def system_table(self) -> int: return self.ql.loader.gST + class SmmConfTable(UefiConfTable): - _struct_systbl = EFI_SMM_SYSTEM_TABLE2 - _fname_arrptr = 'SmmConfigurationTable' - _fname_nitems = 'NumberOfTableEntries' + def __init__(self, ql: Qiling): + super().__init__(ql, EFI_SMM_SYSTEM_TABLE2, 'SmmConfigurationTable', 'NumberOfTableEntries') @property def system_table(self) -> int: diff --git a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py index f7124c9ea..ea4d9aa94 100644 --- a/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py +++ b/qiling/os/uefi/protocols/EfiSmmSwDispatch2Protocol.py @@ -3,13 +3,19 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # -from qiling import Qiling +from typing import TYPE_CHECKING + from qiling.os.const import * from ..const import * from ..fncc import * from ..ProcessorBind import * from ..UefiBaseType import * + +if TYPE_CHECKING: + from qiling import Qiling + + MAXIMUM_SWI_VALUE = 0xff class EFI_SMM_SW_CONTEXT(STRUCT): @@ -61,9 +67,9 @@ def hook_Register(ql: Qiling, address: int, params): # a value of -1 indicates that the swsmi index for this handler is flexible and # should be assigned by the protocol if idx == ((1 << ql.arch.bits) - 1): - idx = next((i for i in range(1, MAXIMUM_SWI_VALUE) if i not in handlers), None) - - if idx is None: + try: + idx = next(i for i in range(1, MAXIMUM_SWI_VALUE) if i not in handlers) + except StopIteration: return EFI_OUT_OF_RESOURCES SwRegisterContext.SwSmiInputValue = idx @@ -101,9 +107,9 @@ def hook_UnRegister(ql: Qiling, address: int, params): handlers = ql.loader.smm_context.swsmi_handlers heap = ql.loader.smm_context.heap - idx = next((idx for idx, (_, args) in handlers.items() if args['DispatchHandle'] == DispatchHandle), None) - - if idx is None: + try: + idx = next(idx for idx, (_, args) in handlers.items() if args['DispatchHandle'] == DispatchHandle) + except StopIteration: return EFI_INVALID_PARAMETER heap.free(DispatchHandle) diff --git a/qiling/os/uefi/st.py b/qiling/os/uefi/st.py index 22260786f..b5fca9225 100644 --- a/qiling/os/uefi/st.py +++ b/qiling/os/uefi/st.py @@ -51,9 +51,9 @@ def initialize(ql: Qiling, context: UefiContext, gST: int): ql.loader.gST = gST - gBS = gST + EFI_SYSTEM_TABLE.sizeof() # boot services - gRT = gBS + EFI_BOOT_SERVICES.sizeof() # runtime services - gDS = gRT + EFI_RUNTIME_SERVICES.sizeof() # dxe services + gBS = gST + EFI_SYSTEM_TABLE.sizeof() # boot services + gRT = gBS + EFI_BOOT_SERVICES.sizeof() # runtime services + gDS = gRT + EFI_RUNTIME_SERVICES.sizeof() # dxe services cfg = gDS + ds.EFI_DXE_SERVICES.sizeof() # configuration tables array ql.log.info(f'Global tables:') diff --git a/qiling/os/uefi/utils.py b/qiling/os/uefi/utils.py index fdd35d5be..e84a3a1b2 100644 --- a/qiling/os/uefi/utils.py +++ b/qiling/os/uefi/utils.py @@ -4,12 +4,17 @@ # from uuid import UUID -from typing import Optional, Mapping +from typing import TYPE_CHECKING, Any, Optional, Mapping from qiling import Qiling from qiling.os.uefi.const import EFI_SUCCESS from qiling.os.uefi.UefiBaseType import EFI_GUID + +if TYPE_CHECKING: + from qiling.os.uefi.ProcessorBind import STRUCT + + def signal_event(ql: Qiling, event_id: int) -> None: event = ql.loader.events[event_id] @@ -61,7 +66,7 @@ def __notify_next(ql: Qiling): return True -def init_struct(ql: Qiling, base: int, descriptor: Mapping): +def init_struct(ql: Qiling, base: int, descriptor: Mapping[str, Any]) -> 'STRUCT': struct_class = descriptor['struct'] struct_fields = descriptor.get('fields', []) @@ -126,4 +131,4 @@ def GetEfiConfigurationTable(context, guid: str) -> Optional[int]: """Find a configuration table by its GUID. """ - return context.conftable.get_vendor_table(guid) \ No newline at end of file + return context.conftable.get_vendor_table(guid) From ac0743acaa67f2c638ccc4e07c36f5a93eddb112 Mon Sep 17 00:00:00 2001 From: yangcheng01 Date: Mon, 15 Jul 2024 15:37:16 +0800 Subject: [PATCH 13/15] solve a IDAPython relocation issue --- qiling/extensions/idaplugin/qilingida.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qiling/extensions/idaplugin/qilingida.py b/qiling/extensions/idaplugin/qilingida.py index f3524ec94..c3bb64ecf 100644 --- a/qiling/extensions/idaplugin/qilingida.py +++ b/qiling/extensions/idaplugin/qilingida.py @@ -906,7 +906,7 @@ def start(self, *args, **kwargs): elif self.ql.arch.bits == 64: self.baseaddr = int(self.ql.os.profile.get("OS64", "load_address"), 16) else: - self.baseaddr = 0x0 + self.baseaddr = get_imagebase() def run(self, begin=None, end=None): self.ql.run(begin, end) @@ -1115,7 +1115,7 @@ def ql_run_selection(self): def ql_set_pc(self): if self.qlinit: - ea = IDA.get_current_address() + ea = self.qlemu.ql_addr_from_ida(IDA.get_current_address()) self.qlemu.ql.arch.regs.arch_pc = ea logging.info(f"QIling PC set to {hex(ea)}") self.qlemu.status = self.qlemu.ql.save() From 1e175c045aef67f1aa48f5a8b5182154f9090422 Mon Sep 17 00:00:00 2001 From: elicn Date: Thu, 26 Sep 2024 15:58:29 +0300 Subject: [PATCH 14/15] Allow loading UEFI PE with the proper sections perms --- qiling/loader/pe_uefi.py | 57 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) diff --git a/qiling/loader/pe_uefi.py b/qiling/loader/pe_uefi.py index 5be9dd294..6ae6f00d9 100644 --- a/qiling/loader/pe_uefi.py +++ b/qiling/loader/pe_uefi.py @@ -7,6 +7,8 @@ from typing import Any, Mapping, Optional, Sequence from pefile import PE +from unicorn.unicorn_const import UC_PROT_READ, UC_PROT_WRITE, UC_PROT_EXEC + from qiling import Qiling from qiling.const import QL_ARCH from qiling.exception import QlErrorArch, QlMemoryMappedError @@ -97,17 +99,64 @@ def map_and_load(self, path: str, context: UefiContext, exec_now: bool=False): # use image base only if it does not point to NULL image_base = pe.OPTIONAL_HEADER.ImageBase or context.next_image_base image_size = ql.mem.align_up(pe.OPTIONAL_HEADER.SizeOfImage) + image_name = os.path.basename(path) assert (image_base % ql.mem.pagesize) == 0, 'image base is expected to be page-aligned' if image_base != pe.OPTIONAL_HEADER.ImageBase: pe.relocate_image(image_base) - pe.parse_data_directories() - data = bytes(pe.get_memory_mapped_image()) + # pe.parse_data_directories() + + sec_alignment = pe.OPTIONAL_HEADER.SectionAlignment + + def __map_sections(): + """Load file sections to memory, each in its own memory region protected by + its defined permissions. That allows separation of code and data, which makes + it easier to detect abnomal behavior or memory corruptions. + """ + + # load the header + hdr_data = bytes(pe.header) + hdr_base = image_base + hdr_size = ql.mem.align_up(len(hdr_data), sec_alignment) + hdr_perm = UC_PROT_READ + + ql.mem.map(hdr_base, hdr_size, hdr_perm, image_name) + ql.mem.write(hdr_base, hdr_data) + + # load sections + for section in pe.sections: + if not section.IMAGE_SCN_MEM_DISCARDABLE: + sec_name = section.Name.rstrip(b'\x00').decode() + sec_data = bytes(section.get_data(ignore_padding=True)) + sec_base = image_base + section.get_VirtualAddress_adj() + sec_size = ql.mem.align_up(len(sec_data), sec_alignment) + + sec_perm = sum(( + section.IMAGE_SCN_MEM_READ * UC_PROT_READ, + section.IMAGE_SCN_MEM_WRITE * UC_PROT_WRITE, + section.IMAGE_SCN_MEM_EXECUTE * UC_PROT_EXEC + )) + + ql.mem.map(sec_base, sec_size, sec_perm, f'{image_name} ({sec_name})') + ql.mem.write(sec_base, sec_data) + + def __map_all(): + """Load the entire file to memory as a single memory region. + """ + + data = bytes(pe.get_memory_mapped_image()) + + ql.mem.map(image_base, image_size, info=image_name) + ql.mem.write(image_base, data) + + # if sections are aligned to page, we can map them separately + if (sec_alignment % ql.mem.pagesize) == 0: + __map_sections() + else: + __map_all() - ql.mem.map(image_base, image_size, info=os.path.basename(path)) - ql.mem.write(image_base, data) ql.log.info(f'Module {path} loaded to {image_base:#x}') entry_point = image_base + pe.OPTIONAL_HEADER.AddressOfEntryPoint From 6cd5f26361d43504355552f834fa33b0355dc554 Mon Sep 17 00:00:00 2001 From: elicn Date: Thu, 10 Oct 2024 17:42:28 +0300 Subject: [PATCH 15/15] Imports cleanup and annotation fixes --- qiling/os/uefi/ProcessorBind.py | 7 +-- qiling/os/uefi/protocols/PcdProtocol.py | 69 ++++++++++++++----------- 2 files changed, 40 insertions(+), 36 deletions(-) diff --git a/qiling/os/uefi/ProcessorBind.py b/qiling/os/uefi/ProcessorBind.py index 8d3c4a449..a68c20df3 100644 --- a/qiling/os/uefi/ProcessorBind.py +++ b/qiling/os/uefi/ProcessorBind.py @@ -6,15 +6,12 @@ from __future__ import annotations import ctypes -from contextlib import contextmanager + from functools import lru_cache -from typing import TYPE_CHECKING, Mapping, Sequence, Union, Optional +from typing import Mapping, Sequence, Union from qiling.os.struct import BaseStructEL -if TYPE_CHECKING: - from qiling import Qiling - bits = 64 psize = bits // 8 diff --git a/qiling/os/uefi/protocols/PcdProtocol.py b/qiling/os/uefi/protocols/PcdProtocol.py index 8fdba9aed..656162dbf 100644 --- a/qiling/os/uefi/protocols/PcdProtocol.py +++ b/qiling/os/uefi/protocols/PcdProtocol.py @@ -3,12 +3,19 @@ # Cross Platform and Multi Architecture Advanced Binary Emulation Framework # +from __future__ import annotations +from typing import TYPE_CHECKING + from qiling.os.const import * from ..fncc import dxeapi from ..ProcessorBind import * from ..UefiBaseType import EFI_GUID, EFI_STATUS +if TYPE_CHECKING: + from qiling import Qiling + + PCD_PROTOCOL_CALLBACK = FUNCPTR(VOID, PTR(EFI_GUID), UINTN, PTR(VOID), UINTN) PCD_PROTOCOL_SET_SKU = FUNCPTR(VOID, UINTN) @@ -83,126 +90,126 @@ class PCD_PROTOCOL(STRUCT): @dxeapi(params = { "SkuId": UINT }) -def hook_SetSku(ql, address, params): +def hook_SetSku(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_Get8(ql, address, params): +def hook_Get8(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_Get16(ql, address, params): +def hook_Get16(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_Get32(ql, address, params): +def hook_Get32(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_Get64(ql, address, params): +def hook_Get64(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_GetPtr(ql, address, params): +def hook_GetPtr(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_GetBool(ql, address, params): +def hook_GetBool(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT }) -def hook_GetSize(ql, address, params): +def hook_GetSize(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_Get8Ex(ql, address, params): +def hook_Get8Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_Get16Ex(ql, address, params): +def hook_Get16Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_Get32Ex(ql, address, params): +def hook_Get32Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_Get64Ex(ql, address, params): +def hook_Get64Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_GetPtrEx(ql, address, params): +def hook_GetPtrEx(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_GetBoolEx(ql, address, params): +def hook_GetBoolEx(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": UINT }) -def hook_GetSizeEx(ql, address, params): +def hook_GetSizeEx(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT, "Value": INT }) -def hook_Set8(ql, address, params): +def hook_Set8(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT, "Value": INT }) -def hook_Set16(ql, address, params): +def hook_Set16(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT, "Value": INT }) -def hook_Set32(ql, address, params): +def hook_Set32(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT, "Value": INT }) -def hook_Set64(ql, address, params): +def hook_Set64(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -210,14 +217,14 @@ def hook_Set64(ql, address, params): "SizeOfValue": POINTER, "Buffer": POINTER }) -def hook_SetPtr(ql, address, params): +def hook_SetPtr(ql: Qiling, address: int, params): pass @dxeapi(params = { "TokenNumber": UINT, "Value": INT }) -def hook_SetBool(ql, address, params): +def hook_SetBool(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -225,7 +232,7 @@ def hook_SetBool(ql, address, params): "TokenNumber": UINT, "Value": INT }) -def hook_Set8Ex(ql, address, params): +def hook_Set8Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -233,7 +240,7 @@ def hook_Set8Ex(ql, address, params): "TokenNumber": UINT, "Value": INT }) -def hook_Set16Ex(ql, address, params): +def hook_Set16Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -241,7 +248,7 @@ def hook_Set16Ex(ql, address, params): "TokenNumber": UINT, "Value": INT }) -def hook_Set32Ex(ql, address, params): +def hook_Set32Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -249,7 +256,7 @@ def hook_Set32Ex(ql, address, params): "TokenNumber": UINT, "Value": INT }) -def hook_Set64Ex(ql, address, params): +def hook_Set64Ex(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -258,7 +265,7 @@ def hook_Set64Ex(ql, address, params): "SizeOfValue": POINTER, "Buffer": POINTER }) -def hook_SetPtrEx(ql, address, params): +def hook_SetPtrEx(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -266,7 +273,7 @@ def hook_SetPtrEx(ql, address, params): "TokenNumber": UINT, "Value": INT }) -def hook_SetBoolEx(ql, address, params): +def hook_SetBoolEx(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -274,7 +281,7 @@ def hook_SetBoolEx(ql, address, params): "TokenNumber": UINT, "CallBackFunction": POINTER }) -def hook_CallbackOnSet(ql, address, params): +def hook_CallbackOnSet(ql: Qiling, address: int, params): pass @dxeapi(params = { @@ -282,20 +289,20 @@ def hook_CallbackOnSet(ql, address, params): "TokenNumber": UINT, "CallBackFunction": POINTER }) -def hook_CancelCallback(ql, address, params): +def hook_CancelCallback(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": GUID, "TokenNumber": POINTER }) -def hook_GetNextToken(ql, address, params): +def hook_GetNextToken(ql: Qiling, address: int, params): pass @dxeapi(params = { "Guid": POINTER }) -def hook_GetNextTokenSpace(ql, address, params): +def hook_GetNextTokenSpace(ql: Qiling, address: int, params): pass