diff options
| author | Rusty Wagner <rusty.wagner@gmail.com> | 2023-01-24 18:38:13 -0700 |
|---|---|---|
| committer | Rusty Wagner <rusty.wagner@gmail.com> | 2023-01-30 11:57:43 -0500 |
| commit | a3939bdec15f9299ae9a681255fa93c47113870a (patch) | |
| tree | 2b4bb5643ac3cd25a618a99a542968fe81c66bcc | |
| parent | cf4220570c2d1b7105fb29719383f64026d46837 (diff) | |
Fix UAF on C++ BinaryView plugin init, improve demangler and BinaryView APIs
| -rw-r--r-- | architecture.cpp | 5 | ||||
| -rw-r--r-- | binaryninjaapi.h | 150 | ||||
| -rw-r--r-- | binaryninjacore.h | 19 | ||||
| -rw-r--r-- | binaryreader.cpp | 11 | ||||
| -rw-r--r-- | binaryview.cpp | 111 | ||||
| -rw-r--r-- | binaryviewtype.cpp | 43 | ||||
| -rw-r--r-- | demangle.cpp | 26 | ||||
| -rw-r--r-- | python/binaryview.py | 35 | ||||
| -rw-r--r-- | rapidjson/document.h | 12 | ||||
| -rw-r--r-- | rust/src/binaryview.rs | 45 | ||||
| -rw-r--r-- | rust/src/lib.rs | 16 | ||||
| -rw-r--r-- | type.cpp | 7 |
12 files changed, 402 insertions, 78 deletions
diff --git a/architecture.cpp b/architecture.cpp index 7fcc43a8..3c44202f 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -1252,7 +1252,10 @@ void Architecture::RegisterRelocationHandler(const string& viewName, RelocationH Ref<RelocationHandler> Architecture::GetRelocationHandler(const std::string& viewName) { - return new CoreRelocationHandler(BNArchitectureGetRelocationHandler(m_object, viewName.c_str())); + auto handler = BNArchitectureGetRelocationHandler(m_object, viewName.c_str()); + if (!handler) + return nullptr; + return new CoreRelocationHandler(handler); } bool Architecture::IsBinaryViewTypeConstantDefined(const string& type, const string& name) diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 80b9cacd..05a5e1df 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -57,6 +57,40 @@ #endif namespace BinaryNinja { +#ifdef __GNUC__ +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + static inline uint16_t ToLE16(uint16_t val) { return val; } + static inline uint32_t ToLE32(uint32_t val) { return val; } + static inline uint64_t ToLE64(uint64_t val) { return val; } + static inline uint16_t ToBE16(uint16_t val) { return __builtin_bswap16(val); } + static inline uint32_t ToBE32(uint32_t val) { return __builtin_bswap32(val); } + static inline uint64_t ToBE64(uint64_t val) { return __builtin_bswap64(val); } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + static inline uint16_t ToBE16(uint16_t val) { return val; } + static inline uint32_t ToBE32(uint32_t val) { return val; } + static inline uint64_t ToBE64(uint64_t val) { return val; } + static inline uint16_t ToLE16(uint16_t val) { return __builtin_bswap16(val); } + static inline uint32_t ToLE32(uint32_t val) { return __builtin_bswap32(val); } + static inline uint64_t ToLE64(uint64_t val) { return __builtin_bswap64(val); } +#endif +#elif defined(_MSC_VER) +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + static inline uint16_t ToLE16(uint16_t val) { return val; } + static inline uint32_t ToLE32(uint32_t val) { return val; } + static inline uint64_t ToLE64(uint64_t val) { return val; } + static inline uint16_t ToBE16(uint16_t val) { return _byteswap_ushort(val); } + static inline uint32_t ToBE32(uint32_t val) { return _byteswap_ulong(val); } + static inline uint64_t ToBE64(uint64_t val) { return _byteswap_uint64(val); } +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + static inline uint16_t ToBE16(uint16_t val) { return val; } + static inline uint32_t ToBE32(uint32_t val) { return val; } + static inline uint64_t ToBE64(uint64_t val) { return val; } + static inline uint16_t ToLE16(uint16_t val) { return _byteswap_ushort(val); } + static inline uint32_t ToLE32(uint32_t val) { return _byteswap_ulong(val); } + static inline uint64_t ToLE64(uint64_t val) { return _byteswap_uint64(val); } +#endif +#endif + /*! \ingroup refcount */ @@ -145,6 +179,9 @@ namespace BinaryNinja { if (m_refs == 0) delete this; } + + void AddRefForCallback() { AddRefInternal(); } + void ReleaseForCallback() { ReleaseInternal(); } }; /*! @@ -312,6 +349,28 @@ namespace BinaryNinja { T* GetPtr() const { return m_obj; } }; + /*! + \ingroup refcount + */ + template <class T> + class CallbackRef + { + T* m_obj; + + public: + CallbackRef<T>(void* obj) : m_obj((T*)obj) { m_obj->AddRefForCallback(); } + ~CallbackRef<T>() { m_obj->ReleaseForCallback(); } + operator T*() const { return m_obj; } + T* operator->() const { return m_obj; } + T& operator*() const { return *m_obj; } + bool operator==(const T* obj) const { return T::GetObject(m_obj) == T::GetObject(obj); } + bool operator==(const Ref<T>& obj) const { return T::GetObject(m_obj) == T::GetObject(obj.m_obj); } + bool operator!=(const T* obj) const { return T::GetObject(m_obj) != T::GetObject(obj); } + bool operator!=(const Ref<T>& obj) const { return T::GetObject(m_obj) != T::GetObject(obj.m_obj); } + bool operator<(const T* obj) const { return T::GetObject(m_obj) < T::GetObject(obj); } + bool operator<(const Ref<T>& obj) const { return T::GetObject(m_obj) < T::GetObject(obj.m_obj); } + T* GetPtr() const { return m_obj; } + }; /*! \ingroup confidence @@ -911,59 +970,67 @@ namespace BinaryNinja { \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. \param[in] mangledName a mangled Microsoft Visual Studio C++ name - \param[out] outType Pointer to Type to output + \param[out] outType Reference to Type to output \param[out] outVarName QualifiedName reference to write the output name to. \param[in] simplify Whether to simplify demangled names. \ingroup demangle */ - bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const bool simplify = false); + bool DemangleMS(Architecture* arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, + const bool simplify = false); /*! Demangles a Microsoft Visual Studio C++ name This overload will use the view's "analysis.types.templateSimplifier" setting - to determine whether to simplify the mangled name. + to determine whether to simplify the mangled name. - \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. + \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. \param[in] mangledName a mangled Microsoft Visual Studio C++ name - \param[out] outType Pointer to Type to output + \param[out] outType Reference to Type to output \param[out] outVarName QualifiedName reference to write the output name to. \param[in] view View to check the analysis.types.templateSimplifier for - \ingroup demangle + \ingroup demangle */ - bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const Ref<BinaryView>& view); + bool DemangleMS(Architecture* arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, + BinaryView* view); /*! Demangles a GNU3 name - \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. + \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. \param[in] mangledName a mangled GNU3 name - \param[out] outType Pointer to Type to output + \param[out] outType Reference to Type to output \param[out] outVarName QualifiedName reference to write the output name to. \param[in] simplify Whether to simplify demangled names. \ingroup demangle */ - bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const bool simplify = false); + bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Ref<Type>& outType, + QualifiedName& outVarName, const bool simplify = false); /*! Demangles a GNU3 name This overload will use the view's "analysis.types.templateSimplifier" setting to determine whether to simplify the mangled name. - \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. + \param[in] arch Architecture for the symbol. Required for pointer and integer sizes. \param[in] mangledName a mangled GNU3 name - \param[out] outType Pointer to Type to output + \param[out] outType Reference to Type to output \param[out] outVarName QualifiedName reference to write the output name to. \param[in] view View to check the analysis.types.templateSimplifier for \ingroup demangle */ - bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const Ref<BinaryView>& view); + bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Ref<Type>& outType, + QualifiedName& outVarName, BinaryView* view); + + /*! Determines if a symbol name is a mangled GNU3 name + + \param[in] mangledName a potentially mangled name + + \ingroup demangle + */ + bool IsGNU3MangledString(const std::string& mangledName); /*! \ingroup mainthread @@ -3458,8 +3525,11 @@ namespace BinaryNinja { \param platform Platform for the function to be loaded \param addr Virtual adddress of the function to be loaded + \param autoDiscovered true if function was automatically discovered, false if created by user + \param type optional function type */ - void AddFunctionForAnalysis(Platform* platform, uint64_t addr); + Ref<Function> AddFunctionForAnalysis( + Platform* platform, uint64_t addr, bool autoDiscovered = false, Type* type = nullptr); /*! adds an virtual address to start analysis from for a given platform @@ -3471,8 +3541,9 @@ namespace BinaryNinja { /*! removes a function from the list of functions \param func Function to be removed + \param updateRefs automatically update other functions that were referenced */ - void RemoveAnalysisFunction(Function* func); + void RemoveAnalysisFunction(Function* func, bool updateRefs = false); /*! Add a new user function of the given platform at the virtual address @@ -5151,14 +5222,14 @@ namespace BinaryNinja { \param data An existing BinaryView, typically with the \c Raw type \return The BinaryView created by this BinaryViewType */ - virtual BinaryView* Create(BinaryView* data) = 0; + virtual Ref<BinaryView> Create(BinaryView* data) = 0; /*! Create ephemeral BinaryView to generate information for preview \param data An existing BinaryView, typically with the \c Raw type \return The BinaryView created by this BinaryViewType */ - virtual BinaryView* Parse(BinaryView* data) = 0; + virtual Ref<BinaryView> Parse(BinaryView* data); /*! Check whether this BinaryViewType is valid for given data @@ -5166,7 +5237,8 @@ namespace BinaryNinja { \return Whether this BinaryViewType is valid for given data */ virtual bool IsTypeValidForData(BinaryView* data) = 0; - virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) = 0; + virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data); + Ref<Settings> GetDefaultLoadSettingsForData(BinaryView* data); static void RegisterBinaryViewFinalizationEvent(const std::function<void(BinaryView* view)>& callback); static void RegisterBinaryViewInitialAnalysisCompletionEvent( @@ -5183,9 +5255,10 @@ namespace BinaryNinja { { public: CoreBinaryViewType(BNBinaryViewType* type); - virtual BinaryView* Create(BinaryView* data) override; - virtual BinaryView* Parse(BinaryView* data) override; + virtual Ref<BinaryView> Create(BinaryView* data) override; + virtual Ref<BinaryView> Parse(BinaryView* data) override; virtual bool IsTypeValidForData(BinaryView* data) override; + virtual bool IsDeprecated() override; virtual Ref<Settings> GetLoadSettingsForData(BinaryView* data) override; }; @@ -5452,6 +5525,18 @@ namespace BinaryNinja { */ void SeekRelative(int64_t offset); + /*! Gets the virtual base offset for the stream + + \return The current virtual base + */ + uint64_t GetVirtualBase(); + + /*! Sets a virtual base offset for the stream + + \param base The new virtual base + */ + void SetVirtualBase(uint64_t base); + /*! Whether the current cursor position is at the end of the file. */ @@ -14868,4 +14953,21 @@ namespace BinaryNinja { void Finalize(); }; + /*! + \ingroup binaryview + */ + class SymbolQueue + { + BNSymbolQueue* m_object; + + static void ResolveCallback(void* ctxt, BNSymbol** symbol, BNType** type); + static void AddCallback(void* ctxt, BNSymbol* symbol, BNType* type); + + public: + SymbolQueue(); + ~SymbolQueue(); + void Append(const std::function<std::pair<Ref<Symbol>, Ref<Type>>()>& resolve, + const std::function<void(Symbol*, Type*)>& add); + void Process(); + }; } // namespace BinaryNinja diff --git a/binaryninjacore.h b/binaryninjacore.h index c3c1546f..f76ae881 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -36,14 +36,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 30 +#define BN_CURRENT_CORE_ABI_VERSION 31 // 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 30 +#define BN_MINIMUM_CORE_ABI_VERSION 31 #ifdef __GNUC__ #ifdef BINARYNINJACORE_LIBRARY @@ -257,6 +257,7 @@ extern "C" struct BNDebugInfoParser; struct BNSecretsProvider; struct BNLogger; + struct BNSymbolQueue; //! Console log levels @@ -3537,6 +3538,8 @@ extern "C" BINARYNINJACOREAPI uint64_t BNGetReaderPosition(BNBinaryReader* stream); BINARYNINJACOREAPI void BNSeekBinaryReader(BNBinaryReader* stream, uint64_t offset); BINARYNINJACOREAPI void BNSeekBinaryReaderRelative(BNBinaryReader* stream, int64_t offset); + BINARYNINJACOREAPI uint64_t BNGetBinaryReaderVirtualBase(BNBinaryReader* stream); + BINARYNINJACOREAPI void BNSetBinaryReaderVirtualBase(BNBinaryReader* stream, uint64_t base); BINARYNINJACOREAPI bool BNIsEndOfFile(BNBinaryReader* stream); // Stream writer object @@ -3708,9 +3711,10 @@ extern "C" const uint8_t* data, uint64_t addr, size_t length, const BNLowLevelILFunction* il, BNRelocation* relocation); // Analysis BINARYNINJACOREAPI void BNAddAnalysisOption(BNBinaryView* view, const char* name); - BINARYNINJACOREAPI void BNAddFunctionForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); + BINARYNINJACOREAPI BNFunction* BNAddFunctionForAnalysis( + BNBinaryView* view, BNPlatform* platform, uint64_t addr, bool autoDiscovered, BNType* type); BINARYNINJACOREAPI void BNAddEntryPointForAnalysis(BNBinaryView* view, BNPlatform* platform, uint64_t addr); - BINARYNINJACOREAPI void BNRemoveAnalysisFunction(BNBinaryView* view, BNFunction* func); + BINARYNINJACOREAPI void BNRemoveAnalysisFunction(BNBinaryView* view, BNFunction* func, bool updateRefs); BINARYNINJACOREAPI BNFunction* BNCreateUserFunction(BNBinaryView* view, BNPlatform* platform, uint64_t addr); BINARYNINJACOREAPI void BNRemoveUserFunction(BNBinaryView* view, BNFunction* func); BINARYNINJACOREAPI bool BNHasInitialAnalysis(BNBinaryView* view); @@ -6440,6 +6444,13 @@ extern "C" BINARYNINJACOREAPI bool BNStoreSecretsProviderData(BNSecretsProvider* provider, const char* key, const char* data); BINARYNINJACOREAPI bool BNDeleteSecretsProviderData(BNSecretsProvider* provider, const char* key); + BINARYNINJACOREAPI BNSymbolQueue* BNCreateSymbolQueue(void); + BINARYNINJACOREAPI void BNDestroySymbolQueue(BNSymbolQueue* queue); + BINARYNINJACOREAPI void BNAppendSymbolQueue(BNSymbolQueue* queue, + void (*resolve)(void* ctxt, BNSymbol** symbol, BNType** type), void* resolveContext, + void (*add)(void* ctxt, BNSymbol* symbol, BNType* type), void* addContext); + BINARYNINJACOREAPI void BNProcessSymbolQueue(BNSymbolQueue* queue); + #ifdef __cplusplus } #endif diff --git a/binaryreader.cpp b/binaryreader.cpp index a50af69b..a574f908 100644 --- a/binaryreader.cpp +++ b/binaryreader.cpp @@ -262,6 +262,17 @@ void BinaryReader::SeekRelative(int64_t offset) } +uint64_t BinaryReader::GetVirtualBase() +{ + return BNGetBinaryReaderVirtualBase(m_stream); +} + +void BinaryReader::SetVirtualBase(uint64_t base) +{ + BNSetBinaryReaderVirtualBase(m_stream, base); +} + + bool BinaryReader::IsEndOfFile() const { return BNIsEndOfFile(m_stream); diff --git a/binaryview.cpp b/binaryview.cpp index 83ff95d9..40e4144a 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -27,6 +27,17 @@ using namespace BinaryNinja; using namespace std; +struct SymbolQueueResolveContext +{ + std::function<std::pair<Ref<Symbol>, Ref<Type>>()> resolve; +}; + +struct SymbolQueueAddContext +{ + std::function<void(Symbol*, Type*)> add; +}; + + void BinaryDataNotification::DataWrittenCallback(void* ctxt, BNBinaryView* object, uint64_t offset, size_t len) { BinaryDataNotification* notify = (BinaryDataNotification*)ctxt; @@ -1009,147 +1020,147 @@ BinaryView::BinaryView(BNBinaryView* view) bool BinaryView::InitCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->Init(); } void BinaryView::FreeCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); view->ReleaseForRegistration(); } size_t BinaryView::ReadCallback(void* ctxt, void* dest, uint64_t offset, size_t len) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(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; + CallbackRef<BinaryView> view(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; + CallbackRef<BinaryView> view(ctxt); return view->PerformInsert(offset, src, len); } size_t BinaryView::RemoveCallback(void* ctxt, uint64_t offset, uint64_t len) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformRemove(offset, len); } BNModificationStatus BinaryView::GetModificationCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetModification(offset); } bool BinaryView::IsValidOffsetCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsValidOffset(offset); } bool BinaryView::IsOffsetReadableCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsOffsetReadable(offset); } bool BinaryView::IsOffsetWritableCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsOffsetWritable(offset); } bool BinaryView::IsOffsetExecutableCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsOffsetExecutable(offset); } bool BinaryView::IsOffsetBackedByFileCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsOffsetBackedByFile(offset); } uint64_t BinaryView::GetNextValidOffsetCallback(void* ctxt, uint64_t offset) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetNextValidOffset(offset); } uint64_t BinaryView::GetStartCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetStart(); } uint64_t BinaryView::GetLengthCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetLength(); } uint64_t BinaryView::GetEntryPointCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetEntryPoint(); } bool BinaryView::IsExecutableCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsExecutable(); } BNEndianness BinaryView::GetDefaultEndiannessCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetDefaultEndianness(); } bool BinaryView::IsRelocatableCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformIsRelocatable(); } size_t BinaryView::GetAddressSizeCallback(void* ctxt) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); return view->PerformGetAddressSize(); } bool BinaryView::SaveCallback(void* ctxt, BNFileAccessor* file) { - BinaryView* view = (BinaryView*)ctxt; + CallbackRef<BinaryView> view(ctxt); CoreFileAccessor accessor(file); return view->PerformSave(&accessor); } @@ -1670,9 +1681,13 @@ void BinaryView::AddAnalysisOption(const string& name) } -void BinaryView::AddFunctionForAnalysis(Platform* platform, uint64_t addr) +Ref<Function> BinaryView::AddFunctionForAnalysis(Platform* platform, uint64_t addr, bool autoDiscovered, Type* type) { - BNAddFunctionForAnalysis(m_object, platform->GetObject(), addr); + BNFunction* func = BNAddFunctionForAnalysis( + m_object, platform->GetObject(), addr, autoDiscovered, type ? type->GetObject() : nullptr); + if (!func) + return nullptr; + return new Function(func); } @@ -1682,9 +1697,9 @@ void BinaryView::AddEntryPointForAnalysis(Platform* platform, uint64_t addr) } -void BinaryView::RemoveAnalysisFunction(Function* func) +void BinaryView::RemoveAnalysisFunction(Function* func, bool updateRefs) { - BNRemoveAnalysisFunction(m_object, func->GetObject()); + BNRemoveAnalysisFunction(m_object, func->GetObject(), updateRefs); } @@ -4630,3 +4645,49 @@ Ref<BinaryView> BinaryNinja::OpenView(Ref<BinaryView> view, bool updateAnalysis, return bv; } + +SymbolQueue::SymbolQueue() +{ + m_object = BNCreateSymbolQueue(); +} + + +SymbolQueue::~SymbolQueue() +{ + BNDestroySymbolQueue(m_object); +} + + +void SymbolQueue::ResolveCallback(void* ctxt, BNSymbol** symbol, BNType** type) +{ + SymbolQueueResolveContext* resolve = (SymbolQueueResolveContext*)ctxt; + auto result = resolve->resolve(); + delete resolve; + *symbol = result.first ? BNNewSymbolReference(result.first->GetObject()) : nullptr; + *type = result.second ? BNNewTypeReference(result.second->GetObject()) : nullptr; +} + + +void SymbolQueue::AddCallback(void* ctxt, BNSymbol* symbol, BNType* type) +{ + SymbolQueueAddContext* add = (SymbolQueueAddContext*)ctxt; + Ref<Symbol> apiSymbol = new Symbol(symbol); + Ref<Type> apiType = new Type(type); + add->add(apiSymbol, apiType); + delete add; +} + + +void SymbolQueue::Append( + const std::function<std::pair<Ref<Symbol>, Ref<Type>>()>& resolve, const std::function<void(Symbol*, Type*)>& add) +{ + SymbolQueueResolveContext* resolveCtxt = new SymbolQueueResolveContext {resolve}; + SymbolQueueAddContext* addCtxt = new SymbolQueueAddContext {add}; + BNAppendSymbolQueue(m_object, ResolveCallback, resolveCtxt, AddCallback, addCtxt); +} + + +void SymbolQueue::Process() +{ + BNProcessSymbolQueue(m_object); +} diff --git a/binaryviewtype.cpp b/binaryviewtype.cpp index b1f9ebe9..8ab09aae 100644 --- a/binaryviewtype.cpp +++ b/binaryviewtype.cpp @@ -243,7 +243,7 @@ string BinaryViewType::GetLongName() bool BinaryViewType::IsDeprecated() { - return BNIsBinaryViewTypeDeprecated(m_object); + return false; } @@ -283,10 +283,41 @@ BNPlatform* BinaryViewType::PlatformRecognizerCallback(void* ctxt, BNBinaryView* } +Ref<BinaryView> BinaryViewType::Parse(BinaryView* data) +{ + Ref<BinaryView> viewRef; + + // Create ephemeral BinaryView to generate information for preview + if (data && (GetName() != data->GetTypeName())) + { + viewRef = Create(data); + if (!viewRef || !viewRef->Init()) + LogError("View type '%s' could not be created", GetName().c_str()); + } + + return viewRef; +} + + +Ref<Settings> BinaryViewType::GetLoadSettingsForData(BinaryView* data) +{ + return GetDefaultLoadSettingsForData(data); +} + + +Ref<Settings> BinaryViewType::GetDefaultLoadSettingsForData(BinaryView* data) +{ + BNSettings* settings = BNGetBinaryViewDefaultLoadSettingsForData(m_object, data->GetObject()); + if (!settings) + return nullptr; + return new Settings(settings); +} + + CoreBinaryViewType::CoreBinaryViewType(BNBinaryViewType* type) : BinaryViewType(type) {} -BinaryView* CoreBinaryViewType::Create(BinaryView* data) +Ref<BinaryView> CoreBinaryViewType::Create(BinaryView* data) { BNBinaryView* view = BNCreateBinaryViewOfType(m_object, data->GetObject()); if (!view) @@ -295,7 +326,7 @@ BinaryView* CoreBinaryViewType::Create(BinaryView* data) } -BinaryView* CoreBinaryViewType::Parse(BinaryView* data) +Ref<BinaryView> CoreBinaryViewType::Parse(BinaryView* data) { BNBinaryView* view = BNParseBinaryViewOfType(m_object, data->GetObject()); if (!view) @@ -310,6 +341,12 @@ bool CoreBinaryViewType::IsTypeValidForData(BinaryView* data) } +bool CoreBinaryViewType::IsDeprecated() +{ + return BNIsBinaryViewTypeDeprecated(m_object); +} + + Ref<Settings> CoreBinaryViewType::GetLoadSettingsForData(BinaryView* data) { BNSettings* settings = BNGetBinaryViewLoadSettingsForData(m_object, data->GetObject()); diff --git a/demangle.cpp b/demangle.cpp index 17879f4f..9239da6d 100644 --- a/demangle.cpp +++ b/demangle.cpp @@ -3,14 +3,14 @@ using namespace std; namespace BinaryNinja { - bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const Ref<BinaryView>& view) + bool DemangleMS(Architecture* arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, + BinaryView* view) { const bool simplify = Settings::Instance()->Get<bool>("analysis.types.templateSimplifier", view); return DemangleMS(arch, mangledName, outType, outVarName, simplify); } - bool DemangleMS(Architecture* arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, + bool DemangleMS(Architecture* arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, const bool simplify) { BNType* localType = nullptr; @@ -18,9 +18,7 @@ namespace BinaryNinja { size_t localSize = 0; if (!BNDemangleMS(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize, simplify)) return false; - if (!localType) - return false; - *outType = new Type(BNNewTypeReference(localType)); + outType = localType ? new Type(BNNewTypeReference(localType)) : nullptr; for (size_t i = 0; i < localSize; i++) { outVarName.push_back(localVarName[i]); @@ -30,14 +28,14 @@ namespace BinaryNinja { return true; } - bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, - const Ref<BinaryView>& view) + bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, + BinaryView* view) { const bool simplify = Settings::Instance()->Get<bool>("analysis.types.templateSimplifier", view); return DemangleGNU3(arch, mangledName, outType, outVarName, simplify); } - bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Type** outType, QualifiedName& outVarName, + bool DemangleGNU3(Ref<Architecture> arch, const std::string& mangledName, Ref<Type>& outType, QualifiedName& outVarName, const bool simplify) { BNType* localType; @@ -45,9 +43,7 @@ namespace BinaryNinja { size_t localSize = 0; if (!BNDemangleGNU3(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize, simplify)) return false; - if (!localType) - return false; - *outType = new Type(BNNewTypeReference(localType)); + outType = localType ? new Type(BNNewTypeReference(localType)) : nullptr; for (size_t i = 0; i < localSize; i++) { outVarName.push_back(localVarName[i]); @@ -58,6 +54,12 @@ namespace BinaryNinja { } + bool IsGNU3MangledString(const std::string& mangledName) + { + return BNIsGNU3MangledString(mangledName.c_str()); + } + + string SimplifyName::to_string(const string& input) { return (string)SimplifyName(input, SimplifierDest::str, true); diff --git a/python/binaryview.py b/python/binaryview.py index e429fc77..031c2886 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -3721,7 +3721,7 @@ class BinaryView: self._notifications[notify]._unregister() del self._notifications[notify] - def add_function(self, addr: int, plat: Optional['_platform.Platform'] = None) -> None: + def add_function(self, addr: int, plat: Optional['_platform.Platform'] = None, auto_discovered: bool = False, func_type: Optional['_function.Function'] = None) -> Optional['_function.Function']: """ ``add_function`` add a new function of the given ``plat`` at the virtual address ``addr`` @@ -3729,6 +3729,8 @@ class BinaryView: :param int addr: virtual address of the function to be added :param Platform plat: Platform for the function to be added + :param auto_discovered: True if function was automatically discovered, False if created by user + :param func_type: optional function type :rtype: None :Example: @@ -3743,7 +3745,16 @@ class BinaryView: plat = self.platform if not isinstance(plat, _platform.Platform): raise ValueError("Provided platform is not of type `Platform`") - core.BNAddFunctionForAnalysis(self.handle, plat.handle, addr) + + if isinstance(func_type, _types.Type): + func_type = func_type.handle + elif func_type is not None: + raise ValueError("Provided type is not of type `binaryninja.Type`") + + result = core.BNAddFunctionForAnalysis(self.handle, plat.handle, addr, auto_discovered, func_type) + if result: + return _function.Function(self, result) + return None def add_entry_point(self, addr: int, plat: Optional['_platform.Platform'] = None) -> None: """ @@ -3764,13 +3775,14 @@ class BinaryView: raise ValueError("Provided platform is not of type `Platform`") core.BNAddEntryPointForAnalysis(self.handle, plat.handle, addr) - def remove_function(self, func: '_function.Function') -> None: + def remove_function(self, func: '_function.Function', update_refs = False) -> None: """ ``remove_function`` removes the function ``func`` from the list of functions .. warning:: This method should only be used when the function that is removed is expected to re-appear after any other analysis executes that could re-add it. Most users will want to use :py:func:`remove_user_function` in their scripts. :param Function func: a Function object. + :param bool update_refs: automatically update other functions that were referenced :rtype: None :Example: @@ -3780,7 +3792,7 @@ class BinaryView: >>> bv.functions [] """ - core.BNRemoveAnalysisFunction(self.handle, func.handle) + core.BNRemoveAnalysisFunction(self.handle, func.handle, update_refs) def create_user_function(self, addr: int, plat: Optional['_platform.Platform'] = None) -> '_function.Function': """ @@ -8172,6 +8184,21 @@ class BinaryReader: core.BNSeekBinaryReader(self._handle, value) @property + def virtual_base(self) -> int: + """ + The current virtual base offset for the stream (read/write). + + :getter: returns the current virtual base + :setter: sets the virtual base + :type: int + """ + return core.BNGetBinaryReaderVirtualBase(self._handle) + + @virtual_base.setter + def virtual_base(self, value: int) -> None: + core.BNSetBinaryReaderVirtualBase(self._handle, value) + + @property def eof(self) -> bool: """ Is end of file (read-only) diff --git a/rapidjson/document.h b/rapidjson/document.h index 5ae54685..549bfcdc 100644 --- a/rapidjson/document.h +++ b/rapidjson/document.h @@ -1147,7 +1147,11 @@ public: return FindMember(n); } +#ifdef BINARYNINJACORE_LIBRARY MemberIterator FindMember(const BinaryNinjaCore::string& name) { +#else + MemberIterator FindMember(const std::string& name) { +#endif GenericValue n(StringRef(name.data(), name.size())); return FindMember(n); } @@ -1224,7 +1228,11 @@ public: return *this; } +#ifdef BINARYNINJACORE_LIBRARY GenericValue& AddMember(GenericValue& name, BinaryNinjaCore::string& value, Allocator& allocator) { +#else + GenericValue& AddMember(GenericValue& name, std::string& value, Allocator& allocator) { +#endif GenericValue v(value.data(), allocator); return AddMember(name, v, allocator); } @@ -1571,7 +1579,11 @@ public: return *this; } +#ifdef BINARYNINJACORE_LIBRARY GenericValue& PushBack(BinaryNinjaCore::string value, Allocator& allocator) { +#else + GenericValue& PushBack(std::string value, Allocator& allocator) { +#endif GenericValue v(value.c_str(), allocator); return PushBack(v, allocator); } diff --git a/rust/src/binaryview.rs b/rust/src/binaryview.rs index 26b0bae2..aab920d2 100644 --- a/rust/src/binaryview.rs +++ b/rust/src/binaryview.rs @@ -622,9 +622,50 @@ pub trait BinaryViewExt: BinaryViewBase { } } - fn add_auto_function(&self, plat: &Platform, addr: u64) { + fn add_auto_function(&self, plat: &Platform, addr: u64) -> Option<Ref<Function>> { unsafe { - BNAddFunctionForAnalysis(self.as_ref().handle, plat.handle, addr); + let handle = BNAddFunctionForAnalysis( + self.as_ref().handle, + plat.handle, + addr, + false, + ptr::null_mut(), + ); + + if handle.is_null() { + return None; + } + + Some(Function::from_raw(handle)) + } + } + + fn add_function_with_type( + &self, + plat: &Platform, + addr: u64, + auto_discovered: bool, + func_type: Option<&Type>, + ) -> Option<Ref<Function>> { + unsafe { + let func_type = match func_type { + Some(func_type) => func_type.handle, + None => ptr::null_mut(), + }; + + let handle = BNAddFunctionForAnalysis( + self.as_ref().handle, + plat.handle, + addr, + auto_discovered, + func_type, + ); + + if handle.is_null() { + return None; + } + + Some(Function::from_raw(handle)) } } diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 5fbb8239..57b71cba 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -528,6 +528,22 @@ pub fn plugin_ui_abi_minimum_version() -> u32 { binaryninjacore_sys::BN_MINIMUM_UI_ABI_VERSION } +pub fn add_required_plugin_dependency<S: string::BnStrCompatible>(name: S) { + unsafe { + binaryninjacore_sys::BNAddRequiredPluginDependency( + name.into_bytes_with_nul().as_ref().as_ptr() as *const std::os::raw::c_char, + ) + }; +} + +pub fn add_optional_plugin_dependency<S: string::BnStrCompatible>(name: S) { + unsafe { + binaryninjacore_sys::BNAddOptionalPluginDependency( + name.into_bytes_with_nul().as_ref().as_ptr() as *const std::os::raw::c_char, + ) + }; +} + // Provide ABI version automatically so that the core can verify binary compatibility #[no_mangle] #[allow(non_snake_case)] @@ -794,7 +794,8 @@ Ref<Type> Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t wid BNBoolWithConfidence isSignedConf; isSignedConf.value = isSigned.GetValue(); isSignedConf.confidence = isSigned.GetConfidence(); - return new Type(BNCreateEnumerationType(arch->GetObject(), enm->GetObject(), width, &isSignedConf)); + return new Type( + BNCreateEnumerationType(arch ? arch->GetObject() : nullptr, enm->GetObject(), width, &isSignedConf)); } @@ -1629,8 +1630,8 @@ TypeBuilder TypeBuilder::EnumerationType( BNBoolWithConfidence isSignedConf; isSignedConf.value = isSigned.GetValue(); isSignedConf.confidence = isSigned.GetConfidence(); - return TypeBuilder( - BNCreateEnumerationTypeBuilderWithBuilder(arch->GetObject(), enm->GetObject(), width, &isSignedConf)); + return TypeBuilder(BNCreateEnumerationTypeBuilderWithBuilder( + arch ? arch->GetObject() : nullptr, enm->GetObject(), width, &isSignedConf)); } TypeBuilder TypeBuilder::PointerType(Architecture* arch, const Confidence<Ref<Type>>& type, |
