diff options
Diffstat (limited to 'python')
40 files changed, 549 insertions, 260 deletions
diff --git a/python/__init__.py b/python/__init__.py index c7c5f768..4f58a6db 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/architecture.py b/python/architecture.py index d3778613..34f2ca35 100644 --- a/python/architecture.py +++ b/python/architecture.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -651,11 +651,11 @@ class Architecture(object): operand_list = [] for i in xrange(operand_count): if operands[i].constant: - operand_list.append(("const", operands[i].value)) + operand_list.append(operands[i].value) elif lowlevelil.LLIL_REG_IS_TEMP(operands[i].reg): - operand_list.append(("reg", operands[i].reg)) + operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) else: - operand_list.append(("reg", self._regs_by_index[operands[i].reg])) + operand_list.append(lowlevelil.ILRegister(self, operands[i].reg)) return self.perform_get_flag_write_low_level_il(op, size, write_type_name, flag_name, operand_list, lowlevelil.LowLevelILFunction(self, core.BNNewLowLevelILFunctionReference(il))).index except (KeyError, OSError): @@ -915,7 +915,10 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + flag = self.get_flag_index(flag) + if flag not in self._flag_roles: + return il.unimplemented() + return self.get_default_flag_write_low_level_il(op, size, self._flag_roles[flag], operands, il) @abc.abstractmethod def perform_get_flag_condition_low_level_il(self, cond, il): @@ -927,7 +930,7 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ - return il.unimplemented() + return self.get_default_flag_condition_low_level_il(cond, il) @abc.abstractmethod def perform_assemble(self, code, addr): @@ -1232,6 +1235,20 @@ class Architecture(object): """ return core.BNGetArchitectureFlagName(self.handle, flag) + def get_reg_index(self, reg): + if isinstance(reg, str): + return self.regs[reg].index + elif isinstance(reg, lowlevelil.ILRegister): + return reg.index + return reg + + def get_flag_index(self, flag): + if isinstance(flag, str): + return self._flags[flag] + elif isinstance(flag, lowlevelil.ILFlag): + return flag.index + return flag + def get_flag_write_type_name(self, write_type): """ ``get_flag_write_type_name`` gets the flag write type name for the given flag. @@ -1262,7 +1279,7 @@ class Architecture(object): """ return self._flag_write_types[write_type] - def get_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): """ :param LowLevelILOperation op: :param int size: @@ -1272,22 +1289,26 @@ class Architecture(object): :param LowLevelILFunction il: :rtype: LowLevelILExpr """ + flag = self.get_flag_index(flag) operand_list = (core.BNRegisterOrConstant * len(operands))() for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + elif isinstance(operands[i], lowlevelil.ILRegister): + operand_list[i].constant = False + operand_list[i].reg = operands[i].index else: operand_list[i].constant = True operand_list[i].value = operands[i] return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], operand_list, len(operand_list), il.handle)) + self._flag_write_types[write_type], flag, operand_list, len(operand_list), il.handle)) - def get_default_flag_write_low_level_il(self, op, size, write_type, operands, il): + def get_default_flag_write_low_level_il(self, op, size, role, operands, il): """ :param LowLevelILOperation op: :param int size: - :param str write_type: + :param FlagRole role: :param list(str or int) operands: a list of either items that are either string register names or constant \ integer values :param LowLevelILFunction il: @@ -1297,12 +1318,15 @@ class Architecture(object): for i in xrange(len(operands)): if isinstance(operands[i], str): operand_list[i].constant = False - operand_list[i].reg = self._flags[operands[i]] + operand_list[i].reg = self.regs[operands[i]] + elif isinstance(operands[i], lowlevelil.ILRegister): + operand_list[i].constant = False + operand_list[i].reg = operands[i].index else: operand_list[i].constant = True operand_list[i].value = operands[i] return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagWriteLowLevelIL(self.handle, op, size, - self._flag_write_types[write_type], operand_list, len(operand_list), il.handle)) + role, operand_list, len(operand_list), il.handle)) def get_flag_condition_low_level_il(self, cond, il): """ @@ -1312,6 +1336,14 @@ class Architecture(object): """ return lowlevelil.LowLevelILExpr(core.BNGetArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_default_flag_condition_low_level_il(self, cond, il): + """ + :param LowLevelILFlagCondition cond: + :param LowLevelILFunction il: + :rtype: LowLevelILExpr + """ + return lowlevelil.LowLevelILExpr(core.BNGetDefaultArchitectureFlagConditionLowLevelIL(self.handle, cond, il.handle)) + def get_modified_regs_on_write(self, reg): """ ``get_modified_regs_on_write`` returns a list of register names that are modified when ``reg`` is written. diff --git a/python/associateddatastore.py b/python/associateddatastore.py index 6b5e688e..c9b35ee0 100644 --- a/python/associateddatastore.py +++ b/python/associateddatastore.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/basicblock.py b/python/basicblock.py index 5bec391b..3dc5b050 100644 --- a/python/basicblock.py +++ b/python/basicblock.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/binaryview.py b/python/binaryview.py index 042c08f5..8165c592 100644 --- a/python/binaryview.py +++ b/python/binaryview.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -641,7 +641,7 @@ class BinaryView(object): @classmethod def set_default_session_data(cls, name, value): """ - ```set_default_session_data``` saves a variable to the BinaryView. + ``set_default_session_data`` saves a variable to the BinaryView. :param name: name of the variable to be saved :param value: value of the variable to be saved @@ -1329,7 +1329,7 @@ class BinaryView(object): def perform_is_offset_executable(self, addr): """ - ``perform_is_offset_writable`` implements a check if a virtual address ``addr`` is executable. + ``perform_is_offset_executable`` implements a check if a virtual address ``addr`` is executable. .. note:: This method **may** be overridden by custom BinaryViews. Use ``add_auto_segment`` to provide data without overriding this method. @@ -1410,7 +1410,7 @@ class BinaryView(object): def create_database(self, filename, progress_func=None): """ - ``perform_get_database`` writes the current database (.bndb) file out to the specified file. + ``create_database`` writes the current database (.bndb) file out to the specified file. :param str filename: path and filename to write the bndb to, this string `should` have ".bndb" appended to it. :param callable() progress_func: optional function to be called with the current progress and total count. @@ -1851,7 +1851,7 @@ class BinaryView(object): def define_user_data_var(self, addr, var_type): """ - ``define_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``. + ``define_user_data_var`` defines a user data variable ``var_type`` at the virtual address ``addr``. :param int addr: virtual address to define the given data variable :param binaryninja.Type var_type: type to be defined at the given virtual address @@ -1881,7 +1881,7 @@ class BinaryView(object): def undefine_user_data_var(self, addr): """ - ``undefine_data_var`` removes the user data variable at the virtual address ``addr``. + ``undefine_user_data_var`` removes the user data variable at the virtual address ``addr``. :param int addr: virtual address to define the data variable to be removed :rtype: None @@ -2145,6 +2145,8 @@ class BinaryView(object): """ ``define_auto_symbol`` adds a symbol to the internal list of automatically discovered Symbol objects. + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :rtype: None """ @@ -2154,6 +2156,8 @@ class BinaryView(object): """ ``define_auto_symbol_and_var_or_function`` + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :param SymbolType sym_type: Type of symbol being defined :param Platform plat: (optional) platform @@ -2180,6 +2184,8 @@ class BinaryView(object): """ ``define_user_symbol`` adds a symbol to the internal list of user added Symbol objects. + .. warning:: If multiple symbols for the same address are defined, only the most recent symbol will ever be used. + :param Symbol sym: the symbol to define :rtype: None """ diff --git a/python/callingconvention.py b/python/callingconvention.py index 04ba711f..4c87eef6 100644 --- a/python/callingconvention.py +++ b/python/callingconvention.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/databuffer.py b/python/databuffer.py index 6b3423da..3f9e4ce5 100644 --- a/python/databuffer.py +++ b/python/databuffer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/demangle.py b/python/demangle.py index ed38674a..11673263 100644 --- a/python/demangle.py +++ b/python/demangle.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -48,8 +48,8 @@ def demangle_ms(arch, mangled_name): :param Architecture arch: Architecture for the symbol. Required for pointer and integer sizes. :param str mangled_name: a mangled Microsoft Visual Studio C++ name - :return: returns a Type object for the mangled name - :rtype: Type + :return: returns tuple of (Type, demangled_name) or (None, mangled_name) on error + :rtype: Tuple :Example: >>> demangle_ms(Architecture["x86_64"], "?testf@Foobar@@SA?AW4foo@1@W421@@Z") diff --git a/python/examples/angr_plugin.py b/python/examples/angr_plugin.py index 90217d65..c84373be 100644 --- a/python/examples/angr_plugin.py +++ b/python/examples/angr_plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/bin_info.py b/python/examples/bin_info.py index 4c4ab8fd..17a96685 100644 --- a/python/examples/bin_info.py +++ b/python/examples/bin_info.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -38,7 +38,6 @@ def get_bininfo(bv): sys.exit(1) bv = BinaryViewType.get_view_of_file(filename) - log.redirect_output_to_log() log.log_to_stdout(True) contents = "## %s ##\n" % bv.file.filename diff --git a/python/examples/breakpoint.py b/python/examples/breakpoint.py index b1297e26..a2801511 100644 --- a/python/examples/breakpoint.py +++ b/python/examples/breakpoint.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/export_svg.py b/python/examples/export_svg.py index 95e2d62d..7814c9fd 100755 --- a/python/examples/export_svg.py +++ b/python/examples/export_svg.py @@ -1,6 +1,7 @@ # from binaryninja import * import os import webbrowser +import time try: from urllib import pathname2url # Python 2.x except: @@ -34,7 +35,7 @@ def save_svg(bv, function): outputfile = get_save_filename_input('File name for export_svg', 'HTML files (*.html)', filename) if outputfile is None: return - content = render_svg(function) + content = render_svg(function, origname) output = open(outputfile, 'w') output.write(content) output.close() @@ -54,7 +55,7 @@ def instruction_data_flow(function, address): return 'Opcode: {bytes}'.format(bytes=padded) -def render_svg(function): +def render_svg(function, origname): graph = function.create_graph() graph.layout_and_wait() heightconst = 15 @@ -67,7 +68,13 @@ def render_svg(function): @import url(https://fonts.googleapis.com/css?family=Source+Code+Pro); body { background-color: rgb(42, 42, 42); + color: rgb(220, 220, 220); + font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace; } + a, a:visited { + color: rgb(200, 200, 200); + font-weight: bold; + } svg { background-color: rgb(42, 42, 42); display: block; @@ -101,7 +108,7 @@ def render_svg(function): fill: currentColor; } text { - font-family: 'Source Code Pro'; + font-family: "Source Code Pro", "Lucida Console", "Consolas", monospace; font-size: 9pt; fill: rgb(224, 224, 224); } @@ -207,7 +214,10 @@ def render_svg(function): edges += ' <polyline class="edge {type}" points="{points}" marker-end="url(#arrow-{type})"/>\n'.format(type=BranchType(edge.type).name, points=points) output += ' ' + edges + '\n' output += ' </g>\n' - output += '</svg></html>' + output += '</svg>' + + output += '<p>This CFG generated by <a href="https://binary.ninja/">Binary Ninja</a> from {filename} on {timestring}.</p>'.format(filename = origname, timestring = time.strftime("%c")) + output += '</html>' return output diff --git a/python/examples/instruction_iterator.py b/python/examples/instruction_iterator.py index 7ff2d692..f55e1c1b 100644 --- a/python/examples/instruction_iterator.py +++ b/python/examples/instruction_iterator.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/jump_table.py b/python/examples/jump_table.py index 439e2ab6..419cc188 100644 --- a/python/examples/jump_table.py +++ b/python/examples/jump_table.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/nds.py b/python/examples/nds.py index ff137b4b..34d8a292 100644 --- a/python/examples/nds.py +++ b/python/examples/nds.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/nes.py b/python/examples/nes.py index 4122cde0..e55a90b7 100644 --- a/python/examples/nes.py +++ b/python/examples/nes.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -191,21 +191,21 @@ OperandTokens = [ def indirect_load(il, value): if (value & 0xff) == 0xff: - lo_addr = il.const(2, value) - hi_addr = il.const(2, (value & 0xff00) | ((value + 1) & 0xff)) + lo_addr = il.const_pointer(2, value) + hi_addr = il.const_pointer(2, (value & 0xff00) | ((value + 1) & 0xff)) lo = il.zero_extend(2, il.load(1, lo_addr)) hi = il.shift_left(2, il.zero_extend(2, il.load(1, hi_addr)), il.const(2, 8)) return il.or_expr(2, lo, hi) - return il.load(2, il.const(2, value)) + return il.load(2, il.const_pointer(2, value)) def load_zero_page_16(il, value): if il[value].operation == LowLevelILOperation.LLIL_CONST: - if il[value].value == 0xff: - lo = il.zero_extend(2, il.load(1, il.const(2, 0xff))) - hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const(2, 0)), il.const(2, 8))) + if il[value].constant == 0xff: + lo = il.zero_extend(2, il.load(1, il.const_pointer(2, 0xff))) + hi = il.shift_left(2, il.zero_extend(2, il.load(1, il.const_pointer(2, 0)), il.const(2, 8))) return il.or_expr(2, lo, hi) - return il.load(2, il.const(2, il[value].value)) + return il.load(2, il.const_pointer(2, il[value].constant)) il.append(il.set_reg(1, LLIL_TEMP(0), value)) value = il.reg(1, LLIL_TEMP(0)) lo_addr = value @@ -217,23 +217,23 @@ def load_zero_page_16(il, value): OperandIL = [ lambda il, value: None, # NONE - lambda il, value: il.load(1, il.const(2, value)), # ABS + lambda il, value: il.load(1, il.const_pointer(2, value)), # ABS lambda il, value: il.const(2, value), # ABS_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x")))), # ABS_X lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "x"))), # ABS_X_DEST lambda il, value: il.load(1, il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y")))), # ABS_Y lambda il, value: il.add(2, il.const(2, value), il.zero_extend(2, il.reg(1, "y"))), # ABS_Y_DEST lambda il, value: il.reg(1, "a"), # ACCUM - lambda il, value: il.const(2, value), # ADDR + lambda il, value: il.const_pointer(2, value), # ADDR lambda il, value: il.const(1, value), # IMMED lambda il, value: indirect_load(il, value), # IND lambda il, value: il.load(1, load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x")))), # IND_X lambda il, value: load_zero_page_16(il, il.add(1, il.const(1, value), il.reg(1, "x"))), # IND_X_DEST lambda il, value: il.load(1, il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y"))), # IND_Y lambda il, value: il.add(2, load_zero_page_16(il, il.const(1, value)), il.reg(1, "y")), # IND_Y_DEST - lambda il, value: il.const(2, value), # REL - lambda il, value: il.load(1, il.const(2, value)), # ZERO - lambda il, value: il.const(2, value), # ZERO_DEST + lambda il, value: il.const_pointer(2, value), # REL + lambda il, value: il.load(1, il.const_pointer(2, value)), # ZERO + lambda il, value: il.const_pointer(2, value), # ZERO_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x")))), # ZERO_X lambda il, value: il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "x"))), # ZERO_X_DEST lambda il, value: il.load(1, il.zero_extend(2, il.add(1, il.const(1, value), il.reg(1, "y")))), # ZERO_Y @@ -244,7 +244,7 @@ OperandIL = [ def cond_branch(il, cond, dest): t = None if il[dest].operation == LowLevelILOperation.LLIL_CONST: - t = il.get_label_for_address(Architecture['6502'], il[dest].value) + t = il.get_label_for_address(Architecture['6502'], il[dest].constant) if t is None: t = LowLevelILLabel() indirect = True @@ -262,7 +262,7 @@ def cond_branch(il, cond, dest): def jump(il, dest): label = None if il[dest].operation == LowLevelILOperation.LLIL_CONST: - label = il.get_label_for_address(Architecture['6502'], il[dest].value) + label = il.get_label_for_address(Architecture['6502'], il[dest].constant) if label is None: il.append(il.jump(dest)) else: @@ -300,7 +300,7 @@ def rti(il): InstructionIL = { - "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, flags = "*")), + "adc": lambda il, operand: il.set_reg(1, "a", il.add_carry(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")), "asl": lambda il, operand: il.store(1, operand, il.shift_left(1, il.load(1, operand), il.const(1, 1), flags = "czs")), "asl@": lambda il, operand: il.set_reg(1, "a", il.shift_left(1, operand, il.const(1, 1), flags = "czs")), "and": lambda il, operand: il.set_reg(1, "a", il.and_expr(1, il.reg(1, "a"), operand, flags = "zs")), @@ -341,13 +341,13 @@ InstructionIL = { "php": lambda il, operand: il.push(1, get_p_value(il)), "pla": lambda il, operand: il.set_reg(1, "a", il.pop(1), flags = "zs"), "plp": lambda il, operand: set_p_value(il, il.pop(1)), - "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), - "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), - "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), flags = "czs")), - "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), flags = "czs")), + "rol": lambda il, operand: il.store(1, operand, il.rotate_left_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")), + "rol@": lambda il, operand: il.set_reg(1, "a", il.rotate_left_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")), + "ror": lambda il, operand: il.store(1, operand, il.rotate_right_carry(1, il.load(1, operand), il.const(1, 1), il.flag("c"), flags = "czs")), + "ror@": lambda il, operand: il.set_reg(1, "a", il.rotate_right_carry(1, il.reg(1, "a"), il.const(1, 1), il.flag("c"), flags = "czs")), "rti": lambda il, operand: rti(il), "rts": lambda il, operand: il.ret(il.add(2, il.pop(2), il.const(2, 1))), - "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, flags = "*")), + "sbc": lambda il, operand: il.set_reg(1, "a", il.sub_borrow(1, il.reg(1, "a"), operand, il.flag("c"), flags = "*")), "sec": lambda il, operand: il.set_flag("c", il.const(0, 1)), "sed": lambda il, operand: il.set_flag("d", il.const(0, 1)), "sei": lambda il, operand: il.set_flag("i", il.const(0, 1)), @@ -469,6 +469,15 @@ class M6502(Architecture): return length + def perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il): + if flag == 'c': + if (op == LowLevelILOperation.LLIL_SUB) or (op == LowLevelILOperation.LLIL_SBB): + # Subtraction carry flag is inverted from the commom implementation + return il.not_expr(0, self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il)) + # Other operations use a normal carry flag + return self.get_default_flag_write_low_level_il(op, size, FlagRole.CarryFlagRole, operands, il) + return Architecture.perform_get_flag_write_low_level_il(self, op, size, write_type, flag, operands, il) + def perform_is_never_branch_patch_available(self, data, addr): if (data[0] == "\x10") or (data[0] == "\x30") or (data[0] == "\x50") or (data[0] == "\x70") or (data[0] == "\x90") or (data[0] == "\xb0") or (data[0] == "\xd0") or (data[0] == "\xf0"): return True diff --git a/python/examples/nsf.py b/python/examples/nsf.py index b1bac3a8..b0164065 100644 --- a/python/examples/nsf.py +++ b/python/examples/nsf.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/print_syscalls.py b/python/examples/print_syscalls.py index 2af4d38d..d995ad1e 100644 --- a/python/examples/print_syscalls.py +++ b/python/examples/print_syscalls.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/examples/version_switcher.py b/python/examples/version_switcher.py index 9d5bbf05..3e1cab40 100644 --- a/python/examples/version_switcher.py +++ b/python/examples/version_switcher.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/fileaccessor.py b/python/fileaccessor.py index 8fec43a1..2c1f1d19 100644 --- a/python/fileaccessor.py +++ b/python/fileaccessor.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/filemetadata.py b/python/filemetadata.py index b489d5bb..4bfc0214 100644 --- a/python/filemetadata.py +++ b/python/filemetadata.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/function.py b/python/function.py index d54cf25a..34511cfa 100644 --- a/python/function.py +++ b/python/function.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -205,11 +205,15 @@ class Variable(object): class ConstantReference(object): - def __init__(self, val, size): + def __init__(self, val, size, ptr, intermediate): self.value = val self.size = size + self.pointer = ptr + self.intermediate = intermediate def __repr__(self): + if self.pointer: + return "<constant pointer %#x>" % self.value if self.size == 0: return "<constant %#x>" % self.value return "<constant %#x size %d>" % (self.value, self.size) @@ -426,6 +430,16 @@ class Function(object): else: return Function._associated_data[handle.value] + @property + def analysis_performance_info(self): + count = ctypes.c_ulonglong() + info = core.BNGetFunctionAnalysisPerformanceInfo(self.handle, count) + result = {} + for i in xrange(0, count.value): + result[info[i].name] = info[i].seconds + core.BNFreeAnalysisPerformanceInfo(info, count.value) + return result + def __iter__(self): count = ctypes.c_ulonglong() blocks = core.BNGetFunctionBasicBlockList(self.handle, count) @@ -500,8 +514,7 @@ class Function(object): """ if arch is None: arch = self.arch - if isinstance(reg, str): - reg = arch.regs[reg].index + reg = arch.get_reg_index(reg) value = core.BNGetRegisterValueAtInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) return result @@ -521,8 +534,7 @@ class Function(object): """ if arch is None: arch = self.arch - if isinstance(reg, str): - reg = arch.regs[reg].index + reg = arch.get_reg_index(reg) value = core.BNGetRegisterValueAfterInstruction(self.handle, arch.handle, addr, reg) result = RegisterValue(arch, value) return result @@ -618,7 +630,7 @@ class Function(object): refs = core.BNGetConstantsReferencedByInstruction(self.handle, arch.handle, addr, count) result = [] for i in xrange(0, count.value): - result.append(ConstantReference(refs[i].value, refs[i].size)) + result.append(ConstantReference(refs[i].value, refs[i].size, refs[i].pointer, refs[i].intermediate)) core.BNFreeConstantReferenceList(refs) return result @@ -628,8 +640,7 @@ class Function(object): return self.lifted_il[core.BNGetLiftedILForInstruction(self.handle, arch.handle, addr)] def get_lifted_il_flag_uses_for_definition(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] + flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagUsesForDefinition(self.handle, i, flag, count) result = [] @@ -639,8 +650,7 @@ class Function(object): return result def get_lifted_il_flag_definitions_for_use(self, i, flag): - if isinstance(flag, str): - flag = self.arch._flags[flag] + flag = self.arch.get_flag_index(flag) count = ctypes.c_ulonglong() instrs = core.BNGetLiftedILFlagDefinitionsForUse(self.handle, i, flag, count) result = [] @@ -743,7 +753,7 @@ class Function(object): :param int instr_addr: :param int value: :param int operand: - :param IntegerDisplayTypeEnum display_type: + :param enums.IntegerDisplayType display_type: :param Architecture arch: (optional) """ if arch is None: diff --git a/python/functionrecognizer.py b/python/functionrecognizer.py index 960aee2f..8514a2ee 100644 --- a/python/functionrecognizer.py +++ b/python/functionrecognizer.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/generator.cpp b/python/generator.cpp index 1c0e7b16..6f19db66 100644 --- a/python/generator.cpp +++ b/python/generator.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2015-2016 Vector 35 LLC +// 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 diff --git a/python/highlight.py b/python/highlight.py index 6af1cf95..96bc543d 100644 --- a/python/highlight.py +++ b/python/highlight.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/interaction.py b/python/interaction.py index 6d640d17..60607692 100644 --- a/python/interaction.py +++ b/python/interaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -23,7 +23,7 @@ import traceback # Binary Ninja components import _binaryninjacore as core -from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonResult +from enums import FormInputFieldType, MessageBoxIcon, MessageBoxButtonSet, MessageBoxButtonResult import binaryview import log @@ -517,5 +517,17 @@ def get_form_input(fields, title): return True -def show_message_box(title, text, buttons = MessageBoxButtonResult.OKButton, icon = MessageBoxIcon.InformationIcon): +def show_message_box(title, text, buttons = MessageBoxButtonSet.OKButtonSet, icon = MessageBoxIcon.InformationIcon): + """ + ``show_message_box`` Displays a configurable message box in the UI, or prompts on the console as appropriate + retrieves a list of all Symbol objects of the provided symbol type in the optionally + provided range. + + :param str title: Text title for the message box. + :param str text: Text for the main body of the message box. + :param MessageBoxButtonSet buttons: One of :py:class:`MessageBoxButtonSet` + :param MessageBoxIcon icon: One of :py:class:`MessageBoxIcon` + :return: Which button was selected + :rtype: MessageBoxButtonResult + """ return core.BNShowMessageBox(title, text, buttons, icon) diff --git a/python/lineardisassembly.py b/python/lineardisassembly.py index 9b88b78a..5ef8d623 100644 --- a/python/lineardisassembly.py +++ b/python/lineardisassembly.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/log.py b/python/log.py index 45adb4aa..f7144183 100644 --- a/python/log.py +++ b/python/log.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -23,11 +23,19 @@ import _binaryninjacore as core +_output_to_log = False + + def redirect_output_to_log(): global _output_to_log _output_to_log = True +def is_output_redirected_to_log(): + global _output_to_log + return _output_to_log + + def log(level, text): """ ``log`` writes messages to the log console for the given log level. diff --git a/python/lowlevelil.py b/python/lowlevelil.py index 3634cca2..d1a76a2a 100644 --- a/python/lowlevelil.py +++ b/python/lowlevelil.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -37,6 +37,73 @@ class LowLevelILLabel(object): self.handle = handle +class ILRegister(object): + def __init__(self, arch, reg): + self.arch = arch + self.index = reg + self.temp = (self.index & 0x80000000) != 0 + if self.temp: + self.name = "temp%d" % (self.index & 0x7fffffff) + else: + self.name = self.arch.get_reg_name(self.index) + + @property + def info(self): + return self.arch.regs[self.name] + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + +class ILFlag(object): + def __init__(self, arch, flag): + self.arch = arch + self.index = flag + self.temp = (self.index & 0x80000000) != 0 + if self.temp: + self.name = "cond:%d" % (self.index & 0x7fffffff) + else: + self.name = self.arch.get_flag_name(self.index) + + def __str__(self): + return self.name + + def __repr__(self): + return self.name + + +class SSARegister(object): + def __init__(self, reg, version): + self.reg = reg + self.version = version + + def __repr__(self): + return "<ssa %s version %d>" % (repr(self.reg), self.version) + + +class SSAFlag(object): + def __init__(self, flag, version): + self.flag = flag + self.version = version + + def __repr__(self): + return "<ssa %s version %d>" % (repr(self.flag), self.version) + + +class LowLevelILOperationAndSize(object): + def __init__(self, operation, size): + self.operation = operation + self.size = size + + def __repr__(self): + if self.size == 0: + return "<%s>" % self.operation.name + return "<%s %d>" % (self.operation.name, self.size) + + class LowLevelILInstruction(object): """ ``class LowLevelILInstruction`` Low Level Intermediate Language Instructions are infinite length tree-based @@ -55,12 +122,13 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_POP: [], LowLevelILOperation.LLIL_REG: [("src", "reg")], LowLevelILOperation.LLIL_CONST: [("constant", "int")], + LowLevelILOperation.LLIL_CONST_PTR: [("constant", "int")], LowLevelILOperation.LLIL_FLAG: [("src", "flag")], LowLevelILOperation.LLIL_FLAG_BIT: [("src", "flag"), ("bit", "int")], LowLevelILOperation.LLIL_ADD: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_ADC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_SUB: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_SBB: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_AND: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_OR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_XOR: [("left", "expr"), ("right", "expr")], @@ -68,9 +136,9 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_LSR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ASR: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_ROL: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RLC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_ROR: [("left", "expr"), ("right", "expr")], - LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr")], + LowLevelILOperation.LLIL_RRC: [("left", "expr"), ("right", "expr"), ("carry", "expr")], LowLevelILOperation.LLIL_MUL: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULU_DP: [("left", "expr"), ("right", "expr")], LowLevelILOperation.LLIL_MULS_DP: [("left", "expr"), ("right", "expr")], @@ -86,6 +154,7 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_NOT: [("src", "expr")], LowLevelILOperation.LLIL_SX: [("src", "expr")], LowLevelILOperation.LLIL_ZX: [("src", "expr")], + LowLevelILOperation.LLIL_LOW_PART: [("src", "expr")], LowLevelILOperation.LLIL_JUMP: [("dest", "expr")], LowLevelILOperation.LLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], LowLevelILOperation.LLIL_CALL: [("dest", "expr")], @@ -112,24 +181,24 @@ class LowLevelILInstruction(object): LowLevelILOperation.LLIL_UNDEF: [], LowLevelILOperation.LLIL_UNIMPL: [], LowLevelILOperation.LLIL_UNIMPL_MEM: [("src", "expr")], - LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg"), ("index", "int"), ("src", "expr")], - LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("dest", "reg"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA: [("dest", "reg_ssa"), ("src", "expr")], + LowLevelILOperation.LLIL_SET_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("dest", "reg"), ("src", "expr")], LowLevelILOperation.LLIL_SET_REG_SPLIT_SSA: [("hi", "expr"), ("lo", "expr"), ("src", "expr")], - LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg", "index", "int")], - LowLevelILOperation.LLIL_REG_SSA: [("src", "reg"), ("index", "int")], - LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg"), ("index", "int"), ("src", "reg")], - LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag"), ("index", "int"), ("src", "expr")], - LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag"), ("index", "int")], - LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag"), ("index", "int"), ("bit", "int")], + LowLevelILOperation.LLIL_REG_SPLIT_DEST_SSA: [("dest", "reg_ssa")], + LowLevelILOperation.LLIL_REG_SSA: [("src", "reg_ssa")], + LowLevelILOperation.LLIL_REG_SSA_PARTIAL: [("full_reg", "reg_ssa"), ("src", "reg")], + LowLevelILOperation.LLIL_SET_FLAG_SSA: [("dest", "flag_ssa"), ("src", "expr")], + LowLevelILOperation.LLIL_FLAG_SSA: [("src", "flag_ssa")], + LowLevelILOperation.LLIL_FLAG_BIT_SSA: [("src", "flag_ssa"), ("bit", "int")], LowLevelILOperation.LLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_SYSCALL_SSA: [("output", "expr"), ("stack", "expr"), ("param", "expr")], LowLevelILOperation.LLIL_CALL_OUTPUT_SSA: [("dest_memory", "int"), ("dest", "reg_ssa_list")], - LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg"), ("index", "int"), ("src_memory", "int")], + LowLevelILOperation.LLIL_CALL_STACK_SSA: [("src", "reg_ssa"), ("src_memory", "int")], LowLevelILOperation.LLIL_CALL_PARAM_SSA: [("src", "reg_ssa_list")], LowLevelILOperation.LLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], LowLevelILOperation.LLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], - LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg"), ("index", "int"), ("src", "reg_ssa_list")], - LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "reg"), ("index", "int"), ("src", "flag_ssa_list")], + LowLevelILOperation.LLIL_REG_PHI: [("dest", "reg_ssa"), ("src", "reg_ssa_list")], + LowLevelILOperation.LLIL_FLAG_PHI: [("dest", "flag_ssa"), ("src", "flag_ssa_list")], LowLevelILOperation.LLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -150,27 +219,31 @@ class LowLevelILInstruction(object): self.source_operand = None operands = LowLevelILInstruction.ILOperations[instr.operation] self.operands = [] - for i in xrange(0, len(operands)): - name, operand_type = operands[i] + i = 0 + for operand in operands: + name, operand_type = operand if operand_type == "int": value = instr.operands[i] elif operand_type == "expr": value = LowLevelILInstruction(func, instr.operands[i]) elif operand_type == "reg": - if (instr.operands[i] & 0x80000000) != 0: - value = instr.operands[i] - else: - value = func.arch.get_reg_name(instr.operands[i]) + value = ILRegister(func.arch, instr.operands[i]) + elif operand_type == "reg_ssa": + reg = ILRegister(func.arch, instr.operands[i]) + i += 1 + value = SSARegister(reg, instr.operands[i]) elif operand_type == "flag": - if (instr.operands[i] & 0x80000000) != 0: - value = instr.operands[i] - else: - value = func.arch.get_flag_name(instr.operands[i]) + value = ILFlag(func.arch, instr.operands[i]) + elif operand_type == "flag_ssa": + flag = ILFlag(func.arch, instr.operands[i]) + i += 1 + value = SSAFlag(flag, instr.operands[i]) elif operand_type == "cond": value = LowLevelILFlagCondition(instr.operands[i]) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 value = [] for i in xrange(count.value): value.append(operand_list[i]) @@ -178,27 +251,26 @@ class LowLevelILInstruction(object): elif operand_type == "reg_ssa_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 value = [] for i in xrange(count.value / 2): reg = operand_list[i * 2] - reg_index = operand_list[(i * 2) + 1] - if (reg & 0x80000000) == 0: - reg = func.arch.get_reg_name(reg) - value.append((reg, reg_index)) + reg_version = operand_list[(i * 2) + 1] + value.append(SSARegister(ILRegister(func.arch, reg), reg_version)) core.BNLowLevelILFreeOperandList(operand_list) elif operand_type == "flag_ssa_list": count = ctypes.c_ulonglong() operand_list = core.BNLowLevelILGetOperandList(func.handle, self.expr_index, i, count) + i += 1 value = [] for i in xrange(count.value / 2): flag = operand_list[i * 2] - flag_index = operand_list[(i * 2) + 1] - if (flag & 0x80000000) == 0: - flag = func.arch.get_flag_name(flag) - value.append((flag, flag_index)) + flag_version = operand_list[(i * 2) + 1] + value.append(SSAFlag(ILFlag(func.arch, flag), flag_version)) core.BNLowLevelILFreeOperandList(operand_list) self.operands.append(value) self.__dict__[name] = value + i += 1 def __str__(self): tokens = self.tokens @@ -273,61 +345,76 @@ class LowLevelILInstruction(object): core.BNFreePossibleValueSet(value) return result + @property + def prefix_operands(self): + """All operands in the expression tree in prefix order""" + result = [LowLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: + if isinstance(operand, LowLevelILInstruction): + result += operand.prefix_operands + else: + result.append(operand) + return result + + @property + def postfix_operands(self): + """All operands in the expression tree in postfix order""" + result = [] + for operand in self.operands: + if isinstance(operand, LowLevelILInstruction): + result += operand.postfix_operands + else: + result.append(operand) + result.append(LowLevelILOperationAndSize(self.operation, self.size)) + return result + def get_reg_value(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + 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) return result def get_reg_value_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + 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) return result def get_possible_reg_values(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + 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) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + 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) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + 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) return result def get_flag_value_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + 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) return result def get_possible_flag_values(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + 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) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + 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) core.BNFreePossibleValueSet(value) @@ -589,8 +676,7 @@ class LowLevelILFunction(object): :return: The expression ``reg = value`` :rtype: LowLevelILExpr """ - if isinstance(reg, str): - reg = self.arch.regs[reg].index + reg = self.arch.get_reg_index(reg) return self.expr(LowLevelILOperation.LLIL_SET_REG, reg, value.index, size = size, flags = flags) def set_reg_split(self, size, hi, lo, value, flags = 0): @@ -606,10 +692,8 @@ class LowLevelILFunction(object): :return: The expression ``hi:lo = value`` :rtype: LowLevelILExpr """ - if isinstance(hi, str): - hi = self.arch.regs[hi].index - if isinstance(lo, str): - lo = self.arch.regs[lo].index + hi = self.arch.get_reg_index(hi) + lo = self.arch.get_reg_index(lo) return self.expr(LowLevelILOperation.LLIL_SET_REG_SPLIT, hi, lo, value.index, size = size, flags = flags) def set_flag(self, flag, value): @@ -676,8 +760,7 @@ class LowLevelILFunction(object): :return: A register expression for the given string :rtype: LowLevelILExpr """ - if isinstance(reg, str): - reg = self.arch.regs[reg].index + reg = self.arch.get_reg_index(reg) return self.expr(LowLevelILOperation.LLIL_REG, reg, size=size) def const(self, size, value): @@ -691,6 +774,17 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_CONST, value, size=size) + def const_pointer(self, size, value): + """ + ``const_pointer`` returns an expression for the constant pointer ``value`` with size ``size`` + + :param int size: the size of the pointer in bytes + :param int value: address referenced by pointer + :return: A constant expression of given value and size + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_CONST_PTR, value, size=size) + def flag(self, reg): """ ``flag`` returns a flag expression for the given flag name. @@ -727,7 +821,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ADD, a.index, b.index, size=size, flags=flags) - def add_carry(self, size, a, b, flags=None): + def add_carry(self, size, a, b, carry, flags=None): """ ``add_carry`` adds with carry expression ``a`` to expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -735,11 +829,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: flags to set - :return: The expression ``adc.<size>{<flags>}(a, b)`` + :return: The expression ``adc.<size>{<flags>}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_ADC, a.index, b.index, carry.index, size=size, flags=flags) def sub(self, size, a, b, flags=None): """ @@ -755,7 +850,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SUB, a.index, b.index, size=size, flags=flags) - def sub_borrow(self, size, a, b, flags=None): + def sub_borrow(self, size, a, b, carry, flags=None): """ ``sub_borrow`` subtracts with borrow expression ``b`` from expression ``a`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -763,11 +858,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: flags to set - :return: The expression ``sbc.<size>{<flags>}(a, b)`` + :return: The expression ``sbb.<size>{<flags>}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_SBB, a.index, b.index, carry.index, size=size, flags=flags) def and_expr(self, size, a, b, flags=None): """ @@ -867,7 +963,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ROL, a.index, b.index, size=size, flags=flags) - def rotate_left_carry(self, size, a, b, flags=None): + def rotate_left_carry(self, size, a, b, carry, flags=None): """ ``rotate_left_carry`` bitwise rotates left with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -875,11 +971,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: optional, flags to set - :return: The expression ``rcl.<size>{<flags>}(a, b)`` + :return: The expression ``rlc.<size>{<flags>}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RLC, a.index, b.index, carry.index, size=size, flags=flags) def rotate_right(self, size, a, b, flags=None): """ @@ -895,7 +992,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_ROR, a.index, b.index, size=size, flags=flags) - def rotate_right_carry(self, size, a, b, flags=None): + def rotate_right_carry(self, size, a, b, carry, flags=None): """ ``rotate_right_carry`` bitwise rotates right with carry expression ``a`` by expression ``b`` potentially setting flags ``flags`` and returning an expression of ``size`` bytes. @@ -903,11 +1000,12 @@ class LowLevelILFunction(object): :param int size: the size of the result in bytes :param LowLevelILExpr a: LHS expression :param LowLevelILExpr b: RHS expression + :param LowLevelILExpr carry: Carry flag expression :param str flags: optional, flags to set - :return: The expression ``rcr.<size>{<flags>}(a, b)`` + :return: The expression ``rrc.<size>{<flags>}(a, b, carry)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, size=size, flags=flags) + return self.expr(LowLevelILOperation.LLIL_RRC, a.index, b.index, carry.index, size=size, flags=flags) def mult(self, size, a, b, flags=None): """ @@ -1107,7 +1205,7 @@ class LowLevelILFunction(object): """ return self.expr(LowLevelILOperation.LLIL_SX, value.index, size=size, flags=flags) - def zero_extend(self, size, value): + def zero_extend(self, size, value, flags=None): """ ``zero_extend`` zero-extends the expression in ``value`` to ``size`` bytes @@ -1116,7 +1214,18 @@ class LowLevelILFunction(object): :return: The expression ``sx.<size>(value)`` :rtype: LowLevelILExpr """ - return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size) + return self.expr(LowLevelILOperation.LLIL_ZX, value.index, size=size, flags=flags) + + def low_part(self, size, value, flags=None): + """ + ``low_part`` truncates ``value`` to ``size`` bytes + + :param int size: the size of the result in bytes + :param LowLevelILExpr value: the expression to zero extend + :return: The expression ``(value).<size>`` + :rtype: LowLevelILExpr + """ + return self.expr(LowLevelILOperation.LLIL_LOW_PART, value.index, size=size, flags=flags) def jump(self, dest): """ @@ -1477,18 +1586,16 @@ class LowLevelILFunction(object): def get_non_ssa_instruction_index(self, instr): return core.BNGetLowLevelILNonSSAInstructionIndex(self.handle, instr) - def get_ssa_reg_definition(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, index) + def get_ssa_reg_definition(self, reg_ssa): + reg = self.arch.get_reg_index(reg_ssa.reg) + result = core.BNGetLowLevelILSSARegisterDefinition(self.handle, reg, reg_ssa.version) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None return result - def get_ssa_flag_definition(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) - result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, index) + def get_ssa_flag_definition(self, flag_ssa): + flag = self.arch.get_flag_index(flag_ssa.flag) + result = core.BNGetLowLevelILSSAFlagDefinition(self.handle, flag, flag_ssa.version) if result >= core.BNGetLowLevelILInstructionCount(self.handle): return None return result @@ -1499,22 +1606,20 @@ class LowLevelILFunction(object): return None return result - def get_ssa_reg_uses(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index + def get_ssa_reg_uses(self, reg_ssa): + reg = self.arch.get_reg_index(reg_ssa.reg) count = ctypes.c_ulonglong() - instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, index, count) + instrs = core.BNGetLowLevelILSSARegisterUses(self.handle, reg, reg_ssa.version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_flag_uses(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) + def get_ssa_flag_uses(self, flag_ssa): + flag = self.arch.get_flag_index(flag_ssa.flag) count = ctypes.c_ulonglong() - instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, index, count) + instrs = core.BNGetLowLevelILSSAFlagUses(self.handle, flag, flag_ssa.version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) @@ -1530,17 +1635,15 @@ class LowLevelILFunction(object): core.BNFreeILInstructionList(instrs) return result - def get_ssa_reg_value(self, reg, index): - if isinstance(reg, str): - reg = self.arch.regs[reg].index - value = core.BNGetLowLevelILSSARegisterValue(self.handle, reg, index) + 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) return result - def get_ssa_flag_value(self, flag, index): - if isinstance(flag, str): - flag = self.arch.get_flag_by_name(flag) - value = core.BNGetLowLevelILSSAFlagValue(self.handle, flag, index) + 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) return result diff --git a/python/mainthread.py b/python/mainthread.py index 220f0b64..3e12bd65 100644 --- a/python/mainthread.py +++ b/python/mainthread.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/mediumlevelil.py b/python/mediumlevelil.py index f205714e..4aacad00 100644 --- a/python/mediumlevelil.py +++ b/python/mediumlevelil.py @@ -28,6 +28,15 @@ import basicblock import lowlevelil +class SSAVariable(object): + def __init__(self, var, version): + self.var = var + self.version = version + + def __repr__(self): + return "<ssa %s version %d>" % (repr(self.var), self.version) + + class MediumLevelILLabel(object): def __init__(self, handle = None): if handle is None: @@ -37,6 +46,17 @@ class MediumLevelILLabel(object): self.handle = handle +class MediumLevelILOperationAndSize(object): + def __init__(self, operation, size): + self.operation = operation + self.size = size + + def __repr__(self): + if self.size == 0: + return "<%s>" % self.operation.name + return "<%s %d>" % (self.operation.name, self.size) + + class MediumLevelILInstruction(object): """ ``class MediumLevelILInstruction`` Medium Level Intermediate Language Instructions are infinite length tree-based @@ -56,6 +76,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_ADDRESS_OF: [("src", "var")], MediumLevelILOperation.MLIL_ADDRESS_OF_FIELD: [("src", "var"), ("offset", "int")], MediumLevelILOperation.MLIL_CONST: [("constant", "int")], + MediumLevelILOperation.MLIL_CONST_PTR: [("constant", "int")], MediumLevelILOperation.MLIL_ADD: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_ADC: [("left", "expr"), ("right", "expr")], MediumLevelILOperation.MLIL_SUB: [("left", "expr"), ("right", "expr")], @@ -85,6 +106,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_NOT: [("src", "expr")], MediumLevelILOperation.MLIL_SX: [("src", "expr")], MediumLevelILOperation.MLIL_ZX: [("src", "expr")], + MediumLevelILOperation.MLIL_LOW_PART: [("src", "expr")], MediumLevelILOperation.MLIL_JUMP: [("dest", "expr")], MediumLevelILOperation.MLIL_JUMP_TO: [("dest", "expr"), ("targets", "int_list")], MediumLevelILOperation.MLIL_CALL: [("output", "var_list"), ("dest", "expr"), ("params", "expr_list")], @@ -114,15 +136,15 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_UNDEF: [], MediumLevelILOperation.MLIL_UNIMPL: [], MediumLevelILOperation.MLIL_UNIMPL_MEM: [("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var"), ("index", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("dest", "var"), ("dest_index", "int"), ("src_index", "int"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA: [("dest", "var_ssa"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA: [("high", "expr"), ("low", "expr"), ("src", "expr")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "exor")], - MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("dest", "var"), ("dest_memory", "int"), ("src_memory", "int"), ("offset", "int"), ("src", "exor")], - MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var"), ("index", "int")], - MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var"), ("index", "int"), ("offset", "int")], - MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var"), ("src_memory", "int")], - MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var"), ("src_memory", "int"), ("offset", "int")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED: [("prev", "var_ssa_dest_and_src"), ("src", "expr")], + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD: [("prev", "var_ssa_dest_and_src"), ("offset", "int"), ("src", "expr")], + MediumLevelILOperation.MLIL_VAR_SSA: [("src", "var_ssa")], + MediumLevelILOperation.MLIL_VAR_SSA_FIELD: [("src", "var_ssa"), ("offset", "int")], + MediumLevelILOperation.MLIL_VAR_ALIASED: [("src", "var_ssa")], + MediumLevelILOperation.MLIL_VAR_ALIASED_FIELD: [("src", "var_ssa"), ("offset", "int")], MediumLevelILOperation.MLIL_CALL_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr_list"), ("src_memory", "int")], MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA: [("output", "expr"), ("dest", "expr"), ("params", "expr"), ("stack", "expr")], MediumLevelILOperation.MLIL_SYSCALL_SSA: [("output", "expr"), ("params", "expr_list"), ("src_memory", "int")], @@ -131,7 +153,7 @@ class MediumLevelILInstruction(object): MediumLevelILOperation.MLIL_CALL_PARAM_SSA: [("src_memory", "int"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_LOAD_SSA: [("src", "expr"), ("src_memory", "int")], MediumLevelILOperation.MLIL_STORE_SSA: [("dest", "expr"), ("dest_memory", "int"), ("src_memory", "int"), ("src", "expr")], - MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var"), ("index", "int"), ("src", "var_ssa_list")], + MediumLevelILOperation.MLIL_VAR_PHI: [("dest", "var_ssa"), ("src", "var_ssa_list")], MediumLevelILOperation.MLIL_MEM_PHI: [("dest_memory", "int"), ("src_memory", "int_list")] } @@ -157,6 +179,19 @@ class MediumLevelILInstruction(object): value = MediumLevelILInstruction(func, instr.operands[i]) elif operand_type == "var": value = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + elif operand_type == "var_ssa": + var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + version = instr.operands[i + 1] + i += 1 + value = SSAVariable(var, version) + elif operand_type == "var_ssa_dest_and_src": + var = function.Variable.from_identifier(self.function.source_function, instr.operands[i]) + dest_version = instr.operands[i + 1] + src_version = instr.operands[i + 2] + i += 2 + self.operands.append(SSAVariable(var, dest_version)) + self.dest = SSAVariable(var, dest_version) + value = SSAVariable(var, src_version) elif operand_type == "int_list": count = ctypes.c_ulonglong() operand_list = core.BNMediumLevelILGetOperandList(func.handle, self.expr_index, i, count) @@ -179,9 +214,9 @@ class MediumLevelILInstruction(object): value = [] for j in xrange(count.value / 2): var_id = operand_list[j * 2] - var_index = operand_list[(j * 2) + 1] - value.append((function.Variable.from_identifier(self.function.source_function, - var_id), var_index)) + var_version = operand_list[(j * 2) + 1] + value.append(SSAVariable(function.Variable.from_identifier(self.function.source_function, + var_id), var_version)) core.BNMediumLevelILFreeOperandList(operand_list) elif operand_type == "expr_list": count = ctypes.c_ulonglong() @@ -281,35 +316,108 @@ class MediumLevelILInstruction(object): return lowlevelil.LowLevelILInstruction(self.function.low_level_il.ssa_form, expr) @property - def ssa_memory_index(self): - """Index of active memory contents in SSA form for this instruction""" - return core.BNGetMediumLevelILSSAMemoryIndexAtILInstruction(self.function.handle, self.instr_index) + def ssa_memory_version(self): + """Version of active memory contents in SSA form for this instruction""" + return core.BNGetMediumLevelILSSAMemoryVersionAtILInstruction(self.function.handle, self.instr_index) + + @property + def prefix_operands(self): + """All operands in the expression tree in prefix order""" + result = [MediumLevelILOperationAndSize(self.operation, self.size)] + for operand in self.operands: + if isinstance(operand, MediumLevelILInstruction): + result += operand.prefix_operands + else: + result.append(operand) + return result + + @property + def postfix_operands(self): + """All operands in the expression tree in postfix order""" + result = [] + for operand in self.operands: + if isinstance(operand, MediumLevelILInstruction): + result += operand.postfix_operands + else: + result.append(operand) + result.append(MediumLevelILOperationAndSize(self.operation, self.size)) + return result + + @property + def vars_written(self): + """List of variables written by instruction""" + if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_SSA, MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_ALIASED, MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD, + MediumLevelILOperation.MLIL_VAR_PHI]: + return [self.dest] + elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA]: + return [self.high, self.low] + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL]: + return self.output + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, + MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, + MediumLevelILOperation.MLIL_SYSCALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + return self.output.vars_written + elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: + return self.dest + return [] + + @property + def vars_read(self): + """List of variables read by instruction""" + if self.operation in [MediumLevelILOperation.MLIL_SET_VAR, MediumLevelILOperation.MLIL_SET_VAR_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_SPLIT, MediumLevelILOperation.MLIL_SET_VAR_SSA, + MediumLevelILOperation.MLIL_SET_VAR_SPLIT_SSA, MediumLevelILOperation.MLIL_SET_VAR_ALIASED]: + return self.src.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_SET_VAR_SSA_FIELD, + MediumLevelILOperation.MLIL_SET_VAR_ALIASED_FIELD]: + return [self.prev] + self.src.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_CALL, MediumLevelILOperation.MLIL_SYSCALL, + MediumLevelILOperation.MLIL_CALL_SSA, MediumLevelILOperation.MLIL_SYSCALL_SSA]: + result = [] + for param in self.params: + result += param.vars_read + return result + elif self.operation in [MediumLevelILOperation.MLIL_CALL_UNTYPED, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED, + MediumLevelILOperation.MLIL_CALL_UNTYPED_SSA, MediumLevelILOperation.MLIL_SYSCALL_UNTYPED_SSA]: + return self.params.vars_read + elif self.operation in [MediumLevelILOperation.MLIL_CALL_PARAM, MediumLevelILOperation.MLIL_CALL_PARAM_SSA, + MediumLevelILOperation.MLIL_VAR_PHI]: + return self.src + elif self.operation in [MediumLevelILOperation.MLIL_CALL_OUTPUT, MediumLevelILOperation.MLIL_CALL_OUTPUT_SSA]: + return [] + result = [] + for operand in self.operands: + if (isinstance(operand, function.Variable)) or (isinstance(operand, SSAVariable)): + result.append(operand) + elif isinstance(operand, MediumLevelILInstruction): + result += operand.vars_read + return result - def get_ssa_var_possible_values(self, var, index): + def get_ssa_var_possible_values(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, index, self.instr_index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + value = core.BNGetMediumLevelILPossibleSSAVarValues(self.function.handle, var_data, ssa_var.version, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result - def get_ssa_var_index(self, var): + def get_ssa_var_version(self, var): var_data = core.BNVariable() var_data.type = var.source_type var_data.index = var.index var_data.storage = var.storage - return core.BNGetMediumLevelILSSAVarIndexAtILInstruction(self.function.handle, var_data, self.instr_index) + return core.BNGetMediumLevelILSSAVarVersionAtILInstruction(self.function.handle, var_data, self.instr_index) def get_var_for_reg(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) result = core.BNGetMediumLevelILVariableForRegisterAtInstruction(self.function.handle, reg, self.instr_index) return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_var_for_flag(self, flag): - if isinstance(flag, str): - flag = self.function.arch.regs[flag].index + flag = self.function.arch.get_flag_index(flag) result = core.BNGetMediumLevelILVariableForFlagAtInstruction(self.function.handle, flag, self.instr_index) return function.Variable(self.function.source_function, result.type, result.index, result.storage) @@ -318,60 +426,52 @@ class MediumLevelILInstruction(object): return function.Variable(self.function.source_function, result.type, result.index, result.storage) def get_reg_value(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAtInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_reg_value_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILRegisterValueAfterInstruction(self.function.handle, reg, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_reg_values(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAtInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_reg_values_after(self, reg): - if isinstance(reg, str): - reg = self.function.arch.regs[reg].index + reg = self.function.arch.get_reg_index(reg) value = core.BNGetMediumLevelILPossibleRegisterValuesAfterInstruction(self.function.handle, reg, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_flag_value(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAtInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_flag_value_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILFlagValueAfterInstruction(self.function.handle, flag, self.instr_index) result = function.RegisterValue(self.function.arch, value) return result def get_possible_flag_values(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAtInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) return result def get_possible_flag_values_after(self, flag): - if isinstance(flag, str): - flag = self.function.arch.flags[flag].index + flag = self.function.arch.get_flag_index(flag) value = core.BNGetMediumLevelILPossibleFlagValuesAfterInstruction(self.function.handle, flag, self.instr_index) result = function.PossibleValueSet(self.function.arch, value) core.BNFreePossibleValueSet(value) @@ -644,50 +744,50 @@ class MediumLevelILFunction(object): def get_non_ssa_instruction_index(self, instr): return core.BNGetMediumLevelILNonSSAInstructionIndex(self.handle, instr) - def get_ssa_var_definition(self, var, index): + def get_ssa_var_definition(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + result = core.BNGetMediumLevelILSSAVarDefinition(self.handle, var_data, ssa_var.version) if result >= core.BNGetMediumLevelILInstructionCount(self.handle): return None return result - def get_ssa_memory_definition(self, index): - result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, index) + def get_ssa_memory_definition(self, version): + result = core.BNGetMediumLevelILSSAMemoryDefinition(self.handle, version) if result >= core.BNGetMediumLevelILInstructionCount(self.handle): return None return result - def get_ssa_var_uses(self, var, index): + def get_ssa_var_uses(self, ssa_var): count = ctypes.c_ulonglong() var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - instrs = core.BNGetMediumLevelILSSAVarUses(self.handle, var_data, index, count) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + 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): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_memory_uses(self, index): + def get_ssa_memory_uses(self, version): count = ctypes.c_ulonglong() - instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, index, count) + instrs = core.BNGetMediumLevelILSSAMemoryUses(self.handle, version, count) result = [] for i in xrange(0, count.value): result.append(instrs[i]) core.BNFreeILInstructionList(instrs) return result - def get_ssa_var_value(self, var, index): + def get_ssa_var_value(self, ssa_var): var_data = core.BNVariable() - var_data.type = var.source_type - var_data.index = var.index - var_data.storage = var.storage - value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, index) + var_data.type = ssa_var.var.source_type + var_data.index = ssa_var.var.index + var_data.storage = ssa_var.var.storage + value = core.BNGetMediumLevelILSSAVarValue(self.handle, var_data, ssa_var.version) result = function.RegisterValue(self.arch, value) return result diff --git a/python/platform.py b/python/platform.py index 139b7d5e..9ba7625f 100644 --- a/python/platform.py +++ b/python/platform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/plugin.py b/python/plugin.py index 2632b5a9..f038d122 100644 --- a/python/plugin.py +++ b/python/plugin.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/pluginmanager.py b/python/pluginmanager.py index 37962114..c0f70260 100644 --- a/python/pluginmanager.py +++ b/python/pluginmanager.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/scriptingprovider.py b/python/scriptingprovider.py index 71402b1b..94616d59 100644 --- a/python/scriptingprovider.py +++ b/python/scriptingprovider.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -35,8 +35,6 @@ import basicblock import startup import log -_output_to_log = False - class _ThreadActionContext(object): _actions = [] @@ -379,14 +377,12 @@ class _PythonScriptingInstanceOutput(object): return self.write('\n'.join(lines)) def write(self, data): - global _output_to_log - interpreter = None if "value" in dir(PythonScriptingInstance._interpreter): interpreter = PythonScriptingInstance._interpreter.value if interpreter is None: - if _output_to_log: + if log.is_output_redirected_to_log(): self.buffer += data while True: i = self.buffer.find('\n') diff --git a/python/startup.py b/python/startup.py index 324cc690..0abc47cb 100644 --- a/python/startup.py +++ b/python/startup.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/transform.py b/python/transform.py index 40382c69..59d719e7 100644 --- a/python/transform.py +++ b/python/transform.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/types.py b/python/types.py index ebaa36fc..f8e416f4 100644 --- a/python/types.py +++ b/python/types.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 @@ -22,7 +22,7 @@ import ctypes # Binary Ninja components import _binaryninjacore as core -from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType +from enums import SymbolType, TypeClass, NamedTypeReferenceClass, InstructionTextTokenType, StructureType import callingconvention import function @@ -646,9 +646,13 @@ class Structure(object): def union(self): return core.BNIsStructureUnion(self.handle) - @union.setter - def union(self, value): - core.BNSetStructureUnion(self.handle, value) + @property + def type(self): + return StructureType(core.BNGetStructureType(self.handle)) + + @type.setter + def type(self, value): + core.BNSetStructureType(self.handle, value) def __setattr__(self, name, value): try: diff --git a/python/undoaction.py b/python/undoaction.py index 9f742e00..7e3c76a0 100644 --- a/python/undoaction.py +++ b/python/undoaction.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 diff --git a/python/update.py b/python/update.py index 6417e4a0..be6962d7 100644 --- a/python/update.py +++ b/python/update.py @@ -1,4 +1,4 @@ -# Copyright (c) 2015-2016 Vector 35 LLC +# 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 |
