summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2023-01-24 18:38:13 -0700
committerRusty Wagner <rusty.wagner@gmail.com>2023-01-30 11:57:43 -0500
commita3939bdec15f9299ae9a681255fa93c47113870a (patch)
tree2b4bb5643ac3cd25a618a99a542968fe81c66bcc
parentcf4220570c2d1b7105fb29719383f64026d46837 (diff)
Fix UAF on C++ BinaryView plugin init, improve demangler and BinaryView APIs
-rw-r--r--architecture.cpp5
-rw-r--r--binaryninjaapi.h150
-rw-r--r--binaryninjacore.h19
-rw-r--r--binaryreader.cpp11
-rw-r--r--binaryview.cpp111
-rw-r--r--binaryviewtype.cpp43
-rw-r--r--demangle.cpp26
-rw-r--r--python/binaryview.py35
-rw-r--r--rapidjson/document.h12
-rw-r--r--rust/src/binaryview.rs45
-rw-r--r--rust/src/lib.rs16
-rw-r--r--type.cpp7
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)]
diff --git a/type.cpp b/type.cpp
index a2e92985..1c7b425e 100644
--- a/type.cpp
+++ b/type.cpp
@@ -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,