diff options
| -rw-r--r-- | binaryninjaapi.h | 7 | ||||
| -rw-r--r-- | binaryninjacore.h | 10 | ||||
| -rw-r--r-- | python/transform.py | 36 | ||||
| -rw-r--r-- | transform.cpp | 42 |
4 files changed, 92 insertions, 3 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 9da9f677..bd4f6de5 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -8928,6 +8928,8 @@ namespace BinaryNinja { size_t fixedLength; // Variable length if zero }; + class TransformContext; + /*! Allows users to implement custom transformations. New transformations may be added at runtime, so an instance of a transform is created like @@ -8970,6 +8972,7 @@ namespace BinaryNinja { void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); static bool EncodeCallback( void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); + static bool DecodeWithContextCallback(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount); static bool CanDecodeCallback(void* ctxt, BNBinaryView* input); static std::vector<TransformParameter> EncryptionKeyParameters(size_t fixedKeyLength = 0); @@ -8987,6 +8990,7 @@ namespace BinaryNinja { BNTransformType GetType() const; BNTransformCapabilities GetCapabilities() const; bool SupportsDetection() const; + bool SupportsContext() const; std::string GetName() const; std::string GetLongName() const; std::string GetGroup() const; @@ -8995,6 +8999,7 @@ namespace BinaryNinja { virtual bool Decode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()); virtual bool Encode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()); + virtual bool DecodeWithContext(Ref<TransformContext> context, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()); virtual bool CanDecode(Ref<BinaryView> input) const; }; @@ -9011,6 +9016,8 @@ namespace BinaryNinja { const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override; virtual bool Encode(const DataBuffer& input, DataBuffer& output, const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override; + virtual bool DecodeWithContext(Ref<TransformContext> context, + const std::map<std::string, DataBuffer>& params = std::map<std::string, DataBuffer>()) override; virtual bool CanDecode(Ref<BinaryView> input) const override; }; diff --git a/binaryninjacore.h b/binaryninjacore.h index 6299618d..67b17bc4 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -37,14 +37,14 @@ // Current ABI version for linking to the core. This is incremented any time // there are changes to the API that affect linking, including new functions, // new types, or modifications to existing functions or types. -#define BN_CURRENT_CORE_ABI_VERSION 133 +#define BN_CURRENT_CORE_ABI_VERSION 134 // Minimum ABI version that is supported for loading of plugins. Plugins that // are linked to an ABI version less than this will not be able to load and // will require rebuilding. The minimum version is increased when there are // incompatible changes that break binary compatibility, such as changes to // existing types or functions. -#define BN_MINIMUM_CORE_ABI_VERSION 133 +#define BN_MINIMUM_CORE_ABI_VERSION 134 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -353,7 +353,8 @@ extern "C" typedef enum BNTransformCapabilities { TransformNoCapabilities = 0, - TransformSupportsDetection = 1 + TransformSupportsDetection = 1, + TransformSupportsContext = 2 } BNTransformCapabilities; typedef enum BNTransformSessionMode @@ -1770,6 +1771,7 @@ extern "C" void (*freeParameters)(BNTransformParameterInfo* params, size_t count); bool (*decode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); bool (*encode)(void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); + bool (*decodeWithContext)(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount); bool (*canDecode)(void* ctxt, BNBinaryView* input); } BNCustomTransform; @@ -4634,6 +4636,7 @@ extern "C" BINARYNINJACOREAPI BNTransformType BNGetTransformType(BNTransform* xform); BINARYNINJACOREAPI uint32_t BNGetTransformCapabilities(BNTransform* xform); BINARYNINJACOREAPI bool BNTransformSupportsDetection(BNTransform* xform); + BINARYNINJACOREAPI bool BNTransformSupportsContext(BNTransform* xform); BINARYNINJACOREAPI char* BNGetTransformName(BNTransform* xform); BINARYNINJACOREAPI char* BNGetTransformLongName(BNTransform* xform); BINARYNINJACOREAPI char* BNGetTransformGroup(BNTransform* xform); @@ -4643,6 +4646,7 @@ extern "C" BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); BINARYNINJACOREAPI bool BNEncode( BNTransform* xform, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount); + BINARYNINJACOREAPI bool BNDecodeWithContext(BNTransform* xform, BNTransformContext* context, BNTransformParameter* params, size_t paramCount); BINARYNINJACOREAPI bool BNCanDecode(BNTransform* xform, BNBinaryView* input); // Transform Context diff --git a/python/transform.py b/python/transform.py index 3ef5c4b6..3168982d 100644 --- a/python/transform.py +++ b/python/transform.py @@ -116,6 +116,7 @@ class Transform(metaclass=_TransformMetaClass): self._cb.freeParameters = self._cb.freeParameters.__class__(self._free_parameters) self._cb.decode = self._cb.decode.__class__(self._decode) self._cb.encode = self._cb.encode.__class__(self._encode) + self._cb.decodeWithContext = self._cb.decodeWithContext.__class__(self._decode_with_context) self._cb.canDecode = self._cb.canDecode.__class__(self._can_decode) self._pending_param_lists = {} self.type = self.__class__.transform_type @@ -131,6 +132,7 @@ class Transform(metaclass=_TransformMetaClass): self.type = TransformType(core.BNGetTransformType(self.handle)) self.capabilities = core.BNGetTransformCapabilities(self.handle) self.supports_detection = core.BNTransformSupportsDetection(self.handle) + self.supports_context = core.BNTransformSupportsContext(self.handle) self.name = core.BNGetTransformName(self.handle) self.long_name = core.BNGetTransformLongName(self.handle) self.group = core.BNGetTransformGroup(self.handle) @@ -232,6 +234,21 @@ class Transform(metaclass=_TransformMetaClass): log_error_for_exception("Unhandled Python exception in Transform._encode") return False + def _decode_with_context(self, ctxt, context, params, count): + try: + # TODO: Make Python TransformSession and TransformContext objects + from . import transform_context + context_obj = transform_context.TransformContext(core.BNNewTransformContextReference(context)) + param_map = {} + for i in range(0, count): + data = databuffer.DataBuffer(handle=core.BNDuplicateDataBuffer(params[i].value)) + param_map[params[i].name] = bytes(data) + result = self.perform_decode_with_context(context_obj, param_map) + return result if result is not None else False + except: + log_error_for_exception("Unhandled Python exception in Transform._decode_with_context") + return False + def _can_decode(self, ctxt, input): try: input_obj = binaryview.BinaryView(handle=core.BNNewViewReference(input)) @@ -250,6 +267,9 @@ class Transform(metaclass=_TransformMetaClass): def perform_encode(self, data, params): return None + def perform_decode_with_context(self, context, params): + return False + def decode(self, input_buf, params={}): if isinstance(input_buf, int) or isinstance(input_buf, int): return None @@ -282,6 +302,22 @@ class Transform(metaclass=_TransformMetaClass): return None return bytes(output_buf) + def decode_with_context(self, context, params={}): + # TODO: Make Python TransformSession and TransformContext objects + from . import transform_context + if not isinstance(context, transform_context.TransformContext): + return None + keys = list(params.keys()) + param_buf = (core.BNTransformParameter * len(keys))() + data = [] + for i in range(0, len(keys)): + data.append(databuffer.DataBuffer(params[keys[i]])) + param_buf[i].name = keys[i] + param_buf[i].value = data[i].handle + if not core.BNDecodeWithContext(self.handle, context.handle, param_buf, len(keys)): + return False + return True + def can_decode(self, input): """ ``can_decode`` checks if this transform can decode the given input. diff --git a/transform.cpp b/transform.cpp index 468cc0f2..735fb1b9 100644 --- a/transform.cpp +++ b/transform.cpp @@ -107,6 +107,18 @@ bool Transform::EncodeCallback( } +bool Transform::DecodeWithContextCallback(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount) +{ + map<string, DataBuffer> paramMap; + for (size_t i = 0; i < paramCount; i++) + paramMap[params[i].name] = DataBuffer(BNDuplicateDataBuffer(params[i].value)); + + CallbackRef<Transform> xform(ctxt); + Ref<TransformContext> contextRef = new TransformContext(BNNewTransformContextReference(context)); + return xform->DecodeWithContext(contextRef, paramMap); +} + + bool Transform::CanDecodeCallback(void* ctxt, BNBinaryView* input) { CallbackRef<Transform> xform(ctxt); @@ -150,6 +162,7 @@ void Transform::Register(Transform* xform) callbacks.freeParameters = FreeParametersCallback; callbacks.decode = DecodeCallback; callbacks.encode = EncodeCallback; + callbacks.decodeWithContext = DecodeWithContextCallback; callbacks.canDecode = CanDecodeCallback; xform->AddRefForRegistration(); xform->m_object = BNRegisterTransformTypeWithCapabilities(xform->m_typeForRegister, xform->m_capabilitiesForRegister, @@ -199,6 +212,12 @@ bool Transform::SupportsDetection() const } +bool Transform::SupportsContext() const +{ + return BNTransformSupportsContext(m_object); +} + + string Transform::GetName() const { char* name = BNGetTransformName(m_object); @@ -246,6 +265,12 @@ bool Transform::Encode(const DataBuffer&, DataBuffer&, const map<string, DataBuf } +bool Transform::DecodeWithContext(Ref<TransformContext>, const map<string, DataBuffer>&) +{ + return false; +} + + bool Transform::CanDecode(Ref<BinaryView> input) const { return false; @@ -310,6 +335,23 @@ bool CoreTransform::Encode(const DataBuffer& input, DataBuffer& output, const ma } +bool CoreTransform::DecodeWithContext(Ref<TransformContext> context, const map<string, DataBuffer>& params) +{ + BNTransformParameter* list = new BNTransformParameter[params.size()]; + size_t idx = 0; + for (auto& i : params) + { + list[idx].name = i.first.c_str(); + list[idx++].value = i.second.GetBufferObject(); + } + + bool result = BNDecodeWithContext(m_object, context->GetObject(), list, idx); + + delete[] list; + return result; +} + + bool CoreTransform::CanDecode(Ref<BinaryView> input) const { return BNCanDecode(m_object, input->GetObject()); |
