From c4d8b6f18c094d98df4448bdaf14faa86b33cc86 Mon Sep 17 00:00:00 2001 From: Matt Revelle Date: Wed, 8 Nov 2017 11:18:03 -0500 Subject: Cache arch and platform property values (#862) * Added __hash__ impl for BasicBlock instances. * Removed too specific __hash__ impl. * Cache arch and platform property values. --- python/function.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index f8aaae44..bec3c2ad 100644 --- a/python/function.py +++ b/python/function.py @@ -307,6 +307,8 @@ class Function(object): self._view = view self.handle = core.handle_of_type(handle, core.BNFunction) self._advanced_analysis_requests = 0 + self._arch = None + self._platform = None def __del__(self): if self._advanced_analysis_requests > 0: @@ -358,18 +360,26 @@ class Function(object): @property def arch(self): """Function architecture (read-only)""" - arch = core.BNGetFunctionArchitecture(self.handle) - if arch is None: - return None - return architecture.Architecture(arch) + if self._arch: + return self._arch + else: + arch = core.BNGetFunctionArchitecture(self.handle) + if arch is None: + return None + self._arch = architecture.Architecture(arch) + return self._arch @property def platform(self): """Function platform (read-only)""" - plat = core.BNGetFunctionPlatform(self.handle) - if plat is None: - return None - return platform.Platform(None, handle = plat) + if self._platform: + return self._platform + else: + plat = core.BNGetFunctionPlatform(self.handle) + if plat is None: + return None + self._platform = plat + return platform.Platform(None, handle = plat) @property def start(self): -- cgit v1.3.1 From 382b1353649472bc2088598b3b8b60c096c1e201 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 10 Nov 2017 17:42:28 -0500 Subject: Add 'relocatable' property to BinaryView class --- binaryninjaapi.h | 3 +++ binaryninjacore.h | 2 ++ binaryview.cpp | 19 +++++++++++++++++++ python/binaryview.py | 26 ++++++++++++++++++++++++++ 4 files changed, 50 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index a6276b00..5f3aace7 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1088,6 +1088,7 @@ namespace BinaryNinja virtual uint64_t PerformGetEntryPoint() const { return 0; } virtual bool PerformIsExecutable() const { return false; } virtual BNEndianness PerformGetDefaultEndianness() const; + virtual bool PerformIsRelocatable() const; virtual size_t PerformGetAddressSize() const; virtual bool PerformSave(FileAccessor* file); @@ -1115,6 +1116,7 @@ namespace BinaryNinja static uint64_t GetEntryPointCallback(void* ctxt); static bool IsExecutableCallback(void* ctxt); static BNEndianness GetDefaultEndiannessCallback(void* ctxt); + static bool IsRelocatableCallback(void* ctxt); static size_t GetAddressSizeCallback(void* ctxt); static bool SaveCallback(void* ctxt, BNFileAccessor* file); @@ -1181,6 +1183,7 @@ namespace BinaryNinja void SetDefaultPlatform(Platform* platform); BNEndianness GetDefaultEndianness() const; + bool IsRelocatable() const; size_t GetAddressSize() const; bool IsExecutable() const; diff --git a/binaryninjacore.h b/binaryninjacore.h index 870c2de3..45e6310c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -935,6 +935,7 @@ extern "C" uint64_t (*getEntryPoint)(void* ctxt); bool (*isExecutable)(void* ctxt); BNEndianness (*getDefaultEndianness)(void* ctxt); + bool (*isRelocatable)(void* ctxt); size_t (*getAddressSize)(void* ctxt); bool (*save)(void* ctxt, BNFileAccessor* accessor); }; @@ -1777,6 +1778,7 @@ extern "C" BINARYNINJACOREAPI BNPlatform* BNGetDefaultPlatform(BNBinaryView* view); BINARYNINJACOREAPI void BNSetDefaultPlatform(BNBinaryView* view, BNPlatform* platform); BINARYNINJACOREAPI BNEndianness BNGetDefaultEndianness(BNBinaryView* view); + BINARYNINJACOREAPI bool BNIsRelocatable(BNBinaryView* view); BINARYNINJACOREAPI size_t BNGetViewAddressSize(BNBinaryView* view); BINARYNINJACOREAPI bool BNIsViewModified(BNBinaryView* view); diff --git a/binaryview.cpp b/binaryview.cpp index 213be79a..0a082458 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -288,6 +288,7 @@ BinaryView::BinaryView(const std::string& typeName, FileMetadata* file, BinaryVi view.getEntryPoint = GetEntryPointCallback; view.isExecutable = IsExecutableCallback; view.getDefaultEndianness = GetDefaultEndiannessCallback; + view.isRelocatable = IsRelocatableCallback; view.getAddressSize = GetAddressSizeCallback; view.save = SaveCallback; @@ -431,6 +432,13 @@ BNEndianness BinaryView::GetDefaultEndiannessCallback(void* ctxt) } +bool BinaryView::IsRelocatableCallback(void* ctxt) +{ + BinaryView* view = (BinaryView*)ctxt; + return view->PerformIsRelocatable(); +} + + size_t BinaryView::GetAddressSizeCallback(void* ctxt) { BinaryView* view = (BinaryView*)ctxt; @@ -494,6 +502,11 @@ BNEndianness BinaryView::PerformGetDefaultEndianness() const } +bool BinaryView::PerformIsRelocatable() const +{ + return false; +} + size_t BinaryView::PerformGetAddressSize() const { Ref arch = GetDefaultArchitecture(); @@ -836,6 +849,12 @@ BNEndianness BinaryView::GetDefaultEndianness() const } +bool BinaryView::IsRelocatable() const +{ + return BNIsRelocatable(m_object); +} + + size_t BinaryView::GetAddressSize() const { return BNGetViewAddressSize(m_object); diff --git a/python/binaryview.py b/python/binaryview.py index e6cb5b04..9f149ba8 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -583,6 +583,7 @@ class BinaryView(object): self._cb.getEntryPoint = self._cb.getEntryPoint.__class__(self._get_entry_point) self._cb.isExecutable = self._cb.isExecutable.__class__(self._is_executable) self._cb.getDefaultEndianness = self._cb.getDefaultEndianness.__class__(self._get_default_endianness) + self._cb.isRelocatable = self._cb.isRelocatable.__class__(self._is_relocatable) self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) self._cb.save = self._cb.save.__class__(self._save) self.file = file_metadata @@ -838,6 +839,11 @@ class BinaryView(object): """Endianness of the binary (read-only)""" return Endianness(core.BNGetDefaultEndianness(self.handle)) + @property + def relocatable(self): + """Boolean - is the binary relocatable (read-only)""" + return core.BNIsRelocatable(self.handle) + @property def address_size(self): """Address size of the binary (read-only)""" @@ -1202,6 +1208,13 @@ class BinaryView(object): log.log_error(traceback.format_exc()) return Endianness.LittleEndian + def _is_relocatable(self, ctxt): + try: + return self.perform_is_relocatable() + except: + log.log_error(traceback.format_exc()) + return False + def _get_address_size(self, ctxt): try: return self.perform_get_address_size() @@ -1494,6 +1507,19 @@ class BinaryView(object): """ return Endianness.LittleEndian + def perform_is_relocatable(self): + """ + ``perform_is_relocatable`` implements a check which returns true if the BinaryView is relocatable. Defaults to + True. + + .. note:: This method **may** be implemented for custom BinaryViews that are relocatable. + .. warning:: This method **must not** be called directly. + + :return: True if the BinaryView is relocatable, False otherwise + :rtype: boolean + """ + return True + def create_database(self, filename, progress_func=None): """ ``create_database`` writes the current database (.bndb) file out to the specified file. -- cgit v1.3.1 From 0cff612e91e59a343fad898daa6fa51ab525a789 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 13 Nov 2017 17:09:13 -0500 Subject: Add GetInstructionAlignment Callback to Architecture. --- architecture.cpp | 20 ++++++++++++++++++++ binaryninjaapi.h | 3 +++ binaryninjacore.h | 2 ++ examples/x86_extension/src/x86_extension.cpp | 5 +++++ python/architecture.py | 13 ++++++++++++- python/examples/nes.py | 1 + 6 files changed, 43 insertions(+), 1 deletion(-) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index eb588394..17d02909 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -111,6 +111,13 @@ size_t Architecture::GetDefaultIntegerSizeCallback(void* ctxt) } +size_t Architecture::GetInstructionAlignmentCallback(void* ctxt) +{ + Architecture* arch = (Architecture*)ctxt; + return arch->GetInstructionAlignment(); +} + + size_t Architecture::GetMaxInstructionLengthCallback(void* ctxt) { Architecture* arch = (Architecture*)ctxt; @@ -443,6 +450,7 @@ void Architecture::Register(Architecture* arch) callbacks.getEndianness = GetEndiannessCallback; callbacks.getAddressSize = GetAddressSizeCallback; callbacks.getDefaultIntegerSize = GetDefaultIntegerSizeCallback; + callbacks.getInstructionAlignment = GetInstructionAlignmentCallback; callbacks.getMaxInstructionLength = GetMaxInstructionLengthCallback; callbacks.getOpcodeDisplayLength = GetOpcodeDisplayLengthCallback; callbacks.getAssociatedArchitectureByAddress = GetAssociatedArchitectureByAddressCallback; @@ -523,6 +531,12 @@ size_t Architecture::GetDefaultIntegerSize() const } +size_t Architecture::GetInstructionAlignment() const +{ + return 1; +} + + size_t Architecture::GetMaxInstructionLength() const { return BN_DEFAULT_NSTRUCTION_LENGTH; @@ -905,6 +919,12 @@ size_t CoreArchitecture::GetDefaultIntegerSize() const } +size_t CoreArchitecture::GetInstructionAlignment() const +{ + return BNGetArchitectureInstructionAlignment(m_object); +} + + size_t CoreArchitecture::GetMaxInstructionLength() const { return BNGetArchitectureMaxInstructionLength(m_object); diff --git a/binaryninjaapi.h b/binaryninjaapi.h index 5f3aace7..4f62ef5f 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1585,6 +1585,7 @@ namespace BinaryNinja static BNEndianness GetEndiannessCallback(void* ctxt); static size_t GetAddressSizeCallback(void* ctxt); static size_t GetDefaultIntegerSizeCallback(void* ctxt); + static size_t GetInstructionAlignmentCallback(void* ctxt); static size_t GetMaxInstructionLengthCallback(void* ctxt); static size_t GetOpcodeDisplayLengthCallback(void* ctxt); static BNArchitecture* GetAssociatedArchitectureByAddressCallback(void* ctxt, uint64_t* addr); @@ -1640,6 +1641,7 @@ namespace BinaryNinja virtual size_t GetAddressSize() const = 0; virtual size_t GetDefaultIntegerSize() const; + virtual size_t GetInstructionAlignment() const; virtual size_t GetMaxInstructionLength() const; virtual size_t GetOpcodeDisplayLength() const; @@ -1780,6 +1782,7 @@ namespace BinaryNinja virtual BNEndianness GetEndianness() const override; virtual size_t GetAddressSize() const override; virtual size_t GetDefaultIntegerSize() const override; + virtual size_t GetInstructionAlignment() const override; virtual size_t GetMaxInstructionLength() const override; virtual size_t GetOpcodeDisplayLength() const override; virtual Ref GetAssociatedArchitectureByAddress(uint64_t& addr) override; diff --git a/binaryninjacore.h b/binaryninjacore.h index 45e6310c..cb99958c 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1003,6 +1003,7 @@ extern "C" BNEndianness (*getEndianness)(void* ctxt); size_t (*getAddressSize)(void* ctxt); size_t (*getDefaultIntegerSize)(void* ctxt); + size_t (*getInstructionAlignment)(void* ctxt); size_t (*getMaxInstructionLength)(void* ctxt); size_t (*getOpcodeDisplayLength)(void* ctxt); BNArchitecture* (*getAssociatedArchitectureByAddress)(void* ctxt, uint64_t* addr); @@ -1946,6 +1947,7 @@ extern "C" BINARYNINJACOREAPI BNEndianness BNGetArchitectureEndianness(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureAddressSize(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureDefaultIntegerSize(BNArchitecture* arch); + BINARYNINJACOREAPI size_t BNGetArchitectureInstructionAlignment(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureMaxInstructionLength(BNArchitecture* arch); BINARYNINJACOREAPI size_t BNGetArchitectureOpcodeDisplayLength(BNArchitecture* arch); BINARYNINJACOREAPI BNArchitecture* BNGetAssociatedArchitectureByAddress(BNArchitecture* arch, uint64_t* addr); diff --git a/examples/x86_extension/src/x86_extension.cpp b/examples/x86_extension/src/x86_extension.cpp index 9efcc119..076551ab 100644 --- a/examples/x86_extension/src/x86_extension.cpp +++ b/examples/x86_extension/src/x86_extension.cpp @@ -327,6 +327,11 @@ public: return LittleEndian; } + virtual size_t GetInstructionAlignment() const override + { + return 1; + } + virtual bool GetInstructionInfo(const uint8_t* data, uint64_t addr, size_t maxLen, InstructionInfo& result) override { return m_arch->GetInstructionInfo(data, addr, maxLen, result); diff --git a/python/architecture.py b/python/architecture.py index 72403fec..41a130bf 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -111,6 +111,7 @@ class Architecture(object): endianness = Endianness.LittleEndian address_size = 8 default_int_size = 4 + instr_alignment = 1 max_instr_length = 16 opcode_display_length = 8 regs = {} @@ -132,6 +133,7 @@ class Architecture(object): self.__dict__["endianness"] = Endianness(core.BNGetArchitectureEndianness(self.handle)) self.__dict__["address_size"] = core.BNGetArchitectureAddressSize(self.handle) self.__dict__["default_int_size"] = core.BNGetArchitectureDefaultIntegerSize(self.handle) + self.__dict__["instr_alignment"] = core.BNGetArchitectureInstructionAlignment(self.handle) self.__dict__["max_instr_length"] = core.BNGetArchitectureMaxInstructionLength(self.handle) self.__dict__["opcode_display_length"] = core.BNGetArchitectureOpcodeDisplayLength(self.handle) self.__dict__["stack_pointer"] = core.BNGetArchitectureRegisterName(self.handle, @@ -228,6 +230,7 @@ class Architecture(object): self._cb.getEndianness = self._cb.getEndianness.__class__(self._get_endianness) self._cb.getAddressSize = self._cb.getAddressSize.__class__(self._get_address_size) self._cb.getDefaultIntegerSize = self._cb.getDefaultIntegerSize.__class__(self._get_default_integer_size) + self._cb.getInstructionAlignment = self._cb.getInstructionAlignment.__class__(self._get_instruction_alignment) 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 = \ @@ -385,7 +388,8 @@ class Architecture(object): def __setattr__(self, name, value): if ((name == "name") or (name == "endianness") or (name == "address_size") or - (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length")): + (name == "default_int_size") or (name == "regs") or (name == "get_max_instruction_length") or + (name == "get_instruction_alignment")): raise AttributeError("attribute '%s' is read only" % name) else: try: @@ -420,6 +424,13 @@ class Architecture(object): log.log_error(traceback.format_exc()) return 4 + def __get_instruction_alignment(self, ctxt): + try: + return self.__class__.instr_alignment + except: + log.log_error(traceback.format_exc()) + return 1 + def _get_max_instruction_length(self, ctxt): try: return self.__class__.max_instr_length diff --git a/python/examples/nes.py b/python/examples/nes.py index e55a90b7..39544c9f 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -367,6 +367,7 @@ class M6502(Architecture): name = "6502" address_size = 2 default_int_size = 1 + instr_alignment = 1 max_instr_length = 3 regs = { "a": RegisterInfo("a", 1), -- cgit v1.3.1 From 88af32b1b20026d3bc063be558f63aeb1ccfd579 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Tue, 14 Nov 2017 15:33:01 -0500 Subject: Fix _get_instruction_alignment type. --- python/architecture.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/architecture.py b/python/architecture.py index 41a130bf..ed03a6e6 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -424,7 +424,7 @@ class Architecture(object): log.log_error(traceback.format_exc()) return 4 - def __get_instruction_alignment(self, ctxt): + def _get_instruction_alignment(self, ctxt): try: return self.__class__.instr_alignment except: -- cgit v1.3.1 From 661581594a014ceadc6284ef8c907162ef17380e Mon Sep 17 00:00:00 2001 From: David Barksdale Date: Tue, 14 Nov 2017 14:05:22 -0600 Subject: Cache Platform object and not handle --- python/function.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'python') diff --git a/python/function.py b/python/function.py index bec3c2ad..9547e34a 100644 --- a/python/function.py +++ b/python/function.py @@ -378,8 +378,8 @@ class Function(object): plat = core.BNGetFunctionPlatform(self.handle) if plat is None: return None - self._platform = plat - return platform.Platform(None, handle = plat) + self._platform = platform.Platform(None, handle = plat) + return self._platform @property def start(self): -- cgit v1.3.1 From 8db4153af8182f9a3ef8b124a34860e5e4d16bcc Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 20 Nov 2017 11:50:34 -0500 Subject: Update Python API to display PossibleValues that are of type ConstantPointerValue. --- python/function.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'python') diff --git a/python/function.py b/python/function.py index 9547e34a..e9e5dcc9 100644 --- a/python/function.py +++ b/python/function.py @@ -123,6 +123,8 @@ class PossibleValueSet(object): self.reg = arch.get_reg_name(value.value) elif value.state == RegisterValueType.ConstantValue: self.value = value.value + elif value.state == RegisterValueType.ConstantPointerValue: + self.value = value.value elif value.state == RegisterValueType.StackFrameOffset: self.offset = value.value elif value.state == RegisterValueType.SignedRangeValue: @@ -164,6 +166,8 @@ class PossibleValueSet(object): return "" % self.reg if self.type == RegisterValueType.ConstantValue: return "" % self.value + if self.type == RegisterValueType.ConstantPointerValue: + return "" % self.value if self.type == RegisterValueType.StackFrameOffset: return "" % self.offset if self.type == RegisterValueType.SignedRangeValue: -- cgit v1.3.1 From 448ffe2842b2b1e0d21f905403489d3f865672d8 Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 4 Dec 2017 13:12:06 -0500 Subject: Add MediumLevelIL Function Recognizer. --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 1 + functionrecognizer.cpp | 18 ++++++++++++++++++ python/functionrecognizer.py | 15 +++++++++++++++ 4 files changed, 36 insertions(+) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index e4ef4c43..baeb5de6 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -2951,6 +2951,7 @@ namespace BinaryNinja class FunctionRecognizer { static bool RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il); + static bool RecognizeMediumLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNMediumLevelILFunction* il); public: FunctionRecognizer(); @@ -2959,6 +2960,7 @@ namespace BinaryNinja static void RegisterArchitectureFunctionRecognizer(Architecture* arch, FunctionRecognizer* recog); virtual bool RecognizeLowLevelIL(BinaryView* data, Function* func, LowLevelILFunction* il); + virtual bool RecognizeMediumLevelIL(BinaryView* data, Function* func, MediumLevelILFunction* il); }; class UpdateException: public std::exception diff --git a/binaryninjacore.h b/binaryninjacore.h index 82198efd..7a0e585e 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1191,6 +1191,7 @@ extern "C" { void* context; bool (*recognizeLowLevelIL)(void* ctxt, BNBinaryView* data, BNFunction* func, BNLowLevelILFunction* il); + bool (*recognizeMediumLevelIL)(void* ctxt, BNBinaryView* data, BNFunction* func, BNMediumLevelILFunction* il); }; struct BNTypeParserResult diff --git a/functionrecognizer.cpp b/functionrecognizer.cpp index 32c7245c..34f1db80 100644 --- a/functionrecognizer.cpp +++ b/functionrecognizer.cpp @@ -38,11 +38,22 @@ bool FunctionRecognizer::RecognizeLowLevelILCallback(void* ctxt, BNBinaryView* d } +bool FunctionRecognizer::RecognizeMediumLevelILCallback(void* ctxt, BNBinaryView* data, BNFunction* func, BNMediumLevelILFunction* il) +{ + FunctionRecognizer* recog = (FunctionRecognizer*)ctxt; + Ref dataObj = new BinaryView(BNNewViewReference(data)); + Ref funcObj = new Function(BNNewFunctionReference(func)); + Ref ilObj = new MediumLevelILFunction(BNNewMediumLevelILFunctionReference(il)); + return recog->RecognizeMediumLevelIL(dataObj, funcObj, ilObj); +} + + void FunctionRecognizer::RegisterGlobalRecognizer(FunctionRecognizer* recog) { BNFunctionRecognizer reg; reg.context = recog; reg.recognizeLowLevelIL = RecognizeLowLevelILCallback; + reg.recognizeMediumLevelIL = RecognizeMediumLevelILCallback; BNRegisterGlobalFunctionRecognizer(®); } @@ -52,6 +63,7 @@ void FunctionRecognizer::RegisterArchitectureFunctionRecognizer(Architecture* ar BNFunctionRecognizer reg; reg.context = recog; reg.recognizeLowLevelIL = RecognizeLowLevelILCallback; + reg.recognizeMediumLevelIL = RecognizeMediumLevelILCallback; BNRegisterArchitectureFunctionRecognizer(arch->GetObject(), ®); } @@ -60,3 +72,9 @@ bool FunctionRecognizer::RecognizeLowLevelIL(BinaryView*, Function*, LowLevelILF { return false; } + + +bool FunctionRecognizer::RecognizeMediumLevelIL(BinaryView*, Function*, MediumLevelILFunction*) +{ + return false; +} diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 8514a2ee..4ac304ca 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -36,6 +36,7 @@ class FunctionRecognizer(object): self._cb = core.BNFunctionRecognizer() self._cb.context = 0 self._cb.recognizeLowLevelIL = self._cb.recognizeLowLevelIL.__class__(self._recognize_low_level_il) + self._cb.recognizeMediumLevelIL = self._cb.recognizeMediumLevelIL.__class__(self._recognize_medium_level_il) @classmethod def register_global(cls): @@ -62,3 +63,17 @@ class FunctionRecognizer(object): def recognize_low_level_il(self, data, func, il): return False + + def _recognize_medium_level_il(self, ctxt, data, func, il): + try: + file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data)) + view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data)) + func = function.Function(view, handle = core.BNNewFunctionReference(func)) + il = mediumlevelil.MediumLevelILFunction(func.arch, handle = core.BNNewMediumLevelILFunctionReference(il)) + return self.recognize_medium_level_il(view, func, il) + except: + log.log_error(traceback.format_exc()) + return False + + def recognize_medium_level_il(self, data, func, il): + return False -- cgit v1.3.1 From 10cf74045e1e2495813597a499dee4fb4baf601f Mon Sep 17 00:00:00 2001 From: Brian Potchik Date: Mon, 4 Dec 2017 13:23:26 -0500 Subject: Better Architecture Transition Support. --- architecture.cpp | 1 + binaryninjacore.h | 1 + python/architecture.py | 2 ++ python/function.py | 1 + 4 files changed, 5 insertions(+) (limited to 'python') diff --git a/architecture.cpp b/architecture.cpp index 17d02909..66372bcb 100644 --- a/architecture.cpp +++ b/architecture.cpp @@ -30,6 +30,7 @@ using namespace std; InstructionInfo::InstructionInfo() { length = 0; + archTransitionByTargetAddr = false; branchCount = 0; branchDelay = false; } diff --git a/binaryninjacore.h b/binaryninjacore.h index 7a0e585e..1bb0c70a 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -973,6 +973,7 @@ extern "C" { size_t length; size_t branchCount; + bool archTransitionByTargetAddr; bool branchDelay; BNBranchType branchType[BN_MAX_INSTRUCTION_BRANCHES]; uint64_t branchTarget[BN_MAX_INSTRUCTION_BRANCHES]; diff --git a/python/architecture.py b/python/architecture.py index ed03a6e6..a893c1d4 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -462,6 +462,7 @@ class Architecture(object): if info is None: return False result[0].length = info.length + result[0].archTransitionByTargetAddr = info.arch_transition_by_target_addr result[0].branchDelay = info.branch_delay result[0].branchCount = len(info.branches) for i in xrange(0, len(info.branches)): @@ -1163,6 +1164,7 @@ class Architecture(object): return None result = function.InstructionInfo() result.length = info.length + result.arch_transition_by_target_addr = info.archTransitionByTargetAddr result.branch_delay = info.branchDelay for i in xrange(0, info.branchCount): target = info.branchTarget[i] diff --git a/python/function.py b/python/function.py index e9e5dcc9..58bee8f4 100644 --- a/python/function.py +++ b/python/function.py @@ -1755,6 +1755,7 @@ class InstructionBranch(object): class InstructionInfo(object): def __init__(self): self.length = 0 + self.arch_transition_by_target_addr = False self.branch_delay = False self.branches = [] -- cgit v1.3.1 From 78a9a6fd52cb36e1e2fddfb0cbaf4f56a6b8016e Mon Sep 17 00:00:00 2001 From: David Barksdale Date: Tue, 5 Dec 2017 11:34:32 -0600 Subject: Add __eq__ and __hash__ to BasicBlockEdge --- python/basicblock.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'python') diff --git a/python/basicblock.py b/python/basicblock.py index 66d96882..8e64c1c1 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -35,6 +35,14 @@ class BasicBlockEdge(object): self.target = target self.back_edge = back_edge + def __eq__(self, value): + if not isinstance(value, BasicBlockEdge): + return False + return (self.type, self.source, self.target, self.back_edge) == (value.type, value.source, value.target, value.back_edge) + + def __hash__(self): + return hash((self.type, self.source, self.target, self.back_edge)) + def __repr__(self): if self.type == BranchType.UnresolvedBranch: return "<%s>" % BranchType(self.type).name -- cgit v1.3.1 From 565dd968745465d3ab939303056431bf9fa2f924 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 14 Dec 2017 15:13:54 -0500 Subject: Fix multi-line execution in python console --- python/scriptingprovider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index f9758cc9..8645c96c 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -547,7 +547,7 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_llil"] = self.active_func.low_level_il self.locals["current_mlil"] = self.active_func.medium_level_il - self.interpreter.runsource(code) + self.interpreter.runcode(code) if self.locals["here"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]): -- cgit v1.3.1 From ae5ce4da4c1f6ea3a071a4eec1a5da3e6e2a3305 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 14 Dec 2017 18:38:57 -0500 Subject: Fix multi-line insertion and single expression evalutation --- python/scriptingprovider.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 8645c96c..761b359c 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -457,7 +457,7 @@ class PythonScriptingInstance(ScriptingInstance): super(PythonScriptingInstance.InterpreterThread, self).__init__() self.instance = instance self.locals = {"__name__": "__console__", "__doc__": None, "binaryninja": sys.modules[__name__]} - self.interpreter = code.InteractiveInterpreter(self.locals) + self.interpreter = code.InteractiveConsole(self.locals) self.event = threading.Event() self.daemon = True @@ -484,7 +484,7 @@ class PythonScriptingInstance(ScriptingInstance): self.code = None self.input = "" - self.interpreter.runsource("from binaryninja import *\n") + self.interpreter.push("from binaryninja import *\n") def execute(self, code): self.code = code @@ -547,7 +547,8 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_llil"] = self.active_func.low_level_il self.locals["current_mlil"] = self.active_func.medium_level_il - self.interpreter.runcode(code) + for line in code.split("\n"): + self.interpreter.push(line) if self.locals["here"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]): -- cgit v1.3.1 From b207c76729df133c7b6fc4bc9f1abb6948ae6438 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Thu, 14 Dec 2017 18:46:10 -0500 Subject: Add autoDefined attribute to Sections and Segments --- binaryninjaapi.h | 2 ++ binaryninjacore.h | 2 ++ binaryview.cpp | 2 +- python/binaryview.py | 17 ++++++++++------- 4 files changed, 15 insertions(+), 8 deletions(-) (limited to 'python') diff --git a/binaryninjaapi.h b/binaryninjaapi.h index baeb5de6..72f74c5a 100644 --- a/binaryninjaapi.h +++ b/binaryninjaapi.h @@ -1027,6 +1027,7 @@ namespace BinaryNinja uint64_t start, length; uint64_t dataOffset, dataLength; uint32_t flags; + bool autoDefined; }; struct Section @@ -1037,6 +1038,7 @@ namespace BinaryNinja uint64_t infoData; uint64_t align, entrySize; BNSectionSemantics semantics; + bool autoDefined; }; struct QualifiedNameAndType; diff --git a/binaryninjacore.h b/binaryninjacore.h index 1bb0c70a..245e6353 100644 --- a/binaryninjacore.h +++ b/binaryninjacore.h @@ -1531,6 +1531,7 @@ extern "C" uint64_t start, length; uint64_t dataOffset, dataLength; uint32_t flags; + bool autoDefined; }; enum BNSectionSemantics @@ -1551,6 +1552,7 @@ extern "C" uint64_t infoData; uint64_t align, entrySize; BNSectionSemantics semantics; + bool autoDefined; }; struct BNAddressRange diff --git a/binaryview.cpp b/binaryview.cpp index 0a082458..50011a0f 100644 --- a/binaryview.cpp +++ b/binaryview.cpp @@ -1724,6 +1724,7 @@ vector BinaryView::GetSegments() segment.dataOffset = segments[i].dataOffset; segment.dataLength = segments[i].dataLength; segment.flags = segments[i].flags; + segment.autoDefined = segments[i].autoDefined; result.push_back(segment); } @@ -1731,7 +1732,6 @@ vector BinaryView::GetSegments() return result; } - bool BinaryView::GetSegmentAt(uint64_t addr, Segment& result) { BNSegment segment; diff --git a/python/binaryview.py b/python/binaryview.py index 9f149ba8..6eb59db1 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -416,12 +416,13 @@ class BinaryViewType(object): class Segment(object): - def __init__(self, start, length, data_offset, data_length, flags): + def __init__(self, start, length, data_offset, data_length, flags, auto_defined): self.start = start self.length = length self.data_offset = data_offset self.data_length = data_length self.flags = flags + self.auto_defined = auto_defined @property def executable(self): @@ -450,7 +451,7 @@ class Segment(object): class Section(object): - def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics): + def __init__(self, name, section_type, start, length, linked_section, info_section, info_data, align, entry_size, semantics, auto_defined): self.name = name self.type = section_type self.start = start @@ -461,6 +462,7 @@ class Section(object): self.align = align self.entry_size = entry_size self.semantics = SectionSemantics(semantics) + self.auto_defined = auto_defined @property def end(self): @@ -965,7 +967,7 @@ class BinaryView(object): 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)) + segment_list[i].dataOffset, segment_list[i].dataLength, segment_list[i].flags, segment_list[i].autoDefined)) core.BNFreeSegmentList(segment_list) return result @@ -979,7 +981,7 @@ class BinaryView(object): 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, - section_list[i].semantics) + section_list[i].semantics, section_list[i].autoDefined) core.BNFreeSectionList(section_list, count.value) return result @@ -3353,7 +3355,7 @@ class BinaryView(object): if not core.BNGetSegmentAt(self.handle, addr, segment): return None result = Segment(segment.start, segment.length, segment.dataOffset, segment.dataLength, - segment.flags) + segment.flags, segment.autoDefined) return result def get_address_for_data_offset(self, offset): @@ -3386,7 +3388,7 @@ class BinaryView(object): 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, - section_list[i].semantics)) + section_list[i].semantics, section_list[i].autoDefined)) core.BNFreeSectionList(section_list, count.value) return result @@ -3395,7 +3397,8 @@ class BinaryView(object): 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, section.semantics) + section.infoSection, section.infoData, section.align, section.entrySize, section.semantics, + section_list.autoDefined) core.BNFreeSection(section) return result -- cgit v1.3.1 From b64d65be48ba44d9c2b564d88aec15430fd289df Mon Sep 17 00:00:00 2001 From: toolCHAINZ Date: Thu, 14 Dec 2017 19:07:25 -0500 Subject: Fix PluginManager Doc Example (#885) Fix doc string example for add_repository --- python/pluginmanager.py | 1 - 1 file changed, 1 deletion(-) (limited to 'python') diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 6896d699..2f293577 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -382,7 +382,6 @@ class RepositoryManager(object): >>> mgr = RepositoryManager() >>> mgr.add_repository(url="https://github.com/vector35/community-plugins.git", repopath="myrepo", - repomanifest="plugins", localreference="master", remotereference="origin") True >>> -- cgit v1.3.1 From 4862340bc92c7bcde9d377cbf7cff1417a39509e Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Fri, 15 Dec 2017 09:56:59 -0500 Subject: Make multi-line python input more robust --- python/scriptingprovider.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 761b359c..6b03d49e 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -42,14 +42,14 @@ class _ThreadActionContext(object): def __init__(self, func): self.func = func self.interpreter = None - if "value" in dir(PythonScriptingInstance._interpreter): + if hasattr(PythonScriptingInstance._interpreter, "value"): self.interpreter = PythonScriptingInstance._interpreter.value self.__class__._actions.append(self) self.callback = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(lambda ctxt: self.execute()) def execute(self): old_interpreter = None - if "value" in dir(PythonScriptingInstance._interpreter): + if hasattr(PythonScriptingInstance._interpreter, "value"): old_interpreter = PythonScriptingInstance._interpreter.value PythonScriptingInstance._interpreter.value = self.interpreter try: @@ -380,7 +380,7 @@ class _PythonScriptingInstanceOutput(object): def write(self, data): interpreter = None - if "value" in dir(PythonScriptingInstance._interpreter): + if hasattr(PythonScriptingInstance._interpreter, "value"): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: @@ -419,7 +419,7 @@ class _PythonScriptingInstanceInput(object): def read(self, size): interpreter = None - if "value" in dir(PythonScriptingInstance._interpreter): + if hasattr(PythonScriptingInstance._interpreter, "value"): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: @@ -434,7 +434,7 @@ class _PythonScriptingInstanceInput(object): def readline(self): interpreter = None - if "value" in dir(PythonScriptingInstance._interpreter): + if hasattr(PythonScriptingInstance._interpreter, "value"): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: @@ -548,7 +548,7 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_mlil"] = self.active_func.medium_level_il for line in code.split("\n"): - self.interpreter.push(line) + self.interpreter.push(line + "\n") if self.locals["here"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]): -- cgit v1.3.1 From 0963fc9e3623f9758afb63b4b089a0fa7873c395 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Mon, 18 Dec 2017 11:43:43 -0500 Subject: Remove newline from split lines as it breaks more than it fixes --- python/scriptingprovider.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'python') diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 6b03d49e..c92c249a 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -548,7 +548,7 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_mlil"] = self.active_func.medium_level_il for line in code.split("\n"): - self.interpreter.push(line + "\n") + self.interpreter.push(line) if self.locals["here"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]): -- cgit v1.3.1