Skip to content

Commit 6e0806b

Browse files
committed
Add DecodeWithContext method to Transform API layers.
1 parent 416332c commit 6e0806b

File tree

4 files changed

+92
-3
lines changed

4 files changed

+92
-3
lines changed

binaryninjaapi.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8928,6 +8928,8 @@ namespace BinaryNinja {
89288928
size_t fixedLength; // Variable length if zero
89298929
};
89308930

8931+
class TransformContext;
8932+
89318933
/*! Allows users to implement custom transformations.
89328934

89338935
New transformations may be added at runtime, so an instance of a transform is created like
@@ -8970,6 +8972,7 @@ namespace BinaryNinja {
89708972
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
89718973
static bool EncodeCallback(
89728974
void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
8975+
static bool DecodeWithContextCallback(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount);
89738976
static bool CanDecodeCallback(void* ctxt, BNBinaryView* input);
89748977

89758978
static std::vector<TransformParameter> EncryptionKeyParameters(size_t fixedKeyLength = 0);
@@ -8987,6 +8990,7 @@ namespace BinaryNinja {
89878990
BNTransformType GetType() const;
89888991
BNTransformCapabilities GetCapabilities() const;
89898992
bool SupportsDetection() const;
8993+
bool SupportsContext() const;
89908994
std::string GetName() const;
89918995
std::string GetLongName() const;
89928996
std::string GetGroup() const;
@@ -8995,6 +8999,7 @@ namespace BinaryNinja {
89958999

89969000
virtual bool Decode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
89979001
virtual bool Encode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
9002+
virtual bool DecodeWithContext(Ref<TransformContext> context, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>());
89989003
virtual bool CanDecode(Ref<BinaryView> input) const;
89999004
};
90009005

@@ -9011,6 +9016,8 @@ namespace BinaryNinja {
90119016
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override;
90129017
virtual bool Encode(const DataBuffer& input, DataBuffer& output,
90139018
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override;
9019+
virtual bool DecodeWithContext(Ref<TransformContext> context,
9020+
const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override;
90149021
virtual bool CanDecode(Ref<BinaryView> input) const override;
90159022
};
90169023

binaryninjacore.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,14 @@
3737
// Current ABI version for linking to the core. This is incremented any time
3838
// there are changes to the API that affect linking, including new functions,
3939
// new types, or modifications to existing functions or types.
40-
#define BN_CURRENT_CORE_ABI_VERSION 133
40+
#define BN_CURRENT_CORE_ABI_VERSION 134
4141

4242
// Minimum ABI version that is supported for loading of plugins. Plugins that
4343
// are linked to an ABI version less than this will not be able to load and
4444
// will require rebuilding. The minimum version is increased when there are
4545
// incompatible changes that break binary compatibility, such as changes to
4646
// existing types or functions.
47-
#define BN_MINIMUM_CORE_ABI_VERSION 133
47+
#define BN_MINIMUM_CORE_ABI_VERSION 134
4848

4949
#ifdef __GNUC__
5050
#ifdef BINARYNINJACORE_LIBRARY
@@ -353,7 +353,8 @@ extern "C"
353353
typedef enum BNTransformCapabilities
354354
{
355355
TransformNoCapabilities = 0,
356-
TransformSupportsDetection = 1
356+
TransformSupportsDetection = 1,
357+
TransformSupportsContext = 2
357358
} BNTransformCapabilities;
358359

359360
typedef enum BNTransformSessionMode
@@ -1770,6 +1771,7 @@ extern "C"
17701771
void (*freeParameters)(BNTransformParameterInfo* params, size_t count);
17711772
bool (*decode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
17721773
bool (*encode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
1774+
bool (*decodeWithContext)(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount);
17731775
bool (*canDecode)(void* ctxt, BNBinaryView* input);
17741776
} BNCustomTransform;
17751777

@@ -4634,6 +4636,7 @@ extern "C"
46344636
BINARYNINJACOREAPI BNTransformType BNGetTransformType(BNTransform* xform);
46354637
BINARYNINJACOREAPI uint32_t BNGetTransformCapabilities(BNTransform* xform);
46364638
BINARYNINJACOREAPI bool BNTransformSupportsDetection(BNTransform* xform);
4639+
BINARYNINJACOREAPI bool BNTransformSupportsContext(BNTransform* xform);
46374640
BINARYNINJACOREAPI char* BNGetTransformName(BNTransform* xform);
46384641
BINARYNINJACOREAPI char* BNGetTransformLongName(BNTransform* xform);
46394642
BINARYNINJACOREAPI char* BNGetTransformGroup(BNTransform* xform);
@@ -4643,6 +4646,7 @@ extern "C"
46434646
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
46444647
BINARYNINJACOREAPI bool BNEncode(
46454648
BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount);
4649+
BINARYNINJACOREAPI bool BNDecodeWithContext(BNTransform* xform, BNTransformContext* context, BNTransformParameter* params, size_t paramCount);
46464650
BINARYNINJACOREAPI bool BNCanDecode(BNTransform* xform, BNBinaryView* input);
46474651

46484652
// Transform Context

python/transform.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ def __init__(self, handle):
116116
self._cb.freeParameters = self._cb.freeParameters.__class__(self._free_parameters)
117117
self._cb.decode = self._cb.decode.__class__(self._decode)
118118
self._cb.encode = self._cb.encode.__class__(self._encode)
119+
self._cb.decodeWithContext = self._cb.decodeWithContext.__class__(self._decode_with_context)
119120
self._cb.canDecode = self._cb.canDecode.__class__(self._can_decode)
120121
self._pending_param_lists = {}
121122
self.type = self.__class__.transform_type
@@ -131,6 +132,7 @@ def __init__(self, handle):
131132
self.type = TransformType(core.BNGetTransformType(self.handle))
132133
self.capabilities = core.BNGetTransformCapabilities(self.handle)
133134
self.supports_detection = core.BNTransformSupportsDetection(self.handle)
135+
self.supports_context = core.BNTransformSupportsContext(self.handle)
134136
self.name = core.BNGetTransformName(self.handle)
135137
self.long_name = core.BNGetTransformLongName(self.handle)
136138
self.group = core.BNGetTransformGroup(self.handle)
@@ -232,6 +234,21 @@ def _encode(self, ctxt, input_buf, output_buf, params, count):
232234
log_error_for_exception("Unhandled Python exception in Transform._encode")
233235
return False
234236

237+
def _decode_with_context(self, ctxt, context, params, count):
238+
try:
239+
# TODO: Make Python TransformSession and TransformContext objects
240+
from . import transform_context
241+
context_obj = transform_context.TransformContext(core.BNNewTransformContextReference(context))
242+
param_map = {}
243+
for i in range(0, count):
244+
data = databuffer.DataBuffer(handle=core.BNDuplicateDataBuffer(params[i].value))
245+
param_map[params[i].name] = bytes(data)
246+
result = self.perform_decode_with_context(context_obj, param_map)
247+
return result if result is not None else False
248+
except:
249+
log_error_for_exception("Unhandled Python exception in Transform._decode_with_context")
250+
return False
251+
235252
def _can_decode(self, ctxt, input):
236253
try:
237254
input_obj = binaryview.BinaryView(handle=core.BNNewViewReference(input))
@@ -250,6 +267,9 @@ def perform_decode(self, data, params):
250267
def perform_encode(self, data, params):
251268
return None
252269

270+
def perform_decode_with_context(self, context, params):
271+
return False
272+
253273
def decode(self, input_buf, params={}):
254274
if isinstance(input_buf, int) or isinstance(input_buf, int):
255275
return None
@@ -282,6 +302,22 @@ def encode(self, input_buf, params={}):
282302
return None
283303
return bytes(output_buf)
284304

305+
def decode_with_context(self, context, params={}):
306+
# TODO: Make Python TransformSession and TransformContext objects
307+
from . import transform_context
308+
if not isinstance(context, transform_context.TransformContext):
309+
return None
310+
keys = list(params.keys())
311+
param_buf = (core.BNTransformParameter * len(keys))()
312+
data = []
313+
for i in range(0, len(keys)):
314+
data.append(databuffer.DataBuffer(params[keys[i]]))
315+
param_buf[i].name = keys[i]
316+
param_buf[i].value = data[i].handle
317+
if not core.BNDecodeWithContext(self.handle, context.handle, param_buf, len(keys)):
318+
return False
319+
return True
320+
285321
def can_decode(self, input):
286322
"""
287323
``can_decode`` checks if this transform can decode the given input.

transform.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,18 @@ bool Transform::EncodeCallback(
107107
}
108108

109109

110+
bool Transform::DecodeWithContextCallback(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount)
111+
{
112+
map<string, DataBuffer> paramMap;
113+
for (size_t i = 0; i < paramCount; i++)
114+
paramMap[params[i].name] = DataBuffer(BNDuplicateDataBuffer(params[i].value));
115+
116+
CallbackRef<Transform> xform(ctxt);
117+
Ref<TransformContext> contextRef = new TransformContext(BNNewTransformContextReference(context));
118+
return xform->DecodeWithContext(contextRef, paramMap);
119+
}
120+
121+
110122
bool Transform::CanDecodeCallback(void* ctxt, BNBinaryView* input)
111123
{
112124
CallbackRef<Transform> xform(ctxt);
@@ -150,6 +162,7 @@ void Transform::Register(Transform* xform)
150162
callbacks.freeParameters = FreeParametersCallback;
151163
callbacks.decode = DecodeCallback;
152164
callbacks.encode = EncodeCallback;
165+
callbacks.decodeWithContext = DecodeWithContextCallback;
153166
callbacks.canDecode = CanDecodeCallback;
154167
xform->AddRefForRegistration();
155168
xform->m_object = BNRegisterTransformTypeWithCapabilities(xform->m_typeForRegister, xform->m_capabilitiesForRegister,
@@ -199,6 +212,12 @@ bool Transform::SupportsDetection() const
199212
}
200213

201214

215+
bool Transform::SupportsContext() const
216+
{
217+
return BNTransformSupportsContext(m_object);
218+
}
219+
220+
202221
string Transform::GetName() const
203222
{
204223
char* name = BNGetTransformName(m_object);
@@ -246,6 +265,12 @@ bool Transform::Encode(const DataBuffer&, DataBuffer&, const map<string, DataBuf
246265
}
247266

248267

268+
bool Transform::DecodeWithContext(Ref<TransformContext>, const map<string, DataBuffer>&)
269+
{
270+
return false;
271+
}
272+
273+
249274
bool Transform::CanDecode(Ref<BinaryView> input) const
250275
{
251276
return false;
@@ -310,6 +335,23 @@ bool CoreTransform::Encode(const DataBuffer& input, DataBuffer& output, const ma
310335
}
311336

312337

338+
bool CoreTransform::DecodeWithContext(Ref<TransformContext> context, const map<string, DataBuffer>& params)
339+
{
340+
BNTransformParameter* list = new BNTransformParameter[params.size()];
341+
size_t idx = 0;
342+
for (auto& i : params)
343+
{
344+
list[idx].name = i.first.c_str();
345+
list[idx++].value = i.second.GetBufferObject();
346+
}
347+
348+
bool result = BNDecodeWithContext(m_object, context->GetObject(), list, idx);
349+
350+
delete[] list;
351+
return result;
352+
}
353+
354+
313355
bool CoreTransform::CanDecode(Ref<BinaryView> input) const
314356
{
315357
return BNCanDecode(m_object, input->GetObject());

0 commit comments

Comments
 (0)