From 3f4a7a5d0c18bf91a4b43f574f66e516028e38c9 Mon Sep 17 00:00:00 2001 From: Ryan Snyder Date: Fri, 11 May 2018 15:25:12 -0400 Subject: Fix Python BackgroundTask wrapper --- python/plugin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/plugin.py') diff --git a/python/plugin.py b/python/plugin.py index c6cd9fc0..30a46412 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -560,8 +560,8 @@ class _BackgroundTaskMetaclass(type): tasks = core.BNGetRunningBackgroundTasks(count) result = [] for i in xrange(0, count.value): - result.append(BackgroundTask(core.BNNewBackgroundTaskReference(tasks[i]))) - core.BNFreeBackgroundTaskList(tasks) + result.append(BackgroundTask(handle=core.BNNewBackgroundTaskReference(tasks[i]))) + core.BNFreeBackgroundTaskList(tasks, count.value) return result def __iter__(self): @@ -570,9 +570,9 @@ class _BackgroundTaskMetaclass(type): tasks = core.BNGetRunningBackgroundTasks(count) try: for i in xrange(0, count.value): - yield BackgroundTask(core.BNNewBackgroundTaskReference(tasks[i])) + yield BackgroundTask(handle=core.BNNewBackgroundTaskReference(tasks[i])) finally: - core.BNFreeBackgroundTaskList(tasks) + core.BNFreeBackgroundTaskList(tasks, count.value) class BackgroundTask(object): -- cgit v1.3.1 From 3b433195716732f63f352730d481a0a9415639a1 Mon Sep 17 00:00:00 2001 From: negasora Date: Mon, 11 Jun 2018 19:03:18 -0400 Subject: Add empty list properties to some classes to allow for visibility --- python/architecture.py | 5 +++++ python/binaryview.py | 4 ++++ python/platform.py | 5 +++++ python/plugin.py | 10 ++++++++++ python/scriptingprovider.py | 5 +++++ python/transform.py | 5 +++++ python/update.py | 4 ++++ 7 files changed, 38 insertions(+) (limited to 'python/plugin.py') diff --git a/python/architecture.py b/python/architecture.py index c5f87ec6..df22da7f 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -391,6 +391,11 @@ class Architecture(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def full_width_regs(self): """List of full width register strings (read-only)""" diff --git a/python/binaryview.py b/python/binaryview.py index 0cf25e70..80298304 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -341,6 +341,10 @@ class BinaryViewType(object): if not isinstance(value, BinaryViewType): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass @property def name(self): diff --git a/python/platform.py b/python/platform.py index a79e3b9a..dd756178 100644 --- a/python/platform.py +++ b/python/platform.py @@ -120,6 +120,11 @@ class Platform(object): return True return ctypes.addressof(self.handle.contents) != ctypes.addressof(value.handle.contents) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def default_calling_convention(self): """ diff --git a/python/plugin.py b/python/plugin.py index 30a46412..13ca51af 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -83,6 +83,11 @@ class PluginCommand(object): self.description = str(cmd.description) self.type = PluginCommandType(cmd.type) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @classmethod def _default_action(cls, view, action): try: @@ -587,6 +592,11 @@ class BackgroundTask(object): def __del__(self): core.BNFreeBackgroundTask(self.handle) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @property def progress(self): """Text description of the progress of the background task (displayed in status bar of the UI)""" diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 988f856d..1e2338d9 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -303,6 +303,11 @@ class ScriptingProvider(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNScriptingProvider) self.__dict__["name"] = core.BNGetScriptingProviderName(handle) + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + def register(self): self._cb = core.BNScriptingProviderCallbacks() diff --git a/python/transform.py b/python/transform.py index 59d719e7..3284ed74 100644 --- a/python/transform.py +++ b/python/transform.py @@ -200,6 +200,11 @@ class Transform(object): log.log_error(traceback.format_exc()) return False + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass + @abc.abstractmethod def perform_decode(self, data, params): if self.type == TransformType.InvertingTransform: diff --git a/python/update.py b/python/update.py index 1eb8ea61..2f817595 100644 --- a/python/update.py +++ b/python/update.py @@ -115,6 +115,10 @@ class UpdateChannel(object): self.name = name self.description = desc self.latest_version_num = ver + @property + def list(self): + """Allow tab completion to discover metaclass list property""" + pass @property def versions(self): -- cgit v1.3.1 From 8849fb2b2b8dc824bd3f17ce1026a04856477a94 Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Sun, 4 Mar 2018 18:08:04 -0500 Subject: working division, prints, and metaclasses, but imports broken, still needs work --- python/__init__.py | 60 +-- python/architecture.py | 36 +- python/basicblock.py | 12 +- python/binaryview.py | 66 ++- python/callingconvention.py | 17 +- python/databuffer.py | 4 +- python/demangle.py | 7 +- python/examples/README.md | 56 --- python/examples/angr_plugin.py | 153 ------- python/examples/arch_hook.py | 16 - python/examples/bin_info.py | 72 ---- python/examples/breakpoint.py | 50 --- python/examples/export_svg.py | 224 ----------- python/examples/instruction_iterator.py | 53 --- python/examples/jump_table.py | 86 ---- python/examples/nds.py | 117 ------ python/examples/nes.py | 646 ------------------------------ python/examples/notification_callbacks.py | 51 --- python/examples/nsf.py | 145 ------- python/examples/print_syscalls.py | 55 --- python/examples/version_switcher.py | 150 ------- python/fileaccessor.py | 7 +- python/filemetadata.py | 17 +- python/function.py | 35 +- python/functionrecognizer.py | 14 +- python/generator.cpp | 4 +- python/highlight.py | 6 +- python/interaction.py | 12 +- python/log.py | 5 +- python/lowlevelil.py | 25 +- python/mainthread.py | 6 +- python/mediumlevelil.py | 18 +- python/metadata.py | 7 +- python/platform.py | 19 +- python/plugin.py | 29 +- python/pluginmanager.py | 8 +- python/scriptingprovider.py | 25 +- python/setting.py | 4 +- python/startup.py | 2 +- python/transform.py | 18 +- python/types.py | 15 +- python/undoaction.py | 10 +- python/update.py | 17 +- 43 files changed, 278 insertions(+), 2101 deletions(-) delete mode 100644 python/examples/README.md delete mode 100644 python/examples/angr_plugin.py delete mode 100644 python/examples/arch_hook.py delete mode 100644 python/examples/bin_info.py delete mode 100644 python/examples/breakpoint.py delete mode 100755 python/examples/export_svg.py delete mode 100644 python/examples/instruction_iterator.py delete mode 100644 python/examples/jump_table.py delete mode 100644 python/examples/nds.py delete mode 100644 python/examples/nes.py delete mode 100644 python/examples/notification_callbacks.py delete mode 100644 python/examples/nsf.py delete mode 100644 python/examples/print_syscalls.py delete mode 100644 python/examples/version_switcher.py (limited to 'python/plugin.py') diff --git a/python/__init__.py b/python/__init__.py index fda5f297..66f4bfe8 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -19,41 +19,41 @@ # IN THE SOFTWARE. +from __future__ import absolute_import import atexit import sys from time import gmtime # Binary Ninja components -import _binaryninjacore as core -from .enums import * -from .databuffer import * -from .filemetadata import * -from .fileaccessor import * -from .binaryview import * -from .transform import * -from .architecture import * -from .basicblock import * -from .function import * -from .log import * -from .lowlevelil import * -from .mediumlevelil import * -from .types import * -from .functionrecognizer import * -from .update import * -from .plugin import * -from .callingconvention import * -from .platform import * -from .demangle import * -from .mainthread import * -from .interaction import * -from .lineardisassembly import * -from .undoaction import * -from .highlight import * -from .scriptingprovider import * -from .downloadprovider import * -from .pluginmanager import * -from .setting import * -from .metadata import * +from binaryninja import _binaryninjacore as core +from binaryninja.enums import * +from binaryninja.databuffer import * +from binaryninja.filemetadata import * +from binaryninja.fileaccessor import * +from binaryninja.binaryview import * +from binaryninja.transform import * +from binaryninja.architecture import * +from binaryninja.basicblock import * +from binaryninja.function import * +from binaryninja.log import * +from binaryninja.lowlevelil import * +from binaryninja.mediumlevelil import * +from binaryninja.types import * +from binaryninja.functionrecognizer import * +from binaryninja.update import * +from binaryninja.plugin import * +from binaryninja.callingconvention import * +from binaryninja.platform import * +from binaryninja.demangle import * +from binaryninja.mainthread import * +from binaryninja.interaction import * +from binaryninja.lineardisassembly import * +from binaryninja.undoaction import * +from binaryninja.highlight import * +from binaryninja.scriptingprovider import * +from binaryninja.pluginmanager import * +from binaryninja.setting import * +from binaryninja.metadata import * def shutdown(): diff --git a/python/architecture.py b/python/architecture.py index df22da7f..360ce6bf 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -18,25 +18,22 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +from __future__ import absolute_import import traceback import ctypes import abc -# Binary Ninja components -import _binaryninjacore as core -from enums import (Endianness, ImplicitRegisterExtend, BranchType, +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import (Endianness, ImplicitRegisterExtend, BranchType, InstructionTextTokenType, LowLevelILFlagCondition, FlagRole) -import startup -import function -import lowlevelil -import callingconvention -import platform -import log -import databuffer -import types + +#2-3 compatibility +from six import with_metaclass class _ArchitectureMetaClass(type): + from binaryninja import startup @property def list(self): startup._init_plugins() @@ -80,12 +77,12 @@ class _ArchitectureMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) -class Architecture(object): +class Architecture(with_metaclass(_ArchitectureMetaClass, object)): """ ``class Architecture`` is the parent class for all CPU architectures. Subclasses of Architecture implement assembly, disassembly, IL lifting, and patching. - ``class Architecture`` has a ``__metaclass__`` with the additional methods ``register``, and supports + ``class Architecture`` has a metaclass with the additional methods ``register``, and supports iteration:: >>> #List the architectures @@ -130,10 +127,17 @@ class Architecture(object): semantic_class_for_flag_write_type = {} reg_stacks = {} intrinsics = {} - __metaclass__ = _ArchitectureMetaClass next_address = 0 def __init__(self): + from binaryninja import function + from binaryninja import startup + from binaryninja import lowlevelil + from binaryninja import types + from binaryninja import databuffer + from binaryninja import log + from binaryninja import platform + from binaryninja import callingconvention startup._init_plugins() if self.__class__.opcode_display_length > self.__class__.max_instr_length: @@ -2045,6 +2049,10 @@ class Architecture(object): _architecture_cache = {} class CoreArchitecture(Architecture): def __init__(self, handle): + from binaryninja import function + from binaryninja import types + from binaryninja import databuffer + from binaryninja import lowlevelil super(CoreArchitecture, self).__init__() self.handle = core.handle_of_type(handle, core.BNArchitecture) diff --git a/python/basicblock.py b/python/basicblock.py index a79b53ad..907b4065 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -20,12 +20,9 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType -import architecture -import highlight -import function +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType class BasicBlockEdge(object): @@ -54,6 +51,9 @@ class BasicBlockEdge(object): class BasicBlock(object): def __init__(self, view, handle): + from binaryninja import architecture + from binaryninja import function + from binaryninja import highlight self.view = view self.handle = core.handle_of_type(handle, core.BNBasicBlock) self._arch = None diff --git a/python/binaryview.py b/python/binaryview.py index 1e078523..f6a1bc83 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -24,23 +24,14 @@ import ctypes import abc import threading -# Binary Ninja components -import _binaryninjacore as core -from enums import (AnalysisState, SymbolType, InstructionTextTokenType, +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import (AnalysisState, SymbolType, InstructionTextTokenType, Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) -import function -import startup -import architecture -import platform -import associateddatastore -import fileaccessor -import filemetadata -import log -import databuffer -import basicblock -import types -import lineardisassembly -import metadata +from binaryninja import associateddatastore # required for _BinaryViewAssociatedDataStore + +#2-3 compatibility +from six import with_metaclass class BinaryDataNotification(object): @@ -113,12 +104,13 @@ class AnalysisCompletionEvent(object): :Example: >>> def on_complete(self): - ... print "Analysis Complete", self.view + ... print("Analysis Complete", self.view) ... >>> evt = AnalysisCompletionEvent(bv, on_complete) >>> """ def __init__(self, view, callback): + from binaryninja import log self.view = view self.callback = callback self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify) @@ -197,6 +189,9 @@ class DataVariable(object): class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): + from binaryninja import function + from binaryninja import types + from binaryninja import log self.view = view self.notify = notify self._cb = core.BNBinaryDataNotification() @@ -319,6 +314,7 @@ class BinaryDataNotificationCallbacks(object): class _BinaryViewTypeMetaclass(type): + from binaryninja import startup @property def list(self): """List all BinaryView types (read-only)""" @@ -349,10 +345,12 @@ class _BinaryViewTypeMetaclass(type): return BinaryViewType(view_type) -class BinaryViewType(object): - __metaclass__ = _BinaryViewTypeMetaclass +class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): def __init__(self, handle): + from binaryninja import architecture + from binaryninja import filemetadata + from binaryninja import platform self.handle = core.handle_of_type(handle, core.BNBinaryViewType) def __eq__(self, value): @@ -581,6 +579,18 @@ class BinaryView(object): database (e.g. ``remove_user_function()`` rather than ``remove_function()``). Thus use ``_user_`` methods if saving \ to the database is desired. """ + import binaryninja.function + import binaryninja.architecture + import binaryninja.platform + import binaryninja.fileaccessor + import binaryninja.filemetadata + import binaryninja.databuffer + import binaryninja.basicblock + import binaryninja.types + import binaryninja.log + import binaryninja.startup + import binaryninja.lineardisassembly + import binaryninja.metadata name = None long_name = None _registered = False @@ -590,6 +600,18 @@ class BinaryView(object): _associated_data = {} def __init__(self, file_metadata=None, parent_view=None, handle=None): + function = binaryninja.function + architecture = binaryninja.architecture + platform = binaryninja.platform + fileaccessor = binaryninja.fileaccessor + filemetadata = binaryninja.filemetadata + databuffer = binaryninja.databuffer + basicblock = binaryninja.basicblock + types = binaryninja.types + log = binaryninja.log + startup = binaryninja.startup + lineardisassembly = binaryninja.lineardisassembly + metadata = binaryninja.metadata if handle is not None: self.handle = core.handle_of_type(handle, core.BNBinaryView) if file_metadata is None: @@ -680,7 +702,7 @@ class BinaryView(object): @classmethod def open(cls, src, file_metadata=None): - startup._init_plugins() + binaryninja.startup._init_plugins() if isinstance(src, fileaccessor.FileAccessor): if file_metadata is None: file_metadata = filemetadata.FileMetadata() @@ -2790,7 +2812,7 @@ class BinaryView(object): :Example: >>> def completionEvent(): - ... print "done" + ... print("done") ... >>> bv.add_analysis_completion_event(completionEvent) @@ -3098,7 +3120,7 @@ class BinaryView(object): >>> settings = DisassemblySettings() >>> lines = bv.get_linear_disassembly(settings) >>> for line in lines: - ... print line + ... print(line) ... break ... cf fa ed fe 07 00 00 01 ........ diff --git a/python/callingconvention.py b/python/callingconvention.py index e3ec7261..ab8058fc 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -21,17 +21,11 @@ import traceback import ctypes -# Binary Ninja components -import _binaryninjacore as core -import architecture -import log -import types -import function -import binaryview -from enums import VariableSourceType - +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class CallingConvention(object): + from binaryninja import types name = None caller_saved_regs = [] int_arg_regs = [] @@ -48,6 +42,11 @@ class CallingConvention(object): _registered_calling_conventions = [] def __init__(self, arch=None, name=None, handle=None, confidence=types.max_confidence): + from binaryninja import architecture + from binaryninja import log + from binaryninja import function + from binaryninja import binaryview + from binaryninja.enums import VariableSourceType if handle is None: if arch is None or name is None: raise ValueError("Must specify either handle or architecture and name") diff --git a/python/databuffer.py b/python/databuffer.py index 3f9e4ce5..bf366750 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -20,8 +20,8 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class DataBuffer(object): diff --git a/python/demangle.py b/python/demangle.py index 11673263..50322694 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -20,9 +20,8 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core -import types +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core def get_qualified_name(names): @@ -56,6 +55,7 @@ def demangle_ms(arch, mangled_name): (, ['Foobar', 'testf']) >>> """ + from binaryninja import types handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() @@ -69,6 +69,7 @@ def demangle_ms(arch, mangled_name): def demangle_gnu3(arch, mangled_name): + from binaryninja import types handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() outSize = ctypes.c_ulonglong() diff --git a/python/examples/README.md b/python/examples/README.md deleted file mode 100644 index 43af34be..00000000 --- a/python/examples/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# Binary Ninja Python API Examples - -The following examples demonstrate some of the Binary Ninja API. They include both stand-alone examples that directly call into the core without a GUI, as well as examples meant to be loaded as plugins available from the UI. - -## Stand-alone - -These plugins only operate when run directly outside of the UI - -* bin_info.py - general binary information -* print_syscalls.py - extract syscall numbers from IL on specified file. Can be run both headless and in Binary Ninja -* version_switcher.py - uses the update API to see raw version notes and manually downgrade or upgrade -* instruction_iterator.py - very simple plugin that iterates through functions, blocks, and instructions - -To use the stand-alone Python examples, make sure your `PYTHON_PATH` includes the API, as shown below. Please note, this is a feature that requires the "GUI-less processing" capability not available in the personal edition. In the personal edition, all scripts must by run from the integrated python console (follow the directions below under "Loading Plugins" section) - -``` -PYTHONPATH=$PYTHONPATH:/Applications/Binary\ Ninja.app/Contents/Resources/python -``` - -## GUI Plugins - -These plugins require the UI to be running - -* breakpoint.py - small example showing how to modify a file and register a GUI menu item -* jump_table.py - heuristic based jump table detection for when the data-flow based computation fails, triggered by right-clicking on the location where the jump value is computed -* angr_plugin.py - a plugin to demonstrate both background threads, the simplified plugin UI elements, and highlighting -* export_svg.py - exports the graph view of a function to an SVG file for including in reports - -## Both - -These plugins are able to operate in either the GUI or as stand-alone plugins - -* nes.py - 6502 CPU architecture including LLIL lifting and `.NES` file format parser - - -## Loading Plugins - -Plugins are meant to be loaded into a running Binary Ninja GUI and should either be copied or symlinked into the appropriate plugin folder. You'll need to then re-start Binary Ninja. - -### OSX - -``` -~/Library/Application Support/Binary Ninja/plugins -``` - -### Windows - -``` -%APPDATA%\Binary Ninja\plugins -``` - -### Linux - -``` -~/.binaryninja/plugins -``` diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py deleted file mode 100644 index 26f8040c..00000000 --- a/python/examples/angr_plugin.py +++ /dev/null @@ -1,153 +0,0 @@ -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -# This plugin assumes angr is already installed and available on the system. See the angr documentation -# for information about installing angr. It should be installed using the virtualenv method. -# -# This plugin is currently only known to work on Linux using virtualenv. Switch to the virtual environment -# (using a command such as "workon angr"), then run the Binary Ninja UI from the command line. -# -# This method is known to fail on Mac OS X as the virtualenv used by angr does not appear to provide a -# way to automatically link to the correct version of Python, even when running the UI from within the -# virtual environment. A later update may allow for a manual override to link to the required version -# of Python. - -import tempfile -import logging -import os - -__name__ = "__console__" # angr looks for this, it won't load from within a UI without it - -import angr -# For the lazy instead you can just import everything 'from binaryninja import *'' -from binaryninja.binaryview import BinaryView -from binaryninja.plugin import BackgroundTaskThread, PluginCommand -from binaryninja.interaction import show_plain_text_report, show_message_box -from binaryninja.highlight import HighlightColor -from binaryninja.enums import HighlightStandardColor, MessageBoxButtonSet, MessageBoxIcon - -# Disable warning logs as they show up as errors in the UI -logging.disable(logging.WARNING) - -# Create sets in the BinaryView's data field to store the desired path for each view -BinaryView.set_default_session_data("angr_find", set()) -BinaryView.set_default_session_data("angr_avoid", set()) - - -def escaped_output(str): - return '\n'.join([s.encode("string_escape") for s in str.split('\n')]) - - -# Define a background thread object for solving in the background -class Solver(BackgroundTaskThread): - def __init__(self, find, avoid, view): - BackgroundTaskThread.__init__(self, "Solving with angr...", True) - self.find = tuple(find) - self.avoid = tuple(avoid) - self.view = view - - # Write the binary to disk so that the angr API can read it - self.binary = tempfile.NamedTemporaryFile() - self.binary.write(view.file.raw.read(0, len(view.file.raw))) - self.binary.flush() - - def run(self): - # Create an angr project and an explorer with the user's settings - p = angr.Project(self.binary.name) - e = p.surveyors.Explorer(find = self.find, avoid = self.avoid) - - # Solve loop - while not e.done: - if self.cancelled: - # Solve cancelled, show results if there were any - if len(e.found) > 0: - break - return - - # Perform the next step in the solve - e.step() - - # Update status - active_count = len(e.active) - found_count = len(e.found) - - progress = "Solving with angr (%d active path%s" % (active_count, "s" if active_count != 1 else "") - if found_count > 0: - progress += ", %d path%s found" % (found_count, "s" if found_count != 1 else "") - self.progress = progress + ")..." - - # Solve complete, show report - text_report = "Found %d path%s.\n\n" % (len(e.found), "s" if len(e.found) != 1 else "") - i = 1 - for f in e.found: - text_report += "Path %d\n" % i + "=" * 10 + "\n" - text_report += "stdin:\n" + escaped_output(f.state.posix.dumps(0)) + "\n\n" - text_report += "stdout:\n" + escaped_output(f.state.posix.dumps(1)) + "\n\n" - text_report += "stderr:\n" + escaped_output(f.state.posix.dumps(2)) + "\n\n" - i += 1 - - name = self.view.file.filename - if len(name) > 0: - show_plain_text_report("Results from angr - " + os.path.basename(self.view.file.filename), text_report) - else: - show_plain_text_report("Results from angr", text_report) - - -def find_instr(bv, addr): - # Highlight the instruction in green - blocks = bv.get_basic_blocks_at(addr) - for block in blocks: - block.set_auto_highlight(HighlightColor(HighlightStandardColor.GreenHighlightColor, alpha = 128)) - block.function.set_auto_instr_highlight(addr, HighlightStandardColor.GreenHighlightColor) - - # Add the instruction to the list associated with the current view - bv.session_data.angr_find.add(addr) - - -def avoid_instr(bv, addr): - # Highlight the instruction in red - blocks = bv.get_basic_blocks_at(addr) - for block in blocks: - block.set_auto_highlight(HighlightColor(HighlightStandardColor.RedHighlightColor, alpha = 128)) - block.function.set_auto_instr_highlight(addr, HighlightStandardColor.RedHighlightColor) - - # Add the instruction to the list associated with the current view - bv.session_data.angr_avoid.add(addr) - - -def solve(bv): - if len(bv.session_data.angr_find) == 0: - show_message_box("Angr Solve", "You have not specified a goal instruction.\n\n" + - "Please right click on the goal instruction and select \"Find Path to This Instruction\" to " + - "continue.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon) - return - - # Start a solver thread for the path associated with the view - s = Solver(bv.session_data.angr_find, bv.session_data.angr_avoid, bv) - s.start() - - -# Register commands for the user to interact with the plugin -PluginCommand.register_for_address("Find Path to This Instruction", - "When solving, find a path that gets to this instruction", find_instr) -PluginCommand.register_for_address("Avoid This Instruction", - "When solving, avoid paths that reach this instruction", avoid_instr) -PluginCommand.register("Solve With Angr", "Attempt to solve for a path that satisfies the constraints given", solve) diff --git a/python/examples/arch_hook.py b/python/examples/arch_hook.py deleted file mode 100644 index 452bd2b6..00000000 --- a/python/examples/arch_hook.py +++ /dev/null @@ -1,16 +0,0 @@ -from binaryninja.architecture import Architecture, ArchitectureHook - -class X86ReturnHook(ArchitectureHook): - def get_instruction_text(self, data, addr): - # Call the original implementation's method by calling the superclass - result, length = super(X86ReturnHook, self).get_instruction_text(data, addr) - - # Patch the name of the 'retn' instruction to 'ret' - if len(result) > 0 and result[0].text == 'retn': - result[0].text = 'ret' - - return result, length - -# Install the hook by constructing it with the desired architecture to hook, then registering it -X86ReturnHook(Architecture['x86']).register() - diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py deleted file mode 100644 index 17a96685..00000000 --- a/python/examples/bin_info.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import sys -import binaryninja.log as log -from binaryninja.binaryview import BinaryViewType -import binaryninja.interaction as interaction -from binaryninja.plugin import PluginCommand - - -def get_bininfo(bv): - if bv is None: - filename = "" - if len(sys.argv) > 1: - filename = sys.argv[1] - else: - filename = interaction.get_open_filename_input("Filename:") - if filename is None: - log.log_warn("No file specified") - sys.exit(1) - - bv = BinaryViewType.get_view_of_file(filename) - log.log_to_stdout(True) - - contents = "## %s ##\n" % bv.file.filename - contents += "- START: 0x%x\n\n" % bv.start - contents += "- ENTRY: 0x%x\n\n" % bv.entry_point - contents += "- ARCH: %s\n\n" % bv.arch.name - contents += "### First 10 Functions ###\n" - - contents += "| Start | Name |\n" - contents += "|------:|:-------|\n" - for i in xrange(min(10, len(bv.functions))): - contents += "| 0x%x | %s |\n" % (bv.functions[i].start, bv.functions[i].symbol.full_name) - - contents += "### First 10 Strings ###\n" - contents += "| Start | Length | String |\n" - contents += "|------:|-------:|:-------|\n" - for i in xrange(min(10, len(bv.strings))): - start = bv.strings[i].start - length = bv.strings[i].length - string = bv.read(start, length) - contents += "| 0x%x |%d | %s |\n" % (start, length, string) - return contents - - -def display_bininfo(bv): - interaction.show_markdown_report("Binary Info Report", get_bininfo(bv)) - - -if __name__ == "__main__": - print get_bininfo(None) -else: - PluginCommand.register("Binary Info", "Display basic info about the binary", display_bininfo) diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py deleted file mode 100644 index a2801511..00000000 --- a/python/examples/breakpoint.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - - -from binaryninja.plugin import PluginCommand -from binaryninja.log import log_error - - -def write_breakpoint(view, start, length): - """Sample function to show registering a plugin menu item for a range of bytes. Also possible: - register - register_for_address - register_for_function - """ - bkpt_str = { - "x86": "int3", - "x86_64": "int3", - "armv7": "bkpt", - "aarch64": "brk #0", - "mips32": "break"} - - if view.arch.name not in bkpt_str: - log_error("Architecture %s not supported" % view.arch.name) - return - - bkpt, err = view.arch.assemble(bkpt_str[view.arch.name]) - if bkpt is None: - log_error(err) - return - view.write(start, bkpt * length / len(bkpt)) - - -PluginCommand.register_for_range("Convert to breakpoint", "Fill region with breakpoint instructions.", write_breakpoint) diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py deleted file mode 100755 index 7814c9fd..00000000 --- a/python/examples/export_svg.py +++ /dev/null @@ -1,224 +0,0 @@ -# from binaryninja import * -import os -import webbrowser -import time -try: - from urllib import pathname2url # Python 2.x -except: - from urllib.request import pathname2url # Python 3.x - -from binaryninja.interaction import get_save_filename_input, show_message_box -from binaryninja.enums import MessageBoxButtonSet, MessageBoxIcon, MessageBoxButtonResult, InstructionTextTokenType, BranchType -from binaryninja.plugin import PluginCommand - -colors = {'green': [162, 217, 175], 'red': [222, 143, 151], 'blue': [128, 198, 233], 'cyan': [142, 230, 237], 'lightCyan': [176, 221, 228], 'orange': [237, 189, 129], 'yellow': [237, 223, 179], 'magenta': [218, 196, 209], 'none': [74, 74, 74]} - -escape_table = { - "'": "'", - ">": ">", - "<": "<", - '"': """, - ' ': " " -} - - -def escape(toescape): - toescape = toescape.decode('utf-8').encode('ascii', 'xmlcharrefreplace') # handle extended unicode - return ''.join(escape_table.get(i, i) for i in toescape) # still escape the basics - - -def save_svg(bv, function): - address = hex(function.start).replace('L', '') - path = os.path.dirname(bv.file.filename) - origname = os.path.basename(bv.file.filename) - filename = os.path.join(path, 'binaryninja-{filename}-{function}.html'.format(filename=origname, function=address)) - outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename) - if outputfile is None: - return - content = render_svg(function, origname) - output = open(outputfile, 'w') - output.write(content) - output.close() - result = show_message_box("Open SVG", "Would you like to view the exported SVG?", - buttons = MessageBoxButtonSet.YesNoButtonSet, icon = MessageBoxIcon.QuestionIcon) - if result == MessageBoxButtonResult.YesButton: - url = 'file:{}'.format(pathname2url(outputfile)) - webbrowser.open(url) - - -def instruction_data_flow(function, address): - ''' TODO: Extract data flow information ''' - length = function.view.get_instruction_length(address) - bytes = function.view.read(address, length) - hex = bytes.encode('hex') - padded = ' '.join([hex[i:i + 2] for i in range(0, len(hex), 2)]) - return 'Opcode: {bytes}'.format(bytes=padded) - - -def render_svg(function, origname): - graph = function.create_graph() - graph.layout_and_wait() - heightconst = 15 - ratio = 0.48 - widthconst = heightconst * ratio - - output = ''' - - - - -''' - output += ''' - - - - - - - - - - - - - - - '''.format(width=graph.width * widthconst + 20, height=graph.height * heightconst + 20) - output += ''' - Function Graph 0 - ''' - edges = '' - for i, block in enumerate(graph.blocks): - - # Calculate basic block location and coordinates - x = ((block.x) * widthconst) - y = ((block.y) * heightconst) - width = ((block.width) * widthconst) - height = ((block.height) * heightconst) - - # Render block - output += ' \n'.format(i=i) - output += ' Basic Block {i}\n'.format(i=i) - rgb = colors['none'] - try: - bb = block.basic_block - color_code = bb.highlight.color - color_str = bb.highlight._standard_color_to_str(color_code) - if color_str in colors: - rgb = colors[color_str] - except: - pass - output += ' \n'.format(x=x, y=y, width=width + 16, height=height + 12, r=rgb[0], g=rgb[1], b=rgb[2]) - - # Render instructions, unfortunately tspans don't allow copying/pasting more - # than one line at a time, need SVG 1.2 textarea tags for that it looks like - - output += ' \n'.format(x=x, y=y + (i + 1) * heightconst) - for i, line in enumerate(block.lines): - output += ' '.format(x=x + 6, y=y + 6 + (i + 0.7) * heightconst, address=hex(line.address)[:-1]) - hover = instruction_data_flow(function, line.address) - output += '{hover}'.format(hover=hover) - for token in line.tokens: - # TODO: add hover for hex, function, and reg tokens - output += '{text}'.format(text=escape(token.text), tokentype=InstructionTextTokenType(token.type).name) - output += '\n' - output += ' \n' - output += ' \n' - - # Edges are rendered in a seperate chunk so they have priority over the - # basic blocks or else they'd render below them - - for edge in block.outgoing_edges: - points = "" - x, y = edge.points[0] - points += str(x * widthconst) + "," + str(y * heightconst + 12) + " " - for x, y in edge.points[1:-1]: - points += str(x * widthconst) + "," + str(y * heightconst) + " " - x, y = edge.points[-1] - points += str(x * widthconst) + "," + str(y * heightconst + 0) + " " - if edge.back_edge: - edges += ' \n'.format(type=BranchType(edge.type).name, points=points) - else: - edges += ' \n'.format(type=BranchType(edge.type).name, points=points) - output += ' ' + edges + '\n' - output += ' \n' - output += '' - - output += '

This CFG generated by Binary Ninja from {filename} on {timestring}.

'.format(filename = origname, timestring = time.strftime("%c")) - output += '' - return output - - -PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function", save_svg) diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py deleted file mode 100644 index f55e1c1b..00000000 --- a/python/examples/instruction_iterator.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import sys -import binaryninja as binja - -if len(sys.argv) > 1: - target = sys.argv[1] - -bv = binja.BinaryViewType.get_view_of_file(target) -binja.log_to_stdout(True) -binja.log_info("-------- %s --------" % target) -binja.log_info("START: 0x%x" % bv.start) -binja.log_info("ENTRY: 0x%x" % bv.entry_point) -binja.log_info("ARCH: %s" % bv.arch.name) -binja.log_info("\n-------- Function List --------") - -""" print all the functions, their basic blocks, and their il instructions """ -for func in bv.functions: - binja.log_info(repr(func)) - for block in func.low_level_il: - binja.log_info("\t{0}".format(block)) - - for insn in block: - binja.log_info("\t\t{0}".format(insn)) - - -""" print all the functions, their basic blocks, and their mc instructions """ -for func in bv.functions: - binja.log_info(repr(func)) - for block in func: - binja.log_info("\t{0}".format(block)) - - for insn in block: - binja.log_info("\t\t{0}".format(insn)) diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py deleted file mode 100644 index 419cc188..00000000 --- a/python/examples/jump_table.py +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# This plugin will attempt to resolve simple jump tables (an array of code pointers) and add the destinations -# as indirect branch targets so that the flow graph reflects the jump table's control flow. -from binaryninja.plugin import PluginCommand -from binaryninja.enums import InstructionTextTokenType -import struct - - -def find_jump_table(bv, addr): - for block in bv.get_basic_blocks_at(addr): - func = block.function - arch = func.arch - addrsize = arch.address_size - - # Grab the instruction tokens so that we can look for the table's starting address - tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr) - - # Look for the next jump instruction, which may be the current instruction. Some jump tables will - # compute the address first then jump to the computed address as a separate instruction. - jump_addr = addr - while jump_addr < block.end: - info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr) - if len(info.branches) != 0: - break - jump_addr += info.length - if jump_addr >= block.end: - print "Unable to find jump after instruction 0x%x" % addr - continue - print "Jump at 0x%x" % jump_addr - - # Collect the branch targets for any tables referenced by the clicked instruction - branches = [] - for token in tokens: - if InstructionTextTokenType(token.type) == InstructionTextTokenType.PossibleAddressToken: # Table addresses will be a "possible address" token - tbl = token.value - print "Found possible table at 0x%x" % tbl - i = 0 - while True: - # Read the next pointer from the table - data = bv.read(tbl + (i * addrsize), addrsize) - if len(data) == addrsize: - if addrsize == 4: - ptr = struct.unpack("= bv.start) and (ptr < bv.end): - print "Found destination 0x%x" % ptr - branches.append((arch, ptr)) - else: - # Once a value that is not a pointer is encountered, the jump table is ended - break - else: - # Reading invalid memory - break - - i += 1 - - # Set the indirect branch targets on the jump instruction to be the list of targets discovered - 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 -PluginCommand.register_for_address("Process jump table", "Look for jump table destinations", find_jump_table) diff --git a/python/examples/nds.py b/python/examples/nds.py deleted file mode 100644 index 34d8a292..00000000 --- a/python/examples/nds.py +++ /dev/null @@ -1,117 +0,0 @@ -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -# from binaryninja import * -from binaryninja.binaryview import BinaryView -from binaryninja.architecture import Architecture -from binaryninja.enums import SegmentFlag -from binaryninja.log import log_error - -import struct -import traceback - - -def crc16(data): - crc = 0xffff - for ch in data: - crc ^= ord(ch) - for bit in xrange(0, 8): - if (crc & 1) == 1: - crc = (crc >> 1) ^ 0xa001 - else: - crc >>= 1 - return crc - - -class DSView(BinaryView): - def __init__(self, data): - BinaryView.__init__(self, file_metadata = data.file, parent_view = data) - self.raw = data - - @classmethod - def is_valid_for_data(self, data): - hdr = data.read(0, 0x160) - if len(hdr) < 0x160: - return False - if struct.unpack("> 4) - self.ram_banks = struct.unpack("B", hdr[8])[0] - self.rom_offset = 16 - if self.rom_flags & 4: - self.rom_offset += 512 - self.rom_length = self.rom_banks * 0x4000 - - # Add mapping for RAM and hardware registers, not backed by file contents - self.add_auto_segment(0, 0x8000, 0, 0, SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable | SegmentFlag.SegmentExecutable) - - # Add ROM mappings - self.add_auto_segment(0x8000, 0x4000, self.rom_offset + (self.__class__.bank * 0x4000), 0x4000, - SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable) - self.add_auto_segment(0xc000, 0x4000, self.rom_offset + self.rom_length - 0x4000, 0x4000, - SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable) - - nmi = struct.unpack("= 0x8000: - self.add_function(addr) - - return True - except: - log_error(traceback.format_exc()) - return False - - def perform_is_executable(self): - return True - - def perform_get_entry_point(self): - return struct.unpack("'.format(sys.argv[0])) - else: - print_syscalls(sys.argv[1]) diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py deleted file mode 100644 index 3e1cab40..00000000 --- a/python/examples/version_switcher.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2015-2017 Vector 35 LLC -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. - -import sys - -from binaryninja.update import UpdateChannel, are_auto_updates_enabled, set_auto_updates_enabled, is_update_installation_pending, install_pending_update -from binaryninja import core_version -import datetime - -chandefault = UpdateChannel.list[0].name -channel = None -versions = [] - - -def load_channel(newchannel): - global channel - global versions - if (channel is not None and newchannel == channel.name): - print "Same channel, not updating." - else: - try: - print "Loading channel %s" % newchannel - channel = UpdateChannel[newchannel] - print "Loading versions..." - versions = channel.versions - except Exception: - print "%s is not a valid channel name. Defaulting to " % chandefault - channel = UpdateChannel[chandefault] - - -def select(version): - done = False - date = datetime.datetime.fromtimestamp(version.time).strftime('%c') - while not done: - print "Version:\t%s" % version.version - print "Updated:\t%s" % date - print "Notes:\n\n-----\n%s" % version.notes - print "-----" - print "\t1)\tSwitch to version" - print "\t2)\tMain Menu" - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection == 2): - done = True - elif (selection == 1): - if (version.version == channel.latest_version.version): - print "Requesting update to latest version." - else: - print "Requesting update to prior version." - if are_auto_updates_enabled(): - print "Disabling automatic updates." - set_auto_updates_enabled(False) - if (version.version == core_version): - print "Already running %s" % version.version - else: - print "version.version %s" % version.version - print "core_version %s" % core_version - print "Downloading..." - print version.update() - print "Installing..." - if is_update_installation_pending: - #note that the GUI will be launched after update but should still do the upgrade headless - install_pending_update() - # forward updating won't work without reloading - sys.exit() - else: - print "Invalid selection" - - -def list_channels(): - done = False - print "\tSelect channel:\n" - while not done: - channel_list = UpdateChannel.list - for index, item in enumerate(channel_list): - print "\t%d)\t%s" % (index + 1, item.name) - print "\t%d)\t%s" % (len(channel_list) + 1, "Main Menu") - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection <= 0 or selection > len(channel_list) + 1): - print "%s is an invalid choice." % selection - else: - done = True - if (selection != len(channel_list) + 1): - load_channel(channel_list[selection - 1].name) - - -def toggle_updates(): - set_auto_updates_enabled(not are_auto_updates_enabled()) - - -def main(): - global channel - done = False - load_channel(chandefault) - while not done: - print "\n\tBinary Ninja Version Switcher" - print "\t\tCurrent Channel:\t%s" % channel.name - print "\t\tCurrent Version:\t%s" % core_version - print "\t\tAuto-Updates On:\t%s\n" % are_auto_updates_enabled() - for index, version in enumerate(versions): - date = datetime.datetime.fromtimestamp(version.time).strftime('%c') - print "\t%d)\t%s (%s)" % (index + 1, version.version, date) - print "\t%d)\t%s" % (len(versions) + 1, "Switch Channel") - print "\t%d)\t%s" % (len(versions) + 2, "Toggle Auto Updates") - print "\t%d)\t%s" % (len(versions) + 3, "Exit") - selection = raw_input('Choice: ') - if selection.isdigit(): - selection = int(selection) - else: - selection = 0 - if (selection <= 0 or selection > len(versions) + 3): - print "%d is an invalid choice.\n\n" % selection - else: - if (selection == len(versions) + 3): - done = True - elif (selection == len(versions) + 2): - toggle_updates() - elif (selection == len(versions) + 1): - list_channels() - else: - select(versions[selection - 1]) - - -if __name__ == "__main__": - main() diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 2c1f1d19..5a602b89 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -21,12 +21,11 @@ import traceback import ctypes -# Binary Ninja components -import _binaryninjacore as core -import log - +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class FileAccessor(object): + from binaryninja import log def __init__(self): self._cb = core.BNFileAccessor() self._cb.context = 0 diff --git a/python/filemetadata.py b/python/filemetadata.py index 4bfc0214..695b95f3 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -18,18 +18,17 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +from __future__ import absolute_import import traceback import ctypes -# Binary Ninja components -import _binaryninjacore as core -import startup -import associateddatastore -import log -import binaryview +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja import associateddatastore #required for _FileMetadataAssociatedDataStore class NavigationHandler(object): + from binaryninja import log def _register(self, handle): self._cb = core.BNNavigationHandler() self._cb.context = 0 @@ -66,12 +65,14 @@ class _FileMetadataAssociatedDataStore(associateddatastore._AssociatedDataStore) class FileMetadata(object): - _associated_data = {} - """ ``class FileMetadata`` represents the file being analyzed by Binary Ninja. It is responsible for opening, closing, creating the database (.bndb) files, and is used to keep track of undoable actions. """ + from binaryninja import startup + from binaryninja import binaryview + _associated_data = {} + def __init__(self, filename = None, handle = None): """ Instantiates a new FileMetadata class. diff --git a/python/function.py b/python/function.py index 2f794f47..2ee9b20d 100644 --- a/python/function.py +++ b/python/function.py @@ -18,27 +18,18 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +from __future__ import absolute_import import threading import traceback import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, FunctionAnalysisSkipOverride) -import architecture -import platform -import highlight -import associateddatastore -import types -import basicblock -import lowlevelil -import mediumlevelil -import binaryview -import log -import callingconvention +from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore class LookupTableEntry(object): @@ -51,6 +42,7 @@ class LookupTableEntry(object): class RegisterValue(object): + from binaryninja import types def __init__(self, arch = None, value = None, confidence = types.max_confidence): self.is_constant = False if value is None: @@ -329,6 +321,7 @@ class IndirectBranchInfo(object): class ParameterVariables(object): + from binaryninja import types def __init__(self, var_list, confidence = types.max_confidence): self.vars = var_list self.confidence = confidence @@ -355,6 +348,14 @@ class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore): class Function(object): + from binaryninja import callingconvention + from binaryninja import mediumlevelil + from binaryninja import lowlevelil + from binaryninja import basicblock + from binaryninja import types + from binaryninja import highlight + from binaryninja import platform + from binaryninja import architecture _associated_data = {} def __init__(self, view, handle): @@ -1631,7 +1632,8 @@ class FunctionGraphEdge(object): class FunctionGraphBlock(object): - def __init__(self, handle, graph): + def __init__(self, handle): + from binaryninja import binaryview self.handle = handle self.graph = graph @@ -1839,6 +1841,8 @@ class DisassemblySettings(object): class FunctionGraph(object): + from binaryninja import log + from binaryninja import types def __init__(self, view, handle): self.view = view self.handle = handle @@ -2140,6 +2144,7 @@ class InstructionTextToken(object): ========================== ============================================ """ + from binaryninja import types def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.max_confidence): self.type = InstructionTextTokenType(token_type) diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 4ac304ca..158a0700 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -20,16 +20,16 @@ import traceback -# Binary Ninja components -import _binaryninjacore as core -import function -import filemetadata -import binaryview -import lowlevelil -import log +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class FunctionRecognizer(object): + from binaryninja import function + from binaryninja import filemetadata + from binaryninja import binaryview + from binaryninja import lowlevelil + from binaryninja import log _instance = None def __init__(self): diff --git a/python/generator.cpp b/python/generator.cpp index f838b36d..bb32ab69 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -374,10 +374,10 @@ int main(int argc, char* argv[]) fprintf(out, "def handle_of_type(value, handle_type):\n"); fprintf(out, "\tif isinstance(value, ctypes.POINTER(handle_type)) or isinstance(value, ctypes.c_void_p):\n"); fprintf(out, "\t\treturn ctypes.cast(value, ctypes.POINTER(handle_type))\n"); - fprintf(out, "\traise ValueError, 'expected pointer to %%s' %% str(handle_type)\n"); + fprintf(out, "\traise ValueError('expected pointer to %%s' %% str(handle_type))\n"); fprintf(out, "\n# Set path for core plugins\n"); - fprintf(out, "BNSetBundledPluginDirectory(os.path.join(_base_path, \"plugins\"))\n"); + fprintf(out, "BNSetBundledPluginDirectory(os.path.join(_base_path, \"plugins\").encode('utf-8'))\n"); fclose(out); fclose(enums); diff --git a/python/highlight.py b/python/highlight.py index 96bc543d..b04561bd 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -19,9 +19,9 @@ # IN THE SOFTWARE. -# Binary Ninja components -import _binaryninjacore as core -from enums import HighlightColorStyle, HighlightStandardColor +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import HighlightColorStyle, HighlightStandardColor class HighlightColor(object): diff --git a/python/interaction.py b/python/interaction.py index 5b7ec497..8507682c 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -21,11 +21,9 @@ import ctypes import traceback -# Binary Ninja components -import _binaryninjacore as core -from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult -import binaryview -import log +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult class LabelField(object): @@ -241,6 +239,8 @@ class DirectoryNameField(object): class InteractionHandler(object): + from binaryninja import log + from binaryninja import binaryview _interaction_handler = None def __init__(self): @@ -724,7 +724,7 @@ def get_form_input(fields, title): 3) Maybe Options 1 >>> True - >>> print tex_f.result, int_f.result, choice_f.result + >>> print(tex_f.result, int_f.result, choice_f.result) Peter 1337 0 """ value = (core.BNFormInputField * len(fields))() diff --git a/python/log.py b/python/log.py index b1fd7095..e7cd956d 100644 --- a/python/log.py +++ b/python/log.py @@ -19,9 +19,8 @@ # IN THE SOFTWARE. -# Binary Ninja components -import _binaryninjacore as core -from enums import LogLevel +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core _output_to_log = False diff --git a/python/lowlevelil.py b/python/lowlevelil.py index bd1e9349..3b12c118 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -19,15 +19,13 @@ # IN THE SOFTWARE. import ctypes - -# Binary Ninja components -import _binaryninjacore as core -from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType -import function -import basicblock -import mediumlevelil import struct +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType +from binaryninja import basicblock #required for LowLevelILBasicBlock + class LowLevelILLabel(object): def __init__(self, handle = None): @@ -342,6 +340,8 @@ class LowLevelILInstruction(object): } def __init__(self, func, expr_index, instr_index=None): + from binaryninja import function + from binaryninja import mediumlevelil instr = core.BNGetLowLevelILByIndex(func.handle, expr_index) self.function = func self.expr_index = expr_index @@ -441,7 +441,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): reg = operand_list[j * 2] reg_version = operand_list[(j * 2) + 1] value.append(SSARegister(ILRegister(func.arch, reg), reg_version)) @@ -451,7 +451,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): reg_stack = operand_list[j * 2] reg_version = operand_list[(j * 2) + 1] value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), reg_version)) @@ -461,7 +461,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): flag = operand_list[j * 2] flag_version = operand_list[(j * 2) + 1] value.append(SSAFlag(ILFlag(func.arch, flag), flag_version)) @@ -471,7 +471,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): if (operand_list[j * 2] & (1 << 32)) != 0: reg_or_flag = ILFlag(func.arch, operand_list[j * 2] & 0xffffffff) else: @@ -484,7 +484,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = {} - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): reg_stack = operand_list[j * 2] adjust = operand_list[(j * 2) + 1] if adjust & 0x80000000: @@ -720,6 +720,7 @@ class LowLevelILFunction(object): LLFC_NO !overflow No overflow ======================= ========== =============================== """ + from binaryninja import mediumlevelil def __init__(self, arch, handle = None, source_func = None): self.arch = arch self.source_function = source_func diff --git a/python/mainthread.py b/python/mainthread.py index 3e12bd65..16938f1a 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -18,9 +18,9 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -# Binary Ninja components -import _binaryninjacore as core -import scriptingprovider +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja import scriptingprovider def execute_on_main_thread(func): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 100795fe..9a21bb23 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -19,16 +19,13 @@ # IN THE SOFTWARE. import ctypes - -# Binary Ninja components -import _binaryninjacore as core -from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence -import function -import basicblock -import lowlevelil -import types import struct +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence +from binaryninja import basicblock #required for MediumLevelILBasicBlock argument + class SSAVariable(object): def __init__(self, var, version): @@ -208,6 +205,9 @@ class MediumLevelILInstruction(object): } def __init__(self, func, expr_index, instr_index=None): + from binaryninja import function + from binaryninja import types + from binaryninja import lowlevelil instr = core.BNGetMediumLevelILByIndex(func.handle, expr_index) self.function = func self.expr_index = expr_index @@ -272,7 +272,7 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value / 2): + for j in xrange(count.value // 2): var_id = operand_list[j * 2] var_version = operand_list[(j * 2) + 1] value.append(SSAVariable(function.Variable.from_identifier(self.function.source_function, diff --git a/python/metadata.py b/python/metadata.py index 554bbcf4..21e74533 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -19,11 +19,12 @@ # IN THE SOFTWARE. +from __future__ import absolute_import import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import MetadataType +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import MetadataType class Metadata(object): diff --git a/python/platform.py b/python/platform.py index dd756178..ff59be50 100644 --- a/python/platform.py +++ b/python/platform.py @@ -20,15 +20,16 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core -import startup -import architecture -import callingconvention -import types +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core + +#2-3 compatibility +from six import with_metaclass class _PlatformMetaClass(type): + from binaryninja import startup + from binaryninja import types @property def list(self): startup._init_plugins() @@ -90,12 +91,14 @@ class _PlatformMetaClass(type): return result -class Platform(object): +class Platform(with_metaclass(_PlatformMetaClass, object)): """ ``class Platform`` contains all information releated to the execution environment of the binary, mainly the calling conventions used. """ - __metaclass__ = _PlatformMetaClass + from binaryninja import architecture + from binaryninja import callingconvention + from binaryninja import types name = None def __init__(self, arch, handle = None): diff --git a/python/plugin.py b/python/plugin.py index 13ca51af..5dad9fb6 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -22,16 +22,12 @@ import traceback import ctypes import threading -# Binary Ninja components -import _binaryninjacore as core -from enums import PluginCommandType -import startup -import filemetadata -import binaryview -import function -import log -import lowlevelil -import mediumlevelil +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import PluginCommandType + +#2-3 compatibility +from six import with_metaclass class PluginCommandContext(object): @@ -44,6 +40,7 @@ class PluginCommandContext(object): class _PluginCommandMetaClass(type): + from binaryninja import startup @property def list(self): startup._init_plugins() @@ -72,9 +69,13 @@ class _PluginCommandMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) -class PluginCommand(object): +class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): + from binaryninja import startup + from binaryninja import filemetadata + from binaryninja import binaryview + from binaryninja import function + from binaryninja import log _registered_commands = [] - __metaclass__ = _PluginCommandMetaClass def __init__(self, cmd): self.command = core.BNPluginCommand() @@ -536,6 +537,7 @@ class MainThreadAction(object): class MainThreadActionHandler(object): + from binaryninja import log _main_thread = None def __init__(self): @@ -580,8 +582,7 @@ class _BackgroundTaskMetaclass(type): core.BNFreeBackgroundTaskList(tasks, count.value) -class BackgroundTask(object): - __metaclass__ = _BackgroundTaskMetaclass +class BackgroundTask(with_metaclass(_BackgroundTaskMetaclass, object)): def __init__(self, initial_progress_text = "", can_cancel = False, handle = None): if handle is None: diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 0cc43aca..66f642c3 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -20,10 +20,8 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core -from .enums import PluginType, PluginUpdateStatus -import startup +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class RepoPlugin(object): @@ -31,6 +29,7 @@ class RepoPlugin(object): ``RepoPlugin` is mostly read-only, however you can install/uninstall enable/disable plugins. RepoPlugins are created by parsing the plugins.json in a plugin repository. """ + from binaryninja.enums import PluginType, PluginUpdateStatus def __init__(self, handle): raise Exception("RepoPlugin temporarily disabled!") self.handle = core.handle_of_type(handle, core.BNRepoPlugin) @@ -200,6 +199,7 @@ class RepositoryManager(object): ``RepositoryManager`` Keeps track of all the repositories and keeps the enabled_plugins.json file coherent with the plugins that are installed/unstalled enabled/disabled """ + from binaryninja import startup def __init__(self, handle=None): raise Exception("RepositoryManager temporarily disabled!") self.handle = core.BNGetRepositoryManager() diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 9cacc6ad..ac0ffd4c 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -26,14 +26,12 @@ import threading import abc import sys -# Binary Ninja Components -import _binaryninjacore as core -from enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState -import binaryview -import function -import basicblock -import startup -import log +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState + +#2-3 compatibility +from six import with_metaclass class _ThreadActionContext(object): @@ -60,6 +58,7 @@ class _ThreadActionContext(object): class ScriptingOutputListener(object): + from binaryninja import log def _register(self, handle): self._cb = core.BNScriptingOutputListener() self._cb.context = 0 @@ -100,6 +99,10 @@ class ScriptingOutputListener(object): class ScriptingInstance(object): + from binaryninja import binaryview + from binaryninja import basicblock + from binaryninja import log + from binaryninja import function def __init__(self, provider, handle = None): if handle is None: self._cb = core.BNScriptingInstanceCallbacks() @@ -256,6 +259,7 @@ class ScriptingInstance(object): class _ScriptingProviderMetaclass(type): + from binaryninja import startup @property def list(self): """List all ScriptingProvider types (read-only)""" @@ -292,8 +296,8 @@ class _ScriptingProviderMetaclass(type): raise AttributeError("attribute '%s' is read only" % name) -class ScriptingProvider(object): - __metaclass__ = _ScriptingProviderMetaclass +class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): + from binaryninja import log name = None instance_class = None @@ -335,6 +339,7 @@ class ScriptingProvider(object): class _PythonScriptingInstanceOutput(object): + from binaryninja import log def __init__(self, orig, is_error): self.orig = orig self.is_error = is_error diff --git a/python/setting.py b/python/setting.py index d58c8955..7cde3865 100644 --- a/python/setting.py +++ b/python/setting.py @@ -20,8 +20,8 @@ import ctypes -# Binary Ninja components -import _binaryninjacore as core +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core class Setting(object): diff --git a/python/startup.py b/python/startup.py index 0abc47cb..919a8fbe 100644 --- a/python/startup.py +++ b/python/startup.py @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -import _binaryninjacore as core +from binaryninja import _binaryninjacore as core _plugin_init = False diff --git a/python/transform.py b/python/transform.py index 3284ed74..f04bfdca 100644 --- a/python/transform.py +++ b/python/transform.py @@ -22,15 +22,16 @@ import traceback import ctypes import abc -# Binary Ninja components -import _binaryninjacore as core -from enums import TransformType -import startup -import log -import databuffer +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import TransformType + +#2-3 compatibility +from six import with_metaclass class _TransformMetaClass(type): + from binaryninja import startup @property def list(self): startup._init_plugins() @@ -90,14 +91,15 @@ class TransformParameter(object): self.fixed_length = fixed_length -class Transform(object): +class Transform(with_metaclass(_TransformMetaClass, object)): + from binaryninja import log + from binaryninja import databuffer transform_type = None name = None long_name = None group = None parameters = [] _registered_cb = None - __metaclass__ = _TransformMetaClass def __init__(self, handle): if handle is None: diff --git a/python/types.py b/python/types.py index 42ed7ddd..cbe5a7bc 100644 --- a/python/types.py +++ b/python/types.py @@ -18,15 +18,14 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. +from __future__ import absolute_import max_confidence = 255 import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType -import callingconvention -import function +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType class QualifiedName(object): @@ -213,6 +212,8 @@ class FunctionParameter(object): class Type(object): def __init__(self, handle, platform = None, confidence = max_confidence): + from binaryninja import callingconvention + from binaryninja import function self.handle = handle self.confidence = confidence self.platform = platform @@ -344,7 +345,7 @@ class Type(object): return None return Enumeration(result) - @property + @property def named_type_reference(self): """Reference to a named type (read-only)""" result = core.BNGetTypeNamedTypeReference(self.handle) @@ -376,7 +377,7 @@ class Type(object): def __repr__(self): if self.confidence < max_confidence: - return "" % (str(self), (self.confidence * 100) / max_confidence) + return "" % (str(self), (self.confidence * 100) // max_confidence) return "" % str(self) def get_string_before_name(self): diff --git a/python/undoaction.py b/python/undoaction.py index 7e3c76a0..9771df38 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -22,14 +22,14 @@ import traceback import json import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import ActionType -import startup -import log +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import ActionType class UndoAction(object): + from binaryninja import startup + from binaryninja import log name = None action_type = None _registered = False diff --git a/python/update.py b/python/update.py index 1eb8ea61..1fda149b 100644 --- a/python/update.py +++ b/python/update.py @@ -21,14 +21,17 @@ import traceback import ctypes -# Binary Ninja components -import _binaryninjacore as core -from enums import UpdateResult -import startup -import log +# Binary Ninja components -- additional imports belong in the appropriate class +from binaryninja import _binaryninjacore as core +from binaryninja.enums import UpdateResult + + +#2-3 compatibility +from six import with_metaclass class _UpdateChannelMetaClass(type): + from binaryninja import startup @property def list(self): startup._init_plugins() @@ -95,6 +98,7 @@ class _UpdateChannelMetaClass(type): class UpdateProgressCallback(object): + from binaryninja import log def __init__(self, func): self.cb = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(self.callback) self.func = func @@ -108,8 +112,7 @@ class UpdateProgressCallback(object): log.log_error(traceback.format_exc()) -class UpdateChannel(object): - __metaclass__ = _UpdateChannelMetaClass +class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)): def __init__(self, name, desc, ver): self.name = name -- cgit v1.3.1 From d4d1fbb390c9a31045cea8e612c02e242d11c438 Mon Sep 17 00:00:00 2001 From: Peter LaFosse Date: Mon, 5 Mar 2018 16:09:30 -0500 Subject: Additional changes for python 2/3 compatibility --- python/__init__.py | 49 ++++++++++++++++- python/architecture.py | 50 ++++++++---------- python/basicblock.py | 17 +++--- python/binaryview.py | 122 +++++++++++++++++-------------------------- python/callingconvention.py | 44 ++++++++-------- python/fileaccessor.py | 2 +- python/filemetadata.py | 15 +++--- python/function.py | 55 ++++++++----------- python/functionrecognizer.py | 6 +-- python/interaction.py | 2 +- python/lowlevelil.py | 47 ++++++++--------- python/mediumlevelil.py | 48 ++++++++--------- python/platform.py | 92 ++++++++++++++++---------------- python/plugin.py | 60 +++++++++++---------- python/pluginmanager.py | 4 +- python/scriptingprovider.py | 52 ++++++++---------- python/startup.py | 22 ++++---- python/transform.py | 15 +++--- python/types.py | 13 +++-- python/undoaction.py | 6 +-- python/update.py | 10 ++-- 21 files changed, 364 insertions(+), 367 deletions(-) (limited to 'python/plugin.py') diff --git a/python/__init__.py b/python/__init__.py index 66f4bfe8..d88703cc 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -22,10 +22,41 @@ from __future__ import absolute_import import atexit import sys +import ctypes from time import gmtime # Binary Ninja components -from binaryninja import _binaryninjacore as core +import binaryninja._binaryninjacore as core +# __all__ = [ +# "enums", +# "databuffer", +# "filemetadata", +# "fileaccessor", +# "binaryview", +# "transform", +# "architecture", +# "basicblock", +# "function", +# "log", +# "lowlevelil", +# "mediumlevelil", +# "types", +# "functionrecognizer", +# "update", +# "plugin", +# "callingconvention", +# "platform", +# "demangle", +# "mainthread", +# "interaction", +# "lineardisassembly", +# "undoaction", +# "highlight", +# "scriptingprovider", +# "pluginmanager", +# "setting", +# "metadata", +# ] from binaryninja.enums import * from binaryninja.databuffer import * from binaryninja.filemetadata import * @@ -116,7 +147,7 @@ class PluginManagerLoadPluginCallback(object): load_plugin = PluginManagerLoadPluginCallback() -core.BNRegisterForPluginLoading(_plugin_api_name, load_plugin.cb, 0) +core.BNRegisterForPluginLoading(_plugin_api_name.encode("utf8"), load_plugin.cb, 0) class _DestructionCallbackHandler(object): @@ -138,6 +169,20 @@ class _DestructionCallbackHandler(object): Function._unregister(func) +_plugin_init = False + + +def _init_plugins(): + global _plugin_init + if not _plugin_init: + _plugin_init = True + core.BNInitCorePlugins() + core.BNInitUserPlugins() + core.BNInitRepoPlugins() + if not core.BNIsLicenseValidated(): + raise RuntimeError("License is not valid. Please supply a valid license.") + + _destruct_callbacks = _DestructionCallbackHandler() bundled_plugin_path = core.BNGetBundledPluginDirectory() diff --git a/python/architecture.py b/python/architecture.py index 360ce6bf..a705f2d9 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -27,16 +27,24 @@ import abc from binaryninja import _binaryninjacore as core from binaryninja.enums import (Endianness, ImplicitRegisterExtend, BranchType, InstructionTextTokenType, LowLevelILFlagCondition, FlagRole) +import binaryninja +from binaryninja import log -#2-3 compatibility +from binaryninja import lowlevelil +from binaryninja import types +from binaryninja import databuffer +from binaryninja import platform +from binaryninja import callingconvention + +# 2-3 compatibility from six import with_metaclass class _ArchitectureMetaClass(type): - from binaryninja import startup + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() archs = core.BNGetArchitectureList(count) result = [] @@ -46,7 +54,7 @@ class _ArchitectureMetaClass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() archs = core.BNGetArchitectureList(count) try: @@ -56,14 +64,14 @@ class _ArchitectureMetaClass(type): core.BNFreeArchitectureList(archs) def __getitem__(cls, name): - startup._init_plugins() + binaryninja._init_plugins() arch = core.BNGetArchitectureByName(name) if arch is None: raise KeyError("'%s' is not a valid architecture" % str(name)) return CoreArchitecture._from_cache(arch) def register(cls): - startup._init_plugins() + binaryninja._init_plugins() if cls.name is None: raise ValueError("architecture 'name' is not defined") arch = cls() @@ -130,15 +138,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): next_address = 0 def __init__(self): - from binaryninja import function - from binaryninja import startup - from binaryninja import lowlevelil - from binaryninja import types - from binaryninja import databuffer - from binaryninja import log - from binaryninja import platform - from binaryninja import callingconvention - startup._init_plugins() + binaryninja._init_plugins() if self.__class__.opcode_display_length > self.__class__.max_instr_length: self.__class__.opcode_display_length = self.__class__.max_instr_length @@ -371,9 +371,9 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): info = self.__class__.intrinsics[intrinsic] for i in xrange(0, len(info.inputs)): if isinstance(info.inputs[i], types.Type): - info.inputs[i] = function.IntrinsicInput(info.inputs[i]) + info.inputs[i] = binaryninja.function.IntrinsicInput(info.inputs[i]) elif isinstance(info.inputs[i], tuple): - info.inputs[i] = function.IntrinsicInput(info.inputs[i][0], info.inputs[i][1]) + info.inputs[i] = binaryninja.function.IntrinsicInput(info.inputs[i][0], info.inputs[i][1]) info.index = intrinsic_index self._intrinsics[intrinsic] = intrinsic_index self._intrinsics_by_index[intrinsic_index] = (intrinsic, info) @@ -2049,10 +2049,6 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): _architecture_cache = {} class CoreArchitecture(Architecture): def __init__(self, handle): - from binaryninja import function - from binaryninja import types - from binaryninja import databuffer - from binaryninja import lowlevelil super(CoreArchitecture, self).__init__() self.handle = core.handle_of_type(handle, core.BNArchitecture) @@ -2082,7 +2078,7 @@ class CoreArchitecture(Architecture): name = core.BNGetArchitectureRegisterName(self.handle, regs[i]) info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) - self.regs[name] = function.RegisterInfo(full_width_reg, info.size, info.offset, + self.regs[name] = binaryninja.function.RegisterInfo(full_width_reg, info.size, info.offset, ImplicitRegisterExtend(info.extend), regs[i]) self._all_regs[name] = regs[i] self._regs_by_index[regs[i]] = name @@ -2240,7 +2236,7 @@ class CoreArchitecture(Architecture): for j in xrange(0, info.topRelativeCount): top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j)) top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg) - self.reg_stacks[name] = function.RegisterStackInfo(storage, top_rel, top, regs[i]) + self.reg_stacks[name] = binaryninja.function.RegisterStackInfo(storage, top_rel, top, regs[i]) self._all_reg_stacks[name] = regs[i] self._reg_stacks_by_index[regs[i]] = name core.BNFreeRegisterList(regs) @@ -2258,7 +2254,7 @@ class CoreArchitecture(Architecture): for j in xrange(0, input_count.value): input_name = inputs[j].name type_obj = types.Type(core.BNNewTypeReference(inputs[j].type), confidence = inputs[j].typeConfidence) - input_list.append(function.IntrinsicInput(type_obj, input_name)) + input_list.append(binaryninja.function.IntrinsicInput(type_obj, input_name)) core.BNFreeNameAndTypeList(inputs, input_count.value) output_count = ctypes.c_ulonglong() outputs = core.BNGetArchitectureIntrinsicOutputs(self.handle, intrinsics[i], output_count) @@ -2266,7 +2262,7 @@ class CoreArchitecture(Architecture): for j in xrange(0, output_count.value): output_list.append(types.Type(core.BNNewTypeReference(outputs[j].type), confidence = outputs[j].confidence)) core.BNFreeOutputTypeList(outputs, output_count.value) - self.intrinsics[name] = function.IntrinsicInfo(input_list, output_list) + self.intrinsics[name] = binaryninja.function.IntrinsicInfo(input_list, output_list) self._intrinsics[name] = intrinsics[i] self._intrinsics_by_index[intrinsics[i]] = (name, self.intrinsics[name]) core.BNFreeRegisterList(intrinsics) @@ -2303,7 +2299,7 @@ class CoreArchitecture(Architecture): ctypes.memmove(buf, data, len(data)) if not core.BNGetInstructionInfo(self.handle, buf, addr, len(data), info): return None - result = function.InstructionInfo() + result = binaryninja.function.InstructionInfo() result.length = info.length result.arch_transition_by_target_addr = info.archTransitionByTargetAddr result.branch_delay = info.branchDelay @@ -2345,7 +2341,7 @@ class CoreArchitecture(Architecture): context = tokens[i].context confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result, length.value diff --git a/python/basicblock.py b/python/basicblock.py index 907b4065..ee754863 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -21,6 +21,8 @@ import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja +from binaryninja import highlight from binaryninja import _binaryninjacore as core from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType @@ -51,9 +53,6 @@ class BasicBlockEdge(object): class BasicBlock(object): def __init__(self, view, handle): - from binaryninja import architecture - from binaryninja import function - from binaryninja import highlight self.view = view self.handle = core.handle_of_type(handle, core.BNBasicBlock) self._arch = None @@ -87,7 +86,7 @@ class BasicBlock(object): func = core.BNGetBasicBlockFunction(self.handle) if func is None: return None - self._func = function.Function(self.view, func) + self._func =binaryninja.function.Function(self.view, func) return self._func @property @@ -100,7 +99,7 @@ class BasicBlock(object): arch = core.BNGetBasicBlockArchitecture(self.handle) if arch is None: return None - self._arch = architecture.CoreArchitecture._from_cache(arch) + self._arch = binaryninja.architecture.CoreArchitecture._from_cache(arch) return self._arch @property @@ -225,7 +224,7 @@ class BasicBlock(object): @property def disassembly_text(self): """ - ``disassembly_text`` property which returns a list of function.DisassemblyTextLine objects for the current basic block. + ``disassembly_text`` property which returns a list of binaryninja.function.DisassemblyTextLine objects for the current basic block. :Example: >>> current_basic_block.disassembly_text @@ -322,7 +321,7 @@ class BasicBlock(object): def get_disassembly_text(self, settings=None): """ - ``get_disassembly_text`` returns a list of function.DisassemblyTextLine objects for the current basic block. + ``get_disassembly_text`` returns a list of binaryninja.function.DisassemblyTextLine objects for the current basic block. :param DisassemblySettings settings: (optional) DisassemblySettings object :Example: @@ -353,8 +352,8 @@ class BasicBlock(object): context = lines[i].tokens[j].context confidence = lines[i].tokens[j].confidence address = lines[i].tokens[j].address - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - result.append(function.DisassemblyTextLine(addr, tokens, il_instr)) + tokens.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.DisassemblyTextLine(addr, tokens, il_instr)) core.BNFreeDisassemblyTextLines(lines, count.value) return result diff --git a/python/binaryview.py b/python/binaryview.py index f6a1bc83..b3314c5c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -22,15 +22,22 @@ import struct import traceback import ctypes import abc -import threading # Binary Ninja components -- additional imports belong in the appropriate class from binaryninja import _binaryninjacore as core from binaryninja.enums import (AnalysisState, SymbolType, InstructionTextTokenType, Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) +import binaryninja from binaryninja import associateddatastore # required for _BinaryViewAssociatedDataStore - -#2-3 compatibility +from binaryninja import log +from binaryninja import types +from binaryninja import fileaccessor +from binaryninja import databuffer +from binaryninja import basicblock +from binaryninja import lineardisassembly +from binaryninja import metadata + +# 2-3 compatibility from six import with_metaclass @@ -110,7 +117,6 @@ class AnalysisCompletionEvent(object): >>> """ def __init__(self, view, callback): - from binaryninja import log self.view = view self.callback = callback self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify) @@ -189,9 +195,6 @@ class DataVariable(object): class BinaryDataNotificationCallbacks(object): def __init__(self, view, notify): - from binaryninja import function - from binaryninja import types - from binaryninja import log self.view = view self.notify = notify self._cb = core.BNBinaryDataNotification() @@ -237,19 +240,19 @@ class BinaryDataNotificationCallbacks(object): def _function_added(self, ctxt, view, func): try: - self.notify.function_added(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + self.notify.function_added(self.view, binaryninja.function.Function(self.view, core.BNNewFunctionReference(func))) except: log.log_error(traceback.format_exc()) def _function_removed(self, ctxt, view, func): try: - self.notify.function_removed(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + self.notify.function_removed(self.view, binaryninja.function.Function(self.view, core.BNNewFunctionReference(func))) except: log.log_error(traceback.format_exc()) def _function_updated(self, ctxt, view, func): try: - self.notify.function_updated(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + self.notify.function_updated(self.view, binaryninja.function.Function(self.view, core.BNNewFunctionReference(func))) except: log.log_error(traceback.format_exc()) @@ -314,11 +317,11 @@ class BinaryDataNotificationCallbacks(object): class _BinaryViewTypeMetaclass(type): - from binaryninja import startup + @property def list(self): """List all BinaryView types (read-only)""" - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() types = core.BNGetBinaryViewTypes(count) result = [] @@ -328,7 +331,7 @@ class _BinaryViewTypeMetaclass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() types = core.BNGetBinaryViewTypes(count) try: @@ -338,7 +341,7 @@ class _BinaryViewTypeMetaclass(type): core.BNFreeBinaryViewTypeList(types) def __getitem__(self, value): - startup._init_plugins() + binaryninja._init_plugins() view_type = core.BNGetBinaryViewTypeByName(str(value)) if view_type is None: raise KeyError("'%s' is not a valid view type" % str(value)) @@ -348,9 +351,6 @@ class _BinaryViewTypeMetaclass(type): class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): def __init__(self, handle): - from binaryninja import architecture - from binaryninja import filemetadata - from binaryninja import platform self.handle = core.handle_of_type(handle, core.BNBinaryViewType) def __eq__(self, value): @@ -409,7 +409,7 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): if f is None or f.read(len(sqlite)) != sqlite: return None f.close() - view = filemetadata.FileMetadata().open_existing_database(filename) + view = binaryninja.filemetadata.FileMetadata().open_existing_database(filename) else: view = BinaryView.open(filename) @@ -437,7 +437,7 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): arch = core.BNGetArchitectureForViewType(self.handle, ident, endian) if arch is None: return None - return architecture.CoreArchitecture._from_cache(arch) + return binaryninja.architecture.CoreArchitecture._from_cache(arch) def register_platform(self, ident, arch, plat): core.BNRegisterPlatformForViewType(self.handle, ident, arch.handle, plat.handle) @@ -449,7 +449,7 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): plat = core.BNGetPlatformForViewType(self.handle, ident, arch.handle) if plat is None: return None - return platform.Platform(None, plat) + return binaryninja.platform.Platform(None, plat) class Segment(object): @@ -579,18 +579,6 @@ class BinaryView(object): database (e.g. ``remove_user_function()`` rather than ``remove_function()``). Thus use ``_user_`` methods if saving \ to the database is desired. """ - import binaryninja.function - import binaryninja.architecture - import binaryninja.platform - import binaryninja.fileaccessor - import binaryninja.filemetadata - import binaryninja.databuffer - import binaryninja.basicblock - import binaryninja.types - import binaryninja.log - import binaryninja.startup - import binaryninja.lineardisassembly - import binaryninja.metadata name = None long_name = None _registered = False @@ -600,32 +588,20 @@ class BinaryView(object): _associated_data = {} def __init__(self, file_metadata=None, parent_view=None, handle=None): - function = binaryninja.function - architecture = binaryninja.architecture - platform = binaryninja.platform - fileaccessor = binaryninja.fileaccessor - filemetadata = binaryninja.filemetadata - databuffer = binaryninja.databuffer - basicblock = binaryninja.basicblock - types = binaryninja.types - log = binaryninja.log - startup = binaryninja.startup - lineardisassembly = binaryninja.lineardisassembly - metadata = binaryninja.metadata if handle is not None: self.handle = core.handle_of_type(handle, core.BNBinaryView) if file_metadata is None: - self.file = filemetadata.FileMetadata(handle=core.BNGetFileForView(handle)) + self.file = binaryninja.filemetadata.FileMetadata(handle=core.BNGetFileForView(handle)) else: self.file = file_metadata elif self.__class__ is BinaryView: - startup._init_plugins() + binaryninja._init_plugins() if file_metadata is None: - file_metadata = filemetadata.FileMetadata() + file_metadata = binaryninja.filemetadata.FileMetadata() self.handle = core.BNCreateBinaryDataView(file_metadata.handle) - self.file = filemetadata.FileMetadata(handle=core.BNNewFileReference(file_metadata.handle)) + self.file = binaryninja.filemetadata.FileMetadata(handle=core.BNNewFileReference(file_metadata.handle)) else: - startup._init_plugins() + binaryninja._init_plugins() if not self.__class__._registered: raise TypeError("view type not registered") self._cb = core.BNCustomBinaryView() @@ -668,7 +644,7 @@ class BinaryView(object): @classmethod def register(cls): - startup._init_plugins() + binaryninja._init_plugins() if cls.name is None: raise ValueError("view 'name' not defined") if cls.long_name is None: @@ -683,7 +659,7 @@ class BinaryView(object): @classmethod def _create(cls, ctxt, data): try: - file_metadata = filemetadata.FileMetadata(handle=core.BNGetFileForView(data)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle=core.BNGetFileForView(data)) view = cls(BinaryView(file_metadata=file_metadata, handle=core.BNNewViewReference(data))) if view is None: return None @@ -702,14 +678,14 @@ class BinaryView(object): @classmethod def open(cls, src, file_metadata=None): - binaryninja.startup._init_plugins() + binaryninja._init_plugins() if isinstance(src, fileaccessor.FileAccessor): if file_metadata is None: - file_metadata = filemetadata.FileMetadata() + file_metadata = binaryninja.filemetadata.FileMetadata() view = core.BNCreateBinaryDataViewFromFile(file_metadata.handle, src._cb) else: if file_metadata is None: - file_metadata = filemetadata.FileMetadata(str(src)) + file_metadata = binaryninja.filemetadata.FileMetadata(str(src)) view = core.BNCreateBinaryDataViewFromFilename(file_metadata.handle, str(src)) if view is None: return None @@ -718,9 +694,9 @@ class BinaryView(object): @classmethod def new(cls, data=None, file_metadata=None): - startup._init_plugins() + binaryninja._init_plugins() if file_metadata is None: - file_metadata = filemetadata.FileMetadata() + file_metadata = binaryninja.filemetadata.FileMetadata() if data is None: view = core.BNCreateBinaryDataView(file_metadata.handle) else: @@ -805,7 +781,7 @@ class BinaryView(object): funcs = core.BNGetAnalysisFunctionList(self.handle, count) try: for i in xrange(0, count.value): - yield function.Function(self, core.BNNewFunctionReference(funcs[i])) + yield binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i])) finally: core.BNFreeFunctionList(funcs, count.value) @@ -873,7 +849,7 @@ class BinaryView(object): arch = core.BNGetDefaultArchitecture(self.handle) if arch is None: return None - return architecture.CoreArchitecture._from_cache(handle=arch) + return binaryninja.architecture.CoreArchitecture._from_cache(handle=arch) @arch.setter def arch(self, value): @@ -888,7 +864,7 @@ class BinaryView(object): plat = core.BNGetDefaultPlatform(self.handle) if plat is None: return None - return platform.Platform(self.arch, handle=plat) + return binaryninja.platform.Platform(self.arch, handle=plat) @platform.setter def platform(self, value): @@ -924,7 +900,7 @@ class BinaryView(object): funcs = core.BNGetAnalysisFunctionList(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(function.Function(self, core.BNNewFunctionReference(funcs[i]))) + result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -939,7 +915,7 @@ class BinaryView(object): func = core.BNGetAnalysisEntryPoint(self.handle) if func is None: return None - return function.Function(self, func) + return binaryninja.function.Function(self, func) @property def symbols(self): @@ -1086,7 +1062,7 @@ class BinaryView(object): def global_pointer_value(self): """Discovered value of the global pointer register, if the binary uses one (read-only)""" result = core.BNGetGlobalPointerValue(self.handle) - return function.RegisterValue(self.arch, result.value, confidence = result.confidence) + return binaryninja.function.RegisterValue(self.arch, result.value, confidence = result.confidence) @property def parameters_for_analysis(self): @@ -2192,7 +2168,7 @@ class BinaryView(object): func = core.BNGetAnalysisFunction(self.handle, plat.handle, addr) if func is None: return None - return function.Function(self, func) + return binaryninja.function.Function(self, func) def get_functions_at(self, addr): """ @@ -2209,7 +2185,7 @@ class BinaryView(object): funcs = core.BNGetAnalysisFunctionsForAddress(self.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(function.Function(self, core.BNNewFunctionReference(funcs[i]))) + result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -2217,7 +2193,7 @@ class BinaryView(object): func = core.BNGetRecentAnalysisFunctionForAddress(self.handle, addr) if func is None: return None - return function.Function(self, func) + return binaryninja.function.Function(self, func) def get_basic_blocks_at(self, addr): """ @@ -2279,15 +2255,15 @@ class BinaryView(object): result = [] for i in xrange(0, count.value): if refs[i].func: - func = function.Function(self, core.BNNewFunctionReference(refs[i].func)) + func = binaryninja.function.Function(self, core.BNNewFunctionReference(refs[i].func)) else: func = None if refs[i].arch: - arch = architecture.CoreArchitecture._from_cache(refs[i].arch) + arch = binaryninja.architecture.CoreArchitecture._from_cache(refs[i].arch) else: arch = None addr = refs[i].addr - result.append(architecture.ReferenceSource(func, arch, addr)) + result.append(binaryninja.architecture.ReferenceSource(func, arch, addr)) core.BNFreeCodeReferences(refs, count.value) return result @@ -3006,7 +2982,7 @@ class BinaryView(object): func = None block = None if pos.function: - func = function.Function(self, pos.function) + func = binaryninja.function.Function(self, pos.function) if pos.block: block = basicblock.BasicBlock(self, pos.block) return lineardisassembly.LinearDisassemblyPosition(func, block, pos.address) @@ -3032,7 +3008,7 @@ class BinaryView(object): func = None block = None if lines[i].function: - func = function.Function(self, core.BNNewFunctionReference(lines[i].function)) + func = binaryninja.function.Function(self, core.BNNewFunctionReference(lines[i].function)) if lines[i].block: block = basicblock.BasicBlock(self, core.BNNewBasicBlockReference(lines[i].block)) addr = lines[i].contents.addr @@ -3046,14 +3022,14 @@ class BinaryView(object): context = lines[i].contents.tokens[j].context confidence = lines[i].contents.tokens[j].confidence address = lines[i].contents.tokens[j].address - tokens.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) - contents = function.DisassemblyTextLine(addr, tokens) + tokens.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + contents = binaryninja.function.DisassemblyTextLine(addr, tokens) result.append(lineardisassembly.LinearDisassemblyLine(lines[i].type, func, block, lines[i].lineOffset, contents)) func = None block = None if pos_obj.function: - func = function.Function(self, pos_obj.function) + func = binaryninja.function.Function(self, pos_obj.function) if pos_obj.block: block = basicblock.BasicBlock(self, pos_obj.block) pos.function = func diff --git a/python/callingconvention.py b/python/callingconvention.py index ab8058fc..268d914f 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -22,7 +22,10 @@ import traceback import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core +from binaryninja import log +from binaryninja.enums import VariableSourceType class CallingConvention(object): from binaryninja import types @@ -42,11 +45,6 @@ class CallingConvention(object): _registered_calling_conventions = [] def __init__(self, arch=None, name=None, handle=None, confidence=types.max_confidence): - from binaryninja import architecture - from binaryninja import log - from binaryninja import function - from binaryninja import binaryview - from binaryninja.enums import VariableSourceType if handle is None: if arch is None or name is None: raise ValueError("Must specify either handle or architecture and name") @@ -74,7 +72,7 @@ class CallingConvention(object): self.__class__._registered_calling_conventions.append(self) else: self.handle = handle - self.arch = architecture.CoreArchitecture._from_cache(core.BNGetCallingConventionArchitecture(self.handle)) + self.arch = binaryninja.architecture.CoreArchitecture._from_cache(core.BNGetCallingConventionArchitecture(self.handle)) self.__dict__["name"] = core.BNGetCallingConventionName(self.handle) self.__dict__["arg_regs_share_index"] = core.BNAreArgumentRegistersSharedIndex(self.handle) self.__dict__["stack_reserved_for_arg_regs"] = core.BNIsStackReservedForArgumentRegisters(self.handle) @@ -281,25 +279,25 @@ class CallingConvention(object): def _get_incoming_reg_value(self, ctxt, reg, func, result): try: - func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + func_obj = binaryninja.function.Function(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) reg_name = self.arch.get_reg_name(reg) api_obj = self.perform_get_incoming_reg_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - api_obj = function.RegisterValue()._to_api_object() + api_obj = binaryninja.function.RegisterValue()._to_api_object() result[0].state = api_obj.state result[0].value = api_obj.value def _get_incoming_flag_value(self, ctxt, reg, func, result): try: - func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + func_obj = binaryninja.function.Function(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) reg_name = self.arch.get_reg_name(reg) api_obj = self.perform_get_incoming_flag_value(reg_name, func_obj)._to_api_object() except: log.log_error(traceback.format_exc()) - api_obj = function.RegisterValue()._to_api_object() + api_obj = binaryninja.function.RegisterValue()._to_api_object() result[0].state = api_obj.state result[0].value = api_obj.value @@ -308,9 +306,9 @@ class CallingConvention(object): if func is None: func_obj = None else: - func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + func_obj = binaryninja.function.Function(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) - in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) + in_var_obj = binaryninja.function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) out_var = self.perform_get_incoming_var_for_parameter_var(in_var_obj, func_obj) result[0].type = out_var.source_type result[0].index = out_var.index @@ -326,9 +324,9 @@ class CallingConvention(object): if func is None: func_obj = None else: - func_obj = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + func_obj = binaryninja.function.Function(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) - in_var_obj = function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) + in_var_obj = binaryninja.function.Variable(func_obj, in_var[0].type, in_var[0].index, in_var[0].storage) out_var = self.perform_get_parameter_var_for_incoming_var(in_var_obj, func_obj) result[0].type = out_var.source_type result[0].index = out_var.index @@ -349,11 +347,11 @@ class CallingConvention(object): reg_stack = self.arch.get_reg_stack_for_reg(reg) if reg_stack is not None: if reg == self.arch.reg_stacks[reg_stack].stack_top_reg: - return function.RegisterValue.constant(0) - return function.RegisterValue() + return binaryninja.function.RegisterValue.constant(0) + return binaryninja.function.RegisterValue() def perform_get_incoming_flag_value(self, reg, func): - return function.RegisterValue() + return binaryninja.function.RegisterValue() def perform_get_incoming_var_for_parameter_var(self, in_var, func): in_buf = core.BNVariable() @@ -364,7 +362,7 @@ class CallingConvention(object): name = None if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType): name = func.arch.get_reg_name(out_var.storage) - return function.Variable(func, out_var.type, out_var.index, out_var.storage, name) + return binaryninja.function.Variable(func, out_var.type, out_var.index, out_var.storage, name) def perform_get_parameter_var_for_incoming_var(self, in_var, func): in_buf = core.BNVariable() @@ -372,7 +370,7 @@ class CallingConvention(object): in_buf.index = in_var.index in_buf.storage = in_var.storage out_var = core.BNGetDefaultParameterVariableForIncomingVariable(self.handle, in_buf) - return function.Variable(func, out_var.type, out_var.index, out_var.storage) + return binaryninja.function.Variable(func, out_var.type, out_var.index, out_var.storage) def with_confidence(self, confidence): return CallingConvention(self.arch, handle = core.BNNewCallingConventionReference(self.handle), @@ -383,14 +381,14 @@ class CallingConvention(object): func_handle = None if func is not None: func_handle = func.handle - return function.RegisterValue(self.arch, core.BNGetIncomingRegisterValue(self.handle, reg_num, func_handle)) + return binaryninja.function.RegisterValue(self.arch, core.BNGetIncomingRegisterValue(self.handle, reg_num, func_handle)) def get_incoming_flag_value(self, flag, func): reg_num = self.arch.get_flag_index(flag) func_handle = None if func is not None: func_handle = func.handle - return function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle)) + return binaryninja.function.RegisterValue(self.arch, core.BNGetIncomingFlagValue(self.handle, reg_num, func_handle)) def get_incoming_var_for_parameter_var(self, in_var, func): in_buf = core.BNVariable() @@ -405,7 +403,7 @@ class CallingConvention(object): name = None if (func is not None) and (out_var.type == VariableSourceType.RegisterVariableSourceType): name = func.arch.get_reg_name(out_var.storage) - return function.Variable(func, out_var.type, out_var.index, out_var.storage, name) + return binaryninja.function.Variable(func, out_var.type, out_var.index, out_var.storage, name) def get_parameter_var_for_incoming_var(self, in_var, func): in_buf = core.BNVariable() @@ -417,4 +415,4 @@ class CallingConvention(object): else: func_obj = func.handle out_var = core.BNGetParameterVariableForIncomingVariable(self.handle, in_buf, func_obj) - return function.Variable(func, out_var.type, out_var.index, out_var.storage) + return binaryninja.function.Variable(func, out_var.type, out_var.index, out_var.storage) diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 5a602b89..3c7c5e45 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -25,7 +25,7 @@ import ctypes from binaryninja import _binaryninjacore as core class FileAccessor(object): - from binaryninja import log + def __init__(self): self._cb = core.BNFileAccessor() self._cb.context = 0 diff --git a/python/filemetadata.py b/python/filemetadata.py index 695b95f3..ee69dce8 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -23,12 +23,12 @@ import traceback import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja import associateddatastore #required for _FileMetadataAssociatedDataStore - +from binaryninja import log class NavigationHandler(object): - from binaryninja import log def _register(self, handle): self._cb = core.BNNavigationHandler() self._cb.context = 0 @@ -69,8 +69,7 @@ class FileMetadata(object): ``class FileMetadata`` represents the file being analyzed by Binary Ninja. It is responsible for opening, closing, creating the database (.bndb) files, and is used to keep track of undoable actions. """ - from binaryninja import startup - from binaryninja import binaryview + _associated_data = {} def __init__(self, filename = None, handle = None): @@ -83,7 +82,7 @@ class FileMetadata(object): if handle is not None: self.handle = core.handle_of_type(handle, core.BNFileMetadata) else: - startup._init_plugins() + binaryninja._init_plugins() self.handle = core.BNCreateFileMetadata() if filename is not None: core.BNSetFilename(self.handle, str(filename)) @@ -168,7 +167,7 @@ class FileMetadata(object): view = core.BNGetFileViewOfType(self.handle, "Raw") if view is None: return None - return binaryview.BinaryView(file_metadata = self, handle = view) + return binaryninja.binaryview.BinaryView(file_metadata = self, handle = view) @property def saved(self): @@ -323,7 +322,7 @@ class FileMetadata(object): lambda ctxt, cur, total: progress_func(cur, total))) if view is None: return None - return binaryview.BinaryView(file_metadata = self, handle = view) + return binaryninja.binaryview.BinaryView(file_metadata = self, handle = view) def save_auto_snapshot(self, progress_func = None): if progress_func is None: @@ -342,7 +341,7 @@ class FileMetadata(object): view = core.BNCreateBinaryViewOfType(view_type, self.raw.handle) if view is None: return None - return binaryview.BinaryView(file_metadata = self, handle = view) + return binaryninja.binaryview.BinaryView(file_metadata = self, handle = view) def __setattr__(self, name, value): try: diff --git a/python/function.py b/python/function.py index 2ee9b20d..a0269e75 100644 --- a/python/function.py +++ b/python/function.py @@ -24,13 +24,16 @@ import traceback import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, FunctionAnalysisSkipOverride) from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore - +from binaryninja import types +from binaryninja import highlight +from binaryninja import log class LookupTableEntry(object): def __init__(self, from_values, to_value): @@ -42,8 +45,7 @@ class LookupTableEntry(object): class RegisterValue(object): - from binaryninja import types - def __init__(self, arch = None, value = None, confidence = types.max_confidence): + def __init__(self, arch = None, value = None, confidence = binaryninja.types.max_confidence): self.is_constant = False if value is None: self.type = RegisterValueType.UndeterminedValue @@ -321,7 +323,6 @@ class IndirectBranchInfo(object): class ParameterVariables(object): - from binaryninja import types def __init__(self, var_list, confidence = types.max_confidence): self.vars = var_list self.confidence = confidence @@ -348,14 +349,6 @@ class _FunctionAssociatedDataStore(associateddatastore._AssociatedDataStore): class Function(object): - from binaryninja import callingconvention - from binaryninja import mediumlevelil - from binaryninja import lowlevelil - from binaryninja import basicblock - from binaryninja import types - from binaryninja import highlight - from binaryninja import platform - from binaryninja import architecture _associated_data = {} def __init__(self, view, handle): @@ -421,7 +414,7 @@ class Function(object): arch = core.BNGetFunctionArchitecture(self.handle) if arch is None: return None - self._arch = architecture.CoreArchitecture._from_cache(arch) + self._arch = binaryninja.architecture.CoreArchitecture._from_cache(arch) return self._arch @property @@ -433,7 +426,7 @@ class Function(object): plat = core.BNGetFunctionPlatform(self.handle) if plat is None: return None - self._platform = platform.Platform(None, handle = plat) + self._platform = binaryninja.platform.Platform(None, handle = plat) return self._platform @property @@ -487,7 +480,7 @@ class Function(object): blocks = core.BNGetFunctionBasicBlockList(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i]))) + result.append(binaryninja.basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -505,17 +498,17 @@ class Function(object): @property def low_level_il(self): """returns LowLevelILFunction used to represent Function low level IL (read-only)""" - return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelIL(self.handle), self) + return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLowLevelIL(self.handle), self) @property def lifted_il(self): """returns LowLevelILFunction used to represent lifted IL (read-only)""" - return lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) + return binaryninja.lowlevelil.LowLevelILFunction(self.arch, core.BNGetFunctionLiftedIL(self.handle), self) @property def medium_level_il(self): """Function medium level IL (read-only)""" - return mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self) + return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, core.BNGetFunctionMediumLevelIL(self.handle), self) @property def function_type(self): @@ -559,7 +552,7 @@ class Function(object): branches = core.BNGetIndirectBranches(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + result.append(IndirectBranchInfo(binaryninja.architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, binaryninja.architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -638,7 +631,7 @@ class Function(object): result = core.BNGetFunctionCallingConvention(self.handle) if not result.convention: return None - return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) + return binaryninja.callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @calling_convention.setter def calling_convention(self, value): @@ -855,7 +848,7 @@ class Function(object): blocks = core.BNGetFunctionBasicBlockList(self.handle, count) try: for i in xrange(0, count.value): - yield basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) + yield binaryninja.basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) finally: core.BNFreeBasicBlockList(blocks, count.value) @@ -937,7 +930,7 @@ class Function(object): :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 + :rtype: binaryninja.function.RegisterValue :Example: >>> func.get_reg_value_at(0x400dbe, 'rdi') @@ -957,7 +950,7 @@ class Function(object): :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 + :rtype: binaryninja.function.RegisterValue :Example: >>> func.get_reg_value_after(0x400dbe, 'rdi') @@ -979,7 +972,7 @@ class Function(object): :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 + :rtype: binaryninja.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 @@ -1148,7 +1141,7 @@ class Function(object): branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(IndirectBranchInfo(architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) + result.append(IndirectBranchInfo(binaryninja.architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, binaryninja.architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -1337,7 +1330,7 @@ class Function(object): block = core.BNGetFunctionBasicBlockAtAddress(self.handle, arch.handle, addr) if not block: return None - return basicblock.BasicBlock(self._view, handle = block) + return binaryninja.basicblock.BasicBlock(self._view, handle = block) def get_instr_highlight(self, addr, arch=None): """ @@ -1633,7 +1626,6 @@ class FunctionGraphEdge(object): class FunctionGraphBlock(object): def __init__(self, handle): - from binaryninja import binaryview self.handle = handle self.graph = graph @@ -1669,7 +1661,7 @@ class FunctionGraphBlock(object): block = mediumlevelil.MediumLevelILBasicBlock(view, block, mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func)) else: - block = basicblock.BasicBlock(view, block) + block = binaryninja.basicblock.BasicBlock(view, block) return block @property @@ -1678,7 +1670,7 @@ class FunctionGraphBlock(object): arch = core.BNGetFunctionGraphBlockArchitecture(self.handle) if arch is None: return None - return architecture.CoreArchitecture._from_cache(arch) + return binaryninja.architecture.CoreArchitecture._from_cache(arch) @property def start(self): @@ -1753,7 +1745,7 @@ class FunctionGraphBlock(object): core.BNFreeBasicBlock(target) target = None else: - target = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), + target = binaryninja.basicblock.BasicBlock(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(target)) core.BNFreeFunction(func) points = [] @@ -1841,8 +1833,6 @@ class DisassemblySettings(object): class FunctionGraph(object): - from binaryninja import log - from binaryninja import types def __init__(self, view, handle): self.view = view self.handle = handle @@ -2144,7 +2134,6 @@ class InstructionTextToken(object): ========================== ============================================ """ - from binaryninja import types def __init__(self, token_type, text, value = 0, size = 0, operand = 0xffffffff, context = InstructionTextTokenContext.NoTokenContext, address = 0, confidence = types.max_confidence): self.type = InstructionTextTokenType(token_type) diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 158a0700..e390a3c8 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -29,7 +29,7 @@ class FunctionRecognizer(object): from binaryninja import filemetadata from binaryninja import binaryview from binaryninja import lowlevelil - from binaryninja import log + _instance = None def __init__(self): @@ -54,7 +54,7 @@ class FunctionRecognizer(object): 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)) + func = binaryninja.function.Function(view, handle = core.BNNewFunctionReference(func)) il = lowlevelil.LowLevelILFunction(func.arch, handle = core.BNNewLowLevelILFunctionReference(il)) return self.recognize_low_level_il(view, func, il) except: @@ -68,7 +68,7 @@ class FunctionRecognizer(object): 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)) + func = binaryninja.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: diff --git a/python/interaction.py b/python/interaction.py index 8507682c..da6f792a 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -239,7 +239,7 @@ class DirectoryNameField(object): class InteractionHandler(object): - from binaryninja import log + from binaryninja import binaryview _interaction_handler = None diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 3b12c118..9c1db4cc 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -22,6 +22,7 @@ import ctypes import struct # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType from binaryninja import basicblock #required for LowLevelILBasicBlock @@ -340,8 +341,6 @@ class LowLevelILInstruction(object): } def __init__(self, func, expr_index, instr_index=None): - from binaryninja import function - from binaryninja import mediumlevelil instr = core.BNGetLowLevelILByIndex(func.handle, expr_index) self.function = func self.expr_index = expr_index @@ -530,7 +529,7 @@ class LowLevelILInstruction(object): context = tokens[i].context confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeInstructionText(tokens, count.value) return result @@ -552,7 +551,7 @@ class LowLevelILInstruction(object): expr = self.function.get_medium_level_il_expr_index(self.expr_index) if expr is None: return None - return mediumlevelil.MediumLevelILInstruction(self.function.medium_level_il, expr) + return binaryninja.mediumlevelil.MediumLevelILInstruction(self.function.medium_level_il, expr) @property def mapped_medium_level_il(self): @@ -560,20 +559,20 @@ class LowLevelILInstruction(object): expr = self.function.get_mapped_medium_level_il_expr_index(self.expr_index) if expr is None: return None - return mediumlevelil.MediumLevelILInstruction(self.function.mapped_medium_level_il, expr) + return binaryninja.mediumlevelil.MediumLevelILInstruction(self.function.mapped_medium_level_il, expr) @property def value(self): """Value of expression if constant or a known value (read-only)""" value = core.BNGetLowLevelILExprValue(self.function.handle, self.expr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result @property def possible_values(self): """Possible values of expression using path-sensitive static data flow analysis (read-only)""" value = core.BNGetLowLevelILPossibleExprValues(self.function.handle, self.expr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -603,74 +602,74 @@ class LowLevelILInstruction(object): def get_reg_value(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_reg_value_after(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_reg_values(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetLowLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_flag_value_after(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_flag_values(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetLowLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset, size): value = core.BNGetLowLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_stack_contents_after(self, offset, size): value = core.BNGetLowLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_stack_contents(self, offset, size): value = core.BNGetLowLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_stack_contents_after(self, offset, size): value = core.BNGetLowLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -694,7 +693,7 @@ class LowLevelILExpr(object): class LowLevelILFunction(object): """ - ``class LowLevelILFunction`` contains the list of LowLevelILExpr objects that make up a function. LowLevelILExpr + ``class LowLevelILFunction`` contains the list of LowLevelILExpr objects that make up a binaryninja.function. LowLevelILExpr objects can be added to the LowLevelILFunction by calling ``append`` and passing the result of the various class methods which return LowLevelILExpr objects. @@ -805,7 +804,7 @@ class LowLevelILFunction(object): result = core.BNGetMediumLevelILForLowLevelIL(self.handle) if not result: return None - return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) @property def mapped_medium_level_il(self): @@ -815,7 +814,7 @@ class LowLevelILFunction(object): result = core.BNGetMappedMediumLevelIL(self.handle) if not result: return None - return mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) + return binaryninja.mediumlevelil.MediumLevelILFunction(self.arch, result, self.source_function) def __setattr__(self, name, value): try: @@ -2302,13 +2301,13 @@ class LowLevelILFunction(object): def get_ssa_reg_value(self, reg_ssa): reg = self.arch.get_reg_index(reg_ssa.reg) value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, reg_ssa.version) - result = function.RegisterValue(self.arch, value) + result = binaryninja.function.RegisterValue(self.arch, value) return result def get_ssa_flag_value(self, flag_ssa): flag = self.arch.get_flag_index(flag_ssa.flag) value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, flag_ssa.version) - result = function.RegisterValue(self.arch, value) + result = binaryninja.function.RegisterValue(self.arch, value) return result def get_medium_level_il_instruction_index(self, instr): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index 9a21bb23..a62c5c04 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -238,14 +238,14 @@ class MediumLevelILInstruction(object): elif operand_type == "intrinsic": value = lowlevelil.ILIntrinsic(func.arch, instr.operands[i]) elif operand_type == "var": - value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + value = binaryninja.function.Variable.from_identifier(self.function.source_function, instr.operands[i]) elif operand_type == "var_ssa": - var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + var = binaryninja.function.Variable.from_identifier(self.function.source_function, instr.operands[i]) version = instr.operands[i + 1] i += 1 value = SSAVariable(var, version) elif operand_type == "var_ssa_dest_and_src": - var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + var = binaryninja.function.Variable.from_identifier(self.function.source_function, instr.operands[i]) dest_version = instr.operands[i + 1] src_version = instr.operands[i + 2] i += 2 @@ -346,14 +346,14 @@ class MediumLevelILInstruction(object): def value(self): """Value of expression if constant or a known value (read-only)""" value = core.BNGetMediumLevelILExprValue(self.function.handle, self.expr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result @property def possible_values(self): """Possible values of expression using path-sensitive static data flow analysis (read-only)""" value = core.BNGetMediumLevelILPossibleExprValues(self.function.handle, self.expr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -451,7 +451,7 @@ class MediumLevelILInstruction(object): return [] result = [] for operand in self.operands: - if (isinstance(operand, function.Variable)) or (isinstance(operand, SSAVariable)): + if (isinstance(operand, binaryninja.function.Variable)) or (isinstance(operand, SSAVariable)): result.append(operand) elif isinstance(operand, MediumLevelILInstruction): result += operand.vars_read @@ -474,7 +474,7 @@ class MediumLevelILInstruction(object): var_data.index = ssa_var.var.index var_data.storage = ssa_var.var.storage value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -488,88 +488,88 @@ class MediumLevelILInstruction(object): def get_var_for_reg(self, reg): reg = self.function.arch.get_reg_index(reg) result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.storage) + return binaryninja.function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_flag(self, flag): flag = self.function.arch.get_flag_index(flag) result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.storage) + return binaryninja.function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_stack_location(self, offset): result = core.BNGetMediumLevelILVariableForStackLocationAtInstruction(self.function.handle, offset, self.instr_index) - return function.Variable(self.function.source_function, result.type, result.index, result.storage) + return binaryninja.function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_reg_value(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_reg_value_after(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_reg_values(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_flag_value_after(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_flag_values(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_stack_contents(self, offset, size): value = core.BNGetMediumLevelILStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_stack_contents_after(self, offset, size): value = core.BNGetMediumLevelILStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.RegisterValue(self.function.arch, value) + result = binaryninja.function.RegisterValue(self.function.arch, value) return result def get_possible_stack_contents(self, offset, size): value = core.BNGetMediumLevelILPossibleStackContentsAtInstruction(self.function.handle, offset, size, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_stack_contents_after(self, offset, size): value = core.BNGetMediumLevelILPossibleStackContentsAfterInstruction(self.function.handle, offset, size, self.instr_index) - result = function.PossibleValueSet(self.function.arch, value) + result = binaryninja.function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result @@ -596,7 +596,7 @@ class MediumLevelILExpr(object): class MediumLevelILFunction(object): """ - ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a function. MediumLevelILExpr + ``class MediumLevelILFunction`` contains the list of MediumLevelILExpr objects that make up a binaryninja.function. MediumLevelILExpr objects can be added to the MediumLevelILFunction by calling ``append`` and passing the result of the various class methods which return MediumLevelILExpr objects. """ @@ -902,7 +902,7 @@ class MediumLevelILFunction(object): var_data.index = ssa_var.var.index var_data.storage = ssa_var.var.storage value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, ssa_var.version) - result = function.RegisterValue(self.arch, value) + result = binaryninja.function.RegisterValue(self.arch, value) return result def get_low_level_il_instruction_index(self, instr): diff --git a/python/platform.py b/python/platform.py index ff59be50..083ebf06 100644 --- a/python/platform.py +++ b/python/platform.py @@ -21,6 +21,7 @@ import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core #2-3 compatibility @@ -28,11 +29,11 @@ from six import with_metaclass class _PlatformMetaClass(type): - from binaryninja import startup + from binaryninja import types @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() platforms = core.BNGetPlatformList(count) result = [] @@ -43,7 +44,7 @@ class _PlatformMetaClass(type): @property def os_list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() platforms = core.BNGetPlatformOSList(count) result = [] @@ -53,7 +54,7 @@ class _PlatformMetaClass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() platforms = core.BNGetPlatformList(count) try: @@ -69,14 +70,14 @@ class _PlatformMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) def __getitem__(cls, value): - startup._init_plugins() + binaryninja._init_plugins() platform = core.BNGetPlatformByName(str(value)) if platform is None: raise KeyError("'%s' is not a valid platform" % str(value)) return Platform(None, platform) def get_list(cls, os = None, arch = None): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() if os is None: platforms = core.BNGetPlatformList(count) @@ -96,9 +97,6 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): ``class Platform`` contains all information releated to the execution environment of the binary, mainly the calling conventions used. """ - from binaryninja import architecture - from binaryninja import callingconvention - from binaryninja import types name = None def __init__(self, arch, handle = None): @@ -108,7 +106,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): else: self.handle = handle self.__dict__["name"] = core.BNGetPlatformName(self.handle) - self.arch = architecture.CoreArchitecture._from_cache(core.BNGetPlatformArchitecture(self.handle)) + self.arch = binaryninja.architecture.CoreArchitecture._from_cache(core.BNGetPlatformArchitecture(self.handle)) def __del__(self): core.BNFreePlatform(self.handle) @@ -140,7 +138,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): result = core.BNGetPlatformDefaultCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(handle=result) + return binaryninja.callingconvention.CallingConvention(handle=result) @default_calling_convention.setter def default_calling_convention(self, value): @@ -158,7 +156,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): result = core.BNGetPlatformCdeclCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(handle=result) + return binaryninja.callingconvention.CallingConvention(handle=result) @cdecl_calling_convention.setter def cdecl_calling_convention(self, value): @@ -176,7 +174,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): result = core.BNGetPlatformStdcallCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(handle=result) + return binaryninja.callingconvention.CallingConvention(handle=result) @stdcall_calling_convention.setter def stdcall_calling_convention(self, value): @@ -194,7 +192,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): result = core.BNGetPlatformFastcallCallingConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(handle=result) + return binaryninja.callingconvention.CallingConvention(handle=result) @fastcall_calling_convention.setter def fastcall_calling_convention(self, value): @@ -212,7 +210,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): result = core.BNGetPlatformSystemCallConvention(self.handle) if result is None: return None - return callingconvention.CallingConvention(handle=result) + return binaryninja.callingconvention.CallingConvention(handle=result) @system_call_convention.setter def system_call_convention(self, value): @@ -230,7 +228,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): cc = core.BNGetPlatformCallingConventions(self.handle, count) result = [] for i in xrange(0, count.value): - result.append(callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) + result.append(binaryninja.callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) core.BNFreeCallingConventionList(cc, count.value) return result @@ -241,8 +239,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformTypes(self.handle, count) result = {} for i in xrange(0, count.value): - name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -253,8 +251,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformVariables(self.handle, count) result = {} for i in xrange(0, count.value): - name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -265,8 +263,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformFunctions(self.handle, count) result = {} for i in xrange(0, count.value): - name = types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -277,8 +275,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): call_list = core.BNGetPlatformSystemCalls(self.handle, count) result = {} for i in xrange(0, count.value): - name = types.QualifiedName._from_core_struct(call_list[i].name) - t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(call_list[i].name) + t = binaryninja.types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) core.BNFreeSystemCallList(call_list, count.value) return result @@ -329,25 +327,25 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): return Platform(None, handle = result), new_addr.value def get_type_by_name(self, name): - name = types.QualifiedName(name)._get_core_struct() + name = binaryninja.types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformTypeByName(self.handle, name) if not obj: return None - return types.Type(obj, platform = self) + return binaryninja.types.Type(obj, platform = self) def get_variable_by_name(self, name): - name = types.QualifiedName(name)._get_core_struct() + name = binaryninja.types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformVariableByName(self.handle, name) if not obj: return None - return types.Type(obj, platform = self) + return binaryninja.types.Type(obj, platform = self) def get_function_by_name(self, name): - name = types.QualifiedName(name)._get_core_struct() + name = binaryninja.types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformFunctionByName(self.handle, name) if not obj: return None - return types.Type(obj, platform = self) + return binaryninja.types.Type(obj, platform = self) def get_system_call_name(self, number): return core.BNGetPlatformSystemCallName(self.handle, number) @@ -356,15 +354,15 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): obj = core.BNGetPlatformSystemCallType(self.handle, number) if not obj: return None - return types.Type(obj, platform = self) + return binaryninja.types.Type(obj, platform = self) def generate_auto_platform_type_id(self, name): - name = types.QualifiedName(name)._get_core_struct() + name = binaryninja.types.QualifiedName(name)._get_core_struct() return core.BNGenerateAutoPlatformTypeId(self.handle, name) def generate_auto_platform_type_ref(self, type_class, name): type_id = self.generate_auto_platform_type_id(name) - return types.NamedTypeReference(type_class, type_id, name) + return binaryninja.types.NamedTypeReference(type_class, type_id, name) def get_auto_platform_type_id_source(self): return core.BNGetAutoPlatformTypeIdSource(self.handle) @@ -405,16 +403,16 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) + return binaryninja.types.TypeParserResult(type_dict, variables, functions) def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ @@ -451,13 +449,13 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): variables = {} functions = {} for i in xrange(0, parse.typeCount): - name = types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) for i in xrange(0, parse.variableCount): - name = types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) for i in xrange(0, parse.functionCount): - name = types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) - return types.TypeParserResult(type_dict, variables, functions) + return binaryninja.types.TypeParserResult(type_dict, variables, functions) diff --git a/python/plugin.py b/python/plugin.py index 5dad9fb6..4cf6fb77 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -23,6 +23,8 @@ import ctypes import threading # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja +from binaryninja import log from binaryninja import _binaryninjacore as core from binaryninja.enums import PluginCommandType @@ -40,10 +42,10 @@ class PluginCommandContext(object): class _PluginCommandMetaClass(type): - from binaryninja import startup + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() commands = core.BNGetAllPluginCommands(count) result = [] @@ -53,7 +55,7 @@ class _PluginCommandMetaClass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() commands = core.BNGetAllPluginCommands(count) try: @@ -70,11 +72,11 @@ class _PluginCommandMetaClass(type): class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): - from binaryninja import startup + from binaryninja import filemetadata from binaryninja import binaryview from binaryninja import function - from binaryninja import log + _registered_commands = [] def __init__(self, cmd): @@ -92,8 +94,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): @classmethod def _default_action(cls, view, action): try: - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj) except: log.log_error(traceback.format_exc()) @@ -101,8 +103,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): @classmethod def _address_action(cls, view, addr, action): try: - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr) except: log.log_error(traceback.format_exc()) @@ -110,8 +112,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): @classmethod def _range_action(cls, view, addr, length, action): try: - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr, length) except: log.log_error(traceback.format_exc()) @@ -119,9 +121,9 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): @classmethod def _function_action(cls, view, func, action): try: - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) - func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + func_obj = binaryninja.function.Function(view_obj, core.BNNewFunctionReference(func)) action(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -175,8 +177,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): try: if is_valid is None: return True - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj) except: log.log_error(traceback.format_exc()) @@ -187,8 +189,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): try: if is_valid is None: return True - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr) except: log.log_error(traceback.format_exc()) @@ -199,8 +201,8 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): try: if is_valid is None: return True - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr, length) except: log.log_error(traceback.format_exc()) @@ -211,9 +213,9 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): try: if is_valid is None: return True - file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) - view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) - func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) + func_obj = binaryninja.function.Function(view_obj, core.BNNewFunctionReference(func)) return is_valid(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -288,7 +290,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(lambda ctxt, view: cls._default_action(view, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView))(lambda ctxt, view: cls._default_is_valid(view, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -307,7 +309,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_address`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_action(view, addr, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong)(lambda ctxt, view, addr: cls._address_is_valid(view, addr, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -326,7 +328,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_range`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls._range_action(view, addr, length, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.c_ulonglong, ctypes.c_ulonglong)(lambda ctxt, view, addr, length: cls._range_is_valid(view, addr, length, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -345,7 +347,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNFunction))(lambda ctxt, view, func: cls._function_action(view, func, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNFunction))(lambda ctxt, view, func: cls._function_is_valid(view, func, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -537,7 +539,7 @@ class MainThreadAction(object): class MainThreadActionHandler(object): - from binaryninja import log + _main_thread = None def __init__(self): @@ -572,7 +574,7 @@ class _BackgroundTaskMetaclass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() tasks = core.BNGetRunningBackgroundTasks(count) try: diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 66f642c3..002db573 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -199,7 +199,7 @@ class RepositoryManager(object): ``RepositoryManager`` Keeps track of all the repositories and keeps the enabled_plugins.json file coherent with the plugins that are installed/unstalled enabled/disabled """ - from binaryninja import startup + def __init__(self, handle=None): raise Exception("RepositoryManager temporarily disabled!") self.handle = core.BNGetRepositoryManager() @@ -236,7 +236,7 @@ class RepositoryManager(object): @property def default_repository(self): """Gets the default Repository""" - startup._init_plugins() + binaryninja._init_plugins() return Repository(handle=core.BNRepositoryManagerGetDefaultRepository(self.handle)) def enable_plugin(self, plugin, install=True, repo=None): diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index ac0ffd4c..0b15ee18 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -29,6 +29,7 @@ import sys # Binary Ninja components -- additional imports belong in the appropriate class from binaryninja import _binaryninjacore as core from binaryninja.enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState +import binaryninja.log #2-3 compatibility from six import with_metaclass @@ -58,7 +59,6 @@ class _ThreadActionContext(object): class ScriptingOutputListener(object): - from binaryninja import log def _register(self, handle): self._cb = core.BNScriptingOutputListener() self._cb.context = 0 @@ -74,19 +74,19 @@ class ScriptingOutputListener(object): try: self.notify_output(text) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _error(self, ctxt, text): try: self.notify_error(text) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _input_ready_state_changed(self, ctxt, state): try: self.notify_input_ready_state_changed(state) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def notify_output(self, text): pass @@ -99,10 +99,6 @@ class ScriptingOutputListener(object): class ScriptingInstance(object): - from binaryninja import binaryview - from binaryninja import basicblock - from binaryninja import log - from binaryninja import function def __init__(self, provider, handle = None): if handle is None: self._cb = core.BNScriptingInstanceCallbacks() @@ -126,34 +122,34 @@ class ScriptingInstance(object): try: self.perform_destroy_instance() except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _execute_script_input(self, ctxt, text): try: return self.perform_execute_script_input(text) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return ScriptingProviderExecuteResult.InvalidScriptInput def _set_current_binary_view(self, ctxt, view): try: if view: - view = binaryview.BinaryView(handle = core.BNNewViewReference(view)) + view = binaryninja.binaryview.BinaryView(handle = core.BNNewViewReference(view)) else: view = None self.perform_set_current_binary_view(view) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _set_current_function(self, ctxt, func): try: if func: - func = function.Function(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) + func = binaryninja.function.Function(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewFunctionReference(func)) else: func = None self.perform_set_current_function(func) except: - log.log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _set_current_basic_block(self, ctxt, block): try: @@ -162,25 +158,25 @@ class ScriptingInstance(object): if func is None: block = None else: - block = basicblock.BasicBlock(binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block)) + block = binaryninja.basicblock.BasicBlock(binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func)), core.BNNewBasicBlockReference(block)) core.BNFreeFunction(func) else: block = None self.perform_set_current_basic_block(block) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _set_current_address(self, ctxt, addr): try: self.perform_set_current_address(addr) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def _set_current_selection(self, ctxt, begin, end): try: self.perform_set_current_selection(begin, end) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @abc.abstractmethod def perform_destroy_instance(self): @@ -259,11 +255,11 @@ class ScriptingInstance(object): class _ScriptingProviderMetaclass(type): - from binaryninja import startup + @property def list(self): """List all ScriptingProvider types (read-only)""" - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() types = core.BNGetScriptingProviderList(count) result = [] @@ -273,7 +269,7 @@ class _ScriptingProviderMetaclass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() types = core.BNGetScriptingProviderList(count) try: @@ -283,7 +279,7 @@ class _ScriptingProviderMetaclass(type): core.BNFreeScriptingProviderList(types) def __getitem__(self, value): - startup._init_plugins() + binaryninja._init_plugins() provider = core.BNGetScriptingProviderByName(str(value)) if provider is None: raise KeyError("'%s' is not a valid scripting provider" % str(value)) @@ -297,7 +293,6 @@ class _ScriptingProviderMetaclass(type): class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): - from binaryninja import log name = None instance_class = None @@ -318,7 +313,7 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): self._cb = core.BNScriptingProviderCallbacks() self._cb.context = 0 self._cb.createInstance = self._cb.createInstance.__class__(self._create_instance) - self.handle = core.BNRegisterScriptingProvider(self.__class__.name, self._cb) + self.handle = core.BNRegisterScriptingProvider(self.__class__.name.encode('utf8'), self._cb) self.__class__._registered_providers.append(self) def _create_instance(self, ctxt): @@ -328,7 +323,7 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): return None return ctypes.cast(core.BNNewScriptingInstanceReference(result.handle), ctypes.c_void_p).value except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return None def create_instance(self): @@ -339,7 +334,6 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): class _PythonScriptingInstanceOutput(object): - from binaryninja import log def __init__(self, orig, is_error): self.orig = orig self.is_error = is_error @@ -395,7 +389,7 @@ class _PythonScriptingInstanceOutput(object): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: - if log.is_output_redirected_to_log(): + if binaryninja.log.is_output_redirected_to_log(): self.buffer += data while True: i = self.buffer.find('\n') @@ -405,9 +399,9 @@ class _PythonScriptingInstanceOutput(object): self.buffer = self.buffer[i + 1:] if self.is_error: - log.log_error(line) + binaryninja.log.log_error(line) else: - log.log_info(line) + binaryninja.log.log_info(line) else: self.orig.write(data) else: diff --git a/python/startup.py b/python/startup.py index 919a8fbe..04e7b980 100644 --- a/python/startup.py +++ b/python/startup.py @@ -18,18 +18,18 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -from binaryninja import _binaryninjacore as core +#from binaryninja import _binaryninjacore as core -_plugin_init = False +#_plugin_init = False -def _init_plugins(): - global _plugin_init - if not _plugin_init: - _plugin_init = True - core.BNInitCorePlugins() - core.BNInitUserPlugins() - core.BNInitRepoPlugins() - if not core.BNIsLicenseValidated(): - raise RuntimeError("License is not valid. Please supply a valid license.") +# def _init_plugins(): +# global _plugin_init +# if not _plugin_init: +# _plugin_init = True +# core.BNInitCorePlugins() +# core.BNInitUserPlugins() +# core.BNInitRepoPlugins() +# if not core.BNIsLicenseValidated(): +# raise RuntimeError("License is not valid. Please supply a valid license.") diff --git a/python/transform.py b/python/transform.py index f04bfdca..fd68a987 100644 --- a/python/transform.py +++ b/python/transform.py @@ -23,6 +23,9 @@ import ctypes import abc # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja +from binaryninja import log +from binaryninja import databuffer from binaryninja import _binaryninjacore as core from binaryninja.enums import TransformType @@ -31,10 +34,10 @@ from six import with_metaclass class _TransformMetaClass(type): - from binaryninja import startup + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() xforms = core.BNGetTransformTypeList(count) result = [] @@ -44,7 +47,7 @@ class _TransformMetaClass(type): return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() xforms = core.BNGetTransformTypeList(count) try: @@ -60,14 +63,14 @@ class _TransformMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) def __getitem__(cls, name): - startup._init_plugins() + binaryninja._init_plugins() xform = core.BNGetTransformByName(name) if xform is None: raise KeyError("'%s' is not a valid transform" % str(name)) return Transform(xform) def register(cls): - startup._init_plugins() + binaryninja._init_plugins() if cls.name is None: raise ValueError("transform 'name' is not defined") if cls.long_name is None: @@ -92,7 +95,7 @@ class TransformParameter(object): class Transform(with_metaclass(_TransformMetaClass, object)): - from binaryninja import log + from binaryninja import databuffer transform_type = None name = None diff --git a/python/types.py b/python/types.py index cbe5a7bc..adb9e03a 100644 --- a/python/types.py +++ b/python/types.py @@ -24,6 +24,7 @@ max_confidence = 255 import ctypes # Binary Ninja components -- additional imports belong in the appropriate class +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType @@ -212,8 +213,6 @@ class FunctionParameter(object): class Type(object): def __init__(self, handle, platform = None, confidence = max_confidence): - from binaryninja import callingconvention - from binaryninja import function self.handle = handle self.confidence = confidence self.platform = platform @@ -293,7 +292,7 @@ class Type(object): result = core.BNGetTypeCallingConvention(self.handle) if not result.convention: return None - return callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) + return binaryninja.callingconvention.CallingConvention(None, handle = result.convention, confidence = result.confidence) @property def parameters(self): @@ -311,7 +310,7 @@ class Type(object): name = self.platform.arch.get_reg_name(params[i].location.storage) elif params[i].location.type == VariableSourceType.StackVariableSourceType: name = "arg_%x" % params[i].location.storage - param_location = function.Variable(None, params[i].location.type, params[i].location.index, + param_location = binaryninja.function.Variable(None, params[i].location.type, params[i].location.index, params[i].location.storage, name, param_type) result.append(FunctionParameter(param_type, params[i].name, param_location)) core.BNFreeTypeParameterList(params, count.value) @@ -413,7 +412,7 @@ class Type(object): context = tokens[i].context confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -433,7 +432,7 @@ class Type(object): context = tokens[i].context confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result @@ -453,7 +452,7 @@ class Type(object): context = tokens[i].context confidence = tokens[i].confidence address = tokens[i].address - result.append(function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) + result.append(binaryninja.function.InstructionTextToken(token_type, text, value, size, operand, context, address, confidence)) core.BNFreeTokenList(tokens, count.value) return result diff --git a/python/undoaction.py b/python/undoaction.py index 9771df38..732d559a 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -28,8 +28,8 @@ from binaryninja.enums import ActionType class UndoAction(object): - from binaryninja import startup - from binaryninja import log + + name = None action_type = None _registered = False @@ -52,7 +52,7 @@ class UndoAction(object): @classmethod def register(cls): - startup._init_plugins() + binaryninja._init_plugins() if cls.name is None: raise ValueError("undo action 'name' not defined") if cls.action_type is None: diff --git a/python/update.py b/python/update.py index 1fda149b..560f05ec 100644 --- a/python/update.py +++ b/python/update.py @@ -31,10 +31,10 @@ from six import with_metaclass class _UpdateChannelMetaClass(type): - from binaryninja import startup + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() errors = ctypes.c_char_p() channels = core.BNGetUpdateChannels(count, errors) @@ -57,7 +57,7 @@ class _UpdateChannelMetaClass(type): return core.BNSetActiveUpdateChannel(value) def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() errors = ctypes.c_char_p() channels = core.BNGetUpdateChannels(count, errors) @@ -78,7 +78,7 @@ class _UpdateChannelMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) def __getitem__(cls, name): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() errors = ctypes.c_char_p() channels = core.BNGetUpdateChannels(count, errors) @@ -98,7 +98,7 @@ class _UpdateChannelMetaClass(type): class UpdateProgressCallback(object): - from binaryninja import log + def __init__(self, func): self.cb = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(self.callback) self.func = func -- cgit v1.3.1 From 1c03ac08aa94f5bedf21ec8f48ee1ec998e0e50c Mon Sep 17 00:00:00 2001 From: Jordan Wiens Date: Tue, 29 May 2018 14:32:08 -0400 Subject: addition 3 compatibility changes --- python/__init__.py | 8 ++-- python/architecture.py | 96 +++++++++++++++++++++--------------------- python/basicblock.py | 22 +++++----- python/binaryview.py | 53 +++++++++++------------ python/callingconvention.py | 20 +++++---- python/demangle.py | 7 +++- python/function.py | 100 +++++++++++++++++++++++--------------------- python/generator.cpp | 45 ++++++++++++++++++-- python/interaction.py | 19 +++++---- python/lowlevelil.py | 39 +++++++++-------- python/mediumlevelil.py | 33 ++++++++------- python/metadata.py | 9 ++-- python/platform.py | 35 ++++++++-------- python/plugin.py | 9 ++-- python/pluginmanager.py | 8 ++-- python/scriptingprovider.py | 7 ++-- python/setting.py | 11 +++-- python/transform.py | 17 ++++---- python/types.py | 23 +++++----- python/update.py | 11 ++--- 20 files changed, 325 insertions(+), 247 deletions(-) (limited to 'python/plugin.py') diff --git a/python/__init__.py b/python/__init__.py index d88703cc..a3ba0453 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -118,8 +118,10 @@ class PluginManagerLoadPluginCallback(object): def __init__(self): self.cb = ctypes.CFUNCTYPE( ctypes.c_bool, - ctypes.c_char_p, - ctypes.c_char_p, + core.compatstring, + core.compatstring, + # ctypes.c_char_p, + # ctypes.c_char_p, ctypes.c_void_p)(self._load_plugin) def _load_plugin(self, repo_path, plugin_path, ctx): @@ -147,7 +149,7 @@ class PluginManagerLoadPluginCallback(object): load_plugin = PluginManagerLoadPluginCallback() -core.BNRegisterForPluginLoading(_plugin_api_name.encode("utf8"), load_plugin.cb, 0) +core.BNRegisterForPluginLoading(_plugin_api_name, load_plugin.cb, 0) class _DestructionCallbackHandler(object): diff --git a/python/architecture.py b/python/architecture.py index a705f2d9..b99da184 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -38,7 +38,7 @@ from binaryninja import callingconvention # 2-3 compatibility from six import with_metaclass - +from six.moves import range class _ArchitectureMetaClass(type): @@ -48,7 +48,7 @@ class _ArchitectureMetaClass(type): count = ctypes.c_ulonglong() archs = core.BNGetArchitectureList(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(CoreArchitecture._from_cache(archs[i])) core.BNFreeArchitectureList(archs) return result @@ -58,7 +58,7 @@ class _ArchitectureMetaClass(type): count = ctypes.c_ulonglong() archs = core.BNGetArchitectureList(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield CoreArchitecture._from_cache(archs[i]) finally: core.BNFreeArchitectureList(archs) @@ -369,7 +369,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): for intrinsic in self.__class__.intrinsics.keys(): if intrinsic not in self._intrinsics: info = self.__class__.intrinsics[intrinsic] - for i in xrange(0, len(info.inputs)): + for i in range(0, len(info.inputs)): if isinstance(info.inputs[i], types.Type): info.inputs[i] = binaryninja.function.IntrinsicInput(info.inputs[i]) elif isinstance(info.inputs[i], tuple): @@ -406,7 +406,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): count = ctypes.c_ulonglong() regs = core.BNGetFullWidthArchitectureRegisters(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) core.BNFreeRegisterList(regs) return result @@ -417,7 +417,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): count = ctypes.c_ulonglong() cc = core.BNGetArchitectureCallingConventions(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): obj = callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i])) result[obj.name] = obj core.BNFreeCallingConventionList(cc, count) @@ -508,7 +508,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): 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)): + for i in range(0, len(info.branches)): if isinstance(info.branches[i].type, str): result[0].branchType[i] = BranchType[info.branches[i].type] else: @@ -534,7 +534,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): length[0] = info[1] count[0] = len(tokens) token_buf = (core.BNInstructionTextToken * len(tokens))() - for i in xrange(0, len(tokens)): + for i in range(0, len(tokens)): if isinstance(tokens[i].type, str): token_buf[i].type = InstructionTextTokenType[tokens[i].type] else: @@ -627,7 +627,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): regs = self._full_width_regs.values() count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = regs[i] result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -642,7 +642,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): regs = self._regs_by_index.keys() count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = regs[i] result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -657,7 +657,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): flags = self._flags_by_index.keys() count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): + for i in range(0, len(flags)): flag_buf[i] = flags[i] result = ctypes.cast(flag_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, flag_buf) @@ -672,7 +672,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): write_types = self._flag_write_types_by_index.keys() count[0] = len(write_types) type_buf = (ctypes.c_uint * len(write_types))() - for i in xrange(0, len(write_types)): + for i in range(0, len(write_types)): type_buf[i] = write_types[i] result = ctypes.cast(type_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, type_buf) @@ -687,7 +687,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): sem_classes = self._semantic_flag_classes_by_index.keys() count[0] = len(sem_classes) class_buf = (ctypes.c_uint * len(sem_classes))() - for i in xrange(0, len(sem_classes)): + for i in range(0, len(sem_classes)): class_buf[i] = sem_classes[i] result = ctypes.cast(class_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, class_buf) @@ -702,7 +702,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): sem_groups = self._semantic_flag_groups_by_index.keys() count[0] = len(sem_groups) group_buf = (ctypes.c_uint * len(sem_groups))() - for i in xrange(0, len(sem_groups)): + for i in range(0, len(sem_groups)): group_buf[i] = sem_groups[i] result = ctypes.cast(group_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, group_buf) @@ -735,7 +735,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): flags.append(self._flags[name]) count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): + for i in range(0, len(flags)): flag_buf[i] = flags[i] result = ctypes.cast(flag_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, flag_buf) @@ -753,7 +753,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): flags = [] count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): + for i in range(0, len(flags)): flag_buf[i] = flags[i] result = ctypes.cast(flag_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, flag_buf) @@ -801,7 +801,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): flags = [] count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() - for i in xrange(0, len(flags)): + for i in range(0, len(flags)): flag_buf[i] = flags[i] result = ctypes.cast(flag_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, flag_buf) @@ -828,7 +828,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): write_type_name = self._flag_write_types_by_index[write_type] flag_name = self._flags_by_index[flag] operand_list = [] - for i in xrange(operand_count): + for i in range(operand_count): if operands[i].constant: operand_list.append(operands[i].value) elif lowlevelil.LLIL_REG_IS_TEMP(operands[i].reg): @@ -917,7 +917,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): try: count[0] = len(self.global_regs) reg_buf = (ctypes.c_uint * len(self.global_regs))() - for i in xrange(0, len(self.global_regs)): + for i in range(0, len(self.global_regs)): reg_buf[i] = self._all_regs[self.global_regs[i]] result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -941,7 +941,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): regs = self._reg_stacks_by_index.keys() count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = regs[i] result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -992,7 +992,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): regs = self._intrinsics_by_index.keys() count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = regs[i] result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -1008,7 +1008,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): inputs = self._intrinsics_by_index[intrinsic][1].inputs count[0] = len(inputs) input_buf = (core.BNNameAndType * len(inputs))() - for i in xrange(0, len(inputs)): + for i in range(0, len(inputs)): input_buf[i].name = inputs[i].name input_buf[i].type = core.BNNewTypeReference(inputs[i].type.handle) input_buf[i].typeConfidence = inputs[i].type.confidence @@ -1029,7 +1029,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): raise ValueError("freeing name and type list that wasn't allocated") name_and_types = self._pending_name_and_type_lists[buf.value][1] count = self._pending_name_and_type_lists[buf.value][2] - for i in xrange(0, count): + for i in range(0, count): core.BNFreeType(name_and_types[i].type) del self._pending_name_and_type_lists[buf.value] except (ValueError, KeyError): @@ -1041,7 +1041,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): outputs = self._intrinsics_by_index[intrinsic][1].outputs count[0] = len(outputs) output_buf = (core.BNTypeWithConfidence * len(outputs))() - for i in xrange(0, len(outputs)): + for i in range(0, len(outputs)): output_buf[i].type = core.BNNewTypeReference(outputs[i].handle) output_buf[i].confidence = outputs[i].confidence result = ctypes.cast(output_buf, ctypes.c_void_p) @@ -1061,7 +1061,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): raise ValueError("freeing type list that wasn't allocated") types = self._pending_type_lists[buf.value][1] count = self._pending_type_lists[buf.value][2] - for i in xrange(0, count): + for i in range(0, count): core.BNFreeType(types[i].type) del self._pending_type_lists[buf.value] except (ValueError, KeyError): @@ -1710,7 +1710,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): :rtype: LowLevelILExpr index """ operand_list = (core.BNRegisterOrConstant * len(operands))() - for i in xrange(len(operands)): + for i in range(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False operand_list[i].reg = self.regs[operands[i]].index @@ -1765,7 +1765,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): count = ctypes.c_ulonglong() regs = core.BNGetModifiedArchitectureRegistersOnWrite(self.handle, reg, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) core.BNFreeRegisterList(regs) return result @@ -2074,7 +2074,7 @@ class CoreArchitecture(Architecture): self._regs_by_index = {} self._full_width_regs = {} self.__dict__["regs"] = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureRegisterName(self.handle, regs[i]) info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) @@ -2082,7 +2082,7 @@ class CoreArchitecture(Architecture): ImplicitRegisterExtend(info.extend), regs[i]) self._all_regs[name] = regs[i] self._regs_by_index[regs[i]] = name - for i in xrange(0, count.value): + for i in range(0, count.value): info = core.BNGetArchitectureRegisterInfo(self.handle, regs[i]) full_width_reg = core.BNGetArchitectureRegisterName(self.handle, info.fullWidthRegister) if full_width_reg not in self._full_width_regs: @@ -2094,7 +2094,7 @@ class CoreArchitecture(Architecture): self._flags = {} self._flags_by_index = {} self.__dict__["flags"] = [] - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureFlagName(self.handle, flags[i]) self._flags[name] = flags[i] self._flags_by_index[flags[i]] = name @@ -2106,7 +2106,7 @@ class CoreArchitecture(Architecture): self._flag_write_types = {} self._flag_write_types_by_index = {} self.__dict__["flag_write_types"] = [] - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureFlagWriteTypeName(self.handle, write_types[i]) self._flag_write_types[name] = write_types[i] self._flag_write_types_by_index[write_types[i]] = name @@ -2118,7 +2118,7 @@ class CoreArchitecture(Architecture): self._semantic_flag_classes = {} self._semantic_flag_classes_by_index = {} self.__dict__["semantic_flag_classes"] = [] - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureSemanticFlagClassName(self.handle, sem_classes[i]) self._semantic_flag_classes[name] = sem_classes[i] self._semantic_flag_classes_by_index[sem_classes[i]] = name @@ -2130,7 +2130,7 @@ class CoreArchitecture(Architecture): self._semantic_flag_groups = {} self._semantic_flag_groups_by_index = {} self.__dict__["semantic_flag_groups"] = [] - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureSemanticFlagGroupName(self.handle, sem_groups[i]) self._semantic_flag_groups[name] = sem_groups[i] self._semantic_flag_groups_by_index[sem_groups[i]] = name @@ -2149,7 +2149,7 @@ class CoreArchitecture(Architecture): count = ctypes.c_ulonglong() flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, 0, count) flag_names = [] - for i in xrange(0, count.value): + for i in range(0, count.value): flag_names.append(self._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) self.__dict__["flags_required_for_flag_condition"][cond] = flag_names @@ -2162,7 +2162,7 @@ class CoreArchitecture(Architecture): self._semantic_flag_groups[group], count) flag_indexes = [] flag_names = [] - for i in xrange(0, count.value): + for i in range(0, count.value): flag_indexes.append(flags[i]) flag_names.append(self._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) @@ -2177,7 +2177,7 @@ class CoreArchitecture(Architecture): self._semantic_flag_groups[group], count) class_index_cond = {} class_cond = {} - for i in xrange(0, count.value): + for i in range(0, count.value): class_index_cond[conditions[i].semanticClass] = conditions[i].condition if conditions[i].semanticClass == 0: class_cond[None] = conditions[i].condition @@ -2195,7 +2195,7 @@ class CoreArchitecture(Architecture): self._flag_write_types[write_type], count) flag_indexes = [] flag_names = [] - for i in xrange(0, count.value): + for i in range(0, count.value): flag_indexes.append(flags[i]) flag_names.append(self._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) @@ -2217,7 +2217,7 @@ class CoreArchitecture(Architecture): count = ctypes.c_ulonglong() regs = core.BNGetArchitectureGlobalRegisters(self.handle, count) self.__dict__["global_regs"] = [] - for i in xrange(0, count.value): + for i in range(0, count.value): self.global_regs.append(core.BNGetArchitectureRegisterName(self.handle, regs[i])) core.BNFreeRegisterList(regs) @@ -2226,14 +2226,14 @@ class CoreArchitecture(Architecture): self._all_reg_stacks = {} self._reg_stacks_by_index = {} self.__dict__["reg_stacks"] = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureRegisterStackName(self.handle, regs[i]) info = core.BNGetArchitectureRegisterStackInfo(self.handle, regs[i]) storage = [] - for j in xrange(0, info.storageCount): + for j in range(0, info.storageCount): storage.append(core.BNGetArchitectureRegisterName(self.handle, info.firstStorageReg + j)) top_rel = [] - for j in xrange(0, info.topRelativeCount): + for j in range(0, info.topRelativeCount): top_rel.append(core.BNGetArchitectureRegisterName(self.handle, info.firstTopRelativeReg + j)) top = core.BNGetArchitectureRegisterName(self.handle, info.stackTopReg) self.reg_stacks[name] = binaryninja.function.RegisterStackInfo(storage, top_rel, top, regs[i]) @@ -2246,12 +2246,12 @@ class CoreArchitecture(Architecture): self._intrinsics = {} self._intrinsics_by_index = {} self.__dict__["intrinsics"] = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = core.BNGetArchitectureIntrinsicName(self.handle, intrinsics[i]) input_count = ctypes.c_ulonglong() inputs = core.BNGetArchitectureIntrinsicInputs(self.handle, intrinsics[i], input_count) input_list = [] - for j in xrange(0, input_count.value): + for j in range(0, input_count.value): input_name = inputs[j].name type_obj = types.Type(core.BNNewTypeReference(inputs[j].type), confidence = inputs[j].typeConfidence) input_list.append(binaryninja.function.IntrinsicInput(type_obj, input_name)) @@ -2259,7 +2259,7 @@ class CoreArchitecture(Architecture): output_count = ctypes.c_ulonglong() outputs = core.BNGetArchitectureIntrinsicOutputs(self.handle, intrinsics[i], output_count) output_list = [] - for j in xrange(0, output_count.value): + for j in range(0, output_count.value): output_list.append(types.Type(core.BNNewTypeReference(outputs[j].type), confidence = outputs[j].confidence)) core.BNFreeOutputTypeList(outputs, output_count.value) self.intrinsics[name] = binaryninja.function.IntrinsicInfo(input_list, output_list) @@ -2303,7 +2303,7 @@ class CoreArchitecture(Architecture): result.length = info.length result.arch_transition_by_target_addr = info.archTransitionByTargetAddr result.branch_delay = info.branchDelay - for i in xrange(0, info.branchCount): + for i in range(0, info.branchCount): target = info.branchTarget[i] if info.branchArch[i]: arch = CoreArchitecture._from_cache(info.branchArch[i]) @@ -2332,7 +2332,7 @@ class CoreArchitecture(Architecture): if not core.BNGetInstructionText(self.handle, buf, addr, length, tokens, count): return None, 0 result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -2379,7 +2379,7 @@ class CoreArchitecture(Architecture): """ flag = self.get_flag_index(flag) operand_list = (core.BNRegisterOrConstant * len(operands))() - for i in xrange(len(operands)): + for i in range(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False operand_list[i].reg = self.regs[operands[i]].index @@ -2664,7 +2664,7 @@ class CoreArchitecture(Architecture): count = ctypes.c_ulonglong() flags = core.BNGetArchitectureFlagsRequiredForFlagCondition(self.handle, cond, sem_class, count) flag_names = [] - for i in xrange(0, count.value): + for i in range(0, count.value): flag_names.append(self._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) return flag_names diff --git a/python/basicblock.py b/python/basicblock.py index ee754863..b1f95ba3 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -26,6 +26,8 @@ from binaryninja import highlight from binaryninja import _binaryninjacore as core from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType +# 2-3 compatibility +from six.moves import range class BasicBlockEdge(object): def __init__(self, branch_type, source, target, back_edge): @@ -128,7 +130,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong(0) edges = core.BNGetBasicBlockOutgoingEdges(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) @@ -144,7 +146,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong(0) edges = core.BNGetBasicBlockIncomingEdges(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): branch_type = BranchType(edges[i].type) if edges[i].target: target = self._create_instance(self.view, core.BNNewBasicBlockReference(edges[i].target)) @@ -170,7 +172,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong() blocks = core.BNGetBasicBlockDominators(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -181,7 +183,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong() blocks = core.BNGetBasicBlockStrictDominators(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -200,7 +202,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong() blocks = core.BNGetBasicBlockDominatorTreeChildren(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -211,7 +213,7 @@ class BasicBlock(object): count = ctypes.c_ulonglong() blocks = core.BNGetBasicBlockDominanceFrontier(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self._create_instance(self.view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -275,12 +277,12 @@ class BasicBlock(object): if len(blocks) == 0: return [] block_set = (ctypes.POINTER(core.BNBasicBlock) * len(blocks))() - for i in xrange(len(blocks)): + for i in range(len(blocks)): block_set[i] = blocks[i].handle count = ctypes.c_ulonglong() out_blocks = core.BNGetBasicBlockIteratedDominanceFrontier(block_set, len(blocks), count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(BasicBlock(blocks[0].view, core.BNNewBasicBlockReference(out_blocks[i]))) core.BNFreeBasicBlockList(out_blocks, count.value) return result @@ -336,14 +338,14 @@ class BasicBlock(object): count = ctypes.c_ulonglong() lines = core.BNGetBasicBlockDisassemblyText(self.handle, settings_obj, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): addr = lines[i].addr if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(self, 'il_function'): il_instr = self.il_function[lines[i].instrIndex] else: il_instr = None tokens = [] - for j in xrange(0, lines[i].count): + for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text value = lines[i].tokens[j].value diff --git a/python/binaryview.py b/python/binaryview.py index b3314c5c..ac08ad76 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -39,6 +39,7 @@ from binaryninja import metadata # 2-3 compatibility from six import with_metaclass +from six.moves import range class BinaryDataNotification(object): @@ -325,7 +326,7 @@ class _BinaryViewTypeMetaclass(type): count = ctypes.c_ulonglong() types = core.BNGetBinaryViewTypes(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(BinaryViewType(types[i])) core.BNFreeBinaryViewTypeList(types) return result @@ -335,7 +336,7 @@ class _BinaryViewTypeMetaclass(type): count = ctypes.c_ulonglong() types = core.BNGetBinaryViewTypes(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield BinaryViewType(types[i]) finally: core.BNFreeBinaryViewTypeList(types) @@ -371,12 +372,12 @@ class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): @property def name(self): """BinaryView name (read-only)""" - return core.BNGetBinaryViewTypeName(self.handle) + return core.BNGetBinaryViewTypeName(self.handle).decode('utf8') @property def long_name(self): """BinaryView long name (read-only)""" - return core.BNGetBinaryViewTypeLongName(self.handle) + return core.BNGetBinaryViewTypeLongName(self.handle).decode('utf8') def __repr__(self): return "" % self.name @@ -780,7 +781,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionList(self.handle, count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i])) finally: core.BNFreeFunctionList(funcs, count.value) @@ -899,7 +900,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionList(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -923,7 +924,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) syms = core.BNGetSymbols(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): sym = types.Symbol(None, None, None, handle=core.BNNewSymbolReference(syms[i])) result[sym.raw_name] = sym core.BNFreeSymbolList(syms, count.value) @@ -940,7 +941,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) types = core.BNGetBinaryViewTypesForData(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(BinaryViewType(types[i])) core.BNFreeBinaryViewTypeList(types) return result @@ -990,7 +991,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) var_list = core.BNGetDataVariables(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): addr = var_list[i].address var_type = types.Type(core.BNNewTypeReference(var_list[i].type), platform = self.platform, confidence = var_list[i].typeConfidence) auto_discovered = var_list[i].autoDiscovered @@ -1004,7 +1005,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) type_list = core.BNGetAnalysisTypeList(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = types.QualifiedName._from_core_struct(type_list[i].name) result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self.platform) core.BNFreeTypeList(type_list, count.value) @@ -1016,7 +1017,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) segment_list = core.BNGetSegments(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(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].autoDefined)) core.BNFreeSegmentList(segment_list) @@ -1028,7 +1029,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) section_list = core.BNGetSections(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): result[section_list[i].name] = Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, section_list[i].infoData, section_list[i].align, section_list[i].entrySize, @@ -1042,7 +1043,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) range_list = core.BNGetAllocatedRanges(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(AddressRange(range_list[i].start, range_list[i].end)) core.BNFreeAddressRanges(range_list) return result @@ -2184,7 +2185,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionsForAddress(self.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -2206,7 +2207,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) blocks = core.BNGetBasicBlocksForAddress(self.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(basicblock.BasicBlock(self, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -2222,7 +2223,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) blocks = core.BNGetBasicBlocksStartingAtAddress(self.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(basicblock.BasicBlock(self, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -2253,7 +2254,7 @@ class BinaryView(object): else: refs = core.BNGetCodeReferencesInRange(self.handle, addr, length, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): if refs[i].func: func = binaryninja.function.Function(self, core.BNNewFunctionReference(refs[i].func)) else: @@ -2319,7 +2320,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) syms = core.BNGetSymbolsByName(self.handle, name, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(types.Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) core.BNFreeSymbolList(syms, count.value) return result @@ -2344,7 +2345,7 @@ class BinaryView(object): else: syms = core.BNGetSymbolsInRange(self.handle, start, length, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(types.Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) core.BNFreeSymbolList(syms, count.value) return result @@ -2373,7 +2374,7 @@ class BinaryView(object): else: syms = core.BNGetSymbolsOfTypeInRange(self.handle, sym_type, start, length, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(types.Symbol(None, None, None, handle = core.BNNewSymbolReference(syms[i]))) core.BNFreeSymbolList(syms, count.value) return result @@ -2772,7 +2773,7 @@ class BinaryView(object): length = self.end - start strings = core.BNGetStringsInRange(self.handle, start, length, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(StringReference(self, StringType(strings[i].type), strings[i].start, strings[i].length)) core.BNFreeStringReferenceList(strings) return result @@ -3004,7 +3005,7 @@ class BinaryView(object): lines = api(self.handle, pos_obj, settings, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): func = None block = None if lines[i].function: @@ -3013,7 +3014,7 @@ class BinaryView(object): block = basicblock.BasicBlock(self, core.BNNewBasicBlockReference(lines[i].block)) addr = lines[i].contents.addr tokens = [] - for j in xrange(0, lines[i].contents.count): + for j in range(0, lines[i].contents.count): token_type = InstructionTextTokenType(lines[i].contents.tokens[j].type) text = lines[i].contents.tokens[j].text value = lines[i].contents.tokens[j].value @@ -3456,7 +3457,7 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) section_list = core.BNGetSectionsAt(self.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Section(section_list[i].name, section_list[i].type, section_list[i].start, section_list[i].length, section_list[i].linkedSection, section_list[i].infoSection, section_list[i].infoData, section_list[i].align, section_list[i].entrySize, @@ -3476,11 +3477,11 @@ class BinaryView(object): def get_unique_section_names(self, name_list): incoming_names = (ctypes.c_char_p * len(name_list))() - for i in xrange(0, len(name_list)): + for i in range(0, len(name_list)): incoming_names[i] = name_list[i] outgoing_names = core.BNGetUniqueSectionNames(self.handle, incoming_names, len(name_list)) result = [] - for i in xrange(0, len(name_list)): + for i in range(0, len(name_list)): result.append(str(outgoing_names[i])) core.BNFreeStringList(outgoing_names, len(name_list)) return result diff --git a/python/callingconvention.py b/python/callingconvention.py index 268d914f..1b0d068e 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -27,6 +27,10 @@ from binaryninja import _binaryninjacore as core from binaryninja import log from binaryninja.enums import VariableSourceType +# 2-3 compatibility +from six.moves import range + + class CallingConvention(object): from binaryninja import types name = None @@ -82,7 +86,7 @@ class CallingConvention(object): regs = core.BNGetCallerSavedRegisters(self.handle, count) result = [] arch = self.arch - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs, count.value) self.__dict__["caller_saved_regs"] = result @@ -91,7 +95,7 @@ class CallingConvention(object): regs = core.BNGetIntegerArgumentRegisters(self.handle, count) result = [] arch = self.arch - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs, count.value) self.__dict__["int_arg_regs"] = result @@ -100,7 +104,7 @@ class CallingConvention(object): regs = core.BNGetFloatArgumentRegisters(self.handle, count) result = [] arch = self.arch - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs, count.value) self.__dict__["float_arg_regs"] = result @@ -133,7 +137,7 @@ class CallingConvention(object): regs = core.BNGetImplicitlyDefinedRegisters(self.handle, count) result = [] arch = self.arch - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs, count.value) self.__dict__["implicitly_defined_regs"] = result @@ -158,7 +162,7 @@ class CallingConvention(object): regs = self.__class__.caller_saved_regs count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = self.arch.regs[regs[i]].index result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -173,7 +177,7 @@ class CallingConvention(object): regs = self.__class__.int_arg_regs count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = self.arch.regs[regs[i]].index result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -188,7 +192,7 @@ class CallingConvention(object): regs = self.__class__.float_arg_regs count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = self.arch.regs[regs[i]].index result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) @@ -267,7 +271,7 @@ class CallingConvention(object): regs = self.__class__.implicitly_defined_regs count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() - for i in xrange(0, len(regs)): + for i in range(0, len(regs)): reg_buf[i] = self.arch.regs[regs[i]].index result = ctypes.cast(reg_buf, ctypes.c_void_p) self._pending_reg_lists[result.value] = (result, reg_buf) diff --git a/python/demangle.py b/python/demangle.py index 50322694..ceb1e48b 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -23,6 +23,9 @@ import ctypes # Binary Ninja components -- additional imports belong in the appropriate class from binaryninja import _binaryninjacore as core +# 2-3 compatibility +from six.moves import range + def get_qualified_name(names): """ @@ -61,7 +64,7 @@ def demangle_ms(arch, mangled_name): outSize = ctypes.c_ulonglong() names = [] if core.BNDemangleMS(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): - for i in xrange(outSize.value): + for i in range(outSize.value): names.append(outName[i]) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) return (types.Type(handle), names) @@ -75,7 +78,7 @@ def demangle_gnu3(arch, mangled_name): outSize = ctypes.c_ulonglong() names = [] if core.BNDemangleGNU3(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): - for i in xrange(outSize.value): + for i in range(outSize.value): names.append(outName[i]) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) if not handle: diff --git a/python/function.py b/python/function.py index a0269e75..6392d7f2 100644 --- a/python/function.py +++ b/python/function.py @@ -35,6 +35,10 @@ from binaryninja import types from binaryninja import highlight from binaryninja import log +# 2-3 compatibility +from six.moves import range + + class LookupTableEntry(object): def __init__(self, from_values, to_value): self.from_values = from_values @@ -173,7 +177,7 @@ class PossibleValueSet(object): elif value.state == RegisterValueType.SignedRangeValue: self.offset = value.value self.ranges = [] - for i in xrange(0, value.count): + for i in range(0, value.count): start = value.ranges[i].start end = value.ranges[i].end step = value.ranges[i].step @@ -185,7 +189,7 @@ class PossibleValueSet(object): elif value.state == RegisterValueType.UnsignedRangeValue: self.offset = value.value self.ranges = [] - for i in xrange(0, value.count): + for i in range(0, value.count): start = value.ranges[i].start end = value.ranges[i].end step = value.ranges[i].step @@ -193,15 +197,15 @@ class PossibleValueSet(object): elif value.state == RegisterValueType.LookupTableValue: self.table = [] self.mapping = {} - for i in xrange(0, value.count): + for i in range(0, value.count): from_list = [] - for j in xrange(0, value.table[i].fromCount): + for j in range(0, value.table[i].fromCount): from_list.append(value.table[i].fromValues[j]) self.mapping[value.table[i].fromValues[j]] = value.table[i].toValue self.table.append(LookupTableEntry(from_list, value.table[i].toValue)) elif (value.state == RegisterValueType.InSetOfValues) or (value.state == RegisterValueType.NotInSetOfValues): self.values = set() - for i in xrange(0, value.count): + for i in range(0, value.count): self.values.add(value.valueSet[i]) def __repr__(self): @@ -479,7 +483,7 @@ class Function(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(binaryninja.basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i]))) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -490,7 +494,7 @@ class Function(object): count = ctypes.c_ulonglong() addrs = core.BNGetCommentedAddresses(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): result[addrs[i]] = self.get_comment_at(addrs[i]) core.BNFreeAddressList(addrs) return result @@ -525,7 +529,7 @@ class Function(object): count = ctypes.c_ulonglong() v = core.BNGetStackLayout(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) @@ -538,7 +542,7 @@ class Function(object): count = ctypes.c_ulonglong() v = core.BNGetFunctionVariables(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Variable(self, v[i].var.type, v[i].var.index, v[i].var.storage, v[i].name, types.Type(handle = core.BNNewTypeReference(v[i].type), platform = self.platform, confidence = v[i].typeConfidence))) result.sort(key = lambda x: x.identifier) @@ -551,7 +555,7 @@ class Function(object): count = ctypes.c_ulonglong() branches = core.BNGetIndirectBranches(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(IndirectBranchInfo(binaryninja.architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, binaryninja.architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -572,7 +576,7 @@ class Function(object): count = ctypes.c_ulonglong() info = core.BNGetFunctionAnalysisPerformanceInfo(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): result[info[i].name] = info[i].seconds core.BNFreeAnalysisPerformanceInfo(info, count.value) return result @@ -606,7 +610,7 @@ class Function(object): """Registers that are used for the return value""" result = core.BNGetFunctionReturnRegisters(self.handle) reg_set = [] - for i in xrange(0, result.count): + for i in range(0, result.count): reg_set.append(self.arch.get_reg_name(result.regs[i])) regs = types.RegisterSet(reg_set, confidence = result.confidence) core.BNFreeRegisterSet(result) @@ -617,7 +621,7 @@ class Function(object): regs = core.BNRegisterSetWithConfidence() regs.regs = (ctypes.c_uint * len(value))() regs.count = len(value) - for i in xrange(0, len(value)): + for i in range(0, len(value)): regs.regs[i] = self.arch.get_reg_index(value[i]) if hasattr(value, 'confidence'): regs.confidence = value.confidence @@ -649,7 +653,7 @@ class Function(object): """List of variables for the incoming function parameters""" result = core.BNGetFunctionParameterVariables(self.handle) var_list = [] - for i in xrange(0, result.count): + for i in range(0, result.count): var_list.append(Variable(self, result.vars[i].type, result.vars[i].index, result.vars[i].storage)) confidence = result.confidence core.BNFreeParameterVariables(result) @@ -664,7 +668,7 @@ class Function(object): var_conf = core.BNParameterVariablesWithConfidence() var_conf.vars = (core.BNVariable * len(var_list))() var_conf.count = len(var_list) - for i in xrange(0, len(var_list)): + for i in range(0, len(var_list)): var_conf.vars[i].type = var_list[i].source_type var_conf.vars[i].index = var_list[i].index var_conf.vars[i].storage = var_list[i].storage @@ -714,7 +718,7 @@ class Function(object): count = ctypes.c_ulonglong() adjust = core.BNGetFunctionRegisterStackAdjustments(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = self.arch.get_reg_stack_name(adjust[i].regStack) value = types.RegisterStackAdjustmentWithConfidence(adjust[i].adjustment, confidence = adjust[i].confidence) @@ -742,7 +746,7 @@ class Function(object): """Registers that are modified by this function""" result = core.BNGetFunctionClobberedRegisters(self.handle) reg_set = [] - for i in xrange(0, result.count): + for i in range(0, result.count): reg_set.append(self.arch.get_reg_name(result.regs[i])) regs = types.RegisterSet(reg_set, confidence = result.confidence) core.BNFreeRegisterSet(result) @@ -753,7 +757,7 @@ class Function(object): regs = core.BNRegisterSetWithConfidence() regs.regs = (ctypes.c_uint * len(value))() regs.count = len(value) - for i in xrange(0, len(value)): + for i in range(0, len(value)): regs.regs[i] = self.arch.get_reg_index(value[i]) if hasattr(value, 'confidence'): regs.confidence = value.confidence @@ -847,7 +851,7 @@ class Function(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield binaryninja.basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) finally: core.BNFreeBasicBlockList(blocks, count.value) @@ -918,7 +922,7 @@ class Function(object): count = ctypes.c_ulonglong() exits = core.BNGetLowLevelILExitsForInstruction(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(exits[i]) core.BNFreeILInstructionList(exits) return result @@ -1017,7 +1021,7 @@ class Function(object): count = ctypes.c_ulonglong() regs = core.BNGetRegistersReadByInstruction(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs) return result @@ -1028,7 +1032,7 @@ class Function(object): count = ctypes.c_ulonglong() regs = core.BNGetRegistersWrittenByInstruction(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(arch.get_reg_name(regs[i])) core.BNFreeRegisterList(regs) return result @@ -1039,7 +1043,7 @@ class Function(object): count = ctypes.c_ulonglong() refs = core.BNGetStackVariablesReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): var_type = types.Type(core.BNNewTypeReference(refs[i].type), platform = self.platform, confidence = refs[i].typeConfidence) result.append(StackVariableReference(refs[i].sourceOperand, var_type, refs[i].name, Variable.from_identifier(self, refs[i].varIdentifier, refs[i].name, var_type), @@ -1053,7 +1057,7 @@ class Function(object): count = ctypes.c_ulonglong() refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(ConstantReference(refs[i].value, refs[i].size, refs[i].pointer, refs[i].intermediate)) core.BNFreeConstantReferenceList(refs) return result @@ -1074,7 +1078,7 @@ class Function(object): count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -1084,7 +1088,7 @@ class Function(object): count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagDefinitionsForUse(self.handle, i, flag, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -1093,7 +1097,7 @@ class Function(object): count = ctypes.c_ulonglong() flags = core.BNGetFlagsReadByLiftedILInstruction(self.handle, i, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self.arch._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) return result @@ -1102,7 +1106,7 @@ class Function(object): count = ctypes.c_ulonglong() flags = core.BNGetFlagsWrittenByLiftedILInstruction(self.handle, i, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(self.arch._flags_by_index[flags[i]]) core.BNFreeRegisterList(flags) return result @@ -1120,7 +1124,7 @@ class Function(object): if source_arch is None: source_arch = self.arch branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): + for i in range(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)) @@ -1129,7 +1133,7 @@ class Function(object): if source_arch is None: source_arch = self.arch branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): + for i in range(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)) @@ -1140,7 +1144,7 @@ class Function(object): count = ctypes.c_ulonglong() branches = core.BNGetIndirectBranchesAt(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(IndirectBranchInfo(binaryninja.architecture.CoreArchitecture._from_cache(branches[i].sourceArch), branches[i].sourceAddr, binaryninja.architecture.CoreArchitecture._from_cache(branches[i].destArch), branches[i].destAddr, branches[i].autoDefined)) core.BNFreeIndirectBranchList(branches) return result @@ -1151,9 +1155,9 @@ class Function(object): count = ctypes.c_ulonglong(0) lines = core.BNGetFunctionBlockAnnotations(self.handle, arch.handle, addr, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): tokens = [] - for j in xrange(0, lines[i].count): + for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text value = lines[i].tokens[j].value @@ -1187,7 +1191,7 @@ class Function(object): regs = core.BNRegisterSetWithConfidence() regs.regs = (ctypes.c_uint * len(value))() regs.count = len(value) - for i in xrange(0, len(value)): + for i in range(0, len(value)): regs.regs[i] = self.arch.get_reg_index(value[i]) if hasattr(value, 'confidence'): regs.confidence = value.confidence @@ -1213,7 +1217,7 @@ class Function(object): var_conf = core.BNParameterVariablesWithConfidence() var_conf.vars = (core.BNVariable * len(var_list))() var_conf.count = len(var_list) - for i in xrange(0, len(var_list)): + for i in range(0, len(var_list)): var_conf.vars[i].type = var_list[i].source_type var_conf.vars[i].index = var_list[i].index var_conf.vars[i].storage = var_list[i].storage @@ -1270,7 +1274,7 @@ class Function(object): regs = core.BNRegisterSetWithConfidence() regs.regs = (ctypes.c_uint * len(value))() regs.count = len(value) - for i in xrange(0, len(value)): + for i in range(0, len(value)): regs.regs[i] = self.arch.get_reg_index(value[i]) if hasattr(value, 'confidence'): regs.confidence = value.confidence @@ -1458,10 +1462,10 @@ class Function(object): count = ctypes.c_ulonglong() lines = core.BNGetFunctionTypeTokens(self.handle, settings, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): addr = lines[i].addr tokens = [] - for j in xrange(0, lines[i].count): + for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text value = lines[i].tokens[j].value @@ -1553,7 +1557,7 @@ class Function(object): count = ctypes.c_ulonglong() adjust = core.BNGetCallRegisterStackAdjustment(self.handle, arch.handle, addr, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): result[arch.get_reg_stack_name(adjust[i].regStack)] = types.RegisterStackAdjustmentWithConfidence( adjust[i].adjustment, confidence = adjust[i].confidence) core.BNFreeRegisterStackAdjustments(adjust) @@ -1709,14 +1713,14 @@ class FunctionGraphBlock(object): lines = core.BNGetFunctionGraphBlockLines(self.handle, count) block = self.basic_block result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): addr = lines[i].addr if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): il_instr = block.il_function[lines[i].instrIndex] else: il_instr = None tokens = [] - for j in xrange(0, lines[i].count): + for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text value = lines[i].tokens[j].value @@ -1736,7 +1740,7 @@ class FunctionGraphBlock(object): count = ctypes.c_ulonglong() edges = core.BNGetFunctionGraphBlockOutgoingEdges(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): branch_type = BranchType(edges[i].type) target = edges[i].target if target: @@ -1749,7 +1753,7 @@ class FunctionGraphBlock(object): core.BNNewBasicBlockReference(target)) core.BNFreeFunction(func) points = [] - for j in xrange(0, edges[i].pointCount): + for j in range(0, edges[i].pointCount): points.append((edges[i].points[j].x, edges[i].points[j].y)) result.append(FunctionGraphEdge(branch_type, self, target, points, edges[i].backEdge)) core.BNFreeFunctionGraphBlockOutgoingEdgeList(edges, count.value) @@ -1773,14 +1777,14 @@ class FunctionGraphBlock(object): lines = core.BNGetFunctionGraphBlockLines(self.handle, count) block = self.basic_block try: - for i in xrange(0, count.value): + for i in range(0, count.value): addr = lines[i].addr if (lines[i].instrIndex != 0xffffffffffffffff) and hasattr(block, 'il_function'): il_instr = block.il_function[lines[i].instrIndex] else: il_instr = None tokens = [] - for j in xrange(0, lines[i].count): + for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text value = lines[i].tokens[j].value @@ -1877,7 +1881,7 @@ class FunctionGraph(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionGraphBlocks(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result @@ -1956,7 +1960,7 @@ class FunctionGraph(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionGraphBlocks(self.handle, count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self) finally: core.BNFreeFunctionGraphBlockList(blocks, count.value) @@ -1999,7 +2003,7 @@ class FunctionGraph(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionGraphBlocksInRegion(self.handle, left, top, right, bottom, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(FunctionGraphBlock(core.BNNewFunctionGraphBlockReference(blocks[i]), self)) core.BNFreeFunctionGraphBlockList(blocks, count.value) return result diff --git a/python/generator.cpp b/python/generator.cpp index bb32ab69..8fc415b0 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -117,12 +117,14 @@ void OutputType(FILE* out, Type* type, bool isReturnType = false, bool isCallbac break; } else if ((type->GetChildType()->GetClass() == IntegerTypeClass) && - (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned())) + (type->GetChildType()->GetWidth() == 1) && (type->GetChildType()->IsSigned())) { if (isReturnType) fprintf(out, "ctypes.POINTER(ctypes.c_byte)"); - else + else { + //fprintf(out, "compatstring"); fprintf(out, "ctypes.c_char_p"); + } break; } else if (type->GetChildType()->GetClass() == FunctionTypeClass) @@ -188,6 +190,7 @@ int main(int argc, char* argv[]) fprintf(out, "import platform\n"); fprintf(out, "core = None\n"); fprintf(out, "_base_path = None\n"); + fprintf(out, "ctypes.set_conversion_mode('utf-8', 'strict')\n"); fprintf(out, "if platform.system() == \"Darwin\":\n"); fprintf(out, "\t_base_path = os.path.join(os.path.dirname(__file__), \"..\", \"..\", \"..\", \"MacOS\")\n"); fprintf(out, "\tcore = ctypes.CDLL(os.path.join(_base_path, \"libbinaryninjacore.dylib\"))\n\n"); @@ -199,6 +202,40 @@ int main(int argc, char* argv[]) fprintf(out, "\tcore = ctypes.CDLL(os.path.join(_base_path, \"binaryninjacore.dll\"))\n"); fprintf(out, "else:\n"); fprintf(out, "\traise Exception(\"OS not supported\")\n\n"); + // fprintf(out, "class compatstring(ctypes.c_char_p):\n"); + // fprintf(out, "\tdef __init__(self, value=None):\n"); + // fprintf(out, "\t\tsuper(compatstring, self).__init__()\n"); + // fprintf(out, "\t\tif value is not None:\n"); + // fprintf(out, "\t\t\tself.value = value\n"); + // fprintf(out, "\t@classmethod\n"); + // fprintf(out, "\tdef from_param(cls, value):\n"); + // fprintf(out, "\t\tif not isinstance(value, bytes):\n"); + // fprintf(out, "\t\t\treturn super(compatstring, cls).from_param(value.encode('utf8'))\n"); + // fprintf(out, "\t\treturn super(compatstring, cls).from_param(value)\n\n"); + // fprintf(out, "\t@property\n"); + // fprintf(out, "\tdef value(self, value):\n"); + // fprintf(out, "\t\tif not isinstance(value, bytes):\n"); + // fprintf(out, "\t\t\treturn super(compatstring, cls).from_param(value.encode('utf8'))\n"); + // fprintf(out, "\t\treturn super(compatstring, cls).from_param(value)\n\n"); + fprintf(out, "class compatstring(ctypes.c_char_p):\n"); + fprintf(out, " @classmethod\n"); + fprintf(out, " def from_param(cls, obj):\n"); + fprintf(out, " if (obj is not None) and (not isinstance(obj, cls)):\n"); + fprintf(out, " if not isinstance(obj, basestring):\n"); + fprintf(out, " raise TypeError('parameter must be a string type instance')\n"); + fprintf(out, " if not isinstance(obj, unicode):\n"); + fprintf(out, " obj = unicode(obj)\n"); + fprintf(out, " obj = obj.encode('utf-8')\n"); + fprintf(out, " return ctypes.c_char_p.from_param(obj)\n"); + fprintf(out, "\n"); + fprintf(out, " def decode(self):\n"); + fprintf(out, " if self.value is None:\n"); + fprintf(out, " return None\n"); + fprintf(out, " return self.value.decode('utf-8')\n"); + fprintf(out, " @property\n"); + fprintf(out, " def value(self, c_void_p=ctypes.c_void_p):\n"); + fprintf(out, " addr = c_void_p.from_buffer(self).value\n"); + fprintf(out, " return \n"); // Create type objects fprintf(out, "# Type definitions\n"); @@ -227,7 +264,7 @@ int main(int argc, char* argv[]) } } else if ((i.second->GetClass() == BoolTypeClass) || (i.second->GetClass() == IntegerTypeClass) || - (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass)) + (i.second->GetClass() == FloatTypeClass) || (i.second->GetClass() == ArrayTypeClass)) { fprintf(out, "%s = ", name.c_str()); OutputType(out, i.second); @@ -377,7 +414,7 @@ int main(int argc, char* argv[]) fprintf(out, "\traise ValueError('expected pointer to %%s' %% str(handle_type))\n"); fprintf(out, "\n# Set path for core plugins\n"); - fprintf(out, "BNSetBundledPluginDirectory(os.path.join(_base_path, \"plugins\").encode('utf-8'))\n"); + fprintf(out, "BNSetBundledPluginDirectory(os.path.join(_base_path, \"plugins\"))\n"); fclose(out); fclose(enums); diff --git a/python/interaction.py b/python/interaction.py index da6f792a..5b78b278 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -25,6 +25,9 @@ import traceback from binaryninja import _binaryninjacore as core from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult +# 2-3 compatibility +from six.moves import range + class LabelField(object): """ @@ -160,7 +163,7 @@ class ChoiceField(object): value.type = FormInputFieldType.ChoiceFormField value.prompt = self.prompt choice_buf = (ctypes.c_char_p * len(self.choices))() - for i in xrange(0, len(self.choices)): + for i in range(0, len(self.choices)): choice_buf[i] = str(self.choices[i]) value.choices = choice_buf value.count = len(self.choices) @@ -330,7 +333,7 @@ class InteractionHandler(object): def _get_choice_input(self, ctxt, result, prompt, title, choice_buf, count): try: choices = [] - for i in xrange(0, count): + for i in range(0, count): choices.append(choice_buf[i]) value = self.get_choice_input(prompt, title, choices) if value is None: @@ -373,7 +376,7 @@ class InteractionHandler(object): def _get_form_input(self, ctxt, fields, count, title): try: field_objs = [] - for i in xrange(0, count): + for i in range(0, count): if fields[i].type == FormInputFieldType.LabelFormField: field_objs.append(LabelField(fields[i].prompt)) elif fields[i].type == FormInputFieldType.SeparatorFormField: @@ -391,7 +394,7 @@ class InteractionHandler(object): field_objs.append(AddressField(fields[i].prompt, view, fields[i].currentAddress)) elif fields[i].type == FormInputFieldType.ChoiceFormField: choices = [] - for j in xrange(0, fields[i].count): + for j in range(0, fields[i].count): choices.append(fields[i].choices[j]) field_objs.append(ChoiceField(fields[i].prompt, choices)) elif fields[i].type == FormInputFieldType.OpenFileNameFormField: @@ -404,7 +407,7 @@ class InteractionHandler(object): field_objs.append(LabelField(fields[i].prompt)) if not self.get_form_input(field_objs, title): return False - for i in xrange(0, count): + for i in range(0, count): field_objs[i]._fill_core_result(fields[i]) return True except: @@ -613,7 +616,7 @@ def get_choice_input(prompt, title, choices): 0L """ choice_buf = (ctypes.c_char_p * len(choices))() - for i in xrange(0, len(choices)): + for i in range(0, len(choices)): choice_buf[i] = str(choices[i]) value = ctypes.c_ulonglong() if not core.BNGetChoiceInput(value, prompt, title, choice_buf, len(choices)): @@ -728,7 +731,7 @@ def get_form_input(fields, title): Peter 1337 0 """ value = (core.BNFormInputField * len(fields))() - for i in xrange(0, len(fields)): + for i in range(0, len(fields)): if isinstance(fields[i], str): LabelField(fields[i])._fill_core_struct(value[i]) elif fields[i] is None: @@ -737,7 +740,7 @@ def get_form_input(fields, title): fields[i]._fill_core_struct(value[i]) if not core.BNGetFormInput(value, len(fields), title): return False - for i in xrange(0, len(fields)): + for i in range(0, len(fields)): if not (isinstance(fields[i], str) or (fields[i] is None)): fields[i]._get_result(value[i]) core.BNFreeFormInputResults(value, len(fields)) diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 9c1db4cc..333bb5a1 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -27,6 +27,9 @@ from binaryninja import _binaryninjacore as core from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType from binaryninja import basicblock #required for LowLevelILBasicBlock +# 2-3 compatibility +from six.moves import range + class LowLevelILLabel(object): def __init__(self, handle = None): @@ -413,7 +416,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value): + for j in range(count.value): value.append(operand_list[j]) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": @@ -421,7 +424,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value): + for j in range(count.value): value.append(LowLevelILInstruction(func, operand_list[j])) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "reg_or_flag_list": @@ -429,7 +432,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value): + for j in range(count.value): if (operand_list[j] & (1 << 32)) != 0: value.append(ILFlag(func.arch, operand_list[j] & 0xffffffff)) else: @@ -440,7 +443,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value // 2): + for j in range(count.value // 2): reg = operand_list[j * 2] reg_version = operand_list[(j * 2) + 1] value.append(SSARegister(ILRegister(func.arch, reg), reg_version)) @@ -450,7 +453,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value // 2): + for j in range(count.value // 2): reg_stack = operand_list[j * 2] reg_version = operand_list[(j * 2) + 1] value.append(SSARegisterStack(ILRegisterStack(func.arch, reg_stack), reg_version)) @@ -460,7 +463,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value // 2): + for j in range(count.value // 2): flag = operand_list[j * 2] flag_version = operand_list[(j * 2) + 1] value.append(SSAFlag(ILFlag(func.arch, flag), flag_version)) @@ -470,7 +473,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value // 2): + for j in range(count.value // 2): if (operand_list[j * 2] & (1 << 32)) != 0: reg_or_flag = ILFlag(func.arch, operand_list[j * 2] & 0xffffffff) else: @@ -483,7 +486,7 @@ class LowLevelILInstruction(object): operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = {} - for j in xrange(count.value // 2): + for j in range(count.value // 2): reg_stack = operand_list[j * 2] adjust = operand_list[(j * 2) + 1] if adjust & 0x80000000: @@ -520,7 +523,7 @@ class LowLevelILInstruction(object): self.expr_index, tokens, count): return None result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -777,7 +780,7 @@ class LowLevelILFunction(object): view = None if self.source_function is not None: view = self.source_function.view - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -844,7 +847,7 @@ class LowLevelILFunction(object): if self.source_function is not None: view = self.source_function.view try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield LowLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) finally: core.BNFreeBasicBlockList(blocks, count.value) @@ -862,7 +865,7 @@ class LowLevelILFunction(object): def set_indirect_branches(self, branches): branch_list = (core.BNArchitectureAndAddress * len(branches))() - for i in xrange(len(branches)): + for i in range(len(branches)): branch_list[i].arch = branches[i][0].handle branch_list[i].address = branches[i][1] core.BNLowLevelILSetIndirectBranches(self.handle, branch_list, len(branches)) @@ -2178,7 +2181,7 @@ class LowLevelILFunction(object): :rtype: LowLevelILExpr """ label_list = (ctypes.POINTER(core.BNLowLevelILLabel) * len(labels))() - for i in xrange(len(labels)): + for i in range(len(labels)): label_list[i] = labels[i].handle return LowLevelILExpr(core.BNLowLevelILAddLabelList(self.handle, label_list, len(labels))) @@ -2191,7 +2194,7 @@ class LowLevelILFunction(object): :rtype: LowLevelILExpr """ operand_list = (ctypes.c_ulonglong * len(operands))() - for i in xrange(len(operands)): + for i in range(len(operands)): operand_list[i] = operands[i] return LowLevelILExpr(core.BNLowLevelILAddOperandList(self.handle, operand_list, len(operands))) @@ -2274,7 +2277,7 @@ class LowLevelILFunction(object): count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, reg_ssa.version, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -2284,7 +2287,7 @@ class LowLevelILFunction(object): count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, flag_ssa.version, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -2293,7 +2296,7 @@ class LowLevelILFunction(object): count = ctypes.c_ulonglong() instrs = core.BNGetLowLevelILSSAMemoryUses(self.handle, index, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -2353,7 +2356,7 @@ class LowLevelILBasicBlock(basicblock.BasicBlock): self.il_function = owner def __iter__(self): - for idx in xrange(self.start, self.end): + for idx in range(self.start, self.end): yield self.il_function[idx] def __getitem__(self, idx): diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index a62c5c04..707915d7 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -26,6 +26,9 @@ from binaryninja import _binaryninjacore as core from binaryninja.enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence from binaryninja import basicblock #required for MediumLevelILBasicBlock argument +# 2-3 compatibility +from six.moves import range + class SSAVariable(object): def __init__(self, var, version): @@ -256,7 +259,7 @@ class MediumLevelILInstruction(object): count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) value = [] - for j in xrange(count.value): + for j in range(count.value): value.append(operand_list[j]) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_list": @@ -264,7 +267,7 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value): + for j in range(count.value): value.append(function.Variable.from_identifier(self.function.source_function, operand_list[j])) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "var_ssa_list": @@ -272,7 +275,7 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value // 2): + for j in range(count.value // 2): var_id = operand_list[j * 2] var_version = operand_list[(j * 2) + 1] value.append(SSAVariable(function.Variable.from_identifier(self.function.source_function, @@ -283,7 +286,7 @@ class MediumLevelILInstruction(object): operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) i += 1 value = [] - for j in xrange(count.value): + for j in range(count.value): value.append(MediumLevelILInstruction(func, operand_list[j])) core.BNMediumLevelILFreeOperandList(operand_list) self.operands.append(value) @@ -317,7 +320,7 @@ class MediumLevelILInstruction(object): self.expr_index, tokens, count): return None result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -363,7 +366,7 @@ class MediumLevelILInstruction(object): count = ctypes.c_ulonglong() deps = core.BNGetAllMediumLevelILBranchDependence(self.function.handle, self.instr_index, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): result[deps[i].branch] = ILBranchDependence(deps[i].dependence) core.BNFreeILBranchDependenceList(deps) return result @@ -647,7 +650,7 @@ class MediumLevelILFunction(object): view = None if self.source_function is not None: view = self.source_function.view - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self)) core.BNFreeBasicBlockList(blocks, count.value) return result @@ -704,7 +707,7 @@ class MediumLevelILFunction(object): if self.source_function is not None: view = self.source_function.view try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield MediumLevelILBasicBlock(view, core.BNNewBasicBlockReference(blocks[i]), self) finally: core.BNFreeBasicBlockList(blocks, count.value) @@ -775,7 +778,7 @@ class MediumLevelILFunction(object): :rtype: MediumLevelILExpr """ label_list = (ctypes.POINTER(core.BNMediumLevelILLabel) * len(labels))() - for i in xrange(len(labels)): + for i in range(len(labels)): label_list[i] = labels[i].handle return MediumLevelILExpr(core.BNMediumLevelILAddLabelList(self.handle, label_list, len(labels))) @@ -788,7 +791,7 @@ class MediumLevelILFunction(object): :rtype: MediumLevelILExpr """ operand_list = (ctypes.c_ulonglong * len(operands))() - for i in xrange(len(operands)): + for i in range(len(operands)): operand_list[i] = operands[i] return MediumLevelILExpr(core.BNMediumLevelILAddOperandList(self.handle, operand_list, len(operands))) @@ -842,7 +845,7 @@ class MediumLevelILFunction(object): var_data.storage = ssa_var.var.storage instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, ssa_var.version, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -851,7 +854,7 @@ class MediumLevelILFunction(object): count = ctypes.c_ulonglong() instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, version, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -878,7 +881,7 @@ class MediumLevelILFunction(object): var_data.storage = var.storage instrs = core.BNGetMediumLevelILVariableDefinitions(self.handle, var_data, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -891,7 +894,7 @@ class MediumLevelILFunction(object): var_data.storage = var.storage instrs = core.BNGetMediumLevelILVariableUses(self.handle, var_data, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result @@ -936,7 +939,7 @@ class MediumLevelILBasicBlock(basicblock.BasicBlock): self.il_function = owner def __iter__(self): - for idx in xrange(self.start, self.end): + for idx in range(self.start, self.end): yield self.il_function[idx] def __getitem__(self, idx): diff --git a/python/metadata.py b/python/metadata.py index 21e74533..64080060 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -26,6 +26,9 @@ import ctypes from binaryninja import _binaryninjacore as core from binaryninja.enums import MetadataType +# 2-3 compatibility +from six.moves import range + class Metadata(object): def __init__(self, value=None, signed=None, raw=None, handle=None): @@ -138,12 +141,12 @@ class Metadata(object): def __iter__(self): if self.is_array: - for i in xrange(core.BNMetadataSize(self.handle)): + for i in range(core.BNMetadataSize(self.handle)): yield Metadata(handle=core.BNMetadataGetForIndex(self.handle, i)).value elif self.is_dict: result = core.BNMetadataGetValueStore(self.handle) try: - for i in xrange(result.contents.size): + for i in range(result.contents.size): yield result.contents.keys[i] finally: core.BNFreeMetadataValueStore(result) @@ -175,7 +178,7 @@ class Metadata(object): length.value = 0 native_list = core.BNMetadataGetRaw(self.handle, ctypes.byref(length)) out_list = [] - for i in xrange(length.value): + for i in range(length.value): out_list.append(native_list[i]) core.BNFreeMetadataRaw(native_list) return ''.join(chr(a) for a in out_list) diff --git a/python/platform.py b/python/platform.py index 083ebf06..c57315ce 100644 --- a/python/platform.py +++ b/python/platform.py @@ -26,6 +26,7 @@ from binaryninja import _binaryninjacore as core #2-3 compatibility from six import with_metaclass +from six.moves import range class _PlatformMetaClass(type): @@ -37,7 +38,7 @@ class _PlatformMetaClass(type): count = ctypes.c_ulonglong() platforms = core.BNGetPlatformList(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Platform(None, core.BNNewPlatformReference(platforms[i]))) core.BNFreePlatformList(platforms, count.value) return result @@ -48,7 +49,7 @@ class _PlatformMetaClass(type): count = ctypes.c_ulonglong() platforms = core.BNGetPlatformOSList(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(str(platforms[i])) core.BNFreePlatformOSList(platforms, count.value) return result @@ -58,7 +59,7 @@ class _PlatformMetaClass(type): count = ctypes.c_ulonglong() platforms = core.BNGetPlatformList(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield Platform(None, core.BNNewPlatformReference(platforms[i])) finally: core.BNFreePlatformList(platforms, count.value) @@ -86,7 +87,7 @@ class _PlatformMetaClass(type): else: platforms = core.BNGetPlatformListByArchitecture(os, arch.handle) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Platform(None, core.BNNewPlatformReference(platforms[i]))) core.BNFreePlatformList(platforms, count.value) return result @@ -227,7 +228,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): count = ctypes.c_ulonglong() cc = core.BNGetPlatformCallingConventions(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(binaryninja.callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) core.BNFreeCallingConventionList(cc, count.value) return result @@ -238,7 +239,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): count = ctypes.c_ulonglong(0) type_list = core.BNGetPlatformTypes(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) @@ -250,7 +251,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): count = ctypes.c_ulonglong(0) type_list = core.BNGetPlatformVariables(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) @@ -262,7 +263,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): count = ctypes.c_ulonglong(0) type_list = core.BNGetPlatformFunctions(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) @@ -274,7 +275,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): count = ctypes.c_ulonglong(0) call_list = core.BNGetPlatformSystemCalls(self.handle, count) result = {} - for i in xrange(0, count.value): + for i in range(0, count.value): name = binaryninja.types.QualifiedName._from_core_struct(call_list[i].name) t = binaryninja.types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) @@ -389,7 +390,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): if filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): + for i in range(0, len(include_dirs)): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() @@ -402,13 +403,13 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_dict = {} variables = {} functions = {} - for i in xrange(0, parse.typeCount): + for i in range(0, parse.typeCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) - for i in xrange(0, parse.variableCount): + for i in range(0, parse.variableCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) - for i in xrange(0, parse.functionCount): + for i in range(0, parse.functionCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) @@ -435,7 +436,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): >>> """ dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): + for i in range(0, len(include_dirs)): dir_buf[i] = str(include_dirs[i]) parse = core.BNTypeParserResult() errors = ctypes.c_char_p() @@ -448,13 +449,13 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_dict = {} variables = {} functions = {} - for i in xrange(0, parse.typeCount): + for i in range(0, parse.typeCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) - for i in xrange(0, parse.variableCount): + for i in range(0, parse.variableCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) - for i in xrange(0, parse.functionCount): + for i in range(0, parse.functionCount): name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) diff --git a/python/plugin.py b/python/plugin.py index 4cf6fb77..52feced4 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -30,6 +30,7 @@ from binaryninja.enums import PluginCommandType #2-3 compatibility from six import with_metaclass +from six.moves import range class PluginCommandContext(object): @@ -49,7 +50,7 @@ class _PluginCommandMetaClass(type): count = ctypes.c_ulonglong() commands = core.BNGetAllPluginCommands(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(PluginCommand(commands[i])) core.BNFreePluginCommandList(commands) return result @@ -59,7 +60,7 @@ class _PluginCommandMetaClass(type): count = ctypes.c_ulonglong() commands = core.BNGetAllPluginCommands(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield PluginCommand(commands[i]) finally: core.BNFreePluginCommandList(commands) @@ -568,7 +569,7 @@ class _BackgroundTaskMetaclass(type): count = ctypes.c_ulonglong() tasks = core.BNGetRunningBackgroundTasks(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(BackgroundTask(handle=core.BNNewBackgroundTaskReference(tasks[i]))) core.BNFreeBackgroundTaskList(tasks, count.value) return result @@ -578,7 +579,7 @@ class _BackgroundTaskMetaclass(type): count = ctypes.c_ulonglong() tasks = core.BNGetRunningBackgroundTasks(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield BackgroundTask(handle=core.BNNewBackgroundTaskReference(tasks[i])) finally: core.BNFreeBackgroundTaskList(tasks, count.value) diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 002db573..ad314629 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -23,6 +23,8 @@ import ctypes # Binary Ninja components -- additional imports belong in the appropriate class from binaryninja import _binaryninjacore as core +# 2-3 compatibility +from six.moves import range class RepoPlugin(object): """ @@ -110,7 +112,7 @@ class RepoPlugin(object): result = [] count = ctypes.c_ulonglong(0) plugintypes = core.BNPluginGetPluginTypes(self.handle, count) - for i in xrange(count.value): + for i in range(count.value): result.append(PluginType(plugintypes[i])) core.BNFreePluginTypes(plugintypes) return result @@ -182,7 +184,7 @@ class Repository(object): pluginlist = [] count = ctypes.c_ulonglong(0) result = core.BNRepositoryGetPlugins(self.handle, count) - for i in xrange(count.value): + for i in range(count.value): pluginlist.append(RepoPlugin(handle=result[i])) core.BNFreeRepositoryPluginList(result, count.value) del result @@ -220,7 +222,7 @@ class RepositoryManager(object): result = [] count = ctypes.c_ulonglong(0) repos = core.BNRepositoryManagerGetRepositories(self.handle, count) - for i in xrange(count.value): + for i in range(count.value): result.append(Repository(handle=repos[i])) core.BNFreeRepositoryManagerRepositoriesList(repos) return result diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 0b15ee18..374b2f41 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -33,6 +33,7 @@ import binaryninja.log #2-3 compatibility from six import with_metaclass +from six.moves import range class _ThreadActionContext(object): @@ -263,7 +264,7 @@ class _ScriptingProviderMetaclass(type): count = ctypes.c_ulonglong() types = core.BNGetScriptingProviderList(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(ScriptingProvider(types[i])) core.BNFreeScriptingProviderList(types) return result @@ -273,7 +274,7 @@ class _ScriptingProviderMetaclass(type): count = ctypes.c_ulonglong() types = core.BNGetScriptingProviderList(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield ScriptingProvider(types[i]) finally: core.BNFreeScriptingProviderList(types) @@ -313,7 +314,7 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): self._cb = core.BNScriptingProviderCallbacks() self._cb.context = 0 self._cb.createInstance = self._cb.createInstance.__class__(self._create_instance) - self.handle = core.BNRegisterScriptingProvider(self.__class__.name.encode('utf8'), self._cb) + self.handle = core.BNRegisterScriptingProvider(self.__class__.name, self._cb) self.__class__._registered_providers.append(self) def _create_instance(self, ctxt): diff --git a/python/setting.py b/python/setting.py index 7cde3865..16d943e7 100644 --- a/python/setting.py +++ b/python/setting.py @@ -23,6 +23,9 @@ import ctypes # Binary Ninja components -- additional imports belong in the appropriate class from binaryninja import _binaryninjacore as core +# 2-3 compatibility +from six.moves import range + class Setting(object): def __init__(self, plugin_name="core"): @@ -45,7 +48,7 @@ class Setting(object): default_list[i] = default_value[i] result = core.BNSettingGetIntegerList(self.plugin_name, name, default_list, ctypes.byref(length)) out_list = [] - for i in xrange(length.value): + for i in range(length.value): out_list.append(result[i]) core.BNFreeSettingIntegerList(result) return out_list @@ -58,7 +61,7 @@ class Setting(object): default_list[i] = default_value[i] result = core.BNSettingGetStringList(self.plugin_name, name, default_list, ctypes.byref(length)) out_list = [] - for i in xrange(length.value): + for i in range(length.value): out_list.append(result[i]) core.BNFreeStringList(result, length) return out_list @@ -100,7 +103,7 @@ class Setting(object): length = ctypes.c_ulonglong() length.value = len(value) default_list = (ctypes.c_longlong * len(value))() - for i in xrange(len(value)): + for i in range(len(value)): default_list[i] = value[i] return core.BNSettingSetIntegerList(self.plugin_name, name, default_list, length, auto_flush) @@ -109,7 +112,7 @@ class Setting(object): length = ctypes.c_ulonglong() length.value = len(value) default_list = (ctypes.c_char_p * len(value))() - for i in xrange(len(value)): + for i in range(len(value)): default_list[i] = str(value[i]) return core.BNSettingSetStringList(self.plugin_name, name, default_list, length, auto_flush) diff --git a/python/transform.py b/python/transform.py index fd68a987..e16c6bfc 100644 --- a/python/transform.py +++ b/python/transform.py @@ -31,6 +31,7 @@ from binaryninja.enums import TransformType #2-3 compatibility from six import with_metaclass +from six.moves import range class _TransformMetaClass(type): @@ -41,7 +42,7 @@ class _TransformMetaClass(type): count = ctypes.c_ulonglong() xforms = core.BNGetTransformTypeList(count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(Transform(xforms[i])) core.BNFreeTransformTypeList(xforms) return result @@ -51,7 +52,7 @@ class _TransformMetaClass(type): count = ctypes.c_ulonglong() xforms = core.BNGetTransformTypeList(count) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield Transform(xforms[i]) finally: core.BNFreeTransformTypeList(xforms) @@ -129,7 +130,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): count = ctypes.c_ulonglong() params = core.BNGetTransformParameterList(self.handle, count) self.parameters = [] - for i in xrange(0, count.value): + for i in range(0, count.value): self.parameters.append(TransformParameter(params[i].name, params[i].longName, params[i].fixedLength)) core.BNFreeTransformParameterList(params, count.value) @@ -150,7 +151,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): try: count[0] = len(self.parameters) param_buf = (core.BNTransformParameterInfo * len(self.parameters))() - for i in xrange(0, len(self.parameters)): + for i in range(0, len(self.parameters)): param_buf[i].name = self.parameters[i].name param_buf[i].longName = self.parameters[i].long_name param_buf[i].fixedLength = self.parameters[i].fixed_length @@ -175,7 +176,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): try: input_obj = databuffer.DataBuffer(handle = core.BNDuplicateDataBuffer(input_buf)) param_map = {} - for i in xrange(0, count): + for i in range(0, count): data = databuffer.DataBuffer(handle = core.BNDuplicateDataBuffer(params[i].value)) param_map[params[i].name] = str(data) result = self.perform_decode(str(input_obj), param_map) @@ -192,7 +193,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): try: input_obj = databuffer.DataBuffer(handle = core.BNDuplicateDataBuffer(input_buf)) param_map = {} - for i in xrange(0, count): + for i in range(0, count): data = databuffer.DataBuffer(handle = core.BNDuplicateDataBuffer(params[i].value)) param_map[params[i].name] = str(data) result = self.perform_encode(str(input_obj), param_map) @@ -225,7 +226,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): output_buf = databuffer.DataBuffer() keys = params.keys() param_buf = (core.BNTransformParameter * len(keys))() - for i in xrange(0, len(keys)): + for i in range(0, len(keys)): data = databuffer.DataBuffer(params[keys[i]]) param_buf[i].name = keys[i] param_buf[i].value = data.handle @@ -238,7 +239,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): output_buf = databuffer.DataBuffer() keys = params.keys() param_buf = (core.BNTransformParameter * len(keys))() - for i in xrange(0, len(keys)): + for i in range(0, len(keys)): data = databuffer.DataBuffer(params[keys[i]]) param_buf[i].name = keys[i] param_buf[i].value = data.handle diff --git a/python/types.py b/python/types.py index adb9e03a..857f67e6 100644 --- a/python/types.py +++ b/python/types.py @@ -28,6 +28,9 @@ import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType +#2-3 compatibility +from six.moves import range + class QualifiedName(object): def __init__(self, name = []): @@ -98,7 +101,7 @@ class QualifiedName(object): def _get_core_struct(self): result = core.BNQualifiedName() name_list = (ctypes.c_char_p * len(self.name))() - for i in xrange(0, len(self.name)): + for i in range(0, len(self.name)): name_list[i] = self.name[i] result.name = name_list result.nameCount = len(self.name) @@ -107,7 +110,7 @@ class QualifiedName(object): @classmethod def _from_core_struct(cls, name): result = [] - for i in xrange(0, name.nameCount): + for i in range(0, name.nameCount): result.append(name.name[i]) return QualifiedName(result) @@ -300,7 +303,7 @@ class Type(object): count = ctypes.c_ulonglong() params = core.BNGetTypeParameters(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): param_type = Type(core.BNNewTypeReference(params[i].type), platform = self.platform, confidence = params[i].typeConfidence) if params[i].defaultLocation: param_location = None @@ -403,7 +406,7 @@ class Type(object): platform = self.platform.handle tokens = core.BNGetTypeTokens(self.handle, platform, base_confidence, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -423,7 +426,7 @@ class Type(object): platform = self.platform.handle tokens = core.BNGetTypeTokensBeforeName(self.handle, platform, base_confidence, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -443,7 +446,7 @@ class Type(object): platform = self.platform.handle tokens = core.BNGetTypeTokensAfterName(self.handle, platform, base_confidence, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): token_type = InstructionTextTokenType(tokens[i].type) text = tokens[i].text value = tokens[i].value @@ -574,7 +577,7 @@ class Type(object): :param bool variable_arguments: optional argument for functions that have a variable number of arguments """ param_buf = (core.BNFunctionParameter * len(params))() - for i in xrange(0, len(params)): + for i in range(0, len(params)): if isinstance(params[i], Type): param_buf[i].name = "" param_buf[i].type = params[i].handle @@ -851,7 +854,7 @@ class Structure(object): count = ctypes.c_ulonglong() members = core.BNGetStructureMembers(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(StructureMember(Type(core.BNNewTypeReference(members[i].type), confidence = members[i].typeConfidence), members[i].name, members[i].offset)) core.BNFreeStructureMemberList(members, count.value) @@ -962,7 +965,7 @@ class Enumeration(object): count = ctypes.c_ulonglong() members = core.BNGetEnumerationMembers(self.handle, count) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(EnumerationMember(members[i].name, members[i].value, members[i].isDefault)) core.BNFreeEnumerationMemberList(members, count.value) return result @@ -1018,7 +1021,7 @@ def preprocess_source(source, filename=None, include_dirs=[]): if filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): + for i in range(0, len(include_dirs)): dir_buf[i] = str(include_dirs[i]) output = ctypes.c_char_p() errors = ctypes.c_char_p() diff --git a/python/update.py b/python/update.py index 560f05ec..4c77b202 100644 --- a/python/update.py +++ b/python/update.py @@ -28,6 +28,7 @@ from binaryninja.enums import UpdateResult #2-3 compatibility from six import with_metaclass +from six.moves import range class _UpdateChannelMetaClass(type): @@ -43,7 +44,7 @@ class _UpdateChannelMetaClass(type): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion)) core.BNFreeUpdateChannelList(channels, count.value) return result @@ -66,7 +67,7 @@ class _UpdateChannelMetaClass(type): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) try: - for i in xrange(0, count.value): + for i in range(0, count.value): yield UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion) finally: core.BNFreeUpdateChannelList(channels, count.value) @@ -87,7 +88,7 @@ class _UpdateChannelMetaClass(type): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) result = None - for i in xrange(0, count.value): + for i in range(0, count.value): if channels[i].name == str(name): result = UpdateChannel(channels[i].name, channels[i].description, channels[i].latestVersion) break @@ -130,7 +131,7 @@ class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) result = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time)) core.BNFreeUpdateChannelVersionList(versions, count.value) return result @@ -146,7 +147,7 @@ class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)): core.BNFreeString(ctypes.cast(errors, ctypes.POINTER(ctypes.c_byte))) raise IOError(error_str) result = None - for i in xrange(0, count.value): + for i in range(0, count.value): if versions[i].version == self.latest_version_num: result = UpdateVersion(self, versions[i].version, versions[i].notes, versions[i].time) break -- cgit v1.3.1 From 5d4015659d20cfee839ccccdcfb96094ac8e610a Mon Sep 17 00:00:00 2001 From: KyleMiles Date: Wed, 6 Jun 2018 20:44:47 -0400 Subject: Various Python 3 support changes --- .gitignore | 14 ++ Makefile | 50 +++---- python/__init__.py | 26 ++++ python/architecture.py | 35 ++--- python/basicblock.py | 5 +- python/binaryview.py | 34 +++-- python/callingconvention.py | 7 +- python/databuffer.py | 4 +- python/demangle.py | 4 +- python/downloadprovider.py | 4 +- python/fileaccessor.py | 3 +- python/filemetadata.py | 2 +- python/function.py | 25 +++- python/functionrecognizer.py | 14 +- python/highlight.py | 2 +- python/interaction.py | 17 ++- python/log.py | 14 +- python/lowlevelil.py | 4 +- python/mainthread.py | 2 +- python/mediumlevelil.py | 2 +- python/metadata.py | 6 +- python/platform.py | 76 +++++------ python/plugin.py | 19 +-- python/pluginmanager.py | 6 +- python/scriptingprovider.py | 46 ++++--- python/setting.py | 8 +- python/transform.py | 15 +-- python/types.py | 15 ++- python/undoaction.py | 4 +- python/update.py | 12 +- scripts/install_api.py | 2 +- suite/binaries | 2 +- suite/generator.py | 107 +++++++++------ suite/testcommon.py | 282 ++++++++++++++++++++++++++------------- suite/unit.py | 309 +++++++++++++------------------------------ 35 files changed, 621 insertions(+), 556 deletions(-) (limited to 'python/plugin.py') diff --git a/.gitignore b/.gitignore index fc71333a..eff64eb4 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,17 @@ CTestTestfile.cmake api-docs/source/python.rst api-docs/source/index.rst .coverage +# Make +generator +libcrypto.so.1.0.2 +libcurl.so.4 +libssl.so.1.0.2 +plugins/ +python/examples/binaryninja/ +python/libcrypto.so.1.0.2 +python/libcurl.so.4 +python/libssl.so.1.0.2 +python/plugins/ +python/types/ +suite/binaryninja/ +types/ diff --git a/Makefile b/Makefile index 852569a0..e1576dcf 100644 --- a/Makefile +++ b/Makefile @@ -43,7 +43,8 @@ json.o: ./json/jsoncpp.cpp ./json/json.h ./json/json-forwards.h install: generate $(TARGET).a @echo "Installing binaryninja API."; cp -r python/* $(INSTALLPATH)/python/binaryninja - cp $(TARGETDIR)/$(TARGET).a $(INSTALLPATH) + cp $(TARGET).a $(INSTALLPATH) + @echo "Done."; generator: python/generator.cpp $(TARGET).a @echo "Building generator..."; @@ -65,43 +66,36 @@ python_test: environment python/_binaryninjacore.py python/enums.py oracle: environment python/_binaryninjacore.py python/enums.py python3 suite/generator.py -environment: python/_binaryninjacore.py python/enums.py - @echo "Copying libs to needed locations..." - @cp $(INSTALLPATH)/libbinaryninjacore.so.1 . - @cp $(INSTALLPATH)/libcurl.so.4 . - @cp $(INSTALLPATH)/libcrypto.so.1.0.2 . - @cp $(INSTALLPATH)/libssl.so.1.0.2 . - - @mkdir -p api/python/examples - @cp python/examples/bin_info.py api/python/examples/ - @cp $(INSTALLPATH)/libbinaryninjacore.so.1 api/python/ - @cp $(INSTALLPATH)/libcurl.so.4 api/python/ - @cp $(INSTALLPATH)/libcrypto.so.1.0.2 api/python/ - @cp $(INSTALLPATH)/libssl.so.1.0.2 api/python/ +environment: environment_clean python/_binaryninjacore.py python/enums.py + @echo "Copying over libs..." + cp $(INSTALLPATH)/libbinaryninjacore.so.1 . + cp $(INSTALLPATH)/libbinaryninjacore.so.1 python/ @echo "Building 'binaryninja' Packages..." - @mkdir -p suite/binaryninja/ - @cp -r python/* suite/binaryninja/ - @mkdir -p api/python/examples/binaryninja/ - @cp -r python/* api/python/examples/binaryninja/ + mkdir -p suite/binaryninja/ + cp -r python/* suite/binaryninja/ + cp -r suite/binaryninja/ python/examples/ @echo "Copying Architectures Over..." - @cp -r $(INSTALLPATH)/types/ . - @cp -r $(INSTALLPATH)/plugins/ . - @cp -r $(INSTALLPATH)/plugins/ api/python/ + cp -r $(INSTALLPATH)/types/ . + cp -r $(INSTALLPATH)/plugins/ . + cp -r $(INSTALLPATH)/types/ python/ + cp -r $(INSTALLPATH)/plugins/ python/ environment_clean: @echo "Removing 'binaryninja' Packages..." - @rm -r suite/binaryninja/ - @rm -r api/ - -@rm suite/*.pyc - + rm -rf suite/binaryninja/ + rm -rf python/examples/binaryninja/ + @echo "Removing libs..." - @rm lib* + rm -f libbinaryninjacore.so.1 + rm -f python/libbinaryninjacore.so.1 @echo "Removing Architectures..." - @rm -r types/ - @rm -r plugins/ + rm -rf types/ + rm -rf plugins/ + rm -rf python/types/ + rm -rf python/plugins/ clean: @echo " Cleaning..."; diff --git a/python/__init__.py b/python/__init__.py index 2f7cc5a0..e1288b0a 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -25,6 +25,32 @@ import sys import ctypes from time import gmtime + +# 2-3 compatibility +try: + import builtins # __builtins__ for python2 +except ImportError: + pass +def range(*args): + """ A Python2 and Python3 Compatible Range Generator """ + try: + return xrange(*args) + except NameError: + return builtins.range(*args) + + +def with_metaclass(meta, *bases): + """Create a base class with a metaclass.""" + class metaclass(type): + def __new__(cls, name, this_bases, d): + return meta(name, bases, d) + + @classmethod + def __prepare__(cls, name, this_bases): + return meta.__prepare__(name, bases) + return type.__new__(metaclass, 'temporary_class', (), {}) + + # Binary Ninja components import binaryninja._binaryninjacore as core # __all__ = [ diff --git a/python/architecture.py b/python/architecture.py index 521c750a..aee7c301 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -23,13 +23,12 @@ import traceback import ctypes import abc -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import (Endianness, ImplicitRegisterExtend, BranchType, InstructionTextTokenType, LowLevelILFlagCondition, FlagRole) import binaryninja from binaryninja import log - from binaryninja import lowlevelil from binaryninja import types from binaryninja import databuffer @@ -37,8 +36,9 @@ from binaryninja import platform from binaryninja import callingconvention # 2-3 compatibility -from six import with_metaclass -from six.moves import range +from binaryninja import range +from binaryninja import with_metaclass + class _ArchitectureMetaClass(type): @@ -624,7 +624,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_full_width_registers(self, ctxt, count): try: - regs = self._full_width_regs.values() + regs = list(self._full_width_regs.values()) count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() for i in range(0, len(regs)): @@ -639,7 +639,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_registers(self, ctxt, count): try: - regs = self._regs_by_index.keys() + regs = list(self._regs_by_index.keys()) count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() for i in range(0, len(regs)): @@ -654,7 +654,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_flags(self, ctxt, count): try: - flags = self._flags_by_index.keys() + flags = list(self._flags_by_index.keys()) count[0] = len(flags) flag_buf = (ctypes.c_uint * len(flags))() for i in range(0, len(flags)): @@ -669,7 +669,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_flag_write_types(self, ctxt, count): try: - write_types = self._flag_write_types_by_index.keys() + write_types = list(self._flag_write_types_by_index.keys()) count[0] = len(write_types) type_buf = (ctypes.c_uint * len(write_types))() for i in range(0, len(write_types)): @@ -684,7 +684,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_semantic_flag_classes(self, ctxt, count): try: - sem_classes = self._semantic_flag_classes_by_index.keys() + sem_classes = list(self._semantic_flag_classes_by_index.keys()) count[0] = len(sem_classes) class_buf = (ctypes.c_uint * len(sem_classes))() for i in range(0, len(sem_classes)): @@ -699,7 +699,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_semantic_flag_groups(self, ctxt, count): try: - sem_groups = self._semantic_flag_groups_by_index.keys() + sem_groups = list(self._semantic_flag_groups_by_index.keys()) count[0] = len(sem_groups) group_buf = (ctypes.c_uint * len(sem_groups))() for i in range(0, len(sem_groups)): @@ -938,7 +938,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_register_stacks(self, ctxt, count): try: - regs = self._reg_stacks_by_index.keys() + regs = list(self._reg_stacks_by_index.keys()) count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() for i in range(0, len(regs)): @@ -989,7 +989,7 @@ class Architecture(with_metaclass(_ArchitectureMetaClass, object)): def _get_all_intrinsics(self, ctxt, count): try: - regs = self._intrinsics_by_index.keys() + regs = list(self._intrinsics_by_index.keys()) count[0] = len(regs) reg_buf = (ctypes.c_uint * len(regs))() for i in range(0, len(regs)): @@ -2415,8 +2415,8 @@ class CoreArchitecture(Architecture): :param str code: string representation of the instructions to be assembled :param int addr: virtual address that the instructions will be loaded at - :return: the bytes for the assembled instructions or error string - :rtype: (a tuple of instructions and empty string) or (or None and error string) + :return: the bytes for the assembled instructions + :rtype: Python3 - a 'bytes' object; Python2 - a 'str' :Example: >>> arch.assemble("je 10") @@ -2426,8 +2426,11 @@ class CoreArchitecture(Architecture): result = databuffer.DataBuffer() errors = ctypes.c_char_p() if not core.BNAssemble(self.handle, code, addr, result.handle, errors): - return None, errors.value - return str(result), errors.value + raise ValueError("Could not assemble") + if isinstance(str(result), bytes): + return str(result) + else: + return bytes(result) def is_never_branch_patch_available(self, data, addr): """ diff --git a/python/basicblock.py b/python/basicblock.py index b1f95ba3..11d5a7f4 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -20,14 +20,15 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import highlight from binaryninja import _binaryninjacore as core from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType # 2-3 compatibility -from six.moves import range +from binaryninja import range + class BasicBlockEdge(object): def __init__(self, branch_type, source, target, back_edge): diff --git a/python/binaryview.py b/python/binaryview.py index b1bc4822..d439f563 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -23,7 +23,7 @@ import traceback import ctypes import abc -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import (AnalysisState, SymbolType, InstructionTextTokenType, Endianness, ModificationStatus, StringType, SegmentFlag, SectionSemantics) @@ -38,8 +38,8 @@ from binaryninja import lineardisassembly from binaryninja import metadata # 2-3 compatibility -from six import with_metaclass -from six.moves import range +from binaryninja import range +from binaryninja import with_metaclass class BinaryDataNotification(object): @@ -98,17 +98,19 @@ class StringReference(object): @property def value(self): - return self.view.read(self.start, self.length) + return self.view.read(self.start, self.length).decode("charmap") def __repr__(self): return "<%s: %#x, len %#x>" % (self.type, self.start, self.length) +_pending_analysis_completion_events = {} class AnalysisCompletionEvent(object): """ The ``AnalysisCompletionEvent`` object provides an asynchronous mechanism for receiving callbacks when analysis is complete. The callback runs once. A completion event must be added - for each new analysis in order to be notified of each analysis completion. + for each new analysis in order to be notified of each analysis completion. The + AnalysisCompletionEvent class takes responcibility for keeping track of the object's lifetime. :Example: >>> def on_complete(self): @@ -122,11 +124,19 @@ class AnalysisCompletionEvent(object): self.callback = callback self._cb = ctypes.CFUNCTYPE(None, ctypes.c_void_p)(self._notify) self.handle = core.BNAddAnalysisCompletionEvent(self.view.handle, None, self._cb) + global _pending_analysis_completion_events + _pending_analysis_completion_events[id(self)] = self def __del__(self): + global _pending_analysis_completion_events + if id(self) in _pending_analysis_completion_events: + del _pending_analysis_completion_events[id(self)] core.BNFreeAnalysisCompletionEvent(self.handle) def _notify(self, ctxt): + global _pending_analysis_completion_events + if id(self) in _pending_analysis_completion_events: + del _pending_analysis_completion_events[id(self)] try: self.callback(self) except: @@ -142,6 +152,9 @@ class AnalysisCompletionEvent(object): """ self.callback = self._empty_callback core.BNCancelAnalysisCompletionEvent(self.handle) + global _pending_analysis_completion_events + if id(self) in _pending_analysis_completion_events: + del _pending_analysis_completion_events[id(self)] class ActiveAnalysisInfo(object): @@ -1731,10 +1744,13 @@ class BinaryView(object): """ ``read`` returns the data reads at most ``length`` bytes from virtual address ``addr``. + Note: Python2 returns a str, but Python3 returns a bytes object. str(DataBufferObject) will + still get you a str in either case. + :param int addr: virtual address to read from. :param int length: number of bytes to read. :return: at most ``length`` bytes from the virtual address ``addr``, empty string on error or no data. - :rtype: str + :rtype: python2 - str; python3 - bytes :Example: >>> #Opening a x86_64 Mach-O binary @@ -2784,7 +2800,9 @@ class BinaryView(object): def add_analysis_completion_event(self, callback): """ ``add_analysis_completion_event`` sets up a call back function to be called when analysis has been completed. - This is helpful when using asynchronously analysis. + This is helpful when using ``update_analysis`` which does not wait for analysis completion before returning. + + The callee of this function is not resposible for maintaining the lifetime of the returned AnalysisCompletionEvent object. :param callable() callback: A function to be called with no parameters when analysis has completed. :return: An initialized AnalysisCompletionEvent object. @@ -3481,7 +3499,7 @@ class BinaryView(object): def get_unique_section_names(self, name_list): incoming_names = (ctypes.c_char_p * len(name_list))() for i in range(0, len(name_list)): - incoming_names[i] = name_list[i] + incoming_names[i] = name_list[i].encode('charmap') outgoing_names = core.BNGetUniqueSectionNames(self.handle, incoming_names, len(name_list)) result = [] for i in range(0, len(name_list)): diff --git a/python/callingconvention.py b/python/callingconvention.py index 1b0d068e..6b906184 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -21,18 +21,17 @@ import traceback import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core from binaryninja import log from binaryninja.enums import VariableSourceType # 2-3 compatibility -from six.moves import range +from binaryninja import range class CallingConvention(object): - from binaryninja import types name = None caller_saved_regs = [] int_arg_regs = [] @@ -48,7 +47,7 @@ class CallingConvention(object): _registered_calling_conventions = [] - def __init__(self, arch=None, name=None, handle=None, confidence=types.max_confidence): + def __init__(self, arch=None, name=None, handle=None, confidence=binaryninja.types.max_confidence): if handle is None: if arch is None or name is None: raise ValueError("Must specify either handle or architecture and name") diff --git a/python/databuffer.py b/python/databuffer.py index 1b29a7eb..298d0002 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -20,7 +20,7 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core @@ -114,7 +114,7 @@ class DataBuffer(object): def __str__(self): buf = ctypes.create_string_buffer(len(self)) ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self)) - if type(buf.raw) is str: + if isinstance(buf.raw, str): return buf.raw else: return buf.raw.decode("charmap") diff --git a/python/demangle.py b/python/demangle.py index 90a19761..466324bc 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -20,11 +20,11 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core # 2-3 compatibility -from six.moves import range +from binaryninja import range def get_qualified_name(names): diff --git a/python/downloadprovider.py b/python/downloadprovider.py index d34ca358..c714cb98 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -28,6 +28,7 @@ import traceback # Binary Ninja Components import binaryninja._binaryninjacore as core from binaryninja.setting import Setting +from binaryninja import with_metaclass from binaryninja import startup from binaryninja import log @@ -109,8 +110,7 @@ class _DownloadProviderMetaclass(type): raise AttributeError("attribute '%s' is read only" % name) -class DownloadProvider(object): - __metaclass__ = _DownloadProviderMetaclass +class DownloadProvider(with_metaclass(_DownloadProviderMetaclass, object)): name = None instance_class = None _registered_providers = [] diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 3c7c5e45..c2539b39 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -21,11 +21,10 @@ import traceback import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core class FileAccessor(object): - def __init__(self): self._cb = core.BNFileAccessor() self._cb.context = 0 diff --git a/python/filemetadata.py b/python/filemetadata.py index ee69dce8..cafe1d67 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -22,7 +22,7 @@ from __future__ import absolute_import import traceback import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja Components import binaryninja from binaryninja import _binaryninjacore as core from binaryninja import associateddatastore #required for _FileMetadataAssociatedDataStore diff --git a/python/function.py b/python/function.py index 6392d7f2..8407eece 100644 --- a/python/function.py +++ b/python/function.py @@ -23,20 +23,20 @@ import threading import traceback import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core +from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore +from binaryninja import highlight +from binaryninja import log +from binaryninja import types from binaryninja.enums import (AnalysisSkipReason, FunctionGraphType, BranchType, SymbolType, InstructionTextTokenType, HighlightStandardColor, HighlightColorStyle, RegisterValueType, ImplicitRegisterExtend, DisassemblyOption, IntegerDisplayType, InstructionTextTokenContext, VariableSourceType, FunctionAnalysisSkipOverride) -from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore -from binaryninja import types -from binaryninja import highlight -from binaryninja import log # 2-3 compatibility -from six.moves import range +from binaryninja import range class LookupTableEntry(object): @@ -49,7 +49,7 @@ class LookupTableEntry(object): class RegisterValue(object): - def __init__(self, arch = None, value = None, confidence = binaryninja.types.max_confidence): + def __init__(self, arch = None, value = None, confidence = types.max_confidence): self.is_constant = False if value is None: self.type = RegisterValueType.UndeterminedValue @@ -1160,6 +1160,8 @@ class Function(object): for j in range(0, lines[i].count): token_type = InstructionTextTokenType(lines[i].tokens[j].type) text = lines[i].tokens[j].text + if not isinstance(text, str): + text = text.encode("charmap") value = lines[i].tokens[j].value size = lines[i].tokens[j].size operand = lines[i].tokens[j].operand @@ -1836,6 +1838,7 @@ class DisassemblySettings(object): core.BNSetDisassemblySettingsOption(self.handle, option, state) +_pending_function_graph_completion_events = {} class FunctionGraph(object): def __init__(self, view, handle): self.view = view @@ -1969,6 +1972,9 @@ class FunctionGraph(object): try: if self._on_complete is not None: self._on_complete() + global _pending_function_graph_completion_events + if id(self) in _pending_function_graph_completion_events: + del _pending_function_graph_completion_events[id(self)] except: log.log_error(traceback.format_exc()) @@ -1993,11 +1999,16 @@ class FunctionGraph(object): self._wait_cond.release() def on_complete(self, callback): + global _pending_function_graph_completion_events + _pending_function_graph_completion_events[id(self)] = self self._on_complete = callback core.BNSetFunctionGraphCompleteCallback(self.handle, None, self._cb) def abort(self): core.BNAbortFunctionGraph(self.handle) + global _pending_function_graph_completion_events + if id(self) in _pending_function_graph_completion_events: + del _pending_function_graph_completion_events[id(self)] def get_blocks_in_region(self, left, top, right, bottom): count = ctypes.c_ulonglong() diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index e390a3c8..319bff0e 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -20,15 +20,15 @@ import traceback -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core +from binaryninja import function +from binaryninja import filemetadata +from binaryninja import binaryview +from binaryninja import lowlevelil class FunctionRecognizer(object): - from binaryninja import function - from binaryninja import filemetadata - from binaryninja import binaryview - from binaryninja import lowlevelil _instance = None @@ -54,7 +54,7 @@ class FunctionRecognizer(object): try: file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data)) view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data)) - func = binaryninja.function.Function(view, handle = core.BNNewFunctionReference(func)) + func = function.Function(view, handle = core.BNNewFunctionReference(func)) il = lowlevelil.LowLevelILFunction(func.arch, handle = core.BNNewLowLevelILFunctionReference(il)) return self.recognize_low_level_il(view, func, il) except: @@ -68,7 +68,7 @@ class FunctionRecognizer(object): try: file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(data)) view = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(data)) - func = binaryninja.function.Function(view, handle = core.BNNewFunctionReference(func)) + 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: diff --git a/python/highlight.py b/python/highlight.py index b04561bd..55246a9a 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -19,7 +19,7 @@ # IN THE SOFTWARE. -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import HighlightColorStyle, HighlightStandardColor diff --git a/python/interaction.py b/python/interaction.py index 5b78b278..49b4e024 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -21,12 +21,13 @@ import ctypes import traceback -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult +from binaryninja import binaryview # 2-3 compatibility -from six.moves import range +from binaryninja import range class LabelField(object): @@ -152,7 +153,11 @@ class AddressField(object): class ChoiceField(object): """ ``ChoiceField`` prompts the user to choose from the list of strings provided in ``choices``. Result is stored - in self.result as an index in to the coices array. + in self.result as an index in to the choices array. + + :attr str prompt: prompt to be presented to the user + :attr list(str) choices: list of choices to choose from + """ def __init__(self, prompt, choices): self.prompt = prompt @@ -164,7 +169,7 @@ class ChoiceField(object): value.prompt = self.prompt choice_buf = (ctypes.c_char_p * len(self.choices))() for i in range(0, len(self.choices)): - choice_buf[i] = str(self.choices[i]) + choice_buf[i] = self.choices[i].encode('charmap') value.choices = choice_buf value.count = len(self.choices) @@ -242,8 +247,6 @@ class DirectoryNameField(object): class InteractionHandler(object): - - from binaryninja import binaryview _interaction_handler = None def __init__(self): @@ -617,7 +620,7 @@ def get_choice_input(prompt, title, choices): """ choice_buf = (ctypes.c_char_p * len(choices))() for i in range(0, len(choices)): - choice_buf[i] = str(choices[i]) + choice_buf[i] = str(choices[i]).encode('charmap') value = ctypes.c_ulonglong() if not core.BNGetChoiceInput(value, prompt, title, choice_buf, len(choices)): return None diff --git a/python/log.py b/python/log.py index d4d87019..9a5e1358 100644 --- a/python/log.py +++ b/python/log.py @@ -19,7 +19,7 @@ # IN THE SOFTWARE. -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import LogLevel @@ -55,7 +55,7 @@ def log(level, text): :param str text: message to print :rtype: None """ - core.BNLog(level, "%s", str(text)) + core.BNLog(level,text) def log_debug(text): @@ -70,7 +70,7 @@ def log_debug(text): >>> log_debug("Hotdogs!") Hotdogs! """ - core.BNLogDebug("%s", str(text)) + core.BNLogDebug(text) def log_info(text): @@ -85,7 +85,7 @@ def log_info(text): Saucisson! >>> """ - core.BNLogInfo("%s", str(text)) + core.BNLogInfo(text) def log_warn(text): @@ -101,7 +101,7 @@ def log_warn(text): Chilidogs! >>> """ - core.BNLogWarn("%s", str(text)) + core.BNLogWarn(text) def log_error(text): @@ -117,7 +117,7 @@ def log_error(text): Spanferkel! >>> """ - core.BNLogError("%s", str(text)) + core.BNLogError(text) def log_alert(text): @@ -133,7 +133,7 @@ def log_alert(text): Kielbasa! >>> """ - core.BNLogAlert("%s", str(text)) + core.BNLogAlert(text) def log_to_stdout(min_level=LogLevel.InfoLog): diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 272b2474..e714eb48 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -21,14 +21,14 @@ import ctypes import struct -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType from binaryninja import basicblock #required for LowLevelILBasicBlock # 2-3 compatibility -from six.moves import range +from binaryninja import range class LowLevelILLabel(object): diff --git a/python/mainthread.py b/python/mainthread.py index 16938f1a..5b0cd53c 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -18,7 +18,7 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja import scriptingprovider diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index f7e9951a..cfa8f900 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -30,7 +30,7 @@ from binaryninja import types from binaryninja import lowlevelil # 2-3 compatibility -from six.moves import range +from binaryninja import range class SSAVariable(object): diff --git a/python/metadata.py b/python/metadata.py index fed8bdaa..b17bbf4f 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -22,12 +22,12 @@ from __future__ import absolute_import import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import MetadataType # 2-3 compatibility -from six.moves import range +from binaryninja import range class Metadata(object): @@ -147,7 +147,7 @@ class Metadata(object): result = core.BNMetadataGetValueStore(self.handle) try: for i in range(result.contents.size): - if type(result.contents.keys[i]) is bytes: + if isinstance(result.contents.keys[i], bytes): yield str(result.contents.keys[i].decode('charmap')) else: yield result.contents.keys[i] diff --git a/python/platform.py b/python/platform.py index c57315ce..9a5f70df 100644 --- a/python/platform.py +++ b/python/platform.py @@ -20,18 +20,18 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core +from binaryninja import types -#2-3 compatibility -from six import with_metaclass -from six.moves import range +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _PlatformMetaClass(type): - from binaryninja import types @property def list(self): binaryninja._init_plugins() @@ -240,8 +240,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformTypes(self.handle, count) result = {} for i in range(0, count.value): - name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -252,8 +252,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformVariables(self.handle, count) result = {} for i in range(0, count.value): - name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -264,8 +264,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): type_list = core.BNGetPlatformFunctions(self.handle, count) result = {} for i in range(0, count.value): - name = binaryninja.types.QualifiedName._from_core_struct(type_list[i].name) - result[name] = binaryninja.types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) + name = types.QualifiedName._from_core_struct(type_list[i].name) + result[name] = types.Type(core.BNNewTypeReference(type_list[i].type), platform = self) core.BNFreeTypeList(type_list, count.value) return result @@ -276,8 +276,8 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): call_list = core.BNGetPlatformSystemCalls(self.handle, count) result = {} for i in range(0, count.value): - name = binaryninja.types.QualifiedName._from_core_struct(call_list[i].name) - t = binaryninja.types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) + name = types.QualifiedName._from_core_struct(call_list[i].name) + t = types.Type(core.BNNewTypeReference(call_list[i].type), platform = self) result[call_list[i].number] = (name, t) core.BNFreeSystemCallList(call_list, count.value) return result @@ -328,25 +328,25 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): return Platform(None, handle = result), new_addr.value def get_type_by_name(self, name): - name = binaryninja.types.QualifiedName(name)._get_core_struct() + name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformTypeByName(self.handle, name) if not obj: return None - return binaryninja.types.Type(obj, platform = self) + return types.Type(obj, platform = self) def get_variable_by_name(self, name): - name = binaryninja.types.QualifiedName(name)._get_core_struct() + name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformVariableByName(self.handle, name) if not obj: return None - return binaryninja.types.Type(obj, platform = self) + return types.Type(obj, platform = self) def get_function_by_name(self, name): - name = binaryninja.types.QualifiedName(name)._get_core_struct() + name = types.QualifiedName(name)._get_core_struct() obj = core.BNGetPlatformFunctionByName(self.handle, name) if not obj: return None - return binaryninja.types.Type(obj, platform = self) + return types.Type(obj, platform = self) def get_system_call_name(self, number): return core.BNGetPlatformSystemCallName(self.handle, number) @@ -355,15 +355,15 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): obj = core.BNGetPlatformSystemCallType(self.handle, number) if not obj: return None - return binaryninja.types.Type(obj, platform = self) + return types.Type(obj, platform = self) def generate_auto_platform_type_id(self, name): - name = binaryninja.types.QualifiedName(name)._get_core_struct() + name = types.QualifiedName(name)._get_core_struct() return core.BNGenerateAutoPlatformTypeId(self.handle, name) def generate_auto_platform_type_ref(self, type_class, name): type_id = self.generate_auto_platform_type_id(name) - return binaryninja.types.NamedTypeReference(type_class, type_id, name) + return types.NamedTypeReference(type_class, type_id, name) def get_auto_platform_type_id_source(self): return core.BNGetAutoPlatformTypeIdSource(self.handle) @@ -391,7 +391,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) + dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() errors = ctypes.c_char_p() result = core.BNParseTypesFromSource(self.handle, source, filename, parse, errors, dir_buf, @@ -404,16 +404,16 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): variables = {} functions = {} for i in range(0, parse.typeCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) for i in range(0, parse.variableCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) for i in range(0, parse.functionCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) - return binaryninja.types.TypeParserResult(type_dict, variables, functions) + return types.TypeParserResult(type_dict, variables, functions) def parse_types_from_source_file(self, filename, include_dirs=[], auto_type_source=None): """ @@ -437,7 +437,7 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): """ dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) + dir_buf[i] = include_dirs[i].encode('charmap') parse = core.BNTypeParserResult() errors = ctypes.c_char_p() result = core.BNParseTypesFromSourceFile(self.handle, filename, parse, errors, dir_buf, @@ -450,13 +450,13 @@ class Platform(with_metaclass(_PlatformMetaClass, object)): variables = {} functions = {} for i in range(0, parse.typeCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.types[i].name) - type_dict[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.types[i].name) + type_dict[name] = types.Type(core.BNNewTypeReference(parse.types[i].type), platform = self) for i in range(0, parse.variableCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.variables[i].name) - variables[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.variables[i].name) + variables[name] = types.Type(core.BNNewTypeReference(parse.variables[i].type), platform = self) for i in range(0, parse.functionCount): - name = binaryninja.types.QualifiedName._from_core_struct(parse.functions[i].name) - functions[name] = binaryninja.types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) + name = types.QualifiedName._from_core_struct(parse.functions[i].name) + functions[name] = types.Type(core.BNNewTypeReference(parse.functions[i].type), platform = self) core.BNFreeTypeParserResult(parse) - return binaryninja.types.TypeParserResult(type_dict, variables, functions) + return types.TypeParserResult(type_dict, variables, functions) diff --git a/python/plugin.py b/python/plugin.py index 52feced4..b8217f0b 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -22,15 +22,18 @@ import traceback import ctypes import threading -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import log from binaryninja import _binaryninjacore as core from binaryninja.enums import PluginCommandType +from binaryninja import filemetadata +from binaryninja import binaryview +from binaryninja import function -#2-3 compatibility -from six import with_metaclass -from six.moves import range +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class PluginCommandContext(object): @@ -43,7 +46,6 @@ class PluginCommandContext(object): class _PluginCommandMetaClass(type): - @property def list(self): binaryninja._init_plugins() @@ -73,11 +75,6 @@ class _PluginCommandMetaClass(type): class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): - - from binaryninja import filemetadata - from binaryninja import binaryview - from binaryninja import function - _registered_commands = [] def __init__(self, cmd): @@ -540,7 +537,6 @@ class MainThreadAction(object): class MainThreadActionHandler(object): - _main_thread = None def __init__(self): @@ -586,7 +582,6 @@ class _BackgroundTaskMetaclass(type): class BackgroundTask(with_metaclass(_BackgroundTaskMetaclass, object)): - def __init__(self, initial_progress_text = "", can_cancel = False, handle = None): if handle is None: self.handle = core.BNBeginBackgroundTask(initial_progress_text, can_cancel) diff --git a/python/pluginmanager.py b/python/pluginmanager.py index ad314629..c7a0c83a 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -20,11 +20,12 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core # 2-3 compatibility -from six.moves import range +from binaryninja import range + class RepoPlugin(object): """ @@ -201,7 +202,6 @@ class RepositoryManager(object): ``RepositoryManager`` Keeps track of all the repositories and keeps the enabled_plugins.json file coherent with the plugins that are installed/unstalled enabled/disabled """ - def __init__(self, handle=None): raise Exception("RepositoryManager temporarily disabled!") self.handle = core.BNGetRepositoryManager() diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 374b2f41..37642ed4 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -26,14 +26,15 @@ import threading import abc import sys -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components +import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState -import binaryninja.log +from binaryninja import log -#2-3 compatibility -from six import with_metaclass -from six.moves import range +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _ThreadActionContext(object): @@ -75,19 +76,19 @@ class ScriptingOutputListener(object): try: self.notify_output(text) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _error(self, ctxt, text): try: self.notify_error(text) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _input_ready_state_changed(self, ctxt, state): try: self.notify_input_ready_state_changed(state) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def notify_output(self, text): pass @@ -123,13 +124,13 @@ class ScriptingInstance(object): try: self.perform_destroy_instance() except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _execute_script_input(self, ctxt, text): try: return self.perform_execute_script_input(text) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) return ScriptingProviderExecuteResult.InvalidScriptInput def _set_current_binary_view(self, ctxt, view): @@ -140,7 +141,7 @@ class ScriptingInstance(object): view = None self.perform_set_current_binary_view(view) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _set_current_function(self, ctxt, func): try: @@ -150,7 +151,7 @@ class ScriptingInstance(object): func = None self.perform_set_current_function(func) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _set_current_basic_block(self, ctxt, block): try: @@ -165,19 +166,19 @@ class ScriptingInstance(object): block = None self.perform_set_current_basic_block(block) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _set_current_address(self, ctxt, addr): try: self.perform_set_current_address(addr) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) def _set_current_selection(self, ctxt, begin, end): try: self.perform_set_current_selection(begin, end) except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) @abc.abstractmethod def perform_destroy_instance(self): @@ -324,7 +325,7 @@ class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): return None return ctypes.cast(core.BNNewScriptingInstanceReference(result.handle), ctypes.c_void_p).value except: - binaryninja.log.log_error(traceback.format_exc()) + log.log_error(traceback.format_exc()) return None def create_instance(self): @@ -390,7 +391,7 @@ class _PythonScriptingInstanceOutput(object): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: - if binaryninja.log.is_output_redirected_to_log(): + if log.is_output_redirected_to_log(): self.buffer += data while True: i = self.buffer.find('\n') @@ -400,9 +401,9 @@ class _PythonScriptingInstanceOutput(object): self.buffer = self.buffer[i + 1:] if self.is_error: - binaryninja.log.log_error(line) + log.log_error(line) else: - binaryninja.log.log_info(line) + log.log_info(line) else: self.orig.write(data) else: @@ -490,7 +491,7 @@ class PythonScriptingInstance(ScriptingInstance): self.code = None self.input = "" - self.interpreter.push("from binaryninja import *\n") + self.interpreter.push("from binaryninja import *") def execute(self, code): self.code = code @@ -553,8 +554,8 @@ class PythonScriptingInstance(ScriptingInstance): self.locals["current_llil"] = self.active_func.low_level_il self.locals["current_mlil"] = self.active_func.medium_level_il - for line in code.split("\n"): - self.interpreter.push(line) + for line in code.split(b'\n'): + self.interpreter.push(line.decode('charmap')) if self.locals["here"] != self.active_addr: if not self.active_view.file.navigate(self.active_view.file.view, self.locals["here"]): @@ -660,3 +661,4 @@ def redirect_stdio(): sys.stdin = _PythonScriptingInstanceInput(sys.stdin) sys.stdout = _PythonScriptingInstanceOutput(sys.stdout, False) sys.stderr = _PythonScriptingInstanceOutput(sys.stderr, True) + sys.excepthook = sys.__excepthook__ \ No newline at end of file diff --git a/python/setting.py b/python/setting.py index fea06140..355492aa 100644 --- a/python/setting.py +++ b/python/setting.py @@ -20,11 +20,11 @@ import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core # 2-3 compatibility -from six.moves import range +from binaryninja import range class Setting(object): @@ -113,7 +113,7 @@ class Setting(object): length.value = len(value) default_list = (ctypes.c_char_p * len(value))() for i in range(len(value)): - default_list[i] = value[i].encode('utf-8') + default_list[i] = value[i].encode('charmap') return core.BNSettingSetStringList(self.plugin_name, name, default_list, length, auto_flush) @@ -141,4 +141,4 @@ class Setting(object): core.BNSettingRemoveSettingGroup(self.plugin_name, auto_flush) def remove_setting(self, setting, auto_flush=True): - core.BNSettingRemoveSetting(self.plugin_name, setting, auto_flush) \ No newline at end of file + core.BNSettingRemoveSetting(self.plugin_name, setting, auto_flush) diff --git a/python/transform.py b/python/transform.py index e16c6bfc..1734d248 100644 --- a/python/transform.py +++ b/python/transform.py @@ -22,20 +22,19 @@ import traceback import ctypes import abc -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import log from binaryninja import databuffer from binaryninja import _binaryninjacore as core from binaryninja.enums import TransformType -#2-3 compatibility -from six import with_metaclass -from six.moves import range +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _TransformMetaClass(type): - @property def list(self): binaryninja._init_plugins() @@ -96,8 +95,6 @@ class TransformParameter(object): class Transform(with_metaclass(_TransformMetaClass, object)): - - from binaryninja import databuffer transform_type = None name = None long_name = None @@ -224,7 +221,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): def decode(self, input_buf, params = {}): input_buf = databuffer.DataBuffer(input_buf) output_buf = databuffer.DataBuffer() - keys = params.keys() + keys = list(params.keys()) param_buf = (core.BNTransformParameter * len(keys))() for i in range(0, len(keys)): data = databuffer.DataBuffer(params[keys[i]]) @@ -237,7 +234,7 @@ class Transform(with_metaclass(_TransformMetaClass, object)): def encode(self, input_buf, params = {}): input_buf = databuffer.DataBuffer(input_buf) output_buf = databuffer.DataBuffer() - keys = params.keys() + keys = list(params.keys()) param_buf = (core.BNTransformParameter * len(keys))() for i in range(0, len(keys)): data = databuffer.DataBuffer(params[keys[i]]) diff --git a/python/types.py b/python/types.py index 2ad8d2c2..e8ce7464 100644 --- a/python/types.py +++ b/python/types.py @@ -23,23 +23,26 @@ max_confidence = 255 import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType -#2-3 compatibility -from six.moves import range +# 2-3 compatibility +from binaryninja import range class QualifiedName(object): def __init__(self, name = []): if isinstance(name, str): self.name = [name] + self.byte_name = [name.encode('charmap')] elif isinstance(name, QualifiedName): self.name = name.name + self.byte_name = [n.encode('charmap') for n in name.name] else: - self.name = [i.decode('utf-8') for i in name] + self.name = [i.decode('charmap') for i in name] + self.byte_name = name def __str__(self): return "::".join(self.name) @@ -102,7 +105,7 @@ class QualifiedName(object): result = core.BNQualifiedName() name_list = (ctypes.c_char_p * len(self.name))() for i in range(0, len(self.name)): - name_list[i] = self.name[i] + name_list[i] = self.name[i].encode('charmap') result.name = name_list result.nameCount = len(self.name) return result @@ -1022,7 +1025,7 @@ def preprocess_source(source, filename=None, include_dirs=[]): filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() for i in range(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) + dir_buf[i] = include_dirs[i].encode('charmap') output = ctypes.c_char_p() errors = ctypes.c_char_p() result = core.BNPreprocessSource(source, filename, output, errors, dir_buf, len(include_dirs)) diff --git a/python/undoaction.py b/python/undoaction.py index 732d559a..7891bf54 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -22,14 +22,12 @@ import traceback import json import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import ActionType class UndoAction(object): - - name = None action_type = None _registered = False diff --git a/python/update.py b/python/update.py index 4c77b202..7f5d6f9c 100644 --- a/python/update.py +++ b/python/update.py @@ -21,18 +21,16 @@ import traceback import ctypes -# Binary Ninja components -- additional imports belong in the appropriate class +# Binary Ninja components from binaryninja import _binaryninjacore as core from binaryninja.enums import UpdateResult - -#2-3 compatibility -from six import with_metaclass -from six.moves import range +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _UpdateChannelMetaClass(type): - @property def list(self): binaryninja._init_plugins() @@ -99,7 +97,6 @@ class _UpdateChannelMetaClass(type): class UpdateProgressCallback(object): - def __init__(self, func): self.cb = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.c_ulonglong, ctypes.c_ulonglong)(self.callback) self.func = func @@ -114,7 +111,6 @@ class UpdateProgressCallback(object): class UpdateChannel(with_metaclass(_UpdateChannelMetaClass, object)): - def __init__(self, name, desc, ver): self.name = name self.description = desc diff --git a/scripts/install_api.py b/scripts/install_api.py index 53679ba5..3cc0ed0d 100755 --- a/scripts/install_api.py +++ b/scripts/install_api.py @@ -80,6 +80,6 @@ else: sys.exit(1) binaryninja_pth_path = os.path.join(install_path, 'binaryninja.pth') -open(binaryninja_pth_path, 'wb').write(api_path) +open(binaryninja_pth_path, 'wb').write(api_path.encode('charmap')) print("Binary Ninja API installed using {}".format(binaryninja_pth_path)) diff --git a/suite/binaries b/suite/binaries index 7d5d207d..ab6b1816 160000 --- a/suite/binaries +++ b/suite/binaries @@ -1 +1 @@ -Subproject commit 7d5d207de812ccd7c4648331b00fa936ef0a82c3 +Subproject commit ab6b18161a5b9ccd3588c88233f150fb6c7e2ce9 diff --git a/suite/generator.py b/suite/generator.py index b812b1b5..3302d118 100755 --- a/suite/generator.py +++ b/suite/generator.py @@ -10,24 +10,77 @@ import time unit_test_template = """#!/usr/bin/env python # This is an auto generated unit test file do not edit directly import os +import sys import unittest import pickle import zipfile import testcommon -import binaryninja import api_test import difflib +from collections import Counter +global verbose +verbose = False class TestBinaryNinjaAPI(unittest.TestCase): + # Returns a tuple of: + # bool : Two lists are equal + # string : The string diff + # Args: + # list + # list : (compare list one vs list two) + # string : anything additional wanted to be printed before the string diff + # bool : the ordering of the items in the two lists must be the same + def report(self, oracle, test, firstText='', strictOrdering = False): + stringDiff = "" + + equality = False + if not strictOrdering: + equality = (Counter(oracle) == Counter(test)) + else: + equality = (oracle == test) + + if equality: + return (True, '') + elif not strictOrdering: + try: + for elem in oracle: + test.remove(elem) + oracle.remove(elem) # If it's not in the test, it won't get here! + except ValueError: + pass + + differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) + skipped_lines = 0 + for delta in differ.compare(oracle, test): + if delta[0] == ' ': + skipped_lines += 1 + continue + if skipped_lines > 0: + stringDiff += "<---" + str(skipped_lines) + ' same lines--->\\n' + skipped_lines = 0 + delta = delta.replace(\'\\n\', '') + stringDiff += delta + \'\\n\' + + stringDiffList = stringDiff.split(\'\\n\') + + if len(stringDiffList) > 10: + if not verbose: + stringDiff = \'\\n\'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList[:10]) + stringDiff += \'\\n\\n### And ' + str(len(stringDiffList)) + " more lines, use '-v' to show ###" + elif not verbose: + stringDiff = \'\\n\'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList) + stringDiff = \'\\n\\n\' + firstText + stringDiff + return (equality, stringDiff) + @classmethod def setUpClass(self): self.builder = testcommon.TestBuilder("{3}") try: - #Python 2 does not have the encodings option - self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rUb"), errors="ignore") + # Python 2 does not have the encodings option + self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rb"), encoding='charmap') except TypeError: - self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "rU")) + self.oracle_test_data = pickle.load(open(os.path.join("{0}", "oracle.pkl"), "r")) self.verifybuilder = testcommon.VerifyBuilder("{3}") def run_binary_test(self, testfile): @@ -38,10 +91,10 @@ class TestBinaryNinjaAPI(unittest.TestCase): self.assertTrue(os.path.exists(testname + ".pkl"), "Test pickle doesn't exist") try: - #Python 2 does not have the encodings option - binary_oracle = pickle.load(open(testname + ".pkl", "rUb"), errors="ignore") + # Python 2 does not have the encodings option + binary_oracle = pickle.load(open(testname + ".pkl", "rb"), encoding='charmap') except TypeError: - binary_oracle = pickle.load(open(testname + ".pkl", "rU")) + binary_oracle = pickle.load(open(testname + ".pkl", "r")) test_builder = testcommon.BinaryViewTestBuilder(testname, "{3}") for method in test_builder.methods(): @@ -52,22 +105,16 @@ class TestBinaryNinjaAPI(unittest.TestCase): result = getattr(test_builder, method).__doc__ result += ":\\n" - d = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in d.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\\n' - skipped_lines = 0 - delta = delta.replace('\\n', '') - result += delta + '\\n' - self.assertTrue(False, result) + report = self.report(oracle, test, result) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle os.unlink(testname) {1}{2} if __name__ == "__main__": + if len(sys.argv) > 1: + if sys.argv[1] == '-v' or sys.argv[1] == '-V' or sys.argv[1] == '--verbose': + verbose = True + test_suite = unittest.defaultTestLoader.loadTestsFromModule(api_test) test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestBinaryNinjaAPI)) runner = unittest.TextTestRunner(verbosity=2) @@ -83,20 +130,8 @@ test_string = """ def {0}(self): oracle = self.oracle_test_data['{0}'] test = self.builder.{0}() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\\n' - skipped_lines = 0 - delta = delta.replace('\\n', '') - result += delta + '\\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle """ verify_string = """ @@ -108,7 +143,7 @@ verify_string = """ class OracleTestFile: def __init__(self, filename): self.f = open(filename + ".pkl", "wb") - self.pkl = pickle.Pickler(self.f) + self.pkl = pickle.Pickler(self.f, protocol=2) self.filename = filename self.oracle_test_data = {} @@ -131,7 +166,7 @@ class UnitTestFile: self.binary_tests = "" def close(self): - self.f.write(self.template.format(self.outdir, self.tests, self.binary_tests, self.test_store).encode('utf-8')) + self.f.write(self.template.format(self.outdir, self.tests, self.binary_tests, self.test_store).encode('charmap')) self.f.close() def add_verify(self, test_name): @@ -146,8 +181,6 @@ class UnitTestFile: quiet = False - - def myprint(stuff): if not quiet: print(stuff) diff --git a/suite/testcommon.py b/suite/testcommon.py index 1bbc0d47..ef85c053 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -1,14 +1,54 @@ import tempfile import pickle import os +import sys import zipfile import inspect import binaryninja as binja from binaryninja.binaryview import BinaryViewType, BinaryView from binaryninja.filemetadata import FileMetadata import subprocess -import traceback -import types +import re + + +# Dear people from the future: If you're adding tests or debuging an +# issue where python2 and python3 are producing different output +# for the same function and it's a issue of `longs`, run the output +# through this function. If it's a unicode/bytes issue, fix it in +# api/python/ +def fixOutput(outputList): + # Apply regular expression to detect python2 longs + splitList = [] + for elem in outputList: + if isinstance(elem, str): + splitList.append(re.split(r"((?<=[\[ ])0x[\da-f]+L|[\d]+L)", elem)) + else: + splitList.append(elem) + + # Resolve application of regular expression + result = [] + for elem in splitList: + if isinstance(elem, list): + newElem = [] + for item in elem: + if len(item) > 1 and item[-1] == 'L': + newElem.append(item[:-1]) + else: + newElem.append(item) + result.append(''.join(newElem)) + else: + result.append(elem) + return result + + +# Alright so this one is here for Binja functions that output +def fixSet(string): + # Apply regular expression + splitList = (re.split(r"((?<=))", string)) + if len(splitList) > 1: + return splitList[0] + ', '.join(sorted(splitList[1].split(', '))) + splitList[2] + else: + return string def get_file_list(test_store): @@ -16,13 +56,12 @@ def get_file_list(test_store): for root, dir, files in os.walk(test_store): for file in files: all_files.append(os.path.join(root, file)) - return all_files def remove_low_confidence(type_string): low_confidence_types = ["int32_t", "void"] for lct in low_confidence_types: - type_string = type_string.replace(lct + " ", '') # done to resolve confidence ties + type_string = type_string.replace(lct + " ", '') # done to resolve confidence ties return type_string class Builder(object): @@ -66,15 +105,24 @@ class BinaryViewTestBuilder(Builder): def test_function_starts(self): """Function starts list doesnt match""" - return ["Function start: " + hex(x.start) for x in self.bv.functions] + result = [] + for x in self.bv.functions: + result.append("Function start: " + hex(x.start)) + return fixOutput(result) def test_function_symbol_names(self): """Function.symbol.name list doesnt match""" - return ["Symbol: " + x.symbol.name + ' ' + str(x.symbol.type) + ' ' + hex(x.symbol.address) for x in self.bv.functions] + result = [] + for x in self.bv.functions: + result.append("Symbol: " + x.symbol.name + ' ' + str(x.symbol.type) + ' ' + hex(x.symbol.address)) + return fixOutput(result) def test_function_can_return(self): """Function.can_return list doesnt match""" - return ["function name: " + x.symbol.name + ' type: ' + str(x.symbol.type) + ' address: ' + hex(x.symbol.address) + ' can_return: ' + str(bool(x.can_return)) for x in self.bv.functions] + result = [] + for x in self.bv.functions: + result.append("function name: " + x.symbol.name + ' type: ' + str(x.symbol.type) + ' address: ' + hex(x.symbol.address) + ' can_return: ' + str(bool(x.can_return))) + return fixOutput(result) def test_function_basic_blocks(self): """Function basic_block list doesnt match (start, end, has_undetermined_outgoing_edges)""" @@ -85,32 +133,31 @@ class BinaryViewTestBuilder(Builder): for anno in func.get_block_annotations(bb.start): bblist.append("basic block {} function annotation: ".format(str(bb)) + str(anno)) bblist.append("basic block {} test get self: ".format(str(bb)) + str(func.get_basic_block_at(bb.start))) - return bblist + return fixOutput(bblist) def test_function_low_il_basic_blocks(self): - """"Function low_il_basic_block list doesnt match""" + """Function low_il_basic_block list doesnt match""" ilbblist = [] for func in self.bv.functions: for bb in func.low_level_il.basic_blocks: ilbblist.append("LLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing edges: ' + str(len(bb.outgoing_edges))) - return ilbblist + return fixOutput(ilbblist) def test_function_med_il_basic_blocks(self): - """"Function med_il_basic_block list doesn't match""" + """Function med_il_basic_block list doesn't match""" ilbblist = [] for func in self.bv.functions: for bb in func.medium_level_il.basic_blocks: ilbblist.append("MLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing_edges: ' + str(len(bb.outgoing_edges))) - return ilbblist + return fixOutput(ilbblist) def test_symbols(self): - """"Symbols list doesn't match""" + """Symbols list doesn't match""" return ["Symbol: " + str(i) for i in sorted(self.bv.symbols)] def test_strings(self): """Strings list doesn't match""" - return ["String: " + x.value + ' type: ' + str(x.type) + ' at: ' + hex(x.start) for x in self.bv.strings] - + return fixOutput(["String: " + str(x.value) + ' type: ' + str(x.type) + ' at: ' + hex(x.start) for x in self.bv.strings]) def test_low_il_instructions(self): """LLIL instructions produced different output""" @@ -126,9 +173,7 @@ class BinaryViewTestBuilder(Builder): retinfo.append("Postfix operands: " + str(ins.postfix_operands)) retinfo.append("SSA form: " + str(ins.ssa_form)) retinfo.append("Non-SSA form: " + str(ins.non_ssa_form)) - - return retinfo - + return fixOutput(retinfo) def test_low_il_ssa(self): """LLIL ssa produced different output""" @@ -151,9 +196,7 @@ class BinaryViewTestBuilder(Builder): retinfo.append("SSA instruction index: " + str(func.get_ssa_instruction_index(tempind))) retinfo.append("MLIL instruction index: " + str(func.get_medium_level_il_instruction_index(ins.instr_index))) retinfo.append("Mapped MLIL instruction index: " + str(func.get_mapped_medium_level_il_instruction_index(ins.instr_index))) - - return retinfo - + return fixOutput(retinfo) def test_med_il_instructions(self): """MLIL instructions produced different output""" @@ -165,18 +208,33 @@ class BinaryViewTestBuilder(Builder): retinfo.append("LLIL: " + str(ins.low_level_il)) retinfo.append("Value: " + str(ins.value)) retinfo.append("Possible values: " + str(ins.possible_values)) - retinfo.append("Branch dependence: " + str(ins.branch_dependence)) - retinfo.append("Prefix operands: " + str(sorted([str(i) for i in ins.prefix_operands]))) - retinfo.append("Postfix operands: " + str(sorted([str(i) for i in ins.postfix_operands]))) + retinfo.append("Branch dependence: " + str(sorted(ins.branch_dependence.items()))) + + prefixList = [] + for i in ins.prefix_operands: + if isinstance(i, float) and 'e' in str(i): + prefixList.append(str(round(i, 21))) + elif isinstance(i, float): + prefixList.append(str(round(i, 11))) + else: + prefixList.append(str(i)) + retinfo.append("Prefix operands: " + str(sorted(prefixList))) + postfixList = [] + for i in ins.prefix_operands: + if isinstance(i, float) and 'e' in str(i): + postfixList.append(str(round(i, 21))) + elif isinstance(i, float): + postfixList.append(str(round(i, 11))) + else: + postfixList.append(str(i)) + + retinfo.append("Postfix operands: " + str(sorted(postfixList))) retinfo.append("SSA form: " + str(ins.ssa_form)) retinfo.append("Non-SSA form" + str(ins.non_ssa_form)) - - return retinfo - - + return fixOutput(retinfo) def test_med_il_vars(self): - """"Function med_il_vars doesn't match""" + """Function med_il_vars doesn't match""" varlist = [] for func in self.bv.functions: func = func.medium_level_il @@ -184,14 +242,13 @@ class BinaryViewTestBuilder(Builder): for instruction in bb: instruction = instruction.ssa_form for var in (instruction.vars_read + instruction.vars_written): - #varlist.append((func.get_var_uses(var), func.get_var_definitions(var))) if hasattr(var, "var"): varlist.append("SSA var definition: " + str(func.get_ssa_var_definition(var))) varlist.append("SSA var uses: " + str(func.get_ssa_var_uses(var))) varlist.append("SSA var value: " + str(func.get_ssa_var_value(var))) - varlist.append("SSA var possible values: " + str(instruction.get_ssa_var_possible_values(var))) + varlist.append("SSA var possible values: " + fixSet(str(instruction.get_ssa_var_possible_values(var)))) varlist.append("SSA var version: " + str(instruction.get_ssa_var_version)) - return varlist + return fixOutput(varlist) def test_function_stack(self): """Function stack produced different output""" @@ -211,32 +268,26 @@ class BinaryViewTestBuilder(Builder): funcinfo.append("Sample stack var: " + str(func.get_stack_var_at_frame_offset(0, 0))) func.delete_user_stack_var(0) func.delete_auto_stack_var(0) - return funcinfo def test_function_llil(self): """Function LLIL produced different output""" retinfo = [] - for func in self.bv.functions: for llilbb in func.llil_basic_blocks: retinfo.append("LLIL basic block: " + str(llilbb)) for llilins in func.llil_instructions: retinfo.append("LLIL instruction: " + str(llilins)) - for mlilbb in func.mlil_basic_blocks: retinfo.append("MLIL basic block: " + str(mlilbb)) for mlilins in func.mlil_instructions: retinfo.append("MLIL instruction: " + str(mlilins)) - for ins in func.instructions: - retinfo.append("Instructiin: {}: ".format(hex(ins[1])) + ''.join([str(i) for i in ins[0]])) - - return retinfo - + retinfo.append("Instruction: {}: ".format(hex(ins[1])) + ''.join([str(i) for i in ins[0]])) + return fixOutput(retinfo) def test_functions_attributes(self): - """"Function attributes don't match""" + """Function attributes don't match""" funcinfo = [] for func in self.bv.functions: func.comment = "testcomment " + func.name @@ -284,9 +335,7 @@ class BinaryViewTestBuilder(Builder): token = str(token) token = remove_low_confidence(token) funcinfo.append("Function {} type token: ".format(func.name) + str(token)) - - - return funcinfo + return fixOutput(funcinfo) def test_BinaryView(self): """BinaryView produced different results""" @@ -309,11 +358,12 @@ class BinaryViewTestBuilder(Builder): retinfo.append("BV entry point: " + hex(self.bv.entry_point)) retinfo.append("BV start: " + hex(self.bv.start)) retinfo.append("BV length: " + hex(len(self.bv))) - return retinfo + + return fixOutput(retinfo) class TestBuilder(Builder): - """ The TestBuilder is for tests that need to be checked against + """ The TestBuilder is for tests that need to be checked againsttest_BinaryView stored oracle data that isn't from a binary. These test are generated on your local machine then run again on the build machine to verify correctness. @@ -335,23 +385,81 @@ class TestBuilder(Builder): """unexpected assemble result""" result = [] # success cases - result.append("x86 assembly: " + str(binja.Architecture["x86"].assemble("xor eax, eax"))) - result.append("x86_64 assembly: " + str(binja.Architecture["x86_64"].assemble("xor rax, rax"))) - result.append("mips32 assembly: " + str(binja.Architecture["mips32"].assemble("move $ra, $zero"))) - result.append("mipsel32 assembly: " + str(binja.Architecture["mipsel32"].assemble("move $ra, $zero"))) - result.append("armv7 assembly: " + str(binja.Architecture["armv7"].assemble("str r2, [sp, #-0x4]!"))) - result.append("aarch64 assembly: " + str(binja.Architecture["aarch64"].assemble("mov x0, x0"))) - result.append("thumb2 assembly: " + str(binja.Architecture["thumb2"].assemble("ldr r4, [r4]"))) - result.append("thumb2eb assembly: " + str(binja.Architecture["thumb2eb"].assemble("ldr r4, [r4]"))) + + strResult = binja.Architecture["x86"].assemble("xor eax, eax") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("x86 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("x86 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["x86_64"].assemble("xor rax, rax") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("x86_64 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("x86_64 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["mips32"].assemble("move $ra, $zero") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("mips32 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("mips32 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["mipsel32"].assemble("move $ra, $zero") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("mipsel32 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("mipsel32 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["armv7"].assemble("str r2, [sp, #-0x4]!") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("armv7 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("armv7 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["aarch64"].assemble("mov x0, x0") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("aarch64 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("aarch64 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["thumb2"].assemble("ldr r4, [r4]") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("thumb2 assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("thumb2 assembly: " + repr(str(strResult))) + strResult = binja.Architecture["thumb2eb"].assemble("ldr r4, [r4]") + if sys.version_info.major == 3 and not strResult[0] is None: + result.append("thumb2eb assembly: " + "'" + str(strResult)[2:-1] + "'") + else: + result.append("thumb2eb assembly: " + repr(str(strResult))) + # fail cases - result.append("x86 assembly: " + str(binja.Architecture["x86"].assemble("thisisnotaninstruction"))) - result.append("x86_64 assembly: " + str(binja.Architecture["x86_64"].assemble("thisisnotaninstruction"))) - result.append("mips32 assembly: " + str(binja.Architecture["mips32"].assemble("thisisnotaninstruction"))) - result.append("mipsel32 assembly: " + str(binja.Architecture["mipsel32"].assemble("thisisnotaninstruction"))) - result.append("armv7 assembly: " + str(binja.Architecture["armv7"].assemble("thisisnotaninstruction"))) - result.append("aarch64 assembly: " + str(binja.Architecture["aarch64"].assemble("thisisnotaninstruction"))) - result.append("thumb2 assembly: " + str(binja.Architecture["thumb2"].assemble("thisisnotaninstruction"))) - result.append("thumb2eb assembly: " + str(binja.Architecture["thumb2eb"].assemble("thisisnotaninstruction"))) + try: + strResult = binja.Architecture["x86"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'x86'") + try: + strResult = binja.Architecture["x86_64"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'x86_64'") + try: + strResult = binja.Architecture["mips32"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'mips32'") + try: + strResult = binja.Architecture["mipsel32"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'mipsel32'") + try: + strResult = binja.Architecture["armv7"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'armv7'") + try: + strResult = binja.Architecture["aarch64"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'aarch64'") + try: + strResult = binja.Architecture["thumb2"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'thumb2'") + try: + strResult = binja.Architecture["thumb2eb"].assemble("thisisnotaninstruction") + except ValueError: + result.append("Assemble Failed As Expected; 'thisisnotaninstruction' is not an instruction on 'thumb2eb'") return result def test_Architecture(self): @@ -385,8 +493,6 @@ class TestBuilder(Builder): retinfo.append("Instruction: " + str(ins)) return retinfo - - def test_Function(self): """Function produced different result""" inttype = binja.Type.int(4) @@ -433,7 +539,6 @@ class TestBuilder(Builder): def test_Types(self): """Types produced different result""" - file_name = os.path.join(self.test_store, "helloworld") bv = binja.BinaryViewType.get_view_of_file(file_name) preprocessed = binja.preprocess_source(""" @@ -445,7 +550,7 @@ class TestBuilder(Builder): long long bar1 = 2; #endif """) - source = '\n'.join([i.decode("utf-8") for i in preprocessed[0].split('\n') if not b"#line" in i and len(i) > 0]) + source = '\n'.join([i.decode('utf-8') for i in preprocessed[0].split(b'\n') if not b'#line' in i and len(i) > 0]) typelist = bv.platform.parse_types_from_source(source) inttype = binja.Type.int(4) @@ -464,12 +569,11 @@ class TestBuilder(Builder): def test_Plugin_bin_info(self): """print_syscalls plugin produced different result""" - file_name = os.path.join(self.test_store, "helloworld") self.unpackage_file(file_name) result = subprocess.Popen(["python", os.path.join(self.examples_dir, "bin_info.py"), file_name], stdout=subprocess.PIPE).communicate()[0] # normalize line endings and path sep - return [result.replace(b"\\", b"/").replace(b"\r\n", b"\n")] + return [result.replace(b"\\", b"/").replace(b"\r\n", b"\n").decode("charmap")] def test_linear_disassembly(self): """linear_disassembly produced different result""" @@ -486,7 +590,6 @@ class TestBuilder(Builder): def test_partial_register_dataflow(self): """partial_register_dataflow produced different results""" - file_name = os.path.join(self.test_store, "partial_register_dataflow") self.unpackage_file(file_name) result = [] @@ -505,7 +608,6 @@ class TestBuilder(Builder): del bv finally: os.unlink(file_name) - return result @@ -524,20 +626,13 @@ class TestBuilder(Builder): retinfo.append("LLIL second stack element: " + str(ins.get_stack_contents_after(0,1))) retinfo.append("LLIL possible first stack element: " + str(ins.get_possible_stack_contents(0,1))) retinfo.append("LLIL possible second stack element: " + str(ins.get_possible_stack_contents_after(0,1))) - - for flag in flag_list: retinfo.append("LLIL flag {} value at: ".format(flag, hex(ins.address)) + str(ins.get_flag_value(flag))) retinfo.append("LLIL flag {} value after {}: ".format(flag, hex(ins.address)) + str(ins.get_flag_value_after(flag))) - retinfo.append("LLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag))) retinfo.append("LLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values_after(flag))) - - os.unlink(file_name) - os.unlink(file_name) - - return retinfo + return fixOutput(retinfo) def test_med_il_stack(self): """MLIL stack produced different output""" @@ -555,25 +650,21 @@ class TestBuilder(Builder): retinfo.append("MLIL second stack element: " + str(ins.get_stack_contents_after(0, 1))) retinfo.append("MLIL possible first stack element: " + str(ins.get_possible_stack_contents(0, 1))) retinfo.append("MLIL possible second stack element: " + str(ins.get_possible_stack_contents_after(0, 1))) - + for reg in reg_list: retinfo.append("MLIL reg {} var at {}: ".format(reg, hex(ins.address)) + str(ins.get_var_for_reg(reg))) retinfo.append("MLIL reg {} value at {}: ".format(reg, hex(ins.address)) + str(ins.get_reg_value(reg))) retinfo.append("MLIL reg {} value after {}: ".format(reg, hex(ins.address)) + str(ins.get_reg_value_after(reg))) - retinfo.append("MLIL reg {} possible value at {}: ".format(reg, hex(ins.address)) + str(ins.get_possible_reg_values(reg))) - retinfo.append("MLIL reg {} possible value after {}: ".format(reg, hex(ins.address)) + str(ins.get_possible_reg_values_after(reg))) - + retinfo.append("MLIL reg {} possible value at {}: ".format(reg, hex(ins.address)) + fixSet(str(ins.get_possible_reg_values(reg)))) + retinfo.append("MLIL reg {} possible value after {}: ".format(reg, hex(ins.address)) + fixSet(str(ins.get_possible_reg_values_after(reg)))) for flag in flag_list: retinfo.append("MLIL flag {} value at: ".format(flag, hex(ins.address)) + str(ins.get_flag_value(flag))) retinfo.append("MLIL flag {} value after {}: ".format(flag, hex(ins.address)) + str(ins.get_flag_value_after(flag))) - retinfo.append("MLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag))) - retinfo.append("MLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + str(ins.get_possible_flag_values(flag))) - + retinfo.append("MLIL flag {} possible value at {}: ".format(flag, hex(ins.address)) + fixSet(str(ins.get_possible_flag_values(flag)))) + retinfo.append("MLIL flag {} possible value after {}: ".format(flag, hex(ins.address)) + fixSet(str(ins.get_possible_flag_values(flag)))) os.unlink(file_name) - - return retinfo - + return fixOutput(retinfo) def test_events(self): """Event failure""" @@ -582,11 +673,9 @@ class TestBuilder(Builder): bv = binja.BinaryViewType['ELF'].open(file_name) results = [] - def simple_complete(self): results.append("analysis complete") - evt = binja.AnalysisCompletionEvent(bv, simple_complete) class NotifyTest(binja.BinaryDataNotification): @@ -643,7 +732,13 @@ class TestBuilder(Builder): def string_found(self, view, string_type, offset, length): def string_found_complete(self): - results.append("string found: offset {0} length {1}".format(hex(offset), hex(length))) + offset = hex(offset) + length = hex(length) + if offset[-1] == 'L': + offset = offset[:-1] + if length[-1] == 'L': + length = length[:-1] + results.append("string found: offset {0} length {1}".format(offset, length)) evt = binja.AnalysisCompletionEvent(bv, string_found_complete) def string_removed(self, view, string_type, offset, length): @@ -666,7 +761,6 @@ class TestBuilder(Builder): bv.register_notification(test) sacrificial_addr = 0x84fc - type, name = bv.parse_type_string("int foo") type_id = type.generate_auto_type_id("source", name) bv.define_type(type_id, name, type) @@ -684,10 +778,10 @@ class TestBuilder(Builder): bv.remove(sacrificial_addr, 4) bv.update_analysis_and_wait() - + bv.unregister_notification(test) - return sorted(results) + return fixOutput(sorted(results)) def unpackage(self, fileName): testname = None diff --git a/suite/unit.py b/suite/unit.py index 9a59b13f..fe2c4b8c 100644 --- a/suite/unit.py +++ b/suite/unit.py @@ -1,24 +1,77 @@ #!/usr/bin/env python # This is an auto generated unit test file do not edit directly import os +import sys import unittest import pickle import zipfile import testcommon -import binaryninja import api_test import difflib +from collections import Counter +global verbose +verbose = False class TestBinaryNinjaAPI(unittest.TestCase): + # Returns a tuple of: + # bool : Two lists are equal + # string : The string diff + # Args: + # list + # list : (compare list one vs list two) + # string : anything additional wanted to be printed before the string diff + # bool : the ordering of the items in the two lists must be the same + def report(self, oracle, test, firstText='', strictOrdering = False): + stringDiff = "" + + equality = False + if not strictOrdering: + equality = (Counter(oracle) == Counter(test)) + else: + equality = (oracle == test) + + if equality: + return (True, '') + elif not strictOrdering: + try: + for elem in oracle: + test.remove(elem) + oracle.remove(elem) # If it's not in the test, it won't get here! + except ValueError: + pass + + differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) + skipped_lines = 0 + for delta in differ.compare(oracle, test): + if delta[0] == ' ': + skipped_lines += 1 + continue + if skipped_lines > 0: + stringDiff += "<---" + str(skipped_lines) + ' same lines--->\n' + skipped_lines = 0 + delta = delta.replace('\n', '') + stringDiff += delta + '\n' + + stringDiffList = stringDiff.split('\n') + + if len(stringDiffList) > 10: + if not verbose: + stringDiff = '\n'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList[:10]) + stringDiff += '\n\n### And ' + str(len(stringDiffList)) + " more lines, use '-v' to show ###" + elif not verbose: + stringDiff = '\n'.join(line if len(line) <= 100 else line[:100] + "...and " + str(len(line) - 100) + " more characters" for line in stringDiffList) + stringDiff = '\n\n' + firstText + stringDiff + return (equality, stringDiff) + @classmethod def setUpClass(self): self.builder = testcommon.TestBuilder("suite/binaries/test_corpus") try: - #Python 2 does not have the encodings option - self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rUb"), errors="ignore") + # Python 2 does not have the encodings option + self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rb"), encoding='charmap') except TypeError: - self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rU")) + self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "r")) self.verifybuilder = testcommon.VerifyBuilder("suite/binaries/test_corpus") def run_binary_test(self, testfile): @@ -29,10 +82,10 @@ class TestBinaryNinjaAPI(unittest.TestCase): self.assertTrue(os.path.exists(testname + ".pkl"), "Test pickle doesn't exist") try: - #Python 2 does not have the encodings option - binary_oracle = pickle.load(open(testname + ".pkl", "rUb"), errors="ignore") + # Python 2 does not have the encodings option + binary_oracle = pickle.load(open(testname + ".pkl", "rb"), encoding='charmap') except TypeError: - binary_oracle = pickle.load(open(testname + ".pkl", "rU")) + binary_oracle = pickle.load(open(testname + ".pkl", "r")) test_builder = testcommon.BinaryViewTestBuilder(testname, "suite/binaries/test_corpus") for method in test_builder.methods(): @@ -43,271 +96,93 @@ class TestBinaryNinjaAPI(unittest.TestCase): result = getattr(test_builder, method).__doc__ result += ":\n" - d = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in d.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - self.assertTrue(False, result) + report = self.report(oracle, test, result) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle os.unlink(testname) def test_Architecture(self): oracle = self.oracle_test_data['test_Architecture'] test = self.builder.test_Architecture() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Architecture_list(self): oracle = self.oracle_test_data['test_Architecture_list'] test = self.builder.test_Architecture_list() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Assemble(self): oracle = self.oracle_test_data['test_Assemble'] test = self.builder.test_Assemble() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_BinaryViewType_list(self): oracle = self.oracle_test_data['test_BinaryViewType_list'] test = self.builder.test_BinaryViewType_list() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Enumeration(self): oracle = self.oracle_test_data['test_Enumeration'] test = self.builder.test_Enumeration() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Function(self): oracle = self.oracle_test_data['test_Function'] test = self.builder.test_Function() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Plugin_bin_info(self): oracle = self.oracle_test_data['test_Plugin_bin_info'] test = self.builder.test_Plugin_bin_info() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Struct(self): oracle = self.oracle_test_data['test_Struct'] test = self.builder.test_Struct() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_Types(self): oracle = self.oracle_test_data['test_Types'] test = self.builder.test_Types() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_events(self): oracle = self.oracle_test_data['test_events'] test = self.builder.test_events() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_linear_disassembly(self): oracle = self.oracle_test_data['test_linear_disassembly'] test = self.builder.test_linear_disassembly() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_low_il_stack(self): oracle = self.oracle_test_data['test_low_il_stack'] test = self.builder.test_low_il_stack() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_med_il_stack(self): oracle = self.oracle_test_data['test_med_il_stack'] test = self.builder.test_med_il_stack() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_partial_register_dataflow(self): oracle = self.oracle_test_data['test_partial_register_dataflow'] test = self.builder.test_partial_register_dataflow() - result = "" - differ = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK) - skipped_lines = 0 - for delta in differ.compare(test, oracle): - if delta[0] == ' ': - skipped_lines += 1 - continue - if skipped_lines > 0: - result += "<---" + str(skipped_lines) + ' same lines--->\n' - skipped_lines = 0 - delta = delta.replace('\n', '') - result += delta + '\n' - - self.assertTrue(oracle == test, result) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle def test_verify_BNDB_round_trip(self): self.assertTrue(self.verifybuilder.test_verify_BNDB_round_trip(), self.test_verify_BNDB_round_trip.__doc__) @@ -386,6 +261,10 @@ class TestBinaryNinjaAPI(unittest.TestCase): if __name__ == "__main__": + if len(sys.argv) > 1: + if sys.argv[1] == '-v' or sys.argv[1] == '-V' or sys.argv[1] == '--verbose': + verbose = True + test_suite = unittest.defaultTestLoader.loadTestsFromModule(api_test) test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestBinaryNinjaAPI)) runner = unittest.TextTestRunner(verbosity=2) -- cgit v1.3.1 From 975249d22e10360ed2c4c0bcea151c39d9446b0a Mon Sep 17 00:00:00 2001 From: KyleMiles Date: Thu, 5 Jul 2018 18:28:59 -0400 Subject: Rebased so commit history is correct now --- .gitignore | 6 - python/__init__.py | 1 + python/downloadprovider.py | 1 - python/examples/README.md | 56 +++ python/examples/angr_plugin.py | 153 +++++++ python/examples/arch_hook.py | 16 + python/examples/bin_info.py | 76 ++++ python/examples/breakpoint.py | 50 +++ python/examples/export_svg.py | 224 ++++++++++ python/examples/instruction_iterator.py | 53 +++ python/examples/jump_table.py | 86 ++++ python/examples/nds.py | 120 ++++++ python/examples/nes.py | 650 ++++++++++++++++++++++++++++++ python/examples/notification_callbacks.py | 74 ++++ python/examples/nsf.py | 145 +++++++ python/examples/print_syscalls.py | 55 +++ python/examples/version_switcher.py | 150 +++++++ python/function.py | 14 +- python/plugin.py | 32 +- suite/generator.py | 1 + suite/oracle.pkl | Bin 9098577 -> 440689 bytes suite/testcommon.py | 6 +- suite/unit.py | 7 +- 23 files changed, 1937 insertions(+), 39 deletions(-) create mode 100644 python/examples/README.md create mode 100644 python/examples/angr_plugin.py create mode 100644 python/examples/arch_hook.py create mode 100644 python/examples/bin_info.py create mode 100644 python/examples/breakpoint.py create mode 100755 python/examples/export_svg.py create mode 100644 python/examples/instruction_iterator.py create mode 100644 python/examples/jump_table.py create mode 100644 python/examples/nds.py create mode 100644 python/examples/nes.py create mode 100644 python/examples/notification_callbacks.py create mode 100644 python/examples/nsf.py create mode 100644 python/examples/print_syscalls.py create mode 100644 python/examples/version_switcher.py (limited to 'python/plugin.py') diff --git a/.gitignore b/.gitignore index eff64eb4..302ad960 100644 --- a/.gitignore +++ b/.gitignore @@ -33,14 +33,8 @@ api-docs/source/index.rst .coverage # Make generator -libcrypto.so.1.0.2 -libcurl.so.4 -libssl.so.1.0.2 plugins/ python/examples/binaryninja/ -python/libcrypto.so.1.0.2 -python/libcurl.so.4 -python/libssl.so.1.0.2 python/plugins/ python/types/ suite/binaryninja/ diff --git a/python/__init__.py b/python/__init__.py index e1288b0a..36ed4f0d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -108,6 +108,7 @@ from binaryninja.lineardisassembly import * from binaryninja.undoaction import * from binaryninja.highlight import * from binaryninja.scriptingprovider import * +from binaryninja.downloadprovider import * from binaryninja.pluginmanager import * from binaryninja.setting import * from binaryninja.metadata import * diff --git a/python/downloadprovider.py b/python/downloadprovider.py index c714cb98..09abd516 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -20,7 +20,6 @@ import abc -import code import ctypes import sys import traceback diff --git a/python/examples/README.md b/python/examples/README.md new file mode 100644 index 00000000..43af34be --- /dev/null +++ b/python/examples/README.md @@ -0,0 +1,56 @@ +# Binary Ninja Python API Examples + +The following examples demonstrate some of the Binary Ninja API. They include both stand-alone examples that directly call into the core without a GUI, as well as examples meant to be loaded as plugins available from the UI. + +## Stand-alone + +These plugins only operate when run directly outside of the UI + +* bin_info.py - general binary information +* print_syscalls.py - extract syscall numbers from IL on specified file. Can be run both headless and in Binary Ninja +* version_switcher.py - uses the update API to see raw version notes and manually downgrade or upgrade +* instruction_iterator.py - very simple plugin that iterates through functions, blocks, and instructions + +To use the stand-alone Python examples, make sure your `PYTHON_PATH` includes the API, as shown below. Please note, this is a feature that requires the "GUI-less processing" capability not available in the personal edition. In the personal edition, all scripts must by run from the integrated python console (follow the directions below under "Loading Plugins" section) + +``` +PYTHONPATH=$PYTHONPATH:/Applications/Binary\ Ninja.app/Contents/Resources/python +``` + +## GUI Plugins + +These plugins require the UI to be running + +* breakpoint.py - small example showing how to modify a file and register a GUI menu item +* jump_table.py - heuristic based jump table detection for when the data-flow based computation fails, triggered by right-clicking on the location where the jump value is computed +* angr_plugin.py - a plugin to demonstrate both background threads, the simplified plugin UI elements, and highlighting +* export_svg.py - exports the graph view of a function to an SVG file for including in reports + +## Both + +These plugins are able to operate in either the GUI or as stand-alone plugins + +* nes.py - 6502 CPU architecture including LLIL lifting and `.NES` file format parser + + +## Loading Plugins + +Plugins are meant to be loaded into a running Binary Ninja GUI and should either be copied or symlinked into the appropriate plugin folder. You'll need to then re-start Binary Ninja. + +### OSX + +``` +~/Library/Application Support/Binary Ninja/plugins +``` + +### Windows + +``` +%APPDATA%\Binary Ninja\plugins +``` + +### Linux + +``` +~/.binaryninja/plugins +``` diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py new file mode 100644 index 00000000..26f8040c --- /dev/null +++ b/python/examples/angr_plugin.py @@ -0,0 +1,153 @@ +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +# This plugin assumes angr is already installed and available on the system. See the angr documentation +# for information about installing angr. It should be installed using the virtualenv method. +# +# This plugin is currently only known to work on Linux using virtualenv. Switch to the virtual environment +# (using a command such as "workon angr"), then run the Binary Ninja UI from the command line. +# +# This method is known to fail on Mac OS X as the virtualenv used by angr does not appear to provide a +# way to automatically link to the correct version of Python, even when running the UI from within the +# virtual environment. A later update may allow for a manual override to link to the required version +# of Python. + +import tempfile +import logging +import os + +__name__ = "__console__" # angr looks for this, it won't load from within a UI without it + +import angr +# For the lazy instead you can just import everything 'from binaryninja import *'' +from binaryninja.binaryview import BinaryView +from binaryninja.plugin import BackgroundTaskThread, PluginCommand +from binaryninja.interaction import show_plain_text_report, show_message_box +from binaryninja.highlight import HighlightColor +from binaryninja.enums import HighlightStandardColor, MessageBoxButtonSet, MessageBoxIcon + +# Disable warning logs as they show up as errors in the UI +logging.disable(logging.WARNING) + +# Create sets in the BinaryView's data field to store the desired path for each view +BinaryView.set_default_session_data("angr_find", set()) +BinaryView.set_default_session_data("angr_avoid", set()) + + +def escaped_output(str): + return '\n'.join([s.encode("string_escape") for s in str.split('\n')]) + + +# Define a background thread object for solving in the background +class Solver(BackgroundTaskThread): + def __init__(self, find, avoid, view): + BackgroundTaskThread.__init__(self, "Solving with angr...", True) + self.find = tuple(find) + self.avoid = tuple(avoid) + self.view = view + + # Write the binary to disk so that the angr API can read it + self.binary = tempfile.NamedTemporaryFile() + self.binary.write(view.file.raw.read(0, len(view.file.raw))) + self.binary.flush() + + def run(self): + # Create an angr project and an explorer with the user's settings + p = angr.Project(self.binary.name) + e = p.surveyors.Explorer(find = self.find, avoid = self.avoid) + + # Solve loop + while not e.done: + if self.cancelled: + # Solve cancelled, show results if there were any + if len(e.found) > 0: + break + return + + # Perform the next step in the solve + e.step() + + # Update status + active_count = len(e.active) + found_count = len(e.found) + + progress = "Solving with angr (%d active path%s" % (active_count, "s" if active_count != 1 else "") + if found_count > 0: + progress += ", %d path%s found" % (found_count, "s" if found_count != 1 else "") + self.progress = progress + ")..." + + # Solve complete, show report + text_report = "Found %d path%s.\n\n" % (len(e.found), "s" if len(e.found) != 1 else "") + i = 1 + for f in e.found: + text_report += "Path %d\n" % i + "=" * 10 + "\n" + text_report += "stdin:\n" + escaped_output(f.state.posix.dumps(0)) + "\n\n" + text_report += "stdout:\n" + escaped_output(f.state.posix.dumps(1)) + "\n\n" + text_report += "stderr:\n" + escaped_output(f.state.posix.dumps(2)) + "\n\n" + i += 1 + + name = self.view.file.filename + if len(name) > 0: + show_plain_text_report("Results from angr - " + os.path.basename(self.view.file.filename), text_report) + else: + show_plain_text_report("Results from angr", text_report) + + +def find_instr(bv, addr): + # Highlight the instruction in green + blocks = bv.get_basic_blocks_at(addr) + for block in blocks: + block.set_auto_highlight(HighlightColor(HighlightStandardColor.GreenHighlightColor, alpha = 128)) + block.function.set_auto_instr_highlight(addr, HighlightStandardColor.GreenHighlightColor) + + # Add the instruction to the list associated with the current view + bv.session_data.angr_find.add(addr) + + +def avoid_instr(bv, addr): + # Highlight the instruction in red + blocks = bv.get_basic_blocks_at(addr) + for block in blocks: + block.set_auto_highlight(HighlightColor(HighlightStandardColor.RedHighlightColor, alpha = 128)) + block.function.set_auto_instr_highlight(addr, HighlightStandardColor.RedHighlightColor) + + # Add the instruction to the list associated with the current view + bv.session_data.angr_avoid.add(addr) + + +def solve(bv): + if len(bv.session_data.angr_find) == 0: + show_message_box("Angr Solve", "You have not specified a goal instruction.\n\n" + + "Please right click on the goal instruction and select \"Find Path to This Instruction\" to " + + "continue.", MessageBoxButtonSet.OKButtonSet, MessageBoxIcon.ErrorIcon) + return + + # Start a solver thread for the path associated with the view + s = Solver(bv.session_data.angr_find, bv.session_data.angr_avoid, bv) + s.start() + + +# Register commands for the user to interact with the plugin +PluginCommand.register_for_address("Find Path to This Instruction", + "When solving, find a path that gets to this instruction", find_instr) +PluginCommand.register_for_address("Avoid This Instruction", + "When solving, avoid paths that reach this instruction", avoid_instr) +PluginCommand.register("Solve With Angr", "Attempt to solve for a path that satisfies the constraints given", solve) diff --git a/python/examples/arch_hook.py b/python/examples/arch_hook.py new file mode 100644 index 00000000..452bd2b6 --- /dev/null +++ b/python/examples/arch_hook.py @@ -0,0 +1,16 @@ +from binaryninja.architecture import Architecture, ArchitectureHook + +class X86ReturnHook(ArchitectureHook): + def get_instruction_text(self, data, addr): + # Call the original implementation's method by calling the superclass + result, length = super(X86ReturnHook, self).get_instruction_text(data, addr) + + # Patch the name of the 'retn' instruction to 'ret' + if len(result) > 0 and result[0].text == 'retn': + result[0].text = 'ret' + + return result, length + +# Install the hook by constructing it with the desired architecture to hook, then registering it +X86ReturnHook(Architecture['x86']).register() + diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py new file mode 100644 index 00000000..05a72ed0 --- /dev/null +++ b/python/examples/bin_info.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys + +import binaryninja.log as log +from binaryninja.binaryview import BinaryViewType +import binaryninja.interaction as interaction +from binaryninja.plugin import PluginCommand + +# 2-3 compatibility +from binaryninja import range + + +def get_bininfo(bv): + if bv is None: + filename = "" + if len(sys.argv) > 1: + filename = sys.argv[1] + else: + filename = interaction.get_open_filename_input("Filename:") + if filename is None: + log.log_warn("No file specified") + sys.exit(1) + + bv = BinaryViewType.get_view_of_file(filename) + log.log_to_stdout(True) + + contents = "## %s ##\n" % bv.file.filename + contents += "- START: 0x%x\n\n" % bv.start + contents += "- ENTRY: 0x%x\n\n" % bv.entry_point + contents += "- ARCH: %s\n\n" % bv.arch.name + contents += "### First 10 Functions ###\n" + + contents += "| Start | Name |\n" + contents += "|------:|:-------|\n" + for i in range(min(10, len(bv.functions))): + contents += "| 0x%x | %s |\n" % (bv.functions[i].start, bv.functions[i].symbol.full_name) + + contents += "### First 10 Strings ###\n" + contents += "| Start | Length | String |\n" + contents += "|------:|-------:|:-------|\n" + for i in range(min(10, len(bv.strings))): + start = bv.strings[i].start + length = bv.strings[i].length + string = bv.read(start, length) + contents += "| 0x%x |%d | %s |\n" % (start, length, string) + return contents + + +def display_bininfo(bv): + interaction.show_markdown_report("Binary Info Report", get_bininfo(bv)) + + +if __name__ == "__main__": + print(get_bininfo(None)) +else: + PluginCommand.register("Binary Info", "Display basic info about the binary", display_bininfo) diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py new file mode 100644 index 00000000..cbcb86d4 --- /dev/null +++ b/python/examples/breakpoint.py @@ -0,0 +1,50 @@ +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + + +from binaryninja.plugin import PluginCommand +from binaryninja.log import log_error + + +def write_breakpoint(view, start, length): + """Sample function to show registering a plugin menu item for a range of bytes. Also possible: + register + register_for_address + register_for_function + """ + bkpt_str = { + "x86": "int3", + "x86_64": "int3", + "armv7": "bkpt", + "aarch64": "brk #0", + "mips32": "break"} + + if view.arch.name not in bkpt_str: + log_error("Architecture %s not supported" % view.arch.name) + return + + bkpt, err = view.arch.assemble(bkpt_str[view.arch.name]) + if bkpt is None: + log_error(err) + return + view.write(start, bkpt * length // len(bkpt)) + + +PluginCommand.register_for_range("Convert to breakpoint", "Fill region with breakpoint instructions.", write_breakpoint) diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py new file mode 100755 index 00000000..5bb27824 --- /dev/null +++ b/python/examples/export_svg.py @@ -0,0 +1,224 @@ +# from binaryninja import * +import os +import webbrowser +import time +try: + from urllib import pathname2url # Python 2.x +except: + from urllib.request import pathname2url # Python 3.x + +from binaryninja.interaction import get_save_filename_input, show_message_box +from binaryninja.enums import MessageBoxButtonSet, MessageBoxIcon, MessageBoxButtonResult, InstructionTextTokenType, BranchType +from binaryninja.plugin import PluginCommand + +colors = {'green': [162, 217, 175], 'red': [222, 143, 151], 'blue': [128, 198, 233], 'cyan': [142, 230, 237], 'lightCyan': [176, 221, 228], 'orange': [237, 189, 129], 'yellow': [237, 223, 179], 'magenta': [218, 196, 209], 'none': [74, 74, 74]} + +escape_table = { + "'": "'", + ">": ">", + "<": "<", + '"': """, + ' ': " " +} + + +def escape(toescape): + toescape = toescape.decode('utf-8').encode('ascii', 'xmlcharrefreplace') # handle extended unicode + return ''.join(escape_table.get(i, i) for i in toescape) # still escape the basics + + +def save_svg(bv, function): + address = hex(function.start).replace('L', '') + path = os.path.dirname(bv.file.filename) + origname = os.path.basename(bv.file.filename) + filename = os.path.join(path, 'binaryninja-{filename}-{function}.html'.format(filename=origname, function=address)) + outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename) + if outputfile is None: + return + content = render_svg(function, origname) + output = open(outputfile, 'w') + output.write(content) + output.close() + result = show_message_box("Open SVG", "Would you like to view the exported SVG?", + buttons = MessageBoxButtonSet.YesNoButtonSet, icon = MessageBoxIcon.QuestionIcon) + if result == MessageBoxButtonResult.YesButton: + url = 'file:{}'.format(pathname2url(outputfile)) + webbrowser.open(url) + + +def instruction_data_flow(function, address): + ''' TODO: Extract data flow information ''' + length = binaryninja.function.view.get_instruction_length(address) + bytes = binaryninja.function.view.read(address, length) + hex = bytes.encode('hex') + padded = ' '.join([hex[i:i + 2] for i in range(0, len(hex), 2)]) + return 'Opcode: {bytes}'.format(bytes=padded) + + +def render_svg(function, origname): + graph = binaryninja.function.create_graph() + graph.layout_and_wait() + heightconst = 15 + ratio = 0.48 + widthconst = heightconst * ratio + + output = ''' + + + + +''' + output += ''' + + + + + + + + + + + + + + + '''.format(width=graph.width * widthconst + 20, height=graph.height * heightconst + 20) + output += ''' + Function Graph 0 + ''' + edges = '' + for i, block in enumerate(graph.blocks): + + # Calculate basic block location and coordinates + x = ((block.x) * widthconst) + y = ((block.y) * heightconst) + width = ((block.width) * widthconst) + height = ((block.height) * heightconst) + + # Render block + output += ' \n'.format(i=i) + output += ' Basic Block {i}\n'.format(i=i) + rgb = colors['none'] + try: + bb = block.basic_block + color_code = bb.highlight.color + color_str = bb.highlight._standard_color_to_str(color_code) + if color_str in colors: + rgb = colors[color_str] + except: + pass + output += ' \n'.format(x=x, y=y, width=width + 16, height=height + 12, r=rgb[0], g=rgb[1], b=rgb[2]) + + # Render instructions, unfortunately tspans don't allow copying/pasting more + # than one line at a time, need SVG 1.2 textarea tags for that it looks like + + output += ' \n'.format(x=x, y=y + (i + 1) * heightconst) + for i, line in enumerate(block.lines): + output += ' '.format(x=x + 6, y=y + 6 + (i + 0.7) * heightconst, address=hex(line.address)[:-1]) + hover = instruction_data_flow(function, line.address) + output += '{hover}'.format(hover=hover) + for token in line.tokens: + # TODO: add hover for hex, function, and reg tokens + output += '{text}'.format(text=escape(token.text), tokentype=InstructionTextTokenType(token.type).name) + output += '\n' + output += ' \n' + output += ' \n' + + # Edges are rendered in a seperate chunk so they have priority over the + # basic blocks or else they'd render below them + + for edge in block.outgoing_edges: + points = "" + x, y = edge.points[0] + points += str(x * widthconst) + "," + str(y * heightconst + 12) + " " + for x, y in edge.points[1:-1]: + points += str(x * widthconst) + "," + str(y * heightconst) + " " + x, y = edge.points[-1] + points += str(x * widthconst) + "," + str(y * heightconst + 0) + " " + if edge.back_edge: + edges += ' \n'.format(type=BranchType(edge.type).name, points=points) + else: + edges += ' \n'.format(type=BranchType(edge.type).name, points=points) + output += ' ' + edges + '\n' + output += ' \n' + output += '' + + output += '

This CFG generated by Binary Ninja from {filename} on {timestring}.

'.format(filename = origname, timestring = time.strftime("%c")) + output += '' + return output + + +PluginCommand.register_for_function("Export to SVG", "Exports an SVG of the current function", save_svg) diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py new file mode 100644 index 00000000..f55e1c1b --- /dev/null +++ b/python/examples/instruction_iterator.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys +import binaryninja as binja + +if len(sys.argv) > 1: + target = sys.argv[1] + +bv = binja.BinaryViewType.get_view_of_file(target) +binja.log_to_stdout(True) +binja.log_info("-------- %s --------" % target) +binja.log_info("START: 0x%x" % bv.start) +binja.log_info("ENTRY: 0x%x" % bv.entry_point) +binja.log_info("ARCH: %s" % bv.arch.name) +binja.log_info("\n-------- Function List --------") + +""" print all the functions, their basic blocks, and their il instructions """ +for func in bv.functions: + binja.log_info(repr(func)) + for block in func.low_level_il: + binja.log_info("\t{0}".format(block)) + + for insn in block: + binja.log_info("\t\t{0}".format(insn)) + + +""" print all the functions, their basic blocks, and their mc instructions """ +for func in bv.functions: + binja.log_info(repr(func)) + for block in func: + binja.log_info("\t{0}".format(block)) + + for insn in block: + binja.log_info("\t\t{0}".format(insn)) diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py new file mode 100644 index 00000000..4ed8dda2 --- /dev/null +++ b/python/examples/jump_table.py @@ -0,0 +1,86 @@ +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# This plugin will attempt to resolve simple jump tables (an array of code pointers) and add the destinations +# as indirect branch targets so that the flow graph reflects the jump table's control flow. +from binaryninja.plugin import PluginCommand +from binaryninja.enums import InstructionTextTokenType +import struct + + +def find_jump_table(bv, addr): + for block in bv.get_basic_blocks_at(addr): + func = block.function + arch = func.arch + addrsize = arch.address_size + + # Grab the instruction tokens so that we can look for the table's starting address + tokens, length = arch.get_instruction_text(bv.read(addr, 16), addr) + + # Look for the next jump instruction, which may be the current instruction. Some jump tables will + # compute the address first then jump to the computed address as a separate instruction. + jump_addr = addr + while jump_addr < block.end: + info = arch.get_instruction_info(bv.read(jump_addr, 16), jump_addr) + if len(info.branches) != 0: + break + jump_addr += info.length + if jump_addr >= block.end: + print("Unable to find jump after instruction 0x%x" % addr) + continue + print("Jump at 0x%x" % jump_addr) + + # Collect the branch targets for any tables referenced by the clicked instruction + branches = [] + for token in tokens: + if InstructionTextTokenType(token.type) == InstructionTextTokenType.PossibleAddressToken: # Table addresses will be a "possible address" token + tbl = token.value + print("Found possible table at 0x%x" % tbl) + i = 0 + while True: + # Read the next pointer from the table + data = bv.read(tbl + (i * addrsize), addrsize) + if len(data) == addrsize: + if addrsize == 4: + ptr = struct.unpack("= bv.start) and (ptr < bv.end): + print("Found destination 0x%x" % ptr) + branches.append((arch, ptr)) + else: + # Once a value that is not a pointer is encountered, the jump table is ended + break + else: + # Reading invalid memory + break + + i += 1 + + # Set the indirect branch targets on the jump instruction to be the list of targets discovered + 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 +PluginCommand.register_for_address("Process jump table", "Look for jump table destinations", find_jump_table) diff --git a/python/examples/nds.py b/python/examples/nds.py new file mode 100644 index 00000000..a99303cf --- /dev/null +++ b/python/examples/nds.py @@ -0,0 +1,120 @@ +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +# from binaryninja import * +from binaryninja.binaryview import BinaryView +from binaryninja.architecture import Architecture +from binaryninja.enums import SegmentFlag +from binaryninja.log import log_error + +import struct +import traceback + +# 2-3 compatibility +from binaryninja import range + + +def crc16(data): + crc = 0xffff + for ch in data: + crc ^= ord(ch) + for bit in range(0, 8): + if (crc & 1) == 1: + crc = (crc >> 1) ^ 0xa001 + else: + crc >>= 1 + return crc + + +class DSView(BinaryView): + def __init__(self, data): + BinaryView.__init__(self, file_metadata = data.file, parent_view = data) + self.raw = data + + @classmethod + def is_valid_for_data(self, data): + hdr = data.read(0, 0x160) + if len(hdr) < 0x160: + return False + if struct.unpack("> 4) + self.ram_banks = struct.unpack("B", hdr[8])[0] + self.rom_offset = 16 + if self.rom_flags & 4: + self.rom_offset += 512 + self.rom_length = self.rom_banks * 0x4000 + + # Add mapping for RAM and hardware registers, not backed by file contents + self.add_auto_segment(0, 0x8000, 0, 0, SegmentFlag.SegmentReadable | SegmentFlag.SegmentWritable | SegmentFlag.SegmentExecutable) + + # Add ROM mappings + self.add_auto_segment(0x8000, 0x4000, self.rom_offset + (self.__class__.bank * 0x4000), 0x4000, + SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable) + self.add_auto_segment(0xc000, 0x4000, self.rom_offset + self.rom_length - 0x4000, 0x4000, + SegmentFlag.SegmentReadable | SegmentFlag.SegmentExecutable) + + nmi = struct.unpack("= 0x8000: + self.add_function(addr) + + return True + except: + log_error(traceback.format_exc()) + return False + + def perform_is_executable(self): + return True + + def perform_get_entry_point(self): + return struct.unpack("'.format(sys.argv[0])) + else: + print_syscalls(sys.argv[1]) diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py new file mode 100644 index 00000000..c990a6c0 --- /dev/null +++ b/python/examples/version_switcher.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# Copyright (c) 2015-2017 Vector 35 LLC +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. + +import sys + +from binaryninja.update import UpdateChannel, are_auto_updates_enabled, set_auto_updates_enabled, is_update_installation_pending, install_pending_update +from binaryninja import core_version +import datetime + +chandefault = UpdateChannel.list[0].name +channel = None +versions = [] + + +def load_channel(newchannel): + global channel + global versions + if (channel is not None and newchannel == channel.name): + print("Same channel, not updating.") + else: + try: + print("Loading channel %s" % newchannel) + channel = UpdateChannel[newchannel] + print("Loading versions...") + versions = channel.versions + except Exception: + print("%s is not a valid channel name. Defaulting to " % chandefault) + channel = UpdateChannel[chandefault] + + +def select(version): + done = False + date = datetime.datetime.fromtimestamp(version.time).strftime('%c') + while not done: + print("Version:\t%s" % version.version) + print("Updated:\t%s" % date) + print("Notes:\n\n-----\n%s" % version.notes) + print("-----") + print("\t1)\tSwitch to version") + print("\t2)\tMain Menu") + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection == 2): + done = True + elif (selection == 1): + if (version.version == channel.latest_version.version): + print("Requesting update to latest version.") + else: + print("Requesting update to prior version.") + if are_auto_updates_enabled(): + print("Disabling automatic updates.") + set_auto_updates_enabled(False) + if (version.version == core_version): + print("Already running %s" % version.version) + else: + print("version.version %s" % version.version) + print("core_version %s" % core_version) + print("Downloading...") + print(version.update()) + print("Installing...") + if is_update_installation_pending: + #note that the GUI will be launched after update but should still do the upgrade headless + install_pending_update() + # forward updating won't work without reloading + sys.exit() + else: + print("Invalid selection") + + +def list_channels(): + done = False + print("\tSelect channel:\n") + while not done: + channel_list = UpdateChannel.list + for index, item in enumerate(channel_list): + print("\t%d)\t%s" % (index + 1, item.name)) + print("\t%d)\t%s" % (len(channel_list) + 1, "Main Menu")) + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection <= 0 or selection > len(channel_list) + 1): + print("%s is an invalid choice." % selection) + else: + done = True + if (selection != len(channel_list) + 1): + load_channel(channel_list[selection - 1].name) + + +def toggle_updates(): + set_auto_updates_enabled(not are_auto_updates_enabled()) + + +def main(): + global channel + done = False + load_channel(chandefault) + while not done: + print("\n\tBinary Ninja Version Switcher") + print("\t\tCurrent Channel:\t%s" % channel.name) + print("\t\tCurrent Version:\t%s" % core_version) + print("\t\tAuto-Updates On:\t%s\n" % are_auto_updates_enabled()) + for index, version in enumerate(versions): + date = datetime.datetime.fromtimestamp(version.time).strftime('%c') + print("\t%d)\t%s (%s)" % (index + 1, version.version, date)) + print("\t%d)\t%s" % (len(versions) + 1, "Switch Channel")) + print("\t%d)\t%s" % (len(versions) + 2, "Toggle Auto Updates")) + print("\t%d)\t%s" % (len(versions) + 3, "Exit")) + selection = raw_input('Choice: ') + if selection.isdigit(): + selection = int(selection) + else: + selection = 0 + if (selection <= 0 or selection > len(versions) + 3): + print("%d is an invalid choice.\n\n" % selection) + else: + if (selection == len(versions) + 3): + done = True + elif (selection == len(versions) + 2): + toggle_updates() + elif (selection == len(versions) + 1): + list_channels() + else: + select(versions[selection - 1]) + + +if __name__ == "__main__": + main() diff --git a/python/function.py b/python/function.py index 8407eece..0589a5e2 100644 --- a/python/function.py +++ b/python/function.py @@ -26,7 +26,7 @@ import ctypes # Binary Ninja components import binaryninja from binaryninja import _binaryninjacore as core -from binaryninja import associateddatastore #required in the main scope due to being an argument for _FunctionAssociatedDataStore +from binaryninja import associateddatastore # Required in the main scope due to being an argument for _FunctionAssociatedDataStore from binaryninja import highlight from binaryninja import log from binaryninja import types @@ -1631,7 +1631,7 @@ class FunctionGraphEdge(object): class FunctionGraphBlock(object): - def __init__(self, handle): + def __init__(self, handle, graph): self.handle = handle self.graph = graph @@ -1657,14 +1657,14 @@ class FunctionGraphBlock(object): core.BNFreeBasicBlock(block) return None - view = binaryview.BinaryView(handle = core.BNGetFunctionData(func_handle)) + view = binaryninja.binaryview.BinaryView(handle = core.BNGetFunctionData(func_handle)) func = Function(view, func_handle) if core.BNIsLowLevelILBasicBlock(block): - block = lowlevelil.LowLevelILBasicBlock(view, block, + block = binaryninja.lowlevelil.LowLevelILBasicBlock(view, block, lowlevelil.LowLevelILFunction(func.arch, core.BNGetBasicBlockLowLevelILFunction(block), func)) elif core.BNIsMediumLevelILBasicBlock(block): - block = mediumlevelil.MediumLevelILBasicBlock(view, block, + block = binaryninja.mediumlevelil.MediumLevelILBasicBlock(view, block, mediumlevelil.MediumLevelILFunction(func.arch, core.BNGetBasicBlockMediumLevelILFunction(block), func)) else: block = binaryninja.basicblock.BasicBlock(view, block) @@ -1942,12 +1942,12 @@ class FunctionGraph(object): il_func = core.BNGetFunctionGraphLowLevelILFunction(self.handle) if not il_func: return None - return lowlevelil.LowLevelILFunction(self.function.arch, il_func, self.function) + return binaryninja.lowlevelil.LowLevelILFunction(self.function.arch, il_func, self.function) if self.is_medium_level_il: il_func = core.BNGetFunctionGraphMediumLevelILFunction(self.handle) if not il_func: return None - return mediumlevelil.MediumLevelILFunction(self.function.arch, il_func, self.function) + return binaryninja.mediumlevelil.MediumLevelILFunction(self.function.arch, il_func, self.function) return None def __setattr__(self, name, value): diff --git a/python/plugin.py b/python/plugin.py index b8217f0b..2fc30052 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -121,7 +121,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): try: file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) - func_obj = binaryninja.function.Function(view_obj, core.BNNewFunctionReference(func)) + func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) action(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -132,7 +132,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) - func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) action(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -143,7 +143,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) - func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) action(view_obj, func_obj[instr]) except: log.log_error(traceback.format_exc()) @@ -154,7 +154,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) - func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) action(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -165,7 +165,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) - func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) action(view_obj, func_obj[instr]) except: log.log_error(traceback.format_exc()) @@ -213,7 +213,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): return True file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) - func_obj = binaryninja.function.Function(view_obj, core.BNNewFunctionReference(func)) + func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) return is_valid(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -227,7 +227,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) - func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -241,7 +241,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetLowLevelILOwnerFunction(func)) - func_obj = lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) + func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj[instr]) except: log.log_error(traceback.format_exc()) @@ -255,7 +255,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) - func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj) except: log.log_error(traceback.format_exc()) @@ -269,7 +269,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): file_metadata = filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) view_obj = binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) owner = function.Function(view_obj, core.BNGetMediumLevelILOwnerFunction(func)) - func_obj = mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) + func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj[instr]) except: log.log_error(traceback.format_exc()) @@ -364,7 +364,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja.startup._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_action(view, func, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_is_valid(view, func, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -383,7 +383,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja.startup._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_action(view, func, instr, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_is_valid(view, func, instr, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -402,7 +402,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja.startup._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_action(view, func, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_is_valid(view, func, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -421,7 +421,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - startup._init_plugins() + binaryninja.startup._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_action(view, func, instr, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_is_valid(view, func, instr, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -469,7 +469,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): elif self.command.type == PluginCommandType.LowLevelILInstructionPluginCommand: if context.instruction is None: return False - if not isinstance(context.instruction, lowlevelil.LowLevelILInstruction): + if not isinstance(context.instruction, binaryninja.lowlevelil.LowLevelILInstruction): return False if not self.command.lowLevelILInstructionIsValid: return True @@ -484,7 +484,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): elif self.command.type == PluginCommandType.MediumLevelILInstructionPluginCommand: if context.instruction is None: return False - if not isinstance(context.instruction, mediumlevelil.MediumLevelILInstruction): + if not isinstance(context.instruction, binaryninja.mediumlevelil.MediumLevelILInstruction): return False if not self.command.mediumLevelILInstructionIsValid: return True diff --git a/suite/generator.py b/suite/generator.py index ad0d24fc..f4ee69ee 100755 --- a/suite/generator.py +++ b/suite/generator.py @@ -22,6 +22,7 @@ from collections import Counter global verbose verbose = False + class TestBinaryNinjaAPI(unittest.TestCase): # Returns a tuple of: # bool : Two lists are equal diff --git a/suite/oracle.pkl b/suite/oracle.pkl index d7ce1115..f0be17d4 100644 Binary files a/suite/oracle.pkl and b/suite/oracle.pkl differ diff --git a/suite/testcommon.py b/suite/testcommon.py index ef85c053..07ceb592 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -541,6 +541,7 @@ class TestBuilder(Builder): """Types produced different result""" file_name = os.path.join(self.test_store, "helloworld") bv = binja.BinaryViewType.get_view_of_file(file_name) + preprocessed = binja.preprocess_source(""" #ifdef nonexistant int foo = 1; @@ -550,7 +551,7 @@ class TestBuilder(Builder): long long bar1 = 2; #endif """) - source = '\n'.join([i.decode('utf-8') for i in preprocessed[0].split(b'\n') if not b'#line' in i and len(i) > 0]) + source = '\n'.join([i.decode('charmap') for i in preprocessed[0].split(b'\n') if not b'#line' in i and len(i) > 0]) typelist = bv.platform.parse_types_from_source(source) inttype = binja.Type.int(4) @@ -566,14 +567,13 @@ class TestBuilder(Builder): retinfo.append("Type equality: " + str((inttype == inttype) and not (inttype != inttype))) return retinfo - def test_Plugin_bin_info(self): """print_syscalls plugin produced different result""" file_name = os.path.join(self.test_store, "helloworld") self.unpackage_file(file_name) result = subprocess.Popen(["python", os.path.join(self.examples_dir, "bin_info.py"), file_name], stdout=subprocess.PIPE).communicate()[0] # normalize line endings and path sep - return [result.replace(b"\\", b"/").replace(b"\r\n", b"\n").decode("charmap")] + return [line for line in result.replace(b"\\", b"/").replace(b"\r\n", b"\n").decode("charmap").split("\n")] def test_linear_disassembly(self): """linear_disassembly produced different result""" diff --git a/suite/unit.py b/suite/unit.py index 9cbed511..e01b0f19 100644 --- a/suite/unit.py +++ b/suite/unit.py @@ -13,6 +13,7 @@ from collections import Counter global verbose verbose = False + class TestBinaryNinjaAPI(unittest.TestCase): # Returns a tuple of: # bool : Two lists are equal @@ -235,12 +236,6 @@ class TestBinaryNinjaAPI(unittest.TestCase): def test_binary___loop_constant_propagate(self): self.run_binary_test('suite/binaries/test_corpus/loop_constant_propagate.zip') - def test_binary___ls(self): - self.run_binary_test('suite/binaries/test_corpus/ls.zip') - - def test_binary___md5(self): - self.run_binary_test('suite/binaries/test_corpus/md5.zip') - def test_binary___partial_register_dataflow(self): self.run_binary_test('suite/binaries/test_corpus/partial_register_dataflow.zip') -- cgit v1.3.1 From f9d7cc83105d6cbfe03409c6eddbc039b0d9839c Mon Sep 17 00:00:00 2001 From: KyleMiles Date: Mon, 16 Jul 2018 15:56:28 -0400 Subject: Fix format of strings in python/log.py --- .gitignore | 1 + Makefile | 6 +++--- python/generator.cpp | 10 ++++++++++ python/log.py | 12 ++++++------ python/plugin.py | 35 +++++++++++++++++------------------ 5 files changed, 37 insertions(+), 27 deletions(-) (limited to 'python/plugin.py') diff --git a/.gitignore b/.gitignore index fca3f67d..088713e7 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ api-docs/build/* .env api-docs/source/binaryninja.* bin/ +suite/unit.py # CMake CMakeCache.txt CMakeFiles diff --git a/Makefile b/Makefile index e1576dcf..8480c05a 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ all: $(TARGET).a $(TARGET).a: $(OBJECTS) @mkdir -p $(TARGETDIR) $(AR) rcs $@ $^ - + %.o: %.cpp @echo " Compiling... $@ $<" $(CC) $(CFLAGS) $(INC) -c -o $@ $< @@ -86,7 +86,7 @@ environment_clean: @echo "Removing 'binaryninja' Packages..." rm -rf suite/binaryninja/ rm -rf python/examples/binaryninja/ - + @echo "Removing libs..." rm -f libbinaryninjacore.so.1 rm -f python/libbinaryninjacore.so.1 @@ -97,7 +97,7 @@ environment_clean: rm -rf python/types/ rm -rf python/plugins/ -clean: +clean: @echo " Cleaning..."; $(RM) -r *.o $(TARGETDIR) generator diff --git a/python/generator.cpp b/python/generator.cpp index afc77254..39e45aea 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -391,6 +391,16 @@ int main(int argc, char* argv[]) } fprintf(out, "\t]\n"); } + else + { + // As of writing this, only BNLog's have variable instruction lengths, but in an attempt not to break in the future: + if (funcName.compare(0, 6, "_BNLog") == 0) + { + fprintf(out, "def %s(*args):\n", name.c_str()); + fprintf(out, "\treturn %s(*[cstr(arg) for arg in args])\n\n", funcName.c_str()); + continue; + } + } if (stringResult) { diff --git a/python/log.py b/python/log.py index 9a5e1358..4997b222 100644 --- a/python/log.py +++ b/python/log.py @@ -55,7 +55,7 @@ def log(level, text): :param str text: message to print :rtype: None """ - core.BNLog(level,text) + core.BNLog(level, '%s', text) def log_debug(text): @@ -70,7 +70,7 @@ def log_debug(text): >>> log_debug("Hotdogs!") Hotdogs! """ - core.BNLogDebug(text) + core.BNLogDebug('%s', text) def log_info(text): @@ -85,7 +85,7 @@ def log_info(text): Saucisson! >>> """ - core.BNLogInfo(text) + core.BNLogInfo('%s', text) def log_warn(text): @@ -101,7 +101,7 @@ def log_warn(text): Chilidogs! >>> """ - core.BNLogWarn(text) + core.BNLogWarn('%s', text) def log_error(text): @@ -117,7 +117,7 @@ def log_error(text): Spanferkel! >>> """ - core.BNLogError(text) + core.BNLogError('%s', text) def log_alert(text): @@ -133,7 +133,7 @@ def log_alert(text): Kielbasa! >>> """ - core.BNLogAlert(text) + core.BNLogAlert('%s', text) def log_to_stdout(min_level=LogLevel.InfoLog): diff --git a/python/plugin.py b/python/plugin.py index 2fc30052..6ca930c9 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -24,7 +24,6 @@ import threading # Binary Ninja components import binaryninja -from binaryninja import log from binaryninja import _binaryninjacore as core from binaryninja.enums import PluginCommandType from binaryninja import filemetadata @@ -96,7 +95,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _address_action(cls, view, addr, action): @@ -105,7 +104,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _range_action(cls, view, addr, length, action): @@ -114,7 +113,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) action(view_obj, addr, length) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _function_action(cls, view, func, action): @@ -124,7 +123,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) action(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _low_level_il_function_action(cls, view, func, action): @@ -135,7 +134,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) action(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _low_level_il_instruction_action(cls, view, func, instr, action): @@ -146,7 +145,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) action(view_obj, func_obj[instr]) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _medium_level_il_function_action(cls, view, func, action): @@ -157,7 +156,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) action(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _medium_level_il_instruction_action(cls, view, func, instr, action): @@ -168,7 +167,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) action(view_obj, func_obj[instr]) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) @classmethod def _default_is_valid(cls, view, is_valid): @@ -179,7 +178,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -191,7 +190,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -203,7 +202,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) return is_valid(view_obj, addr, length) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -216,7 +215,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) return is_valid(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -230,7 +229,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -244,7 +243,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.lowlevelil.LowLevelILFunction(owner.arch, core.BNNewLowLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj[instr]) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -258,7 +257,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -272,7 +271,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): func_obj = binaryninja.mediumlevelil.MediumLevelILFunction(owner.arch, core.BNNewMediumLevelILFunctionReference(func), owner) return is_valid(view_obj, func_obj[instr]) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) return False @classmethod @@ -552,7 +551,7 @@ class MainThreadActionHandler(object): try: self.add_action(MainThreadAction(action)) except: - log.log_error(traceback.format_exc()) + binaryninja.log.log_error(traceback.format_exc()) def add_action(self, action): pass -- cgit v1.3.1 From 1f986c2698ff9df6d42429b1b7699842223634e5 Mon Sep 17 00:00:00 2001 From: Josh Watson Date: Tue, 24 Jul 2018 17:17:00 -0700 Subject: Fix PluginCommand.register_for methods (#1084) Several register_for_* methods included an extraneous `.startup` that was probably removed in the python3 refactor. This PR fixes that problem and allows those plugins to correctly register. --- python/plugin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'python/plugin.py') diff --git a/python/plugin.py b/python/plugin.py index 6ca930c9..4d9add9c 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -363,7 +363,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_low_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - binaryninja.startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_action(view, func, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction))(lambda ctxt, view, func: cls._low_level_il_function_is_valid(view, func, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -382,7 +382,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_low_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - binaryninja.startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_action(view, func, instr, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNLowLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._low_level_il_instruction_is_valid(view, func, instr, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -401,7 +401,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_medium_level_il_function`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - binaryninja.startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_action(view, func, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction))(lambda ctxt, view, func: cls._medium_level_il_function_is_valid(view, func, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) @@ -420,7 +420,7 @@ class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): .. warning:: Calling ``register_for_medium_level_il_instruction`` with the same function name will replace the existing function but will leak the memory of the original plugin. """ - binaryninja.startup._init_plugins() + binaryninja._init_plugins() action_obj = ctypes.CFUNCTYPE(None, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_action(view, func, instr, action)) is_valid_obj = ctypes.CFUNCTYPE(ctypes.c_bool, ctypes.c_void_p, ctypes.POINTER(core.BNBinaryView), ctypes.POINTER(core.BNMediumLevelILFunction), ctypes.c_ulonglong)(lambda ctxt, view, func, instr: cls._medium_level_il_instruction_is_valid(view, func, instr, is_valid)) cls._registered_commands.append((action_obj, is_valid_obj)) -- cgit v1.3.1