Skip to content

Commit

Permalink
Fix UAF on C++ BinaryView plugin init, improve demangler and BinaryVi…
Browse files Browse the repository at this point in the history
…ew APIs
  • Loading branch information
D0ntPanic committed Jan 30, 2023
1 parent cf42205 commit a3939bd
Show file tree
Hide file tree
Showing 12 changed files with 402 additions and 78 deletions.
5 changes: 4 additions & 1 deletion architecture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
150 changes: 126 additions & 24 deletions binaryninjaapi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down Expand Up @@ -145,6 +179,9 @@ namespace BinaryNinja {
if (m_refs == 0)
delete this;
}

void AddRefForCallback() { AddRefInternal(); }
void ReleaseForCallback() { ReleaseInternal(); }
};

/*!
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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

Expand Down Expand Up @@ -5151,22 +5222,23 @@ 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

\param data An existing BinaryView, typically with the \c Raw type
\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(
Expand All @@ -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;
};

Expand Down Expand Up @@ -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.

*/
Expand Down Expand Up @@ -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
19 changes: 15 additions & 4 deletions binaryninjacore.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -257,6 +257,7 @@ extern "C"
struct BNDebugInfoParser;
struct BNSecretsProvider;
struct BNLogger;
struct BNSymbolQueue;


//! Console log levels
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions binaryreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading

0 comments on commit a3939bd

Please sign in to comment.