diff options
| -rw-r--r-- | platform/efi/efi_resolver/include/DxeResolver.h | 31 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/GuidRenderer.h | 15 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/ModuleType.h | 23 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/PeiResolver.h | 27 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/Resolver.h | 93 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/TypePropagation.h | 15 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/include/Utils.h | 46 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/DxeResolver.cpp | 403 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/GuidRenderer.cpp | 63 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/PeiResolver.cpp | 444 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/Plugin.cpp | 69 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/Resolver.cpp | 1141 | ||||
| -rw-r--r-- | platform/efi/efi_resolver/src/TypePropagation.cpp | 303 |
13 files changed, 1406 insertions, 1267 deletions
diff --git a/platform/efi/efi_resolver/include/DxeResolver.h b/platform/efi/efi_resolver/include/DxeResolver.h index 3515b94a..eef6e6c2 100644 --- a/platform/efi/efi_resolver/include/DxeResolver.h +++ b/platform/efi/efi_resolver/include/DxeResolver.h @@ -2,24 +2,25 @@ #include "Resolver.h" -class DxeResolver : Resolver { - bool resolveBootServices(); - bool resolveRuntimeServices(); +class DxeResolver : Resolver +{ + bool resolveBootServices(); + bool resolveRuntimeServices(); - bool resolveSmmTables(string serviceName, string tableName); - bool resolveSmmServices(); - bool resolveSmiHandlers(); + bool resolveSmmTables(string serviceName, string tableName); + bool resolveSmmServices(); + bool resolveSmiHandlers(); public: - /*! - resolve BootServices and RuntimeServices, define protocol types that loaded by BootServices - */ - bool resolveDxe(); + /*! + resolve BootServices and RuntimeServices, define protocol types that loaded by BootServices + */ + bool resolveDxe(); - /*! - Define MMST/SMMST and resolve SMM related protocols - */ - bool resolveSmm(); + /*! + Define MMST/SMMST and resolve SMM related protocols + */ + bool resolveSmm(); - DxeResolver(Ref<BinaryView> view, Ref<BackgroundTask> task); + DxeResolver(Ref<BinaryView> view, Ref<BackgroundTask> task); };
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/GuidRenderer.h b/platform/efi/efi_resolver/include/GuidRenderer.h index 30bd9126..e30aa880 100644 --- a/platform/efi/efi_resolver/include/GuidRenderer.h +++ b/platform/efi/efi_resolver/include/GuidRenderer.h @@ -6,16 +6,15 @@ using namespace BinaryNinja; using namespace std; -class EfiGuidRenderer : public BinaryNinja::DataRenderer { - EfiGuidRenderer() = default; +class EfiGuidRenderer : public BinaryNinja::DataRenderer +{ + EfiGuidRenderer() = default; public: - bool IsValidForData(BinaryView*, uint64_t address, Type*, - vector<pair<Type*, size_t>>&) override; + bool IsValidForData(BinaryView*, uint64_t address, Type*, vector<pair<Type*, size_t>>&) override; - vector<DisassemblyTextLine> GetLinesForData( - BinaryView*, uint64_t address, Type*, const vector<InstructionTextToken>& prefix, - size_t width, vector<pair<Type*, size_t>>&) override; + vector<DisassemblyTextLine> GetLinesForData(BinaryView*, uint64_t address, Type*, + const vector<InstructionTextToken>& prefix, size_t width, vector<pair<Type*, size_t>>&) override; - static void Register(); + static void Register(); };
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/ModuleType.h b/platform/efi/efi_resolver/include/ModuleType.h index 81b579b9..187dcc36 100644 --- a/platform/efi/efi_resolver/include/ModuleType.h +++ b/platform/efi/efi_resolver/include/ModuleType.h @@ -4,19 +4,20 @@ using namespace BinaryNinja; -enum EFIModuleType { - UNKNOWN, - PEI, - DXE, +enum EFIModuleType +{ + UNKNOWN, + PEI, + DXE, }; static inline EFIModuleType identifyModuleType(BinaryView* bv) { - std::string viewType = bv->GetCurrentView(); - if (viewType == "Linear:PE") - return DXE; - else if (viewType == "Linear:TE") - return PEI; - else - return UNKNOWN; + std::string viewType = bv->GetCurrentView(); + if (viewType == "Linear:PE") + return DXE; + else if (viewType == "Linear:TE") + return PEI; + else + return UNKNOWN; }
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/PeiResolver.h b/platform/efi/efi_resolver/include/PeiResolver.h index 76827a1a..2ecf8ace 100644 --- a/platform/efi/efi_resolver/include/PeiResolver.h +++ b/platform/efi/efi_resolver/include/PeiResolver.h @@ -2,19 +2,20 @@ #include "Resolver.h" -class PeiResolver : Resolver { - bool resolvePeiIdt(); - bool resolvePeiMrc(); - bool resolvePeiMrs(); - bool resolvePlatformPointers(); - bool resolvePeiDescriptors(); - bool resolvePeiServices(); +class PeiResolver : Resolver +{ + bool resolvePeiIdt(); + bool resolvePeiMrc(); + bool resolvePeiMrs(); + bool resolvePlatformPointers(); + bool resolvePeiDescriptors(); + bool resolvePeiServices(); public: - /*! - resolve Pei related types and PPIs, this function will also resolve processor-specific pointers - and tried to define the EFI_PEI_DESCRIPTORS - */ - bool resolvePei(); - PeiResolver(Ref<BinaryView> view, Ref<BackgroundTask> task); + /*! + resolve Pei related types and PPIs, this function will also resolve processor-specific pointers + and tried to define the EFI_PEI_DESCRIPTORS + */ + bool resolvePei(); + PeiResolver(Ref<BinaryView> view, Ref<BackgroundTask> task); };
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/Resolver.h b/platform/efi/efi_resolver/include/Resolver.h index 7bbd3b99..91bb1862 100644 --- a/platform/efi/efi_resolver/include/Resolver.h +++ b/platform/efi/efi_resolver/include/Resolver.h @@ -16,61 +16,60 @@ using namespace std; typedef array<uint8_t, 16> EFI_GUID; -class Resolver { +class Resolver +{ protected: - Ref<BinaryView> m_view; - Ref<BackgroundTask> m_task; - size_t m_width; - map<EFI_GUID, pair<string, string>> m_protocol; - map<EFI_GUID, string> m_user_guids; + Ref<BinaryView> m_view; + Ref<BackgroundTask> m_task; + size_t m_width; + map<EFI_GUID, pair<string, string>> m_protocol; + map<EFI_GUID, string> m_user_guids; - vector<pair<uint64_t, string>> m_service_usages; - vector<pair<uint64_t, string>> m_protocol_usages; - vector<pair<uint64_t, EFI_GUID>> m_guid_usages; - vector<pair<uint64_t, string>> m_variable_usages; + vector<pair<uint64_t, string>> m_service_usages; + vector<pair<uint64_t, string>> m_protocol_usages; + vector<pair<uint64_t, EFI_GUID>> m_guid_usages; + vector<pair<uint64_t, string>> m_variable_usages; - bool parseUserGuidIfExists(const string& filePath); - bool parseProtocolMapping(const string& filePath); + bool parseUserGuidIfExists(const string& filePath); + bool parseProtocolMapping(const string& filePath); - /*! - For backward compatibility, if a user saved a bndb with older version Binary Ninja - this function will try to retrieve types from Platform Types if it doesn't find one - in BinaryView - */ - Ref<Type> GetTypeFromViewAndPlatform(string type_name); - void initProtocolMapping(); + /*! + For backward compatibility, if a user saved a bndb with older version Binary Ninja + this function will try to retrieve types from Platform Types if it doesn't find one + in BinaryView + */ + Ref<Type> GetTypeFromViewAndPlatform(string type_name); + void initProtocolMapping(); public: - bool setModuleEntry(EFIModuleType fileType); - bool resolveGuidInterface(Ref<Function> func, uint64_t addr, int guid_pos, int interface_pos); - Resolver(Ref<BinaryView> view, Ref<BackgroundTask> task); + bool setModuleEntry(EFIModuleType fileType); + bool resolveGuidInterface(Ref<Function> func, uint64_t addr, int guid_pos, int interface_pos); + Resolver(Ref<BinaryView> view, Ref<BackgroundTask> task); - pair<string, string> lookupGuid(EFI_GUID guidBytes); - pair<string, string> defineAndLookupGuid(uint64_t addr); + pair<string, string> lookupGuid(EFI_GUID guidBytes); + pair<string, string> defineAndLookupGuid(uint64_t addr); - string nonConflictingName(const string& basename); - static string nonConflictingLocalName(Ref<Function> func, const string& basename); + string nonConflictingName(const string& basename); + static string nonConflictingLocalName(Ref<Function> func, const string& basename); - /*! - Define the structure used at the callsite with type `typeName`, propagate it to the data section. If it's a structure type, define it fields - according to the `followFields` parameter. The input `addr` should be a call instruction - \param func the function that contains the callsite (it's parent function) - \param addr address of the callsite - \param typeName the type that need to define - \param paramIdx the parameter index that want to define - \param followFields whether to define the structure's fields if they are pointers - \return False if failed + /*! + Define the structure used at the callsite with type `typeName`, propagate it to the data section. If it's a + structure type, define it fields according to the `followFields` parameter. The input `addr` should be a call + instruction \param func the function that contains the callsite (it's parent function) \param addr address of the + callsite \param typeName the type that need to define \param paramIdx the parameter index that want to define \param + followFields whether to define the structure's fields if they are pointers \return False if failed - \b Example: - \code{.cpp} - refs = bv->GetCodeReferencesForType(QualifiedName("EFI_GET_VARIABLE")); - for (auto ref : refs) - { - // ... some checking, need to make sure is a call instruction - bool ok = defineTypeAtCallsite(ref.func, ref.addr, "EFI_GUID", 2, false); - } - \endcode - */ - bool defineTypeAtCallsite(Ref<Function> func, uint64_t addr, string typeName, int paramIdx, bool followFields = false); - vector<HighLevelILInstruction> HighLevelILExprsAt(Ref<Function> func, Ref<Architecture> arch, uint64_t addr); + \b Example: + \code{.cpp} + refs = bv->GetCodeReferencesForType(QualifiedName("EFI_GET_VARIABLE")); + for (auto ref : refs) + { + // ... some checking, need to make sure is a call instruction + bool ok = defineTypeAtCallsite(ref.func, ref.addr, "EFI_GUID", 2, false); + } + \endcode + */ + bool defineTypeAtCallsite( + Ref<Function> func, uint64_t addr, string typeName, int paramIdx, bool followFields = false); + vector<HighLevelILInstruction> HighLevelILExprsAt(Ref<Function> func, Ref<Architecture> arch, uint64_t addr); };
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/TypePropagation.h b/platform/efi/efi_resolver/include/TypePropagation.h index 2ba131ba..1985e2ab 100644 --- a/platform/efi/efi_resolver/include/TypePropagation.h +++ b/platform/efi/efi_resolver/include/TypePropagation.h @@ -5,13 +5,14 @@ using namespace BinaryNinja; -class TypePropagation { - Ref<BinaryView> m_view; - std::deque<uint64_t> m_queue; - Ref<Platform> m_platform; +class TypePropagation +{ + Ref<BinaryView> m_view; + std::deque<uint64_t> m_queue; + Ref<Platform> m_platform; public: - TypePropagation(BinaryView* view); - bool propagateFuncParamTypes(Function* func); - bool propagateFuncParamTypes(Function* func, SSAVariable ssa_var); + TypePropagation(BinaryView* view); + bool propagateFuncParamTypes(Function* func); + bool propagateFuncParamTypes(Function* func, SSAVariable ssa_var); };
\ No newline at end of file diff --git a/platform/efi/efi_resolver/include/Utils.h b/platform/efi/efi_resolver/include/Utils.h index f2c371a8..981908b2 100644 --- a/platform/efi/efi_resolver/include/Utils.h +++ b/platform/efi/efi_resolver/include/Utils.h @@ -6,31 +6,35 @@ using namespace BinaryNinja; static inline std::string GetOriginalTypeName(Ref<Type> type) { - std::string result; - if (type->IsPointer()) { - if (type->GetChildType().GetValue()->IsNamedTypeRefer()) { - return type->GetChildType().GetValue()->GetNamedTypeReference()->GetName().GetString(); - } - return type->GetTypeName().GetString(); - } - if (type->IsNamedTypeRefer()) - return type->GetNamedTypeReference()->GetName().GetString(); + std::string result; + if (type->IsPointer()) + { + if (type->GetChildType().GetValue()->IsNamedTypeRefer()) + { + return type->GetChildType().GetValue()->GetNamedTypeReference()->GetName().GetString(); + } + return type->GetTypeName().GetString(); + } + if (type->IsNamedTypeRefer()) + return type->GetNamedTypeReference()->GetName().GetString(); - return type->GetTypeName().GetString(); + return type->GetTypeName().GetString(); } static inline std::string GetVarNameForTypeStr(const std::string typeStr) { - std::istringstream iss(typeStr); - std::string word; - std::string result; + std::istringstream iss(typeStr); + std::string word; + std::string result; - while (std::getline(iss, word, '_')) { - if (!word.empty()) { - word[0] = std::toupper(word[0]); - std::transform(word.begin() + 1, word.end(), word.begin() + 1, ::tolower); - result += word; - } - } - return result; + while (std::getline(iss, word, '_')) + { + if (!word.empty()) + { + word[0] = std::toupper(word[0]); + std::transform(word.begin() + 1, word.end(), word.begin() + 1, ::tolower); + result += word; + } + } + return result; } diff --git a/platform/efi/efi_resolver/src/DxeResolver.cpp b/platform/efi/efi_resolver/src/DxeResolver.cpp index f801a8e5..f31c42ae 100644 --- a/platform/efi/efi_resolver/src/DxeResolver.cpp +++ b/platform/efi/efi_resolver/src/DxeResolver.cpp @@ -2,254 +2,273 @@ bool DxeResolver::resolveBootServices() { - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_BOOT_SERVICES")); - // search reference of `EFI_BOOT_SERVICES` so that we can easily parse different services + m_task->SetProgressText("Resolving Boot Services..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_BOOT_SERVICES")); + // search reference of `EFI_BOOT_SERVICES` so that we can easily parse different services - for (auto& ref : refs) { - if (m_task->IsCancelled()) - return false; + for (auto& ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) { - auto dest = instr.GetDestExpr(); - if (dest.operation != MLIL_LOAD_STRUCT_SSA) - continue; - auto offset = dest.GetOffset(); + if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) + { + auto dest = instr.GetDestExpr(); + if (dest.operation != MLIL_LOAD_STRUCT_SSA) + continue; + auto offset = dest.GetOffset(); - if (offset == 0x18 + m_width * 16 || offset == 0x18 + m_width * 32) { - // HandleProtocol, OpenProtocol - // Guid:1, Interface:2 - resolveGuidInterface(ref.func, ref.addr, 1, 2); - } else if (offset == 0x18 + m_width * 37) { - // LocateProtocol - resolveGuidInterface(ref.func, ref.addr, 0, 2); - } - } - } - return true; + if (offset == 0x18 + m_width * 16 || offset == 0x18 + m_width * 32) + { + // HandleProtocol, OpenProtocol + // Guid:1, Interface:2 + resolveGuidInterface(ref.func, ref.addr, 1, 2); + } + else if (offset == 0x18 + m_width * 37) + { + // LocateProtocol + resolveGuidInterface(ref.func, ref.addr, 0, 2); + } + } + } + return true; } bool DxeResolver::resolveRuntimeServices() { - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_RUNTIME_SERVICES")); + m_task->SetProgressText("Resolving Runtime Services..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_RUNTIME_SERVICES")); - for (auto &ref : refs) { - if (m_task->IsCancelled()) - return false; + for (auto& ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) { - auto dest = instr.GetDestExpr(); - if (dest.operation != MLIL_LOAD_STRUCT_SSA) - continue; - auto offset = dest.GetOffset(); - if (offset == 0x18 + m_width * 6 || offset == 0x18 + m_width * 8) { - // TODO implement this - // GetVariable and SetVariable - } - } - } - return true; + if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) + { + auto dest = instr.GetDestExpr(); + if (dest.operation != MLIL_LOAD_STRUCT_SSA) + continue; + auto offset = dest.GetOffset(); + if (offset == 0x18 + m_width * 6 || offset == 0x18 + m_width * 8) + { + // TODO implement this + // GetVariable and SetVariable + } + } + } + return true; } bool DxeResolver::resolveSmmTables(string serviceName, string tableName) { - auto refs = m_view->GetCodeReferencesForType(QualifiedName(serviceName)); - // both versions use the same type, so we only need to search for this one - for (auto &ref : refs) { - if (m_task->IsCancelled()) - return false; + m_task->SetProgressText("Defining MM tables..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName(serviceName)); + // both versions use the same type, so we only need to search for this one + for (auto& ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - if (instr.operation != MLIL_CALL_SSA && instr.operation != MLIL_TAILCALL_SSA) - continue; + if (instr.operation != MLIL_CALL_SSA && instr.operation != MLIL_TAILCALL_SSA) + continue; - auto destExpr = instr.GetDestExpr(); - if (destExpr.operation != MLIL_LOAD_STRUCT_SSA) - continue; + auto destExpr = instr.GetDestExpr(); + if (destExpr.operation != MLIL_LOAD_STRUCT_SSA) + continue; - if (destExpr.GetOffset() != 8) - continue; + if (destExpr.GetOffset() != 8) + continue; - auto params = instr.GetParameterExprs(); - if (params.size() < 2) - continue; + auto params = instr.GetParameterExprs(); + if (params.size() < 2) + continue; - auto smstAddr = params[1]; - if (smstAddr.operation != MLIL_CONST_PTR) - continue; + auto smstAddr = params[1]; + if (smstAddr.operation != MLIL_CONST_PTR) + continue; - QualifiedNameAndType result; - string errors; - bool ok = m_view->ParseTypeString(tableName, result, errors); - if (!ok) - return false; - m_view->DefineDataVariable(smstAddr.GetValue().value, result.type); - m_view->DefineUserSymbol(new Symbol(DataSymbol, "gMmst", smstAddr.GetValue().value)); - m_view->UpdateAnalysisAndWait(); - } - return true; + QualifiedNameAndType result; + string errors; + bool ok = m_view->ParseTypeString(tableName, result, errors); + if (!ok) + return false; + m_view->DefineDataVariable(smstAddr.GetValue().value, result.type); + m_view->DefineUserSymbol(new Symbol(DataSymbol, "gMmst", smstAddr.GetValue().value)); + m_view->UpdateAnalysisAndWait(); + } + return true; } bool DxeResolver::resolveSmmServices() { - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_MM_SYSTEM_TABLE")); - auto refs_smm = m_view->GetCodeReferencesForType(QualifiedName("EFI_SMM_SYSTEM_TABLE2")); - // These tables have same type information, we can just iterate once - refs.insert(refs.end(), refs_smm.begin(), refs_smm.end()); + m_task->SetProgressText("Resolving MM services..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_MM_SYSTEM_TABLE")); + auto refs_smm = m_view->GetCodeReferencesForType(QualifiedName("EFI_SMM_SYSTEM_TABLE2")); + // These tables have same type information, we can just iterate once + refs.insert(refs.end(), refs_smm.begin(), refs_smm.end()); - for (auto &ref : refs) { - if (m_task->IsCancelled()) - return false; + for (auto& ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) { - auto dest = instr.GetDestExpr(); - if (dest.operation != MLIL_LOAD_STRUCT_SSA) - continue; - auto offset = dest.GetOffset(); + if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) + { + auto dest = instr.GetDestExpr(); + if (dest.operation != MLIL_LOAD_STRUCT_SSA) + continue; + auto offset = dest.GetOffset(); - if (offset == 0x18 + m_width * 0x14) { - // SmmHandleProtocol - resolveGuidInterface(ref.func, ref.addr, 1, 2); - } else if (offset == 0x18 + m_width * 0x17) { - // SmmLocateProtocol - resolveGuidInterface(ref.func, ref.addr, 0, 2); - } - } - } - return true; + if (offset == 0x18 + m_width * 0x14) + { + // SmmHandleProtocol + resolveGuidInterface(ref.func, ref.addr, 1, 2); + } + else if (offset == 0x18 + m_width * 0x17) + { + // SmmLocateProtocol + resolveGuidInterface(ref.func, ref.addr, 0, 2); + } + } + } + return true; } bool DxeResolver::resolveSmiHandlers() { - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_MM_SW_REGISTER")); - for (auto &ref : refs) - { - if (m_task->IsCancelled()) - return false; + m_task->SetProgressText("Resolving SMI Handlers..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_MM_SW_REGISTER")); + auto refs_smm_sw = m_view->GetCodeReferencesForType(QualifiedName("EFI_SMM_SW_REGISTER2")); + auto refs_mm_sx = m_view->GetCodeReferencesForType(QualifiedName("EFI_MM_SX_REGISTER")); + auto refs_smm_sx = m_view->GetCodeReferencesForType(QualifiedName("EFI_SMM_SX_REGISTER2")); + // Define them together - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + refs.insert(refs.end(), refs_smm_sw.begin(), refs_smm_sw.end()); + refs.insert(refs.end(), refs_smm_sx.begin(), refs_smm_sw.end()); + refs.insert(refs.end(), refs_mm_sx.begin(), refs_mm_sx.end()); - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + for (auto& ref : refs) + { + if (m_task->IsCancelled()) + return false; - if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) - { - auto dest = instr.GetDestExpr(); - if (dest.operation != MLIL_LOAD_STRUCT_SSA) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto offset = dest.GetOffset(); - if (offset == 0) { - /* EFI_MM_SW_REGISTER, we want to rename the second parameter according to the third parameter - typedef enum EFI_STATUS (* EFI_MM_SW_REGISTER)( - struct EFI_MM_SW_DISPATCH_PROTOCOL* This, - EFI_MM_HANDLER_ENTRY_POINT DispatchFunction, - struct EFI_MM_SW_REGISTER_CONTEXT* - RegisterContext, EFI_HANDLE* DispatchHandle); */ + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - auto parameters = instr.GetParameterExprs(); - if (parameters.size() < 3) - continue; + if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) + { + auto dest = instr.GetDestExpr(); + if (dest.operation != MLIL_LOAD_STRUCT_SSA) + continue; - auto dispatchFunction = parameters[1]; - auto registerContext = parameters[2]; + auto offset = dest.GetOffset(); + if (offset == 0) + { + auto parameters = instr.GetParameterExprs(); + if (parameters.size() < 4) + continue; - // Determine the function name according to the registerContext - /* struct EFI_MM_SW_REGISTER_CONTEXT - * { - * UINTN SwMmiInputValue; - * }; - */ - string funcName = "SmiHandler"; + // TODO we should be able to parse registerContext, but it's normally an aliased variable + // and we have some issues relate to that + auto dispatchFunction = parameters[1]; + if (dispatchFunction.operation != MLIL_CONST_PTR) + continue; + auto funcAddr = static_cast<uint64_t>(dispatchFunction.GetConstant()); + auto targetFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), funcAddr); + auto funcType = targetFunc->GetType(); + std::ostringstream ss; + ss << "SmiHandler_" << std::hex << funcAddr; + string funcName = ss.str(); - if (dispatchFunction.operation != MLIL_CONST_PTR) - continue; - auto funcAddr = static_cast<uint64_t> (dispatchFunction.GetConstant()); - auto targetFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), funcAddr); - auto funcType = targetFunc->GetType(); - // typedef enum - string handleTypeStr = "EFI_STATUS SmiHandler(EFI_HANDLE DispatchHandle, VOID* Context, VOID* CommBuffer, UINTN* CommBufferSize);"; - QualifiedNameAndType result; - string errors; - bool ok = m_view->ParseTypeString(handleTypeStr, result, errors); - if (!ok) - return false; - targetFunc->SetUserType(result.type); - m_view->DefineUserSymbol(new Symbol(FunctionSymbol, funcName, funcAddr)); - m_view->UpdateAnalysisAndWait(); + // typedef enum + string handleTypeStr = + "EFI_STATUS SmiHandler(EFI_HANDLE DispatchHandle, VOID* Context, VOID* CommBuffer, UINTN* " + "CommBufferSize);"; + QualifiedNameAndType result; + string errors; + bool ok = m_view->ParseTypeString(handleTypeStr, result, errors); + if (!ok) + return false; + targetFunc->SetUserType(result.type); + m_view->DefineUserSymbol(new Symbol(FunctionSymbol, funcName, funcAddr)); + m_view->UpdateAnalysisAndWait(); - // After setting the type, we want to propagate the parameters' type - TypePropagation propagator(m_view); - propagator.propagateFuncParamTypes(targetFunc); - } - } - } - return true; + // After setting the type, we want to propagate the parameters' type + TypePropagation propagator(m_view); + propagator.propagateFuncParamTypes(targetFunc); + } + } + } + return true; } bool DxeResolver::resolveDxe() { - if (!resolveBootServices()) - return false; - if (!resolveRuntimeServices()) - return false; - return true; + if (!resolveBootServices()) + return false; + if (!resolveRuntimeServices()) + return false; + return true; } bool DxeResolver::resolveSmm() { - if (!resolveSmmTables("EFI_SMM_GET_SMST_LOCATION2", "EFI_SMM_SYSTEM_TABLE2*")) - return false; - if (!resolveSmmTables("EFI_MM_GET_MMST_LOCATION", "EFI_MM_SYSTEM_TABLE*")) - return false; - if (!resolveSmmServices()) - return false; - if (!resolveSmiHandlers()) - return false; - return true; + if (!resolveSmmTables("EFI_SMM_GET_SMST_LOCATION2", "EFI_SMM_SYSTEM_TABLE2*")) + return false; + if (!resolveSmmTables("EFI_MM_GET_MMST_LOCATION", "EFI_MM_SYSTEM_TABLE*")) + return false; + if (!resolveSmmServices()) + return false; + if (!resolveSmiHandlers()) + return false; + return true; } -DxeResolver::DxeResolver(Ref<BinaryView> view, Ref<BackgroundTask> task) - : Resolver(view, task) +DxeResolver::DxeResolver(Ref<BinaryView> view, Ref<BackgroundTask> task) : Resolver(view, task) { - initProtocolMapping(); - setModuleEntry(DXE); + initProtocolMapping(); + setModuleEntry(DXE); } diff --git a/platform/efi/efi_resolver/src/GuidRenderer.cpp b/platform/efi/efi_resolver/src/GuidRenderer.cpp index ef148094..deac0265 100644 --- a/platform/efi/efi_resolver/src/GuidRenderer.cpp +++ b/platform/efi/efi_resolver/src/GuidRenderer.cpp @@ -2,55 +2,50 @@ bool isType(const vector<pair<Type*, size_t>>& context, const string& name) { - if (context.empty()) - return false; + if (context.empty()) + return false; - auto [deepestType, size] = context.back(); - if (!deepestType->IsNamedTypeRefer()) - return false; + auto [deepestType, size] = context.back(); + if (!deepestType->IsNamedTypeRefer()) + return false; - return deepestType->GetTypeName().GetString() == name; + return deepestType->GetTypeName().GetString() == name; } -bool EfiGuidRenderer::IsValidForData(BinaryView* bv, uint64_t address, Type* type, - vector<pair<Type*, size_t>>& context) +bool EfiGuidRenderer::IsValidForData(BinaryView* bv, uint64_t address, Type* type, vector<pair<Type*, size_t>>& context) { - return isType(context, "EFI_GUID"); + return isType(context, "EFI_GUID"); } static string formatGuid(uint32_t data1, uint16_t data2, uint16_t data3, uint64_t data4) { - std::ostringstream oss; - oss << std::hex << std::uppercase << std::setfill('0') - << std::setw(8) << data1 << "-" - << std::setw(4) << data2 << "-" - << std::setw(4) << data3 << "-" - << std::setw(16) << data4; - return oss.str(); + std::ostringstream oss; + oss << std::hex << std::uppercase << std::setfill('0') << std::setw(8) << data1 << "-" << std::setw(4) << data2 + << "-" << std::setw(4) << data3 << "-" << std::setw(16) << data4; + return oss.str(); } -vector<DisassemblyTextLine> EfiGuidRenderer::GetLinesForData( - BinaryView* bv, uint64_t address, Type*, const vector<InstructionTextToken>& prefix, - size_t, vector<pair<Type*, size_t>>& context) +vector<DisassemblyTextLine> EfiGuidRenderer::GetLinesForData(BinaryView* bv, uint64_t address, Type*, + const vector<InstructionTextToken>& prefix, size_t, vector<pair<Type*, size_t>>& context) { - BinaryReader reader(bv); - reader.Seek(address); - auto data1 = reader.Read32(); - auto data2 = reader.Read16(); - auto data3 = reader.Read16(); - auto data4 = reader.ReadBE64(); - string guidStr = formatGuid(data1, data2, data3, data4); + BinaryReader reader(bv); + reader.Seek(address); + auto data1 = reader.Read32(); + auto data2 = reader.Read16(); + auto data3 = reader.Read16(); + auto data4 = reader.ReadBE64(); + string guidStr = formatGuid(data1, data2, data3, data4); - DisassemblyTextLine line; - line.addr = address; - line.tokens = prefix; - line.tokens.emplace_back(TextToken, "[EFI_GUID(\""); - line.tokens.emplace_back(StringToken, guidStr); - line.tokens.emplace_back(TextToken, "\")]"); - return { line }; + DisassemblyTextLine line; + line.addr = address; + line.tokens = prefix; + line.tokens.emplace_back(TextToken, "[EFI_GUID(\""); + line.tokens.emplace_back(StringToken, guidStr); + line.tokens.emplace_back(TextToken, "\")]"); + return {line}; } void EfiGuidRenderer::Register() { - DataRendererContainer::RegisterTypeSpecificDataRenderer(new EfiGuidRenderer()); + DataRendererContainer::RegisterTypeSpecificDataRenderer(new EfiGuidRenderer()); } diff --git a/platform/efi/efi_resolver/src/PeiResolver.cpp b/platform/efi/efi_resolver/src/PeiResolver.cpp index 2699f2bb..c3f5d50a 100644 --- a/platform/efi/efi_resolver/src/PeiResolver.cpp +++ b/platform/efi/efi_resolver/src/PeiResolver.cpp @@ -2,277 +2,303 @@ bool PeiResolver::resolvePeiIdt() { - string archName = m_view->GetDefaultArchitecture()->GetName(); - string intrinsicName; - if (archName == "x86") - intrinsicName = "IDTR32"; - else - intrinsicName = "IDTR64"; + string archName = m_view->GetDefaultArchitecture()->GetName(); + string intrinsicName; + if (archName == "x86") + intrinsicName = "IDTR32"; + else + intrinsicName = "IDTR64"; - auto refs = m_view->GetCodeReferencesForType(QualifiedName(intrinsicName)); - for (auto ref : refs) { - if (m_task->IsCancelled()) - return false; + auto refs = m_view->GetCodeReferencesForType(QualifiedName(intrinsicName)); + for (auto ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto mlil = ref.func->GetMediumLevelIL(); - auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlil->GetInstruction(instrIdx); + auto mlil = ref.func->GetMediumLevelIL(); + auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlil->GetInstruction(instrIdx); - auto hlil = ref.func->GetHighLevelIL(); - auto hlils = HighLevelILExprsAt(ref.func, m_view->GetDefaultArchitecture(), ref.addr); + auto hlil = ref.func->GetHighLevelIL(); + auto hlils = HighLevelILExprsAt(ref.func, m_view->GetDefaultArchitecture(), ref.addr); - for (auto expr : hlils) { - if (expr.operation != HLIL_INTRINSIC || - expr.GetParent().operation != HLIL_ASSIGN || - expr.GetParent().GetDestExpr<HLIL_ASSIGN>().operation != HLIL_STRUCT_FIELD || - expr.GetParent().GetDestExpr<HLIL_ASSIGN>().GetSourceExpr<HLIL_STRUCT_FIELD>().operation != HLIL_VAR) - continue; + for (auto expr : hlils) + { + if (expr.operation != HLIL_INTRINSIC || expr.GetParent().operation != HLIL_ASSIGN + || expr.GetParent().GetDestExpr<HLIL_ASSIGN>().operation != HLIL_STRUCT_FIELD + || expr.GetParent().GetDestExpr<HLIL_ASSIGN>().GetSourceExpr<HLIL_STRUCT_FIELD>().operation != HLIL_VAR) + continue; - auto var = expr.GetParent().GetDestExpr<HLIL_ASSIGN>().GetSourceExpr<HLIL_STRUCT_FIELD>().GetVariable(); - ref.func->CreateUserVariable(var, m_view->GetTypeByName(QualifiedName(intrinsicName)), intrinsicName); - } + auto var = expr.GetParent().GetDestExpr<HLIL_ASSIGN>().GetSourceExpr<HLIL_STRUCT_FIELD>().GetVariable(); + ref.func->CreateUserVariable(var, m_view->GetTypeByName(QualifiedName(intrinsicName)), intrinsicName); + } - if (instr.operation == MLIL_INTRINSIC) { - // binja doesn't do type propagation on intrinsic instructions - auto output_params = instr.GetOutputVariables<MLIL_INTRINSIC>(); - if (output_params.size() < 1) - continue; - ref.func->CreateUserVariable(output_params[0], - m_view->GetTypeByName(QualifiedName(intrinsicName)), - intrinsicName); - } - m_view->UpdateAnalysisAndWait(); - } + if (instr.operation == MLIL_INTRINSIC) + { + // binja doesn't do type propagation on intrinsic instructions + auto output_params = instr.GetOutputVariables<MLIL_INTRINSIC>(); + if (output_params.size() < 1) + continue; + ref.func->CreateUserVariable( + output_params[0], m_view->GetTypeByName(QualifiedName(intrinsicName)), intrinsicName); + } + m_view->UpdateAnalysisAndWait(); + } - // TODO There is an issue related to structure's type propagation, binja doesn't propagate indirect structure access properly - // here is a temporary fix, should be removed after vector35/binaryninja/#749 got fixed - refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); - for (auto ref : refs) { - if (m_task->IsCancelled()) - return false; + // TODO There is an issue related to structure's type propagation, binja doesn't propagate indirect structure access + // properly + // here is a temporary fix, should be removed after vector35/binaryninja/#749 got fixed + refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); + for (auto ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto mlil = ref.func->GetMediumLevelIL(); - auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlil->GetInstruction(instrIdx); + auto mlil = ref.func->GetMediumLevelIL(); + auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlil->GetInstruction(instrIdx); - if (instr.operation != MLIL_SET_VAR) - continue; + if (instr.operation != MLIL_SET_VAR) + continue; - if (instr.GetSourceExpr<MLIL_SET_VAR>().operation != MLIL_LOAD_STRUCT) - continue; + if (instr.GetSourceExpr<MLIL_SET_VAR>().operation != MLIL_LOAD_STRUCT) + continue; - ref.func->CreateUserVariable(instr.GetDestVariable<MLIL_SET_VAR>(), - mlil->GetExprType(instr.GetSourceExpr<MLIL_SET_VAR>()).GetValue(), - nonConflictingLocalName(ref.func, "EfiPeiServices")); - m_view->UpdateAnalysisAndWait(); - } + ref.func->CreateUserVariable(instr.GetDestVariable<MLIL_SET_VAR>(), + mlil->GetExprType(instr.GetSourceExpr<MLIL_SET_VAR>()).GetValue(), + nonConflictingLocalName(ref.func, "EfiPeiServices")); + m_view->UpdateAnalysisAndWait(); + } - return true; + return true; } bool PeiResolver::resolvePeiMrc() { - auto funcs = m_view->GetAnalysisFunctionList(); - for (auto func : funcs) { - if (m_task->IsCancelled()) - return false; + auto funcs = m_view->GetAnalysisFunctionList(); + for (auto func : funcs) + { + if (m_task->IsCancelled()) + return false; - auto mlil = func->GetMediumLevelIL(); - auto blocks = mlil->GetBasicBlocks(); - for (auto block : blocks) { - for (size_t i = block->GetStart(); i < block->GetEnd(); i++) { - auto instr = mlil->GetInstruction(i); - if (instr.operation != MLIL_INTRINSIC) - continue; - uint32_t intrinsicIdx = instr.GetIntrinsic<MLIL_INTRINSIC>(); + auto mlil = func->GetMediumLevelIL(); + auto blocks = mlil->GetBasicBlocks(); + for (auto block : blocks) + { + for (size_t i = block->GetStart(); i < block->GetEnd(); i++) + { + auto instr = mlil->GetInstruction(i); + if (instr.operation != MLIL_INTRINSIC) + continue; + uint32_t intrinsicIdx = instr.GetIntrinsic<MLIL_INTRINSIC>(); - if (m_view->GetDefaultArchitecture()->GetIntrinsicName(intrinsicIdx) != "Coproc_GetOneWord") - continue; - auto intrinsicParams = instr.GetParameterExprs<MLIL_INTRINSIC>(); - if (intrinsicParams.size() != 5) - continue; + if (m_view->GetDefaultArchitecture()->GetIntrinsicName(intrinsicIdx) != "Coproc_GetOneWord") + continue; + auto intrinsicParams = instr.GetParameterExprs<MLIL_INTRINSIC>(); + if (intrinsicParams.size() != 5) + continue; - bool found = true; + bool found = true; - const int value[5] = { 0xf, 0x0, 0xd, 0x0, 0x2 }; - for (int j = 0; j < 5; j++) { - auto param = intrinsicParams[j]; - if (param.operation != MLIL_CONST) { - found = false; - break; - } + const int value[5] = {0xf, 0x0, 0xd, 0x0, 0x2}; + for (int j = 0; j < 5; j++) + { + auto param = intrinsicParams[j]; + if (param.operation != MLIL_CONST) + { + found = false; + break; + } - if (param.GetConstant<MLIL_CONST>() != value[j]) { - found = false; - break; - } - } + if (param.GetConstant<MLIL_CONST>() != value[j]) + { + found = false; + break; + } + } - if (!found) - continue; + if (!found) + continue; - // At this point, we can make sure this instruction fetches EFI_PEI_SERVICES - auto output = instr.GetOutputVariables(); - if (output.size() > 0) { - auto pointerType = Type::PointerType(m_view->GetDefaultArchitecture(), - Type::PointerType(m_view->GetDefaultArchitecture(), - m_view->GetTypeByName(QualifiedName("EFI_PEI_SERVICES")))); - func->CreateUserVariable(output[0], pointerType, nonConflictingLocalName(func, "PeiServices")); - m_view->UpdateAnalysisAndWait(); - } - } - } - } - return true; + // At this point, we can make sure this instruction fetches EFI_PEI_SERVICES + auto output = instr.GetOutputVariables(); + if (output.size() > 0) + { + auto pointerType = Type::PointerType(m_view->GetDefaultArchitecture(), + Type::PointerType(m_view->GetDefaultArchitecture(), + m_view->GetTypeByName(QualifiedName("EFI_PEI_SERVICES")))); + func->CreateUserVariable(output[0], pointerType, nonConflictingLocalName(func, "PeiServices")); + m_view->UpdateAnalysisAndWait(); + } + } + } + } + return true; } bool PeiResolver::resolvePeiMrs() { - // ideally we don't need this function, but since we don't support type propagation on intrinsic instructions - // we have to manually propagate it - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); - for (auto ref : refs) { - if (m_task->IsCancelled()) - return false; + // ideally we don't need this function, but since we don't support type propagation on intrinsic instructions + // we have to manually propagate it + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); + for (auto ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto mlil = ref.func->GetMediumLevelIL(); - auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlil->GetInstruction(instrIdx); - if (instr.operation == MLIL_INTRINSIC) { - auto params = instr.GetOutputVariables(); - if (params.size() < 1) - continue; + auto mlil = ref.func->GetMediumLevelIL(); + auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlil->GetInstruction(instrIdx); + if (instr.operation == MLIL_INTRINSIC) + { + auto params = instr.GetOutputVariables(); + if (params.size() < 1) + continue; - auto pointerType = Type::PointerType(m_view->GetDefaultArchitecture(), - Type::PointerType(m_view->GetDefaultArchitecture(), - m_view->GetTypeByName(QualifiedName("EFI_PEI_SERVICES")))); - ref.func->CreateUserVariable(params[0], - pointerType, - nonConflictingLocalName(ref.func, "EfiPeiServices")); - m_view->UpdateAnalysisAndWait(); - } - } - return true; + auto pointerType = Type::PointerType(m_view->GetDefaultArchitecture(), + Type::PointerType( + m_view->GetDefaultArchitecture(), m_view->GetTypeByName(QualifiedName("EFI_PEI_SERVICES")))); + ref.func->CreateUserVariable(params[0], pointerType, nonConflictingLocalName(ref.func, "EfiPeiServices")); + m_view->UpdateAnalysisAndWait(); + } + } + return true; } bool PeiResolver::resolvePlatformPointers() { - string archName = m_view->GetDefaultArchitecture()->GetName(); - string intrinsicTypeName; + m_task->SetProgressText("Resolving PEI Services Pointers..."); + string archName = m_view->GetDefaultArchitecture()->GetName(); + string intrinsicTypeName; - if (archName == "x86" || archName == "x86-64") { - return resolvePeiIdt(); - } else if (archName == "arm" || archName == "thumb2") { - return resolvePeiMrc(); - } else if (archName == "aarch64") { - return resolvePeiMrs(); - } - LogError("Not supported arch: %s", archName.c_str()); - return false; + if (archName == "x86" || archName == "x86-64") + { + return resolvePeiIdt(); + } + else if (archName == "arm" || archName == "thumb2") + { + return resolvePeiMrc(); + } + else if (archName == "aarch64") + { + return resolvePeiMrs(); + } + LogError("Not supported arch: %s", archName.c_str()); + return false; } bool PeiResolver::resolvePeiDescriptors() { - const string descriptorNames[2] = { "EFI_PEI_NOTIFY_DESCRIPTOR", "EFI_PEI_PPI_DESCRIPTOR" }; - for (auto descriptor : descriptorNames) { - auto refs = m_view->GetCodeReferencesForType(QualifiedName(descriptor)); - for (auto ref : refs) { - if (m_task->IsCancelled()) - return false; + m_task->SetProgressText("Defining PEI Descriptors..."); + const string descriptorNames[2] = {"EFI_PEI_NOTIFY_DESCRIPTOR", "EFI_PEI_PPI_DESCRIPTOR"}; + for (auto descriptor : descriptorNames) + { + auto refs = m_view->GetCodeReferencesForType(QualifiedName(descriptor)); + for (auto ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto mlil = ref.func->GetMediumLevelIL(); - auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlil->GetInstruction(instrIdx); + auto mlil = ref.func->GetMediumLevelIL(); + auto instrIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlil->GetInstruction(instrIdx); - if (instr.operation != MLIL_CALL && instr.operation != MLIL_TAILCALL) - continue; + if (instr.operation != MLIL_CALL && instr.operation != MLIL_TAILCALL) + continue; - auto destExpr = instr.GetDestExpr(); - if (destExpr.operation != MLIL_LOAD_STRUCT) - continue; + auto destExpr = instr.GetDestExpr(); + if (destExpr.operation != MLIL_LOAD_STRUCT) + continue; - // at this point this instruction is probably a call to LocatPpi, InstallPpi or NotifyPpi - if (!mlil->GetExprType(destExpr).GetValue()->IsPointer()) - continue; + // at this point this instruction is probably a call to LocatPpi, InstallPpi or NotifyPpi + if (!mlil->GetExprType(destExpr).GetValue()->IsPointer()) + continue; - auto funcType = mlil->GetExprType(destExpr).GetValue()->GetChildType().GetValue(); - auto params = funcType->GetParameters(); - int targetParamIdx = -1; - for (int i = 0; i < params.size(); i++) { - auto param = params[i]; - if (!param.type.GetValue()->IsPointer()) - continue; - auto paramTypeName = param.type.GetValue()->GetChildType().GetValue()->GetTypeName().GetString(); - if (paramTypeName.find(descriptor) != paramTypeName.npos) { - // this is the param - targetParamIdx = i; - break; - } - } - if (targetParamIdx < 0) - continue; + auto funcType = mlil->GetExprType(destExpr).GetValue()->GetChildType().GetValue(); + auto params = funcType->GetParameters(); + int targetParamIdx = -1; + for (int i = 0; i < params.size(); i++) + { + auto param = params[i]; + if (!param.type.GetValue()->IsPointer()) + continue; + auto paramTypeName = param.type.GetValue()->GetChildType().GetValue()->GetTypeName().GetString(); + if (paramTypeName.find(descriptor) != paramTypeName.npos) + { + // this is the param + targetParamIdx = i; + break; + } + } + if (targetParamIdx < 0) + continue; - // Now we are confident that this position is a call that pass Descriptor as a parameter - defineTypeAtCallsite(ref.func, ref.addr, descriptor, targetParamIdx, true); - } - } - return true; + // Now we are confident that this position is a call that pass Descriptor as a parameter + defineTypeAtCallsite(ref.func, ref.addr, descriptor, targetParamIdx, true); + } + } + return true; } bool PeiResolver::resolvePeiServices() { - auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); + m_task->SetProgressText("Resolving PPIs..."); + auto refs = m_view->GetCodeReferencesForType(QualifiedName("EFI_PEI_SERVICES")); - for (auto ref : refs) { - if (m_task->IsCancelled()) - return false; + for (auto ref : refs) + { + if (m_task->IsCancelled()) + return false; - auto func = ref.func; - auto mlil = func->GetMediumLevelIL(); - if (!mlil) - continue; + auto func = ref.func; + auto mlil = func->GetMediumLevelIL(); + if (!mlil) + continue; - auto mlilSsa = mlil->GetSSAForm(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); - auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); + auto mlilSsa = mlil->GetSSAForm(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), ref.addr); + auto instr = mlilSsa->GetInstruction(mlil->GetSSAInstructionIndex(mlilIdx)); - if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) { - auto dest = instr.GetDestExpr(); - if (dest.operation != MLIL_LOAD_STRUCT_SSA) - continue; - auto offset = dest.GetOffset(); + if (instr.operation == MLIL_CALL_SSA || instr.operation == MLIL_TAILCALL_SSA) + { + auto dest = instr.GetDestExpr(); + if (dest.operation != MLIL_LOAD_STRUCT_SSA) + continue; + auto offset = dest.GetOffset(); - if (offset == 0x18 + m_width * 2) { - // LocatePpi - resolveGuidInterface(ref.func, ref.addr, 1, 4); - } else if (offset == 0x18 || offset == 0x18 + m_width || offset == 0x18 + m_width * 3) { - // InstallPpi, ReinstallPpi, NotifyPpi - } - } - } - return true; + if (offset == 0x18 + m_width * 2) + { + // LocatePpi + resolveGuidInterface(ref.func, ref.addr, 1, 4); + } + else if (offset == 0x18 || offset == 0x18 + m_width || offset == 0x18 + m_width * 3) + { + // InstallPpi, ReinstallPpi, NotifyPpi + } + } + } + return true; } bool PeiResolver::resolvePei() { - if (!setModuleEntry(PEI)) - return false; + if (!setModuleEntry(PEI)) + return false; - if (!resolvePlatformPointers()) - return false; + if (!resolvePlatformPointers()) + return false; - if (!resolvePeiDescriptors()) - return false; + if (!resolvePeiDescriptors()) + return false; - if (!resolvePeiServices()) - return false; + if (!resolvePeiServices()) + return false; - return true; + return true; } -PeiResolver::PeiResolver(Ref<BinaryView> view, Ref<BackgroundTask> task) - : Resolver(view, task) +PeiResolver::PeiResolver(Ref<BinaryView> view, Ref<BackgroundTask> task) : Resolver(view, task) { - initProtocolMapping(); - setModuleEntry(PEI); + initProtocolMapping(); + setModuleEntry(PEI); } diff --git a/platform/efi/efi_resolver/src/Plugin.cpp b/platform/efi/efi_resolver/src/Plugin.cpp index bfa19a7f..b562975c 100644 --- a/platform/efi/efi_resolver/src/Plugin.cpp +++ b/platform/efi/efi_resolver/src/Plugin.cpp @@ -5,60 +5,61 @@ using namespace BinaryNinja; -extern "C" { +extern "C" +{ BN_DECLARE_CORE_ABI_VERSION BINARYNINJAPLUGIN void CorePluginDependencies() { - BinaryNinja::AddOptionalPluginDependency("arch_x86"); - BinaryNinja::AddOptionalPluginDependency("arch_armv7"); - BinaryNinja::AddOptionalPluginDependency("arch_arm64"); - BinaryNinja::AddOptionalPluginDependency("platform_efi"); + BinaryNinja::AddOptionalPluginDependency("arch_x86"); + BinaryNinja::AddOptionalPluginDependency("arch_armv7"); + BinaryNinja::AddOptionalPluginDependency("arch_arm64"); + BinaryNinja::AddOptionalPluginDependency("platform_efi"); } static Ref<BackgroundTask> efiBackgroundTask = nullptr; void Run(Ref<BinaryView> view) { - efiBackgroundTask = new BackgroundTask("Loading EFI protocol mappings!", true); - thread resolverThread([view]() { - LogInfo("Entering new thread"); + efiBackgroundTask = new BackgroundTask("Loading EFI protocol mappings!", true); + thread resolverThread([view]() { + LogInfo("Entering new thread"); - LogInfo("Identifying module type"); - EFIModuleType moduleType = identifyModuleType(view); + LogInfo("Identifying module type"); + EFIModuleType moduleType = identifyModuleType(view); -#ifdef DEBUG - auto undo = view->BeginUndoActions(); +#ifndef DEBUG + auto undo = view->BeginUndoActions(); #endif - if (moduleType == PEI) { - efiBackgroundTask->SetProgressText("Resolving PEIM..."); - auto resolver = PeiResolver(view, efiBackgroundTask); - resolver.resolvePei(); - } else if (moduleType == DXE) { - efiBackgroundTask->SetProgressText("Resolving DXE protocols..."); - auto resolver = DxeResolver(view, efiBackgroundTask); - resolver.resolveDxe(); - efiBackgroundTask->SetProgressText("Resolving MM related protocols..."); - resolver.resolveSmm(); - } + if (moduleType == PEI) + { + efiBackgroundTask->SetProgressText("Resolving PEIM..."); + auto resolver = PeiResolver(view, efiBackgroundTask); + resolver.resolvePei(); + } + else if (moduleType == DXE) + { + efiBackgroundTask->SetProgressText("Resolving DXE protocols..."); + auto resolver = DxeResolver(view, efiBackgroundTask); + resolver.resolveDxe(); + efiBackgroundTask->SetProgressText("Resolving MM related protocols..."); + resolver.resolveSmm(); + } -#ifdef DEBUG - resolver.m_view->CommitUndoActions(undo); +#ifndef DEBUG + view->CommitUndoActions(undo); #endif - efiBackgroundTask->Finish(); - }); - resolverThread.detach(); + efiBackgroundTask->Finish(); + }); + resolverThread.detach(); } BINARYNINJAPLUGIN bool CorePluginInit() { - EfiGuidRenderer::Register(); + EfiGuidRenderer::Register(); - PluginCommand::Register( - "EFI Resolver\\Resolve EFI Types And Protocols", - "Resolve EFI Protocols", - &Run); + PluginCommand::Register("EFI Resolver\\Resolve EFI Types And Protocols", "Resolve EFI Protocols", &Run); - return true; + return true; } } diff --git a/platform/efi/efi_resolver/src/Resolver.cpp b/platform/efi/efi_resolver/src/Resolver.cpp index 94510321..36fa190b 100644 --- a/platform/efi/efi_resolver/src/Resolver.cpp +++ b/platform/efi/efi_resolver/src/Resolver.cpp @@ -2,675 +2,752 @@ string Resolver::nonConflictingName(const string& basename) { - int idx = 0; - string name = basename; - do { - auto sym = m_view->GetSymbolByRawName(name); - if (!sym) - return name; - else { - name = basename + to_string(idx); - idx += 1; - } - } while (true); + int idx = 0; + string name = basename; + do + { + auto sym = m_view->GetSymbolByRawName(name); + if (!sym) + return name; + else + { + name = basename + to_string(idx); + idx += 1; + } + } while (true); } string Resolver::nonConflictingLocalName(Ref<Function> func, const string& basename) { - string name = basename; - int idx = 0; - while (true) { - bool ok = true; - for (const auto& varPair : func->GetVariables()) { - if (varPair.second.name == name) { - ok = false; - break; - } - } - if (ok) - break; - name = basename + to_string(idx); - idx += 1; - } - return name; + string name = basename; + int idx = 0; + while (true) + { + bool ok = true; + for (const auto& varPair : func->GetVariables()) + { + if (varPair.second.name == name) + { + ok = false; + break; + } + } + if (ok) + break; + name = basename + to_string(idx); + idx += 1; + } + return name; } static string GetBundledEfiPath() { - string path = GetBundledPluginDirectory(); + string path = GetBundledPluginDirectory(); #if defined(_WIN32) - return path + "..\\types\\efi.c"; -#elif defined(__linux__) - return path + "../types/efi.c"; + return path + "..\\types\\efi.c"; +#elif defined(__APPLE__) + return path + "/../../Resources/types/efi.c"; #else - return path + "/../../Resources/types/efi.c"; + return path + "../types/efi.c"; #endif } static string GetUserGuidPath() { - string path = GetUserDirectory(); + string path = GetUserDirectory(); #if defined(_WIN32) - return path + "\\types\\efi-guids.json"; -#elif defined(__linux__) - return path + "/types/efi-guids.json"; + return path + "\\types\\efi-guids.json"; +#elif defined(__APPLE__) + return path + "/types/efi-guids.json"; #else - return path + "/types/efi-guids.json"; + return path + "/types/efi-guids.json"; #endif } static EFI_GUID parseGuid(const string& guidStr) { - EFI_GUID guid; - istringstream iss(guidStr); - string token; - unsigned long value; + EFI_GUID guid; + istringstream iss(guidStr); + string token; + unsigned long value; - getline(iss, token, ','); - value = stoul(token, nullptr, 16); - guid[0] = static_cast<uint8_t>(value); - guid[1] = static_cast<uint8_t>(value >> 8); - guid[2] = static_cast<uint8_t>(value >> 16); - guid[3] = static_cast<uint8_t>(value >> 24); + getline(iss, token, ','); + value = stoul(token, nullptr, 16); + guid[0] = static_cast<uint8_t>(value); + guid[1] = static_cast<uint8_t>(value >> 8); + guid[2] = static_cast<uint8_t>(value >> 16); + guid[3] = static_cast<uint8_t>(value >> 24); - getline(iss, token, ','); - value = stoul(token, nullptr, 16); - guid[4] = static_cast<uint8_t>(value); - guid[5] = static_cast<uint8_t>(value >> 8); + getline(iss, token, ','); + value = stoul(token, nullptr, 16); + guid[4] = static_cast<uint8_t>(value); + guid[5] = static_cast<uint8_t>(value >> 8); - getline(iss, token, ','); - value = stoul(token, nullptr, 16); - guid[6] = static_cast<uint8_t>(value); - guid[7] = static_cast<uint8_t>(value >> 8); + getline(iss, token, ','); + value = stoul(token, nullptr, 16); + guid[6] = static_cast<uint8_t>(value); + guid[7] = static_cast<uint8_t>(value >> 8); - for (int i = 8; i < 16; i++) { - getline(iss, token, ','); - value = stoul(token, nullptr, 16); - guid[i] = static_cast<uint8_t>(value); - } - return guid; + for (int i = 8; i < 16; i++) + { + getline(iss, token, ','); + value = stoul(token, nullptr, 16); + guid[i] = static_cast<uint8_t>(value); + } + return guid; } bool Resolver::parseProtocolMapping(const string& filePath) { - vector<pair<EFI_GUID, string>> guids; - ifstream efiDefs; - string line; + vector<pair<EFI_GUID, string>> guids; + ifstream efiDefs; + string line; - m_protocol.clear(); + m_protocol.clear(); - efiDefs.open(filePath.c_str()); - if (!efiDefs.is_open()) - return false; + efiDefs.open(filePath.c_str()); + if (!efiDefs.is_open()) + return false; - while (getline(efiDefs, line)) { - if (m_task->IsCancelled()) - return false; + while (getline(efiDefs, line)) + { + if (m_task->IsCancelled()) + return false; - if (line.substr(0, 12) == "///@protocol") { - string guid = line.substr(12); - guid.erase(remove_if(guid.begin(), guid.end(), [](char c) { return c == '{' || c == '}' || c == ' '; }), guid.end()); - guids.emplace_back( parseGuid(guid), "" ); - } else if (line.substr(0, 11) == "///@binding") { - istringstream iss(line.substr(11)); - string guidName, guid; - iss >> guidName >> guid; - guid.erase(remove_if(guid.begin(), guid.end(), [](char c) { return c == '{' || c == '}' || c == ' '; }), guid.end()); - guids.emplace_back( parseGuid(guid), guidName ); - } else if (line.substr(0, 6) == "struct") { - if (guids.empty()) - continue; - istringstream iss(line.substr(6)); - string name; - iss >> name; - for (const auto& guidInfo : guids) { - if (guidInfo.second.empty()) { - m_protocol[guidInfo.first] = make_pair(name, name + "_GUID"); - } else { - m_protocol[guidInfo.first] = make_pair(name, guidInfo.second); - } - } - } else { - guids.clear(); - } - } - efiDefs.close(); + if (line.substr(0, 12) == "///@protocol") + { + string guid = line.substr(12); + guid.erase(remove_if(guid.begin(), guid.end(), [](char c) { return c == '{' || c == '}' || c == ' '; }), + guid.end()); + guids.emplace_back(parseGuid(guid), ""); + } + else if (line.substr(0, 11) == "///@binding") + { + istringstream iss(line.substr(11)); + string guidName, guid; + iss >> guidName >> guid; + guid.erase(remove_if(guid.begin(), guid.end(), [](char c) { return c == '{' || c == '}' || c == ' '; }), + guid.end()); + guids.emplace_back(parseGuid(guid), guidName); + } + else if (line.substr(0, 6) == "struct") + { + if (guids.empty()) + continue; + istringstream iss(line.substr(6)); + string name; + iss >> name; + for (const auto& guidInfo : guids) + { + if (guidInfo.second.empty()) + { + m_protocol[guidInfo.first] = make_pair(name, name + "_GUID"); + } + else + { + m_protocol[guidInfo.first] = make_pair(name, guidInfo.second); + } + } + } + else + { + guids.clear(); + } + } + efiDefs.close(); - return true; + return true; } bool Resolver::parseUserGuidIfExists(const string& filePath) { - ifstream userJson(filePath); - if (!userJson.is_open()) - return false; + ifstream userJson(filePath); + if (!userJson.is_open()) + return false; - nlohmann::json jsonContent; - userJson >> jsonContent; + nlohmann::json jsonContent; + userJson >> jsonContent; - for (const auto& element : jsonContent.items()) { - if (m_task->IsCancelled()) - return false; + for (const auto& element : jsonContent.items()) + { + if (m_task->IsCancelled()) + return false; - const auto& guidName = element.key(); - auto guidBytes = element.value(); - if (guidBytes.size() != 11) { - LogError("Error: GUID array size is incorrect for %s", guidName.c_str()); - return false; - } - EFI_GUID guid; - guid[0] = static_cast<uint8_t>(int(guidBytes[0])); - guid[1] = static_cast<uint8_t>(int(guidBytes[0]) >> 8); - guid[2] = static_cast<uint8_t>(int(guidBytes[0]) >> 16); - guid[3] = static_cast<uint8_t>(int(guidBytes[0]) >> 24); + const auto& guidName = element.key(); + auto guidBytes = element.value(); + if (guidBytes.size() != 11) + { + LogError("Error: GUID array size is incorrect for %s", guidName.c_str()); + return false; + } + EFI_GUID guid; + guid[0] = static_cast<uint8_t>(int(guidBytes[0])); + guid[1] = static_cast<uint8_t>(int(guidBytes[0]) >> 8); + guid[2] = static_cast<uint8_t>(int(guidBytes[0]) >> 16); + guid[3] = static_cast<uint8_t>(int(guidBytes[0]) >> 24); - guid[4] = static_cast<uint8_t>(int(guidBytes[1])); - guid[5] = static_cast<uint8_t>(int(guidBytes[1]) >> 8); + guid[4] = static_cast<uint8_t>(int(guidBytes[1])); + guid[5] = static_cast<uint8_t>(int(guidBytes[1]) >> 8); - guid[6] = static_cast<uint8_t>(int(guidBytes[2])); - guid[7] = static_cast<uint8_t>(int(guidBytes[2]) >> 8); + guid[6] = static_cast<uint8_t>(int(guidBytes[2])); + guid[7] = static_cast<uint8_t>(int(guidBytes[2]) >> 8); - for (int i = 8; i < 16; i++) - guid[i] = static_cast<uint8_t>(int(guidBytes[i-5])); + for (int i = 8; i < 16; i++) + guid[i] = static_cast<uint8_t>(int(guidBytes[i - 5])); - // Insert the GUID and its name into the map - m_user_guids[guid] = guidName; - } + // Insert the GUID and its name into the map + m_user_guids[guid] = guidName; + } - return true; + return true; } void Resolver::initProtocolMapping() { - if (!m_protocol.empty()) - return; - auto fileName = GetBundledEfiPath(); - if (!parseProtocolMapping(fileName)) - LogAlert("Binary Ninja Version Too Low. Please upgrade to a new version."); + if (!m_protocol.empty()) + return; + auto fileName = GetBundledEfiPath(); + if (!parseProtocolMapping(fileName)) + LogAlert("Binary Ninja Version Too Low. Please upgrade to a new version."); - fileName = GetUserGuidPath(); - parseUserGuidIfExists(fileName); + fileName = GetUserGuidPath(); + parseUserGuidIfExists(fileName); } bool Resolver::setModuleEntry(EFIModuleType fileType) { - // Wait until initial analysis is finished - m_view->UpdateAnalysisAndWait(); + // Wait until initial analysis is finished + m_view->UpdateAnalysisAndWait(); - uint64_t entry = m_view->GetEntryPoint(); - auto entryFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), entry); - if (!entryFunc) - { - LogDebug("Entry func Not found... "); - return false; - } + uint64_t entry = m_view->GetEntryPoint(); + auto entryFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), entry); + if (!entryFunc) + { + LogDebug("Entry func Not found... "); + return false; + } - // TODO sometimes the parameter at callsite cannot be correctly recognized, #Vector35/binaryninja-api/4529 - // temporary workaround for this issue, adjust callsite types in entry function if it doesn't has parameters + // TODO sometimes the parameter at callsite cannot be correctly recognized, #Vector35/binaryninja-api/4529 + // temporary workaround for this issue, adjust callsite types in entry function if it doesn't has parameters - // Note: we only adjust the callsite in entry function, this is just a temp fix and it cannot cover all cases - auto callsites = entryFunc->GetCallSites(); - LogDebug("Checking callsites at 0x%llx", entryFunc->GetStart()); - LogDebug("callsite count : %zu", callsites.size()); - for (auto callsite: entryFunc->GetCallSites()) - { - auto mlil = entryFunc->GetMediumLevelIL(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), callsite.addr); - auto instr = mlil->GetInstruction(mlilIdx); - LogDebug("Checking Callsite at 0x%llx", callsite.addr); - if(instr.operation == MLIL_CALL || instr.operation == MLIL_TAILCALL) - { - auto params = instr.GetParameterExprs(); - if (params.size() == 0) - { - // no parameter at call site, check whether it's correctly recognized - auto constantPtr = instr.GetDestExpr(); - if (constantPtr.operation == MLIL_CONST_PTR) - { - auto addr = constantPtr.GetConstant(); - auto funcType = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), addr)->GetType(); - entryFunc->SetUserCallTypeAdjustment(m_view->GetDefaultArchitecture(), callsite.addr, funcType); - m_view->UpdateAnalysisAndWait(); - } - else - LogDebug("Operation not ConstPtr: %d", constantPtr.operation); - } - else - LogDebug("param size not zero"); - } - } + // Note: we only adjust the callsite in entry function, this is just a temp fix and it cannot cover all cases + auto callsites = entryFunc->GetCallSites(); + LogDebug("Checking callsites at 0x%llx", entryFunc->GetStart()); + LogDebug("callsite count : %zu", callsites.size()); + for (auto callsite : entryFunc->GetCallSites()) + { + auto mlil = entryFunc->GetMediumLevelIL(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), callsite.addr); + auto instr = mlil->GetInstruction(mlilIdx); + LogDebug("Checking Callsite at 0x%llx", callsite.addr); + if (instr.operation == MLIL_CALL || instr.operation == MLIL_TAILCALL) + { + auto params = instr.GetParameterExprs(); + if (params.size() == 0) + { + // no parameter at call site, check whether it's correctly recognized + auto constantPtr = instr.GetDestExpr(); + if (constantPtr.operation == MLIL_CONST_PTR) + { + auto addr = constantPtr.GetConstant(); + auto funcType = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), addr)->GetType(); + entryFunc->SetUserCallTypeAdjustment(m_view->GetDefaultArchitecture(), callsite.addr, funcType); + m_view->UpdateAnalysisAndWait(); + } + else + LogDebug("Operation not ConstPtr: %d", constantPtr.operation); + } + else + LogDebug("param size not zero"); + } + } - string errors; - QualifiedNameAndType result; - bool ok; + string errors; + QualifiedNameAndType result; + bool ok; - string typeString; - switch (fileType) { - case PEI: { - typeString = "EFI_STATUS _ModuleEntry(EFI_PEI_FILE_HANDLE FileHandle, EFI_PEI_SERVICES **PeiServices)"; - ok = m_view->ParseTypeString(typeString, result, errors, {}, true); - break; - } + string typeString; + switch (fileType) + { + case PEI: + { + typeString = "EFI_STATUS _ModuleEntry(EFI_PEI_FILE_HANDLE FileHandle, EFI_PEI_SERVICES **PeiServices)"; + ok = m_view->ParseTypeString(typeString, result, errors, {}, true); + break; + } - case DXE: { - typeString = "EFI_STATUS _ModuleEntry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable)"; - ok = m_view->ParseTypeString(typeString, result, errors, {}, true); - break; - } + case DXE: + { + typeString = "EFI_STATUS _ModuleEntry(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE* SystemTable)"; + ok = m_view->ParseTypeString(typeString, result, errors, {}, true); + break; + } - case UNKNOWN: { - LogAlert("Could not identify EFI module type"); - return false; - } - } + case UNKNOWN: + { + LogAlert("Could not identify EFI module type"); + return false; + } + } - if (!ok) - return false; + if (!ok) + return false; - // use UserType so that it would not be overwritten - entryFunc->SetUserType(result.type); - m_view->DefineUserSymbol(new Symbol(FunctionSymbol, "_ModuleEntry", entry)); - m_view->UpdateAnalysisAndWait(); + // use UserType so that it would not be overwritten + entryFunc->SetUserType(result.type); + m_view->DefineUserSymbol(new Symbol(FunctionSymbol, "_ModuleEntry", entry)); + m_view->UpdateAnalysisAndWait(); - TypePropagation propagation = TypePropagation(m_view); - return propagation.propagateFuncParamTypes(entryFunc); + TypePropagation propagation = TypePropagation(m_view); + return propagation.propagateFuncParamTypes(entryFunc); } vector<HighLevelILInstruction> Resolver::HighLevelILExprsAt(Ref<Function> func, Ref<Architecture> arch, uint64_t addr) { - auto llil = func->GetLowLevelIL(); - auto mlil = func->GetMediumLevelIL(); - auto hlil = func->GetHighLevelIL(); + auto llil = func->GetLowLevelIL(); + auto mlil = func->GetMediumLevelIL(); + auto hlil = func->GetHighLevelIL(); - size_t llilIdx = func->GetLowLevelILForInstruction(arch, addr); - size_t llilExprIdx = llil->GetIndexForInstruction(llilIdx); - auto mlilIdxes = llil->GetMediumLevelILExprIndexes(llilExprIdx); + size_t llilIdx = func->GetLowLevelILForInstruction(arch, addr); + size_t llilExprIdx = llil->GetIndexForInstruction(llilIdx); + auto mlilIdxes = llil->GetMediumLevelILExprIndexes(llilExprIdx); - vector<HighLevelILInstruction> hlils; + vector<HighLevelILInstruction> hlils; - for (size_t mlilIdx : mlilIdxes) { - auto hlilIdxes = mlil->GetHighLevelILExprIndexes(mlilIdx); - for (auto hlilIdx : hlilIdxes) { - auto hlilExpr = hlil->GetExpr(hlilIdx); - hlils.push_back(hlilExpr); - } - } - return hlils; + for (size_t mlilIdx : mlilIdxes) + { + auto hlilIdxes = mlil->GetHighLevelILExprIndexes(mlilIdx); + for (auto hlilIdx : hlilIdxes) + { + auto hlilExpr = hlil->GetExpr(hlilIdx); + hlils.push_back(hlilExpr); + } + } + return hlils; } Ref<Type> Resolver::GetTypeFromViewAndPlatform(string typeName) { - QualifiedNameAndType result; - string errors; - bool ok = m_view->ParseTypeString(typeName, result, errors); - if (!ok) { - // TODO how to retrieve platform types? - return nullptr; - } - return result.type; + QualifiedNameAndType result; + string errors; + bool ok = m_view->ParseTypeString(typeName, result, errors); + if (!ok) + { + // TODO how to retrieve platform types? + return nullptr; + } + return result.type; } bool Resolver::resolveGuidInterface(Ref<Function> func, uint64_t addr, int guidPos, int interfacePos) { - auto hlils = HighLevelILExprsAt(func, m_view->GetDefaultArchitecture(), addr); - for (auto hlil : hlils) { - if (hlil.operation != HLIL_CALL) - continue; + auto hlils = HighLevelILExprsAt(func, m_view->GetDefaultArchitecture(), addr); + for (auto hlil : hlils) + { + if (hlil.operation != HLIL_CALL) + continue; - HighLevelILInstruction instr; - if (hlil.GetParameterExprs().size() == 1 && hlil.GetParameterExprs()[0].operation == HLIL_CALL) - instr = hlil.GetParameterExprs()[0]; - else - instr = hlil; + HighLevelILInstruction instr; + if (hlil.GetParameterExprs().size() == 1 && hlil.GetParameterExprs()[0].operation == HLIL_CALL) + instr = hlil.GetParameterExprs()[0]; + else + instr = hlil; - auto params = instr.GetParameterExprs(); - if (params.size() <= max(guidPos, interfacePos)) - continue; + auto params = instr.GetParameterExprs(); + if (params.size() <= max(guidPos, interfacePos)) + continue; - auto guidAddr = params[guidPos].GetValue(); - EFI_GUID guid; - if (guidAddr.state == ConstantValue || guidAddr.state == ConstantPointerValue) { - if (m_view->Read(&guid, guidAddr.value, 16) < 16) - continue; - } else if (guidAddr.state == StackFrameOffset) { - auto mlil = instr.GetMediumLevelIL(); - int64_t offset = 0; - vector<uint8_t> contentBytes; - while (offset < 16) { - auto var = mlil.GetVariableForStackLocation(guidAddr.value + offset); - if (!func->GetVariableType(var)) - break; + auto guidAddr = params[guidPos].GetValue(); + EFI_GUID guid; + if (guidAddr.state == ConstantValue || guidAddr.state == ConstantPointerValue) + { + if (m_view->Read(&guid, guidAddr.value, 16) < 16) + continue; + } + else if (guidAddr.state == StackFrameOffset) + { + auto mlil = instr.GetMediumLevelIL(); + int64_t offset = 0; + vector<uint8_t> contentBytes; + while (offset < 16) + { + auto var = mlil.GetVariableForStackLocation(guidAddr.value + offset); + if (!func->GetVariableType(var)) + break; - auto width = func->GetVariableType(var)->GetWidth(); - if (width == 0 || width > 8) - break; + auto width = func->GetVariableType(var)->GetWidth(); + if (width == 0 || width > 8) + break; - auto value = mlil.GetStackContents(guidAddr.value + offset, width); - int64_t content; - if (value.state == ConstantValue || value.state == ConstantPointerValue) - content = value.value; - else - break; + auto value = mlil.GetStackContents(guidAddr.value + offset, width); + int64_t content; + if (value.state == ConstantValue || value.state == ConstantPointerValue) + content = value.value; + else + break; - for (auto i = 0; i < width; i++) { - contentBytes.push_back(static_cast<uint8_t>(content >> (i * 8))); - } - } - if (contentBytes.size() != 16) - continue; + for (auto i = 0; i < width; i++) + { + contentBytes.push_back(static_cast<uint8_t>(content >> (i * 8))); + } + } + if (contentBytes.size() != 16) + continue; - memcpy(guid.data(), contentBytes.data(), 16); - } else if (params[guidPos].operation == HLIL_VAR) { - // want to check whether is a protocol wrapper - auto ssa = params[guidPos].GetSSAForm(); - HighLevelILInstruction ssaExpr; - if (ssa.operation != HLIL_VAR_SSA) - continue; - if (ssa.GetSSAVariable().version != 0) { - auto incomming_def = func->GetHighLevelIL()->GetSSAVarDefinition(ssa.GetSSAVariable()); - if (!incomming_def) - continue; - auto incomming_def_ssa = func->GetHighLevelIL()->GetSSAForm()->GetExpr(incomming_def); - if (incomming_def_ssa.operation != HLIL_VAR_INIT_SSA) - continue; - if (incomming_def_ssa.GetSourceExpr().operation != HLIL_VAR_SSA) - continue; - if (incomming_def_ssa.GetSourceExpr().GetSSAVariable().version != 0) - continue; - ssaExpr = incomming_def_ssa.GetSourceExpr(); - } else - ssaExpr = ssa; + memcpy(guid.data(), contentBytes.data(), 16); + } + else if (params[guidPos].operation == HLIL_VAR) + { + // want to check whether is a protocol wrapper + auto ssa = params[guidPos].GetSSAForm(); + HighLevelILInstruction ssaExpr; + if (ssa.operation != HLIL_VAR_SSA) + continue; + if (ssa.GetSSAVariable().version != 0) + { + auto incomming_def = func->GetHighLevelIL()->GetSSAVarDefinition(ssa.GetSSAVariable()); + if (!incomming_def) + continue; + auto incomming_def_ssa = func->GetHighLevelIL()->GetSSAForm()->GetExpr(incomming_def); + if (incomming_def_ssa.operation != HLIL_VAR_INIT_SSA) + continue; + if (incomming_def_ssa.GetSourceExpr().operation != HLIL_VAR_SSA) + continue; + if (incomming_def_ssa.GetSourceExpr().GetSSAVariable().version != 0) + continue; + ssaExpr = incomming_def_ssa.GetSourceExpr(); + } + else + ssaExpr = ssa; - auto funcParams = func->GetParameterVariables().GetValue(); - bool found = false; - int incomingGuidIdx; - for (int i = 0; i < funcParams.size(); i++) { - if (funcParams[i] == ssaExpr.GetSSAVariable().var) { - incomingGuidIdx = i; - found = true; - break; - } - } - if (!found) - continue; + auto funcParams = func->GetParameterVariables().GetValue(); + bool found = false; + int incomingGuidIdx; + for (int i = 0; i < funcParams.size(); i++) + { + if (funcParams[i] == ssaExpr.GetSSAVariable().var) + { + incomingGuidIdx = i; + found = true; + break; + } + } + if (!found) + continue; - // see if output interface varible is an incoming parameter - auto interfaceInstrSsa = params[interfacePos].GetSSAForm(); - if (interfaceInstrSsa.operation != HLIL_VAR_SSA) - continue; + // see if output interface varible is an incoming parameter + auto interfaceInstrSsa = params[interfacePos].GetSSAForm(); + if (interfaceInstrSsa.operation != HLIL_VAR_SSA) + continue; - if (interfaceInstrSsa.GetSSAVariable().version != 0) { - auto incomingDef = func->GetHighLevelIL()->GetSSAForm()->GetSSAVarDefinition(interfaceInstrSsa.GetSSAVariable()); - auto defExpr = func->GetHighLevelIL()->GetSSAForm()->GetExpr(incomingDef); - if (defExpr.operation != HLIL_VAR_INIT_SSA) - continue; - if (defExpr.GetSourceExpr().operation != HLIL_VAR_SSA) - continue; - if (defExpr.GetSourceExpr().GetSSAVariable().version != 0) - continue; - interfaceInstrSsa = defExpr.GetSourceExpr(); - } - found = false; - int incomingInstrIdx; - for (int i = 0; i < funcParams.size(); i++) { - if (funcParams[i] == interfaceInstrSsa.GetSSAVariable().var) { - incomingInstrIdx = i; - found = true; - break; - } - } - if (!found) - continue; + if (interfaceInstrSsa.GetSSAVariable().version != 0) + { + auto incomingDef = + func->GetHighLevelIL()->GetSSAForm()->GetSSAVarDefinition(interfaceInstrSsa.GetSSAVariable()); + auto defExpr = func->GetHighLevelIL()->GetSSAForm()->GetExpr(incomingDef); + if (defExpr.operation != HLIL_VAR_INIT_SSA) + continue; + if (defExpr.GetSourceExpr().operation != HLIL_VAR_SSA) + continue; + if (defExpr.GetSourceExpr().GetSSAVariable().version != 0) + continue; + interfaceInstrSsa = defExpr.GetSourceExpr(); + } + found = false; + int incomingInstrIdx; + for (int i = 0; i < funcParams.size(); i++) + { + if (funcParams[i] == interfaceInstrSsa.GetSSAVariable().var) + { + incomingInstrIdx = i; + found = true; + break; + } + } + if (!found) + continue; - LogInfo("Found EFI Protocol wrapper at 0x%llx, checking reference to this function", addr); + LogInfo("Found EFI Protocol wrapper at 0x%llx, checking reference to this function", addr); - auto refs = m_view->GetCodeReferences(func->GetStart()); - for (auto &ref : refs) - resolveGuidInterface(ref.func, ref.addr, incomingGuidIdx, incomingInstrIdx); - continue; - } + auto refs = m_view->GetCodeReferences(func->GetStart()); + for (auto& ref : refs) + resolveGuidInterface(ref.func, ref.addr, incomingGuidIdx, incomingInstrIdx); + continue; + } - if (guid.empty()) - continue; + if (guid.empty()) + continue; - auto names = lookupGuid(guid); - string protocol_name = names.first; - string guidName = names.second; + auto names = lookupGuid(guid); + string protocol_name = names.first; + string guidName = names.second; - if (protocol_name.empty()) { - // protocol name is empty - if (!guidName.empty()) { - // user added guid, check whether the user has added the protocol type - string possible_protocol_type = guidName; - size_t pos = possible_protocol_type.rfind("_GUID"); - if (pos != string::npos) - possible_protocol_type.erase(pos, 5); + if (protocol_name.empty()) + { + // protocol name is empty + if (!guidName.empty()) + { + // user added guid, check whether the user has added the protocol type + string possible_protocol_type = guidName; + size_t pos = possible_protocol_type.rfind("_GUID"); + if (pos != string::npos) + possible_protocol_type.erase(pos, 5); - // check whether `possible_protocol_type` is in bv.types - QualifiedNameAndType result; - string errors; - bool ok = m_view->ParseTypeString(possible_protocol_type, result, errors); - if (ok) - protocol_name = possible_protocol_type; - } else { - // use UnknownProtocol as defult - LogWarn("Unknown EFI Protocol referenced at 0x%llx", addr); - guidName = nonConflictingName("UnknownProtocolGuid"); - } - } + // check whether `possible_protocol_type` is in bv.types + QualifiedNameAndType result; + string errors; + bool ok = m_view->ParseTypeString(possible_protocol_type, result, errors); + if (ok) + protocol_name = possible_protocol_type; + } + else + { + // use UnknownProtocol as defult + LogWarn("Unknown EFI Protocol referenced at 0x%llx", addr); + guidName = nonConflictingName("UnknownProtocolGuid"); + } + } - // now we just need to rename the GUID and apply the protocol type - auto sym = m_view->GetSymbolByAddress(guidAddr.value); - auto guidVarName = guidName; - if (sym) - guidVarName = sym->GetRawName(); + // now we just need to rename the GUID and apply the protocol type + auto sym = m_view->GetSymbolByAddress(guidAddr.value); + auto guidVarName = guidName; + if (sym) + guidVarName = sym->GetRawName(); - QualifiedNameAndType result; - string errors; - bool ok = m_view->ParseTypeString("EFI_GUID", result, errors); - if (!ok) - return false; - m_view->DefineDataVariable(guidAddr.value, result.type); - m_view->DefineUserSymbol(new Symbol(DataSymbol, guidVarName, guidAddr.value)); + QualifiedNameAndType result; + string errors; + bool ok = m_view->ParseTypeString("EFI_GUID", result, errors); + if (!ok) + return false; + m_view->DefineDataVariable(guidAddr.value, result.type); + m_view->DefineUserSymbol(new Symbol(DataSymbol, guidVarName, guidAddr.value)); - if (protocol_name.empty()) { - LogWarn("Found unknown protocol at 0x%llx", addr); - protocol_name = "VOID*"; - } + if (protocol_name.empty()) + { + LogWarn("Found unknown protocol at 0x%llx", addr); + protocol_name = "VOID*"; + } - auto protocolType = GetTypeFromViewAndPlatform(protocol_name); - if (!protocolType) - continue; - protocolType = Type::PointerType(m_view->GetDefaultArchitecture(), protocolType); - auto interfaceParam = params[interfacePos]; - if (interfaceParam.operation == HLIL_ADDRESS_OF) { - interfaceParam = interfaceParam.GetSourceExpr(); - if (interfaceParam.operation == HLIL_VAR) { - string interfaceName = guidName; - if (guidName.substr(0, 19) == "UnknownProtocolGuid") { - interfaceName.replace(0, 19, "UnknownProtocolInterface"); - interfaceName = nonConflictingLocalName(func, interfaceName); - } else { - interfaceName = nonConflictingLocalName(func, GetVarNameForTypeStr(guidName)); - } - func->CreateUserVariable(interfaceParam.GetVariable(), - protocolType, - interfaceName); - } - } else if (interfaceParam.operation == HLIL_CONST_PTR) { - auto dataVarAddr = interfaceParam.GetValue().value; - m_view->DefineDataVariable(dataVarAddr, protocolType); - string interfaceName = guidName; - if (interfaceName.find("GUID") != interfaceName.npos) { - interfaceName.replace(interfaceName.find("GUID"), 4, "INTERFACE"); - interfaceName = GetVarNameForTypeStr(interfaceName); - } else if (guidName.substr(0, 19) == "UnknownProtocolGuid") { - interfaceName.replace(15, 4, "Interface"); - } - m_view->DefineUserSymbol(new Symbol(DataSymbol, interfaceName, dataVarAddr)); - } - m_view->UpdateAnalysisAndWait(); - } + auto protocolType = GetTypeFromViewAndPlatform(protocol_name); + if (!protocolType) + continue; + protocolType = Type::PointerType(m_view->GetDefaultArchitecture(), protocolType); + auto interfaceParam = params[interfacePos]; - return true; + // TODO we need to check whether it is an aliased var, or it can probably overwrite the other interfaces + + if (interfaceParam.operation == HLIL_ADDRESS_OF) + { + interfaceParam = interfaceParam.GetSourceExpr(); + if (interfaceParam.operation == HLIL_VAR) + { + string interfaceName = guidName; + if (guidName.substr(0, 19) == "UnknownProtocolGuid") + { + interfaceName.replace(0, 19, "UnknownProtocolInterface"); + interfaceName = nonConflictingLocalName(func, interfaceName); + } + else + { + interfaceName = nonConflictingLocalName(func, GetVarNameForTypeStr(guidName)); + } + func->CreateUserVariable(interfaceParam.GetVariable(), protocolType, interfaceName); + } + } + else if (interfaceParam.operation == HLIL_CONST_PTR) + { + auto dataVarAddr = interfaceParam.GetValue().value; + m_view->DefineDataVariable(dataVarAddr, protocolType); + string interfaceName = guidName; + if (interfaceName.find("GUID") != interfaceName.npos) + { + interfaceName = interfaceName.replace(interfaceName.find("GUID"), 4, "INTERFACE"); + interfaceName = GetVarNameForTypeStr(interfaceName); + } + else if (guidName.substr(0, 19) == "UnknownProtocolGuid") + { + interfaceName.replace(15, 4, "Interface"); + } + m_view->DefineUserSymbol(new Symbol(DataSymbol, interfaceName, dataVarAddr)); + } + m_view->UpdateAnalysisAndWait(); + } + + return true; } -bool Resolver::defineTypeAtCallsite(Ref<Function> func, uint64_t addr, const string typeName, int paramIdx, bool followFields) +bool Resolver::defineTypeAtCallsite( + Ref<Function> func, uint64_t addr, const string typeName, int paramIdx, bool followFields) { - auto mlil = func->GetMediumLevelIL(); - size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), addr); - auto instr = mlil->GetInstruction(mlilIdx); + auto mlil = func->GetMediumLevelIL(); + size_t mlilIdx = mlil->GetInstructionStart(m_view->GetDefaultArchitecture(), addr); + auto instr = mlil->GetInstruction(mlilIdx); - auto params = instr.GetParameterExprs(); - if (params.size() < paramIdx + 1) - return false; + auto params = instr.GetParameterExprs(); + if (params.size() < paramIdx + 1) + return false; - auto param = params[paramIdx]; - if (param.operation != MLIL_CONST_PTR) - return false; + auto param = params[paramIdx]; + if (param.operation != MLIL_CONST_PTR) + return false; - uint64_t varAddr = param.GetConstant(); - DataVariable datavar; - auto ok = m_view->GetDataVariableAtAddress(varAddr, datavar); - if (ok) { - string datavarTypeName = datavar.type.GetValue()->GetTypeName().GetString(); - if (datavarTypeName.find(typeName) != datavarTypeName.npos) - // the variable already has this type, return - return false; - } + uint64_t varAddr = param.GetConstant(); + DataVariable datavar; + auto ok = m_view->GetDataVariableAtAddress(varAddr, datavar); + if (ok) + { + string datavarTypeName = datavar.type.GetValue()->GetTypeName().GetString(); + if (datavarTypeName.find(typeName) != datavarTypeName.npos) + // the variable already has this type, return + return false; + } - // Now we want to define the type at varAddr + // Now we want to define the type at varAddr - if (typeName == "EFI_GUID") { - // If it's GUID, we want to define it with name - defineAndLookupGuid(varAddr); - // defining a GUID should never fail. Also it can not have fields - return true; - } + if (typeName == "EFI_GUID") + { + // If it's GUID, we want to define it with name + defineAndLookupGuid(varAddr); + // defining a GUID should never fail. Also it can not have fields + return true; + } - QualifiedNameAndType result; - string errors; - ok = m_view->ParseTypeString(typeName, result, errors); - if (!ok) { - LogError("Cannot parse type %s when trying to define type at 0x%llx", typeName.c_str(), addr); - return false; - } + QualifiedNameAndType result; + string errors; + ok = m_view->ParseTypeString(typeName, result, errors); + if (!ok) + { + LogError("Cannot parse type %s when trying to define type at 0x%llx", typeName.c_str(), addr); + return false; + } - m_view->DefineDataVariable(varAddr, result.type); + m_view->DefineDataVariable(varAddr, result.type); - if (!followFields) - return true; + if (!followFields) + return true; - // We want to define the Guid field and the Notify field, which are both pointers - DataVariable structVar; - ok = m_view->GetDataVariableAtAddress(varAddr, structVar); - if (!ok) - return false; + // We want to define the Guid field and the Notify field, which are both pointers + DataVariable structVar; + ok = m_view->GetDataVariableAtAddress(varAddr, structVar); + if (!ok) + return false; - if (!structVar.type.GetValue()->IsNamedTypeRefer()) - return false; + if (!structVar.type.GetValue()->IsNamedTypeRefer()) + return false; - auto structTypeId = structVar.type.GetValue()->GetNamedTypeReference()->GetTypeId(); - auto structStructureType = m_view->GetTypeById(structTypeId)->GetStructure(); + auto structTypeId = structVar.type.GetValue()->GetNamedTypeReference()->GetTypeId(); + auto structStructureType = m_view->GetTypeById(structTypeId)->GetStructure(); - if (!structStructureType) - return false; - auto members = structStructureType->GetMembers(); + if (!structStructureType) + return false; + auto members = structStructureType->GetMembers(); - // we want to keep this name for renaming NotifyFunction - string guidName; - for (auto member : members) { - auto memberOffset = member.offset; - auto memberType = member.type.GetValue(); - auto memberName = member.name; + // we want to keep this name for renaming NotifyFunction + string guidName; + for (auto member : members) + { + auto memberOffset = member.offset; + auto memberType = member.type.GetValue(); + auto memberName = member.name; - // we only want to define pointers - if (!memberType->IsPointer() && !(memberType->IsNamedTypeRefer() && memberName == "Notify")) - continue; + // we only want to define pointers + if (!memberType->IsPointer() && !(memberType->IsNamedTypeRefer() && memberName == "Notify")) + continue; - if (memberName == "Guid") { - uint64_t guidAddr = 0; - m_view->Read(&guidAddr, varAddr + memberOffset, m_view->GetAddressSize()); - auto name = defineAndLookupGuid(guidAddr); - guidName = name.second; - } else if (memberName == "Notify") { - // Notify has the type EFI_NOTIFY_ENTRY_POINT - // which is a NamedTypeRefer - uint64_t funcAddr; - m_view->Read(&funcAddr, varAddr + memberOffset, m_view->GetAddressSize()); - auto notifyFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), funcAddr); - if (!notifyFunc) - continue; + if (memberName == "Guid") + { + uint64_t guidAddr = 0; + m_view->Read(&guidAddr, varAddr + memberOffset, m_view->GetAddressSize()); + auto name = defineAndLookupGuid(guidAddr); + guidName = name.second; + } + else if (memberName == "Notify") + { + // Notify has the type EFI_NOTIFY_ENTRY_POINT + // which is a NamedTypeRefer + uint64_t funcAddr; + m_view->Read(&funcAddr, varAddr + memberOffset, m_view->GetAddressSize()); + auto notifyFunc = m_view->GetAnalysisFunction(m_view->GetDefaultPlatform(), funcAddr); + if (!notifyFunc) + continue; - string funcName = guidName; - if (guidName.empty()) - funcName = nonConflictingName("UnknownNotify"); - else - funcName = "Notify" + funcName.replace(funcName.find("GUID"), 4, ""); + string funcName = guidName; + if (guidName.empty()) + funcName = nonConflictingName("UnknownNotify"); + else + funcName = "Notify" + funcName.replace(funcName.find("GUID"), 4, ""); - string notifyTypeStr = "EFI_STATUS Notify(EFI_PEI_SERVICES **PeiServices, EFI_PEI_NOTIFY_DESCRIPTOR* NotifyDescriptor, VOID* Ppi)"; - ok = m_view->ParseTypeString(notifyTypeStr, result, errors); - notifyFunc->SetUserType(result.type); - m_view->DefineUserSymbol(new Symbol(FunctionSymbol, funcName, funcAddr)); - m_view->UpdateAnalysisAndWait(); + string notifyTypeStr = + "EFI_STATUS Notify(EFI_PEI_SERVICES **PeiServices, EFI_PEI_NOTIFY_DESCRIPTOR* NotifyDescriptor, VOID* " + "Ppi)"; + ok = m_view->ParseTypeString(notifyTypeStr, result, errors); + notifyFunc->SetUserType(result.type); + m_view->DefineUserSymbol(new Symbol(FunctionSymbol, funcName, funcAddr)); + m_view->UpdateAnalysisAndWait(); - TypePropagation propagator(m_view); - propagator.propagateFuncParamTypes(notifyFunc); - } - } - return true; + TypePropagation propagator(m_view); + propagator.propagateFuncParamTypes(notifyFunc); + } + } + return true; } Resolver::Resolver(Ref<BinaryView> view, Ref<BackgroundTask> task) { - m_view = view; - m_task = task; - m_width = m_view->GetAddressSize(); + m_view = view; + m_task = task; + m_width = m_view->GetAddressSize(); } pair<string, string> Resolver::lookupGuid(EFI_GUID guidBytes) { - auto it = m_protocol.find(guidBytes); - if (it != m_protocol.end()) - return it->second; + auto it = m_protocol.find(guidBytes); + if (it != m_protocol.end()) + return it->second; - auto user_it = m_user_guids.find(guidBytes); - if (user_it != m_user_guids.end()) - return make_pair(string(), user_it->second); + auto user_it = m_user_guids.find(guidBytes); + if (user_it != m_user_guids.end()) + return make_pair(string(), user_it->second); - return {}; + return {}; } pair<string, string> Resolver::defineAndLookupGuid(uint64_t addr) { - EFI_GUID guidBytes; - try { - auto readSize = m_view->Read(&guidBytes, addr, 16); - if (readSize != 16) - return make_pair(string(), string()); - } catch (ReadException) { - LogError("Read GUID failed at 0x%llx", addr); - return make_pair(string(), string()); - } - auto namePair = lookupGuid(guidBytes); - string protocolName = namePair.first; - string guidName = namePair.second; + EFI_GUID guidBytes; + try + { + auto readSize = m_view->Read(&guidBytes, addr, 16); + if (readSize != 16) + return make_pair(string(), string()); + } + catch (ReadException) + { + LogError("Read GUID failed at 0x%llx", addr); + return make_pair(string(), string()); + } + auto namePair = lookupGuid(guidBytes); + string protocolName = namePair.first; + string guidName = namePair.second; - QualifiedNameAndType result; - string errors; - // must use ParseTypeString, - // m_view->GetTypeByName() doesn't return a NamedTypeReference and the DataRenderer doesn't applied - bool ok = m_view->ParseTypeString("EFI_GUID", result, errors); - if (!ok) - return make_pair(string(""), string("")); - m_view->DefineDataVariable(addr, result.type); - if (guidName.empty()) { - m_view->DefineUserSymbol(new Symbol(DataSymbol, nonConflictingName("UnknownGuid"), addr)); - LogDebug("Found UnknownGuid at 0x%llx", addr); - } else { - m_view->DefineUserSymbol(new Symbol(DataSymbol, guidName, addr)); - LogDebug("Define %s at 0x%llx", guidName.c_str(), addr); - } + QualifiedNameAndType result; + string errors; + // must use ParseTypeString, + // m_view->GetTypeByName() doesn't return a NamedTypeReference and the DataRenderer doesn't applied + bool ok = m_view->ParseTypeString("EFI_GUID", result, errors); + if (!ok) + return make_pair(string(""), string("")); + m_view->DefineDataVariable(addr, result.type); + if (guidName.empty()) + { + m_view->DefineUserSymbol(new Symbol(DataSymbol, nonConflictingName("UnknownGuid"), addr)); + LogDebug("Found UnknownGuid at 0x%llx", addr); + } + else + { + m_view->DefineUserSymbol(new Symbol(DataSymbol, guidName, addr)); + LogDebug("Define %s at 0x%llx", guidName.c_str(), addr); + } - return namePair; + return namePair; } diff --git a/platform/efi/efi_resolver/src/TypePropagation.cpp b/platform/efi/efi_resolver/src/TypePropagation.cpp index 4b4fac6c..ff0d43b9 100644 --- a/platform/efi/efi_resolver/src/TypePropagation.cpp +++ b/platform/efi/efi_resolver/src/TypePropagation.cpp @@ -3,181 +3,196 @@ TypePropagation::TypePropagation(BinaryView* view) { - m_view = view; - m_queue.clear(); - m_platform = view->GetDefaultPlatform(); + m_view = view; + m_queue.clear(); + m_platform = view->GetDefaultPlatform(); } -const std::map<std::string, std::string> defaultName = { - { "EFI_SYSTEM_TABLE", "gST" }, - { "EFI_BOOT_SERVICES", "gBS" }, - { "EFI_RUNTIME_SERVICES", "gRT" }, - { "EFI_MM_SYSTEM_TABLE", "gMmst" }, - { "EFI_SMM_SYSTEM_TABLE2", "gSmmst" }, - { "EFI_HANDLE", "gHandle" } -}; +const std::map<std::string, std::string> defaultName = {{"EFI_SYSTEM_TABLE", "gST"}, {"EFI_BOOT_SERVICES", "gBS"}, + {"EFI_RUNTIME_SERVICES", "gRT"}, {"EFI_MM_SYSTEM_TABLE", "gMmst"}, {"EFI_SMM_SYSTEM_TABLE2", "gSmmst"}, + {"EFI_HANDLE", "gHandle"}}; bool TypePropagation::propagateFuncParamTypes(Function* func) { - m_queue.push_back(func->GetStart()); + m_queue.push_back(func->GetStart()); - LogDebug("Start Type propagation from 0x%llx", func->GetStart()); + LogDebug("Start Type propagation from 0x%llx", func->GetStart()); - while (!m_queue.empty()) { - uint64_t addr = m_queue.front(); - m_queue.pop_front(); + while (!m_queue.empty()) + { + uint64_t addr = m_queue.front(); + m_queue.pop_front(); - Ref<Function> target_func = m_view->GetAnalysisFunction(m_platform, addr); - auto params = target_func->GetType()->GetParameters(); - bool update = false; + Ref<Function> target_func = m_view->GetAnalysisFunction(m_platform, addr); + auto params = target_func->GetType()->GetParameters(); + bool update = false; - auto param_vars = target_func->GetParameterVariables().GetValue(); - for (auto var : param_vars) { - bool propagate = false; - auto var_type = target_func->GetVariableType(var).GetValue(); + auto param_vars = target_func->GetParameterVariables().GetValue(); + for (auto var : param_vars) + { + bool propagate = false; + auto var_type = target_func->GetVariableType(var).GetValue(); - if (var_type->IsPointer()) { - Ref<Type> target_type = var_type->GetChildType().GetValue(); - if (target_type->IsPointer() || target_type->IsNamedTypeRefer()) - propagate = true; - } else if (var_type->IsNamedTypeRefer()) { - Ref<Type> target_type = m_view->GetTypeById(var_type->GetNamedTypeReference()->GetTypeId()); - if (target_type->IsPointer()) - propagate = true; - } - if (!propagate) - continue; + if (var_type->IsPointer()) + { + Ref<Type> target_type = var_type->GetChildType().GetValue(); + if (target_type->IsPointer() || target_type->IsNamedTypeRefer()) + propagate = true; + } + else if (var_type->IsNamedTypeRefer()) + { + Ref<Type> target_type = m_view->GetTypeById(var_type->GetNamedTypeReference()->GetTypeId()); + if (target_type->IsPointer()) + propagate = true; + } + if (!propagate) + continue; - // Check whether the param is an aliased var. If it's an aliased var, it may not be directly used in the function - Ref<HighLevelILFunction> hlil_func_ssa = target_func->GetHighLevelIL()->GetSSAForm(); - std::set<Variable> aliased_vars = target_func->GetHighLevelILAliasedVariables(); + // Check whether the param is an aliased var. If it's an aliased var, it may not be directly used in the + // function + Ref<HighLevelILFunction> hlil_func_ssa = target_func->GetHighLevelIL()->GetSSAForm(); + std::set<Variable> aliased_vars = target_func->GetHighLevelILAliasedVariables(); - auto it = aliased_vars.find(var); - if (it == aliased_vars.end()) { - // not an aliaed var, use version 0 - update |= propagateFuncParamTypes(target_func, SSAVariable(var, 0)); - } else { - // this param is an aliased var, get the ssa_var - auto uses = target_func->GetHighLevelIL()->GetVariableUses(var); - for (auto use : uses) { - auto hlil_instr = target_func->GetHighLevelIL()->GetExpr(use); - hlil_instr = hlil_instr.GetParent(); - if (hlil_instr.operation != HLIL_VAR_INIT) - continue; - SSAVariable ssa_var = hlil_instr.GetSSAForm().GetDestSSAVariable(); - update |= propagateFuncParamTypes(target_func, ssa_var); - } - } - } + auto it = aliased_vars.find(var); + if (it == aliased_vars.end()) + { + // not an aliaed var, use version 0 + update |= propagateFuncParamTypes(target_func, SSAVariable(var, 0)); + } + else + { + // this param is an aliased var, get the ssa_var + auto uses = target_func->GetHighLevelIL()->GetVariableUses(var); + for (auto use : uses) + { + auto hlil_instr = target_func->GetHighLevelIL()->GetExpr(use); + hlil_instr = hlil_instr.GetParent(); + if (hlil_instr.operation != HLIL_VAR_INIT) + continue; + SSAVariable ssa_var = hlil_instr.GetSSAForm().GetDestSSAVariable(); + update |= propagateFuncParamTypes(target_func, ssa_var); + } + } + } - if (update) - m_view->UpdateAnalysisAndWait(); - } - return true; + if (update) + m_view->UpdateAnalysisAndWait(); + } + return true; } bool TypePropagation::propagateFuncParamTypes(Function* func, SSAVariable ssa_var) { - bool update = false; - auto mlil_func_ssa = func->GetMediumLevelIL()->GetSSAForm(); - auto uses = mlil_func_ssa->GetSSAVarUses(ssa_var); - for (auto use : uses) { - auto instr = mlil_func_ssa->GetInstruction(use); - switch (instr.operation) { - case MLIL_CALL_SSA: - case MLIL_TAILCALL_SSA: { - // propagate variable type to sub function - auto dest = instr.GetDestExpr(); - if (!dest.GetValue().IsConstant()) - continue; - Ref<Function> subfunc = m_view->GetAnalysisFunction(m_platform, dest.GetValue().value); + bool update = false; + auto mlil_func_ssa = func->GetMediumLevelIL()->GetSSAForm(); + auto uses = mlil_func_ssa->GetSSAVarUses(ssa_var); + for (auto use : uses) + { + auto instr = mlil_func_ssa->GetInstruction(use); + switch (instr.operation) + { + case MLIL_CALL_SSA: + case MLIL_TAILCALL_SSA: + { + // propagate variable type to sub function + auto dest = instr.GetDestExpr(); + if (!dest.GetValue().IsConstant()) + continue; + Ref<Function> subfunc = m_view->GetAnalysisFunction(m_platform, dest.GetValue().value); - if (!subfunc) - continue; + if (!subfunc) + continue; - auto subfunc_type = subfunc->GetType(); - auto subfunc_params = subfunc->GetType()->GetParameters(); + auto subfunc_type = subfunc->GetType(); + auto subfunc_params = subfunc->GetType()->GetParameters(); - auto instr_params = instr.GetParameterExprs(); - for (int i = 0; i < instr_params.size(); i++) { - if (instr_params[i].operation != MLIL_VAR_SSA) - continue; - if (instr_params[i].GetSourceSSAVariable() != ssa_var) - continue; - if (i >= subfunc_params.size()) - break; - auto ssa_var_type = func->GetVariableType(ssa_var.var).GetValue(); - auto typeName = GetOriginalTypeName(ssa_var_type); + auto instr_params = instr.GetParameterExprs(); + for (int i = 0; i < instr_params.size(); i++) + { + if (instr_params[i].operation != MLIL_VAR_SSA) + continue; + if (instr_params[i].GetSourceSSAVariable() != ssa_var) + continue; + if (i >= subfunc_params.size()) + break; + auto ssa_var_type = func->GetVariableType(ssa_var.var).GetValue(); + auto typeName = GetOriginalTypeName(ssa_var_type); - auto changeFuncType = [](BinaryView* bv, Ref<Type> funcType, std::string paramName, Ref<Type> paramType, int paramIdx) { - auto newFuncType = TypeBuilder(funcType); - auto adjustedParams = newFuncType.GetParameters(); - adjustedParams.at(paramIdx) = FunctionParameter(paramName, paramType); - newFuncType.SetParameters(adjustedParams); - return newFuncType.Finalize(); - }; + auto changeFuncType = + [](BinaryView* bv, Ref<Type> funcType, std::string paramName, Ref<Type> paramType, int paramIdx) { + auto newFuncType = TypeBuilder(funcType); + auto adjustedParams = newFuncType.GetParameters(); + adjustedParams.at(paramIdx) = FunctionParameter(paramName, paramType); + newFuncType.SetParameters(adjustedParams); + return newFuncType.Finalize(); + }; - subfunc->SetUserType(changeFuncType(m_view, subfunc_type, GetVarNameForTypeStr(typeName), ssa_var_type, i)); - m_view->UpdateAnalysisAndWait(); + subfunc->SetUserType( + changeFuncType(m_view, subfunc_type, GetVarNameForTypeStr(typeName), ssa_var_type, i)); + m_view->UpdateAnalysisAndWait(); - if (std::find(m_queue.begin(), m_queue.end(), subfunc->GetStart()) == m_queue.end()) - m_queue.push_back(subfunc->GetStart()); - update = true; - break; - } - break; - } + if (std::find(m_queue.begin(), m_queue.end(), subfunc->GetStart()) == m_queue.end()) + m_queue.push_back(subfunc->GetStart()); + update = true; + break; + } + break; + } - case MLIL_STORE_SSA: { - auto target = instr.GetDestExpr<MLIL_STORE_SSA>(); - if (!target.GetValue().IsConstant()) - continue; - auto constant = target.GetValue().value; - auto ssa_var_type = func->GetVariableType(ssa_var.var).GetValue(); - auto typeName = GetOriginalTypeName(ssa_var_type); + case MLIL_STORE_SSA: + { + auto target = instr.GetDestExpr<MLIL_STORE_SSA>(); + if (!target.GetValue().IsConstant()) + continue; + auto constant = target.GetValue().value; + auto ssa_var_type = func->GetVariableType(ssa_var.var).GetValue(); + auto typeName = GetOriginalTypeName(ssa_var_type); - auto it = defaultName.find(typeName); - if (it != defaultName.end()) - typeName = it->second; + auto it = defaultName.find(typeName); + if (it != defaultName.end()) + typeName = it->second; - m_view->DefineDataVariable(constant, ssa_var_type); - m_view->DefineUserSymbol(new Symbol(DataSymbol, typeName, constant)); + m_view->DefineDataVariable(constant, ssa_var_type); + m_view->DefineUserSymbol(new Symbol(DataSymbol, typeName, constant)); - update = true; - break; - } + update = true; + break; + } - case MLIL_SET_VAR_SSA: { - auto src = instr.GetSourceExpr<MLIL_SET_VAR_SSA>(); - auto dest = instr.GetDestSSAVariable<MLIL_SET_VAR_SSA>(); + case MLIL_SET_VAR_SSA: + { + auto src = instr.GetSourceExpr<MLIL_SET_VAR_SSA>(); + auto dest = instr.GetDestSSAVariable<MLIL_SET_VAR_SSA>(); - auto dest_type = func->GetVariableType(dest.var); - Confidence<Ref<Type>> src_type; - switch (src.operation) { - case MLIL_VAR_SSA: - src_type = func->GetVariableType(src.GetSourceSSAVariable().var); - break; + auto dest_type = func->GetVariableType(dest.var); + Confidence<Ref<Type>> src_type; + switch (src.operation) + { + case MLIL_VAR_SSA: + src_type = func->GetVariableType(src.GetSourceSSAVariable().var); + break; - case MLIL_LOAD_SSA: - case MLIL_LOAD_STRUCT_SSA: - src_type = src.GetType(); - break; + case MLIL_LOAD_SSA: + case MLIL_LOAD_STRUCT_SSA: + src_type = src.GetType(); + break; - default: - continue; - } + default: + continue; + } - if (src_type.GetValue() && src_type.GetValue() != dest_type.GetValue()) { - func->CreateUserVariable(dest.var, src_type, func->GetVariableName(dest.var)); - update |= propagateFuncParamTypes(func, SSAVariable(dest.var, dest.version)); - } - break; - } + if (src_type.GetValue() && src_type.GetValue() != dest_type.GetValue()) + { + func->CreateUserVariable(dest.var, src_type, func->GetVariableName(dest.var)); + update |= propagateFuncParamTypes(func, SSAVariable(dest.var, dest.version)); + } + break; + } - default: - LogInfo("Not handled case during type propagation. At %llx: %d", instr.address, instr.operation); - break; - } - } - return update; + default: + LogInfo("Not handled case during type propagation. At %llx: %d", instr.address, instr.operation); + break; + } + } + return update; } |
