summaryrefslogtreecommitdiff
path: root/platform/efi/efi_resolver/src/Resolver.cpp
diff options
context:
space:
mode:
authorZichuan Li <34680029+river-li@users.noreply.github.com>2024-08-15 18:23:43 -0400
committerBrandon Miller <brandon@vector35.com>2025-05-08 07:23:08 -0400
commitf07f66ba03dfeed222f419e1bae274e95cbcd2d4 (patch)
treeac93834d248b5b2af242a9288785106bcecc354f /platform/efi/efi_resolver/src/Resolver.cpp
parent7f08117cfeb48a8f48d08e14cb498ee028efcef2 (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/efi/efi_resolver/src/Resolver.cpp')
-rw-r--r--platform/efi/efi_resolver/src/Resolver.cpp1141
1 files changed, 609 insertions, 532 deletions
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;
}