// Copyright (c) 2015-2026 Vector 35 Inc // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. #include "binaryninjaapi.h" using namespace BinaryNinja; using namespace std; Transform::Transform(BNTransform* xform) { m_object = xform; } Transform::Transform(BNTransformType type, const string& name, const string& longName, const string& group) : m_typeForRegister(type), m_capabilitiesForRegister(TransformNoCapabilities), m_nameForRegister(name), m_longNameForRegister(longName), m_groupForRegister(group) { m_object = nullptr; } Transform::Transform(BNTransformType type, BNTransformCapabilities capabilities, const string& name, const string& longName, const string& group) : m_typeForRegister(type), m_capabilitiesForRegister(capabilities), m_nameForRegister(name), m_longNameForRegister(longName), m_groupForRegister(group) { m_object = nullptr; } BNTransformParameterInfo* Transform::GetParametersCallback(void* ctxt, size_t* count) { CallbackRef xform(ctxt); vector params = xform->GetParameters(); *count = params.size(); BNTransformParameterInfo* result = new BNTransformParameterInfo[params.size()]; for (size_t i = 0; i < params.size(); i++) { result[i].name = BNAllocString(params[i].name.c_str()); result[i].longName = BNAllocString(params[i].longName.c_str()); result[i].fixedLength = params[i].fixedLength; } return result; } void Transform::FreeParametersCallback(BNTransformParameterInfo* params, size_t count) { for (size_t i = 0; i < count; i++) { BNFreeString(params[i].name); BNFreeString(params[i].longName); } delete[] params; } bool Transform::DecodeCallback( void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount) { map paramMap; for (size_t i = 0; i < paramCount; i++) paramMap[params[i].name] = DataBuffer(BNDuplicateDataBuffer(params[i].value)); DataBuffer inputBuf(BNDuplicateDataBuffer(input)); DataBuffer outputBuf; CallbackRef xform(ctxt); bool result = xform->Decode(inputBuf, outputBuf, paramMap); BNAssignDataBuffer(output, outputBuf.GetBufferObject()); return result; } bool Transform::EncodeCallback( void* ctxt, BNDataBuffer* input, BNDataBuffer* output, BNTransformParameter* params, size_t paramCount) { map paramMap; for (size_t i = 0; i < paramCount; i++) paramMap[params[i].name] = DataBuffer(BNDuplicateDataBuffer(params[i].value)); DataBuffer inputBuf(BNDuplicateDataBuffer(input)); DataBuffer outputBuf; CallbackRef xform(ctxt); bool result = xform->Encode(inputBuf, outputBuf, paramMap); BNAssignDataBuffer(output, outputBuf.GetBufferObject()); return result; } bool Transform::DecodeWithContextCallback(void* ctxt, BNTransformContext* context, BNTransformParameter* params, size_t paramCount) { map paramMap; for (size_t i = 0; i < paramCount; i++) paramMap[params[i].name] = DataBuffer(BNDuplicateDataBuffer(params[i].value)); CallbackRef xform(ctxt); return xform->DecodeWithContext(new TransformContext(context), paramMap); } bool Transform::CanDecodeCallback(void* ctxt, BNBinaryView* input) { CallbackRef xform(ctxt); return xform->CanDecode(new BinaryView(input)); } vector Transform::EncryptionKeyParameters(size_t fixedKeyLength) { vector params; TransformParameter key; key.name = "key"; key.longName = "Encryption key"; key.fixedLength = fixedKeyLength; params.push_back(key); return params; } vector Transform::EncryptionKeyAndIVParameters(size_t fixedKeyLength, size_t fixedIVLength) { vector params; TransformParameter key, iv; key.name = "key"; key.longName = "Encryption key"; key.fixedLength = fixedKeyLength; iv.name = "iv"; iv.longName = "Initialization vector"; iv.fixedLength = fixedIVLength; params.push_back(key); params.push_back(iv); return params; } void Transform::Register(Transform* xform) { BNCustomTransform callbacks; callbacks.context = xform; callbacks.getParameters = GetParametersCallback; 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, xform->m_nameForRegister.c_str(), xform->m_longNameForRegister.c_str(), xform->m_groupForRegister.c_str(), &callbacks); } Ref Transform::GetByName(const string& name) { BNTransform* result = BNGetTransformByName(name.c_str()); if (!result) return nullptr; return new CoreTransform(result); } vector> Transform::GetTransformTypes() { size_t count; BNTransform** list = BNGetTransformTypeList(&count); vector> result; result.reserve(count); for (size_t i = 0; i < count; i++) result.push_back(new CoreTransform(list[i])); BNFreeTransformTypeList(list); return result; } BNTransformType Transform::GetType() const { return BNGetTransformType(m_object); } BNTransformCapabilities Transform::GetCapabilities() const { return static_cast(BNGetTransformCapabilities(m_object)); } bool Transform::SupportsDetection() const { return BNTransformSupportsDetection(m_object); } bool Transform::SupportsContext() const { return BNTransformSupportsContext(m_object); } string Transform::GetName() const { char* name = BNGetTransformName(m_object); string result = name; BNFreeString(name); return result; } string Transform::GetLongName() const { char* name = BNGetTransformLongName(m_object); string result = name; BNFreeString(name); return result; } string Transform::GetGroup() const { char* name = BNGetTransformGroup(m_object); string result = name; BNFreeString(name); return result; } vector Transform::GetParameters() const { return vector(); } bool Transform::Decode(const DataBuffer& input, DataBuffer& output, const map& params) { if (GetType() == InvertingTransform) return Encode(input, output, params); return false; } bool Transform::Encode(const DataBuffer&, DataBuffer&, const map&) { return false; } bool Transform::DecodeWithContext(Ref, const map&) { return false; } bool Transform::CanDecode(Ref input) const { return false; } CoreTransform::CoreTransform(BNTransform* xform) : Transform(xform) {} vector CoreTransform::GetParameters() const { size_t count; BNTransformParameterInfo* list = BNGetTransformParameterList(m_object, &count); vector result; result.reserve(count); for (size_t i = 0; i < count; i++) { TransformParameter param; param.name = list[i].name; param.longName = list[i].longName; param.fixedLength = list[i].fixedLength; result.push_back(param); } BNFreeTransformParameterList(list, count); return result; } bool CoreTransform::Decode(const DataBuffer& input, DataBuffer& output, const map& 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 = BNDecode(m_object, input.GetBufferObject(), output.GetBufferObject(), list, idx); delete[] list; return result; } bool CoreTransform::Encode(const DataBuffer& input, DataBuffer& output, const map& 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 = BNEncode(m_object, input.GetBufferObject(), output.GetBufferObject(), list, idx); delete[] list; return result; } bool CoreTransform::DecodeWithContext(Ref context, const map& 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 input) const { return BNCanDecode(m_object, input->GetObject()); }