summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Wagner <rusty@vector35.com>2016-12-01 18:13:54 -0500
committerRusty Wagner <rusty@vector35.com>2016-12-01 18:13:54 -0500
commit8c42dabe92340b4d342f3b4e7594fb70f1890e41 (patch)
tree406a4a0e0486b00a71b3d0bb65a3dd15cdf91981
parentf69430aedd957f5e8f221488cd6acb9031d3c1c1 (diff)
parent3b719e990e3e01242918bf66d5a1fb6032517641 (diff)
Merge branch 'dev'
-rw-r--r--api-docs/source/conf.py8
-rw-r--r--architecture.cpp20
-rw-r--r--binaryninjaapi.h63
-rw-r--r--binaryninjacore.h112
-rw-r--r--binaryview.cpp228
-rw-r--r--demangle.cpp20
-rw-r--r--docs/.s3_website.yaml3
-rw-r--r--docs/getting-started.md9
-rw-r--r--docs/guide/troubleshooting.md22
-rw-r--r--platform.cpp9
-rw-r--r--python/__init__.py434
-rw-r--r--python/examples/nds.py88
-rw-r--r--python/examples/nes.py114
-rw-r--r--python/examples/nsf.py138
-rw-r--r--type.cpp46
15 files changed, 1111 insertions, 203 deletions
diff --git a/api-docs/source/conf.py b/api-docs/source/conf.py
index 42bcfb87..ac6042b4 100644
--- a/api-docs/source/conf.py
+++ b/api-docs/source/conf.py
@@ -121,7 +121,7 @@ exclude_patterns = []
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
-# add_module_names = True
+add_module_names = False
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
@@ -211,7 +211,7 @@ html_static_path = ['_static']
# If false, no module index is generated.
#
-# html_domain_indices = True
+html_domain_indices = False
# If false, no index is generated.
#
@@ -219,11 +219,11 @@ html_static_path = ['_static']
# If true, the index is split into individual pages for each letter.
#
-# html_split_index = False
+html_split_index = False
# If true, links to the reST sources are added to the pages.
#
-# html_show_sourcelink = True
+html_show_sourcelink = False
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
diff --git a/architecture.cpp b/architecture.cpp
index af7b0cba..3c7d9af8 100644
--- a/architecture.cpp
+++ b/architecture.cpp
@@ -111,6 +111,13 @@ size_t Architecture::GetOpcodeDisplayLengthCallback(void* ctxt)
}
+BNArchitecture* Architecture::GetAssociatedArchitectureByAddressCallback(void* ctxt, uint64_t* addr)
+{
+ Architecture* arch = (Architecture*)ctxt;
+ return arch->GetAssociatedArchitectureByAddress(*addr)->GetObject();
+}
+
+
bool Architecture::GetInstructionInfoCallback(void* ctxt, const uint8_t* data, uint64_t addr,
size_t maxLen, BNInstructionInfo* result)
{
@@ -408,6 +415,7 @@ void Architecture::Register(Architecture* arch)
callbacks.getDefaultIntegerSize = GetDefaultIntegerSizeCallback;
callbacks.getMaxInstructionLength = GetMaxInstructionLengthCallback;
callbacks.getOpcodeDisplayLength = GetOpcodeDisplayLengthCallback;
+ callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback;
callbacks.getInstructionInfo = GetInstructionInfoCallback;
callbacks.getInstructionText = GetInstructionTextCallback;
callbacks.freeInstructionText = FreeInstructionTextCallback;
@@ -499,6 +507,12 @@ size_t Architecture::GetOpcodeDisplayLength() const
}
+Ref<Architecture> Architecture::GetAssociatedArchitectureByAddress(uint64_t&)
+{
+ return this;
+}
+
+
bool Architecture::GetInstructionLowLevelIL(const uint8_t*, uint64_t, size_t&, LowLevelILFunction& il)
{
il.AddInstruction(il.Undefined());
@@ -919,6 +933,12 @@ size_t CoreArchitecture::GetOpcodeDisplayLength() const
}
+Ref<Architecture> CoreArchitecture::GetAssociatedArchitectureByAddress(uint64_t& addr)
+{
+ return new CoreArchitecture(BNGetAssociatedArchitectureByAddress(m_object, &addr));
+}
+
+
bool CoreArchitecture::GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result)
{
return BNGetInstructionInfo(m_object, data, addr, maxLen, &result);
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index b115263c..a918fc42 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -730,6 +730,22 @@ namespace BinaryNinja
bool autoDiscovered;
};
+ struct Segment
+ {
+ uint64_t start, length;
+ uint64_t dataOffset, dataLength;
+ uint32_t flags;
+ };
+
+ struct Section
+ {
+ std::string name, type;
+ uint64_t start, length;
+ std::string linkedSection, infoSection;
+ uint64_t infoData;
+ uint64_t align, entrySize;
+ };
+
struct NameAndType;
/*! BinaryView is the base class for creating views on binary data (e.g. ELF, PE, Mach-O).
@@ -743,8 +759,9 @@ namespace BinaryNinja
/*! BinaryView constructor
\param typeName name of the BinaryView (e.g. ELF, PE, Mach-O, ...)
\param file a file to create a view from
+ \param parentView optional view that contains the raw data used by this view
*/
- BinaryView(const std::string& typeName, FileMetadata* file);
+ BinaryView(const std::string& typeName, FileMetadata* file, BinaryView* parentView = nullptr);
/*! PerformRead provides a mapping between the flat file and virtual offsets in the file.
@@ -771,7 +788,7 @@ namespace BinaryNinja
virtual BNEndianness PerformGetDefaultEndianness() const;
virtual size_t PerformGetAddressSize() const;
- virtual bool PerformSave(FileAccessor* file) { (void)file; return false; }
+ virtual bool PerformSave(FileAccessor* file);
void NotifyDataWritten(uint64_t offset, size_t len);
void NotifyDataInserted(uint64_t offset, size_t len);
@@ -805,6 +822,7 @@ namespace BinaryNinja
virtual bool Init() { return true; }
FileMetadata* GetFile() const { return m_file; }
+ Ref<BinaryView> GetParentView() const;
std::string GetTypeName() const;
bool IsModified() const;
@@ -908,6 +926,7 @@ namespace BinaryNinja
std::vector<Ref<Symbol>> GetSymbolsOfType(BNSymbolType type, uint64_t start, uint64_t len);
void DefineAutoSymbol(Ref<Symbol> sym);
+ void DefineAutoSymbolAndVariableOrFunction(Ref<Platform> platform, Ref<Symbol> sym, Ref<Type> type);
void UndefineAutoSymbol(Ref<Symbol> sym);
void DefineUserSymbol(Ref<Symbol> sym);
@@ -969,6 +988,29 @@ namespace BinaryNinja
bool GetAddressInput(uint64_t& result, const std::string& prompt, const std::string& title);
bool GetAddressInput(uint64_t& result, const std::string& prompt, const std::string& title,
uint64_t currentAddress);
+
+ void AddAutoSegment(uint64_t start, uint64_t length, uint64_t dataOffset, uint64_t dataLength, uint32_t flags);
+ void RemoveAutoSegment(uint64_t start, uint64_t length);
+ void AddUserSegment(uint64_t start, uint64_t length, uint64_t dataOffset, uint64_t dataLength, uint32_t flags);
+ void RemoveUserSegment(uint64_t start, uint64_t length);
+ std::vector<Segment> GetSegments();
+ bool GetSegmentAt(uint64_t addr, Segment& result);
+
+ void AddAutoSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "",
+ uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "",
+ const std::string& infoSection = "", uint64_t infoData = 0);
+ void RemoveAutoSection(const std::string& name);
+ void AddUserSection(const std::string& name, uint64_t start, uint64_t length, const std::string& type = "",
+ uint64_t align = 1, uint64_t entrySize = 0, const std::string& linkedSection = "",
+ const std::string& infoSection = "", uint64_t infoData = 0);
+ void RemoveUserSection(const std::string& name);
+ std::vector<Section> GetSections();
+ std::vector<Section> GetSectionsAt(uint64_t addr);
+ bool GetSectionByName(const std::string& name, Section& result);
+
+ std::vector<std::string> GetUniqueSectionNames(const std::vector<std::string>& names);
+
+ std::vector<BNAddressRange> GetAllocatedRanges();
};
class BinaryData: public BinaryView
@@ -1216,6 +1258,7 @@ namespace BinaryNinja
static size_t GetDefaultIntegerSizeCallback(void* ctxt);
static size_t GetMaxInstructionLengthCallback(void* ctxt);
static size_t GetOpcodeDisplayLengthCallback(void* ctxt);
+ static BNArchitecture* GetAssociatedArchitectureByAddressCallback(void* ctxt, uint64_t* addr);
static bool GetInstructionInfoCallback(void* ctxt, const uint8_t* data, uint64_t addr,
size_t maxLen, BNInstructionInfo* result);
static bool GetInstructionTextCallback(void* ctxt, const uint8_t* data, uint64_t addr,
@@ -1270,6 +1313,8 @@ namespace BinaryNinja
virtual size_t GetMaxInstructionLength() const;
virtual size_t GetOpcodeDisplayLength() const;
+ virtual Ref<Architecture> GetAssociatedArchitectureByAddress(uint64_t& addr);
+
virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) = 0;
virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len,
std::vector<InstructionTextToken>& result) = 0;
@@ -1413,6 +1458,7 @@ namespace BinaryNinja
virtual size_t GetDefaultIntegerSize() const override;
virtual size_t GetMaxInstructionLength() const override;
virtual size_t GetOpcodeDisplayLength() const override;
+ virtual Ref<Architecture> GetAssociatedArchitectureByAddress(uint64_t& addr) override;
virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override;
virtual bool GetInstructionText(const uint8_t* data, uint64_t addr, size_t& len,
std::vector<InstructionTextToken>& result) override;
@@ -1449,6 +1495,7 @@ namespace BinaryNinja
};
class Structure;
+ class UnknownType;
class Enumeration;
struct NameAndType
@@ -1476,6 +1523,8 @@ namespace BinaryNinja
bool CanReturn() const;
Ref<Structure> GetStructure() const;
Ref<Enumeration> GetEnumeration() const;
+ Ref<UnknownType> GetUnknownType() const;
+
uint64_t GetElementCount() const;
void SetFunctionCanReturn(bool canReturn);
@@ -1492,6 +1541,7 @@ namespace BinaryNinja
static Ref<Type> IntegerType(size_t width, bool sign, const std::string& altName = "");
static Ref<Type> FloatType(size_t width, const std::string& typeName = "");
static Ref<Type> StructureType(Structure* strct);
+ static Ref<Type> UnknownNamedType(UnknownType* unknwn);
static Ref<Type> EnumerationType(Architecture* arch, Enumeration* enm, size_t width = 0, bool issigned = false);
static Ref<Type> PointerType(Architecture* arch, Type* type, bool cnst = false, bool vltl = false,
BNReferenceType refType = PointerReferenceType);
@@ -1502,6 +1552,14 @@ namespace BinaryNinja
static std::string GetQualifiedName(const std::vector<std::string>& names);
};
+ class UnknownType: public CoreRefCountObject<BNUnknownType, BNNewUnknownTypeReference, BNFreeUnknownType>
+ {
+ public:
+ UnknownType(BNUnknownType* s, std::vector<std::string> name = {});
+ std::vector<std::string> GetName() const;
+ void SetName(const std::vector<std::string>& name);
+ };
+
struct StructureMember
{
Ref<Type> type;
@@ -2186,6 +2244,7 @@ namespace BinaryNinja
Ref<Platform> GetRelatedPlatform(Architecture* arch);
void AddRelatedPlatform(Architecture* arch, Platform* platform);
+ Ref<Platform> GetAssociatedPlatformByAddress(uint64_t& addr);
};
class ScriptingOutputListener
diff --git a/binaryninjacore.h b/binaryninjacore.h
index b6d2f7ed..b2ed7cd3 100644
--- a/binaryninjacore.h
+++ b/binaryninjacore.h
@@ -94,6 +94,7 @@ extern "C"
struct BNLowLevelILFunction;
struct BNType;
struct BNStructure;
+ struct BNUnknownType;
struct BNEnumeration;
struct BNCallingConvention;
struct BNPlatform;
@@ -200,7 +201,14 @@ extern "C"
FunctionContinuationLineType,
StackVariableLineType,
StackVariableListEndLineType,
- FunctionEndLineType
+ FunctionEndLineType,
+ NoteStartLineType,
+ NoteLineType,
+ NoteEndLineType,
+ SectionStartLineType,
+ SectionEndLineType,
+ SectionSeparatorLineType,
+ NonContiguousSeparatorLineType
};
enum BNSymbolType
@@ -355,7 +363,8 @@ extern "C"
ArrayTypeClass = 7,
FunctionTypeClass = 8,
VarArgsTypeClass = 9,
- ValueTypeClass = 10
+ ValueTypeClass = 10,
+ UnknownTypeClass = 11
};
enum BNStructureType
@@ -384,7 +393,8 @@ extern "C"
{
PointerReferenceType = 0,
ReferenceReferenceType = 1,
- RValueReferenceType = 2
+ RValueReferenceType = 2,
+ NoReference = 3
};
enum BNPointerSuffix
@@ -471,7 +481,11 @@ extern "C"
RttiBaseClassDescriptor,
RttiBaseClassArray,
RttiClassHeirarchyDescriptor,
- RttiCompleteObjectLocator
+ RttiCompleteObjectLocator,
+ OperatorUnaryMinusNameType,
+ OperatorUnaryPlusNameType,
+ OperatorUnaryBitAndNameType,
+ OperatorUnaryStarNameType
};
enum BNCallingConventionName
@@ -711,6 +725,7 @@ extern "C"
size_t (*getDefaultIntegerSize)(void* ctxt);
size_t (*getMaxInstructionLength)(void* ctxt);
size_t (*getOpcodeDisplayLength)(void* ctxt);
+ BNArchitecture* (*getAssociatedArchitectureByAddress)(void* ctxt, uint64_t* addr);
bool (*getInstructionInfo)(void* ctxt, const uint8_t* data, uint64_t addr, size_t maxLen, BNInstructionInfo* result);
bool (*getInstructionText)(void* ctxt, const uint8_t* data, uint64_t addr, size_t* len,
BNInstructionTextToken** result, size_t* count);
@@ -1137,8 +1152,44 @@ extern "C"
void (*destructFunction)(void* ctxt, BNFunction* func);
};
+ enum BNSegmentFlag
+ {
+ SegmentExecutable = 1,
+ SegmentWritable = 2,
+ SegmentReadable = 4,
+ SegmentContainsData = 8,
+ SegmentContainsCode = 0x10,
+ SegmentDenyWrite = 0x20,
+ SegmentDenyExecute = 0x40
+ };
+
+ struct BNSegment
+ {
+ uint64_t start, length;
+ uint64_t dataOffset, dataLength;
+ uint32_t flags;
+ };
+
+ struct BNSection
+ {
+ char* name;
+ char* type;
+ uint64_t start, length;
+ char* linkedSection;
+ char* infoSection;
+ uint64_t infoData;
+ uint64_t align, entrySize;
+ };
+
+ struct BNAddressRange
+ {
+ uint64_t start;
+ uint64_t end;
+ };
+
BINARYNINJACOREAPI char* BNAllocString(const char* contents);
BINARYNINJACOREAPI void BNFreeString(char* str);
+ BINARYNINJACOREAPI void BNFreeStringList(char** strs, size_t count);
BINARYNINJACOREAPI void BNShutdown(void);
@@ -1266,6 +1317,8 @@ extern "C"
BINARYNINJACOREAPI BNFileMetadata* BNGetFileForView(BNBinaryView* view);
BINARYNINJACOREAPI char* BNGetViewType(BNBinaryView* view);
+ BINARYNINJACOREAPI BNBinaryView* BNGetParentView(BNBinaryView* view);
+
BINARYNINJACOREAPI size_t BNReadViewData(BNBinaryView* view, void* dest, uint64_t offset, size_t len);
BINARYNINJACOREAPI BNDataBuffer* BNReadViewBuffer(BNBinaryView* view, uint64_t offset, size_t len);
@@ -1325,6 +1378,35 @@ extern "C"
BINARYNINJACOREAPI bool BNFindNextData(BNBinaryView* view, uint64_t start, BNDataBuffer* data, uint64_t* result,
BNFindFlag flags);
+ BINARYNINJACOREAPI void BNAddAutoSegment(BNBinaryView* view, uint64_t start, uint64_t length,
+ uint64_t dataOffset, uint64_t dataLength, uint32_t flags);
+ BINARYNINJACOREAPI void BNRemoveAutoSegment(BNBinaryView* view, uint64_t start, uint64_t length);
+ BINARYNINJACOREAPI void BNAddUserSegment(BNBinaryView* view, uint64_t start, uint64_t length,
+ uint64_t dataOffset, uint64_t dataLength, uint32_t flags);
+ BINARYNINJACOREAPI void BNRemoveUserSegment(BNBinaryView* view, uint64_t start, uint64_t length);
+ BINARYNINJACOREAPI BNSegment* BNGetSegments(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI void BNFreeSegmentList(BNSegment* segments);
+ BINARYNINJACOREAPI bool BNGetSegmentAt(BNBinaryView* view, uint64_t addr, BNSegment* result);
+
+ BINARYNINJACOREAPI void BNAddAutoSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length,
+ const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection, const char* infoSection,
+ uint64_t infoData);
+ BINARYNINJACOREAPI void BNRemoveAutoSection(BNBinaryView* view, const char* name);
+ BINARYNINJACOREAPI void BNAddUserSection(BNBinaryView* view, const char* name, uint64_t start, uint64_t length,
+ const char* type, uint64_t align, uint64_t entrySize, const char* linkedSection, const char* infoSection,
+ uint64_t infoData);
+ BINARYNINJACOREAPI void BNRemoveUserSection(BNBinaryView* view, const char* name);
+ BINARYNINJACOREAPI BNSection* BNGetSections(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI BNSection* BNGetSectionsAt(BNBinaryView* view, uint64_t addr, size_t* count);
+ BINARYNINJACOREAPI void BNFreeSectionList(BNSection* sections, size_t count);
+ BINARYNINJACOREAPI bool BNGetSectionByName(BNBinaryView* view, const char* name, BNSection* result);
+ BINARYNINJACOREAPI void BNFreeSection(BNSection* section);
+
+ BINARYNINJACOREAPI char** BNGetUniqueSectionNames(BNBinaryView* view, const char** names, size_t count);
+
+ BINARYNINJACOREAPI BNAddressRange* BNGetAllocatedRanges(BNBinaryView* view, size_t* count);
+ BINARYNINJACOREAPI void BNFreeAddressRanges(BNAddressRange* ranges);
+
// Raw binary data view
BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataView(BNFileMetadata* file);
BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataViewFromBuffer(BNFileMetadata* file, BNDataBuffer* buf);
@@ -1333,7 +1415,8 @@ extern "C"
BINARYNINJACOREAPI BNBinaryView* BNCreateBinaryDataViewFromFile(BNFileMetadata* file, BNFileAccessor* accessor);
// Creation of new types of binary views
- BINARYNINJACOREAPI BNBinaryView* BNCreateCustomBinaryView(const char* name, BNFileMetadata* file, BNCustomBinaryView* view);
+ BINARYNINJACOREAPI BNBinaryView* BNCreateCustomBinaryView(const char* name, BNFileMetadata* file,
+ BNBinaryView* parent, BNCustomBinaryView* view);
// Binary view type management
BINARYNINJACOREAPI BNBinaryViewType* BNGetBinaryViewTypeByName(const char* name);
@@ -1434,6 +1517,7 @@ extern "C"
BINARYNINJACOREAPI size_t BNGetArchitectureDefaultIntegerSize(BNArchitecture* arch);
BINARYNINJACOREAPI size_t BNGetArchitectureMaxInstructionLength(BNArchitecture* arch);
BINARYNINJACOREAPI size_t BNGetArchitectureOpcodeDisplayLength(BNArchitecture* arch);
+ BINARYNINJACOREAPI BNArchitecture* BNGetAssociatedArchitectureByAddress(BNArchitecture* arch, uint64_t* addr);
BINARYNINJACOREAPI bool BNGetInstructionInfo(BNArchitecture* arch, const uint8_t* data, uint64_t addr,
size_t maxLen, BNInstructionInfo* result);
BINARYNINJACOREAPI bool BNGetInstructionText(BNArchitecture* arch, const uint8_t* data, uint64_t addr,
@@ -1616,7 +1700,7 @@ extern "C"
BINARYNINJACOREAPI BNStringReference* BNGetStrings(BNBinaryView* view, size_t* count);
BINARYNINJACOREAPI BNStringReference* BNGetStringsInRange(BNBinaryView* view, uint64_t start,
uint64_t len, size_t* count);
- BINARYNINJACOREAPI void BNFreeStringList(BNStringReference* strings);
+ BINARYNINJACOREAPI void BNFreeStringReferenceList(BNStringReference* strings);
BINARYNINJACOREAPI BNStackVariable* BNGetStackLayout(BNFunction* func, size_t* count);
BINARYNINJACOREAPI void BNFreeStackLayout(BNStackVariable* vars, size_t count);
@@ -1793,6 +1877,8 @@ extern "C"
BINARYNINJACOREAPI void BNDefineUserSymbol(BNBinaryView* view, BNSymbol* sym);
BINARYNINJACOREAPI void BNUndefineUserSymbol(BNBinaryView* view, BNSymbol* sym);
BINARYNINJACOREAPI void BNDefineImportedFunction(BNBinaryView* view, BNSymbol* importAddressSym, BNFunction* func);
+ BINARYNINJACOREAPI void BNDefineAutoSymbolAndVariableOrFunction(BNBinaryView* view, BNPlatform* platform,
+ BNSymbol* sym, BNType* type);
BINARYNINJACOREAPI BNSymbol* BNImportedFunctionFromImportAddressSymbol(BNSymbol* sym, uint64_t addr);
@@ -1878,6 +1964,13 @@ extern "C"
BINARYNINJACOREAPI char* BNGetTypeStringBeforeName(BNType* type);
BINARYNINJACOREAPI char* BNGetTypeStringAfterName(BNType* type);
+ BINARYNINJACOREAPI BNType* BNCreateUnknownNamedType(BNUnknownType* ut);
+ BINARYNINJACOREAPI BNUnknownType* BNCreateUnknownType(void);
+ BINARYNINJACOREAPI void BNSetUnknownTypeName(BNUnknownType* ut, const char** name, size_t size);
+ BINARYNINJACOREAPI char** BNGetUnknownTypeName(BNUnknownType* ut, size_t* size);
+ BINARYNINJACOREAPI void BNFreeUnknownType(BNUnknownType* ut);
+ BINARYNINJACOREAPI BNUnknownType* BNNewUnknownTypeReference(BNUnknownType* ut);
+
BINARYNINJACOREAPI BNStructure* BNCreateStructure(void);
BINARYNINJACOREAPI BNStructure* BNNewStructureReference(BNStructure* s);
BINARYNINJACOREAPI void BNFreeStructure(BNStructure* s);
@@ -2044,6 +2137,7 @@ extern "C"
BINARYNINJACOREAPI BNPlatform* BNGetRelatedPlatform(BNPlatform* platform, BNArchitecture* arch);
BINARYNINJACOREAPI void BNAddRelatedPlatform(BNPlatform* platform, BNArchitecture* arch, BNPlatform* related);
+ BINARYNINJACOREAPI BNPlatform* BNGetAssociatedPlatformByAddress(BNPlatform* platform, uint64_t* addr);
//Demangler
BINARYNINJACOREAPI bool BNDemangleMS(BNArchitecture* arch,
@@ -2143,6 +2237,12 @@ extern "C"
BINARYNINJACOREAPI BNMessageBoxButtonResult BNShowMessageBox(const char* title, const char* text,
BNMessageBoxButtonSet buttons, BNMessageBoxIcon icon);
+ BINARYNINJACOREAPI bool BNDemangleGNU3(BNArchitecture* arch,
+ const char* mangledName,
+ BNType** outType,
+ char*** outVarName,
+ size_t* outVarNameElements);
+ BINARYNINJACOREAPI void BNFreeDemangledName(char*** name, size_t nameElements);
#ifdef __cplusplus
}
#endif
diff --git a/binaryview.cpp b/binaryview.cpp
index 863d57b2..cc6667c5 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -18,6 +18,8 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
+#include <algorithm>
+#include <iterator>
#include "binaryninjaapi.h"
using namespace BinaryNinja;
@@ -243,7 +245,7 @@ void AnalysisCompletionEvent::Cancel()
}
-BinaryView::BinaryView(const std::string& typeName, FileMetadata* file)
+BinaryView::BinaryView(const std::string& typeName, FileMetadata* file, BinaryView* parentView)
{
BNCustomBinaryView view;
view.context = this;
@@ -270,7 +272,8 @@ BinaryView::BinaryView(const std::string& typeName, FileMetadata* file)
m_file = file;
AddRefForRegistration();
- m_object = BNCreateCustomBinaryView(typeName.c_str(), m_file->GetObject(), &view);
+ m_object = BNCreateCustomBinaryView(typeName.c_str(), m_file->GetObject(),
+ parentView ? parentView->GetObject() : nullptr, &view);
}
@@ -481,6 +484,15 @@ size_t BinaryView::PerformGetAddressSize() const
}
+bool BinaryView::PerformSave(FileAccessor* file)
+{
+ Ref<BinaryView> parent = GetParentView();
+ if (parent)
+ return parent->Save(file);
+ return false;
+}
+
+
void BinaryView::NotifyDataWritten(uint64_t offset, size_t len)
{
BNNotifyDataWritten(m_object, offset, len);
@@ -499,6 +511,15 @@ void BinaryView::NotifyDataRemoved(uint64_t offset, uint64_t len)
}
+Ref<BinaryView> BinaryView::GetParentView() const
+{
+ BNBinaryView* view = BNGetParentView(m_object);
+ if (!view)
+ return nullptr;
+ return new BinaryView(view);
+}
+
+
string BinaryView::GetTypeName() const
{
char* str = BNGetViewType(m_object);
@@ -1135,6 +1156,13 @@ void BinaryView::DefineAutoSymbol(Ref<Symbol> sym)
}
+void BinaryView::DefineAutoSymbolAndVariableOrFunction(Ref<Platform> platform, Ref<Symbol> sym, Ref<Type> type)
+{
+ BNDefineAutoSymbolAndVariableOrFunction(m_object, platform ? platform->GetObject() : nullptr, sym->GetObject(),
+ type ? type->GetObject() : nullptr);
+}
+
+
void BinaryView::UndefineAutoSymbol(Ref<Symbol> sym)
{
BNUndefineAutoSymbol(m_object, sym->GetObject());
@@ -1225,7 +1253,7 @@ vector<BNStringReference> BinaryView::GetStrings()
BNStringReference* strings = BNGetStrings(m_object, &count);
vector<BNStringReference> result;
result.insert(result.end(), strings, strings + count);
- BNFreeStringList(strings);
+ BNFreeStringReferenceList(strings);
return result;
}
@@ -1236,7 +1264,7 @@ vector<BNStringReference> BinaryView::GetStrings(uint64_t start, uint64_t len)
BNStringReference* strings = BNGetStringsInRange(m_object, start, len, &count);
vector<BNStringReference> result;
result.insert(result.end(), strings, strings + count);
- BNFreeStringList(strings);
+ BNFreeStringReferenceList(strings);
return result;
}
@@ -1513,6 +1541,198 @@ bool BinaryView::GetAddressInput(uint64_t& result, const string& prompt, const s
}
+void BinaryView::AddAutoSegment(uint64_t start, uint64_t length, uint64_t dataOffset, uint64_t dataLength,
+ uint32_t flags)
+{
+ BNAddAutoSegment(m_object, start, length, dataOffset, dataLength, flags);
+}
+
+
+void BinaryView::RemoveAutoSegment(uint64_t start, uint64_t length)
+{
+ BNRemoveAutoSegment(m_object, start, length);
+}
+
+
+void BinaryView::AddUserSegment(uint64_t start, uint64_t length, uint64_t dataOffset, uint64_t dataLength,
+ uint32_t flags)
+{
+ BNAddUserSegment(m_object, start, length, dataOffset, dataLength, flags);
+}
+
+
+void BinaryView::RemoveUserSegment(uint64_t start, uint64_t length)
+{
+ BNRemoveUserSegment(m_object, start, length);
+}
+
+
+vector<Segment> BinaryView::GetSegments()
+{
+ size_t count;
+ BNSegment* segments = BNGetSegments(m_object, &count);
+
+ vector<Segment> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ Segment segment;
+ segment.start = segments[i].start;
+ segment.length = segments[i].length;
+ segment.dataOffset = segments[i].dataOffset;
+ segment.dataLength = segments[i].dataLength;
+ segment.flags = segments[i].flags;
+ result.push_back(segment);
+ }
+
+ BNFreeSegmentList(segments);
+ return result;
+}
+
+
+bool BinaryView::GetSegmentAt(uint64_t addr, Segment& result)
+{
+ BNSegment segment;
+ if (!BNGetSegmentAt(m_object, addr, &segment))
+ return false;
+
+ result.start = segment.start;
+ result.length = segment.length;
+ result.dataOffset = segment.dataOffset;
+ result.dataLength = segment.dataLength;
+ result.flags = segment.flags;
+ return true;
+}
+
+
+void BinaryView::AddAutoSection(const string& name, uint64_t start, uint64_t length, const string& type,
+ uint64_t align, uint64_t entrySize, const string& linkedSection, const string& infoSection, uint64_t infoData)
+{
+ BNAddAutoSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(),
+ infoSection.c_str(), infoData);
+}
+
+
+void BinaryView::RemoveAutoSection(const string& name)
+{
+ BNRemoveAutoSection(m_object, name.c_str());
+}
+
+
+void BinaryView::AddUserSection(const string& name, uint64_t start, uint64_t length, const string& type,
+ uint64_t align, uint64_t entrySize, const string& linkedSection, const string& infoSection, uint64_t infoData)
+{
+ BNAddUserSection(m_object, name.c_str(), start, length, type.c_str(), align, entrySize, linkedSection.c_str(),
+ infoSection.c_str(), infoData);
+}
+
+
+void BinaryView::RemoveUserSection(const string& name)
+{
+ BNRemoveUserSection(m_object, name.c_str());
+}
+
+
+vector<Section> BinaryView::GetSections()
+{
+ size_t count;
+ BNSection* sections = BNGetSections(m_object, &count);
+
+ vector<Section> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ Section section;
+ section.name = sections[i].name;
+ section.type = sections[i].type;
+ section.start = sections[i].start;
+ section.length = sections[i].length;
+ section.linkedSection = sections[i].linkedSection;
+ section.infoSection = sections[i].infoSection;
+ section.infoData = sections[i].infoData;
+ section.align = sections[i].align;
+ section.entrySize = sections[i].entrySize;
+ result.push_back(section);
+ }
+
+ BNFreeSectionList(sections, count);
+ return result;
+}
+
+
+vector<Section> BinaryView::GetSectionsAt(uint64_t addr)
+{
+ size_t count;
+ BNSection* sections = BNGetSectionsAt(m_object, addr, &count);
+
+ vector<Section> result;
+ for (size_t i = 0; i < count; i++)
+ {
+ Section section;
+ section.name = sections[i].name;
+ section.type = sections[i].type;
+ section.start = sections[i].start;
+ section.length = sections[i].length;
+ section.linkedSection = sections[i].linkedSection;
+ section.infoSection = sections[i].infoSection;
+ section.infoData = sections[i].infoData;
+ section.align = sections[i].align;
+ section.entrySize = sections[i].entrySize;
+ result.push_back(section);
+ }
+
+ BNFreeSectionList(sections, count);
+ return result;
+}
+
+
+bool BinaryView::GetSectionByName(const string& name, Section& result)
+{
+ BNSection section;
+ if (!BNGetSectionByName(m_object, name.c_str(), &section))
+ return false;
+
+ result.name = section.name;
+ result.type = section.type;
+ result.start = section.start;
+ result.length = section.length;
+ result.linkedSection = section.linkedSection;
+ result.infoSection = section.infoSection;
+ result.infoData = section.infoData;
+ result.align = section.align;
+ result.entrySize = section.entrySize;
+
+ BNFreeSection(&section);
+ return true;
+}
+
+
+vector<string> BinaryView::GetUniqueSectionNames(const vector<string>& names)
+{
+ const char** incomingNames = new const char*[names.size()];
+ for (size_t i = 0; i < names.size(); i++)
+ incomingNames[i] = names[i].c_str();
+
+ char** outgoingNames = BNGetUniqueSectionNames(m_object, incomingNames, names.size());
+ vector<string> result;
+ for (size_t i = 0; i < names.size(); i++)
+ result.push_back(outgoingNames[i]);
+
+ BNFreeStringList(outgoingNames, names.size());
+ return result;
+}
+
+
+vector<BNAddressRange> BinaryView::GetAllocatedRanges()
+{
+ size_t count;
+ BNAddressRange* ranges = BNGetAllocatedRanges(m_object, &count);
+
+ vector<BNAddressRange> result;
+ copy(&ranges[0], &ranges[count], back_inserter(result));
+ BNFreeAddressRanges(ranges);
+ return result;
+}
+
+
BinaryData::BinaryData(FileMetadata* file): BinaryView(BNCreateBinaryDataView(file->GetObject()))
{
}
diff --git a/demangle.cpp b/demangle.cpp
index 1a998a87..a12303ca 100644
--- a/demangle.cpp
+++ b/demangle.cpp
@@ -21,3 +21,23 @@ bool DemangleMS(Architecture* arch,
delete [] localVarName;
return true;
}
+
+
+bool DemangleGNU3(Architecture* arch,
+ const std::string& mangledName,
+ Type** outType,
+ std::vector<std::string>& outVarName)
+{
+ BNType* localType = (*outType)->GetObject();
+ char** localVarName = nullptr;
+ size_t localSize = 0;
+ if (!BNDemangleGNU3(arch->GetObject(), mangledName.c_str(), &localType, &localVarName, &localSize))
+ return false;
+ for (size_t i = 0; i < localSize; i++)
+ {
+ outVarName.push_back(localVarName[i]);
+ BNFreeString(localVarName[i]);
+ }
+ delete [] localVarName;
+ return true;
+}
diff --git a/docs/.s3_website.yaml b/docs/.s3_website.yaml
new file mode 100644
index 00000000..02c4a996
--- /dev/null
+++ b/docs/.s3_website.yaml
@@ -0,0 +1,3 @@
+s3_bucket: docs.binary.ninja
+site: ../site
+s3_reduced_redundancy: True
diff --git a/docs/getting-started.md b/docs/getting-started.md
index b7ffda4a..72c4796c 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -52,8 +52,8 @@ Switching views happens multiple ways. In some instances, it's automatic (clicki
- `h` : Switch to hex view
- `p` : Create a function
- - `&lt;ESC&gt;` : Navigate backward
- - `&lt;SPACE&gt;` : Toggle between linear view and graph view
+ - `[ESC]` : Navigate backward
+ - `[SPACE]` : Toggle between linear view and graph view
- `g` : Go To Address dialog
- `n` : Name a symbol
- `u` : Undefine a symbol
@@ -63,9 +63,14 @@ Switching views happens multiple ways. In some instances, it's automatic (clicki
- `i` : Switches between disassembly and low-level il in graph view
- `y` : Change type
- [1248] : Change type directly to a data variable of the indicated widths
+ - `a` : Change the data type to an ASCII string
- `d` : Switches between data variables of various widths
- `r` : Change the data type to single ASCII character
- `o` : Create a pointer data type
+ - `[CMD-SHIFT] +` (OS X) : Graph view zoom in
+ - `[CMD-SHIFT] -` (OS X) : Graph view zoom out
+ - `[CTRL-SHIFT] +` (Windows/Linux) : Graph view zoom in
+ - `[CTRL-SHIFT] -` (Windows/Linux) : Graph view zoom out
### Graph View
diff --git a/docs/guide/troubleshooting.md b/docs/guide/troubleshooting.md
index a521ab1f..af91f6f1 100644
--- a/docs/guide/troubleshooting.md
+++ b/docs/guide/troubleshooting.md
@@ -15,22 +15,36 @@ Running Binary Ninja with debug logging will make your bug report more useful.
## License Problems
-- If experiencing problems with Windows UAC permissions during an update, the easiest fix is to completely un-install and re-download the latest installer. Preferences are saved outside the installation folder and are preserved, though you might want to remove your [license](/getting-started/index.html#license).
+- If experiencing problems with Windows UAC permissions during an update, the easiest fix is to completely un-install and [recover][recover] the latest installer and license. Preferences are saved outside the installation folder and are preserved, though you might want to remove your [license](/getting-started/index.html#license).
- If you need to change the email address on your license, contact [support].
-## Arch Linux
+## Linux
-Arch Linux is not an officially supported operating system, but many of our users have run it, and there are a few pitfalls to watch out for.
+Given the diversity of Linux distributions, some work-arounds are required to run Binary Ninja on platforms that are not [officially supported][faq].
+
+### Arch Linux
- Install python2 from the [official repositories][archrepo]
- Install the [libcurl-compat] library from AUR, and run Binary Ninja via `LD_PRELOAD=libcurl.so.3 ~/binaryninja/binaryninja`
+### KDE
+
+To run Binary Ninja in a KDE based environment, set the `QT_PLUGIN_PATH` to the `QT` sub-folder:
+
+```
+cd ~/binaryninja
+QT_PLUGIN_PATH=./qt ./binaryninja
+```
+
+
## API
- - If the GUI launches but the license file is not valid, check that you're using the right version of Python. Only a 64-bit Python 2.7 is supported at this time.
+ - If the GUI launches but the license file is not valid when launched from the command-line, check that you're using the right version of Python. Only a 64-bit Python 2.7 is supported at this time. Additionally, the [personal][purchase] edition does not support headless operation.
[known issues]: https://github.com/Vector35/binaryninja-api/issues?q=is%3Aissue
[libcurl-compat]: https://aur.archlinux.org/packages/libcurl-compat/
[archrepo]: https://wiki.archlinux.org/index.php/Official_repositories
[recover]: https://binary.ninja/recover.html
[support]: https://binary.ninja/support.html
+[faq]: https://binary.ninja/faq.html
+[purchase]: https://binary.ninja/purchase.html
diff --git a/platform.cpp b/platform.cpp
index 9b4053db..7a6571cc 100644
--- a/platform.cpp
+++ b/platform.cpp
@@ -244,3 +244,12 @@ void Platform::AddRelatedPlatform(Architecture* arch, Platform* platform)
{
BNAddRelatedPlatform(m_object, arch->GetObject(), platform->GetObject());
}
+
+
+Ref<Platform> Platform::GetAssociatedPlatformByAddress(uint64_t& addr)
+{
+ BNPlatform* platform = BNGetAssociatedPlatformByAddress(m_object, &addr);
+ if (!platform)
+ return nullptr;
+ return new Platform(platform);
+}
diff --git a/python/__init__.py b/python/__init__.py
index 087c31af..9afd22c2 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -300,7 +300,7 @@ class FileMetadata(object):
view = core.BNGetFileViewOfType(self.handle, "Raw")
if view is None:
return None
- return BinaryView(self, handle = view)
+ return BinaryView(file_metadata = self, handle = view)
@property
def saved(self):
@@ -455,7 +455,7 @@ class FileMetadata(object):
lambda ctxt, cur, total: progress_func(cur, total)))
if view is None:
return None
- return BinaryView(self, handle = view)
+ return BinaryView(file_metadata = self, handle = view)
def save_auto_snapshot(self, progress_func = None):
if progress_func is None:
@@ -474,7 +474,7 @@ class FileMetadata(object):
view = core.BNCreateBinaryViewOfType(view_type, self.raw.handle)
if view is None:
return None
- return BinaryView(self, handle = view)
+ return BinaryView(file_metadata = self, handle = view)
def __setattr__(self, name, value):
try:
@@ -812,7 +812,7 @@ class BinaryViewType(object):
view = core.BNCreateBinaryViewOfType(self.handle, data.handle)
if view is None:
return None
- return BinaryView(data.file, handle = view)
+ return BinaryView(file_metadata = data.file, handle = view)
def open(self, src, file_metadata = None):
data = BinaryView.open(src, file_metadata)
@@ -924,6 +924,64 @@ class DataVariable(object):
def __repr__(self):
return "<var 0x%x: %s>" % (self.address, str(self.type))
+class Segment(object):
+ def __init__(self, start, length, data_offset, data_length, flags):
+ self.start = start
+ self.length = length
+ self.data_offset = data_offset
+ self.data_length = data_length
+ self.flags = flags
+
+ @property
+ def end(self):
+ return self.start + self.length
+
+ def __len__(self):
+ return self.length
+
+ def __repr__(self):
+ return "<segment: %#x-%#x, %s%s%s>" % (self.start, self.end,
+ "r" if (self.flags & core.SegmentReadable) != 0 else "-",
+ "w" if (self.flags & core.SegmentWritable) != 0 else "-",
+ "x" if (self.flags & core.SegmentExecutable) != 0 else "-")
+
+class Section(object):
+ def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size):
+ self.name = name
+ self.type = section_type
+ self.start = start
+ self.length = length
+ self.linked_section = linked_section
+ self.info_section = info_section
+ self.info_data = info_data
+ self.align = align
+ self.entry_size = entry_size
+
+ @property
+ def end(self):
+ return self.start + self.length
+
+ def __len__(self):
+ return self.length
+
+ def __repr__(self):
+ return "<section %s: %#x-%#x>" % (self.name, self.start, self.end)
+
+class AddressRange(object):
+ def __init__(self, start, end):
+ self.start = start
+ self.end = end
+
+ @property
+ def length(self):
+ return self.end - self.start
+
+ def __len__(self):
+ return self.end - self.start
+
+ def __repr__(self):
+ return "<%#x-%#x>" % (self.start, self.end)
+
class _BinaryViewAssociatedDataStore(_AssociatedDataStore):
_defaults = {}
@@ -982,7 +1040,7 @@ class BinaryView(object):
next_address = 0
_associated_data = {}
- def __init__(self, file_metadata = None, handle = None):
+ def __init__(self, file_metadata = None, parent_view = None, handle = None):
if handle is not None:
self.handle = core.handle_of_type(handle, core.BNBinaryView)
if file_metadata is None:
@@ -1020,7 +1078,9 @@ class BinaryView(object):
self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size)
self._cb.save = self._cb.save.__class__(self._save)
self.file = file_metadata
- self.handle = core.BNCreateCustomBinaryView(self.__class__.name, file_metadata.handle, self._cb)
+ if parent_view is not None:
+ parent_view = parent_view.handle
+ self.handle = core.BNCreateCustomBinaryView(self.__class__.name, file_metadata.handle, parent_view, self._cb)
self.notifications = {}
self.next_address = None # Do NOT try to access view before init() is called, use placeholder
@@ -1042,7 +1102,7 @@ class BinaryView(object):
def _create(cls, ctxt, data):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(data))
- view = cls(BinaryView(file_metadata, handle = core.BNNewViewReference(data)))
+ view = cls(BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data)))
if view is None:
return None
return ctypes.cast(core.BNNewViewReference(view.handle), ctypes.c_void_p).value
@@ -1053,7 +1113,7 @@ class BinaryView(object):
@classmethod
def _is_valid_for_data(cls, ctxt, data):
try:
- return cls.is_valid_for_data(BinaryView(None, handle = core.BNNewViewReference(data)))
+ return cls.is_valid_for_data(BinaryView(handle = core.BNNewViewReference(data)))
except:
log_error(traceback.format_exc())
return False
@@ -1071,7 +1131,7 @@ class BinaryView(object):
view = core.BNCreateBinaryDataViewFromFilename(file_metadata.handle, str(src))
if view is None:
return None
- result = BinaryView(file_metadata, handle = view)
+ result = BinaryView(file_metadata = file_metadata, handle = view)
return result
@classmethod
@@ -1086,7 +1146,7 @@ class BinaryView(object):
view = core.BNCreateBinaryDataViewFromBuffer(file_metadata.handle, buf.handle)
if view is None:
return None
- result = BinaryView(file_metadata, handle = view)
+ result = BinaryView(file_metadata = file_metadata, handle = view)
return result
@classmethod
@@ -1097,6 +1157,16 @@ class BinaryView(object):
@classmethod
def set_default_session_data(cls, name, value):
+ """
+ ```set_default_session_data``` saves a variable to the BinaryView.
+ :param name: name of the variable to be saved
+ :param value: value of the variable to be saved
+
+ :Example:
+ >>> BinaryView.set_default_session_data("variable_name", "value")
+ >>> bv.session_data.variable_name
+ 'value'
+ """
_BinaryViewAssociatedDataStore.set_default(name, value)
def __del__(self):
@@ -1114,6 +1184,14 @@ class BinaryView(object):
core.BNFreeFunctionList(funcs, count.value)
@property
+ def parent_view(self):
+ """View that contains the raw data used by this view (read-only)"""
+ result = core.BNGetParentView(self.handle)
+ if result is None:
+ return None
+ return BinaryView(handle = result)
+
+ @property
def modified(self):
"""boolean modification state of the BinaryView (read/write)"""
return self.file.modified
@@ -1311,6 +1389,42 @@ class BinaryView(object):
return result
@property
+ def segments(self):
+ """List of segments (read-only)"""
+ count = ctypes.c_ulonglong(0)
+ segment_list = core.BNGetSegments(self.handle, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(Segment(segment_list[i].start, segment_list[i].length,
+ segment_list[i].dataOffset, segment_list[i].dataLength, segment_list[i].flags))
+ core.BNFreeSegmentList(segment_list)
+ return result
+
+ @property
+ def sections(self):
+ """List of sections (read-only)"""
+ count = ctypes.c_ulonglong(0)
+ section_list = core.BNGetSections(self.handle, count)
+ result = {}
+ for i in xrange(0, count.value):
+ result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start,
+ section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection,
+ section_list[i].infoData, section_list[i].align, section_list[i].entrySize)
+ core.BNFreeSectionList(section_list, count.value)
+ return result
+
+ @property
+ def allocated_ranges(self):
+ """List of valid address ranges for this view (read-only)"""
+ count = ctypes.c_ulonglong(0)
+ range_list = core.BNGetAllocatedRanges(self.handle, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(AddressRange(range_list[i].start, range_list[i].end))
+ core.BNFreeAddressRanges(range_list)
+ return result
+
+ @property
def session_data(self):
"""Dictionary object where plugins can store arbitrary data associated with the view"""
handle = ctypes.cast(self.handle, ctypes.c_void_p)
@@ -1587,43 +1701,52 @@ class BinaryView(object):
return None
return ''.join(str(a) for a in txt).strip()
- @abc.abstractmethod
def perform_save(self, accessor):
- raise NotImplementedError
+ if self.parent_view is not None:
+ return self.parent_view.save(accessor)
+ return False
@abc.abstractmethod
def perform_get_address_size(self):
raise NotImplementedError
- @abc.abstractmethod
def perform_get_length(self):
- raise NotImplementedError
+ """
+ ``perform_get_length`` implements a query for the size of the virtual address range used by
+ the BinaryView.
+
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
+ .. warning:: This method **must not** be called directly.
+
+ :return: returns the size of the virtual address range used by the BinaryView.
+ :rtype: int
+ """
+ return 0
- @abc.abstractmethod
def perform_read(self, addr, length):
"""
``perform_read`` implements a mapping between a virtual address and an absolute file offset, reading
``length`` bytes from the rebased address ``addr``.
- .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is\
- different from the physical address.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to attempt to read from
:param int length: the number of bytes to be read
:return: length bytes read from addr, should return empty string on error
- :rtype: int
+ :rtype: str
"""
- raise NotImplementedError
+ return ""
- @abc.abstractmethod
def perform_write(self, addr, data):
"""
``perform_write`` implements a mapping between a virtual address and an absolute file offset, writing
the bytes ``data`` to rebased address ``addr``.
- .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \
- different from the physical address.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address
@@ -1631,16 +1754,14 @@ class BinaryView(object):
:return: length of data written, should return 0 on error
:rtype: int
"""
- raise NotImplementedError
+ return 0
- @abc.abstractmethod
def perform_insert(self, addr, data):
"""
``perform_insert`` implements a mapping between a virtual address and an absolute file offset, inserting
the bytes ``data`` to rebased address ``addr``.
- .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \
- different from the physical address.
+ .. note:: This method **may** be overridden by custom BinaryViews. If not overridden, inserting is disallowed
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address
@@ -1648,16 +1769,14 @@ class BinaryView(object):
:return: length of data inserted, should return 0 on error
:rtype: int
"""
- raise NotImplementedError
+ return 0
- @abc.abstractmethod
def perform_remove(self, addr, length):
"""
``perform_remove`` implements a mapping between a virtual address and an absolute file offset, removing
``length`` bytes from the rebased address ``addr``.
- .. note:: This method must be overridden by custom BinaryViews if they have segments or the virtual address is \
- different from the physical address.
+ .. note:: This method **may** be overridden by custom BinaryViews. If not overridden, removing data is disallowed
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address
@@ -1665,14 +1784,14 @@ class BinaryView(object):
:return: length of data removed, should return 0 on error
:rtype: int
"""
- raise NotImplementedError
+ return 0
- @abc.abstractmethod
def perform_get_modification(self, addr):
"""
``perform_get_modification`` implements query to the whether the virtual address ``addr`` is modified.
- .. note:: This method **may** be overridden by custom BinaryViews.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to be checked
@@ -1681,13 +1800,12 @@ class BinaryView(object):
"""
return core.Original
- @abc.abstractmethod
def perform_is_valid_offset(self, addr):
"""
``perform_is_valid_offset`` implements a check if an virtual address ``addr`` is valid.
- .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \
- physical file offsets.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to be checked
@@ -1697,13 +1815,12 @@ class BinaryView(object):
data = self.read(addr, 1)
return (data is not None) and (len(data) == 1)
- @abc.abstractmethod
def perform_is_offset_readable(self, offset):
"""
``perform_is_offset_readable`` implements a check if an virtual address is readable.
- .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \
- physical file offsets, or if memory protections exist.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int offset: a virtual address to be checked
@@ -1712,13 +1829,12 @@ class BinaryView(object):
"""
return self.is_valid_offset(offset)
- @abc.abstractmethod
def perform_is_offset_writable(self, addr):
"""
``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is writable.
- .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \
- physical file offsets, or if memory protections exist.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to be checked
@@ -1727,13 +1843,12 @@ class BinaryView(object):
"""
return self.is_valid_offset(addr)
- @abc.abstractmethod
def perform_is_offset_executable(self, addr):
"""
``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is executable.
- .. note:: This method **must** be implemented for custom BinaryViews whose virtual addresses differ from \
- physical file offsets, or if memory protections exist.
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to be checked
@@ -1742,13 +1857,13 @@ class BinaryView(object):
"""
return self.is_valid_offset(addr)
- @abc.abstractmethod
def perform_get_next_valid_offset(self, addr):
"""
``perform_get_next_valid_offset`` implements a query for the next valid readable, writable, or executable virtual
memory address.
- .. note:: This method **may** be implemented by custom BinaryViews
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:param int addr: a virtual address to start checking from.
@@ -1759,13 +1874,13 @@ class BinaryView(object):
return self.perform_get_start()
return addr
- @abc.abstractmethod
def perform_get_start(self):
"""
``perform_get_start`` implements a query for the first readable, writable, or executable virtual address in
the BinaryView.
- .. note:: This method **may** be implemented by custom BinaryViews
+ .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide
+ data without overriding this method.
.. warning:: This method **must not** be called directly.
:return: returns the first virtual address in the BinaryView.
@@ -1773,7 +1888,6 @@ class BinaryView(object):
"""
return 0
- @abc.abstractmethod
def perform_get_entry_point(self):
"""
``perform_get_entry_point`` implements a query for the initial entry point for code execution.
@@ -1786,7 +1900,6 @@ class BinaryView(object):
"""
return 0
- @abc.abstractmethod
def perform_is_executable(self):
"""
``perform_is_executable`` implements a check which returns true if the BinaryView is executable.
@@ -1797,9 +1910,8 @@ class BinaryView(object):
:return: true if the current BinaryView is executable, false if it is not executable or on error
:rtype: bool
"""
- raise NotImplementedError
+ return False
- @abc.abstractmethod
def perform_get_default_endianness(self):
"""
``perform_get_default_endianness`` implements a check which returns true if the BinaryView is executable.
@@ -2388,6 +2500,19 @@ class BinaryView(object):
return BasicBlock(self, block)
def get_code_refs(self, addr, length = None):
+ """
+ ``get_code_refs`` returns a list of ReferenceSource objects (xrefs or cross-references) that point to the provided virtual address.
+
+ :param int addr: virtual address to query for references
+ :return: List of References for the given virtual address
+ :rtype: list(ReferenceSource)
+ :Example:
+
+ >>> bv.get_code_refs(here)
+ [<ref: x86@0x4165ff>]
+ >>>
+
+ """
count = ctypes.c_ulonglong(0)
if length is None:
refs = core.BNGetCodeReferences(self.handle, addr, count)
@@ -2528,6 +2653,21 @@ class BinaryView(object):
"""
core.BNDefineAutoSymbol(self.handle, sym.handle)
+ def define_auto_symbol_and_var_or_function(self, sym, sym_type, platform = None):
+ """
+ ``define_auto_symbol`` adds a symbol to the internal list of automatically discovered Symbol objects.
+
+ :param Symbol sym: the symbol to define
+ :rtype: None
+ """
+ if platform is None:
+ platform = self.platform
+ if platform is not None:
+ platform = platform.handle
+ if sym_type is not None:
+ sym_type = sym_type.handle
+ core.BNDefineAutoSymbolAndVariableOrFunction(self.handle, platform, sym.handle, sym_type)
+
def undefine_auto_symbol(self, sym):
"""
``undefine_auto_symbol`` removes a symbol from the internal list of automatically discovered Symbol objects.
@@ -2868,7 +3008,7 @@ class BinaryView(object):
result = []
for i in xrange(0, count.value):
result.append(StringReference(core.BNStringType_names[strings[i].type], strings[i].start, strings[i].length))
- core.BNFreeStringList(strings)
+ core.BNFreeStringReferenceList(strings)
return result
def add_analysis_completion_event(self, callback):
@@ -3387,6 +3527,73 @@ class BinaryView(object):
return None
return value.value
+ def add_auto_segment(self, start, length, data_offset, data_length, flags):
+ core.BNAddAutoSegment(self.handle, start, length, data_offset, data_length, flags)
+
+ def remove_auto_segment(self, start, length):
+ core.BNRemoveAutoSegment(self.handle, start, length)
+
+ def add_user_segment(self, start, length, data_offset, data_length, flags):
+ core.BNAddUserSegment(self.handle, start, length, data_offset, data_length, flags)
+
+ def remove_user_segment(self, start, length):
+ core.BNRemoveUserSegment(self.handle, start, length)
+
+ def get_segment_at(self, addr):
+ segment = core.BNSegment()
+ if not core.BNGetSegmentAt(self.handle, addr, segment):
+ return None
+ result = Segment(segment.start, segment.length, segment.dataOffset, segment.dataLength,
+ segment.flags)
+ return result
+
+ def add_auto_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "",
+ info_section = "", info_data = 0):
+ core.BNAddAutoSection(self.handle, name, start, length, type, align, entry_size, linked_section,
+ info_section, info_data)
+
+ def remove_auto_section(self, name):
+ core.BNRemoveAutoSection(self.handle, name)
+
+ def add_user_section(self, name, start, length, type = "", align = 1, entry_size = 1, linked_section = "",
+ info_section = "", info_data = 0):
+ core.BNAddUserSection(self.handle, name, start, length, type, align, entry_size, linked_section,
+ info_section, info_data)
+
+ def remove_user_section(self, name):
+ core.BNRemoveUserSection(self.handle, name)
+
+ def get_sections_at(self, addr):
+ count = ctypes.c_ulonglong(0)
+ section_list = core.BNGetSectionsAt(self.handle, addr, count)
+ result = []
+ for i in xrange(0, count.value):
+ result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start,
+ section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection,
+ section_list[i].infoData, section_list[i].align, section_list[i].entrySize))
+ core.BNFreeSectionList(section_list, count.value)
+ return result
+
+ def get_section_by_name(self, name):
+ section = core.BNSection()
+ if not core.BNGetSectionByName(self.handle, name, section):
+ return None
+ result = Section(section.name, section.type, section.start, section.length, section.linkedSection,
+ section.infoSection, section.infoData, section.align, section.entrySize)
+ core.BNFreeSection(section)
+ return result
+
+ def get_unique_section_names(self, name_list):
+ incoming_names = (ctypes.c_char_p * len(name_list))()
+ for i in xrange(0, len(name_list)):
+ incoming_names[i] = name_list[i]
+ outgoing_names = core.BNGetUniqueSectionNames(self.handle, incoming_names, len(name_list))
+ result = []
+ for i in xrange(0, len(name_list)):
+ result.append(str(outgoing_names[i]))
+ core.BNFreeStringList(outgoing_names, len(name_list))
+ return result
+
def __setattr__(self, name, value):
try:
object.__setattr__(self,name,value)
@@ -3799,7 +4006,7 @@ class BinaryWriter(object):
def write16(self, value):
"""
- ```` writes the lowest order two bytes from the integer ``value`` to the current offset, using internal endianness.
+ ``write16`` writes the lowest order two bytes from the integer ``value`` to the current offset, using internal endianness.
:param int value: integer value to write.
:return: boolean True on success, False on failure.
@@ -3809,7 +4016,7 @@ class BinaryWriter(object):
def write32(self, value):
"""
- ```` writes the lowest order four bytes from the integer ``value`` to the current offset, using internal endianness.
+ ``write32`` writes the lowest order four bytes from the integer ``value`` to the current offset, using internal endianness.
:param int value: integer value to write.
:return: boolean True on success, False on failure.
@@ -3819,7 +4026,7 @@ class BinaryWriter(object):
def write64(self, value):
"""
- ```` writes the lowest order eight bytes from the integer ``value`` to the current offset, using internal endianness.
+ ``write64`` writes the lowest order eight bytes from the integer ``value`` to the current offset, using internal endianness.
:param int value: integer value to write.
:return: boolean True on success, False on failure.
@@ -4135,14 +4342,16 @@ class Type(object):
return Type(core.BNCreateBoolType())
@classmethod
- def int(self, width, sign = True):
+ def int(self, width, sign = True, altname = ""):
"""
``int`` class method for creating an int Type.
:param int width: width of the integer in bytes
:param bool sign: optional variable representing signedness
+ :param str altname: optional name of integer type
"""
- return Type(core.BNCreateIntegerType(width, sign))
+ return Type(core.BNCreateIntegerType(width, sign,
+ ctypes.create_string_buffer(altname)))
@classmethod
def float(self, width):
@@ -4157,6 +4366,10 @@ class Type(object):
return Type(core.BNCreateUnknownType(unknown_type.handle))
@classmethod
+ def unknown_type(self, s):
+ return Type(core.BNCreateUnknownType(s.handle))
+
+ @classmethod
def enumeration_type(self, arch, e, width = None):
if width is None:
width = arch.default_int_size
@@ -4174,12 +4387,12 @@ class Type(object):
def function(self, ret, params, calling_convention = None, variable_arguments = False):
"""
``function`` class method for creating an function Type.
-
+
:param Type ret: width of the integer in bytes
:param list(Type) params: list of parameter Types
:param CallingConvention calling_convention: optional argument for function calling convention
:param bool variable_arguments: optional argument for functions that have a variable number of arguments
-
+
"""
param_buf = (core.BNNameAndType * len(params))()
for i in xrange(0, len(params)):
@@ -4631,6 +4844,14 @@ class Function(object):
return Architecture(arch)
@property
+ def platform(self):
+ """Function platform (read-only)"""
+ platform = core.BNGetFunctionPlatform(self.handle)
+ if platform is None:
+ return None
+ return Platform(None, handle = platform)
+
+ @property
def start(self):
"""Function start (read-only)"""
return core.BNGetFunctionStart(self.handle)
@@ -5281,7 +5502,7 @@ class FunctionGraphBlock(object):
core.BNFreeBasicBlock(block)
block = None
else:
- block = BasicBlock(BinaryView(None, handle = core.BNGetFunctionData(func)), block)
+ block = BasicBlock(BinaryView(handle = core.BNGetFunctionData(func)), block)
core.BNFreeFunction(func)
return block
@@ -5853,6 +6074,8 @@ class Architecture(object):
self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size)
self._cb.getMaxInstructionLength = self._cb.getMaxInstructionLength.__class__(self._get_max_instruction_length)
self._cb.getOpcodeDisplayLength = self._cb.getOpcodeDisplayLength.__class__(self._get_opcode_display_length)
+ self._cb.getAssociatedArchitectureByAddress = self._cb.getAssociatedArchitectureByAddress.__class__(
+ self._get_associated_arch_by_address)
self._cb.getInstructionInfo = self._cb.getInstructionInfo.__class__(self._get_instruction_info)
self._cb.getInstructionText = self._cb.getInstructionText.__class__(self._get_instruction_text)
self._cb.freeInstructionText = self._cb.freeInstructionText.__class__(self._free_instruction_text)
@@ -6042,6 +6265,15 @@ class Architecture(object):
log_error(traceback.format_exc())
return 8
+ def _get_associated_arch_by_address(self, ctxt, addr):
+ try:
+ result, new_addr = self.perform_get_associated_arch_by_address(addr[0])
+ addr[0] = new_addr
+ return ctypes.cast(result.handle, ctypes.c_void_p).value
+ except:
+ log_error(traceback.format_exc())
+ return ctypes.cast(self.handle, ctypes.c_void_p).value
+
def _get_instruction_info(self, ctxt, data, addr, max_len, result):
try:
buf = ctypes.create_string_buffer(max_len)
@@ -6451,6 +6683,9 @@ class Architecture(object):
log_error(traceback.format_exc())
return False
+ def perform_get_associated_arch_by_address(self, addr):
+ return self, addr
+
@abc.abstractmethod
def perform_get_instruction_info(self, data, addr):
"""
@@ -6701,6 +6936,12 @@ class Architecture(object):
"""
return None
+ def get_associated_arch_by_address(self, addr):
+ new_addr = ctypes.c_ulonglong()
+ new_addr.value = addr
+ result = core.BNGetAssociatedArchitectureByAddress(self.handle, new_addr)
+ return Architecture(handle = result), new_addr.value
+
def get_instruction_info(self, data, addr):
"""
``get_instruction_info`` returns an InstructionInfo object for the instruction at the given virtual address
@@ -8133,16 +8374,17 @@ class LowLevelILFunction(object):
"""
return self.expr(core.LLIL_NOT, value.index, size = size, flags = flags)
- def sign_extend(self, size, value):
+ def sign_extend(self, size, value, flags = None):
"""
``sign_extend`` two's complement sign-extends the expression in ``value`` to ``size`` bytes
:param int size: the size of the result in bytes
:param LowLevelILExpr value: the expression to sign extend
+ :param str flags: optional, flags to set
:return: The expression ``sx.<size>(value)``
:rtype: LowLevelILExpr
"""
- return self.expr(core.LLIL_SX, value.index, size = size)
+ return self.expr(core.LLIL_SX, value.index, size = size, flags = flags)
def zero_extend(self, size, value):
"""
@@ -8734,7 +8976,7 @@ class FunctionRecognizer(object):
def _recognize_low_level_il(self, ctxt, data, func, il):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(data))
- view = BinaryView(file_metadata, handle = core.BNNewViewReference(data))
+ view = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data))
func = Function(view, handle = core.BNNewFunctionReference(func))
il = LowLevelILFunction(func.arch, handle = core.BNNewLowLevelILFunctionReference(il))
return self.recognize_low_level_il(view, func, il)
@@ -8971,7 +9213,7 @@ class PluginCommand:
def _default_action(cls, view, action):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
action(view_obj)
except:
log_error(traceback.format_exc())
@@ -8980,7 +9222,7 @@ class PluginCommand:
def _address_action(cls, view, addr, action):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
action(view_obj, addr)
except:
log_error(traceback.format_exc())
@@ -8989,7 +9231,7 @@ class PluginCommand:
def _range_action(cls, view, addr, length, action):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
action(view_obj, addr, length)
except:
log_error(traceback.format_exc())
@@ -8998,7 +9240,7 @@ class PluginCommand:
def _function_action(cls, view, func, action):
try:
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
func_obj = Function(view_obj, core.BNNewFunctionReference(func))
action(view_obj, func_obj)
except:
@@ -9010,7 +9252,7 @@ class PluginCommand:
if is_valid is None:
return True
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
return is_valid(view_obj)
except:
log_error(traceback.format_exc())
@@ -9022,7 +9264,7 @@ class PluginCommand:
if is_valid is None:
return True
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
return is_valid(view_obj, addr)
except:
log_error(traceback.format_exc())
@@ -9034,7 +9276,7 @@ class PluginCommand:
if is_valid is None:
return True
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
return is_valid(view_obj, addr, length)
except:
log_error(traceback.format_exc())
@@ -9046,7 +9288,7 @@ class PluginCommand:
if is_valid is None:
return True
file_metadata = FileMetadata(handle = core.BNGetFileForView(view))
- view_obj = BinaryView(file_metadata, handle = core.BNNewViewReference(view))
+ view_obj = BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view))
func_obj = Function(view_obj, core.BNNewFunctionReference(func))
return is_valid(view_obj, func_obj)
except:
@@ -9535,6 +9777,21 @@ class Platform(object):
"""
core.BNRegisterPlatformCallingConvention(self.handle, cc.handle)
+ def get_related_platform(self, arch):
+ result = core.BNGetRelatedPlatform(self.handle, arch.handle)
+ if not result:
+ return None
+ return Platform(None, handle = result)
+
+ def add_related_platform(self, arch, platform):
+ core.BNAddRelatedPlatform(self.handle, arch.handle, platform.handle)
+
+ def get_associated_platform_by_address(self, addr):
+ new_addr = ctypes.c_ulonglong()
+ new_addr.value = addr
+ result = core.BNGetAssociatedPlatformByAddress(self.handle, new_addr)
+ return Platform(None, handle = result), new_addr.value
+
class ScriptingOutputListener(object):
def _register(self, handle):
self._cb = core.BNScriptingOutputListener()
@@ -9610,7 +9867,7 @@ class ScriptingInstance(object):
def _set_current_binary_view(self, ctxt, view):
try:
if view:
- view = BinaryView(None, handle = core.BNNewViewReference(view))
+ view = BinaryView(handle = core.BNNewViewReference(view))
else:
view = None
self.perform_set_current_binary_view(view)
@@ -9620,7 +9877,7 @@ class ScriptingInstance(object):
def _set_current_function(self, ctxt, func):
try:
if func:
- func = Function(BinaryView(None, handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func))
+ func = Function(BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func))
else:
func = None
self.perform_set_current_function(func)
@@ -9634,7 +9891,7 @@ class ScriptingInstance(object):
if func is None:
block = None
else:
- block = BasicBlock(BinaryView(None, handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block))
+ block = BasicBlock(BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block))
core.BNFreeFunction(func)
else:
block = None
@@ -10384,7 +10641,7 @@ class InteractionHandler(object):
def _show_plain_text_report(self, ctxt, view, title, contents):
try:
if view:
- view = BinaryView(None, handle = core.BNNewViewReference(view))
+ view = BinaryView(handle = core.BNNewViewReference(view))
else:
view = None
self.show_plain_text_report(view, title, contents)
@@ -10394,7 +10651,7 @@ class InteractionHandler(object):
def _show_markdown_report(self, ctxt, view, title, contents, plaintext):
try:
if view:
- view = BinaryView(None, handle = core.BNNewViewReference(view))
+ view = BinaryView(handle = core.BNNewViewReference(view))
else:
view = None
self.show_markdown_report(view, title, contents, plaintext)
@@ -10404,7 +10661,7 @@ class InteractionHandler(object):
def _show_html_report(self, ctxt, view, title, contents, plaintext):
try:
if view:
- view = BinaryView(None, handle = core.BNNewViewReference(view))
+ view = BinaryView(handle = core.BNNewViewReference(view))
else:
view = None
self.show_html_report(view, title, contents, plaintext)
@@ -10434,7 +10691,7 @@ class InteractionHandler(object):
def _get_address_input(self, ctxt, result, prompt, title, view, current_address):
try:
if view:
- view = BinaryView(None, handle = core.BNNewViewReference(view))
+ view = BinaryView(handle = core.BNNewViewReference(view))
else:
view = None
value = self.get_address_input(prompt, title, view, current_address)
@@ -10505,7 +10762,7 @@ class InteractionHandler(object):
elif fields[i].type == core.AddressFormField:
view = None
if fields[i].view:
- view = BinaryView(None, handle = core.BNNewViewReference(fields[i].view))
+ view = BinaryView(handle = core.BNNewViewReference(fields[i].view))
field_objs.append(AddressField(fields[i].prompt, view, fields[i].currentAddress))
elif fields[i].type == core.ChoiceFormField:
choices = []
@@ -10854,6 +11111,21 @@ def demangle_ms(arch, mangled_name):
names.append(outName[i])
#core.BNFreeDemangledName(outName.value, outSize.value)
return (Type(handle), names)
+ return (None, mangledName)
+
+
+def demangle_gnu3(arch, mangled_name):
+ handle = ctypes.POINTER(core.BNType)()
+ outName = ctypes.POINTER(ctypes.c_char_p)()
+ outSize = ctypes.c_ulonglong()
+ names = []
+ if core.BNDemangleGNU3(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)):
+ for i in xrange(outSize.value):
+ names.append(outName[i])
+ #core.BNFreeDemangledName(outName.value, outSize.value)
+ if not handle:
+ return (None, names)
+ return (Type(handle), names)
return (None, mangled_name)
diff --git a/python/examples/nds.py b/python/examples/nds.py
new file mode 100644
index 00000000..5300018c
--- /dev/null
+++ b/python/examples/nds.py
@@ -0,0 +1,88 @@
+from binaryninja import *
+import struct
+import traceback
+import os
+
+def crc16(data):
+ crc = 0xffff
+ for ch in data:
+ crc ^= ord(ch)
+ for bit in xrange(0, 8):
+ if (crc & 1) == 1:
+ crc = (crc >> 1) ^ 0xa001
+ else:
+ crc >>= 1
+ return crc
+
+class DSView(BinaryView):
+ def __init__(self, data):
+ BinaryView.__init__(self, file_metadata = data.file, parent_view = data)
+ self.raw = data
+
+ @classmethod
+ def is_valid_for_data(self, data):
+ hdr = data.read(0, 0x160)
+ if len(hdr) < 0x160:
+ return False
+ if struct.unpack("<H", hdr[0x15e:0x160])[0] != crc16(hdr[0:0x15e]):
+ return False
+ if struct.unpack("<H", hdr[0x15c:0x15e])[0] != crc16(hdr[0xc0:0x15c]):
+ return False
+ return True
+
+ def init_common(self):
+ self.platform = Architecture["armv7"].standalone_platform
+ self.hdr = self.raw.read(0, 0x160)
+
+ def init_arm9(self):
+ try:
+ self.init_common()
+ self.arm9_offset = struct.unpack("<L", self.hdr[0x20:0x24])[0]
+ self.arm_entry_addr = struct.unpack("<L", self.hdr[0x24:0x28])[0]
+ self.arm9_load_addr = struct.unpack("<L", self.hdr[0x28:0x2C])[0]
+ self.arm9_size = struct.unpack("<L", self.hdr[0x2C:0x30])[0]
+ self.add_auto_segment(self.arm9_load_addr, self.arm9_size, self.arm9_offset, self.arm9_size,
+ SegmentReadable | SegmentExecutable)
+ self.add_entry_point(Architecture['armv7'].standalone_platform, self.arm_entry_addr)
+ return True
+ except:
+ log_error(traceback.format_exc())
+ return False
+
+ def init_arm7(self):
+ try:
+ self.init_common()
+ self.arm7_offset = struct.unpack("<L", self.hdr[0x30:0x34])[0]
+ self.arm_entry_addr = struct.unpack("<L", self.hdr[0x34:0x38])[0]
+ self.arm7_load_addr = struct.unpack("<L", self.hdr[0x38:0x3C])[0]
+ self.arm7_size = struct.unpack("<L", self.hdr[0x3C:0x40])[0]
+ self.add_auto_segment(self.arm7_load_addr, self.arm7_size, self.arm7_offset, self.arm7_size,
+ SegmentReadable | SegmentExecutable)
+ self.add_entry_point(Architecture['armv7'].standalone_platform, self.arm_entry_addr)
+ return True
+ except:
+ log_error(traceback.format_exc())
+ return False
+
+ def perform_is_executable(self):
+ return True
+
+ def perform_get_entry_point(self):
+ return self.arm_entry_addr
+
+class DSARM9View(DSView):
+ name = "DSARM9"
+ long_name = "DS ARM9 ROM"
+
+ def init(self):
+ return self.init_arm9()
+
+class DSARM7View(DSView):
+ name = "DSARM7"
+ long_name = "DS ARM7 ROM"
+
+ def init(self):
+ return self.init_arm7()
+
+DSARM9View.register()
+DSARM7View.register()
diff --git a/python/examples/nes.py b/python/examples/nes.py
index 00f9d8eb..23f5f3d8 100644
--- a/python/examples/nes.py
+++ b/python/examples/nes.py
@@ -488,42 +488,12 @@ class M6502(Architecture):
return None
return "\xa9" + chr(value & 0xff) + "\xea"
-class NESViewUpdateNotification(BinaryDataNotification):
- def __init__(self, view):
- self.view = view
-
- def data_written(self, view, offset, length):
- addr = offset - self.view.rom_offset
- while length > 0:
- bank_ofs = addr & 0x3fff
- if (bank_ofs + length) > 0x4000:
- to_read = 0x4000 - bank_ofs
- else:
- to_read = length
- if length < to_read:
- to_read = length
- if (addr >= (bank_ofs + (self.view.__class__.bank * 0x4000))) and (addr < (bank_ofs + ((self.view.__class__.bank + 1) * 0x4000))):
- self.view.notify_data_written(0x8000 + bank_ofs, to_read)
- elif (addr >= (bank_ofs + (self.view.rom_length - 0x4000))) and (addr < (bank_ofs + self.view.rom_length)):
- self.view.notify_data_written(0xc000 + bank_ofs, to_read)
- length -= to_read
- addr += to_read
-
- def data_inserted(self, view, offset, length):
- self.view.notify_data_written(0x8000, 0x8000)
-
- def data_removed(self, view, offset, length):
- self.view.notify_data_written(0x8000, 0x8000)
-
class NESView(BinaryView):
name = "NES"
long_name = "NES ROM"
def __init__(self, data):
- BinaryView.__init__(self, data.file)
- self.raw = data
- self.notification = NESViewUpdateNotification(self)
- self.raw.register_notification(self.notification)
+ BinaryView.__init__(self, parent_view = data, file_metadata = data.file)
@classmethod
def is_valid_for_data(self, data):
@@ -539,7 +509,7 @@ class NESView(BinaryView):
def init(self):
try:
- hdr = self.raw.read(0, 16)
+ hdr = self.parent_view.read(0, 16)
self.rom_banks = struct.unpack("B", hdr[4])[0]
self.vrom_banks = struct.unpack("B", hdr[5])[0]
self.rom_flags = struct.unpack("B", hdr[6])[0]
@@ -550,6 +520,15 @@ class NESView(BinaryView):
self.rom_offset += 512
self.rom_length = self.rom_banks * 0x4000
+ # Add mapping for RAM and hardware registers, not backed by file contents
+ self.add_auto_segment(0, 0x8000, 0, 0, SegmentReadable | SegmentWritable | SegmentExecutable)
+
+ # Add ROM mappings
+ self.add_auto_segment(0x8000, 0x4000, self.rom_offset + (self.__class__.bank * 0x4000), 0x4000,
+ SegmentReadable | SegmentExecutable)
+ self.add_auto_segment(0xc000, 0x4000, self.rom_offset + self.rom_length - 0x4000, 0x4000,
+ SegmentReadable | SegmentExecutable)
+
nmi = struct.unpack("<H", self.read(0xfffa, 2))[0]
start = struct.unpack("<H", self.read(0xfffc, 2))[0]
irq = struct.unpack("<H", self.read(0xfffe, 2))[0]
@@ -592,9 +571,9 @@ class NESView(BinaryView):
self.define_auto_symbol(Symbol(DataSymbol, 0x4016, "JOY1"))
self.define_auto_symbol(Symbol(DataSymbol, 0x4017, "JOY2"))
- sym_files = [self.raw.file.filename + ".%x.nl" % self.__class__.bank,
- self.raw.file.filename + ".ram.nl",
- self.raw.file.filename + ".%x.nl" % (self.rom_banks - 1)]
+ sym_files = [self.file.filename + ".%x.nl" % self.__class__.bank,
+ self.file.filename + ".ram.nl",
+ self.file.filename + ".%x.nl" % (self.rom_banks - 1)]
for f in sym_files:
if os.path.exists(f):
sym_contents = open(f, "r").read()
@@ -614,71 +593,6 @@ class NESView(BinaryView):
log_error(traceback.format_exc())
return False
- def perform_is_valid_offset(self, addr):
- if (addr >= 0x8000) and (addr < 0x10000):
- return True
- return False
-
- def perform_read(self, addr, length):
- if addr < 0x8000:
- return None
- if addr >= (0x8000 + self.rom_length):
- return None
- if (addr + length) > 0x10000:
- length = 0x10000 - addr
- result = ""
- while length > 0:
- bank_ofs = addr & 0x3fff
- if (bank_ofs + length) > 0x4000:
- to_read = 0x4000 - bank_ofs
- else:
- to_read = length
- if addr < 0xc000:
- data = self.raw.read(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), to_read)
- else:
- data = self.raw.read(self.rom_offset + bank_ofs + self.rom_length - 0x4000, to_read)
- result += data
- if len(data) < to_read:
- break
- length -= to_read
- addr += to_read
- return result
-
- def perform_write(self, addr, value):
- if addr < 0x8000:
- return 0
- if addr >= (0x8000 + self.rom_length):
- return 0
- if (addr + len(value)) > (0x8000 + self.rom_length):
- length = (0x8000 + self.rom_length) - addr
- else:
- length = len(value)
- if (addr + length) > 0x10000:
- length = 0x10000 - addr
- offset = 0
- while length > 0:
- bank_ofs = addr & 0x3fff
- if (bank_ofs + length) > 0x4000:
- to_write = 0x4000 - bank_ofs
- else:
- to_write = length
- if addr < 0xc000:
- written = self.raw.write(self.rom_offset + bank_ofs + (self.__class__.bank * 0x4000), value[offset : offset + to_write])
- else:
- written = self.raw.write(self.rom_offset + bank_ofs + self.rom_length - 0x4000, value[offset : offset + to_write])
- if written < to_write:
- break
- length -= to_write
- addr += to_write
- offset += to_write
- return offset
-
- def perform_get_start(self):
- return 0
-
- def perform_get_length(self):
- return 0x10000
-
def perform_is_executable(self):
return True
diff --git a/python/examples/nsf.py b/python/examples/nsf.py
new file mode 100644
index 00000000..9d4ebd5c
--- /dev/null
+++ b/python/examples/nsf.py
@@ -0,0 +1,138 @@
+# Copyright (c) 2015-2016 Vector 35 LLC
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+#
+#
+# Simple NSF file loader, primarily for analyzing:
+# https://scarybeastsecurity.blogspot.com/2016/11/0day-exploit-compromising-linux-desktop.html
+#
+
+from binaryninja import *
+import struct
+import traceback
+import os
+
+class NSFView(BinaryView):
+ name = "NSF"
+ long_name = "Nintendo Sound Format"
+
+ def __init__(self, data):
+ BinaryView.__init__(self, parent_view = data, file_metadata = data.file)
+
+ @classmethod
+ def is_valid_for_data(self, data):
+ hdr = data.read(0, 128)
+ if len(hdr) < 128:
+ return False
+ if hdr[0:5] != "NESM\x1a":
+ return False
+ song_count = struct.unpack("B", hdr[6])[0]
+ if song_count < 1:
+ log_info("Appears to be an NSF, but no songs.")
+ return False
+ return True
+
+ def init(self):
+ try:
+ hdr = self.parent_view.read(0, 128)
+ self.version = struct.unpack("B", hdr[5])[0]
+ self.song_count = struct.unpack("B", hdr[6])[0]
+ self.starting_song = struct.unpack("B", hdr[7])[0]
+ self.load_address = struct.unpack("<H", hdr[8:10])[0]
+ self.init_address = struct.unpack("<H", hdr[10:12])[0]
+ self.play_address = struct.unpack("<H", hdr[12:14])[0]
+ self.song_name = hdr[15].split('\0')[0]
+ self.artist_name = hdr[46].split('\0')[0]
+ self.copyright_name = hdr[78].split('\0')[0]
+ self.play_speed_ntsc = struct.unpack("<H", hdr[110:112])[0]
+ self.bank_switching = hdr[112:120]
+ self.play_speed_pal = struct.unpack("<H", hdr[120:122])[0]
+ self.pal_ntsc_bits = struct.unpack("B", hdr[122])[0]
+ self.pal = True if (self.pal_ntsc_bits & 1) == 1 else False
+ self.ntsc = not self.pal
+ if self.pal_ntsc_bits & 2 == 2:
+ self.pal = True
+ self.ntsc = True
+ self.extra_sound_bits = struct.unpack("B", hdr[123])[0]
+
+ if self.bank_switching == "\0"*8:
+ #no bank switching
+ self.load_address & 0xFFF
+ self.rom_offset = 128
+
+ else:
+ #bank switching not implemented
+ log_info("Bank switching not implemented in this loader.")
+
+ # Add mapping for RAM and hardware registers, not backed by file contents
+ self.add_auto_segment(0, 0x8000, 0, 0, SegmentReadable | SegmentWritable | SegmentExecutable)
+
+ # Add ROM mappings
+ self.add_auto_segment(0x8000, 0x4000, self.rom_offset, 0x4000,
+ SegmentReadable | SegmentExecutable)
+
+ self.define_auto_symbol(Symbol(FunctionSymbol, self.play_address, "_play"))
+ self.define_auto_symbol(Symbol(FunctionSymbol, self.init_address, "_init"))
+ self.add_entry_point(Architecture['6502'].standalone_platform, self.init_address)
+ self.add_function(Architecture['6502'].standalone_platform, self.play_address)
+
+ # Hardware registers
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2000, "PPUCTRL"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2001, "PPUMASK"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2002, "PPUSTATUS"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2003, "OAMADDR"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2004, "OAMDATA"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2005, "PPUSCROLL"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2006, "PPUADDR"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x2007, "PPUDATA"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4000, "SQ1_VOL"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4001, "SQ1_SWEEP"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4002, "SQ1_LO"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4003, "SQ1_HI"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4004, "SQ2_VOL"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4005, "SQ2_SWEEP"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4006, "SQ2_LO"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4007, "SQ2_HI"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4008, "TRI_LINEAR"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x400a, "TRI_LO"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x400b, "TRI_HI"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x400c, "NOISE_VOL"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x400e, "NOISE_LO"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x400f, "NOISE_HI"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4010, "DMC_FREQ"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4011, "DMC_RAW"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4012, "DMC_START"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4013, "DMC_LEN"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4014, "OAMDMA"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4015, "SND_CHN"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4016, "JOY1"))
+ self.define_auto_symbol(Symbol(DataSymbol, 0x4017, "JOY2"))
+
+ return True
+ except:
+ log_error(traceback.format_exc())
+ return False
+
+ def perform_is_executable(self):
+ return True
+
+ def perform_get_entry_point(self):
+ return struct.unpack("<H", str(self.perform_read(0x0a, 2)))[0]
+
+NSFView.register()
diff --git a/type.cpp b/type.cpp
index 34e142b6..e0235664 100644
--- a/type.cpp
+++ b/type.cpp
@@ -235,6 +235,12 @@ Ref<Type> Type::StructureType(Structure* strct)
}
+Ref<Type> Type::UnknownNamedType(UnknownType* unknwn)
+{
+ return new Type(BNCreateUnknownNamedType(unknwn->GetObject()));
+}
+
+
Ref<Type> Type::EnumerationType(Architecture* arch, Enumeration* enm, size_t width, bool isSigned)
{
return new Type(BNCreateEnumerationType(arch->GetObject(), enm->GetObject(), width, isSigned));
@@ -277,6 +283,46 @@ void Type::SetFunctionCanReturn(bool canReturn)
}
+UnknownType::UnknownType(BNUnknownType* ut, vector<string> names)
+{
+ m_object = ut;
+ const char ** nameList = new const char*[names.size()];
+ for (size_t i = 0; i < names.size(); i++)
+ {
+ nameList[i] = names[i].c_str();
+ }
+ BNSetUnknownTypeName(ut, nameList, names.size());
+ delete [] nameList;
+}
+
+
+void UnknownType::SetName(const vector<string>& names)
+{
+ const char ** nameList = new const char*[names.size()];
+ for (size_t i = 0; i < names.size(); i++)
+ {
+ nameList[i] = names[i].c_str();
+ }
+ BNSetUnknownTypeName(m_object, nameList, names.size());
+ delete [] nameList;
+}
+
+
+vector<string> UnknownType::GetName() const
+{
+ size_t size;
+ char** name = BNGetUnknownTypeName(m_object, &size);
+ vector<string> result;
+ for (size_t i = 0; i < size; i++)
+ {
+ result.push_back(name[i]);
+ BNFreeString(name[i]);
+ }
+ delete [] name;
+ return result;
+}
+
+
Structure::Structure(BNStructure* s)
{
m_object = s;