11#include " library.h"
2+ #include < thread>
23
34using namespace BinaryNinja ;
45
56extern " 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 ;
0 commit comments