#include "binaryninjaapi.h" using namespace BinaryNinja; using namespace std; void BinaryDataNotification::DataWrittenCallback(void* ctxt, BNBinaryView* object, uint64_t offset, size_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); notify->OnBinaryDataWritten(view, offset, len); } void BinaryDataNotification::DataInsertedCallback(void* ctxt, BNBinaryView* object, uint64_t offset, size_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); notify->OnBinaryDataInserted(view, offset, len); } void BinaryDataNotification::DataRemovedCallback(void* ctxt, BNBinaryView* object, uint64_t offset, uint64_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); notify->OnBinaryDataRemoved(view, offset, len); } void BinaryDataNotification::FunctionAddedCallback(void* ctxt, BNBinaryView* object, BNFunction* func) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); Ref funcObj = new Function(BNNewFunctionReference(func)); notify->OnAnalysisFunctionAdded(view, funcObj); } void BinaryDataNotification::FunctionRemovedCallback(void* ctxt, BNBinaryView* object, BNFunction* func) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); Ref funcObj = new Function(BNNewFunctionReference(func)); notify->OnAnalysisFunctionRemoved(view, funcObj); } void BinaryDataNotification::FunctionUpdatedCallback(void* ctxt, BNBinaryView* object, BNFunction* func) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); Ref funcObj = new Function(BNNewFunctionReference(func)); notify->OnAnalysisFunctionUpdated(view, funcObj); } void BinaryDataNotification::StringFoundCallback(void* ctxt, BNBinaryView* object, BNStringType type, uint64_t offset, size_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); notify->OnStringFound(view, type, offset, len); } void BinaryDataNotification::StringRemovedCallback(void* ctxt, BNBinaryView* object, BNStringType type, uint64_t offset, size_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; Ref view = new BinaryView(BNNewViewReference(object)); notify->OnStringRemoved(view, type, offset, len); } BinaryDataNotification::BinaryDataNotification() { m_callbacks.context = this; m_callbacks.dataWritten = DataWrittenCallback; m_callbacks.dataInserted = DataInsertedCallback; m_callbacks.dataRemoved = DataRemovedCallback; m_callbacks.functionAdded = FunctionAddedCallback; m_callbacks.functionRemoved = FunctionRemovedCallback; m_callbacks.functionUpdated = FunctionUpdatedCallback; m_callbacks.stringFound = StringFoundCallback; m_callbacks.stringRemoved = StringRemovedCallback; } Symbol::Symbol(BNSymbolType type, const string& shortName, const string& fullName, const string& rawName, uint64_t addr) { m_sym = BNCreateSymbol(type, shortName.c_str(), fullName.c_str(), rawName.c_str(), addr); } Symbol::Symbol(BNSymbolType type, const std::string& name, uint64_t addr) { m_sym = BNCreateSymbol(type, name.c_str(), name.c_str(), name.c_str(), addr); } Symbol::Symbol(BNSymbol* sym) { m_sym = sym; } Symbol::~Symbol() { BNFreeSymbol(m_sym); } BNSymbolType Symbol::GetType() const { return BNGetSymbolType(m_sym); } string Symbol::GetShortName() const { char* name = BNGetSymbolShortName(m_sym); string result = name; BNFreeString(name); return result; } string Symbol::GetFullName() const { char* name = BNGetSymbolFullName(m_sym); string result = name; BNFreeString(name); return result; } string Symbol::GetRawName() const { char* name = BNGetSymbolRawName(m_sym); string result = name; BNFreeString(name); return result; } uint64_t Symbol::GetAddress() const { return BNGetSymbolAddress(m_sym); } bool Symbol::IsAutoDefined() const { return BNIsSymbolAutoDefined(m_sym); } void Symbol::SetAutoDefined(bool val) { BNSetSymbolAutoDefined(m_sym, val); } Ref Symbol::ImportedFunctionFromImportAddressSymbol(Symbol* sym, uint64_t addr) { return new Symbol(BNImportedFunctionFromImportAddressSymbol(sym->GetSymbolObject(), addr)); } BinaryView::BinaryView(const std::string& typeName, FileMetadata* file) { BNCustomBinaryView view; view.context = this; view.init = InitCallback; view.read = ReadCallback; view.write = WriteCallback; view.insert = InsertCallback; view.remove = RemoveCallback; view.getModification = GetModificationCallback; view.isValidOffset = IsValidOffsetCallback; view.isOffsetReadable = IsOffsetReadableCallback; view.isOffsetWritable = IsOffsetWritableCallback; view.isOffsetExecutable = IsOffsetExecutableCallback; view.getNextValidOffset = GetNextValidOffsetCallback; view.getStart = GetStartCallback; view.getLength = GetLengthCallback; view.getEntryPoint = GetEntryPointCallback; view.isExecutable = IsExecutableCallback; view.getDefaultEndianness = GetDefaultEndiannessCallback; view.getAddressSize = GetAddressSizeCallback; view.save = SaveCallback; m_file = file; m_view = BNCreateCustomBinaryView(typeName.c_str(), m_file->GetFileObject(), &view); } BinaryView::BinaryView(BNBinaryView* view) { m_view = view; m_file = new FileMetadata(BNNewFileReference(BNGetFileForView(m_view))); } BinaryView::~BinaryView() { BNFreeBinaryView(m_view); } bool BinaryView::InitCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->Init(); } size_t BinaryView::ReadCallback(void* ctxt, void* dest, uint64_t offset, size_t len) { BinaryView* view = (BinaryView*)ctxt; return view->PerformRead(dest, offset, len); } size_t BinaryView::WriteCallback(void* ctxt, uint64_t offset, const void* src, size_t len) { BinaryView* view = (BinaryView*)ctxt; return view->PerformWrite(offset, src, len); } size_t BinaryView::InsertCallback(void* ctxt, uint64_t offset, const void* src, size_t len) { BinaryView* view = (BinaryView*)ctxt; return view->PerformInsert(offset, src, len); } size_t BinaryView::RemoveCallback(void* ctxt, uint64_t offset, uint64_t len) { BinaryView* view = (BinaryView*)ctxt; return view->PerformRemove(offset, len); } BNModificationStatus BinaryView::GetModificationCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformGetModification(offset); } bool BinaryView::IsValidOffsetCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformIsValidOffset(offset); } bool BinaryView::IsOffsetReadableCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformIsOffsetReadable(offset); } bool BinaryView::IsOffsetWritableCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformIsOffsetWritable(offset); } bool BinaryView::IsOffsetExecutableCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformIsOffsetExecutable(offset); } uint64_t BinaryView::GetNextValidOffsetCallback(void* ctxt, uint64_t offset) { BinaryView* view = (BinaryView*)ctxt; return view->PerformGetNextValidOffset(offset); } uint64_t BinaryView::GetStartCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->PerformGetStart(); } uint64_t BinaryView::GetLengthCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->PerformGetLength(); } uint64_t BinaryView::GetEntryPointCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->PerformGetEntryPoint(); } bool BinaryView::IsExecutableCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->PerformIsExecutable(); } BNEndianness BinaryView::GetDefaultEndiannessCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->GetDefaultEndianness(); } size_t BinaryView::GetAddressSizeCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; return view->GetAddressSize(); } bool BinaryView::SaveCallback(void* ctxt, BNFileAccessor* file) { BinaryView* view = (BinaryView*)ctxt; CoreFileAccessor accessor(file); return view->PerformSave(&accessor); } bool BinaryView::PerformIsValidOffset(uint64_t offset) { uint8_t val; return PerformRead(&val, offset, 1) == 1; } bool BinaryView::PerformIsOffsetReadable(uint64_t offset) { return PerformIsValidOffset(offset); } bool BinaryView::PerformIsOffsetWritable(uint64_t offset) { return PerformIsValidOffset(offset); } bool BinaryView::PerformIsOffsetExecutable(uint64_t offset) { return PerformIsValidOffset(offset); } uint64_t BinaryView::PerformGetNextValidOffset(uint64_t offset) { if (offset < PerformGetStart()) return PerformGetStart(); return offset; } BNEndianness BinaryView::PerformGetDefaultEndianness() const { Ref arch = GetDefaultArchitecture(); if (arch) return arch->GetEndianness(); return LittleEndian; } size_t BinaryView::PerformGetAddressSize() const { Ref arch = GetDefaultArchitecture(); if (arch) return arch->GetAddressSize(); if (GetEnd() > (1LL << 32)) return 8; return 4; } void BinaryView::NotifyDataWritten(uint64_t offset, size_t len) { BNNotifyDataWritten(m_view, offset, len); } void BinaryView::NotifyDataInserted(uint64_t offset, size_t len) { BNNotifyDataInserted(m_view, offset, len); } void BinaryView::NotifyDataRemoved(uint64_t offset, uint64_t len) { BNNotifyDataRemoved(m_view, offset, len); } string BinaryView::GetTypeName() const { char* str = BNGetViewType(m_view); string result = str; BNFreeString(str); return result; } bool BinaryView::IsModified() const { return BNIsViewModified(m_view); } bool BinaryView::IsAnalysisChanged() const { return m_file->IsAnalysisChanged(); } bool BinaryView::IsBackedByDatabase() const { return m_file->IsBackedByDatabase(); } bool BinaryView::CreateDatabase(const string& path) { return m_file->CreateDatabase(path, this); } bool BinaryView::SaveAutoSnapshot() { return m_file->SaveAutoSnapshot(this); } void BinaryView::BeginUndoActions() { m_file->BeginUndoActions(); } void BinaryView::AddUndoAction(UndoAction* action) { action->Add(m_view); } void BinaryView::CommitUndoActions() { m_file->CommitUndoActions(); } bool BinaryView::Undo() { return m_file->Undo(); } bool BinaryView::Redo() { return m_file->Redo(); } string BinaryView::GetCurrentView() { return m_file->GetCurrentView(); } uint64_t BinaryView::GetCurrentOffset() { return m_file->GetCurrentOffset(); } bool BinaryView::Navigate(const string& view, uint64_t offset) { return m_file->Navigate(view, offset); } DataBuffer BinaryView::ReadBuffer(uint64_t offset, size_t len) { BNDataBuffer* result = BNReadViewBuffer(m_view, offset, len); return DataBuffer(result); } size_t BinaryView::WriteBuffer(uint64_t offset, const DataBuffer& data) { return BNWriteViewBuffer(m_view, offset, data.GetBufferObject()); } size_t BinaryView::InsertBuffer(uint64_t offset, const DataBuffer& data) { return BNInsertViewBuffer(m_view, offset, data.GetBufferObject()); } vector BinaryView::GetModification(uint64_t offset, size_t len) { BNModificationStatus* mod = new BNModificationStatus[len]; len = BNGetModificationArray(m_view, offset, mod, len); vector result; for (size_t i = 0; i < len; i++) result.push_back(mod[i]); delete[] mod; return result; } uint64_t BinaryView::GetEnd() const { return BNGetEndOffset(m_view); } bool BinaryView::Save(const string& path) { return BNSaveToFilename(m_view, path.c_str()); } void BinaryView::RegisterNotification(BinaryDataNotification* notify) { BNRegisterDataNotification(m_view, notify->GetCallbacks()); } void BinaryView::UnregisterNotification(BinaryDataNotification* notify) { BNUnregisterDataNotification(m_view, notify->GetCallbacks()); } size_t BinaryView::Read(void* dest, uint64_t offset, size_t len) { return BNReadViewData(m_view, dest, offset, len); } size_t BinaryView::Write(uint64_t offset, const void* data, size_t len) { return BNWriteViewData(m_view, offset, data, len); } size_t BinaryView::Insert(uint64_t offset, const void* data, size_t len) { return BNInsertViewData(m_view, offset, data, len); } size_t BinaryView::Remove(uint64_t offset, uint64_t len) { return BNRemoveViewData(m_view, offset, len); } BNModificationStatus BinaryView::GetModification(uint64_t offset) { return BNGetModification(m_view, offset); } bool BinaryView::IsValidOffset(uint64_t offset) const { return BNIsValidOffset(m_view, offset); } bool BinaryView::IsOffsetReadable(uint64_t offset) const { return BNIsOffsetReadable(m_view, offset); } bool BinaryView::IsOffsetWritable(uint64_t offset) const { return BNIsOffsetWritable(m_view, offset); } bool BinaryView::IsOffsetExecutable(uint64_t offset) const { return BNIsOffsetExecutable(m_view, offset); } uint64_t BinaryView::GetNextValidOffset(uint64_t offset) const { return BNGetNextValidOffset(m_view, offset); } uint64_t BinaryView::GetStart() const { return BNGetStartOffset(m_view); } uint64_t BinaryView::GetLength() const { return BNGetViewLength(m_view); } uint64_t BinaryView::GetEntryPoint() const { return BNGetEntryPoint(m_view); } Ref BinaryView::GetDefaultArchitecture() const { BNArchitecture* arch = BNGetDefaultArchitecture(m_view); if (!arch) return nullptr; return new CoreArchitecture(arch); } void BinaryView::SetDefaultArchitecture(Architecture* arch) { if (arch) BNSetDefaultArchitecture(m_view, arch->GetArchitectureObject()); else BNSetDefaultArchitecture(m_view, nullptr); } BNEndianness BinaryView::GetDefaultEndianness() const { return BNGetDefaultEndianness(m_view); } size_t BinaryView::GetAddressSize() const { return BNGetViewAddressSize(m_view); } bool BinaryView::IsExecutable() const { return BNIsExecutableView(m_view); } bool BinaryView::Save(FileAccessor* file) { return BNSaveToFile(m_view, file->GetCallbacks()); } void BinaryView::AddFunctionForAnalysis(Architecture* arch, uint64_t addr) { BNAddFunctionForAnalysis(m_view, arch->GetArchitectureObject(), addr); } void BinaryView::AddEntryPointForAnalysis(Architecture* arch, uint64_t addr) { BNAddEntryPointForAnalysis(m_view, arch->GetArchitectureObject(), addr); } void BinaryView::RemoveAnalysisFunction(Function* func) { BNRemoveAnalysisFunction(m_view, func->GetFunctionObject()); } void BinaryView::CreateUserFunction(Architecture* arch, uint64_t start) { BNCreateUserFunction(m_view, arch->GetArchitectureObject(), start); } void BinaryView::UpdateAnalysis() { BNUpdateAnalysis(m_view); } void BinaryView::AbortAnalysis() { BNAbortAnalysis(m_view); } vector> BinaryView::GetAnalysisFunctionList() { size_t count; BNFunction** list = BNGetAnalysisFunctionList(m_view, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); BNFreeFunctionList(list, count); return result; } Ref BinaryView::GetAnalysisFunction(Architecture* arch, uint64_t addr) { BNFunction* func = BNGetAnalysisFunction(m_view, arch->GetArchitectureObject(), addr); if (!func) return nullptr; return new Function(func); } Ref BinaryView::GetRecentAnalysisFunctionForAddress(uint64_t addr) { BNFunction* func = BNGetRecentAnalysisFunctionForAddress(m_view, addr); if (!func) return nullptr; return new Function(func); } vector> BinaryView::GetAnalysisFunctionsForAddress(uint64_t addr) { size_t count; BNFunction** list = BNGetAnalysisFunctionsForAddress(m_view, addr, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Function(BNNewFunctionReference(list[i]))); BNFreeFunctionList(list, count); return result; } Ref BinaryView::GetAnalysisEntryPoint() { BNFunction* func = BNGetAnalysisEntryPoint(m_view); if (!func) return nullptr; return new Function(func); } Ref BinaryView::GetRecentBasicBlockForAddress(uint64_t addr) { BNBasicBlock* block = BNGetRecentBasicBlockForAddress(m_view, addr); if (!block) return nullptr; return new BasicBlock(block); } vector> BinaryView::GetBasicBlocksForAddress(uint64_t addr) { size_t count; BNBasicBlock** blocks = BNGetBasicBlocksForAddress(m_view, addr, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new BasicBlock(BNNewBasicBlockReference(blocks[i]))); BNFreeBasicBlockList(blocks, count); return result; } vector BinaryView::GetCodeReferences(uint64_t addr) { size_t count; BNReferenceSource* refs = BNGetCodeReferences(m_view, addr, &count); vector result; for (size_t i = 0; i < count; i++) { ReferenceSource src; src.func = new Function(BNNewFunctionReference(refs[i].func)); src.arch = new CoreArchitecture(refs[i].arch); src.addr = refs[i].addr; result.push_back(src); } BNFreeCodeReferences(refs, count); return result; } Ref BinaryView::GetSymbolByAddress(uint64_t addr) { BNSymbol* sym = BNGetSymbolByAddress(m_view, addr); if (!sym) return nullptr; return new Symbol(sym); } Ref BinaryView::GetSymbolByRawName(const string& name) { BNSymbol* sym = BNGetSymbolByRawName(m_view, name.c_str()); if (!sym) return nullptr; return new Symbol(sym); } vector> BinaryView::GetSymbolsByName(const string& name) { size_t count; BNSymbol** syms = BNGetSymbolsByName(m_view, name.c_str(), &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); BNFreeSymbolList(syms, count); return result; } vector> BinaryView::GetSymbols() { size_t count; BNSymbol** syms = BNGetSymbols(m_view, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); BNFreeSymbolList(syms, count); return result; } vector> BinaryView::GetSymbols(uint64_t start, uint64_t len) { size_t count; BNSymbol** syms = BNGetSymbolsInRange(m_view, start, len, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); BNFreeSymbolList(syms, count); return result; } vector> BinaryView::GetSymbolsOfType(BNSymbolType type) { size_t count; BNSymbol** syms = BNGetSymbolsOfType(m_view, type, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); BNFreeSymbolList(syms, count); return result; } vector> BinaryView::GetSymbolsOfType(BNSymbolType type, uint64_t start, uint64_t len) { size_t count; BNSymbol** syms = BNGetSymbolsOfTypeInRange(m_view, type, start, len, &count); vector> result; for (size_t i = 0; i < count; i++) result.push_back(new Symbol(BNNewSymbolReference(syms[i]))); BNFreeSymbolList(syms, count); return result; } void BinaryView::DefineAutoSymbol(Symbol* sym) { BNDefineAutoSymbol(m_view, sym->GetSymbolObject()); } void BinaryView::UndefineAutoSymbol(Symbol* sym) { BNUndefineAutoSymbol(m_view, sym->GetSymbolObject()); } void BinaryView::DefineUserSymbol(Symbol* sym) { BNDefineUserSymbol(m_view, sym->GetSymbolObject()); } void BinaryView::UndefineUserSymbol(Symbol* sym) { BNUndefineUserSymbol(m_view, sym->GetSymbolObject()); } bool BinaryView::IsNeverBranchPatchAvailable(Architecture* arch, uint64_t addr) { return BNIsNeverBranchPatchAvailable(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::IsAlwaysBranchPatchAvailable(Architecture* arch, uint64_t addr) { return BNIsAlwaysBranchPatchAvailable(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::IsInvertBranchPatchAvailable(Architecture* arch, uint64_t addr) { return BNIsInvertBranchPatchAvailable(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::IsSkipAndReturnZeroPatchAvailable(Architecture* arch, uint64_t addr) { return BNIsSkipAndReturnZeroPatchAvailable(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::IsSkipAndReturnValuePatchAvailable(Architecture* arch, uint64_t addr) { return BNIsSkipAndReturnValuePatchAvailable(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::ConvertToNop(Architecture* arch, uint64_t addr) { return BNConvertToNop(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::AlwaysBranch(Architecture* arch, uint64_t addr) { return BNAlwaysBranch(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::InvertBranch(Architecture* arch, uint64_t addr) { return BNInvertBranch(m_view, arch->GetArchitectureObject(), addr); } bool BinaryView::SkipAndReturnValue(Architecture* arch, uint64_t addr, uint64_t value) { return BNSkipAndReturnValue(m_view, arch->GetArchitectureObject(), addr, value); } size_t BinaryView::GetInstructionLength(Architecture* arch, uint64_t addr) { return BNGetInstructionLength(m_view, arch->GetArchitectureObject(), addr); } vector BinaryView::GetStrings() { size_t count; BNStringReference* strings = BNGetStrings(m_view, &count); vector result; result.insert(result.end(), strings, strings + count); BNFreeStringList(strings); return result; } vector BinaryView::GetStrings(uint64_t start, uint64_t len) { size_t count; BNStringReference* strings = BNGetStringsInRange(m_view, start, len, &count); vector result; result.insert(result.end(), strings, strings + count); BNFreeStringList(strings); return result; } BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetFileObject())) { } BinaryData::BinaryData(FileMetadata* file, const DataBuffer& data): BinaryView(BNCreateBinaryDataViewFromBuffer(file->GetFileObject(), data.GetBufferObject())) { } BinaryData::BinaryData(FileMetadata* file, const void* data, size_t len): BinaryView(BNCreateBinaryDataViewFromData(file->GetFileObject(), data, len)) { } BinaryData::BinaryData(FileMetadata* file, const string& path): BinaryView(BNCreateBinaryDataViewFromFilename(file->GetFileObject(), path.c_str())) { } BinaryData::BinaryData(FileMetadata* file, FileAccessor* accessor): BinaryView(BNCreateBinaryDataViewFromFile(file->GetFileObject(), accessor->GetCallbacks())) { }