1
1
#include " library.h"
2
+ #include < thread>
2
3
3
4
using namespace BinaryNinja ;
4
5
5
6
extern " C"
6
7
{
7
8
BN_DECLARE_CORE_ABI_VERSION
8
9
9
- BINARYNINJAPLUGIN bool CorePluginInit ()
10
+ BINARYNINJAPLUGIN bool CorePluginInit ()
10
11
{
11
12
PluginCommand::Register (
12
13
" Native Predicate Solver\\ Patch Opaque Predicates (Current Function)" ,
@@ -18,147 +19,195 @@ extern "C"
18
19
LogWarn (" No function at current address 0x%llx" , addr);
19
20
return ;
20
21
}
21
-
22
+
22
23
auto func = functions[0 ];
23
24
auto mlil = func->GetMediumLevelIL ();
24
25
if (!mlil) {
25
26
LogWarn (" No MLIL available for function at 0x%llx" , func->GetStart ());
26
27
return ;
27
28
}
28
-
29
+
29
30
auto arch = func->GetArchitecture ();
30
31
if (!arch) {
31
32
LogWarn (" Failed to get architecture for function" );
32
33
return ;
33
34
}
34
-
35
+
35
36
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
+ }
57
78
}
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
+ }
62
84
}
63
85
}
64
86
}
87
+
88
+ totalPatches += patchCount;
89
+
90
+ if (patchCount == 0 )
91
+ break ;
92
+
93
+ viewRef->UpdateAnalysis ();
94
+ pass++;
65
95
}
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 ();
77
100
});
78
101
79
102
PluginCommand::Register (
80
103
" Native Predicate Solver\\ Patch Opaque Predicates (All Functions)" ,
81
104
" Recursively patch opaque predicates in all functions until none remain" ,
82
105
[](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
+ }
121
167
}
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
+ }
126
173
}
127
174
}
128
175
}
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;
129
188
}
130
-
131
- funcPatches += patchCount;
132
-
133
- if (patchCount == 0 )
134
- break ;
135
-
136
- view->UpdateAnalysis ();
137
- pass++;
138
189
}
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 ;
142
202
}
203
+
204
+ task->SetProgressText (" Updating analysis after pass " + std::to_string (globalPass - 1 ));
205
+ viewRef->UpdateAnalysis ();
143
206
}
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 ();
162
211
});
163
212
164
213
return true ;
0 commit comments