summaryrefslogtreecommitdiff
path: root/python
diff options
context:
space:
mode:
authorPeter LaFosse <peter@vector35.com>2017-01-02 15:19:47 -0500
committerPeter LaFosse <peter@vector35.com>2017-01-02 15:19:47 -0500
commit842aba557f24ca9ab63f05cec6aa0c0efebd51b4 (patch)
tree484981f9b580958b647da146fd17be34a366d442 /python
parent9ad395e9d45d18734f1afbf208c80bdafa6a7a3d (diff)
Making platform and architecture optional parameters where possible
Diffstat (limited to 'python')
-rw-r--r--python/architecture.py6
-rw-r--r--python/basicblock.py47
-rw-r--r--python/binaryview.py153
-rw-r--r--python/examples/jump_table.py2
-rw-r--r--python/examples/print_syscalls.py2
-rw-r--r--python/filemetadata.py8
-rw-r--r--python/function.py162
-rw-r--r--python/scriptingprovider.py43
8 files changed, 330 insertions, 93 deletions
diff --git a/python/architecture.py b/python/architecture.py
index 0cdba6e5..5162e58a 100644
--- a/python/architecture.py
+++ b/python/architecture.py
@@ -1152,6 +1152,12 @@ class Architecture(object):
core.BNFreeInstructionText(tokens, count.value)
return result, length.value
+ def get_instruction_low_level_il_instruction(self, bv, addr):
+ il = lowlevelil.LowLevelILFunction(self)
+ data = bv.read(addr, self.max_instr_length)
+ self.get_instruction_low_level_il(data, addr, il)
+ return il[0]
+
def get_instruction_low_level_il(self, data, addr, il):
"""
``get_instruction_low_level_il`` appends LowLevelILExpr objects for the instruction at the given virtual
diff --git a/python/basicblock.py b/python/basicblock.py
index 7abfdc94..d728cb8d 100644
--- a/python/basicblock.py
+++ b/python/basicblock.py
@@ -111,11 +111,25 @@ class BasicBlock(object):
@property
def disassembly_text(self):
+ """
+ ``disassembly_text`` property which returns a list of function.DisassemblyTextLine objects for the current basic block.
+ :Example:
+
+ >>> current_basic_block.disassembly_text
+ [<0x100000f30: _main:>, ...]
+ """
return self.get_disassembly_text()
@property
def highlight(self):
- """Highlight color for basic block"""
+ """Gets or sets the highlight color for basic block
+
+ :Example:
+
+ >>> current_basic_block.highlight = core.BNHighlightStandardColor.BlueHighlightColor
+ >>> current_basic_block.highlight
+ <color: blue>
+ """
color = core.BNGetBasicBlockHighlight(self.handle)
if color.style == core.BNHighlightColorStyle.StandardHighlightColor:
return highlight.HighlightColor(color=color.color, alpha=color.alpha)
@@ -162,6 +176,13 @@ class BasicBlock(object):
core.BNMarkBasicBlockAsRecentlyUsed(self.handle)
def get_disassembly_text(self, settings=None):
+ """
+ ``get_disassembly_text`` returns a list of function.DisassemblyTextLine objects for the current basic block.
+ :Example:
+
+ >>>current_basic_block.get_disassembly_text()
+ [<0x100000f30: _main:>, <0x100000f30: push rbp>, ... ]
+ """
settings_obj = None
if settings:
settings_obj = settings.handle
@@ -184,11 +205,27 @@ class BasicBlock(object):
return result
def set_auto_highlight(self, color):
- if not isinstance(color, highlight.HighlightColor):
- color = highlight.HighlightColor(color=color)
+ """
+ ``set_auto_highlight`` highlights the current BasicBlock with the supplied color.
+
+ .warning:: Use only in analysis plugins. Do not use in regular plugins, as colors won't be saved to the database.
+
+ :param core.BNHighlightStandardColor or highlight.HighlightColor color: Color value to use for highlighting
+ """
+ if not isinstance(color, core.BNHighlightStandardColor) and not isinstance(color, highlight.HighlightColor):
+ raise ValueError("Specified color is not one of core.BNHighlightStandardColor, highlight.HighlightColor")
core.BNSetAutoBasicBlockHighlight(self.handle, color._get_core_struct())
def set_user_highlight(self, color):
- if not isinstance(color, highlight.HighlightColor):
- color = highlight.HighlightColor(color=color)
+ """
+ ``set_user_highlight`` highlights the current BasicBlock with the supplied color
+
+ :param core.BNHighlightStandardColor or highlight.HighlightColor color: Color value to use for highlighting
+ :Example:
+
+ >>> current_basic_block.set_user_highlight(highlight.HighlightColor(red=0xff, blue=0xff, green=0))
+ >>> current_basic_block.set_user_highlight(core.BNHighlightStandardColor.BlueHighlightColor)
+ """
+ if not isinstance(color, core.BNHighlightStandardColor) and not isinstance(color, highlight.HighlightColor):
+ raise ValueError("Specified color is not one of core.BNHighlightStandardColor, highlight.HighlightColor")
core.BNSetUserBasicBlockHighlight(self.handle, color._get_core_struct())
diff --git a/python/binaryview.py b/python/binaryview.py
index e6e0ff61..7c85cd52 100644
--- a/python/binaryview.py
+++ b/python/binaryview.py
@@ -275,7 +275,7 @@ class BinaryViewType(object):
@property
def name(self):
- """Binary View name (read-only)"""
+ """BinaryView name (read-only)"""
return core.BNGetBinaryViewTypeName(self.handle)
@property
@@ -303,12 +303,21 @@ class BinaryViewType(object):
"""
``get_view_of_file`` returns the first available, non-Raw `BinaryView` available.
- :param str filename: Path to filename
+ :param str filename: Path to filename or bndb
:param bool update_analysis: defaults to True. Pass False to not run update_analysis_and_wait.
:return: returns a BinaryView object for the given filename.
:rtype: BinaryView or None
"""
- view = BinaryView.open(filename)
+ sqlite = "SQLite format 3"
+ if filename.endswith(".bndb"):
+ f = open(filename, 'r')
+ if f is None or f.read(len(sqlite)) != sqlite:
+ return None
+ f.close()
+ view = filemetadata.FileMetadata().open_existing_database(filename)
+ else:
+ view = BinaryView.open(filename)
+
if view is None:
return None
for available in view.available_view_types:
@@ -1381,7 +1390,7 @@ class BinaryView(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -1406,7 +1415,7 @@ class BinaryView(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -1428,7 +1437,7 @@ class BinaryView(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -1453,7 +1462,7 @@ class BinaryView(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -1624,33 +1633,37 @@ class BinaryView(object):
self.notifications[notify]._unregister()
del self.notifications[notify]
- def add_function(self, plat, addr):
+ def add_function(self, addr, plat=None):
"""
``add_function`` add a new function of the given ``plat`` at the virtual address ``addr``
- :param Platform plat: Platform for the function to be added
:param int addr: virtual address of the function to be added
+ :param Platform plat: Platform for the function to be added
:rtype: None
:Example:
- >>> bv.add_function(bv.plat, 1)
+ >>> bv.add_function(1)
>>> bv.functions
[<func: x86_64@0x1>]
"""
+ if plat is None:
+ plat = self.platform
core.BNAddFunctionForAnalysis(self.handle, plat.handle, addr)
- def add_entry_point(self, plat, addr):
+ def add_entry_point(self, addr, plat=None):
"""
``add_entry_point`` adds an virtual address to start analysis from for a given plat.
- :param Platform plat: Platform for the entry point analysis
:param int addr: virtual address to start analysis from
+ :param Platform plat: Platform for the entry point analysis
:rtype: None
:Example:
- >>> bv.add_entry_point(bv.plat, 0xdeadbeef)
+ >>> bv.add_entry_point(0xdeadbeef)
>>>
"""
+ if plat is None:
+ plat = self.platform
core.BNAddEntryPointForAnalysis(self.handle, plat.handle, addr)
def remove_function(self, func):
@@ -1669,20 +1682,22 @@ class BinaryView(object):
"""
core.BNRemoveAnalysisFunction(self.handle, func.handle)
- def create_user_function(self, plat, addr):
+ def create_user_function(self, addr, plat=None):
"""
``create_user_function`` add a new *user* function of the given ``plat`` at the virtual address ``addr``
- :param Platform plat: Platform for the function to be added
:param int addr: virtual address of the *user* function to be added
+ :param Platform plat: Platform for the function to be added
:rtype: None
:Example:
- >>> bv.create_user_function(bv.plat, 1)
+ >>> bv.create_user_function(1)
>>> bv.functions
[<func: x86_64@0x1>]
"""
+ if plat is None:
+ plat = self.platform
core.BNCreateUserFunction(self.handle, plat.handle, addr)
def remove_user_function(self, func):
@@ -1832,20 +1847,22 @@ class BinaryView(object):
return None
return DataVariable(var.address, type.Type(var.type), var.autoDiscovered)
- def get_function_at(self, plat, addr):
+ def get_function_at(self, addr, plat=None):
"""
``get_function_at`` gets a binaryninja.Function object for the function at the virtual address ``addr``:
- :param binaryninja.Platform plat: plat of the desired function
:param int addr: virtual address of the desired function
+ :param Platform plat: plat of the desired function
:return: returns a Function object or None for the function at the virtual address provided
:rtype: Function
:Example:
- >>> bv.get_function_at(bv.plat, bv.entry_point)
+ >>> bv.get_function_at(bv.entry_point)
<func: x86_64@0x100001174>
>>>
"""
+ if plat is None:
+ plat = self.platform
func = core.BNGetAnalysisFunction(self.handle, plat.handle, addr)
if func is None:
return None
@@ -2092,144 +2109,154 @@ class BinaryView(object):
"""
core.BNDefineImportedFunction(self.handle, import_addr_sym.handle, func.handle)
- def is_never_branch_patch_available(self, arch, addr):
+ def is_never_branch_patch_available(self, addr, arch=None):
"""
``is_never_branch_patch_available`` queries the architecture plugin to determine if the instruction at the
instruction at ``addr`` can be made to **never branch**. The actual logic of which is implemented in the
``perform_is_never_branch_patch_available`` in the corresponding architecture.
- :param Architecture arch: the architecture for the current view
:param int addr: the virtual address of the instruction to be patched
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True if the instruction can be patched, False otherwise
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012ed)
'test eax, eax'
- >>> bv.is_never_branch_patch_available(bv.arch, 0x100012ed)
+ >>> bv.is_never_branch_patch_available(0x100012ed)
False
>>> bv.get_disassembly(0x100012ef)
'jg 0x100012f5'
- >>> bv.is_never_branch_patch_available(bv.arch, 0x100012ef)
+ >>> bv.is_never_branch_patch_available(0x100012ef)
True
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNIsNeverBranchPatchAvailable(self.handle, arch.handle, addr)
- def is_always_branch_patch_available(self, arch, addr):
+ def is_always_branch_patch_available(self, addr, arch=None):
"""
``is_always_branch_patch_available`` queries the architecture plugin to determine if the
instruction at ``addr`` can be made to **always branch**. The actual logic of which is implemented in the
``perform_is_always_branch_patch_available`` in the corresponding architecture.
- :param Architecture arch: the architecture for the current view
:param int addr: the virtual address of the instruction to be patched
+ :param Architecture arch: (optional) the architecture for the current view
:return: True if the instruction can be patched, False otherwise
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012ed)
'test eax, eax'
- >>> bv.is_always_branch_patch_available(bv.arch, 0x100012ed)
+ >>> bv.is_always_branch_patch_available(0x100012ed)
False
>>> bv.get_disassembly(0x100012ef)
'jg 0x100012f5'
- >>> bv.is_always_branch_patch_available(bv.arch, 0x100012ef)
+ >>> bv.is_always_branch_patch_available(0x100012ef)
True
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNIsAlwaysBranchPatchAvailable(self.handle, arch.handle, addr)
- def is_invert_branch_patch_available(self, arch, addr):
+ def is_invert_branch_patch_available(self, addr, arch=None):
"""
``is_invert_branch_patch_available`` queries the architecture plugin to determine if the instruction at ``addr``
is a branch that can be inverted. The actual logic of which is implemented in the
``perform_is_invert_branch_patch_available`` in the corresponding architecture.
- :param Architecture arch: the architecture for the current view
:param int addr: the virtual address of the instruction to be patched
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True if the instruction can be patched, False otherwise
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012ed)
'test eax, eax'
- >>> bv.is_invert_branch_patch_available(bv.arch, 0x100012ed)
+ >>> bv.is_invert_branch_patch_available(0x100012ed)
False
>>> bv.get_disassembly(0x100012ef)
'jg 0x100012f5'
- >>> bv.is_invert_branch_patch_available(bv.arch, 0x100012ef)
+ >>> bv.is_invert_branch_patch_available(0x100012ef)
True
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNIsInvertBranchPatchAvailable(self.handle, arch.handle, addr)
- def is_skip_and_return_zero_patch_available(self, arch, addr):
+ def is_skip_and_return_zero_patch_available(self, addr, arch=None):
"""
``is_skip_and_return_zero_patch_available`` queries the architecture plugin to determine if the
instruction at ``addr`` is similar to an x86 "call" instruction which can be made to return zero. The actual
logic of which is implemented in the ``perform_is_skip_and_return_zero_patch_available`` in the corresponding
architecture.
- :param Architecture arch: the architecture for the current view
:param int addr: the virtual address of the instruction to be patched
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True if the instruction can be patched, False otherwise
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012f6)
'mov dword [0x10003020], eax'
- >>> bv.is_skip_and_return_zero_patch_available(bv.arch, 0x100012f6)
+ >>> bv.is_skip_and_return_zero_patch_available(0x100012f6)
False
>>> bv.get_disassembly(0x100012fb)
'call 0x10001629'
- >>> bv.is_skip_and_return_zero_patch_available(bv.arch, 0x100012fb)
+ >>> bv.is_skip_and_return_zero_patch_available(0x100012fb)
True
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNIsSkipAndReturnZeroPatchAvailable(self.handle, arch.handle, addr)
- def is_skip_and_return_value_patch_available(self, arch, addr):
+ def is_skip_and_return_value_patch_available(self, addr, arch=None):
"""
``is_skip_and_return_value_patch_available`` queries the architecture plugin to determine if the
instruction at ``addr`` is similar to an x86 "call" instruction which can be made to return a value. The actual
logic of which is implemented in the ``perform_is_skip_and_return_value_patch_available`` in the corresponding
architecture.
- :param Architecture arch: the architecture for the current view
:param int addr: the virtual address of the instruction to be patched
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True if the instruction can be patched, False otherwise
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012f6)
'mov dword [0x10003020], eax'
- >>> bv.is_skip_and_return_value_patch_available(bv.arch, 0x100012f6)
+ >>> bv.is_skip_and_return_value_patch_available(0x100012f6)
False
>>> bv.get_disassembly(0x100012fb)
'call 0x10001629'
- >>> bv.is_skip_and_return_value_patch_available(bv.arch, 0x100012fb)
+ >>> bv.is_skip_and_return_value_patch_available(0x100012fb)
True
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNIsSkipAndReturnValuePatchAvailable(self.handle, arch.handle, addr)
- def convert_to_nop(self, arch, addr):
+ def convert_to_nop(self, addr, arch=None):
"""
``convert_to_nop`` converts the instruction at virtual address ``addr`` to a nop of the provided architecture.
.. note:: This API performs a binary patch, analysis may need to be updated afterward. Additionally the binary\
file must be saved in order to preserve the changes made.
- :param Architecture arch: architecture of the current BinaryView
:param int addr: virtual address of the instruction to conver to nops
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True on success, False on falure.
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012fb)
'call 0x10001629'
- >>> bv.convert_to_nop(bv.arch, 0x100012fb)
+ >>> bv.convert_to_nop(0x100012fb)
True
>>> #The above 'call' instruction is 5 bytes, a nop in x86 is 1 byte,
>>> # thus 5 nops are used:
@@ -2246,9 +2273,11 @@ class BinaryView(object):
>>> bv.get_next_disassembly()
'mov byte [ebp-0x1c], al'
"""
+ if arch is None:
+ arch = self.arch
return core.BNConvertToNop(self.handle, arch.handle, addr)
- def always_branch(self, arch, addr):
+ def always_branch(self, addr, arch=None):
"""
``always_branch`` convert the instruction of architecture ``arch`` at the virtual address ``addr`` to an
unconditional branch.
@@ -2256,23 +2285,25 @@ class BinaryView(object):
.. note:: This API performs a binary patch, analysis may need to be updated afterward. Additionally the binary\
file must be saved in order to preserve the changes made.
- :param Architecture arch: architecture of the current binary view
:param int addr: virtual address of the instruction to be modified
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True on success, False on falure.
:rtype: bool
:Example:
>>> bv.get_disassembly(0x100012ef)
'jg 0x100012f5'
- >>> bv.always_branch(bv.arch, 0x100012ef)
+ >>> bv.always_branch(0x100012ef)
True
>>> bv.get_disassembly(0x100012ef)
'jmp 0x100012f5'
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNAlwaysBranch(self.handle, arch.handle, addr)
- def never_branch(self, arch, addr):
+ def never_branch(self, addr, arch=None):
"""
``never_branch`` convert the branch instruction of architecture ``arch`` at the virtual address ``addr`` to
a fall through.
@@ -2280,23 +2311,25 @@ class BinaryView(object):
.. note:: This API performs a binary patch, analysis may need to be updated afterward. Additionally the binary\
file must be saved in order to preserve the changes made.
- :param Architecture arch: architecture of the current binary view
:param int addr: virtual address of the instruction to be modified
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True on success, False on falure.
:rtype: bool
:Example:
>>> bv.get_disassembly(0x1000130e)
'jne 0x10001317'
- >>> bv.never_branch(bv.arch, 0x1000130e)
+ >>> bv.never_branch(0x1000130e)
True
>>> bv.get_disassembly(0x1000130e)
'nop'
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNConvertToNop(self.handle, arch.handle, addr)
- def invert_branch(self, arch, addr):
+ def invert_branch(self, addr, arch=None):
"""
``invert_branch`` convert the branch instruction of architecture ``arch`` at the virtual address ``addr`` to the
inverse branch.
@@ -2304,63 +2337,69 @@ class BinaryView(object):
.. note:: This API performs a binary patch, analysis may need to be updated afterward. Additionally the binary
file must be saved in order to preserve the changes made.
- :param Architecture arch: architecture of the current binary view
:param int addr: virtual address of the instruction to be modified
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True on success, False on falure.
:rtype: bool
:Example:
>>> bv.get_disassembly(0x1000130e)
'je 0x10001317'
- >>> bv.invert_branch(bv.arch, 0x1000130e)
+ >>> bv.invert_branch(0x1000130e)
True
>>>
>>> bv.get_disassembly(0x1000130e)
'jne 0x10001317'
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNInvertBranch(self.handle, arch.handle, addr)
- def skip_and_return_value(self, arch, addr, value):
+ def skip_and_return_value(self, addr, value, arch=None):
"""
``skip_and_return_value`` convert the ``call`` instruction of architecture ``arch`` at the virtual address
``addr`` to the equivilent of returning a value.
- :param Architecture arch: architecture of the current binary view
:param int addr: virtual address of the instruction to be modified
:param int value: value to make the instruction *return*
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: True on success, False on falure.
:rtype: bool
:Example:
>>> bv.get_disassembly(0x1000132a)
'call 0x1000134a'
- >>> bv.skip_and_return_value(bv.arch, 0x1000132a, 42)
+ >>> bv.skip_and_return_value(0x1000132a, 42)
True
>>> #The return value from x86 functions is stored in eax thus:
>>> bv.get_disassembly(0x1000132a)
'mov eax, 0x2a'
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNSkipAndReturnValue(self.handle, arch.handle, addr, value)
- def get_instruction_length(self, arch, addr):
+ def get_instruction_length(self, addr, arch=None):
"""
``get_instruction_length`` returns the number of bytes in the instruction of Architecture ``arch`` at the virtual
address ``addr``
- :param Architecture arch: architecture of the current binary view
:param int addr: virtual address of the instruction query
+ :param Architecture arch: (optional) the architecture of the instructions if different from the default
:return: Number of bytes in instruction
:rtype: int
:Example:
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
- >>> bv.get_instruction_length(bv.arch, 0x100012f1)
+ >>> bv.get_instruction_length(0x100012f1)
2L
>>>
"""
+ if arch is None:
+ arch = self.arch
return core.BNGetInstructionLength(self.handle, arch.handle, addr)
def notify_data_written(self, offset, length):
diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py
index 23531de0..0fd0dbab 100644
--- a/python/examples/jump_table.py
+++ b/python/examples/jump_table.py
@@ -77,7 +77,7 @@ def find_jump_table(bv, addr):
i += 1
# Set the indirect branch targets on the jump instruction to be the list of targets discovered
- func.set_user_indirect_branches(arch, jump_addr, branches)
+ func.set_user_indirect_branches(jump_addr, branches)
# Create a plugin command so that the user can right click on an instruction referencing a jump table and
# invoke the command
diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py
index c3b47a8d..003b388e 100644
--- a/python/examples/print_syscalls.py
+++ b/python/examples/print_syscalls.py
@@ -43,7 +43,7 @@ def print_syscalls(bv):
syscalls = (il for il in chain.from_iterable(func.low_level_il)
if il.operation == core.BNLowLevelILOperation.LLIL_SYSCALL)
for il in syscalls:
- value = func.get_reg_value_at(bv.arch, il.address, register).value
+ value = func.get_reg_value_at(il.address, register).value
print("System call address: {:#x} - {:d}".format(il.address, value))
diff --git a/python/filemetadata.py b/python/filemetadata.py
index 846c9f94..f6593405 100644
--- a/python/filemetadata.py
+++ b/python/filemetadata.py
@@ -208,7 +208,7 @@ class FileMetadata(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -230,7 +230,7 @@ class FileMetadata(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -252,7 +252,7 @@ class FileMetadata(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
@@ -277,7 +277,7 @@ class FileMetadata(object):
>>> bv.get_disassembly(0x100012f1)
'xor eax, eax'
>>> bv.begin_undo_actions()
- >>> bv.convert_to_nop(bv.arch, 0x100012f1)
+ >>> bv.convert_to_nop(0x100012f1)
True
>>> bv.commit_undo_actions()
>>> bv.get_disassembly(0x100012f1)
diff --git a/python/function.py b/python/function.py
index 2910d283..7253f264 100644
--- a/python/function.py
+++ b/python/function.py
@@ -286,7 +286,7 @@ class Function(object):
@property
def function_type(self):
- """Function type"""
+ """Function type object"""
return bntype.Type(core.BNGetFunctionType(self.handle))
@function_type.setter
@@ -358,10 +358,26 @@ class Function(object):
def set_comment(self, addr, comment):
core.BNSetCommentForAddress(self.handle, addr, comment)
- def get_low_level_il_at(self, arch, addr):
+ def get_low_level_il_at(self, addr, arch=None):
+ """
+ ``get_low_level_il_at`` gets the LowLevelIL instruction address corresponding to the given virtual address
+
+ :param int addr: virtual address of the function to be queried
+ :param Architecture arch: (optional) Architecture for the given function
+ :rtype: int
+ :Example:
+
+ >>> func = bv.functions[0]
+ >>> func.get_low_level_il_at(func.start)
+ 0L
+ """
+ if arch is None:
+ arch = self.arch
return core.BNGetLowLevelILForInstruction(self.handle, arch.handle, addr)
- def get_low_level_il_exits_at(self, arch, addr):
+ def get_low_level_il_exits_at(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
exits = core.BNGetLowLevelILExitsForInstruction(self.handle, arch.handle, addr, count)
result = []
@@ -370,7 +386,21 @@ class Function(object):
core.BNFreeLowLevelILInstructionList(exits)
return result
- def get_reg_value_at(self, arch, addr, reg):
+ def get_reg_value_at(self, addr, reg, arch=None):
+ """
+ ``get_reg_value_at`` gets the value the provided string register address corresponding to the given virtual address
+
+ :param int addr: virtual address of the instruction to query
+ :param str reg: string value of native register to query
+ :param Architecture arch: (optional) Architecture for the given function
+ :rtype: function.RegisterValue
+ :Example:
+
+ >>> func.get_reg_value_at(0x400dbe, 'rdi')
+ <const 0x2>
+ """
+ if arch is None:
+ arch = self.arch
if isinstance(reg, str):
reg = arch.regs[reg].index
value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg)
@@ -378,7 +408,21 @@ class Function(object):
core.BNFreeRegisterValue(value)
return result
- def get_reg_value_after(self, arch, addr, reg):
+ def get_reg_value_after(self, addr, reg, arch=None):
+ """
+ ``get_reg_value_after`` gets the value instruction address corresponding to the given virtual address
+
+ :param int addr: virtual address of the instruction to query
+ :param str reg: string value of native register to query
+ :param Architecture arch: (optional) Architecture for the given function
+ :rtype: function.RegisterValue
+ :Example:
+
+ >>> func.get_reg_value_after(0x400dbe, 'rdi')
+ <undetermined>
+ """
+ if arch is None:
+ arch = self.arch
if isinstance(reg, str):
reg = arch.regs[reg].index
value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg)
@@ -386,11 +430,25 @@ class Function(object):
core.BNFreeRegisterValue(value)
return result
- def get_reg_value_at_low_level_il_instruction(self, i, reg):
+ def get_reg_value_at_low_level_il_instruction(self, i, reg, arch=None):
+ """
+ ``get_reg_value_at_low_level_il_instruction`` returns the value of the specified register ``reg`` at the il address
+ i
+
+ :param int i: il address of instruction to query
+ :param Architecture arch: (optional) Architecture for the given function
+ :rtype: function.RegisterValue
+ :Example:
+
+ >>> func.get_reg_value_at_low_level_il_instruction(15, 'rdi')
+ <const 0x2>
+ """
+ if arch is None:
+ arch = self.arch
if isinstance(reg, str):
reg = self.arch.regs[reg].index
value = core.BNGetRegisterValueAtLowLevelILInstruction(self.handle, i, reg)
- result = RegisterValue(self.arch, value)
+ result = RegisterValue(arch, value)
core.BNFreeRegisterValue(value)
return result
@@ -402,13 +460,35 @@ class Function(object):
core.BNFreeRegisterValue(value)
return result
- def get_stack_contents_at(self, arch, addr, offset, size):
+ def get_stack_contents_at(self, addr, offset, size, arch=None):
+ """
+ ``get_stack_contents_at`` returns the RegisterValue for the item on the stack in the current function at the
+ given virtual address ``addr``, stack offset ``offset`` and size of ``size``. Optionally specifying the architecture.
+
+ :param int addr: virtual address of the instruction to query
+ :param int offset: stack offset base of stack
+ :param int size: size of memory to query
+ :param Architecture arch: (optional) Architecture for the given function
+ :rtype: function.RegisterValue
+
+ .. note:: Stack base is zero on entry into the function unless the architecture places the return address on the
+ stack as in (x86/x86_64) where the stack base will start at address_size
+
+ :Example:
+
+ >>> func.get_stack_contents_at(0x400fad, -16, 4)
+ <range: 0x8 to 0xffffffff>
+ """
+ if arch is None:
+ arch = self.arch
value = core.BNGetStackContentsAtInstruction(self.handle, arch.handle, addr, offset, size)
result = RegisterValue(arch, value)
core.BNFreeRegisterValue(value)
return result
- def get_stack_contents_after(self, arch, addr, offset, size):
+ def get_stack_contents_after(self, addr, offset, size, arch=None):
+ if arch is None:
+ arch = self.arch
value = core.BNGetStackContentsAfterInstruction(self.handle, arch.handle, addr, offset, size)
result = RegisterValue(arch, value)
core.BNFreeRegisterValue(value)
@@ -426,7 +506,9 @@ class Function(object):
core.BNFreeRegisterValue(value)
return result
- def get_parameter_at(self, arch, addr, func_type, i):
+ def get_parameter_at(self, addr, func_type, i, arch=None):
+ if arch is None:
+ arch = self.arch
if func_type is not None:
func_type = func_type.handle
value = core.BNGetParameterValueAtInstruction(self.handle, arch.handle, addr, func_type, i)
@@ -442,7 +524,9 @@ class Function(object):
core.BNFreeRegisterValue(value)
return result
- def get_regs_read_by(self, arch, addr):
+ def get_regs_read_by(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
regs = core.BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, count)
result = []
@@ -451,7 +535,9 @@ class Function(object):
core.BNFreeRegisterList(regs)
return result
- def get_regs_written_by(self, arch, addr):
+ def get_regs_written_by(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
regs = core.BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, count)
result = []
@@ -460,7 +546,9 @@ class Function(object):
core.BNFreeRegisterList(regs)
return result
- def get_stack_vars_referenced_by(self, arch, addr):
+ def get_stack_vars_referenced_by(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count)
result = []
@@ -470,7 +558,9 @@ class Function(object):
core.BNFreeStackVariableReferenceList(refs, count.value)
return result
- def get_constants_referenced_by(self, arch, addr):
+ def get_constants_referenced_by(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count)
result = []
@@ -479,7 +569,9 @@ class Function(object):
core.BNFreeConstantReferenceList(refs)
return result
- def get_lifted_il_at(self, arch, addr):
+ def get_lifted_il_at(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
return core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)
def get_lifted_il_flag_uses_for_definition(self, i, flag):
@@ -531,21 +623,27 @@ class Function(object):
def apply_auto_discovered_type(self, func_type):
core.BNApplyAutoDiscoveredFunctionType(self.handle, func_type.handle)
- def set_auto_indirect_branches(self, source_arch, source, branches):
+ def set_auto_indirect_branches(self, source, branches, source_arch=None):
+ if source_arch is None:
+ source_arch = self.arch
branch_list = (core.BNArchitectureAndAddress * len(branches))()
for i in xrange(len(branches)):
branch_list[i].arch = branches[i][0].handle
branch_list[i].address = branches[i][1]
core.BNSetAutoIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches))
- def set_user_indirect_branches(self, source_arch, source, branches):
+ def set_user_indirect_branches(self, source, branches, source_arch=None):
+ if source_arch is None:
+ source_arch = self.arch
branch_list = (core.BNArchitectureAndAddress * len(branches))()
for i in xrange(len(branches)):
branch_list[i].arch = branches[i][0].handle
branch_list[i].address = branches[i][1]
core.BNSetUserIndirectBranches(self.handle, source_arch.handle, source, branch_list, len(branches))
- def get_indirect_branches_at(self, arch, addr):
+ def get_indirect_branches_at(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong()
branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count)
result = []
@@ -554,7 +652,9 @@ class Function(object):
core.BNFreeIndirectBranchList(branches)
return result
- def get_block_annotations(self, arch, addr):
+ def get_block_annotations(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
count = ctypes.c_ulonglong(0)
lines = core.BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, count)
result = []
@@ -577,10 +677,14 @@ class Function(object):
def set_user_type(self, value):
core.BNSetFunctionUserType(self.handle, value.handle)
- def get_int_display_type(self, arch, instr_addr, value, operand):
+ def get_int_display_type(self, instr_addr, value, operand, arch=None):
+ if arch is None:
+ arch = self.arch
return core.BNGetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand)
- def set_int_display_type(self, arch, instr_addr, value, operand, display_type):
+ def set_int_display_type(self, instr_addr, value, operand, display_type, arch=None):
+ if arch is None:
+ arch = self.arch
if isinstance(display_type, str):
display_type = core.BNIntegerDisplayType[display_type]
core.BNSetIntegerConstantDisplayType(self.handle, arch.handle, instr_addr, value, operand, display_type)
@@ -601,13 +705,17 @@ class Function(object):
core.BNReleaseAdvancedFunctionAnalysisData(self.handle)
self._advanced_analysis_requests -= 1
- def get_basic_block_at(self, arch, addr):
+ def get_basic_block_at(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
block = core.BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr)
if not block:
return None
return basicblock.BasicBlock(self._view, handle = block)
- def get_instr_highlight(self, arch, addr):
+ def get_instr_highlight(self, addr, arch=None):
+ if arch is None:
+ arch = self.arch
color = core.BNGetInstructionHighlight(self.handle, arch.handle, addr)
if color.style == core.BNHighlightColorStyle.StandardHighlightColor:
return highlight.HighlightColor(color = color.color, alpha = color.alpha)
@@ -617,12 +725,16 @@ class Function(object):
return highlight.HighlightColor(red = color.r, green = color.g, blue = color.b, alpha = color.alpha)
return highlight.HighlightColor(color = core.BNHighlightStandardColor.NoHighlightColor)
- def set_auto_instr_highlight(self, arch, addr, color):
+ def set_auto_instr_highlight(self, addr, color, arch=None):
+ if arch is None:
+ arch = self.arch
if not isinstance(color, highlight.HighlightColor):
color = highlight.HighlightColor(color = color)
core.BNSetAutoInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct())
- def set_user_instr_highlight(self, arch, addr, color):
+ def set_user_instr_highlight(self, addr, color, arch=None):
+ if arch is None:
+ arch = self.arch
if not isinstance(color, highlight.HighlightColor):
color = highlight.HighlightColor(color = color)
core.BNSetUserInstructionHighlight(self.handle, arch.handle, addr, color._get_core_struct())
diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py
index 3ccf9560..cbd9696d 100644
--- a/python/scriptingprovider.py
+++ b/python/scriptingprovider.py
@@ -334,6 +334,48 @@ class _PythonScriptingInstanceOutput(object):
self.orig = orig
self.is_error = is_error
self.buffer = ""
+ self.encoding = 'UTF-8'
+ self.errors = None
+ self.isatty = False
+ self.mode = 'w'
+ self.name = 'PythonScriptingInstanceOutput'
+ self.newlines = None
+
+ def close(self):
+ pass
+
+ def closed(self):
+ return False
+
+ def flush(self):
+ pass
+
+ def next(self):
+ raise IOError("File not open for reading")
+
+ def read(self):
+ raise IOError("File not open for reading")
+
+ def readinto(self):
+ raise IOError("File not open for reading")
+
+ def readlines(self):
+ raise IOError("File not open for reading")
+
+ def seek(self):
+ pass
+
+ def sofspace(self):
+ return 0
+
+ def truncate(self):
+ pass
+
+ def tell(self):
+ return self.orig.tell()
+
+ def writelines(self, lines):
+ return self.write('\n'.join(lines))
def write(self, data):
global _output_to_log
@@ -590,6 +632,7 @@ class PythonScriptingProvider(ScriptingProvider):
name = "Python"
instance_class = PythonScriptingInstance
+
PythonScriptingProvider().register()
# Wrap stdin/stdout/stderr for Python scripting provider implementation