예제 #1
0
class SmmState(object):

    PAGE_SIZE = 0x1000

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

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

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

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

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

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

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

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

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

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

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

        self.protocols[handle][guid] = address
예제 #3
0
class UefiContext(ABC):
    def __init__(self, ql):
        self.ql = ql
        self.heap = None
        self.protocols = {}

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

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

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

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

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

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

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

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

        self.protocols[handle][guid] = address

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

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

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

        instance = EFI_CONFIGURATION_TABLE()
        instance.VendorGuid = str_to_guid(guid)
        instance.VendorTable = table
        instance.saveTo(self.ql, ptr)
예제 #4
0
파일: pe_uefi.py 프로젝트: zha0/qiling
class QlLoaderPE_UEFI(QlLoader):
    def __init__(self, ql):
        super(QlLoaderPE_UEFI, self).__init__(ql)
        self.ql = ql
        self.modules = []
        self.events = {}
        self.handle_dict = {}
        self.notify_list = []
        self.next_image_base = 0x10000

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.execute_next_module()

    def restore_runtime_services(self):
        self.ql.mem.write(self.runtime_services_ptr,
                          convert_struct_to_bytes(self.runtime_services))
예제 #5
0
파일: context.py 프로젝트: ucgJhe/qiling
class UefiContext(ABC):
	def __init__(self, ql: Qiling):
		self.ql = ql
		self.heap = None
		self.protocols = {}

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

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

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

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

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

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

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

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

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

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

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

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

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

		instance = EFI_CONFIGURATION_TABLE()
		instance.VendorGuid = str_to_guid(guid)
		instance.VendorTable = table
		instance.saveTo(self.ql, ptr)
예제 #6
0
class UefiContext(ABC):
    def __init__(self, ql: Qiling):
        self.ql = ql
        self.heap: QlMemoryHeap
        self.top_of_stack: int
        self.protocols = {}
        self.loaded_image_protocol_modules: MutableSequence[int] = []
        self.next_image_base: int

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

        self.conftable: UefiConfTable
        self.end_of_execution_ptr: int

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

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

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

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

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

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

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

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

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

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

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

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

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

        return utils.execute_protocol_notifications(self.ql, from_hook)