Changelog: bv.write and bv.insert require a bytes object in python3 Architecture.assemble outputs a bytes object in python3, a str in python2 Architecture.assemble will throw a value error if it cannot assemble the given instruction API install script should be run in the version of python you want it installed in Fundamental python changes to be aware of: Unicode-type strings are now just str, consequently anything that came out as a unicode string before (annotations) are now just str. Longs no longer exist. They're just ints.
@@ -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) |