1+ #include " library.h"
2+
3+ using namespace BinaryNinja ;
4+
5+ extern " C"
6+ {
7+ BN_DECLARE_CORE_ABI_VERSION
8+
9+ BINARYNINJAPLUGIN bool CorePluginInit ()
10+ {
11+ PluginCommand::Register (
12+ " Native Predicate Solver\\ Patch Opaque Predicates (Current Function)" ,
13+ " Patch opaque predicates in current function" ,
14+ [](BinaryView* view) {
15+ uint64_t addr = view->GetCurrentOffset ();
16+ auto functions = view->GetAnalysisFunctionsContainingAddress (addr);
17+ if (functions.empty ()) {
18+ LogWarn (" No function at current address 0x%llx" , addr);
19+ return ;
20+ }
21+
22+ auto func = functions[0 ];
23+ auto mlil = func->GetMediumLevelIL ();
24+ if (!mlil) {
25+ LogWarn (" No MLIL available for function at 0x%llx" , func->GetStart ());
26+ return ;
27+ }
28+
29+ auto arch = func->GetArchitecture ();
30+ if (!arch) {
31+ LogWarn (" Failed to get architecture for function" );
32+ return ;
33+ }
34+
35+ 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++;
57+ }
58+ } else {
59+ if (view->IsAlwaysBranchPatchAvailable (arch, instr.address )) {
60+ view->AlwaysBranch (arch, instr.address );
61+ patchCount++;
62+ }
63+ }
64+ }
65+ }
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 ());
77+ });
78+
79+ PluginCommand::Register (
80+ " Native Predicate Solver\\ Patch Opaque Predicates (All Functions)" ,
81+ " Recursively patch opaque predicates in all functions until none remain" ,
82+ [](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++;
121+ }
122+ } else {
123+ if (view->IsAlwaysBranchPatchAvailable (arch, instr.address )) {
124+ view->AlwaysBranch (arch, instr.address );
125+ patchCount++;
126+ }
127+ }
128+ }
129+ }
130+
131+ funcPatches += patchCount;
132+
133+ if (patchCount == 0 )
134+ break ;
135+
136+ view->UpdateAnalysis ();
137+ pass++;
138+ }
139+
140+ if (funcPatches > 0 ) {
141+ globalPatchCount += funcPatches;
142+ }
143+ }
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);
162+ });
163+
164+ return true ;
165+ }
166+
167+ BINARYNINJAPLUGIN void CorePluginDependencies ()
168+ {
169+ }
170+ }
0 commit comments