From 75242aecc30c565ee56d3e74ec2e2dd502a6f073 Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Sun, 29 Oct 2017 12:51:23 -0400 Subject: Fixed possible IndexError in Function.get_*_at methods (#775) `Function.get_low_level_il_at` and `Function.get_lifted_il_at` methods could raise an IndexError because proper checking was not performed on the index returned by the core method that retrieves the IL instruction index of the requested instruction. The methods now check this value to see if it is equal to the length of the IL function, and if so, returns `None` instead. The onus of checking for `None` will be on the user, but at least they shouldn't have to wrap this in a try/except block anymore. --- python/function.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'python/function.py') diff --git a/python/function.py b/python/function.py index 5daa7b2a..9aafdf52 100644 --- a/python/function.py +++ b/python/function.py @@ -727,7 +727,13 @@ class Function(object): """ if arch is None: arch = self.arch - return self.low_level_il[core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)] + + idx = core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr) + + if idx == len(self.low_level_il): + return None + + return self.low_level_il[idx] def get_low_level_il_exits_at(self, addr, arch=None): if arch is None: @@ -878,7 +884,13 @@ class Function(object): def get_lifted_il_at(self, addr, arch=None): if arch is None: arch = self.arch - return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)] + + idx = core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr) + + if idx == len(self.lifted_il): + return None + + return self.lifted_il[idx] def get_lifted_il_flag_uses_for_definition(self, i, flag): flag = self.arch.get_flag_index(flag) -- cgit v1.3.1 From 0ca722550555a1a0fc82766686bade6d669af3dc Mon Sep 17 00:00:00 2001 From: Cory Duplantis Date: Sun, 29 Oct 2017 13:23:33 -0500 Subject: Add convenience API's for accessing blocks and instructions in Function (#792) * Update export-svg.py path splitting Changed the path splitting part to the way python's documentation recommends it. I got some errors trying to use that function on windows, because it didn't split correctly. I stumbled upon this in the python documentation: https://docs.python.org/2/library/os.html#os.sep I changed the relevant line using their recommendation. * Rename data to session_data, as this API is per-session and not stored in the db * get_basic_blocks_starting_at incorrectly in the docs * Update troubleshooting.md * Zoom * get_instruction_low_level_il tweak made api docs less ambiguous * documenting Type.int and Type.function * Update __init__.py * Add convenience API's for accessing blocks and instructions in Function --- python/function.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'python/function.py') diff --git a/python/function.py b/python/function.py index 9aafdf52..cbbdf9bd 100644 --- a/python/function.py +++ b/python/function.py @@ -666,6 +666,41 @@ class Function(object): """Sets a comment for the current function""" return core.BNSetFunctionComment(self.handle, comment) + @property + def llil_basic_blocks(self): + """A generator of all LowLevelILBasicBlock objects in the current function""" + for block in self.low_level_il: + yield block + + @property + def mlil_basic_blocks(self): + """A generator of all MediumLevelILBasicBlock objects in the current function""" + for block in self.medium_level_il: + yield block + + @property + def instructions(self): + """A generator of instruction tokens and their start addresses for the current function""" + for block in self.basic_blocks: + start = block.start + for i in block: + yield (i[0], start) + start += i[1] + + @property + def llil_instructions(self): + """A generator of llil instructions of the current function""" + for block in self.llil_basic_blocks: + for i in block: + yield i + + @property + def mlil_instructions(self): + """A generator of mlil instructions of the current function""" + for block in self.mlil_basic_blocks: + for i in block: + yield i + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) -- cgit v1.3.1 From 704ceff1223485e9dc12947a36b0d56a3ff9d3ae Mon Sep 17 00:00:00 2001 From: David Barksdale Date: Thu, 2 Nov 2017 11:38:11 -0500 Subject: Move the function discrimination from SSAVariable to Variable (#856) --- python/function.py | 4 ++-- python/mediumlevelil.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'python/function.py') diff --git a/python/function.py b/python/function.py index cbbdf9bd..f8aaae44 100644 --- a/python/function.py +++ b/python/function.py @@ -241,10 +241,10 @@ class Variable(object): return self.name def __eq__(self, other): - return self.identifier == other.identifier + return (self.identifier, self.function) == (other.identifier, other.function) def __hash__(self): - return hash(self.identifier) + return hash((self.identifier, self.function)) class ConstantReference(object): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 333a6c4d..6f5515bb 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -39,12 +39,12 @@ class SSAVariable(object): def __eq__(self, other): return ( - (self.var.identifier, self.var.function, self.version) == - (other.var.identifier, other.var.function, other.version) + (self.var, self.version) == + (other.var, other.version) ) def __hash__(self): - return hash((self.var.identifier, self.var.function, self.version)) + return hash((self.var, self.version)) class MediumLevelILLabel(object): -- cgit v1.3.1 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/function.py') 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 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/function.py') 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/function.py') 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 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/function.py') 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