Skip to content

Commit 1360242

Browse files
committed
Initial Files
0 parents  commit 1360242

File tree

9 files changed

+304
-0
lines changed

9 files changed

+304
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
build
2+
/.vs
3+
binaryninjaapi
4+
.claude

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "binaryninjaapi"]
2+
path = binaryninjaapi
3+
url = https://github.com/Vector35/binaryninja-api

CMakeLists.txt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# MIT License
2+
#
3+
# Copyright (c) 2015-2024 Vector 35 Inc
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in all
13+
# copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
# SOFTWARE.
22+
23+
cmake_minimum_required(VERSION 3.24)
24+
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
25+
project(NativePredicateSolver CXX)
26+
27+
set(CMAKE_CXX_STANDARD 17)
28+
29+
set(HEADLESS 1)
30+
find_path(
31+
BN_API_PATH
32+
NAMES binaryninjaapi.h mediumlevelilinstruction.h
33+
# List of paths to search for the clone of the api
34+
HINTS ../.. binaryninjaapi $ENV{BN_API_PATH}
35+
REQUIRED
36+
)
37+
add_subdirectory(${BN_API_PATH} api)
38+
39+
add_library(${PROJECT_NAME} SHARED library.cpp)
40+
41+
target_link_libraries(${PROJECT_NAME} PUBLIC binaryninjaapi)
42+
43+
bn_install_plugin(${PROJECT_NAME})

CMakeSettings.json

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"configurations": [
3+
{
4+
"name": "x64-Debug",
5+
"generator": "Ninja",
6+
"configurationType": "Debug",
7+
"inheritEnvironments": [ "msvc_x64_x64" ],
8+
"buildRoot": "${projectDir}\\out\\build\\${name}",
9+
"installRoot": "${projectDir}\\out\\install\\${name}",
10+
"cmakeCommandArgs": "",
11+
"buildCommandArgs": "",
12+
"ctestCommandArgs": ""
13+
},
14+
{
15+
"name": "x64-Release",
16+
"generator": "Ninja",
17+
"configurationType": "Release",
18+
"buildRoot": "${projectDir}\\out\\build\\${name}",
19+
"installRoot": "${projectDir}\\out\\install\\${name}",
20+
"cmakeCommandArgs": "",
21+
"buildCommandArgs": "",
22+
"ctestCommandArgs": "",
23+
"inheritEnvironments": [ "msvc_x64_x64" ],
24+
"variables": []
25+
}
26+
]
27+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 Script-Ware Software
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# native-predicate-solver
2+
3+
Native opaque predicate cleaner plugin for Binary Ninja

binaryninjaapi

Submodule binaryninjaapi added at 67ae186

library.cpp

Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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+
}

library.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// MIT License
2+
//
3+
// Copyright (c) 2015-2024 Vector 35 Inc
4+
//
5+
// Permission is hereby granted, free of charge, to any person obtaining a copy
6+
// of this software and associated documentation files (the "Software"), to deal
7+
// in the Software without restriction, including without limitation the rights
8+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
// copies of the Software, and to permit persons to whom the Software is
10+
// furnished to do so, subject to the following conditions:
11+
//
12+
// The above copyright notice and this permission notice shall be included in all
13+
// copies or substantial portions of the Software.
14+
//
15+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
// SOFTWARE.
22+
23+
#ifndef NATIVE_PREDICATE_SOLVER_LIBRARY_H
24+
#define NATIVE_PREDICATE_SOLVER_LIBRARY_H
25+
26+
#include "binaryninjaapi.h"
27+
#include "mediumlevelilinstruction.h"
28+
#include <string>
29+
#include <exception>
30+
#include <fstream>
31+
#include <sstream>
32+
#endif //NATIVE_PREDICATE_SOLVER_LIBRARY_H

0 commit comments

Comments
 (0)