Skip to content

Commit dd32976

Browse files
committed
Utilise BackgroundTask and do work on a seperate thread
1 parent 1360242 commit dd32976

File tree

2 files changed

+160
-113
lines changed

2 files changed

+160
-113
lines changed

library.cpp

Lines changed: 160 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
#include "library.h"
2+
#include <thread>
23

34
using namespace BinaryNinja;
45

56
extern "C"
67
{
78
BN_DECLARE_CORE_ABI_VERSION
89

9-
BINARYNINJAPLUGIN bool CorePluginInit()
10+
BINARYNINJAPLUGIN bool CorePluginInit()
1011
{
1112
PluginCommand::Register(
1213
"Native Predicate Solver\\Patch Opaque Predicates (Current Function)",
@@ -18,147 +19,195 @@ extern "C"
1819
LogWarn("No function at current address 0x%llx", addr);
1920
return;
2021
}
21-
22+
2223
auto func = functions[0];
2324
auto mlil = func->GetMediumLevelIL();
2425
if (!mlil) {
2526
LogWarn("No MLIL available for function at 0x%llx", func->GetStart());
2627
return;
2728
}
28-
29+
2930
auto arch = func->GetArchitecture();
3031
if (!arch) {
3132
LogWarn("Failed to get architecture for function");
3233
return;
3334
}
34-
35+
3536
std::string funcName = func->GetSymbol() ? func->GetSymbol()->GetShortName() : "sub_" + std::to_string(func->GetStart());
36-
LogInfo("[+] Processing %s", funcName.c_str());
37-
38-
int totalPatches = 0;
39-
int pass = 1;
40-
const int maxPasses = 10;
41-
42-
while (pass <= maxPasses) {
43-
int patchCount = 0;
44-
size_t instructionCount = mlil->GetInstructionCount();
45-
46-
for (size_t i = 0; i < instructionCount; ++i) {
47-
auto instr = mlil->GetInstruction(i);
48-
if (instr.operation != MLIL_IF)
49-
continue;
50-
51-
auto val = mlil->GetExprValue(instr.GetConditionExpr());
52-
if (val.state == BNRegisterValueType::ConstantValue) {
53-
if (val.value == 0) {
54-
if (view->IsNeverBranchPatchAvailable(arch, instr.address)) {
55-
view->ConvertToNop(arch, instr.address);
56-
patchCount++;
37+
38+
Ref<BinaryView> viewRef = view;
39+
Ref<Function> funcRef = func;
40+
Ref<Architecture> archRef = arch;
41+
42+
std::thread([viewRef, funcRef, archRef, funcName]() {
43+
Ref<BackgroundTask> task = new BackgroundTask("Patching opaque predicates", true);
44+
task->SetProgressText("Processing " + funcName);
45+
46+
int totalPatches = 0;
47+
int pass = 1;
48+
const int maxPasses = 10;
49+
50+
while (pass <= maxPasses) {
51+
if (task->IsCancelled()) {
52+
LogWarn("Operation cancelled by user");
53+
break;
54+
}
55+
56+
task->SetProgressText("Pass " + std::to_string(pass) + "/" + std::to_string(maxPasses) + " for " + funcName);
57+
58+
auto mlil = funcRef->GetMediumLevelIL();
59+
if (!mlil) {
60+
break;
61+
}
62+
63+
int patchCount = 0;
64+
size_t instructionCount = mlil->GetInstructionCount();
65+
66+
for (size_t i = 0; i < instructionCount; ++i) {
67+
auto instr = mlil->GetInstruction(i);
68+
if (instr.operation != MLIL_IF)
69+
continue;
70+
71+
auto val = mlil->GetExprValue(instr.GetConditionExpr());
72+
if (val.state == BNRegisterValueType::ConstantValue) {
73+
if (val.value == 0) {
74+
if (viewRef->IsNeverBranchPatchAvailable(archRef, instr.address)) {
75+
viewRef->ConvertToNop(archRef, instr.address);
76+
patchCount++;
77+
}
5778
}
58-
} else {
59-
if (view->IsAlwaysBranchPatchAvailable(arch, instr.address)) {
60-
view->AlwaysBranch(arch, instr.address);
61-
patchCount++;
79+
else {
80+
if (viewRef->IsAlwaysBranchPatchAvailable(archRef, instr.address)) {
81+
viewRef->AlwaysBranch(archRef, instr.address);
82+
patchCount++;
83+
}
6284
}
6385
}
6486
}
87+
88+
totalPatches += patchCount;
89+
90+
if (patchCount == 0)
91+
break;
92+
93+
viewRef->UpdateAnalysis();
94+
pass++;
6595
}
66-
67-
totalPatches += patchCount;
68-
69-
if (patchCount == 0)
70-
break;
71-
72-
view->UpdateAnalysis();
73-
pass++;
74-
}
75-
76-
LogInfo("[+] Completed: %d patches applied to %s", totalPatches, funcName.c_str());
96+
97+
task->Finish();
98+
LogInfo("[+] Completed: %d patches applied to %s", totalPatches, funcName.c_str());
99+
}).detach();
77100
});
78101

79102
PluginCommand::Register(
80103
"Native Predicate Solver\\Patch Opaque Predicates (All Functions)",
81104
"Recursively patch opaque predicates in all functions until none remain",
82105
[](BinaryView* view) {
83-
LogInfo("[+] Starting recursive patching for entire binary");
84-
85-
int globalPass = 1;
86-
int totalGlobalPatches = 0;
87-
88-
while (true) {
89-
auto functions = view->GetAnalysisFunctionList();
90-
int globalPatchCount = 0;
91-
size_t funcNum = 0;
92-
93-
for (auto func : functions) {
94-
funcNum++;
95-
96-
auto mlil = func->GetMediumLevelIL();
97-
if (!mlil || mlil->GetInstructionCount() == 0)
98-
continue;
99-
100-
auto arch = func->GetArchitecture();
101-
if (!arch)
102-
continue;
103-
104-
int funcPatches = 0;
105-
int pass = 1;
106-
107-
while (pass <= 10) {
108-
int patchCount = 0;
109-
110-
for (size_t i = 0; i < mlil->GetInstructionCount(); ++i) {
111-
auto instr = mlil->GetInstruction(i);
112-
if (instr.operation != MLIL_IF)
113-
continue;
114-
115-
auto val = mlil->GetExprValue(instr.GetConditionExpr());
116-
if (val.state == BNRegisterValueType::ConstantValue) {
117-
if (val.value == 0) {
118-
if (view->IsNeverBranchPatchAvailable(arch, instr.address)) {
119-
view->ConvertToNop(arch, instr.address);
120-
patchCount++;
106+
Ref<BinaryView> viewRef = view;
107+
108+
std::thread([viewRef]() {
109+
Ref<BackgroundTask> task = new BackgroundTask("Patching all opaque predicates", true);
110+
task->SetProgressText("Starting recursive patching for entire binary");
111+
112+
int globalPass = 1;
113+
int totalGlobalPatches = 0;
114+
115+
while (true) {
116+
if (task->IsCancelled()) {
117+
LogWarn("Operation cancelled by user");
118+
break;
119+
}
120+
121+
auto functions = viewRef->GetAnalysisFunctionList();
122+
int globalPatchCount = 0;
123+
size_t funcNum = 0;
124+
size_t totalFuncs = functions.size();
125+
126+
task->SetProgressText("Global pass " + std::to_string(globalPass) + " - Analyzing " + std::to_string(totalFuncs) + " functions");
127+
128+
for (auto func : functions) {
129+
if (task->IsCancelled()) {
130+
LogWarn("Operation cancelled by user");
131+
break;
132+
}
133+
134+
funcNum++;
135+
136+
if (funcNum % 10 == 0 || funcNum == totalFuncs) {
137+
task->SetProgressText("Pass " + std::to_string(globalPass) + " - Processing function " +
138+
std::to_string(funcNum) + "/" + std::to_string(totalFuncs));
139+
}
140+
141+
auto mlil = func->GetMediumLevelIL();
142+
if (!mlil || mlil->GetInstructionCount() == 0)
143+
continue;
144+
145+
auto arch = func->GetArchitecture();
146+
if (!arch)
147+
continue;
148+
149+
int funcPatches = 0;
150+
int pass = 1;
151+
152+
while (pass <= 10) {
153+
int patchCount = 0;
154+
155+
for (size_t i = 0; i < mlil->GetInstructionCount(); ++i) {
156+
auto instr = mlil->GetInstruction(i);
157+
if (instr.operation != MLIL_IF)
158+
continue;
159+
160+
auto val = mlil->GetExprValue(instr.GetConditionExpr());
161+
if (val.state == BNRegisterValueType::ConstantValue) {
162+
if (val.value == 0) {
163+
if (viewRef->IsNeverBranchPatchAvailable(arch, instr.address)) {
164+
viewRef->ConvertToNop(arch, instr.address);
165+
patchCount++;
166+
}
121167
}
122-
} else {
123-
if (view->IsAlwaysBranchPatchAvailable(arch, instr.address)) {
124-
view->AlwaysBranch(arch, instr.address);
125-
patchCount++;
168+
else {
169+
if (viewRef->IsAlwaysBranchPatchAvailable(arch, instr.address)) {
170+
viewRef->AlwaysBranch(arch, instr.address);
171+
patchCount++;
172+
}
126173
}
127174
}
128175
}
176+
177+
funcPatches += patchCount;
178+
179+
if (patchCount == 0)
180+
break;
181+
182+
viewRef->UpdateAnalysis();
183+
pass++;
184+
}
185+
186+
if (funcPatches > 0) {
187+
globalPatchCount += funcPatches;
129188
}
130-
131-
funcPatches += patchCount;
132-
133-
if (patchCount == 0)
134-
break;
135-
136-
view->UpdateAnalysis();
137-
pass++;
138189
}
139-
140-
if (funcPatches > 0) {
141-
globalPatchCount += funcPatches;
190+
191+
totalGlobalPatches += globalPatchCount;
192+
LogInfo("[+] Pass %d: %d patches applied", globalPass, globalPatchCount);
193+
194+
if (globalPatchCount == 0)
195+
break;
196+
197+
globalPass++;
198+
199+
if (globalPass > 20) {
200+
LogWarn("[!] Maximum passes reached");
201+
break;
142202
}
203+
204+
task->SetProgressText("Updating analysis after pass " + std::to_string(globalPass - 1));
205+
viewRef->UpdateAnalysis();
143206
}
144-
145-
totalGlobalPatches += globalPatchCount;
146-
LogInfo("[+] Pass %d: %d patches applied", globalPass, globalPatchCount);
147-
148-
if (globalPatchCount == 0)
149-
break;
150-
151-
globalPass++;
152-
153-
if (globalPass > 20) {
154-
LogWarn("[!] Maximum passes reached");
155-
break;
156-
}
157-
158-
view->UpdateAnalysis();
159-
}
160-
161-
LogInfo("[+] Completed: %d total patches applied", totalGlobalPatches);
207+
208+
task->Finish();
209+
LogInfo("[+] Completed: %d total patches applied", totalGlobalPatches);
210+
}).detach();
162211
});
163212

164213
return true;

library.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,4 @@
2727
#include "mediumlevelilinstruction.h"
2828
#include <string>
2929
#include <exception>
30-
#include <fstream>
31-
#include <sstream>
3230
#endif //NATIVE_PREDICATE_SOLVER_LIBRARY_H

0 commit comments

Comments
 (0)