From 3f4b372a6cef322720467d0a8f41557f0570a618 Mon Sep 17 00:00:00 2001 From: Ryan Stortz Date: Thu, 14 Apr 2016 20:48:04 -0400 Subject: Modifies the python api to allow iteration over some base types Introduces __iter__ to Function, which yields BasicBlocks Introduces __iter__ to BasicBlock, with yields instruction text Extended BasicBlock with ILBasicBlock, to iterate over ILBasicBlocks (which yields ILInstruction instances) --- python/__init__.py | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) (limited to 'python') diff --git a/python/__init__.py b/python/__init__.py index e1429bd6..1da42f38 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1932,7 +1932,7 @@ class Function: return result elif name == "low_level_il": return LowLevelILFunction(self.arch, core.BNNewLowLevelILFunctionReference( - core.BNGetFunctionLowLevelIL(self.handle))) + core.BNGetFunctionLowLevelIL(self.handle)), self) elif name == "low_level_il_basic_blocks": count = ctypes.c_ulonglong() blocks = core.BNGetFunctionLowLevelILBasicBlockList(self.handle, count) @@ -1954,6 +1954,14 @@ class Function: return result raise AttributeError, "no attribute '%s'" % name + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetFunctionBasicBlockList(self.handle, count) + for i in xrange(0, count.value): + yield BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) + core.BNFreeBasicBlockList(blocks, count.value) + raise StopIteration + def __setattr__(self, name, value): if ((name == "view") or (name == "arch") or (name == "start") or (name == "symbol") or (name == "auto") or (name == "can_return") or (name == "basic_blocks") or (name == "comments") or (name == "low_level_il") or @@ -2042,7 +2050,7 @@ class Function: result = [] for i in xrange(0, count.value): result.append(StackVariableReference(refs[i].sourceOperand, Type(core.BNNewTypeReference(refs[i].type)), - refs[i].name, refs[i].startingOffset, refs[i].referencedOffset)) + refs[i].name, refs[i].startingOffset, refs[i].referencedOffset)) core.BNFreeStackVariableReferenceList(refs, count.value) return result @@ -2131,9 +2139,36 @@ class BasicBlock: else: return "" % (self.start, self.end) + def __iter__(self): + func = getattr(self, "function") + start = getattr(self, "start") + end = getattr(self, "end") + + idx = start + while idx < end: + data = self.view.read(idx, 16) + inst_info = self.view.arch.get_instruction_info(data, idx) + inst_text = self.view.arch.get_instruction_text(data, idx) + + yield inst_text + idx += inst_info.length + raise StopIteration + def mark_recent_use(): core.BNMarkBasicBlockAsRecentlyUsed(self.handle) +class ILBasicBlock(BasicBlock): + def __iter__(self): + func = getattr(self, "function") + low_level_il_function = func.low_level_il + start = getattr(self, "start") + end = getattr(self, "end") + + for idx in xrange(start, end): + yield low_level_il_function[idx] + + raise StopIteration + class FunctionGraphTextLine: def __init__(self, addr, tokens): self.address = addr @@ -3390,8 +3425,9 @@ class LowLevelILExpr: self.index = index class LowLevelILFunction: - def __init__(self, arch, handle = None): + def __init__(self, arch, handle = None, mcfunc = None): self.arch = arch + self.mcfunc = mcfunc if handle is not None: self.handle = core.handle_of_type(handle, core.BNLowLevelILFunction) else: @@ -3429,6 +3465,14 @@ class LowLevelILFunction: def __setitem__(self, i): raise IndexError, "instruction modification not implemented" + def __iter__(self): + count = ctypes.c_ulonglong() + blocks = core.BNGetFunctionLowLevelILBasicBlockList(self.mcfunc.handle, count) + for i in xrange(0, count.value): + yield ILBasicBlock(self.mcfunc._view, core.BNNewBasicBlockReference(blocks[i])) + core.BNFreeBasicBlockList(blocks, count.value) + raise StopIteration + def expr(self, operation, a = 0, b = 0, c = 0, d = 0, size = 0, flags = None): if isinstance(operation, str): operation = BNLowLevelILOperation_by_name[operation] -- cgit v1.3.1 From 399568bbb0c88b2aa3919ac3552483a9dd8f01ab Mon Sep 17 00:00:00 2001 From: Ryan Stortz Date: Thu, 14 Apr 2016 20:50:59 -0400 Subject: Add an example that uses the interators --- python/examples/instruction-iterator.py | 53 +++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 python/examples/instruction-iterator.py (limited to 'python') diff --git a/python/examples/instruction-iterator.py b/python/examples/instruction-iterator.py new file mode 100644 index 00000000..736a2925 --- /dev/null +++ b/python/examples/instruction-iterator.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import sys +try: + import binaryninja +except ImportError: + sys.path.append("/Applications/Binary Ninja.app/Contents/Resources/python/") + import binaryninja +import time + +if sys.platform.lower().startswith("linux"): + bintype="ELF" +elif sys.platform.lower() == "darwin": + bintype="Mach-O" +else: + raise Exception, "%s is not supported on this plugin" % sys.platform + +if len(sys.argv) > 1: + target = sys.argv[1] +else: + target = "/bin/ls" + +bv = binaryninja.BinaryViewType[bintype].open(target) +bv.update_analysis() + +"""Until update_analysis_and_wait is complete, sleep is necessary as the analysis is multi-threaded.""" +time.sleep(1) + +print "-------- %s --------" % target +print "START: 0x%x" % bv.start +print "ENTRY: 0x%x" % bv.entry_point +print "ARCH: %s" % bv.arch.name +print "\n-------- Function List --------" + +""" print all the functions, their basic blocks, and their il instructions """ +for func in bv.functions: + print repr(func) + for block in func.low_level_il: + print "\t{0}".format(block) + + for insn in block: + print "\t\t{0}".format(insn) + + +""" print all the functions, their basic blocks, and their mc instructions """ +for func in bv.functions: + print repr(func) + for block in func: + print "\t{0}".format(block) + + for insn in block: + print "\t\t{0}".format(insn) + -- cgit v1.3.1