summaryrefslogtreecommitdiff
path: root/plugins/efi_resolver/src/Plugin.cpp
blob: 2f43c4f3697282f0a7e847c6ad15e1f54e4a7fcf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "DxeResolver.h"
#include "PeiResolver.h"
#include "binaryninjaapi.h"
#include <thread>

using namespace BinaryNinja;

static Ref<BackgroundTask> m_efiBackgroundTask = nullptr;

bool IsValid(BinaryView* view)
{
	if (!view)
		return false;

	auto platform = view->GetDefaultPlatform();
	return (platform && platform->GetName().find("efi-") != std::string::npos);
}


void RunCommand(Ref<BinaryView> view)
{
	m_efiBackgroundTask = new BackgroundTask("Running EFI resolver...", true);
	thread resolverThread([view]() {
		LogInfo("Identifying EFI module type...");
		EFIModuleType moduleType = identifyModuleType(view);

		auto undo = view->BeginUndoActions();
		if (moduleType == PEI)
		{
			m_efiBackgroundTask->SetProgressText("Resolving PEIM...");
			auto resolver = PeiResolver(view, m_efiBackgroundTask);
			resolver.resolvePei();
		}
		else if (moduleType == DXE)
		{
			m_efiBackgroundTask->SetProgressText("Resolving DXE protocols...");
			auto resolver = DxeResolver(view, m_efiBackgroundTask);
			resolver.resolveDxe();
			m_efiBackgroundTask->SetProgressText("Resolving MM related protocols...");
			resolver.resolveSmm();
		}
		view->CommitUndoActions(undo);
		m_efiBackgroundTask->Finish();
	});

	resolverThread.detach();
}


void RunWorkflow(const Ref<AnalysisContext>& analysisContext)
{
	auto view = analysisContext->GetBinaryView();
	if (IsValid(view))
		RunCommand(view);
}


extern "C"
{
	BN_DECLARE_CORE_ABI_VERSION
	BINARYNINJAPLUGIN bool CorePluginInit()
	{
		EfiGuidRenderer::Register();
		auto workflow = Workflow::Get("core.module.metaAnalysis")->Clone();
		workflow->RegisterActivity(R"~({
			"title": "EFI Resolver",
			"name": "analysis.efi.efiResolver",
			"role": "action",
			"description": "This analysis step resolves EFI protocol interfaces and propagates type information.",
			"eligibility": {
				"runOnce": true,
				"auto": {}
			},
			"dependencies": {
				"downstream": ["core.module.update"]
			}
		})~", &RunWorkflow);

		workflow->InsertAfter("core.module.extendedAnalysis", "analysis.efi.efiResolver");
		Workflow::RegisterWorkflow(workflow);
		PluginCommand::Register("Run EFI Resolver", "Resolve EFI interfaces and types", &RunCommand, &IsValid);
		return true;
	}
}