diff options
48 files changed, 1680 insertions, 1440 deletions
@@ -31,3 +31,11 @@ CTestTestfile.cmake api-docs/source/python.rst api-docs/source/index.rst .coverage +# Make +generator +plugins/ +python/examples/binaryninja/ +python/plugins/ +python/types/ +suite/binaryninja/ +types/ @@ -5,6 +5,7 @@ # LIB := -L$(HOME)/binaryninja/ -lbinaryninjacore #endif +INSTALLPATH := ~/binaryninja TARGETDIR := bin TARGETNAME := libbinaryninjaapi @@ -15,7 +16,8 @@ SOURCES = $(wildcard *$(SRCEXT)) OBJECTS = $(SOURCES:.cpp=.o) json.o -CFLAGS := -c -fPIC -O2 -pipe -std=gnu++11 -Wall -W +CFLAGS := -c -fPIC -O2 -pipe -std=gnu++11 -Wall -W -Wextra -Wshadow +CPPFLAGS := -O2 -std=c++11 -Wall -W -Wextra -Wshadow ifeq ($(UNAME_S),Darwin) CC := $(shell xcrun -f g++) AR := $(shell xcrun -f ar) @@ -38,8 +40,67 @@ $(TARGET).a: $(OBJECTS) json.o: ./json/jsoncpp.cpp ./json/json.h ./json/json-forwards.h $(CC) $(CFLAGS) -I. -c -o $@ $< -clean: +install: generate $(TARGET).a + @echo "Installing binaryninja API."; + cp -r python/* $(INSTALLPATH)/python/binaryninja + cp $(TARGET).a $(INSTALLPATH) + @echo "Done."; + +generator: python/generator.cpp $(TARGET).a + @echo "Building generator..."; + $(CC) $(CPPFLAGS) -I . $< -L$(TARGETDIR) -lbinaryninjaapi -L $(INSTALLPATH) -lbinaryninjacore -o $@ + chmod +x $@ + +generate: generator + @echo "Running generator..."; + LD_LIBRARY_PATH=$(INSTALLPATH) ./generator binaryninjacore.h python/_binaryninjacore.py python/enums.py + +python/_binaryninjacore.py: generate + +python/enums.py: generate + +python_test: environment python/_binaryninjacore.py python/enums.py + python2 suite/unit.py + python3 suite/unit.py + +oracle: environment python/_binaryninjacore.py python/enums.py + python3 suite/generator.py + +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/ + cp -r suite/binaryninja/ python/examples/ + + @echo "Copying Architectures Over..." + 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 -rf suite/binaryninja/ + rm -rf python/examples/binaryninja/ + + @echo "Removing libs..." + rm -f libbinaryninjacore.so.1 + rm -f python/libbinaryninjacore.so.1 + + @echo "Removing Architectures..." + rm -rf types/ + rm -rf plugins/ + rm -rf python/types/ + rm -rf python/plugins/ + +clean: @echo " Cleaning..."; - $(RM) -r *.o $(TARGETDIR) + $(RM) -r *.o $(TARGETDIR) generator + +squeaky: clean environment_clean -.PHONY: clean +.PHONY: clean environment_clean squeaky python/_binaryninjacore.py python/enums.py diff --git a/basicblock.cpp b/basicblock.cpp index 33f57d40..13b3e7a8 100644 --- a/basicblock.cpp +++ b/basicblock.cpp @@ -245,8 +245,8 @@ set<Ref<BasicBlock>> BasicBlock::GetIteratedDominanceFrontier(const set<Ref<Basi delete[] blockSet; set<Ref<BasicBlock>> result; - for (size_t i = 0; i < count; i++) - result.insert(new BasicBlock(BNNewBasicBlockReference(resultBlocks[i]))); + for (size_t k = 0; k < count; k++) + result.insert(new BasicBlock(BNNewBasicBlockReference(resultBlocks[k]))); BNFreeBasicBlockList(resultBlocks, count); return result; diff --git a/python/__init__.py b/python/__init__.py index fda5f297..36ed4f0d 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -19,41 +19,99 @@ # IN THE SOFTWARE. +from __future__ import absolute_import import atexit 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 _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 * +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 * +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.downloadprovider import * +from binaryninja.pluginmanager import * +from binaryninja.setting import * +from binaryninja.metadata import * def shutdown(): @@ -138,6 +196,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 df22da7f..aee7c301 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -18,55 +18,60 @@ # 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, +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 +import binaryninja +from binaryninja import log +from binaryninja import lowlevelil +from binaryninja import types +from binaryninja import databuffer +from binaryninja import platform +from binaryninja import callingconvention + +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _ArchitectureMetaClass(type): + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() 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 def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) 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() @@ -80,12 +85,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,11 +135,10 @@ class Architecture(object): semantic_class_for_flag_write_type = {} reg_stacks = {} intrinsics = {} - __metaclass__ = _ArchitectureMetaClass next_address = 0 def __init__(self): - 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 @@ -365,11 +369,11 @@ class Architecture(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] = 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) @@ -402,7 +406,7 @@ class Architecture(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 @@ -413,7 +417,7 @@ class Architecture(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) @@ -504,7 +508,7 @@ class Architecture(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: @@ -530,7 +534,7 @@ class Architecture(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: @@ -620,10 +624,10 @@ class Architecture(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 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) @@ -635,10 +639,10 @@ class Architecture(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 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) @@ -650,10 +654,10 @@ class Architecture(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 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) @@ -665,10 +669,10 @@ class Architecture(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 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) @@ -680,10 +684,10 @@ class Architecture(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 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) @@ -695,10 +699,10 @@ class Architecture(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 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) @@ -731,7 +735,7 @@ class Architecture(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) @@ -749,7 +753,7 @@ class Architecture(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) @@ -797,7 +801,7 @@ class Architecture(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) @@ -824,7 +828,7 @@ class Architecture(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): @@ -913,7 +917,7 @@ class Architecture(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) @@ -934,10 +938,10 @@ class Architecture(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 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) @@ -985,10 +989,10 @@ class Architecture(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 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) @@ -1004,7 +1008,7 @@ class Architecture(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 @@ -1025,7 +1029,7 @@ class Architecture(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): @@ -1037,7 +1041,7 @@ class Architecture(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) @@ -1057,7 +1061,7 @@ class Architecture(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): @@ -1069,7 +1073,6 @@ class Architecture(object): errors[0] = core.BNAllocString(str(error_str)) if data is None: return False - data = str(data) buf = ctypes.create_string_buffer(len(data)) ctypes.memmove(buf, data, len(data)) core.BNSetDataBufferContents(result, buf, len(data)) @@ -1706,7 +1709,7 @@ class Architecture(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 @@ -1761,7 +1764,7 @@ class Architecture(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 @@ -2070,15 +2073,15 @@ 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) - 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 - 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: @@ -2090,7 +2093,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 @@ -2102,7 +2105,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 @@ -2114,7 +2117,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 @@ -2126,7 +2129,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 @@ -2145,7 +2148,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 @@ -2158,7 +2161,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) @@ -2173,7 +2176,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 @@ -2191,7 +2194,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) @@ -2213,7 +2216,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) @@ -2222,17 +2225,17 @@ 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] = 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) @@ -2242,23 +2245,23 @@ 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(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) 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] = 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) @@ -2290,16 +2293,15 @@ class CoreArchitecture(Architecture): :rtype: InstructionInfo """ info = core.BNInstructionInfo() - data = str(data) buf = (ctypes.c_ubyte * len(data))() 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 - 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]) @@ -2318,7 +2320,6 @@ class CoreArchitecture(Architecture): :return: an InstructionTextToken list for the current instruction :rtype: list(InstructionTextToken) """ - data = str(data) count = ctypes.c_ulonglong() length = ctypes.c_ulonglong() length.value = len(data) @@ -2328,7 +2329,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 @@ -2337,7 +2338,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 @@ -2355,7 +2356,6 @@ class CoreArchitecture(Architecture): :return: the length of the current instruction :rtype: int """ - data = str(data) length = ctypes.c_ulonglong() length.value = len(data) buf = (ctypes.c_ubyte * len(data))() @@ -2375,7 +2375,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 @@ -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): """ @@ -2445,7 +2448,6 @@ class CoreArchitecture(Architecture): False >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) return core.BNIsArchitectureNeverBranchPatchAvailable(self.handle, buf, addr, len(data)) @@ -2467,7 +2469,6 @@ class CoreArchitecture(Architecture): False >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) return core.BNIsArchitectureAlwaysBranchPatchAvailable(self.handle, buf, addr, len(data)) @@ -2488,7 +2489,6 @@ class CoreArchitecture(Architecture): False >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) return core.BNIsArchitectureInvertBranchPatchAvailable(self.handle, buf, addr, len(data)) @@ -2512,7 +2512,6 @@ class CoreArchitecture(Architecture): False >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) return core.BNIsArchitectureSkipAndReturnZeroPatchAvailable(self.handle, buf, addr, len(data)) @@ -2534,7 +2533,6 @@ class CoreArchitecture(Architecture): False >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) return core.BNIsArchitectureSkipAndReturnValuePatchAvailable(self.handle, buf, addr, len(data)) @@ -2554,7 +2552,6 @@ class CoreArchitecture(Architecture): '\\x90\\x90' >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) if not core.BNArchitectureConvertToNop(self.handle, buf, addr, len(data)): @@ -2581,7 +2578,6 @@ class CoreArchitecture(Architecture): (['jmp ', '0x9'], 5L) >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) if not core.BNArchitectureAlwaysBranch(self.handle, buf, addr, len(data)): @@ -2609,7 +2605,6 @@ class CoreArchitecture(Architecture): (['jl ', '0xa'], 6L) >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) if not core.BNArchitectureInvertBranch(self.handle, buf, addr, len(data)): @@ -2633,7 +2628,6 @@ class CoreArchitecture(Architecture): (['mov ', 'eax', ', ', '0x0'], 5L) >>> """ - data = str(data) buf = (ctypes.c_ubyte * len(data))() ctypes.memmove(buf, data, len(data)) if not core.BNArchitectureSkipAndReturnValue(self.handle, buf, addr, len(data), value): @@ -2660,7 +2654,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 a79b53ad..11d5a7f4 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -21,11 +21,13 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core -from enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType -import architecture -import highlight -import function +import binaryninja +from binaryninja import highlight +from binaryninja import _binaryninjacore as core +from binaryninja.enums import BranchType, HighlightColorStyle, HighlightStandardColor, InstructionTextTokenType + +# 2-3 compatibility +from binaryninja import range class BasicBlockEdge(object): @@ -87,7 +89,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 +102,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 @@ -129,7 +131,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)) @@ -145,7 +147,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)) @@ -171,7 +173,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 @@ -182,7 +184,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 @@ -201,7 +203,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 @@ -212,7 +214,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 @@ -225,7 +227,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 @@ -276,12 +278,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 @@ -322,7 +324,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: @@ -337,14 +339,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 @@ -353,8 +355,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 1e078523..c4fddd7c 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -22,25 +22,24 @@ import struct import traceback import ctypes import abc -import threading # Binary Ninja components -import _binaryninjacore as core -from enums import (AnalysisState, SymbolType, InstructionTextTokenType, +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 +import binaryninja +from binaryninja import associateddatastore # required for _BinaryViewAssociatedDataStore +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 binaryninja import range +from binaryninja import with_metaclass class BinaryDataNotification(object): @@ -99,21 +98,23 @@ 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): - ... print "Analysis Complete", self.view + ... print("Analysis Complete", self.view) ... >>> evt = AnalysisCompletionEvent(bv, on_complete) >>> @@ -123,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: @@ -143,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): @@ -242,25 +254,25 @@ 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()) def _function_update_requested(self, ctxt, view, func): try: - self.notify.function_update_requested(self.view, function.Function(self.view, core.BNNewFunctionReference(func))) + self.notify.function_update_requested(self.view, binaryninja.function.Function(self.view, core.BNNewFunctionReference(func))) except: log.log_error(traceback.format_exc()) @@ -319,38 +331,38 @@ class BinaryDataNotificationCallbacks(object): class _BinaryViewTypeMetaclass(type): + @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 = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(BinaryViewType(types[i])) core.BNFreeBinaryViewTypeList(types) return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) 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)) return BinaryViewType(view_type) -class BinaryViewType(object): - __metaclass__ = _BinaryViewTypeMetaclass +class BinaryViewType(with_metaclass(_BinaryViewTypeMetaclass, object)): def __init__(self, handle): self.handle = core.handle_of_type(handle, core.BNBinaryViewType) @@ -411,7 +423,7 @@ class BinaryViewType(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) @@ -424,6 +436,9 @@ class BinaryViewType(object): else: bv = cls[available.name].open(filename) + if bv is None: + raise Exception("Unknown Architecture/Architecture Not Found (check plugins folder)") + if update_analysis: bv.update_analysis_and_wait() return bv @@ -439,7 +454,7 @@ class BinaryViewType(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) @@ -451,7 +466,7 @@ class BinaryViewType(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): @@ -593,17 +608,17 @@ class BinaryView(object): 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() @@ -646,7 +661,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: @@ -661,7 +676,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 @@ -680,14 +695,14 @@ class BinaryView(object): @classmethod def open(cls, src, file_metadata=None): - 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 @@ -696,9 +711,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: @@ -782,8 +797,8 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionList(self.handle, count) try: - for i in xrange(0, count.value): - yield function.Function(self, core.BNNewFunctionReference(funcs[i])) + for i in range(0, count.value): + yield binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i])) finally: core.BNFreeFunctionList(funcs, count.value) @@ -851,7 +866,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): @@ -866,7 +881,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): @@ -901,8 +916,8 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionList(self.handle, count) result = [] - for i in xrange(0, count.value): - result.append(function.Function(self, core.BNNewFunctionReference(funcs[i]))) + for i in range(0, count.value): + result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -917,7 +932,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): @@ -925,7 +940,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) @@ -942,7 +957,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 @@ -992,7 +1007,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 @@ -1006,7 +1021,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) @@ -1018,7 +1033,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) @@ -1030,7 +1045,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, @@ -1044,7 +1059,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 @@ -1064,7 +1079,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): @@ -1729,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 @@ -1741,7 +1759,7 @@ class BinaryView(object): \'\\xcf\\xfa\\xed\\xfe\' """ buf = databuffer.DataBuffer(handle=core.BNReadViewBuffer(self.handle, addr, length)) - return str(buf) + return bytes(buf) def write(self, addr, data): """ @@ -1760,6 +1778,8 @@ class BinaryView(object): >>> bv.read(0,4) 'AAAA' """ + if not isinstance(data, bytes): + raise TypeError("Must be bytes") buf = databuffer.DataBuffer(data) return core.BNWriteViewBuffer(self.handle, addr, buf.handle) @@ -1778,6 +1798,8 @@ class BinaryView(object): >>> bv.read(0,8) 'BBBBAAAA' """ + if not isinstance(data, bytes): + raise TypeError("Must be bytes") buf = databuffer.DataBuffer(data) return core.BNInsertViewBuffer(self.handle, addr, buf.handle) @@ -2170,7 +2192,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): """ @@ -2186,8 +2208,8 @@ class BinaryView(object): count = ctypes.c_ulonglong(0) funcs = core.BNGetAnalysisFunctionsForAddress(self.handle, addr, count) result = [] - for i in xrange(0, count.value): - result.append(function.Function(self, core.BNNewFunctionReference(funcs[i]))) + for i in range(0, count.value): + result.append(binaryninja.function.Function(self, core.BNNewFunctionReference(funcs[i]))) core.BNFreeFunctionList(funcs, count.value) return result @@ -2195,7 +2217,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): """ @@ -2208,7 +2230,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 @@ -2224,7 +2246,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 @@ -2255,17 +2277,17 @@ 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 = 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 @@ -2321,7 +2343,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 @@ -2346,7 +2368,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 @@ -2375,7 +2397,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 @@ -2774,7 +2796,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 @@ -2782,7 +2804,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. @@ -2790,7 +2814,7 @@ class BinaryView(object): :Example: >>> def completionEvent(): - ... print "done" + ... print("done") ... >>> bv.add_analysis_completion_event(completionEvent) <binaryninja.AnalysisCompletionEvent object at 0x10a2c9f10> @@ -2984,7 +3008,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) @@ -3006,16 +3030,16 @@ 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: - 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 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 @@ -3024,14 +3048,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 @@ -3098,7 +3122,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 ........ @@ -3458,7 +3482,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, @@ -3478,11 +3502,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)): - incoming_names[i] = name_list[i] + for i in range(0, len(name_list)): + incoming_names[i] = name_list[i].encode('charmap') 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 e3ec7261..6b906184 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -22,13 +22,13 @@ 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 +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja import log +from binaryninja.enums import VariableSourceType + +# 2-3 compatibility +from binaryninja import range class CallingConvention(object): @@ -47,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") @@ -75,7 +75,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) @@ -85,7 +85,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 @@ -94,7 +94,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 @@ -103,7 +103,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 @@ -136,7 +136,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 @@ -161,7 +161,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) @@ -176,7 +176,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) @@ -191,7 +191,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) @@ -270,7 +270,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) @@ -282,25 +282,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 @@ -309,9 +309,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 @@ -327,9 +327,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 @@ -350,11 +350,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() @@ -365,7 +365,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() @@ -373,7 +373,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), @@ -384,14 +384,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() @@ -406,7 +406,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() @@ -418,4 +418,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/databuffer.py b/python/databuffer.py index 3f9e4ce5..298d0002 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -21,11 +21,18 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core +from binaryninja import _binaryninjacore as core class DataBuffer(object): def __init__(self, contents="", handle=None): + + # python3 no longer has longs + try: + long + except NameError: + long = int + if handle is not None: self.handle = core.handle_of_type(handle, core.BNDataBuffer) elif isinstance(contents, int) or isinstance(contents, long): @@ -44,7 +51,7 @@ class DataBuffer(object): def __getitem__(self, i): if isinstance(i, tuple): result = "" - source = str(self) + source = bytes(self) for s in i: result += source[s] return result @@ -59,7 +66,7 @@ class DataBuffer(object): ctypes.memmove(buf, core.BNGetDataBufferContentsAt(self.handle, start), stop - start) return buf.raw else: - return str(self)[i] + return bytes(self)[i] elif i < 0: if i >= -len(self): return chr(core.BNGetDataBufferByte(self.handle, int(len(self) + i))) @@ -79,7 +86,7 @@ class DataBuffer(object): if stop < start: stop = start if len(value) != (stop - start): - data = str(self) + data = bytes(self) data = data[0:start] + value + data[stop:] core.BNSetDataBufferContents(self.handle, data, len(data)) else: @@ -107,22 +114,27 @@ class DataBuffer(object): def __str__(self): buf = ctypes.create_string_buffer(len(self)) ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self)) - return buf.raw + if isinstance(buf.raw, str): + return buf.raw + else: + return buf.raw.decode("charmap") - def __repr__(self): - return repr(str(self)) + def __bytes__(self): + buf = ctypes.create_string_buffer(len(self)) + ctypes.memmove(buf, core.BNGetDataBufferContents(self.handle), len(self)) + return buf.raw def escape(self): return core.BNDataBufferToEscapedString(self.handle) def unescape(self): - return DataBuffer(handle=core.BNDecodeEscapedString(str(self))) + return DataBuffer(handle=core.BNDecodeEscapedString(bytes(self))) def base64_encode(self): return core.BNDataBufferToBase64(self.handle) def base64_decode(self): - return DataBuffer(handle = core.BNDecodeBase64(str(self))) + return DataBuffer(handle = core.BNDecodeBase64(bytes(self))) def zlib_compress(self): buf = core.BNZlibCompress(self.handle) diff --git a/python/demangle.py b/python/demangle.py index 11673263..466324bc 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -21,8 +21,10 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core -import types +from binaryninja import _binaryninjacore as core + +# 2-3 compatibility +from binaryninja import range def get_qualified_name(names): @@ -56,26 +58,28 @@ def demangle_ms(arch, mangled_name): (<type: public: static enum Foobar::foo __cdecl (enum Foobar::foo)>, ['Foobar', 'testf']) >>> """ + from binaryninja import types handle = ctypes.POINTER(core.BNType)() outName = ctypes.POINTER(ctypes.c_char_p)() 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): - names.append(outName[i]) + for i in range(outSize.value): + names.append(outName[i].decode('charmap')) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) return (types.Type(handle), names) return (None, 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() names = [] if core.BNDemangleGNU3(arch.handle, mangled_name, ctypes.byref(handle), ctypes.byref(outName), ctypes.byref(outSize)): - for i in xrange(outSize.value): - names.append(outName[i]) + for i in range(outSize.value): + names.append(outName[i].decode('charmap')) core.BNFreeDemangledName(ctypes.byref(outName), outSize.value) if not handle: return (None, names) diff --git a/python/downloadprovider.py b/python/downloadprovider.py index d34ca358..09abd516 100644 --- a/python/downloadprovider.py +++ b/python/downloadprovider.py @@ -20,7 +20,6 @@ import abc -import code import ctypes import sys import traceback @@ -28,6 +27,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 +109,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/examples/bin_info.py b/python/examples/bin_info.py index 17a96685..05a72ed0 100644 --- a/python/examples/bin_info.py +++ b/python/examples/bin_info.py @@ -20,11 +20,15 @@ # 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: @@ -48,13 +52,13 @@ def get_bininfo(bv): contents += "| Start | Name |\n" contents += "|------:|:-------|\n" - for i in xrange(min(10, len(bv.functions))): + 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 xrange(min(10, len(bv.strings))): + for i in range(min(10, len(bv.strings))): start = bv.strings[i].start length = bv.strings[i].length string = bv.read(start, length) @@ -67,6 +71,6 @@ def display_bininfo(bv): if __name__ == "__main__": - print get_bininfo(None) + 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 index a2801511..cbcb86d4 100644 --- a/python/examples/breakpoint.py +++ b/python/examples/breakpoint.py @@ -44,7 +44,7 @@ def write_breakpoint(view, start, length): if bkpt is None: log_error(err) return - view.write(start, bkpt * length / len(bkpt)) + 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 index 7814c9fd..5bb27824 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -48,15 +48,15 @@ def save_svg(bv, function): def instruction_data_flow(function, address): ''' TODO: Extract data flow information ''' - length = function.view.get_instruction_length(address) - bytes = function.view.read(address, length) + 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 = function.create_graph() + graph = binaryninja.function.create_graph() graph.layout_and_wait() heightconst = 15 ratio = 0.48 diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py index 419cc188..4ed8dda2 100644 --- a/python/examples/jump_table.py +++ b/python/examples/jump_table.py @@ -43,16 +43,16 @@ def find_jump_table(bv, addr): break jump_addr += info.length if jump_addr >= block.end: - print "Unable to find jump after instruction 0x%x" % addr + print("Unable to find jump after instruction 0x%x" % addr) continue - print "Jump at 0x%x" % jump_addr + 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 + print("Found possible table at 0x%x" % tbl) i = 0 while True: # Read the next pointer from the table @@ -66,7 +66,7 @@ def find_jump_table(bv, addr): # If the pointer is within the binary, add it as a destination and continue # to the next entry if (ptr >= bv.start) and (ptr < bv.end): - print "Found destination 0x%x" % ptr + 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 diff --git a/python/examples/nds.py b/python/examples/nds.py index 34d8a292..a99303cf 100644 --- a/python/examples/nds.py +++ b/python/examples/nds.py @@ -27,12 +27,15 @@ 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 xrange(0, 8): + for bit in range(0, 8): if (crc & 1) == 1: crc = (crc >> 1) ^ 0xa001 else: diff --git a/python/examples/nes.py b/python/examples/nes.py index 00451abd..d3f75cc6 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -31,6 +31,10 @@ from binaryninja.log import log_error from binaryninja.enums import (BranchType, InstructionTextTokenType, LowLevelILOperation, LowLevelILFlagCondition, FlagRole, SegmentFlag, SymbolType) +# 2-3 compatibility +from binaryninja import range + + InstructionNames = [ "brk", "ora", None, None, None, "ora", "asl", None, # 0x00 "php", "ora", "asl@", None, None, "ora", "asl", None, # 0x08 @@ -631,7 +635,7 @@ class NESView(BinaryView): banks = [] -for i in xrange(0, 32): +for i in range(0, 32): class NESViewBank(NESView): bank = i name = "NES Bank %X" % i diff --git a/python/examples/notification_callbacks.py b/python/examples/notification_callbacks.py index b7c9cde9..02c74db9 100644 --- a/python/examples/notification_callbacks.py +++ b/python/examples/notification_callbacks.py @@ -1,51 +1,74 @@ -from binaryninja import BinaryDataNotification, PluginCommand, log_info +# 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 inspect +from binaryninja import BinaryDataNotification +from binaryninja import PluginCommand + + def reg_notif(view): - demo_notification = DemoNotification(view) - view.register_notification(demo_notification) + demo_notification = DemoNotification(view) + view.register_notification(demo_notification) class DemoNotification(BinaryDataNotification): - def __init__(self, view): - self.view = view + def __init__(self, view): + self.view = view - def data_written(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_written(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def data_inserted(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_inserted(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def data_removed(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_removed(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def function_added(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def function_added(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def function_removed(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def function_removed(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def function_updated(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def function_updated(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def data_var_added(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_var_added(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def data_var_updated(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_var_updated(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def data_var_removed(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def data_var_removed(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def string_found(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def string_found(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def string_removed(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def string_removed(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def type_defined(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def type_defined(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) - def type_undefined(self, *args): - log_info(inspect.stack()[0][3] + str(args)) + def type_undefined(self, *args): + log.log_info(inspect.stack()[0][3] + str(args)) PluginCommand.register("Register Notification", "", reg_notif) diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py index 3e1cab40..c990a6c0 100644 --- a/python/examples/version_switcher.py +++ b/python/examples/version_switcher.py @@ -34,15 +34,15 @@ def load_channel(newchannel): global channel global versions if (channel is not None and newchannel == channel.name): - print "Same channel, not updating." + print("Same channel, not updating.") else: try: - print "Loading channel %s" % newchannel + print("Loading channel %s" % newchannel) channel = UpdateChannel[newchannel] - print "Loading versions..." + print("Loading versions...") versions = channel.versions except Exception: - print "%s is not a valid channel name. Defaulting to " % chandefault + print("%s is not a valid channel name. Defaulting to " % chandefault) channel = UpdateChannel[chandefault] @@ -50,12 +50,12 @@ 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" + 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) @@ -65,44 +65,44 @@ def select(version): done = True elif (selection == 1): if (version.version == channel.latest_version.version): - print "Requesting update to latest version." + print("Requesting update to latest version.") else: - print "Requesting update to prior version." + print("Requesting update to prior version.") if are_auto_updates_enabled(): - print "Disabling automatic updates." + print("Disabling automatic updates.") set_auto_updates_enabled(False) if (version.version == core_version): - print "Already running %s" % version.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..." + 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" + print("Invalid selection") def list_channels(): done = False - print "\tSelect channel:\n" + 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") + 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 + print("%s is an invalid choice." % selection) else: done = True if (selection != len(channel_list) + 1): @@ -118,23 +118,23 @@ def main(): 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() + 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") + 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 + print("%d is an invalid choice.\n\n" % selection) else: if (selection == len(versions) + 3): done = True diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 2c1f1d19..c2539b39 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -22,9 +22,7 @@ import traceback import ctypes # Binary Ninja components -import _binaryninjacore as core -import log - +from binaryninja import _binaryninjacore as core class FileAccessor(object): def __init__(self): diff --git a/python/filemetadata.py b/python/filemetadata.py index 4bfc0214..cafe1d67 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -18,16 +18,15 @@ # 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 +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja import associateddatastore #required for _FileMetadataAssociatedDataStore +from binaryninja import log class NavigationHandler(object): def _register(self, handle): @@ -66,12 +65,13 @@ 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. """ + + _associated_data = {} + def __init__(self, filename = None, handle = None): """ Instantiates a new FileMetadata class. @@ -82,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)) @@ -167,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): @@ -322,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: @@ -341,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 2f794f47..0589a5e2 100644 --- a/python/function.py +++ b/python/function.py @@ -18,27 +18,25 @@ # 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, +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) -import architecture -import platform -import highlight -import associateddatastore -import types -import basicblock -import lowlevelil -import mediumlevelil -import binaryview -import log -import callingconvention + +# 2-3 compatibility +from binaryninja import range class LookupTableEntry(object): @@ -179,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 @@ -191,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 @@ -199,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): @@ -420,7 +418,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 @@ -432,7 +430,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 @@ -485,8 +483,8 @@ class Function(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) result = [] - for i in xrange(0, count.value): - result.append(basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i]))) + 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 @@ -496,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 @@ -504,17 +502,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): @@ -531,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) @@ -544,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) @@ -557,8 +555,8 @@ class Function(object): count = ctypes.c_ulonglong() 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)) + 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 @@ -578,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 @@ -612,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) @@ -623,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 @@ -637,7 +635,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): @@ -655,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) @@ -670,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 @@ -720,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) @@ -748,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) @@ -759,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 @@ -853,8 +851,8 @@ class Function(object): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) try: - for i in xrange(0, count.value): - yield basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) + for i in range(0, count.value): + yield binaryninja.basicblock.BasicBlock(self._view, core.BNNewBasicBlockReference(blocks[i])) finally: core.BNFreeBasicBlockList(blocks, count.value) @@ -924,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 @@ -936,7 +934,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') @@ -956,7 +954,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') @@ -978,7 +976,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 @@ -1023,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 @@ -1034,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 @@ -1045,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), @@ -1059,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 @@ -1080,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 @@ -1090,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 @@ -1099,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 @@ -1108,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 @@ -1126,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)) @@ -1135,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)) @@ -1146,8 +1144,8 @@ class Function(object): count = ctypes.c_ulonglong() 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)) + 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 @@ -1157,11 +1155,13 @@ 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 + 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 @@ -1193,7 +1193,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 @@ -1219,7 +1219,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 @@ -1276,7 +1276,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 @@ -1336,7 +1336,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): """ @@ -1464,10 +1464,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 @@ -1559,7 +1559,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) @@ -1657,17 +1657,17 @@ 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 = basicblock.BasicBlock(view, block) + block = binaryninja.basicblock.BasicBlock(view, block) return block @property @@ -1676,7 +1676,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): @@ -1715,14 +1715,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 @@ -1742,7 +1742,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: @@ -1751,11 +1751,11 @@ 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 = [] - 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) @@ -1779,14 +1779,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 @@ -1838,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 @@ -1883,7 +1884,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 @@ -1941,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): @@ -1962,7 +1963,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) @@ -1971,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()) @@ -1995,17 +1999,22 @@ 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() 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/functionrecognizer.py b/python/functionrecognizer.py index 4ac304ca..319bff0e 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -21,15 +21,15 @@ import traceback # Binary Ninja components -import _binaryninjacore as core -import function -import filemetadata -import binaryview -import lowlevelil -import log +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): + _instance = None def __init__(self): diff --git a/python/generator.cpp b/python/generator.cpp index f838b36d..2da856ff 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -117,7 +117,7 @@ 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)"); @@ -173,7 +173,7 @@ int main(int argc, char* argv[]) } bool ok = arch->GetStandalonePlatform()->ParseTypesFromSourceFile(argv[1], types, vars, funcs, errors); - fprintf(stderr, "Errors: %s", errors.c_str()); + fprintf(stderr, "Errors: %s\n", errors.c_str()); if (!ok) return 1; @@ -200,6 +200,12 @@ int main(int argc, char* argv[]) fprintf(out, "else:\n"); fprintf(out, "\traise Exception(\"OS not supported\")\n\n"); + fprintf(out, "def cstr(arg):\n"); + fprintf(out, "\tif isinstance(arg, str):\n"); + fprintf(out, "\t\treturn arg.encode('charmap')\n"); + fprintf(out, "\telse:\n"); + fprintf(out, "\t\treturn arg\n\n"); + // Create type objects fprintf(out, "# Type definitions\n"); for (auto& i : types) @@ -211,7 +217,23 @@ int main(int argc, char* argv[]) if (i.second->GetClass() == StructureTypeClass) { fprintf(out, "class %s(ctypes.Structure):\n", name.c_str()); - fprintf(out, "\tpass\n"); + + // python uses str's, C uses byte-arrays + bool stringField = false; + for (auto& arg : i.second->GetStructure()->GetMembers()) + { + if ((arg.type->GetClass() == PointerTypeClass) && + (arg.type->GetChildType()->GetWidth() == 1) && + (arg.type->GetChildType()->IsSigned())) + { + fprintf(out, "\t@property\n\tdef %s(self):\n\t\treturn self._%s.decode('charmap')\n", arg.name.c_str(), arg.name.c_str()); + fprintf(out, "\t@%s.setter\n\tdef %s(self, value):\n\t\tself._%s = value.encode('charmap')\n", arg.name.c_str(), arg.name.c_str(), arg.name.c_str()); + stringField = true; + } + } + + if (!stringField) + fprintf(out, "\tpass\n"); } else if (i.second->GetClass() == EnumerationTypeClass) { @@ -227,7 +249,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); @@ -276,7 +298,15 @@ int main(int argc, char* argv[]) fprintf(out, "%s._fields_ = [\n", name.c_str()); for (auto& j : type->GetStructure()->GetMembers()) { - fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); + // To help the python->C wrappers + if ((j.type->GetClass() == PointerTypeClass) && + (j.type->GetChildType()->GetWidth() == 1) && + (j.type->GetChildType()->IsSigned())) + { + fprintf(out, "\t\t(\"_%s\", ", j.name.c_str()); + } + else + fprintf(out, "\t\t(\"%s\", ", j.name.c_str()); OutputType(out, j.type); fprintf(out, "),\n"); } @@ -310,6 +340,22 @@ int main(int argc, char* argv[]) (i.second->GetChildType()->GetChildType()->IsSigned()); // Pointer returns will be automatically wrapped to return None on null pointer bool pointerResult = (i.second->GetChildType()->GetClass() == PointerTypeClass); + + // From python -> C python3 requires str -> str.encode('charmap') + bool stringArgument = false; + for (auto& arg : i.second->GetParameters()) + { + if ((arg.type->GetClass() == PointerTypeClass) && + (arg.type->GetChildType()->GetWidth() == 1) && + (arg.type->GetChildType()->IsSigned())) + { + stringArgument = true; + break; + } + } + if (name == "BNFreeString") + stringArgument = false; + bool callbackConvention = false; if (name == "BNAllocString") { @@ -321,7 +367,7 @@ int main(int argc, char* argv[]) } string funcName = name; - if (stringResult || pointerResult) + if (stringResult || pointerResult || stringArgument) funcName = string("_") + funcName; fprintf(out, "%s = core.%s\n", funcName.c_str(), name.c_str()); @@ -354,8 +400,30 @@ int main(int argc, char* argv[]) { // Emit wrapper to get Python string and free native memory fprintf(out, "def %s(*args):\n", name.c_str()); - fprintf(out, "\tresult = %s(*args)\n", funcName.c_str()); - fprintf(out, "\tstring = ctypes.cast(result, ctypes.c_char_p).value\n"); + if (stringArgument) + { + fprintf(out, "\tresult = %s(", funcName.c_str()); + string stringArgFuncCall = ""; + size_t argN = 0; + for (auto& arg : i.second->GetParameters()) + { + if ((arg.type->GetClass() == PointerTypeClass) && + (arg.type->GetChildType()->GetWidth() == 1) && + (arg.type->GetChildType()->IsSigned())) + { + stringArgFuncCall += "cstr(args[" + to_string(argN) + "]), "; + } + else + stringArgFuncCall += "args[" + to_string(argN) + "], "; + argN++; + } + stringArgFuncCall = stringArgFuncCall.substr(0, stringArgFuncCall.size()-2); + stringArgFuncCall += ")\n"; + fprintf(out, "%s", stringArgFuncCall.c_str()); + } + else + fprintf(out, "\tresult = %s(*args)\n", funcName.c_str()); + fprintf(out, "\tstring = str(ctypes.cast(result, ctypes.c_char_p).value.decode('charmap'))\n"); fprintf(out, "\tBNFreeString(result)\n"); fprintf(out, "\treturn string\n"); } @@ -363,18 +431,76 @@ int main(int argc, char* argv[]) { // Emit wrapper to return None on null pointer fprintf(out, "def %s(*args):\n", name.c_str()); - fprintf(out, "\tresult = %s(*args)\n", funcName.c_str()); + if (stringArgument) + { + fprintf(out, "\tresult = %s(", funcName.c_str()); + string stringArgFuncCall = ""; + size_t argN = 0; + for (auto& arg : i.second->GetParameters()) + { + if ((arg.type->GetClass() == PointerTypeClass) && + (arg.type->GetChildType()->GetWidth() == 1) && + (arg.type->GetChildType()->IsSigned())) + { + stringArgFuncCall += "cstr(args[" + to_string(argN) + "]), "; + } + else + stringArgFuncCall += "args[" + to_string(argN) + "], "; + argN++; + } + stringArgFuncCall = stringArgFuncCall.substr(0, stringArgFuncCall.size()-2); + stringArgFuncCall += ")\n"; + fprintf(out, "%s", stringArgFuncCall.c_str()); + } + else + fprintf(out, "\tresult = %s(*args)\n", funcName.c_str()); fprintf(out, "\tif not result:\n"); fprintf(out, "\t\treturn None\n"); fprintf(out, "\treturn result\n"); } + else if (stringArgument) + { + fprintf(out, "def %s(*args):\n", name.c_str()); + { + fprintf(out, "\treturn %s(", funcName.c_str()); + string stringArgFuncCall = ""; + size_t argN = 0; + for (auto& arg : i.second->GetParameters()) + { + if ((arg.type->GetClass() == PointerTypeClass) && + (arg.type->GetChildType()->GetWidth() == 1) && + (arg.type->GetChildType()->IsSigned())) + { + stringArgFuncCall += "cstr(args[" + to_string(argN) + "]), "; + } + else + stringArgFuncCall += "args[" + to_string(argN) + "], "; + argN++; + } + stringArgFuncCall = stringArgFuncCall.substr(0, stringArgFuncCall.size()-2); + stringArgFuncCall += ")\n"; + fprintf(out, "%s", stringArgFuncCall.c_str()); + } + } + fprintf(out, "\n"); } fprintf(out, "\n# Helper functions\n"); 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"); + + // The following method is addapted from python/enum/__init__.py, lines 25-36 + fprintf(out, "\ntry:\n"); + fprintf(out, "\tbasestring\n"); + fprintf(out, "\tunicode\n"); + fprintf(out, "except NameError:\n"); + fprintf(out, "\t# In Python 2 basestring is the ancestor of both str and unicode\n"); + fprintf(out, "\t# in Python 3 it's just str, but was missing in 3.1\n"); + fprintf(out, "\t# In Python 3 unicode no longer exists (it's just str)\n"); + fprintf(out, "\tbasestring = str\n"); + fprintf(out, "\tunicode = str\n"); fprintf(out, "\n# Set path for core plugins\n"); fprintf(out, "BNSetBundledPluginDirectory(os.path.join(_base_path, \"plugins\"))\n"); diff --git a/python/highlight.py b/python/highlight.py index 96bc543d..55246a9a 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -20,8 +20,8 @@ # Binary Ninja components -import _binaryninjacore as core -from enums import HighlightColorStyle, HighlightStandardColor +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..49b4e024 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -22,10 +22,12 @@ import ctypes import traceback # Binary Ninja components -import _binaryninjacore as core -from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult -import binaryview -import log +from binaryninja import _binaryninjacore as core +from binaryninja.enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult +from binaryninja import binaryview + +# 2-3 compatibility +from binaryninja import range class LabelField(object): @@ -151,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 @@ -162,8 +168,8 @@ 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)): - choice_buf[i] = str(self.choices[i]) + for i in range(0, len(self.choices)): + choice_buf[i] = self.choices[i].encode('charmap') value.choices = choice_buf value.count = len(self.choices) @@ -330,7 +336,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 +379,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 +397,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 +410,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,8 +619,8 @@ def get_choice_input(prompt, title, choices): 0L """ choice_buf = (ctypes.c_char_p * len(choices))() - for i in xrange(0, len(choices)): - choice_buf[i] = str(choices[i]) + for i in range(0, len(choices)): + 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 @@ -724,11 +730,11 @@ 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))() - 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 +743,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/log.py b/python/log.py index b1fd7095..9a5e1358 100644 --- a/python/log.py +++ b/python/log.py @@ -20,8 +20,8 @@ # Binary Ninja components -import _binaryninjacore as core -from enums import LogLevel +from binaryninja import _binaryninjacore as core +from binaryninja.enums import LogLevel _output_to_log = False @@ -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 bd1e9349..e714eb48 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -19,14 +19,16 @@ # IN THE SOFTWARE. import ctypes +import struct # Binary Ninja components -import _binaryninjacore as core -from .enums import LowLevelILOperation, LowLevelILFlagCondition, InstructionTextTokenType -import function -import basicblock -import mediumlevelil -import struct +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 binaryninja import range class LowLevelILLabel(object): @@ -414,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": @@ -422,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": @@ -430,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: @@ -441,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)) @@ -451,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)) @@ -461,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)) @@ -471,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: @@ -484,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: @@ -521,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 @@ -530,7 +532,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 +554,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 +562,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 +605,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 +696,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. @@ -777,7 +779,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 @@ -804,7 +806,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): @@ -814,7 +816,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: @@ -844,7 +846,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 +864,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 +2180,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 +2193,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 +2276,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 +2286,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 +2295,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 @@ -2301,13 +2303,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): @@ -2353,7 +2355,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/mainthread.py b/python/mainthread.py index 3e12bd65..5b0cd53c 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -19,8 +19,8 @@ # IN THE SOFTWARE. # Binary Ninja components -import _binaryninjacore as core -import scriptingprovider +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..cfa8f900 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -19,15 +19,18 @@ # IN THE SOFTWARE. import ctypes +import struct # Binary Ninja components -import _binaryninjacore as core -from .enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence -import function -import basicblock -import lowlevelil -import types -import struct +from binaryninja import _binaryninjacore as core +from binaryninja.enums import MediumLevelILOperation, InstructionTextTokenType, ILBranchDependence +from binaryninja import basicblock #required for MediumLevelILBasicBlock argument +from binaryninja import function +from binaryninja import types +from binaryninja import lowlevelil + +# 2-3 compatibility +from binaryninja import range class SSAVariable(object): @@ -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 @@ -596,7 +599,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. """ @@ -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 554bbcf4..b17bbf4f 100644 --- a/python/metadata.py +++ b/python/metadata.py @@ -19,11 +19,15 @@ # IN THE SOFTWARE. +from __future__ import absolute_import import ctypes # Binary Ninja components -import _binaryninjacore as core -from enums import MetadataType +from binaryninja import _binaryninjacore as core +from binaryninja.enums import MetadataType + +# 2-3 compatibility +from binaryninja import range class Metadata(object): @@ -39,7 +43,7 @@ class Metadata(object): self.handle = core.BNCreateMetadataBooleanData(value) elif isinstance(value, str): if raw: - buffer = (ctypes.c_ubyte * len(value)).from_buffer_copy(value) + buffer = (ctypes.c_ubyte * len(value)).from_buffer_copy(value.encode('charmap')) self.handle = core.BNCreateMetadataRawData(buffer, len(value)) else: self.handle = core.BNCreateMetadataStringData(value) @@ -137,13 +141,16 @@ 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): - yield result.contents.keys[i] + for i in range(result.contents.size): + if isinstance(result.contents.keys[i], bytes): + yield str(result.contents.keys[i].decode('charmap')) + else: + yield result.contents.keys[i] finally: core.BNFreeMetadataValueStore(result) else: @@ -168,13 +175,13 @@ class Metadata(object): def __str__(self): if self.is_string: - return core.BNMetadataGetString(self.handle) + return str(core.BNMetadataGetString(self.handle)) if self.is_raw: length = ctypes.c_ulonglong() 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 dd756178..9a5f70df 100644 --- a/python/platform.py +++ b/python/platform.py @@ -21,42 +21,45 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core -import startup -import architecture -import callingconvention -import types +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja import types + +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _PlatformMetaClass(type): + @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() 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 @property def os_list(self): - startup._init_plugins() + binaryninja._init_plugins() 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 def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) @@ -68,14 +71,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) @@ -84,18 +87,17 @@ 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 -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 name = None def __init__(self, arch, handle = None): @@ -105,7 +107,7 @@ class Platform(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) @@ -137,7 +139,7 @@ class Platform(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): @@ -155,7 +157,7 @@ class Platform(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): @@ -173,7 +175,7 @@ class Platform(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): @@ -191,7 +193,7 @@ class Platform(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): @@ -209,7 +211,7 @@ class Platform(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): @@ -226,8 +228,8 @@ class Platform(object): count = ctypes.c_ulonglong() cc = core.BNGetPlatformCallingConventions(self.handle, count) result = [] - for i in xrange(0, count.value): - result.append(callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) + for i in range(0, count.value): + result.append(binaryninja.callingconvention.CallingConvention(handle=core.BNNewCallingConventionReference(cc[i]))) core.BNFreeCallingConventionList(cc, count.value) return result @@ -237,7 +239,7 @@ class Platform(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 = 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) @@ -249,7 +251,7 @@ class Platform(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 = 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) @@ -261,7 +263,7 @@ class Platform(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 = 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) @@ -273,7 +275,7 @@ class Platform(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 = 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) @@ -388,8 +390,8 @@ class Platform(object): if filename is None: filename = "input" dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) + for i in range(0, len(include_dirs)): + 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, @@ -401,13 +403,13 @@ class Platform(object): type_dict = {} variables = {} functions = {} - for i in xrange(0, parse.typeCount): + for i in range(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) - for i in xrange(0, parse.variableCount): + for i in range(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) - for i in xrange(0, parse.functionCount): + for i in range(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) core.BNFreeTypeParserResult(parse) @@ -434,8 +436,8 @@ class Platform(object): >>> """ dir_buf = (ctypes.c_char_p * len(include_dirs))() - for i in xrange(0, len(include_dirs)): - dir_buf[i] = str(include_dirs[i]) + for i in range(0, len(include_dirs)): + 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, @@ -447,13 +449,13 @@ class Platform(object): type_dict = {} variables = {} functions = {} - for i in xrange(0, parse.typeCount): + for i in range(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) - for i in xrange(0, parse.variableCount): + for i in range(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) - for i in xrange(0, parse.functionCount): + for i in range(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) core.BNFreeTypeParserResult(parse) diff --git a/python/plugin.py b/python/plugin.py index 13ca51af..2fc30052 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -23,15 +23,17 @@ 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 +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 binaryninja import range +from binaryninja import with_metaclass class PluginCommandContext(object): @@ -46,21 +48,21 @@ class PluginCommandContext(object): class _PluginCommandMetaClass(type): @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() 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 def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) @@ -72,9 +74,8 @@ class _PluginCommandMetaClass(type): raise AttributeError("attribute '%s' is read only" % name) -class PluginCommand(object): +class PluginCommand(with_metaclass(_PluginCommandMetaClass, object)): _registered_commands = [] - __metaclass__ = _PluginCommandMetaClass def __init__(self, cmd): self.command = core.BNPluginCommand() @@ -91,8 +92,8 @@ class PluginCommand(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()) @@ -100,8 +101,8 @@ class PluginCommand(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()) @@ -109,8 +110,8 @@ class PluginCommand(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()) @@ -118,8 +119,8 @@ class PluginCommand(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)) + file_metadata = binaryninja.filemetadata.FileMetadata(handle = core.BNGetFileForView(view)) + view_obj = binaryninja.binaryview.BinaryView(file_metadata = file_metadata, handle = core.BNNewViewReference(view)) func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) action(view_obj, func_obj) except: @@ -131,7 +132,7 @@ class PluginCommand(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()) @@ -142,7 +143,7 @@ class PluginCommand(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()) @@ -153,7 +154,7 @@ class PluginCommand(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()) @@ -164,7 +165,7 @@ class PluginCommand(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()) @@ -174,8 +175,8 @@ class PluginCommand(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()) @@ -186,8 +187,8 @@ class PluginCommand(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()) @@ -198,8 +199,8 @@ class PluginCommand(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()) @@ -210,8 +211,8 @@ class PluginCommand(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)) func_obj = function.Function(view_obj, core.BNNewFunctionReference(func)) return is_valid(view_obj, func_obj) except: @@ -226,7 +227,7 @@ class PluginCommand(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()) @@ -240,7 +241,7 @@ class PluginCommand(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()) @@ -254,7 +255,7 @@ class PluginCommand(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()) @@ -268,7 +269,7 @@ class PluginCommand(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()) @@ -287,7 +288,7 @@ class PluginCommand(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)) @@ -306,7 +307,7 @@ class PluginCommand(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)) @@ -325,7 +326,7 @@ class PluginCommand(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)) @@ -344,7 +345,7 @@ class PluginCommand(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)) @@ -363,7 +364,7 @@ class PluginCommand(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)) @@ -382,7 +383,7 @@ class PluginCommand(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)) @@ -401,7 +402,7 @@ class PluginCommand(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)) @@ -420,7 +421,7 @@ class PluginCommand(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)) @@ -468,7 +469,7 @@ class PluginCommand(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 @@ -483,7 +484,7 @@ class PluginCommand(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 @@ -564,25 +565,23 @@ 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 def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) -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: self.handle = core.BNBeginBackgroundTask(initial_progress_text, can_cancel) diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 0cc43aca..c7a0c83a 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -21,9 +21,10 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core -from .enums import PluginType, PluginUpdateStatus -import startup +from binaryninja import _binaryninjacore as core + +# 2-3 compatibility +from binaryninja import range class RepoPlugin(object): @@ -31,6 +32,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) @@ -111,7 +113,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 @@ -183,7 +185,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 @@ -236,7 +238,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 9cacc6ad..37642ed4 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -26,14 +26,15 @@ 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 +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja.enums import ScriptingProviderExecuteResult, ScriptingProviderInputReadyState +from binaryninja import log + +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _ThreadActionContext(object): @@ -135,7 +136,7 @@ class ScriptingInstance(object): 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) @@ -145,12 +146,12 @@ class ScriptingInstance(object): 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()) + log.log_error(traceback.format_exc()) def _set_current_basic_block(self, ctxt, block): try: @@ -159,7 +160,7 @@ 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 @@ -256,30 +257,31 @@ class ScriptingInstance(object): class _ScriptingProviderMetaclass(type): + @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 = [] - for i in xrange(0, count.value): + for i in range(0, count.value): result.append(ScriptingProvider(types[i])) core.BNFreeScriptingProviderList(types) return result def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) 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)) @@ -292,8 +294,7 @@ class _ScriptingProviderMetaclass(type): raise AttributeError("attribute '%s' is read only" % name) -class ScriptingProvider(object): - __metaclass__ = _ScriptingProviderMetaclass +class ScriptingProvider(with_metaclass(_ScriptingProviderMetaclass, object)): name = None instance_class = None @@ -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 d58c8955..355492aa 100644 --- a/python/setting.py +++ b/python/setting.py @@ -21,7 +21,10 @@ import ctypes # Binary Ninja components -import _binaryninjacore as core +from binaryninja import _binaryninjacore as core + +# 2-3 compatibility +from binaryninja import range class Setting(object): @@ -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 @@ -55,11 +58,11 @@ class Setting(object): length.value = len(default_value) default_list = (ctypes.c_char_p * len(default_value))() for i in range(len(default_value)): - default_list[i] = default_value[i] + default_list[i] = default_value[i].encode('charmap') result = core.BNSettingGetStringList(self.plugin_name, name, default_list, ctypes.byref(length)) out_list = [] - for i in xrange(length.value): - out_list.append(result[i]) + for i in range(length.value): + out_list.append(result[i].decode('charmap')) 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,8 +112,8 @@ 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)): - default_list[i] = str(value[i]) + for i in range(len(value)): + default_list[i] = value[i].encode('charmap') return core.BNSettingSetStringList(self.plugin_name, name, default_list, length, auto_flush) @@ -138,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/startup.py b/python/startup.py index 0abc47cb..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. -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 3284ed74..1734d248 100644 --- a/python/transform.py +++ b/python/transform.py @@ -23,31 +23,35 @@ import ctypes import abc # Binary Ninja components -import _binaryninjacore as core -from enums import TransformType -import startup -import log -import databuffer +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 binaryninja import range +from binaryninja import with_metaclass class _TransformMetaClass(type): @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() 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 def __iter__(self): - startup._init_plugins() + binaryninja._init_plugins() 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) @@ -59,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: @@ -90,14 +94,13 @@ class TransformParameter(object): self.fixed_length = fixed_length -class Transform(object): +class Transform(with_metaclass(_TransformMetaClass, object)): transform_type = None name = None long_name = None group = None parameters = [] _registered_cb = None - __metaclass__ = _TransformMetaClass def __init__(self, handle): if handle is None: @@ -124,7 +127,7 @@ class Transform(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) @@ -145,7 +148,7 @@ class Transform(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 @@ -170,7 +173,7 @@ class Transform(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) @@ -187,7 +190,7 @@ class Transform(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) @@ -218,9 +221,9 @@ class Transform(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 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 @@ -231,9 +234,9 @@ class Transform(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 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 42ed7ddd..e8ce7464 100644 --- a/python/types.py +++ b/python/types.py @@ -18,25 +18,31 @@ # 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 +import binaryninja +from binaryninja import _binaryninjacore as core +from binaryninja.enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType, ReferenceType, VariableSourceType + +# 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 = name + self.name = [i.decode('charmap') for i in name] + self.byte_name = name def __str__(self): return "::".join(self.name) @@ -98,8 +104,8 @@ 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)): - name_list[i] = self.name[i] + for i in range(0, len(self.name)): + name_list[i] = self.name[i].encode('charmap') result.name = name_list result.nameCount = len(self.name) return result @@ -107,7 +113,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) @@ -292,7 +298,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): @@ -300,7 +306,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 @@ -310,7 +316,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) @@ -344,7 +350,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 +382,7 @@ class Type(object): def __repr__(self): if self.confidence < max_confidence: - return "<type: %s, %d%% confidence>" % (str(self), (self.confidence * 100) / max_confidence) + return "<type: %s, %d%% confidence>" % (str(self), (self.confidence * 100) // max_confidence) return "<type: %s>" % str(self) def get_string_before_name(self): @@ -403,7 +409,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 @@ -412,7 +418,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 @@ -423,7 +429,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 @@ -432,7 +438,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 @@ -443,7 +449,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 @@ -452,7 +458,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 @@ -574,7 +580,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 +857,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 +968,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,8 +1024,8 @@ 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)): - dir_buf[i] = str(include_dirs[i]) + for i in range(0, len(include_dirs)): + 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 7e3c76a0..7891bf54 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -23,10 +23,8 @@ import json import ctypes # Binary Ninja components -import _binaryninjacore as core -from enums import ActionType -import startup -import log +from binaryninja import _binaryninjacore as core +from binaryninja.enums import ActionType class UndoAction(object): @@ -52,7 +50,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 1eb8ea61..7f5d6f9c 100644 --- a/python/update.py +++ b/python/update.py @@ -22,16 +22,18 @@ import traceback import ctypes # Binary Ninja components -import _binaryninjacore as core -from enums import UpdateResult -import startup -import log +from binaryninja import _binaryninjacore as core +from binaryninja.enums import UpdateResult + +# 2-3 compatibility +from binaryninja import range +from binaryninja import with_metaclass class _UpdateChannelMetaClass(type): @property def list(self): - startup._init_plugins() + binaryninja._init_plugins() count = ctypes.c_ulonglong() errors = ctypes.c_char_p() channels = core.BNGetUpdateChannels(count, errors) @@ -40,7 +42,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 @@ -54,7 +56,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) @@ -63,7 +65,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) @@ -75,7 +77,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) @@ -84,7 +86,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 @@ -108,9 +110,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 self.description = desc @@ -127,7 +127,7 @@ class UpdateChannel(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 @@ -143,7 +143,7 @@ class UpdateChannel(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 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/api_test.py b/suite/api_test.py index a162d26a..740f88e3 100644 --- a/suite/api_test.py +++ b/suite/api_test.py @@ -1,17 +1,10 @@ import unittest -import time import platform import os -import tempfile -import zipfile -import urllib -import subprocess -import getpass from binaryninja.setting import Setting from binaryninja.metadata import Metadata from binaryninja.demangle import demangle_gnu3, get_qualified_name from binaryninja.architecture import Architecture -from binaryninja.binaryview import BinaryViewType class SettingsAPI(unittest.TestCase): @@ -226,39 +219,3 @@ class DemanglerTest(unittest.TestCase): for i, test in enumerate(tests): t, n = demangle_gnu3(Architecture['x86'], test) assert self.get_type_string(t, n) == results[i] - - -class TimingTest(unittest.TestCase): - def unpackage_file(self, file): - if not os.path.exists(file): - with zipfile.ZipFile(file + ".zip", "r") as zf: - zf.extractall() - assert os.path.exists(file) - - def test_analysis_time(self): - if platform.system() != "Linux" or getpass.getuser() != "jenkins": - return - - start_time = time.time() - file_names = [os.path.join(os.path.dirname(__file__), "binaries", "quick3dcoreplugin.dll"), - os.path.join(os.path.dirname(__file__), "binaries", "md5"), - os.path.join(os.path.dirname(__file__), "binaries", "ls")] - - for file_name in file_names: - temp_name = next(tempfile._get_candidate_names()) + ".bndb" - self.unpackage_file(file_name) - try: - bv = BinaryViewType.get_view_of_file(file_name) - bv.create_database(temp_name) - bv.file.close() - bv = BinaryViewType.get_view_of_file(temp_name) - bv.file.close() - finally: - if os.path.exists(file_name): - os.unlink(file_name) - if os.path.exists(temp_name): - os.unlink(temp_name) - - time_s = time.time() - start_time - commit = subprocess.check_output(["git", "rev-parse", "HEAD"])[:-1] - conn = urllib.urlopen("https://script.google.com/macros/s/AKfycbxrZtlgLaWt3l95_7RyH9ceDdFIBm0VaR6jG1-4UDt6CFFCFzQ/exec?BuildID=%s&Test1=%.2f" % (commit, time_s)) diff --git a/suite/binaries b/suite/binaries -Subproject 7d5d207de812ccd7c4648331b00fa936ef0a82c +Subproject 96d08bbb4fdcf1b88c98165fcfe8474659c38d6 diff --git a/suite/generator.py b/suite/generator.py index 347d0d84..09ee00dc 100755 --- a/suite/generator.py +++ b/suite/generator.py @@ -10,41 +10,99 @@ 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 difflib +from collections import Counter + +api_suite_path = os.path.join(os.path.dirname(__file__), {4}) +sys.path.append(api_suite_path) import testcommon -import binaryninja import api_test -import difflib +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}") + pickle_path = os.path.join(os.path.dirname(__file__), "oracle.pkl") 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(pickle_path, "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(pickle_path, "rb")) self.verifybuilder = testcommon.VerifyBuilder("{3}") def run_binary_test(self, testfile): testname = None - with zipfile.ZipFile(testfile, "r") as zf: + with zipfile.ZipFile(os.path.join(api_suite_path, testfile), "r") as zf: testname = zf.namelist()[0] - zf.extractall() + zf.extractall(path=api_suite_path) - self.assertTrue(os.path.exists(testname + ".pkl"), "Test pickle doesn't exist") + pickle_path = os.path.join(os.path.dirname(__file__), testname + ".pkl") + self.assertTrue(pickle_path, "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(pickle_path, "rb"), encoding='charmap') except TypeError: - binary_oracle = pickle.load(open(testname + ".pkl", "rU")) + binary_oracle = pickle.load(open(pickle_path, "rb")) - test_builder = testcommon.BinaryViewTestBuilder(testname, "{3}") + test_builder = testcommon.BinaryViewTestBuilder(testname) for method in test_builder.methods(): test = getattr(test_builder, method)() oracle = binary_oracle[method] @@ -53,22 +111,15 @@ 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) - os.unlink(testname) + report = self.report(oracle, test, result) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle + os.unlink(os.path.join(api_suite_path, 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)) @@ -81,11 +132,13 @@ binary_test_string = """ def test_binary__{0}(self): self.run_binary_test('{1}') """ + test_string = """ def {0}(self): oracle = self.oracle_test_data['{0}'] test = self.builder.{0}() - self.assertTrue(oracle == test, "%s:\\n'%s' does not equal\\n'%s'" % (self.builder.{0}.__doc__, oracle, test)) + report = self.report(oracle, test) + self.assertTrue(report[0], report[1]) # Test does not agree with oracle """ verify_string = """ @@ -97,7 +150,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 = {} @@ -120,7 +173,11 @@ 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')) + api_path = os.path.relpath(os.path.dirname(__file__), start=self.outdir) + api_path = os.path.normpath(api_path) + api_path = map(lambda x: '"{0}"'.format(x), api_path.split(os.sep)) + api_path = '{0}'.format(', '.join(api_path)) + self.f.write(self.template.format(self.outdir, self.tests, self.binary_tests, self.test_store, api_path).encode('charmap')) self.f.close() def add_verify(self, test_name): @@ -135,8 +192,6 @@ class UnitTestFile: quiet = False - - def myprint(stuff): if not quiet: print(stuff) @@ -164,7 +219,7 @@ class TestStoreError(Exception): def generate(test_store, outdir, exclude_binaries): - if not os.path.isdir(test_store): + if not os.path.isdir(os.path.join(os.path.dirname(__file__), test_store)): raise TestStoreError("Specified test store is not a directory") unittest = UnitTestFile(os.path.join(outdir, "unit.py"), outdir, test_store) @@ -193,10 +248,12 @@ def generate(test_store, outdir, exclude_binaries): oraclefile = None if testfile.endswith(".pkl"): continue + elif testfile.endswith(".DS_Store"): + continue elif testfile.endswith(".zip"): # We have a zipped binary unzip it so we can rebaseline with zipfile.ZipFile(testfile, "r") as zf: - zf.extractall() + zf.extractall(path = os.path.dirname(__file__)) if not os.path.exists(testfile[:-4]): print("Error extracting testfile %s from zip: %s" % (testfile[:-4], testfile)) continue @@ -208,14 +265,16 @@ def generate(test_store, outdir, exclude_binaries): # We have a binary that isn't zipped use it as a new test case oraclefile = testfile + oraclefile_rel = os.path.relpath(oraclefile, start=os.path.dirname(__file__)) + # Now generate the oracle data - update_progress(progress, len(allfiles), oraclefile) - unittest.add_binary_test(test_store, oraclefile) + update_progress(progress, len(allfiles), oraclefile_rel) + unittest.add_binary_test(test_store, oraclefile_rel) binary_start_time = time.time() if exclude_binaries: continue - test_data = testcommon.BinaryViewTestBuilder(oraclefile, test_store) - binary_oracle = OracleTestFile(oraclefile) + test_data = testcommon.BinaryViewTestBuilder(oraclefile_rel) + binary_oracle = OracleTestFile(os.path.join(outdir, oraclefile_rel)) for method in test_data.methods(): binary_oracle.add_entry(test_data, method) binary_oracle.close() @@ -223,7 +282,7 @@ def generate(test_store, outdir, exclude_binaries): if not os.path.exists(oraclefile + ".zip"): with zipfile.ZipFile(oraclefile + ".zip", "w") as zf: - zf.write(oraclefile) + zf.write(oraclefile, os.path.relpath(oraclefile, start=os.path.dirname(__file__))) os.unlink(oraclefile) @@ -243,17 +302,13 @@ def main(): default=False, help="Exclude regeneration of binaries") parser.add_option("-o", "--outputdir", default="suite", dest="outputdir", action="store", type="string", - help="output directory where the unit.py and oracle.py files will be stored") - parser.add_option("-i", "--inputdir", default=os.path.join("suite", "binaries", "test_corpus"), + help="output directory where the unit.py and oracle.py files will be stored (relative to cwd)") + parser.add_option("-i", "--inputdir", default=os.path.join("binaries", "test_corpus"), dest="test_store", action="store", type="string", - help="input directory containing the binaries you which to generate unit tests from") + help="input directory containing the binaries you which to generate unit tests from (relative to this file)") options, args = parser.parse_args() - if not os.path.exists(os.path.join(os.getcwd(), 'suite')): - print("Error: Please run this script from the binaryninja-api root directory") - sys.exit(1) - myprint("[+] INFO: Using test store: %s" % options.test_store) if len(testcommon.get_file_list(options.test_store)) == 0: myprint("ERROR: No files in the test store %s" % testcommon.get_file_list(options.test_store)) diff --git a/suite/oracle.pkl b/suite/oracle.pkl Binary files differindex bf1a4b3b..f0be17d4 100644 --- a/suite/oracle.pkl +++ b/suite/oracle.pkl diff --git a/suite/testcommon.py b/suite/testcommon.py index 4e004630..285c24b5 100644 --- a/suite/testcommon.py +++ b/suite/testcommon.py @@ -1,29 +1,74 @@ 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 -def get_file_list(test_store): +# 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 <in set([blah, blah, blah])> +def fixSet(string): + # Apply regular expression + splitList = (re.split(r"((?<=<in set\(\[).*(?=\]\)>))", string)) + if len(splitList) > 1: + return splitList[0] + ', '.join(sorted(splitList[1].split(', '))) + splitList[2] + else: + return string + + +def get_file_list(test_store_rel): + test_store = os.path.join(os.path.dirname(__file__), test_store_rel) all_files = [] 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 + return type_string class Builder(object): def __init__(self, test_store): self.test_store = test_store - self.examples_dir = os.path.join(self.test_store, "..", "..", "..", "python", "examples") + # binja.log.log_to_stdout(binja.LogLevel.DebugLog) # Uncomment for more info def methods(self): methodnames = [] @@ -32,11 +77,13 @@ class Builder(object): methodnames.append(methodname) return methodnames - def unpackage_file(self, file): - if not os.path.exists(file): - with zipfile.ZipFile(file + ".zip", "r") as zf: - zf.extractall() - assert os.path.exists(file) + def unpackage_file(self, filename): + path = os.path.join(os.path.dirname(__file__), self.test_store, filename) + if not os.path.exists(path): + with zipfile.ZipFile(path + ".zip", "r") as zf: + zf.extractall(path = os.path.dirname(__file__)) + assert os.path.exists(path) + return os.path.relpath(path) class BinaryViewTestBuilder(Builder): @@ -48,61 +95,72 @@ class BinaryViewTestBuilder(Builder): - Function doc string used as 'on error' message - Should return: list of strings """ - def __init__(self, filename, test_store): - self.filename = filename - self.bv = BinaryViewType.get_view_of_file(filename) + def __init__(self, filename): + self.filename = os.path.join(os.path.dirname(__file__), filename) + self.bv = BinaryViewType.get_view_of_file(self.filename) if self.bv is None: print("%s is not an executable format" % filename) return def test_available_types(self): """Available types don't match""" - return [x.name for x in BinaryView(FileMetadata()).open(self.filename).available_view_types] + return ["Available Type: " + x.name for x in BinaryView(FileMetadata()).open(self.filename).available_view_types] def test_function_starts(self): """Function starts list doesnt match""" - return [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 [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 [x.symbol.name + ' ' + str(x.symbol.type) + ' ' + hex(x.symbol.address) + ' ' + 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)""" bblist = [] for func in self.bv.functions: for bb in func.basic_blocks: - bblist.append(hex(bb.start) + ' ' + hex(bb.end) + ' ' + str(bb.has_undetermined_outgoing_edges)) - return bblist + bblist.append("basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' undetermined outgoing edges: ' + str(bb.has_undetermined_outgoing_edges)) + 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 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(hex(bb.start) + ' ' + hex(bb.end) + ' ' + str(len(bb.outgoing_edges))) - return ilbblist - + ilbblist.append("LLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing edges: ' + str(len(bb.outgoing_edges))) + 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(hex(bb.start) + ' ' + hex(bb.end) + ' ' + str(len(bb.outgoing_edges))) - return ilbblist + ilbblist.append("MLIL basic block {} start: ".format(str(bb)) + hex(bb.start) + ' end: ' + hex(bb.end) + ' outgoing_edges: ' + str(len(bb.outgoing_edges))) + return fixOutput(ilbblist) def test_symbols(self): - """"Symbols list doesn't match""" - return [str(i) for i in sorted(self.bv.symbols)] + """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 [x.value + ' ' + str(x.type) + ' ' + 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""" @@ -110,42 +168,38 @@ class BinaryViewTestBuilder(Builder): for func in self.bv.functions: for bb in func.low_level_il.basic_blocks: for ins in bb: - retinfo.append(str(ins.medium_level_il)) - retinfo.append(str(ins.mapped_medium_level_il)) - retinfo.append(str(ins.value)) - retinfo.append(str(ins.possible_values)) - retinfo.append(str(ins.prefix_operands)) - retinfo.append(str(ins.postfix_operands)) - retinfo.append(str(ins.ssa_form)) - retinfo.append(str(ins.non_ssa_form)) - - return retinfo + retinfo.append("MLIL: " + str(ins.medium_level_il)) + retinfo.append("Mapped MLIL: " + str(ins.mapped_medium_level_il)) + retinfo.append("Value: " + str(ins.value)) + retinfo.append("Possible Values: " + str(ins.possible_values)) + retinfo.append("Prefix operands: " + str(ins.prefix_operands)) + 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 fixOutput(retinfo) - def test_low_il_ssa(self): """LLIL ssa produced different output""" retinfo = [] - reg_list = [binja.SSARegister(i,1) for i in self.bv.arch.regs] - flag_list = [binja.SSAFlag(i,1) for i in self.bv.arch.flags] for func in self.bv.functions: func = func.low_level_il - for reg in reg_list: - retinfo.append(str(func.get_ssa_reg_definition(reg))) - retinfo.append(str(func.get_ssa_reg_uses(reg))) - retinfo.append(str(func.get_ssa_reg_value(reg))) - for flag in flag_list: - retinfo.append(str(func.get_ssa_flag_uses(flag))) - retinfo.append(str(func.get_ssa_flag_value(flag))) + for reg_name in self.bv.arch.regs: + reg = binja.SSARegister(reg_name, 1) + retinfo.append("Reg {} SSA definition: ".format(reg_name) + str(func.get_ssa_reg_definition(reg))) + retinfo.append("Reg {} SSA uses: ".format(reg_name) + str(func.get_ssa_reg_uses(reg))) + retinfo.append("Reg {} SSA value: ".format(reg_name) + str(func.get_ssa_reg_value(reg))) + for flag_name in self.bv.arch.flags: + flag = binja.SSAFlag(flag_name, 1) + retinfo.append("Flag {} SSA uses: ".format(flag_name) + str(func.get_ssa_flag_uses(flag))) + retinfo.append("Flag {} SSA value: ".format(flag_name) + str(func.get_ssa_flag_value(flag))) for bb in func.basic_blocks: for ins in bb: tempind = func.get_non_ssa_instruction_index(ins.instr_index) - retinfo.append(str(tempind)) - retinfo.append(str(func.get_ssa_instruction_index(tempind))) - retinfo.append(str(func.get_medium_level_il_instruction_index(ins.instr_index))) - retinfo.append(str(func.get_mapped_medium_level_il_instruction_index(ins.instr_index))) - - return retinfo - + retinfo.append("Non-SSA instruction index: " + str(tempind)) + 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 fixOutput(retinfo) def test_med_il_instructions(self): """MLIL instructions produced different output""" @@ -153,22 +207,37 @@ class BinaryViewTestBuilder(Builder): for func in self.bv.functions: for bb in func.medium_level_il.basic_blocks: for ins in bb: - retinfo.append(str(ins.expr_type)) - retinfo.append(str(ins.low_level_il)) - retinfo.append(str(ins.value)) - retinfo.append(str(ins.possible_values)) - retinfo.append(str(ins.branch_dependence)) - retinfo.append(str(sorted([str(i) for i in ins.prefix_operands]))) - retinfo.append(str(sorted([str(i) for i in ins.postfix_operands]))) - retinfo.append(str(ins.ssa_form)) - retinfo.append(str(ins.non_ssa_form)) + retinfo.append("Expression type: " + str(ins.expr_type)) + 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(sorted(ins.branch_dependence.items()))) - return retinfo + 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 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 @@ -176,14 +245,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(str(func.get_ssa_var_definition(var)) + ' ' + \ - str(func.get_ssa_var_uses(var)) + ' ' + \ - str(func.get_ssa_var_value(var)) + ' ' + \ - str(instruction.get_ssa_var_possible_values(var)) + ' ' + \ - str(instruction.get_ssa_var_version)) - return varlist + 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: " + fixSet(str(instruction.get_ssa_var_possible_values(var)))) + varlist.append("SSA var version: " + str(instruction.get_ssa_var_version)) + return fixOutput(varlist) def test_function_stack(self): """Function stack produced different output""" @@ -194,42 +262,35 @@ class BinaryViewTestBuilder(Builder): func.create_user_stack_var(0, binja.Type.int(4), "testuservar") func.create_auto_stack_var(4, binja.Type.int(4), "testautovar") - temp = [] - for i in func.stack_layout: - temp.append(str(i)) - funcinfo.append(str(temp)) + sl = func.stack_layout + for i in range(len(sl)): + funcinfo.append("Stack position {}: ".format(i) + str(sl[i])) - funcinfo.append(str(func.get_stack_contents_at(func.start + 0x10, 0, 0x10))) - funcinfo.append(str(func.get_stack_contents_after(func.start + 0x10, 0, 0x10))) - funcinfo.append(str(func.get_stack_var_at_frame_offset(0, 0))) + funcinfo.append("Stack content sample: " + str(func.get_stack_contents_at(func.start + 0x10, 0, 0x10))) + funcinfo.append("Stack content range sample: " + str(func.get_stack_contents_after(func.start + 0x10, 0, 0x10))) + 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(str(llilbb)) + retinfo.append("LLIL basic block: " + str(llilbb)) for llilins in func.llil_instructions: - retinfo.append(str(llilins)) - + retinfo.append("LLIL instruction: " + str(llilins)) for mlilbb in func.mlil_basic_blocks: - retinfo.append(str(mlilbb)) + retinfo.append("MLIL basic block: " + str(mlilbb)) for mlilins in func.mlil_instructions: - retinfo.append(str(mlilins)) - + retinfo.append("MLIL instruction: " + str(mlilins)) for ins in func.instructions: - retinfo.append(str(ins)) - - 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 @@ -245,62 +306,67 @@ class BinaryViewTestBuilder(Builder): func.clobbered_regs = func.clobbered_regs func.set_user_instr_highlight(func.start, binja.highlight.HighlightColor(red=0xff, blue=0xff, green=0)) func.set_auto_instr_highlight(func.start, binja.highlight.HighlightColor(red=0xff, blue=0xfe, green=0)) - - funcinfo.append(str([str(i) for i in func.vars])) - funcinfo.append(str(func.indirect_branches)) - funcinfo.append(str(func.session_data)) - funcinfo.append(len(func.analysis_performance_info)) - funcinfo.append(str(func.clobbered_regs)) - funcinfo.append(str(func.explicitly_defined_type)) - funcinfo.append(str(func.needs_update)) - funcinfo.append(len(func.lifted_il)) - funcinfo.append(str(func.global_pointer_value)) - funcinfo.append(str(func.comment)) - funcinfo.append(str(func.too_large)) - funcinfo.append(str(func.analysis_skipped)) - funcinfo.append(str(func.get_low_level_il_at(func.start))) - funcinfo.append(str(func.get_low_level_il_exits_at(func.start+0x100))) - funcinfo.append(str(func.get_regs_read_by(func.start))) - funcinfo.append(str(func.get_regs_written_by(func.start))) - funcinfo.append(str(func.get_stack_vars_referenced_by(func.start))) - funcinfo.append(str(func.get_constants_referenced_by(func.start))) - funcinfo.append(str(func.get_lifted_il_at(func.start))) - funcinfo.append(str(func.get_flags_read_by_lifted_il_instruction(0))) - funcinfo.append(str(func.get_flags_written_by_lifted_il_instruction(0))) - funcinfo.append(str(func.create_graph())) - funcinfo.append(str(func.get_indirect_branches_at(func.start+0x10))) - funcinfo.append(str(func.get_block_annotations(func.start))) - funcinfo.append(str(func.get_basic_block_at(func.start))) - funcinfo.append(str(func.get_instr_highlight(func.start))) - funcinfo.append(str(func.get_type_tokens())) + for var in func.vars: + funcinfo.append("Function {} var: ".format(func.name) + str(var)) - return funcinfo + for branch in func.indirect_branches: + funcinfo.append("Function {} indirect branch: ".format(func.name) + str(branch)) + funcinfo.append("Function {} session data: ".format(func.name) + str(func.session_data)) + funcinfo.append("Function {} analysis perf length: ".format(func.name) + str(len(func.analysis_performance_info))) + for cr in func.clobbered_regs: + funcinfo.append("Function {} clobbered reg: ".format(func.name) + str(cr)) + funcinfo.append("Function {} explicitly defined type: ".format(func.name) + str(func.explicitly_defined_type)) + funcinfo.append("Function {} needs update: ".format(func.name) + str(func.needs_update)) + funcinfo.append("Function {} global pointer value: ".format(func.name) + str(func.global_pointer_value)) + funcinfo.append("Function {} comment: ".format(func.name) + str(func.comment)) + funcinfo.append("Function {} too large: ".format(func.name) + str(func.too_large)) + funcinfo.append("Function {} analysis skipped: ".format(func.name) + str(func.analysis_skipped)) + funcinfo.append("Function {} first ins LLIL: ".format(func.name) + str(func.get_low_level_il_at(func.start))) + funcinfo.append("Function {} LLIL exit test: ".format(func.name) + str(func.get_low_level_il_exits_at(func.start+0x100))) + funcinfo.append("Function {} regs read test: ".format(func.name) + str(func.get_regs_read_by(func.start))) + funcinfo.append("Function {} regs written test: ".format(func.name) + str(func.get_regs_written_by(func.start))) + funcinfo.append("Function {} stack var test: ".format(func.name) + str(func.get_stack_vars_referenced_by(func.start))) + funcinfo.append("Function {} constant reference test: ".format(func.name) + str(func.get_constants_referenced_by(func.start))) + funcinfo.append("Function {} first ins lifted IL: ".format(func.name) + str(func.get_lifted_il_at(func.start))) + funcinfo.append("Function {} flags read by lifted IL ins: ".format(func.name) + str(func.get_flags_read_by_lifted_il_instruction(0))) + funcinfo.append("Function {} flags written by lifted IL ins: ".format(func.name) + str(func.get_flags_written_by_lifted_il_instruction(0))) + funcinfo.append("Function {} create graph: ".format(func.name) + str(func.create_graph())) + funcinfo.append("Function {} indirect branches test: ".format(func.name) + str(func.get_indirect_branches_at(func.start+0x10))) + funcinfo.append("Function {} test instr highlight: ".format(func.name) + str(func.get_instr_highlight(func.start))) + for token in func.get_type_tokens(): + token = str(token) + token = remove_low_confidence(token) + funcinfo.append("Function {} type token: ".format(func.name) + str(token)) + return fixOutput(funcinfo) def test_BinaryView(self): """BinaryView produced different results""" retinfo = [] - retinfo += [str(i[1]) for i in self.bv.types.items()] - retinfo.append(str(self.bv.segments)) - retinfo.append(str(self.bv.sections)) - retinfo.append(str(self.bv.allocated_ranges)) - retinfo.append(str(self.bv.session_data)) + for type in self.bv.types.items(): + retinfo.append("BV Type: " + str(type)) + for segment in sorted([str(i) for i in self.bv.segments]): + retinfo.append("BV segment: " + str(segment)) + for section in sorted(self.bv.sections): + retinfo.append("BV section: " + str(section)) + for allrange in self.bv.allocated_ranges: + retinfo.append("BV allocated range: " + str(allrange)) + retinfo.append("Session Data: " + str(self.bv.session_data)) for var in self.bv.data_vars: - retinfo.append(str(var)) - retinfo.append(str(self.bv.entry_function)) + retinfo.append("BV data var: " + str(var)) + retinfo.append("BV Entry function: " + str(self.bv.entry_function)) for i in self.bv: - retinfo.append(str(i)) - retinfo.append(hex(self.bv.entry_point)) - retinfo.append(hex(self.bv.start)) - retinfo.append("length: " + hex(len(self.bv))) - return retinfo - + retinfo.append("BV function: " + str(i)) + 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 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. @@ -312,74 +378,133 @@ class TestBuilder(Builder): def test_BinaryViewType_list(self): """BinaryViewType list doesnt match""" - return [x.name for x in binja.BinaryViewType.list] + return ["BinaryViewType: " + x.name for x in binja.BinaryViewType.list] def test_Architecture_list(self): """Architecture list doesnt match""" - return [x.name for x in binja.Architecture.list] + return ["Arch name: " + x.name for x in binja.Architecture.list] def test_Assemble(self): """unexpected assemble result""" result = [] # success cases - result.append(binja.Architecture["x86"].assemble("xor eax, eax")) - result.append(binja.Architecture["x86_64"].assemble("xor rax, rax")) - result.append(binja.Architecture["mips32"].assemble("move $ra, $zero")) - result.append(binja.Architecture["mipsel32"].assemble("move $ra, $zero")) - result.append(binja.Architecture["armv7"].assemble("str r2, [sp, #-0x4]!")) - result.append(binja.Architecture["aarch64"].assemble("mov x0, x0")) - result.append(binja.Architecture["thumb2"].assemble("ldr r4, [r4]")) - result.append(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(binja.Architecture["x86"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["x86_64"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["mips32"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["mipsel32"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["armv7"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["aarch64"].assemble("thisisnotaninstruction")) - result.append(binja.Architecture["thumb2"].assemble("thisisnotaninstruction")) - result.append(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): """Architecture failure""" if not os.path.exists(os.path.join(os.path.expanduser("~"), '.binaryninja', 'plugins', 'nes.py')): - return + return [""] retinfo = [] file_name = os.path.join(self.test_store, "..", "pwnadventurez.nes") bv = binja.BinaryViewType["NES Bank 0"].open(file_name) - - retinfo.append(str([str(i) for i in bv.platform.arch.calling_conventions])) - retinfo.append(str(bv.platform.arch.full_width_regs)) + + for i in bv.platform.arch.calling_conventions: + retinfo.append("Custom arch calling convention: " + str(i)) + for i in bv.platform.arch.full_width_regs: + retinfo.append("Custom arch full width reg: " + str(i)) reg = binja.RegisterValue() - retinfo.append(str(reg.entry_value(bv.platform.arch, 'x'))) - retinfo.append(str(reg.constant(0xfe))) - retinfo.append(str(reg.constant_ptr(0xcafebabe))) - retinfo.append(str(reg.stack_frame_offset(0x10))) - retinfo.append(str(reg.imported_address(0xdeadbeef))) - retinfo.append(str(reg.return_address())) + retinfo.append("Reg entry value: " + str(reg.entry_value(bv.platform.arch, 'x'))) + retinfo.append("Reg constant: " + str(reg.constant(0xfe))) + retinfo.append("Reg constant pointer: " + str(reg.constant_ptr(0xcafebabe))) + retinfo.append("Reg stack frame offset: " + str(reg.stack_frame_offset(0x10))) + retinfo.append("Reg imported address: " + str(reg.imported_address(0xdeadbeef))) + retinfo.append("Reg return address: " + str(reg.return_address())) bv.update_analysis_and_wait() for func in bv.functions: for bb in func.low_level_il.basic_blocks: for ins in bb: - retinfo.append(str(bv.platform.arch.get_instruction_info(0x10, ins.address))) - retinfo.append(str(bv.platform.arch.get_instruction_text(0x10, ins.address))) - retinfo.append(str(ins)) + retinfo.append("Instruction info: " + str(bv.platform.arch.get_instruction_info(0x10, ins.address))) + retinfo.append("Instruction test: " + str(bv.platform.arch.get_instruction_text(0x10, ins.address))) + retinfo.append("Instruction: " + str(ins)) return retinfo - - def test_Function(self): """Function produced different result""" inttype = binja.Type.int(4) testfunction = binja.Type.function(inttype, [inttype, inttype, inttype]) - return [str(testfunction.parameters), str(testfunction.pointer(binja.Architecture["x86"], testfunction))] + return ["Test_function params: " + str(testfunction.parameters), "Test_function pointer: " + str(testfunction.pointer(binja.Architecture["x86"], testfunction))] def test_Struct(self): """Struct produced different result""" + retinfo = [] inttype = binja.Type.int(4) struct = binja.Structure() struct.a = 1 @@ -387,22 +512,23 @@ class TestBuilder(Builder): struct.append(inttype) struct.replace(0, inttype) struct.remove(1) - retinfo = [str(i) for i in struct.members] - retinfo += [struct.width] + for i in struct.members: + retinfo.append("Struct member: " + str(i)) + retinfo.append("Struct width: " + str(struct.width)) struct.width = 16 - retinfo += [struct.width] - retinfo += [struct.alignment] + retinfo.append("Struct width after adjustment: " + str(struct.width)) + retinfo.append("Struct alignment: " + str(struct.alignment)) struct.alignment = 8 - retinfo += [struct.alignment] - retinfo += [struct.packed] + retinfo.append("Struct alignment after adjustment: " + str(struct.alignment)) + retinfo.append("Struct packed: " + str(struct.packed)) struct.packed = 1 - retinfo += [struct.packed] - retinfo += [struct.type] - retinfo = [str(i) for i in retinfo] + retinfo.append("Struct packed after adjustment: " + str(struct.packed)) + retinfo.append("Struct type: " + str(struct.type)) return retinfo def test_Enumeration(self): """Enumeration produced different result""" + retinfo = [] inttype = binja.Type.int(4) enum = binja.Enumeration() enum.a = 1 @@ -410,16 +536,15 @@ class TestBuilder(Builder): enum.append("b", 2) enum.replace(0, "a", 2) enum.remove(0) - retinfo = [str(enum)] - retinfo += [str((enum == enum) and not (enum != enum))] + retinfo.append(str(enum)) + retinfo.append(str((enum == enum) and not (enum != enum))) return retinfo def test_Types(self): """Types produced different result""" - - file_name = os.path.join(self.test_store, "helloworld") + file_name = self.unpackage_file("helloworld") bv = binja.BinaryViewType.get_view_of_file(file_name) - + preprocessed = binja.preprocess_source(""" #ifdef nonexistant int foo = 1; @@ -429,70 +554,64 @@ 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('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) tokens = inttype.get_tokens() + inttype.get_tokens_before_name() + inttype.get_tokens_after_name() namedtype = binja.NamedTypeReference() - retinfo = [[str(i) for i in typelist.variables.popitem()][::-1] for i in range(len(typelist.variables))] - retinfo += [str(namedtype)] - - equalcheck = (inttype == inttype) and not (inttype != inttype) - retinfo += [str(equalcheck)] - return retinfo + retinfo = [] + for i in range(len(typelist.variables)): + for j in typelist.variables.popitem(): + retinfo.append("Type: " + str(j)) + retinfo.append("Named Type: " + str(namedtype)) + 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] + file_name = self.unpackage_file("helloworld") + bin_info_path = os.path.join(os.path.dirname(__file__), '..', 'python', 'examples', 'bin_info.py') + result = subprocess.Popen(["python", bin_info_path, 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 [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""" - file = os.path.join(self.test_store, "helloworld") - self.unpackage_file(file) - bv = binja.BinaryViewType['ELF'].open(file) - settings = binja.DisassemblySettings() + file_name = self.unpackage_file("helloworld") + bv = binja.BinaryViewType['ELF'].open(file_name) disass = bv.linear_disassembly - res = [] + retinfo = [] for i in disass: - res.append(str(i)) - #return res + i = str(i) + i = remove_low_confidence(i) + retinfo.append(i) + return retinfo 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) + file_name = self.unpackage_file("partial_register_dataflow") result = [] - try: - reg_list = ['ch', 'cl', 'ah', 'edi', 'al', 'cx', 'ebp', 'ax', 'edx', 'ebx', 'esp', 'esi', 'dl', 'dh', 'di', 'bl', 'bh', 'eax', 'dx', 'bx', 'ecx', 'sp', 'si'] - bv = binja.BinaryViewType.get_view_of_file(file_name) - for func in bv.functions: - llil = func.low_level_il - for i in range(0, llil.__len__()-1): - result.append(["LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_reg_value(x)).replace('L', '') for x in reg_list]) - result.append(["LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_possible_reg_values(x)).replace('L', '') for x in reg_list]) - result.append(["LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_reg_value_after(x)).replace('L', '') for x in reg_list]) - result.append(["LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_possible_reg_values_after(x)).replace('L', '') for x in reg_list]) - bv.file.close() - del bv - finally: - os.unlink(file_name) - + reg_list = ['ch', 'cl', 'ah', 'edi', 'al', 'cx', 'ebp', 'ax', 'edx', 'ebx', 'esp', 'esi', 'dl', 'dh', 'di', 'bl', 'bh', 'eax', 'dx', 'bx', 'ecx', 'sp', 'si'] + bv = binja.BinaryViewType.get_view_of_file(file_name) + for func in bv.functions: + llil = func.low_level_il + for i in range(0, llil.__len__()-1): + for x in reg_list: + result.append("LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_reg_value(x)).replace('L', '')) + result.append("LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_possible_reg_values(x)).replace('L', '')) + result.append("LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_reg_value_after(x)).replace('L', '')) + result.append("LLIL:" + str(i).replace('L', '') + ":" + x + ":" + str(llil[i].get_possible_reg_values_after(x)).replace('L', '')) + bv.file.close() + del bv return result def test_low_il_stack(self): """LLIL stack produced different output""" - file_name = os.path.join(self.test_store, "jumptable_reordered") - self.unpackage_file(file_name) + file_name = self.unpackage_file("jumptable_reordered") bv = binja.BinaryViewType.get_view_of_file(file_name) reg_list = ['ch', 'cl', 'ah', 'edi', 'al', 'cx', 'ebp', 'ax', 'edx', 'ebx', 'esp', 'esi', 'dl', 'dh', 'di', 'bl', 'bh', 'eax', 'dx', 'bx', 'ecx', 'sp', 'si'] flag_list = ['c', 'p', 'a', 'z', 's', 'o'] @@ -500,26 +619,20 @@ class TestBuilder(Builder): for func in bv.functions: for bb in func.low_level_il.basic_blocks: for ins in bb: - retinfo.append(str(ins.get_stack_contents(0,1))) - retinfo.append(str(ins.get_stack_contents_after(0,1))) - retinfo.append(str(ins.get_possible_stack_contents(0,1))) - retinfo.append(str(ins.get_possible_stack_contents_after(0,1))) - - + retinfo.append("LLIL first stack element: " + str(ins.get_stack_contents(0,1))) + 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(str(ins.get_flag_value(flag))) - retinfo.append(str(ins.get_flag_value_after(flag))) - retinfo.append(str(ins.get_possible_flag_values(flag))) - retinfo.append(str(ins.get_possible_flag_values_after(flag))) - - os.unlink(file_name) - - return retinfo + 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))) + return fixOutput(retinfo) def test_med_il_stack(self): """MLIL stack produced different output""" - file_name = os.path.join(self.test_store, "jumptable_reordered") - self.unpackage_file(file_name) + file_name = self.unpackage_file("jumptable_reordered") bv = binja.BinaryViewType.get_view_of_file(file_name) reg_list = ['ch', 'cl', 'ah', 'edi', 'al', 'cx', 'ebp', 'ax', 'edx', 'ebx', 'esp', 'esi', 'dl', 'dh', 'di', 'bl', 'bh', 'eax', 'dx', 'bx', 'ecx', 'sp', 'si'] flag_list = ['c', 'p', 'a', 'z', 's', 'o'] @@ -527,159 +640,108 @@ class TestBuilder(Builder): for func in bv.functions: for bb in func.medium_level_il.basic_blocks: for ins in bb: - retinfo.append(str(ins.get_var_for_stack_location(0))) - retinfo.append(str(ins.get_stack_contents(0, 0x10))) - retinfo.append(str(ins.get_stack_contents_after(0, 0x10))) - retinfo.append(str(ins.get_possible_stack_contents(0, 0x10))) - retinfo.append(str(ins.get_possible_stack_contents_after(0, 0x10))) - - for reg in reg_list: - retinfo.append(str(ins.get_var_for_reg(reg))) - retinfo.append(str(ins.get_reg_value(reg))) - retinfo.append(str(ins.get_reg_value_after(reg))) - retinfo.append(str(ins.get_possible_reg_values(reg))) - retinfo.append(str(ins.get_possible_reg_values_after(reg))) + retinfo.append("MLIL stack begin var: " + str(ins.get_var_for_stack_location(0))) + retinfo.append("MLIL first stack element: " + str(ins.get_stack_contents(0, 1))) + 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)) + 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(str(ins.get_flag_value(flag))) - retinfo.append(str(ins.get_flag_value_after(flag))) - retinfo.append(str(ins.get_possible_flag_values(flag))) - retinfo.append(str(ins.get_possible_flag_values_after(flag))) - - os.unlink(file_name) - - return retinfo - + 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)) + 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)))) + return fixOutput(retinfo) def test_events(self): """Event failure""" - file_name = os.path.join(self.test_store, "helloworld") - self.unpackage_file(file_name) + file_name = self.unpackage_file("helloworld") bv = binja.BinaryViewType['ELF'].open(file_name) + bv.update_analysis_and_wait() results = [] - def simple_complete(self): results.append("analysis complete") - evt = binja.AnalysisCompletionEvent(bv, simple_complete) class NotifyTest(binja.BinaryDataNotification): - def data_written(self, view, offset, length): - def data_written_complete(self): - results.append("data written {0} {1}".format(offset, length)) - evt = binja.AnalysisCompletionEvent(bv, data_written_complete) + results.append("data written: offset {0} length {1}".format(hex(offset), hex(length))) def data_inserted(self, view, offset, length): - def data_inserted_complete(self): - results.append("data inserted {0} {1}".format(offset, length)) - evt = binja.AnalysisCompletionEvent(bv, data_inserted_complete) + results.append("data inserted: offset {0} length {1}".format(hex(offset), hex(length))) def data_removed(self, view, offset, length): - def data_removed_complete(self): - results.append("data removed {0} {1}".format(offset, length)) - evt = binja.AnalysisCompletionEvent(bv, data_removed_complete) + results.append("data removed: offset {0} length {1}".format(hex(offset), hex(length))) def function_added(self, view, func): - def function_added_complete(self): - results.append("function added {0}".format(func.name)) - evt = binja.AnalysisCompletionEvent(bv, function_added_complete) + results.append("function added: {0}".format(func.name)) def function_removed(self, view, func): - def function_removed_complete(self): - results.append("function removed {0}".format(func.name)) - evt = binja.AnalysisCompletionEvent(bv, function_removed_complete) - - def function_updated(self, view, func): - def function_updated_complete(self): - results.append("function updated {0}".format(func.name)) - evt = binja.AnalysisCompletionEvent(bv, function_updated_complete) - - def function_update_requested(self, view, func): - def function_update_requested_complete(self): - results.append("function update requested {0}".format(func.name)) - evt = binja.AnalysisCompletionEvent(bv, function_update_requested_complete) + results.append("function removed: {0}".format(func.name)) def data_var_added(self, view, var): - def data_var_added_complete(self): - results.append("data var added {0}".format(var.name)) - evt = binja.AnalysisCompletionEvent(bv, data_var_added_complete) + results.append("data var added: {0}".format(hex(var.address))) def data_var_removed(self, view, var): - def data_var_removed_complete(self): - results.append("data var removed {0}".format(var.name)) - evt = binja.AnalysisCompletionEvent(bv, data_var_removed_complete) - - def data_var_updated(self, view, var): - def data_var_updated_complete(self): - results.append("data var updated {0}".format(var.name)) - evt = binja.AnalysisCompletionEvent(bv, data_var_updated_complete) + results.append("data var removed: {0}".format(hex(var.address))) def string_found(self, view, string_type, offset, length): - def string_found_complete(self): - results.append("string found {0} {1}".format(offset, length)) - evt = binja.AnalysisCompletionEvent(bv, string_found_complete) + results.append("string found: offset {0} length {1}".format(hex(offset), hex(length))) def string_removed(self, view, string_type, offset, length): - def string_removed_complete(self): - results.append("string removed {0} {1}".format(offset, length)) - evt = binja.AnalysisCompletionEvent(bv, string_removed_complete) + results.append("string removed: offset {0} length {1}".format(hex(offset), hex(length))) def type_defined(self, view, name, type): - def type_defined_complete(self): - results.append("type defined {0} {1}".format(name)) - evt = binja.AnalysisCompletionEvent(bv, type_defined_complete) + results.append("type defined: {0}".format(name)) def type_undefined(self, view, name, type): - def type_undefined_complete(self): - results.append("type undefined {0} {1}".format(name)) - evt = binja.AnalysisCompletionEvent(bv, type_undefined_complete) - + results.append("type undefined: {0}".format(name)) test = NotifyTest() 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) bv.undefine_type(type_id) - bv.insert(sacrificial_addr, "AAAA") + bv.update_analysis_and_wait() + + bv.insert(sacrificial_addr, b"AAAA") + bv.update_analysis_and_wait() + bv.define_data_var(sacrificial_addr, binja.types.Type.int(4)) + bv.update_analysis_and_wait() - bv.write(sacrificial_addr, "BBBB") + bv.write(sacrificial_addr, b"BBBB") + bv.update_analysis_and_wait() bv.add_function(sacrificial_addr) + bv.update_analysis_and_wait() + bv.remove_function(bv.get_function_at(sacrificial_addr)) + bv.update_analysis_and_wait() bv.undefine_data_var(sacrificial_addr) - bv.remove(sacrificial_addr, 4) - bv.update_analysis_and_wait() - - bv.unregister_notification(test) - - return str(sorted(results)) - def unpackage(self, fileName): - testname = None - with zipfile.ZipFile(fileName, "r") as zf: - testname = zf.namelist()[0] - zf.extractall() + bv.remove(sacrificial_addr, 4) + bv.update_analysis_and_wait() - if not os.path.exists(testname + ".pkl"): - return None, None - binary_oracle = pickle.load(open(testname + ".pkl", "rb")) - return binary_oracle.oracle_test_data, testname + bv.unregister_notification(test) - def cleanup_package(self, fileName): - if fileName.endswith(".zip"): - os.unlink(fileName[:-4]) + return fixOutput(sorted(results)) class VerifyBuilder(Builder): @@ -690,6 +752,7 @@ class VerifyBuilder(Builder): - Function doc string used as 'on error' message - Should return: boolean """ + def __init__(self, test_store): super(VerifyBuilder, self).__init__(test_store) @@ -709,10 +772,9 @@ class VerifyBuilder(Builder): # - Save the database # - Restore the datbase # - Validate that the modifications are present - file = os.path.join(self.test_store, "helloworld") - self.unpackage_file(file) + file_name = self.unpackage_file("helloworld") try: - bv = binja.BinaryViewType['ELF'].open(file) + bv = binja.BinaryViewType['ELF'].open(file_name) bv.update_analysis_and_wait() # Make some modifications to the binary view @@ -727,10 +789,7 @@ class VerifyBuilder(Builder): bv.create_database(temp_name) bv.file.close() del bv - finally: - os.unlink(file) - try: bv = binja.FileMetadata(temp_name).open_existing_database(temp_name).get_view_of_type('ELF') bv.update_analysis_and_wait() bndb_functions = self.get_functions(bv) @@ -741,4 +800,3 @@ class VerifyBuilder(Builder): return [str(functions == bndb_functions and comments == bndb_comments)] finally: os.unlink(temp_name) - diff --git a/suite/unit.py b/suite/unit.py deleted file mode 100644 index 993daf41..00000000 --- a/suite/unit.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python -# This is an auto generated unit test file do not edit directly -import os -import unittest -import pickle -import zipfile -import testcommon -import binaryninja -import api_test -import difflib - - - -class TestBinaryNinjaAPI(unittest.TestCase): - @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") - except TypeError: - self.oracle_test_data = pickle.load(open(os.path.join("suite", "oracle.pkl"), "rU")) - self.verifybuilder = testcommon.VerifyBuilder("suite/binaries/test_corpus") - - def run_binary_test(self, testfile): - testname = None - with zipfile.ZipFile(testfile, "r") as zf: - testname = zf.namelist()[0] - zf.extractall() - - 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") - except TypeError: - binary_oracle = pickle.load(open(testname + ".pkl", "rU")) - - test_builder = testcommon.BinaryViewTestBuilder(testname, "suite/binaries/test_corpus") - for method in test_builder.methods(): - test = getattr(test_builder, method)() - oracle = binary_oracle[method] - if test == oracle: - continue - - 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) - os.unlink(testname) - - def test_Architecture(self): - oracle = self.oracle_test_data['test_Architecture'] - test = self.builder.test_Architecture() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Architecture.__doc__, oracle, test)) - - def test_Architecture_list(self): - oracle = self.oracle_test_data['test_Architecture_list'] - test = self.builder.test_Architecture_list() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Architecture_list.__doc__, oracle, test)) - - def test_Assemble(self): - oracle = self.oracle_test_data['test_Assemble'] - test = self.builder.test_Assemble() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Assemble.__doc__, oracle, test)) - - def test_BinaryViewType_list(self): - oracle = self.oracle_test_data['test_BinaryViewType_list'] - test = self.builder.test_BinaryViewType_list() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_BinaryViewType_list.__doc__, oracle, test)) - - def test_Enumeration(self): - oracle = self.oracle_test_data['test_Enumeration'] - test = self.builder.test_Enumeration() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Enumeration.__doc__, oracle, test)) - - def test_Function(self): - oracle = self.oracle_test_data['test_Function'] - test = self.builder.test_Function() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Function.__doc__, oracle, test)) - - def test_Plugin_bin_info(self): - oracle = self.oracle_test_data['test_Plugin_bin_info'] - test = self.builder.test_Plugin_bin_info() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Plugin_bin_info.__doc__, oracle, test)) - - def test_Struct(self): - oracle = self.oracle_test_data['test_Struct'] - test = self.builder.test_Struct() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Struct.__doc__, oracle, test)) - - def test_Types(self): - oracle = self.oracle_test_data['test_Types'] - test = self.builder.test_Types() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_Types.__doc__, oracle, test)) - - def test_events(self): - oracle = self.oracle_test_data['test_events'] - test = self.builder.test_events() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_events.__doc__, oracle, test)) - - def test_linear_disassembly(self): - oracle = self.oracle_test_data['test_linear_disassembly'] - test = self.builder.test_linear_disassembly() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_linear_disassembly.__doc__, oracle, test)) - - def test_low_il_stack(self): - oracle = self.oracle_test_data['test_low_il_stack'] - test = self.builder.test_low_il_stack() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_low_il_stack.__doc__, oracle, test)) - - def test_med_il_stack(self): - oracle = self.oracle_test_data['test_med_il_stack'] - test = self.builder.test_med_il_stack() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_med_il_stack.__doc__, oracle, test)) - - def test_partial_register_dataflow(self): - oracle = self.oracle_test_data['test_partial_register_dataflow'] - test = self.builder.test_partial_register_dataflow() - self.assertTrue(oracle == test, "%s:\n'%s' does not equal\n'%s'" % (self.builder.test_partial_register_dataflow.__doc__, oracle, test)) - - def test_verify_BNDB_round_trip(self): - self.assertTrue(self.verifybuilder.test_verify_BNDB_round_trip(), self.test_verify_BNDB_round_trip.__doc__) - - def test_binary___aliased_jumptable(self): - self.run_binary_test('suite/binaries/test_corpus/aliased_jumptable.zip') - - def test_binary___byte_jump_table(self): - self.run_binary_test('suite/binaries/test_corpus/byte_jump_table.zip') - - def test_binary___duff(self): - self.run_binary_test('suite/binaries/test_corpus/duff.zip') - - def test_binary___helloworld(self): - self.run_binary_test('suite/binaries/test_corpus/helloworld.zip') - - def test_binary___helloworld_armeb(self): - self.run_binary_test('suite/binaries/test_corpus/helloworld_armeb.zip') - - def test_binary___integer_test(self): - self.run_binary_test('suite/binaries/test_corpus/integer_test.zip') - - def test_binary___interprocedural_alias(self): - self.run_binary_test('suite/binaries/test_corpus/interprocedural_alias.zip') - - def test_binary___jump_loop(self): - self.run_binary_test('suite/binaries/test_corpus/jump_loop.zip') - - def test_binary___jumptable_aarch64(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_aarch64.zip') - - def test_binary___jumptable_mips32(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_mips32.zip') - - def test_binary___jumptable_multiple_indirect(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_multiple_indirect.zip') - - def test_binary___jumptable_no_range_check(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_no_range_check.zip') - - def test_binary___jumptable_reordered(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_reordered.zip') - - def test_binary___jumptable_x86(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_x86.zip') - - def test_binary___jumptable_x86_64(self): - self.run_binary_test('suite/binaries/test_corpus/jumptable_x86_64.zip') - - def test_binary___loop_constant_propagate(self): - self.run_binary_test('suite/binaries/test_corpus/loop_constant_propagate.zip') - - def test_binary___partial_register_dataflow(self): - self.run_binary_test('suite/binaries/test_corpus/partial_register_dataflow.zip') - - def test_binary___pe_thumb(self): - self.run_binary_test('suite/binaries/test_corpus/pe_thumb.zip') - - def test_binary___quick3dcoreplugin_dll(self): - self.run_binary_test('suite/binaries/test_corpus/quick3dcoreplugin.dll.zip') - - def test_binary___rangecheck(self): - self.run_binary_test('suite/binaries/test_corpus/rangecheck.zip') - - def test_binary___switch_linux_ppc_le_32(self): - self.run_binary_test('suite/binaries/test_corpus/switch_linux_ppc_le_32.zip') - - def test_binary___x87(self): - self.run_binary_test('suite/binaries/test_corpus/x87.zip') - - -if __name__ == "__main__": - - test_suite = unittest.defaultTestLoader.loadTestsFromModule(api_test) - test_suite.addTest(unittest.defaultTestLoader.loadTestsFromTestCase(TestBinaryNinjaAPI)) - runner = unittest.TextTestRunner(verbosity=2) - runner.run(test_suite) |
