diff options
| author | Zichuan Li <34680029+river-li@users.noreply.github.com> | 2024-08-15 18:23:43 -0400 |
|---|---|---|
| committer | Brandon Miller <brandon@vector35.com> | 2025-05-08 07:23:08 -0400 |
| commit | f07f66ba03dfeed222f419e1bae274e95cbcd2d4 (patch) | |
| tree | ac93834d248b5b2af242a9288785106bcecc354f /platform | |
| parent | 7f08117cfeb48a8f48d08e14cb498ee028efcef2 (diff) | |
misc: formated code and fixed several small issues
1. Fix code related to SMI handlers
2. also parse handlers registered by SxDispatch and parse them together
3. Set Progress Text properly
Diffstat (limited to 'platform')
| -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; } |
