diff options
Diffstat (limited to 'miasm2/analysis')
| -rw-r--r-- | miasm2/analysis/binary.py | 34 | ||||
| -rw-r--r-- | miasm2/analysis/cst_propag.py | 6 | ||||
| -rw-r--r-- | miasm2/analysis/data_analysis.py | 39 | ||||
| -rw-r--r-- | miasm2/analysis/data_flow.py | 100 | ||||
| -rw-r--r-- | miasm2/analysis/debugging.py | 175 | ||||
| -rw-r--r-- | miasm2/analysis/depgraph.py | 43 | ||||
| -rw-r--r-- | miasm2/analysis/disasm_cb.py | 24 | ||||
| -rw-r--r-- | miasm2/analysis/dse.py | 59 | ||||
| -rw-r--r-- | miasm2/analysis/expression_range.py | 11 | ||||
| -rw-r--r-- | miasm2/analysis/gdbserver.py | 336 | ||||
| -rw-r--r-- | miasm2/analysis/modularintervals.py | 11 | ||||
| -rw-r--r-- | miasm2/analysis/outofssa.py | 28 | ||||
| -rw-r--r-- | miasm2/analysis/sandbox.py | 148 | ||||
| -rw-r--r-- | miasm2/analysis/simplifier.py | 4 | ||||
| -rw-r--r-- | miasm2/analysis/ssa.py | 41 |
15 files changed, 602 insertions, 457 deletions
diff --git a/miasm2/analysis/binary.py b/miasm2/analysis/binary.py index 93bd74b2..ee733d79 100644 --- a/miasm2/analysis/binary.py +++ b/miasm2/analysis/binary.py @@ -46,7 +46,7 @@ class Container(object): return container_type(data, *args, **kwargs) except ContainerSignatureException: continue - except ContainerParsingException, error: + except ContainerParsingException as error: log.error(error) # Fallback mode @@ -134,7 +134,7 @@ class ContainerPE(Container): from elfesteem import pe_init # Parse signature - if not data.startswith('MZ'): + if not data.startswith(b'MZ'): raise ContainerSignatureException() # Build executable instance @@ -143,7 +143,7 @@ class ContainerPE(Container): self._executable = vm_load_pe(vm, data) else: self._executable = pe_init.PE(data) - except Exception, error: + except Exception as error: raise ContainerParsingException('Cannot read PE: %s' % error) # Check instance validity @@ -159,7 +159,7 @@ class ContainerPE(Container): self._bin_stream = bin_stream_pe(self._executable) ep_detected = self._executable.Opthdr.AddressOfEntryPoint self._entry_point = self._executable.rva2virt(ep_detected) - except Exception, error: + except Exception as error: raise ContainerParsingException('Cannot read PE: %s' % error) @@ -168,7 +168,7 @@ class ContainerELF(Container): def parse(self, data, vm=None, addr=0, apply_reloc=False, **kwargs): """Load an ELF from @data - @data: str containing the ELF bytes + @data: bytes containing the ELF bytes @vm (optional): VmMngr instance. If set, load the ELF in virtual memory @addr (optional): base address the ELF in virtual memory @apply_reloc (optional): if set, apply relocation during ELF loading @@ -181,18 +181,22 @@ class ContainerELF(Container): from elfesteem import elf_init # Parse signature - if not data.startswith('\x7fELF'): + if not data.startswith(b'\x7fELF'): raise ContainerSignatureException() # Build executable instance try: if vm is not None: - self._executable = vm_load_elf(vm, data, loc_db=self.loc_db, - base_addr=addr, - apply_reloc=apply_reloc) + self._executable = vm_load_elf( + vm, + data, + loc_db=self.loc_db, + base_addr=addr, + apply_reloc=apply_reloc + ) else: self._executable = elf_init.ELF(data) - except Exception, error: + except Exception as error: raise ContainerParsingException('Cannot read ELF: %s' % error) # Guess the architecture @@ -202,7 +206,7 @@ class ContainerELF(Container): try: self._bin_stream = bin_stream_elf(self._executable) self._entry_point = self._executable.Ehdr.entry + addr - except Exception, error: + except Exception as error: raise ContainerParsingException('Cannot read ELF: %s' % error) if vm is None: @@ -217,9 +221,11 @@ class ContainerUnknown(Container): def parse(self, data, vm=None, addr=0, **kwargs): self._bin_stream = bin_stream_str(data, base_address=addr) if vm is not None: - vm.add_memory_page(addr, - PAGE_READ, - data) + vm.add_memory_page( + addr, + PAGE_READ, + data + ) self._executable = None self._entry_point = 0 diff --git a/miasm2/analysis/cst_propag.py b/miasm2/analysis/cst_propag.py index 9a5e3d54..25d66318 100644 --- a/miasm2/analysis/cst_propag.py +++ b/miasm2/analysis/cst_propag.py @@ -1,5 +1,7 @@ import logging +from future.utils import viewitems + from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.expression.expression import ExprMem from miasm2.expression.expression_helper import possible_values @@ -95,7 +97,7 @@ class SymbExecStateFix(SymbolicExecutionEngine): for index, assignblk in enumerate(irb): new_assignblk = {} links = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): src = self.propag_expr_cst(src) if dst.is_mem(): ptr = dst.ptr @@ -175,7 +177,7 @@ def propagate_cst_expr(ir_arch, ircfg, addr, init_infos): """ states = compute_cst_propagation_states(ir_arch, ircfg, addr, init_infos) cst_propag_link = {} - for lbl, state in states.iteritems(): + for lbl, state in viewitems(states): if lbl not in ircfg.blocks: continue symbexec = SymbExecStateFix(ir_arch, ircfg, state, cst_propag_link) diff --git a/miasm2/analysis/data_analysis.py b/miasm2/analysis/data_analysis.py index 30346e63..bd073fcb 100644 --- a/miasm2/analysis/data_analysis.py +++ b/miasm2/analysis/data_analysis.py @@ -1,5 +1,12 @@ +from __future__ import print_function + +from future.utils import viewitems + +from builtins import object +from functools import cmp_to_key from miasm2.expression.expression \ - import get_expr_mem, get_list_rw, ExprId, ExprInt + import get_expr_mem, get_list_rw, ExprId, ExprInt, \ + compare_exprs from miasm2.ir.symbexec import SymbolicExecutionEngine @@ -19,7 +26,7 @@ def intra_block_flow_raw(ir_arch, ircfg, flow_graph, irb, in_nodes, out_nodes): # gen mem arg to mem node links all_mems = set() - for node_w, nodes_r in dict_rw.iteritems(): + for node_w, nodes_r in viewitems(dict_rw): for n in nodes_r.union([node_w]): all_mems.update(get_expr_mem(n)) if not all_mems: @@ -40,7 +47,7 @@ def intra_block_flow_raw(ir_arch, ircfg, flow_graph, irb, in_nodes, out_nodes): flow_graph.add_uniq_edge(node_n_r, node_n_w) # gen data flow links - for node_w, nodes_r in dict_rw.iteritems(): + for node_w, nodes_r in viewitems(dict_rw): for n_r in nodes_r: if n_r in current_nodes: node_n_r = current_nodes[n_r] @@ -65,11 +72,11 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node # link current nodes to bloc in_nodes if not lbl in ircfg.blocks: - print "cannot find bloc!!", lbl + print("cannot find bloc!!", lbl) return set() irb = ircfg.blocks[lbl] to_del = set() - for n_r, node_n_r in irb_in_nodes[irb.loc_key].items(): + for n_r, node_n_r in viewitems(irb_in_nodes[irb.loc_key]): if not n_r in current_nodes: continue flow_graph.add_uniq_edge(current_nodes[n_r], node_n_r) @@ -78,7 +85,7 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node # if link exec to data, all nodes depends on exec nodes if link_exec_to_data: for n_x_r in exec_nodes: - for n_r, node_n_r in irb_in_nodes[irb.loc_key].items(): + for n_r, node_n_r in viewitems(irb_in_nodes[irb.loc_key]): if not n_x_r in current_nodes: continue if isinstance(n_r, ExprInt): @@ -86,15 +93,15 @@ def inter_block_flow_link(ir_arch, ircfg, flow_graph, irb_in_nodes, irb_out_node flow_graph.add_uniq_edge(current_nodes[n_x_r], node_n_r) # update current nodes using bloc out_nodes - for n_w, node_n_w in irb_out_nodes[irb.loc_key].items(): + for n_w, node_n_w in viewitems(irb_out_nodes[irb.loc_key]): current_nodes[n_w] = node_n_w # get nodes involved in exec flow - x_nodes = tuple(sorted(list(irb.dst.get_r()))) + x_nodes = tuple(sorted(irb.dst.get_r(), key=cmp_to_key(compare_exprs))) todo = set() for lbl_dst in ircfg.successors(irb.loc_key): - todo.add((lbl_dst, tuple(current_nodes.items()), x_nodes)) + todo.add((lbl_dst, tuple(viewitems(current_nodes)), x_nodes)) return todo @@ -109,7 +116,7 @@ def create_implicit_flow(ir_arch, flow_graph, irb_in_nodes, irb_out_ndes): irb = ir_arch.blocks[lbl] for lbl_son in ir_arch.graph.successors(irb.loc_key): if not lbl_son in ir_arch.blocks: - print "cannot find bloc!!", lbl + print("cannot find bloc!!", lbl) continue irb_son = ir_arch.blocks[lbl_son] for n_r in irb_in_nodes[irb_son.loc_key]: @@ -144,7 +151,7 @@ def inter_block_flow(ir_arch, ircfg, flow_graph, irb_0, irb_in_nodes, irb_out_no todo.update(out) -class symb_exec_func: +class symb_exec_func(object): """ This algorithm will do symbolic execution on a function, trying to propagate @@ -164,15 +171,13 @@ class symb_exec_func: self.ir_arch = ir_arch def add_state(self, parent, ad, state): - variables = dict(state.symbols.items()) + variables = dict(state.symbols) # get bloc dead, and remove from state b = self.ir_arch.get_block(ad) if b is None: raise ValueError("unknown bloc! %s" % ad) - variables = variables.items() - - s = parent, ad, tuple(sorted(variables)) + s = parent, ad, tuple(sorted(viewitems(variables))) self.todo.add(s) def get_next_state(self): @@ -183,10 +188,10 @@ class symb_exec_func: if len(self.todo) == 0: return None if self.total_done > 600: - print "symbexec watchdog!" + print("symbexec watchdog!") return None self.total_done += 1 - print 'CPT', self.total_done + print('CPT', self.total_done) while self.todo: state = self.get_next_state() parent, ad, s = state diff --git a/miasm2/analysis/data_flow.py b/miasm2/analysis/data_flow.py index 2201a088..3874b21b 100644 --- a/miasm2/analysis/data_flow.py +++ b/miasm2/analysis/data_flow.py @@ -1,6 +1,8 @@ """Data flow analysis based on miasm intermediate representation""" - +from builtins import range from collections import namedtuple +from future.utils import viewitems, viewvalues +from miasm2.core.utils import encode_hex from miasm2.core.graph import DiGraph from miasm2.ir.ir import AssignBlock, IRBlock from miasm2.expression.expression import ExprLoc, ExprMem, ExprId, ExprInt,\ @@ -56,7 +58,7 @@ class ReachingDefinitions(dict): modified = True while modified: modified = False - for block in self.ircfg.blocks.itervalues(): + for block in viewvalues(self.ircfg.blocks): modified |= self.process_block(block) def process_block(self, block): @@ -67,7 +69,7 @@ class ReachingDefinitions(dict): predecessor_state = {} for pred_lbl in self.ircfg.predecessors(block.loc_key): pred = self.ircfg.blocks[pred_lbl] - for lval, definitions in self.get_definitions(pred_lbl, len(pred)).iteritems(): + for lval, definitions in viewitems(self.get_definitions(pred_lbl, len(pred))): predecessor_state.setdefault(lval, set()).update(definitions) modified = self.get((block.loc_key, 0)) != predecessor_state @@ -75,7 +77,7 @@ class ReachingDefinitions(dict): return False self[(block.loc_key, 0)] = predecessor_state - for index in xrange(len(block)): + for index in range(len(block)): modified |= self.process_assignblock(block, index) return modified @@ -151,7 +153,7 @@ class DiGraphDefUse(DiGraph): def _compute_def_use(self, reaching_defs, deref_mem=False): - for block in self._blocks.itervalues(): + for block in viewvalues(self._blocks): self._compute_def_use_block(block, reaching_defs, deref_mem=deref_mem) @@ -159,7 +161,7 @@ class DiGraphDefUse(DiGraph): def _compute_def_use_block(self, block, reaching_defs, deref_mem=False): for index, assignblk in enumerate(block): assignblk_reaching_defs = reaching_defs.get_definitions(block.loc_key, index) - for lval, expr in assignblk.iteritems(): + for lval, expr in viewitems(assignblk): self.add_node(AssignblkNode(block.loc_key, index, lval)) read_vars = expr.get_r(mem_read=deref_mem) @@ -212,7 +214,7 @@ def dead_simp_useful_assignblks(irarch, defuse, reaching_defs): ircfg = reaching_defs.ircfg useful = set() - for block_lbl, block in ircfg.blocks.iteritems(): + for block_lbl, block in viewitems(ircfg.blocks): successors = ircfg.successors(block_lbl) for successor in successors: if successor not in ircfg.blocks: @@ -225,14 +227,14 @@ def dead_simp_useful_assignblks(irarch, defuse, reaching_defs): if keep_all_definitions or (len(successors) == 0): valid_definitions = reaching_defs.get_definitions(block_lbl, len(block)) - for lval, definitions in valid_definitions.iteritems(): + for lval, definitions in viewitems(valid_definitions): if lval in irarch.get_out_regs(block) or keep_all_definitions: for definition in definitions: useful.add(AssignblkNode(definition[0], definition[1], lval)) # Force keeping of specific cases for index, assignblk in enumerate(block): - for lval, rval in assignblk.iteritems(): + for lval, rval in viewitems(assignblk): if (lval.is_mem() or irarch.IRDst == lval or lval.is_id("exception_flags") or @@ -262,7 +264,7 @@ def dead_simp(irarch, ircfg): reaching_defs = ReachingDefinitions(ircfg) defuse = DiGraphDefUse(reaching_defs, deref_mem=True) useful = set(dead_simp_useful_assignblks(irarch, defuse, reaching_defs)) - for block in ircfg.blocks.itervalues(): + for block in list(viewvalues(ircfg.blocks)): irs = [] for idx, assignblk in enumerate(block): new_assignblk = dict(assignblk) @@ -311,7 +313,7 @@ def _do_merge_blocks(ircfg, loc_key, son_loc_key): assignblks.append(assignblk) continue affs = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if dst != ircfg.IRDst: affs[dst] = src if affs: @@ -348,7 +350,7 @@ def _test_jmp_only(ircfg, loc_key, heads): irblock = ircfg.blocks[loc_key] if len(irblock.assignblks) != 1: return None - items = dict(irblock.assignblks[0]).items() + items = list(viewitems(dict(irblock.assignblks[0]))) if len(items) != 1: return None if len(ircfg.successors(loc_key)) != 1: @@ -528,7 +530,7 @@ def remove_empty_assignblks(ircfg): @ircfg: IRCFG instance """ modified = False - for loc_key, block in ircfg.blocks.iteritems(): + for loc_key, block in list(viewitems(ircfg.blocks)): irs = [] block_modified = False for assignblk in block: @@ -591,13 +593,13 @@ class SSADefUse(DiGraph): if block is None: continue for index, assignblk in enumerate(block): - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): node = AssignblkNode(lbl, index, dst) graph.add_var_def(node, src) graph.add_def_node(def_nodes, node, src) graph.add_use_node(use_nodes, node, src) - for dst, node in def_nodes.iteritems(): + for dst, node in viewitems(def_nodes): graph.add_node(node) if dst not in use_nodes: continue @@ -650,7 +652,7 @@ class PropagateThroughExprId(object): @assignblks: list of AssignBlock to check """ for assignblk in assignblks: - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if src.is_function_call(): return True if dst.is_mem(): @@ -723,7 +725,7 @@ class PropagateThroughExprId(object): def_dct = {} for node in ircfg.nodes(): for index, assignblk in enumerate(ircfg.blocks[node]): - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if not dst.is_id(): continue if dst in ssa.immutable_ids: @@ -786,7 +788,7 @@ class PropagateThroughExprId(object): """ node_to_reg, to_replace, defuse = self.get_candidates(ssa, head, max_expr_depth) modified = False - for node, reg in node_to_reg.iteritems(): + for node, reg in viewitems(node_to_reg): for successor in defuse.successors(node): if not self.propagation_allowed(ssa, to_replace, node, successor): continue @@ -800,7 +802,7 @@ class PropagateThroughExprId(object): assignblks = list(block) assignblk = block[node_b.index] out = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if src.is_op('Phi'): out[dst] = src continue @@ -874,16 +876,16 @@ class PropagateThroughExprMem(object): ircfg = ssa.graph todo = set() modified = False - for block in ircfg.blocks.itervalues(): + for block in viewvalues(ircfg.blocks): for i, assignblk in enumerate(block): - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if not dst.is_mem(): continue if expr_has_mem(src): continue todo.add((block.loc_key, i + 1, dst, src)) ptr = dst.ptr - for size in xrange(8, dst.size, 8): + for size in range(8, dst.size, 8): todo.add((block.loc_key, i + 1, ExprMem(ptr, size), src[:size])) while todo: @@ -891,13 +893,13 @@ class PropagateThroughExprMem(object): block = ircfg.blocks[loc_key] assignblks = list(block) block_modified = False - for i in xrange(index, len(block)): + for i in range(index, len(block)): assignblk = block[i] write_mem = False assignblk_modified = False out = dict(assignblk) out_new = {} - for dst, src in out.iteritems(): + for dst, src in viewitems(out): if dst.is_mem(): write_mem = True ptr = dst.ptr.replace_expr({mem_dst:mem_src}) @@ -941,7 +943,7 @@ def stack_to_reg(expr): diff = int(ptr.args[1]) assert diff % 4 == 0 diff = (0 - diff) & 0xFFFFFFFF - return ExprId("STACK.%d" % (diff / 4), expr.size) + return ExprId("STACK.%d" % (diff // 4), expr.size) return False @@ -997,12 +999,12 @@ def retrieve_stack_accesses(ir_arch_a, ircfg): @ircfg: IRCFG instance """ stack_vars = set() - for block in ircfg.blocks.itervalues(): + for block in viewvalues(ircfg.blocks): for assignblk in block: - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): stack_vars.update(get_stack_accesses(ir_arch_a, dst)) stack_vars.update(get_stack_accesses(ir_arch_a, src)) - stack_vars = filter(lambda expr: check_expr_below_stack(ir_arch_a, expr), stack_vars) + stack_vars = [expr for expr in stack_vars if check_expr_below_stack(ir_arch_a, expr)] base_to_var = {} for var in stack_vars: @@ -1010,7 +1012,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg): base_to_interval = {} - for addr, vars in base_to_var.iteritems(): + for addr, vars in viewitems(base_to_var): var_interval = interval() for var in vars: offset = expr_simp(addr - ir_arch_a.sp) @@ -1019,7 +1021,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg): continue start = int(offset) - stop = int(expr_simp(offset + ExprInt(var.size / 8, offset.size))) + stop = int(expr_simp(offset + ExprInt(var.size // 8, offset.size))) mem = interval([(start, stop-1)]) var_interval += mem base_to_interval[addr] = var_interval @@ -1033,7 +1035,7 @@ def retrieve_stack_accesses(ir_arch_a, ircfg): tmp += mem base_to_info = {} - for addr, vars in base_to_var.iteritems(): + for addr, vars in viewitems(base_to_var): name = "var_%d" % (len(base_to_info)) size = max([var.size for var in vars]) base_to_info[addr] = size, name @@ -1079,11 +1081,11 @@ def replace_stack_vars(ir_arch_a, ircfg): base_to_info = retrieve_stack_accesses(ir_arch_a, ircfg) modified = False - for block in ircfg.blocks.itervalues(): + for block in list(viewvalues(ircfg.blocks)): assignblks = [] for assignblk in block: out = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): new_dst = dst.visit(lambda expr:replace_mem_stack_vars(expr, base_to_info)) new_src = src.visit(lambda expr:replace_mem_stack_vars(expr, base_to_info)) if new_dst != dst or new_src != src: @@ -1120,9 +1122,9 @@ def get_memlookup(expr, bs, is_addr_ro_variable): def read_mem(bs, expr): ptr = int(expr.ptr) - var_bytes = bs.getbytes(ptr, expr.size / 8)[::-1] + var_bytes = bs.getbytes(ptr, expr.size // 8)[::-1] try: - value = int(var_bytes.encode('hex'), 16) + value = int(encode_hex(var_bytes), 16) except ValueError: return expr return ExprInt(value, expr.size) @@ -1137,11 +1139,11 @@ def load_from_int(ir_arch, bs, is_addr_ro_variable): """ modified = False - for block in ir_arch.blocks.itervalues(): + for block in list(viewvalues(ir_arch.blocks)): assignblks = list() for assignblk in block: out = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): # Test src mems = get_memlookup(src, bs, is_addr_ro_variable) src_new = src @@ -1197,7 +1199,7 @@ class AssignBlockLivenessInfos(object): out.append( '\n'.join( "\t%s = %s" % (dst, src) - for (dst, src) in self.assignblk.iteritems() + for (dst, src) in viewitems(self.assignblk) ) ) out.append("\tVarOut:" + ", ".join(str(x) for x in self.var_out)) @@ -1217,7 +1219,7 @@ class IRBlockLivenessInfos(object): self.assignblks = [] for assignblk in irblock: gens, kills = set(), set() - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): expr = ExprAssign(dst, src) read = expr.get_r(mem_read=True) write = expr.get_w() @@ -1290,13 +1292,13 @@ class DiGraphLiveness(DiGraph): ) if node not in self._blocks: yield [self.DotCellDescription(text="NOT PRESENT", attr={})] - raise StopIteration + return for i, info in enumerate(self._blocks[node].infos): var_in = "VarIn:" + ", ".join(str(x) for x in info.var_in) var_out = "VarOut:" + ", ".join(str(x) for x in info.var_out) - assignmnts = ["%s = %s" % (dst, src) for (dst, src) in info.assignblk.iteritems()] + assignmnts = ["%s = %s" % (dst, src) for (dst, src) in viewitems(info.assignblk)] if i == 0: yield self.DotCellDescription( @@ -1323,7 +1325,7 @@ class DiGraphLiveness(DiGraph): """ infos = block.infos modified = False - for i in reversed(xrange(len(infos))): + for i in reversed(range(len(infos))): new_vars = set(infos[i].gen.union(infos[i].var_out.difference(infos[i].kill))) if infos[i].var_in != new_vars: modified = True @@ -1385,13 +1387,13 @@ def discard_phi_sources(ircfg, deleted_vars): @ircfg: IRCFG instance in ssa form @deleted_vars: unused phi sources """ - for block in ircfg.blocks.values(): + for block in list(viewvalues(ircfg.blocks)): if not block.assignblks: continue assignblk = block[0] todo = {} modified = False - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if not src.is_op('Phi'): todo[dst] = src continue @@ -1459,7 +1461,7 @@ def update_phi_with_deleted_edges(ircfg, edges_to_del): assignblks = list(block) assignblk = assignblks[0] out = {} - for dst, phi_sources in assignblk.iteritems(): + for dst, phi_sources in viewitems(assignblk): if not phi_sources.is_op('Phi'): out = assignblk break @@ -1484,7 +1486,7 @@ def update_phi_with_deleted_edges(ircfg, edges_to_del): new_irblock = IRBlock(loc_dst, assignblks) blocks[block.loc_key] = new_irblock - for loc_key, block in blocks.iteritems(): + for loc_key, block in viewitems(blocks): ircfg.blocks[loc_key] = block return modified @@ -1543,13 +1545,13 @@ class DiGraphLivenessSSA(DiGraphLivenessIRA): super(DiGraphLivenessSSA, self).__init__(ircfg) self.loc_key_to_phi_parents = {} - for irblock in self.blocks.values(): + for irblock in viewvalues(self.blocks): if not irblock_has_phi(irblock): continue out = {} - for sources in irblock[0].itervalues(): + for sources in viewvalues(irblock[0]): var_to_parents = get_phi_sources_parent_block(self, irblock.loc_key, sources.args) - for var, var_parents in var_to_parents.iteritems(): + for var, var_parents in viewitems(var_to_parents): out.setdefault(var, set()).update(var_parents) self.loc_key_to_phi_parents[irblock.loc_key] = out diff --git a/miasm2/analysis/debugging.py b/miasm2/analysis/debugging.py index 6b88f00a..824b62ce 100644 --- a/miasm2/analysis/debugging.py +++ b/miasm2/analysis/debugging.py @@ -1,11 +1,16 @@ +from __future__ import print_function +from builtins import map +from builtins import range import cmd +from future.utils import viewitems + from miasm2.core.utils import hexdump from miasm2.core.interval import interval import miasm2.jitter.csts as csts from miasm2.jitter.jitload import ExceptionHandle -class DebugBreakpoint: +class DebugBreakpoint(object): "Debug Breakpoint parent class" pass @@ -46,17 +51,19 @@ class DebugBreakpointMemory(DebugBreakpoint): def __str__(self): bp_type = "" - for k, v in self.type2str.items(): + for k, v in viewitems(self.type2str): if k & self.access_type != 0: bp_type += v - return "Memory BP @0x%08x, Size 0x%08x, Type %s" % (self.addr, - self.size, - bp_type) + return "Memory BP @0x%08x, Size 0x%08x, Type %s" % ( + self.addr, + self.size, + bp_type + ) @classmethod def get_access_type(cls, read=False, write=False): value = 0 - for k, v in cls.type2str.items(): + for k, v in viewitems(cls.type2str): if v == "R" and read is True: value += k if v == "W" and write is True: @@ -146,10 +153,10 @@ class Debugguer(object): return DebugBreakpointTerminate(res) if isinstance(res, DebugBreakpointSoft): - print "Breakpoint reached @0x%08x" % res.addr + print("Breakpoint reached @0x%08x" % res.addr) elif isinstance(res, ExceptionHandle): if res == ExceptionHandle.memoryBreakpoint(): - print "Memory breakpoint reached!" + print("Memory breakpoint reached!") # Remove flag except_flag = self.myjit.vm.get_exception() @@ -196,7 +203,7 @@ class Debugguer(object): def on_step(self): for addr, size in self.mem_watched: - print "@0x%08x:" % addr + print("@0x%08x:" % addr) self.get_mem(addr, size) def get_reg_value(self, reg_name): @@ -238,20 +245,20 @@ class DebugCmd(cmd.Cmd, object): def print_breakpoints(self): bp_list = self.dbg.bp_list if len(bp_list) == 0: - print "No breakpoints." + print("No breakpoints.") else: for i, b in enumerate(bp_list): - print "%d\t0x%08x" % (i, b.addr) + print("%d\t0x%08x" % (i, b.addr)) def print_watchmems(self): watch_list = self.dbg.mem_watched if len(watch_list) == 0: - print "No memory watchpoints." + print("No memory watchpoints.") else: - print "Num\tAddress \tSize" + print("Num\tAddress \tSize") for i, w in enumerate(watch_list): addr, size = w - print "%d\t0x%08x\t0x%08x" % (i, addr, size) + print("%d\t0x%08x\t0x%08x" % (i, addr, size)) def print_registers(self): regs = self.dbg.get_gpreg_all() @@ -259,17 +266,21 @@ class DebugCmd(cmd.Cmd, object): # Display settings title1 = "Registers" title2 = "Values" - max_name_len = max(map(len, regs.keys() + [title1])) + max_name_len = max(map(len, list(regs) + [title1])) # Print value table s = "%s%s | %s" % ( title1, " " * (max_name_len - len(title1)), title2) - print s - print "-" * len(s) - for name, value in sorted(regs.items(), key=lambda x: x[0]): - print "%s%s | %s" % (name, - " " * (max_name_len - len(name)), - hex(value).replace("L", "")) + print(s) + print("-" * len(s)) + for name, value in sorted(viewitems(regs), key=lambda x: x[0]): + print( + "%s%s | %s" % ( + name, + " " * (max_name_len - len(name)), + hex(value).replace("L", "") + ) + ) def add_breakpoints(self, bp_addr): for addr in bp_addr: @@ -281,35 +292,41 @@ class DebugCmd(cmd.Cmd, object): good = False break if good is False: - print "Breakpoint 0x%08x already set (%d)" % (addr, i) + print("Breakpoint 0x%08x already set (%d)" % (addr, i)) else: l = len(self.dbg.bp_list) self.dbg.add_breakpoint(addr) - print "Breakpoint 0x%08x successfully added ! (%d)" % (addr, l) + print("Breakpoint 0x%08x successfully added ! (%d)" % (addr, l)) - display_mode = {"mn": None, - "regs": None, - "newbloc": None} + display_mode = { + "mn": None, + "regs": None, + "newbloc": None + } def update_display_mode(self): - self.display_mode = {"mn": self.dbg.myjit.jit.log_mn, - "regs": self.dbg.myjit.jit.log_regs, - "newbloc": self.dbg.myjit.jit.log_newbloc} + self.display_mode = { + "mn": self.dbg.myjit.jit.log_mn, + "regs": self.dbg.myjit.jit.log_regs, + "newbloc": self.dbg.myjit.jit.log_newbloc + } # Command line methods def print_warning(self, s): - print self.color_r + s + self.color_e + print(self.color_r + s + self.color_e) def onecmd(self, line): - cmd_translate = {"h": "help", - "q": "exit", - "e": "exit", - "!": "exec", - "r": "run", - "i": "info", - "b": "breakpoint", - "s": "step", - "d": "dump"} + cmd_translate = { + "h": "help", + "q": "exit", + "e": "exit", + "!": "exec", + "r": "run", + "i": "info", + "b": "breakpoint", + "s": "step", + "d": "dump" + } if len(line) >= 2 and \ line[1] == " " and \ @@ -342,12 +359,12 @@ class DebugCmd(cmd.Cmd, object): self.update_display_mode() def help_display(self): - print "Enable/Disable tracing." - print "Usage: display <mode1> <mode2> ... on|off" - print "Available modes are:" + print("Enable/Disable tracing.") + print("Usage: display <mode1> <mode2> ... on|off") + print("Available modes are:") for k in self.display_mode: - print "\t%s" % k - print "Use 'info display' to get current values" + print("\t%s" % k) + print("Use 'info display' to get current values") def do_watchmem(self, arg): if arg == "": @@ -365,21 +382,23 @@ class DebugCmd(cmd.Cmd, object): self.dbg.watch_mem(addr, size) def help_watchmem(self): - print "Add a memory watcher." - print "Usage: watchmem <addr> [size]" - print "Use 'info watchmem' to get current memory watchers" + print("Add a memory watcher.") + print("Usage: watchmem <addr> [size]") + print("Use 'info watchmem' to get current memory watchers") def do_info(self, arg): - av_info = ["registers", - "display", - "breakpoints", - "watchmem"] + av_info = [ + "registers", + "display", + "breakpoints", + "watchmem" + ] if arg == "": - print "'info' must be followed by the name of an info command." - print "List of info subcommands:" + print("'info' must be followed by the name of an info command.") + print("List of info subcommands:") for k in av_info: - print "\t%s" % k + print("\t%s" % k) if arg.startswith("b"): # Breakpoint @@ -388,8 +407,8 @@ class DebugCmd(cmd.Cmd, object): if arg.startswith("d"): # Display self.update_display_mode() - for k, v in self.display_mode.items(): - print "%s\t\t%s" % (k, v) + for k, v in viewitems(self.display_mode): + print("%s\t\t%s" % (k, v)) if arg.startswith("w"): # Watchmem @@ -400,9 +419,9 @@ class DebugCmd(cmd.Cmd, object): self.print_registers() def help_info(self): - print "Generic command for showing things about the program being" - print "debugged. Use 'info' without arguments to get the list of" - print "available subcommands." + print("Generic command for showing things about the program being") + print("debugged. Use 'info' without arguments to get the list of") + print("available subcommands.") def do_breakpoint(self, arg): if arg == "": @@ -412,23 +431,23 @@ class DebugCmd(cmd.Cmd, object): self.add_breakpoints(addrs) def help_breakpoint(self): - print "Add breakpoints to argument addresses." - print "Example:" - print "\tbreakpoint 0x11223344" - print "\tbreakpoint 1122 0xabcd" + print("Add breakpoints to argument addresses.") + print("Example:") + print("\tbreakpoint 0x11223344") + print("\tbreakpoint 1122 0xabcd") def do_step(self, arg): if arg == "": nb = 1 else: nb = int(arg) - for _ in xrange(nb): + for _ in range(nb): self.dbg.step() def help_step(self): - print "Step program until it reaches a different source line." - print "Argument N means do this N times (or till program stops" - print "for another reason)." + print("Step program until it reaches a different source line.") + print("Argument N means do this N times (or till program stops") + print("for another reason).") def do_dump(self, arg): if arg == "": @@ -444,36 +463,36 @@ class DebugCmd(cmd.Cmd, object): self.dbg.get_mem(addr, size) def help_dump(self): - print "Dump <addr> [size]. Dump size bytes at addr." + print("Dump <addr> [size]. Dump size bytes at addr.") def do_run(self, _): self.dbg.run() def help_run(self): - print "Launch or continue the current program" + print("Launch or continue the current program") def do_exit(self, _): return True def do_exec(self, line): try: - print eval(line) - except Exception, error: - print "*** Error: %s" % error + print(eval(line)) + except Exception as error: + print("*** Error: %s" % error) def help_exec(self): - print "Exec a python command." - print "You can also use '!' shortcut." + print("Exec a python command.") + print("You can also use '!' shortcut.") def help_exit(self): - print "Exit the interpreter." - print "You can also use the Ctrl-D shortcut." + print("Exit the interpreter.") + print("You can also use the Ctrl-D shortcut.") def help_help(self): - print "Print help" + print("Print help") def postloop(self): - print '\nGoodbye !' + print('\nGoodbye !') super(DebugCmd, self).postloop() do_EOF = do_exit diff --git a/miasm2/analysis/depgraph.py b/miasm2/analysis/depgraph.py index 4e5f0433..4bfae67f 100644 --- a/miasm2/analysis/depgraph.py +++ b/miasm2/analysis/depgraph.py @@ -1,5 +1,9 @@ """Provide dependency graph""" +from functools import total_ordering + +from future.utils import viewitems + from miasm2.expression.expression import ExprInt, ExprLoc, ExprAssign from miasm2.core.graph import DiGraph from miasm2.core.locationdb import LocationDB @@ -14,7 +18,7 @@ try: except ImportError: pass - +@total_ordering class DependencyNode(object): """Node elements of a DependencyGraph @@ -50,16 +54,17 @@ class DependencyNode(object): self.element == depnode.element and self.line_nb == depnode.line_nb) - def __ne__(self, other): - return not self.__eq__(other) + def __ne__(self, depnode): + # required Python 2.7.14 + return not self == depnode - def __cmp__(self, node): + def __lt__(self, node): """Compares @self with @node.""" if not isinstance(node, self.__class__): - return cmp(self.__class__, node.__class__) + return NotImplemented - return cmp((self.loc_key, self.element, self.line_nb), - (node.loc_key, node.element, node.line_nb)) + return ((self.loc_key, self.element, self.line_nb) < + (node.loc_key, node.element, node.line_nb)) def __str__(self): """Returns a string representation of DependencyNode""" @@ -96,7 +101,7 @@ class DependencyState(object): def __init__(self, loc_key, pending, line_nb=None): self.loc_key = loc_key self.history = [loc_key] - self.pending = {k: set(v) for k, v in pending.iteritems()} + self.pending = {k: set(v) for k, v in viewitems(pending)} self.line_nb = line_nb self.links = set() @@ -104,9 +109,11 @@ class DependencyState(object): self._graph = None def __repr__(self): - return "<State: %r (%r) (%r)>" % (self.loc_key, - self.pending, - self.links) + return "<State: %r (%r) (%r)>" % ( + self.loc_key, + self.pending, + self.links + ) def extend(self, loc_key): """Return a copy of itself, with itself in history @@ -129,7 +136,7 @@ class DependencyState(object): graph.add_node(node_a) else: graph.add_edge(node_a, node_b) - for parent, sons in self.pending.iteritems(): + for parent, sons in viewitems(self.pending): for son in sons: graph.add_edge(parent, son) return graph @@ -148,7 +155,7 @@ class DependencyState(object): def add_pendings(self, future_pending): """Add @future_pending to the state""" - for node, depnodes in future_pending.iteritems(): + for node, depnodes in viewitems(future_pending): if node not in self.pending: self.pending[node] = depnodes else: @@ -263,7 +270,7 @@ class DependencyResult(DependencyState): line2elements.setdefault(depnode.line_nb, set()).add(depnode.element) - for line_nb, elements in sorted(line2elements.iteritems()): + for line_nb, elements in sorted(viewitems(line2elements)): if max_line is not None and line_nb >= max_line: break assignmnts = {} @@ -385,8 +392,10 @@ class DependencyResultImplicit(DependencyResult): self._solver = solver # Return only inputs values (others could be wrongs) - return {element: symb_exec.eval_expr(element) - for element in self.inputs} + return { + element: symb_exec.eval_expr(element) + for element in self.inputs + } @property def is_satisfiable(self): @@ -562,7 +571,7 @@ class DependencyGraph(object): """Track pending expression in an assignblock""" future_pending = {} node_resolved = set() - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): # Only track pending if dst not in state.pending: continue diff --git a/miasm2/analysis/disasm_cb.py b/miasm2/analysis/disasm_cb.py index d3278cb4..36e120b6 100644 --- a/miasm2/analysis/disasm_cb.py +++ b/miasm2/analysis/disasm_cb.py @@ -1,5 +1,9 @@ #-*- coding:utf-8 -*- +from __future__ import print_function + +from future.utils import viewvalues + from miasm2.expression.expression import ExprInt, ExprId, ExprMem, match_expr from miasm2.expression.simplifications import expr_simp from miasm2.core.asmblock import AsmConstraintNext, AsmConstraintTo @@ -27,13 +31,12 @@ def arm_guess_subcall( sp = LocationDB() ir_arch = ira(sp) ircfg = ira.new_ircfg() - print '###' - print cur_bloc + print('###') + print(cur_bloc) ir_arch.add_asmblock_to_ircfg(cur_bloc, ircfg) - ir_blocks = ircfg.blocks.values() to_add = set() - for irblock in ir_blocks: + for irblock in viewvalues(ircfg.blocks): pc_val = None lr_val = None for exprs in irblock: @@ -72,8 +75,7 @@ def arm_guess_jump_table( ircfg = ira.new_ircfg() ir_arch.add_asmblock_to_ircfg(cur_bloc, ircfg) - ir_blocks = ircfg.blocks.values() - for irblock in ir_blocks: + for irblock in viewvalues(ircfg.blocks): pc_val = None for exprs in irblock: for e in exprs: @@ -84,18 +86,18 @@ def arm_guess_jump_table( if not isinstance(pc_val, ExprMem): continue assert(pc_val.size == 32) - print pc_val + print(pc_val) ad = pc_val.arg ad = expr_simp(ad) - print ad + print(ad) res = match_expr(ad, jra + jrb, set([jra, jrb])) if res is False: raise NotImplementedError('not fully functional') - print res + print(res) if not isinstance(res[jrb], ExprInt): raise NotImplementedError('not fully functional') base_ad = int(res[jrb]) - print base_ad + print(base_ad) addrs = set() i = -1 max_table_entry = 10000 @@ -109,7 +111,7 @@ def arm_guess_jump_table( if abs(ad - base_ad) > max_diff_addr: break addrs.add(ad) - print [hex(x) for x in addrs] + print([hex(x) for x in addrs]) for ad in addrs: offsets_to_dis.add(ad) diff --git a/miasm2/analysis/dse.py b/miasm2/analysis/dse.py index 5eb924d7..fee85984 100644 --- a/miasm2/analysis/dse.py +++ b/miasm2/analysis/dse.py @@ -47,7 +47,7 @@ Here are a few remainings TODO: the solver for reducing the possible values thanks to its accumulated constraints. """ - +from builtins import range from collections import namedtuple try: @@ -55,6 +55,9 @@ try: except ImportError: z3 = None +from future.utils import viewitems + +from miasm2.core.utils import encode_hex, force_bytes from miasm2.expression.expression import ExprMem, ExprInt, ExprCompose, \ ExprAssign, ExprId, ExprLoc, LocKey from miasm2.core.bin_stream import bin_stream_vm @@ -111,7 +114,7 @@ class ESETrackModif(EmulatedSymbExec): # Split access in atomic accesses out = [] - for addr in xrange(dst_addr, dst_addr + (expr_mem.size / 8)): + for addr in range(dst_addr, dst_addr + expr_mem.size // 8): if addr in self.dse_memory_range: # Symbolize memory access out.append(self.dse_memory_to_expr(addr)) @@ -249,14 +252,18 @@ class DSEEngine(object): Known functions will be looked by {name}_symb in the @namespace """ + namespace = dict( + (force_bytes(name), func) for name, func in viewitems(namespace) + ) # lambda cannot contain statement def default_func(dse): - fname = "%s_symb" % libimp.fad2cname[dse.jitter.pc] + fname = b"%s_symb" % libimp.fad2cname[dse.jitter.pc] raise RuntimeError("Symbolic stub '%s' not found" % fname) - for addr, fname in libimp.fad2cname.iteritems(): - fname = "%s_symb" % fname + for addr, fname in viewitems(libimp.fad2cname): + fname = force_bytes(fname) + fname = b"%s_symb" % fname func = namespace.get(fname, None) if func is not None: self.add_handler(addr, func) @@ -292,9 +299,11 @@ class DSEEngine(object): if value != symb_value: errors.append(DriftInfo(symbol, symb_value, value)) elif symbol.is_mem() and symbol.ptr.is_int(): - value_chr = self.jitter.vm.get_mem(int(symbol.ptr), - symbol.size / 8) - exp_value = int(value_chr[::-1].encode("hex"), 16) + value_chr = self.jitter.vm.get_mem( + int(symbol.ptr), + symbol.size // 8 + ) + exp_value = int(encode_hex(value_chr[::-1]), 16) if exp_value != symb_value: errors.append(DriftInfo(symbol, symb_value, exp_value)) @@ -410,14 +419,16 @@ class DSEEngine(object): if memory: self.jitter.vm.reset_memory_page_pool() self.jitter.vm.reset_code_bloc_pool() - for addr, metadata in snapshot["mem"].iteritems(): - self.jitter.vm.add_memory_page(addr, - metadata["access"], - metadata["data"]) + for addr, metadata in viewitems(snapshot["mem"]): + self.jitter.vm.add_memory_page( + addr, + metadata["access"], + metadata["data"] + ) # Restore registers self.jitter.pc = snapshot["regs"][self.ir_arch.pc.name] - for reg, value in snapshot["regs"].iteritems(): + for reg, value in viewitems(snapshot["regs"]): setattr(self.jitter.cpu, reg, value) # Reset intern elements @@ -426,16 +437,16 @@ class DSEEngine(object): self.jitter.bs._atomic_mode = False # Reset symb exec - for key, _ in self.symb.symbols.items(): + for key, _ in list(viewitems(self.symb.symbols)): del self.symb.symbols[key] - for expr, value in snapshot["symb"].items(): + for expr, value in viewitems(snapshot["symb"]): self.symb.symbols[expr] = value def update_state(self, assignblk): """From this point, assume @assignblk in the symbolic execution @assignblk: AssignBlock/{dst -> src} """ - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): self.symb.apply_change(dst, src) def _update_state_from_concrete_symb(self, symbexec, cpu=True, mem=False): @@ -534,8 +545,10 @@ class DSEPathConstraint(DSEEngine): def take_snapshot(self, *args, **kwargs): snap = super(DSEPathConstraint, self).take_snapshot(*args, **kwargs) - snap["new_solutions"] = {dst: src.copy - for dst, src in self.new_solutions.iteritems()} + snap["new_solutions"] = { + dst: src.copy + for dst, src in viewitems(self.new_solutions) + } snap["cur_constraints"] = self.cur_solver.assertions() if self._produce_solution_strategy == self.PRODUCE_SOLUTION_PATH_COV: snap["_history"] = list(self._history) @@ -650,9 +663,11 @@ class DSEPathConstraint(DSEEngine): # if addr (- [a, b], then @size[addr] reachables # values are in @8[a, b + size[ for start, stop in addr_range: - stop += (expr.size / 8) - 1 - full_range = ModularIntervals(symb_pc.size, - [(start, stop)]) + stop += expr.size // 8 - 1 + full_range = ModularIntervals( + symb_pc.size, + [(start, stop)] + ) memory_to_add.update(full_range) path_constraint.add(eaff) @@ -662,7 +677,7 @@ class DSEPathConstraint(DSEEngine): # Inject memory for start, stop in memory_to_add: - for address in xrange(start, stop + 1): + for address in range(start, stop + 1): expr_mem = ExprMem(ExprInt(address, self.ir_arch.pc.size), 8) diff --git a/miasm2/analysis/expression_range.py b/miasm2/analysis/expression_range.py index f09a18d0..8f498549 100644 --- a/miasm2/analysis/expression_range.py +++ b/miasm2/analysis/expression_range.py @@ -1,5 +1,8 @@ """Naive range analysis for expression""" +from future.builtins import zip +from functools import reduce + from miasm2.analysis.modularintervals import ModularIntervals _op_range_handler = { @@ -44,9 +47,11 @@ def expr_range(expr): # Otherwise, overapproximate (ie. full range interval) if expr.op in _op_range_handler: sub_ranges = [expr_range(arg) for arg in expr.args] - return reduce(_op_range_handler[expr.op], - (sub_range for sub_range in sub_ranges[1:]), - sub_ranges[0]) + return reduce( + _op_range_handler[expr.op], + (sub_range for sub_range in sub_ranges[1:]), + sub_ranges[0] + ) elif expr.op == "-": assert len(expr.args) == 1 return - expr_range(expr.args[0]) diff --git a/miasm2/analysis/gdbserver.py b/miasm2/analysis/gdbserver.py index 6c630f88..61ee8955 100644 --- a/miasm2/analysis/gdbserver.py +++ b/miasm2/analysis/gdbserver.py @@ -1,10 +1,15 @@ #-*- coding:utf-8 -*- +from __future__ import print_function +from future.builtins import map, range + +from miasm2.core.utils import decode_hex, encode_hex, int_to_byte + import socket import struct import time import logging -from StringIO import StringIO +from io import BytesIO import miasm2.analysis.debugging as debugging from miasm2.jitter.jitload import ExceptionHandle @@ -15,7 +20,7 @@ class GdbServer(object): general_registers_order = [] general_registers_size = {} # RegName : Size in octet - status = "S05" + status = b"S05" def __init__(self, dbg, port=4455): server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) @@ -28,242 +33,243 @@ class GdbServer(object): # Communication methods def compute_checksum(self, data): - return chr(sum(map(ord, data)) % 256).encode("hex") + return encode_hex(int_to_byte(sum(map(ord, data)) % 256)) def get_messages(self): - all_data = "" - data = self.sock.recv(4096) - all_data += data - while (len(data) == 4096 or data == ""): - if data == "": - # Avoid consuming CPU - time.sleep(0.001) - continue + all_data = b"" + while True: data = self.sock.recv(4096) + if not data: + break all_data += data logging.debug("<- %r", all_data) self.recv_queue += self.parse_messages(all_data) def parse_messages(self, data): - buf = StringIO(data) - + buf = BytesIO(data) msgs = [] while (buf.tell() < buf.len): token = buf.read(1) - if token == "+": + if token == b"+": continue - if token == "-": + if token == b"-": raise NotImplementedError("Resend packet") - if token == "$": - packet_data = "" + if token == b"$": + packet_data = b"" c = buf.read(1) - while c != "#": + while c != b"#": packet_data += c c = buf.read(1) checksum = buf.read(2) if checksum != self.compute_checksum(packet_data): raise ValueError("Incorrect checksum") - msgs.append(packet_data) return msgs def send_string(self, s): - self.send_queue.append("O" + s.encode("hex")) + self.send_queue.append(b"O" + encode_hex(s)) def process_messages(self): while self.recv_queue: msg = self.recv_queue.pop(0) - buf = StringIO(msg) + buf = BytesIO(msg) msg_type = buf.read(1) - self.send_queue.append("+") + self.send_queue.append(b"+") - if msg_type == "q": - if msg.startswith("qSupported"): - self.send_queue.append("PacketSize=3fff") - elif msg.startswith("qC"): + if msg_type == b"q": + if msg.startswith(b"qSupported"): + self.send_queue.append(b"PacketSize=3fff") + elif msg.startswith(b"qC"): # Current thread - self.send_queue.append("") - elif msg.startswith("qAttached"): + self.send_queue.append(b"") + elif msg.startswith(b"qAttached"): # Not supported - self.send_queue.append("") - elif msg.startswith("qTStatus"): + self.send_queue.append(b"") + elif msg.startswith(b"qTStatus"): # Not supported - self.send_queue.append("") - elif msg.startswith("qfThreadInfo"): + self.send_queue.append(b"") + elif msg.startswith(b"qfThreadInfo"): # Not supported - self.send_queue.append("") + self.send_queue.append(b"") else: raise NotImplementedError() - elif msg_type == "H": + elif msg_type == b"H": # Set current thread - self.send_queue.append("OK") + self.send_queue.append(b"OK") - elif msg_type == "?": + elif msg_type == b"?": # Report why the target halted self.send_queue.append(self.status) # TRAP signal - elif msg_type == "g": + elif msg_type == b"g": # Report all general register values self.send_queue.append(self.report_general_register_values()) - elif msg_type == "p": + elif msg_type == b"p": # Read a specific register reg_num = int(buf.read(), 16) self.send_queue.append(self.read_register(reg_num)) - elif msg_type == "P": + elif msg_type == b"P": # Set a specific register - reg_num, value = buf.read().split("=") + reg_num, value = buf.read().split(b"=") reg_num = int(reg_num, 16) - value = int(value.decode("hex")[::-1].encode("hex"), 16) + value = int(encode_hex(decode_hex(value)[::-1]), 16) self.set_register(reg_num, value) - self.send_queue.append("OK") + self.send_queue.append(b"OK") - elif msg_type == "m": + elif msg_type == b"m": # Read memory - addr, size = map(lambda x: int(x, 16), buf.read().split(",")) + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) self.send_queue.append(self.read_memory(addr, size)) - elif msg_type == "k": + elif msg_type == b"k": # Kill self.sock.close() self.send_queue = [] self.sock = None - elif msg_type == "!": + elif msg_type == b"!": # Extending debugging will be used - self.send_queue.append("OK") + self.send_queue.append(b"OK") - elif msg_type == "v": - if msg == "vCont?": + elif msg_type == b"v": + if msg == b"vCont?": # Is vCont supported ? - self.send_queue.append("") + self.send_queue.append(b"") - elif msg_type == "s": + elif msg_type == b"s": # Step self.dbg.step() - self.send_queue.append("S05") # TRAP signal + self.send_queue.append(b"S05") # TRAP signal - elif msg_type == "Z": + elif msg_type == b"Z": # Add breakpoint or watchpoint bp_type = buf.read(1) - if bp_type == "0": + if bp_type == b"0": # Exec breakpoint - assert(buf.read(1) == ",") - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) + assert(buf.read(1) == b",") + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) if size != 1: raise NotImplementedError("Bigger size") self.dbg.add_breakpoint(addr) - self.send_queue.append("OK") + self.send_queue.append(b"OK") - elif bp_type == "1": + elif bp_type == b"1": # Hardware BP - assert(buf.read(1) == ",") - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) - - self.dbg.add_memory_breakpoint(addr, size, - read=True, - write=True) - self.send_queue.append("OK") - - elif bp_type in ["2", "3", "4"]: + assert(buf.read(1) == b",") + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) + + self.dbg.add_memory_breakpoint( + addr, + size, + read=True, + write=True + ) + self.send_queue.append(b"OK") + + elif bp_type in [b"2", b"3", b"4"]: # Memory breakpoint - assert(buf.read(1) == ",") - read = bp_type in ["3", "4"] - write = bp_type in ["2", "4"] - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) - - self.dbg.add_memory_breakpoint(addr, size, - read=read, - write=write) - self.send_queue.append("OK") + assert(buf.read(1) == b",") + read = bp_type in [b"3", b"4"] + write = bp_type in [b"2", b"4"] + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) + + self.dbg.add_memory_breakpoint( + addr, + size, + read=read, + write=write + ) + self.send_queue.append(b"OK") else: raise ValueError("Impossible value") - elif msg_type == "z": + elif msg_type == b"z": # Remove breakpoint or watchpoint bp_type = buf.read(1) - if bp_type == "0": + if bp_type == b"0": # Exec breakpoint - assert(buf.read(1) == ",") - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) + assert(buf.read(1) == b",") + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) if size != 1: raise NotImplementedError("Bigger size") dbgsoft = self.dbg.get_breakpoint_by_addr(addr) assert(len(dbgsoft) == 1) self.dbg.remove_breakpoint(dbgsoft[0]) - self.send_queue.append("OK") + self.send_queue.append(b"OK") - elif bp_type == "1": + elif bp_type == b"1": # Hardware BP - assert(buf.read(1) == ",") - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) + assert(buf.read(1) == b",") + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) self.dbg.remove_memory_breakpoint_by_addr_access( - addr, read=True, write=True) - self.send_queue.append("OK") + addr, + read=True, + write=True + ) + self.send_queue.append(b"OK") - elif bp_type in ["2", "3", "4"]: + elif bp_type in [b"2", b"3", b"4"]: # Memory breakpoint - assert(buf.read(1) == ",") - read = bp_type in ["3", "4"] - write = bp_type in ["2", "4"] - addr, size = map( - lambda x: int(x, 16), buf.read().split(",")) + assert(buf.read(1) == b",") + read = bp_type in [b"3", b"4"] + write = bp_type in [b"2", b"4"] + addr, size = (int(x, 16) for x in buf.read().split(b",", 1)) self.dbg.remove_memory_breakpoint_by_addr_access( - addr, read=read, write=write) - self.send_queue.append("OK") + addr, + read=read, + write=write + ) + self.send_queue.append(b"OK") else: raise ValueError("Impossible value") - elif msg_type == "c": + elif msg_type == b"c": # Continue - self.status = "" + self.status = b"" self.send_messages() ret = self.dbg.run() if isinstance(ret, debugging.DebugBreakpointSoft): - self.status = "S05" - self.send_queue.append("S05") # TRAP signal + self.status = b"S05" + self.send_queue.append(b"S05") # TRAP signal elif isinstance(ret, ExceptionHandle): if ret == ExceptionHandle.memoryBreakpoint(): - self.status = "S05" - self.send_queue.append("S05") + self.status = b"S05" + self.send_queue.append(b"S05") else: raise NotImplementedError("Unknown Except") elif isinstance(ret, debugging.DebugBreakpointTerminate): # Connexion should close, but keep it running as a TRAP # The connexion will be close on instance destruction - print ret - self.status = "S05" - self.send_queue.append("S05") + print(ret) + self.status = b"S05" + self.send_queue.append(b"S05") else: raise NotImplementedError() else: raise NotImplementedError( - "Not implemented: message type '%s'" % msg_type) + "Not implemented: message type %r" % msg_type + ) def send_messages(self): for msg in self.send_queue: - if msg == "+": - data = "+" + if msg == b"+": + data = b"+" else: - data = "$%s#%s" % (msg, self.compute_checksum(msg)) + data = b"$%s#%s" % (msg, self.compute_checksum(msg)) logging.debug("-> %r", data) self.sock.send(data) self.send_queue = [] @@ -272,7 +278,7 @@ class GdbServer(object): self.recv_queue = [] self.send_queue = [] - self.send_string("Test\n") + self.send_string(b"Test\n") while (self.sock): self.get_messages() @@ -285,8 +291,8 @@ class GdbServer(object): # Debugguer processing methods def report_general_register_values(self): - s = "" - for i in xrange(len(self.general_registers_order)): + s = b"" + for i in range(len(self.general_registers_order)): s += self.read_register(i) return s @@ -307,7 +313,7 @@ class GdbServer(object): else: raise NotImplementedError("Unknown size") - return struct.pack(pack_token, reg_value).encode("hex") + return encode_hex(struct.pack(pack_token, reg_value)) def set_register(self, reg_num, value): reg_name = self.general_registers_order[reg_num] @@ -319,39 +325,44 @@ class GdbServer(object): def read_memory(self, addr, size): except_flag_vm = self.dbg.myjit.vm.get_exception() try: - return self.dbg.get_mem_raw(addr, size).encode("hex") + return encode_hex(self.dbg.get_mem_raw(addr, size)) except RuntimeError: self.dbg.myjit.vm.set_exception(except_flag_vm) - return "00" * size + return b"00" * size class GdbServer_x86_32(GdbServer): "Extend GdbServer for x86 32bits purposes" - general_registers_order = ["EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", - "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES", - "FS", "GS"] - - general_registers_size = {"EAX": 4, - "ECX": 4, - "EDX": 4, - "EBX": 4, - "ESP": 4, - "EBP": 4, - "ESI": 4, - "EDI": 4, - "EIP": 4, - "EFLAGS": 2, - "CS": 2, - "SS": 2, - "DS": 2, - "ES": 2, - "FS": 2, - "GS": 2} + general_registers_order = [ + "EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", + "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES", + "FS", "GS" + ] + + general_registers_size = { + "EAX": 4, + "ECX": 4, + "EDX": 4, + "EBX": 4, + "ESP": 4, + "EBP": 4, + "ESI": 4, + "EDI": 4, + "EIP": 4, + "EFLAGS": 2, + "CS": 2, + "SS": 2, + "DS": 2, + "ES": 2, + "FS": 2, + "GS": 2 + } register_ignore = [ - "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d"] + "tf", "i_f", "nt", "rf", "vm", "ac", "vif", "vip", "i_d" + ] def read_register_by_name(self, reg_name): sup_func = super(GdbServer_x86_32, self).read_register_by_name @@ -364,7 +375,8 @@ class GdbServer_x86_32(GdbServer): if reg_name == "EFLAGS": val = 0 eflags_args = [ - "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of"] + "cf", 1, "pf", 0, "af", 0, "zf", "nf", "tf", "i_f", "df", "of" + ] eflags_args += ["nt", 0, "rf", "vm", "ac", "vif", "vip", "i_d"] eflags_args += [0] * 10 @@ -387,26 +399,30 @@ class GdbServer_msp430(GdbServer): "Extend GdbServer for msp430 purposes" - general_registers_order = ["PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7", - "R8", "R9", "R10", "R11", "R12", "R13", "R14", - "R15"] - - general_registers_size = {"PC": 2, - "SP": 2, - "SR": 2, - "R3": 2, - "R4": 2, - "R5": 2, - "R6": 2, - "R7": 2, - "R8": 2, - "R9": 2, - "R10": 2, - "R11": 2, - "R12": 2, - "R13": 2, - "R14": 2, - "R15": 2} + general_registers_order = [ + "PC", "SP", "SR", "R3", "R4", "R5", "R6", "R7", + "R8", "R9", "R10", "R11", "R12", "R13", "R14", + "R15" + ] + + general_registers_size = { + "PC": 2, + "SP": 2, + "SR": 2, + "R3": 2, + "R4": 2, + "R5": 2, + "R6": 2, + "R7": 2, + "R8": 2, + "R9": 2, + "R10": 2, + "R11": 2, + "R12": 2, + "R13": 2, + "R14": 2, + "R15": 2 + } def read_register_by_name(self, reg_name): sup_func = super(GdbServer_msp430, self).read_register_by_name diff --git a/miasm2/analysis/modularintervals.py b/miasm2/analysis/modularintervals.py index 83890f19..2195598b 100644 --- a/miasm2/analysis/modularintervals.py +++ b/miasm2/analysis/modularintervals.py @@ -1,4 +1,7 @@ """Intervals with a maximum size, supporting modular arithmetic""" + +from future.builtins import range +from builtins import int as int_types from itertools import product from miasm2.core.interval import interval @@ -59,7 +62,7 @@ class ModularIntervals(object): """Check and promote the second argument from integer to ModularIntervals with one value""" def ret_func(self, target): - if isinstance(target, (int, long)): + if isinstance(target, int_types): target = ModularIntervals(self.size, interval([(target, target)])) if not isinstance(target, ModularIntervals): raise TypeError("Unsupported operation with %s" % target.__class__) @@ -336,7 +339,7 @@ class ModularIntervals(object): shifter &= interval([(0, self.size)]) ret = interval() for shift_range in shifter: - for shift in xrange(shift_range[0], shift_range[1] + 1): + for shift in range(shift_range[0], shift_range[1] + 1): for x_min, x_max in self.intervals: ret += self._range_shift_uniq(x_min, x_max, shift, operation) return self.__class__(self.size, ret) @@ -372,7 +375,7 @@ class ModularIntervals(object): shifter %= self.size ret = interval() for shift_range in shifter: - for shift in xrange(shift_range[0], shift_range[1] + 1): + for shift in range(shift_range[0], shift_range[1] + 1): for x_min, x_max in self.intervals: ret += self._range_rotate_uniq(x_min, x_max, shift, operation) @@ -446,7 +449,7 @@ class ModularIntervals(object): @modulo: integer """ - if not isinstance(modulo, (int, long)): + if not isinstance(modulo, int_types): raise TypeError("Modulo with %s is not supported" % modulo.__class__) return self._integer_modulo(modulo) diff --git a/miasm2/analysis/outofssa.py b/miasm2/analysis/outofssa.py index 6355aeb2..41c665af 100644 --- a/miasm2/analysis/outofssa.py +++ b/miasm2/analysis/outofssa.py @@ -1,3 +1,5 @@ +from future.utils import viewitems, viewvalues + from miasm2.expression.expression import ExprId from miasm2.ir.ir import IRBlock, AssignBlock from miasm2.analysis.ssa import get_phi_sources_parent_block, \ @@ -59,7 +61,7 @@ class UnSSADiGraph(object): """ ircfg = self.ssa.graph - for irblock in ircfg.blocks.values(): + for irblock in list(viewvalues(ircfg.blocks)): if not irblock_has_phi(irblock): continue @@ -82,7 +84,7 @@ class UnSSADiGraph(object): for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src - for parent, parallel_copies in parent_to_parallel_copies.iteritems(): + for parent, parallel_copies in viewitems(parent_to_parallel_copies): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append(AssignBlock(parallel_copies, parent[-1].instr)) @@ -104,10 +106,10 @@ class UnSSADiGraph(object): node """ ircfg = self.ssa.graph - for irblock in ircfg.blocks.itervalues(): + for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue - for dst, sources in irblock[0].iteritems(): + for dst, sources in viewitems(irblock[0]): assert sources.is_op('Phi') new_var = self.create_copy_var(dst) self.phi_new_var[dst] = new_var @@ -130,7 +132,7 @@ class UnSSADiGraph(object): """ Generate trivial coalescing of phi variable and itself """ - for phi_new_var in self.phi_new_var.itervalues(): + for phi_new_var in viewvalues(self.phi_new_var): self.merge_state.setdefault(phi_new_var, set([phi_new_var])) def order_ssa_var_dom(self): @@ -303,7 +305,7 @@ class UnSSADiGraph(object): assignments. @parent: Optional parent location of the phi source for liveness tests """ - for dst, src in parallel_copies.iteritems(): + for dst, src in viewitems(parallel_copies): dst_merge = self.merge_state.setdefault(dst, set([dst])) src_merge = self.merge_state.setdefault(src, set([src])) if not self.merge_sets_interfere(dst_merge, src_merge, parent): @@ -317,7 +319,7 @@ class UnSSADiGraph(object): ircfg = self.ssa.graph # Run coalesce on the post phi parallel copy - for irblock in ircfg.blocks.values(): + for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue parallel_copies = {} @@ -335,7 +337,7 @@ class UnSSADiGraph(object): for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src - for parent, parallel_copies in parent_to_parallel_copies.iteritems(): + for parent, parallel_copies in viewitems(parent_to_parallel_copies): self.aggressive_coalesce_parallel_copy(parallel_copies, parent) def get_best_merge_set_name(self, merge_set): @@ -363,7 +365,7 @@ class UnSSADiGraph(object): # Elect representative for merge sets merge_set_to_name = {} - for merge_set in self.merge_state.itervalues(): + for merge_set in viewvalues(self.merge_state): frozen_merge_set = frozenset(merge_set) merge_sets.add(frozen_merge_set) var_name = self.get_best_merge_set_name(merge_set) @@ -384,10 +386,10 @@ class UnSSADiGraph(object): @ircfg: IRDiGraph instance """ - for irblock in self.ssa.graph.blocks.values(): + for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) out = {} - for dst, src in assignblks[0].iteritems(): + for dst, src in viewitems(assignblks[0]): if src.is_op('Phi'): assert set([dst]) == set(src.args) continue @@ -399,11 +401,11 @@ class UnSSADiGraph(object): """ Remove trivial expressions (a=a) in the current graph """ - for irblock in self.ssa.graph.blocks.values(): + for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) for i, assignblk in enumerate(assignblks): out = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if dst == src: continue out[dst] = src diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index ccffd529..d3e8fce1 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -1,13 +1,20 @@ +from __future__ import print_function +from builtins import range + import os import logging from argparse import ArgumentParser +from future.utils import viewitems, viewvalues + +from miasm2.core.utils import force_bytes from miasm2.analysis.machine import Machine from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE from miasm2.analysis import debugging from miasm2.jitter.jitload import log_func + class Sandbox(object): """ @@ -112,7 +119,7 @@ class Sandbox(object): if self.options.gdbserver: port = self.options.gdbserver - print "Listen on port %d" % port + print("Listen on port %d" % port) gdb = self.machine.gdbserver(dbg, port) self.gdb = gdb gdb.run() @@ -184,7 +191,7 @@ class OS_Win(OS): from miasm2.jitter.loader.pe import vm_load_pe, vm_load_pe_libs,\ preload_pe, libimp_pe, vm_load_pe_and_dependencies from miasm2.os_dep import win_api_x86_32, win_api_x86_32_seh - methods = win_api_x86_32.__dict__ + methods = dict((name.encode(),func) for name, func in viewitems(win_api_x86_32.__dict__)) methods.update(custom_methods) super(OS_Win, self).__init__(methods, *args, **kwargs) @@ -199,33 +206,42 @@ class OS_Win(OS): # Load main pe with open(self.fname, "rb") as fstream: - self.pe = vm_load_pe(self.jitter.vm, fstream.read(), - load_hdr=self.options.load_hdr, - name=self.fname, - **kwargs) + self.pe = vm_load_pe( + self.jitter.vm, + fstream.read(), + load_hdr=self.options.load_hdr, + name=self.fname, + **kwargs + ) self.name2module[fname_basename] = self.pe # Load library if self.options.loadbasedll: # Load libs in memory - self.name2module.update(vm_load_pe_libs(self.jitter.vm, - self.ALL_IMP_DLL, - libs, - self.modules_path, - **kwargs)) + self.name2module.update( + vm_load_pe_libs( + self.jitter.vm, + self.ALL_IMP_DLL, + libs, + self.modules_path, + **kwargs + ) + ) # Patch libs imports - for pe in self.name2module.itervalues(): + for pe in viewvalues(self.name2module): preload_pe(self.jitter.vm, pe, libs) if self.options.dependencies: - vm_load_pe_and_dependencies(self.jitter.vm, - fname_basename, - self.name2module, - libs, - self.modules_path, - **kwargs) + vm_load_pe_and_dependencies( + self.jitter.vm, + fname_basename, + self.name2module, + libs, + self.modules_path, + **kwargs + ) win_api_x86_32.winobjs.current_pe = self.pe @@ -275,8 +291,12 @@ class OS_Linux(OS): self.libs = libimp_elf() with open(self.fname, "rb") as fstream: - self.elf = vm_load_elf(self.jitter.vm, fstream.read(), - name=self.fname, **kwargs) + self.elf = vm_load_elf( + self.jitter.vm, + fstream.read(), + name=self.fname, + **kwargs + ) preload_elf(self.jitter.vm, self.elf, self.libs) self.entry_point = self.elf.Ehdr.entry @@ -325,7 +345,8 @@ class OS_Linux_str(OS): self.options.load_base_addr = int(self.options.load_base_addr, 0) self.jitter.vm.add_memory_page( self.options.load_base_addr, PAGE_READ | PAGE_WRITE, data, - "Initial Str") + "Initial Str" + ) # Library calls handler self.jitter.add_lib_handler(libs, methods) @@ -516,14 +537,17 @@ class Sandbox_Win_x86_64(Sandbox, Arch_x86_64, OS_Win): Sandbox.__init__(self, *args, **kwargs) # reserve stack for local reg - for _ in xrange(0x4): + for _ in range(0x4): self.jitter.push_uint64_t(0) # Pre-stack return address self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): """ @@ -552,14 +576,16 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.ESP -= len(env) ptr = self.jitter.cpu.ESP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.ESP -= len(arg) ptr = self.jitter.cpu.ESP self.jitter.vm.set_mem(ptr, arg) @@ -577,7 +603,10 @@ class Sandbox_Linux_x86_32(Sandbox, Arch_x86_32, OS_Linux): self.jitter.push_uint32_t(self.CALL_FINISH_ADDR) # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): """ @@ -607,14 +636,16 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.RSP -= len(env) ptr = self.jitter.cpu.RSP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.RSP -= len(arg) ptr = self.jitter.cpu.RSP self.jitter.vm.set_mem(ptr, arg) @@ -632,7 +663,10 @@ class Sandbox_Linux_x86_64(Sandbox, Arch_x86_64, OS_Linux): self.jitter.push_uint64_t(self.CALL_FINISH_ADDR) # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): """ @@ -661,14 +695,16 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.SP -= len(env) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.SP -= len(arg) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, arg) @@ -688,7 +724,10 @@ class Sandbox_Linux_arml(Sandbox, Arch_arml, OS_Linux): self.jitter.cpu.LR = self.CALL_FINISH_ADDR # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): if addr is None and self.options.address is None: @@ -714,14 +753,16 @@ class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.SP -= len(env) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.SP -= len(arg) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, arg) @@ -741,7 +782,10 @@ class Sandbox_Linux_armtl(Sandbox, Arch_armtl, OS_Linux): self.jitter.cpu.LR = self.CALL_FINISH_ADDR # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): if addr is None and self.options.address is None: @@ -768,14 +812,16 @@ class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.SP -= len(env) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.SP -= len(arg) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, arg) @@ -792,7 +838,10 @@ class Sandbox_Linux_mips32b(Sandbox, Arch_mips32b, OS_Linux): self.jitter.cpu.RA = 0x1337beef # Set the runtime guard - self.jitter.add_breakpoint(0x1337beef, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + 0x1337beef, + self.__class__.code_sentinelle + ) def run(self, addr=None): if addr is None and self.options.address is None: @@ -850,14 +899,16 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.SP -= len(env) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.SP -= len(arg) ptr = self.jitter.cpu.SP self.jitter.vm.set_mem(ptr, arg) @@ -874,7 +925,10 @@ class Sandbox_Linux_aarch64l(Sandbox, Arch_aarch64l, OS_Linux): self.jitter.cpu.LR = self.CALL_FINISH_ADDR # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): if addr is None and self.options.address is None: @@ -911,14 +965,16 @@ class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux): if self.options.mimic_env: env_ptrs = [] for env in self.envp: - env += "\x00" + env = force_bytes(env) + env += b"\x00" self.jitter.cpu.R1 -= len(env) ptr = self.jitter.cpu.R1 self.jitter.vm.set_mem(ptr, env) env_ptrs.append(ptr) argv_ptrs = [] for arg in self.argv: - arg += "\x00" + arg = force_bytes(arg) + arg += b"\x00" self.jitter.cpu.R1 -= len(arg) ptr = self.jitter.cpu.R1 self.jitter.vm.set_mem(ptr, arg) @@ -947,8 +1003,10 @@ class Sandbox_Linux_ppc32b(Sandbox, Arch_ppc32b, OS_Linux): self.jitter.cpu.LR = self.CALL_FINISH_ADDR # Set the runtime guard - self.jitter.add_breakpoint(self.CALL_FINISH_ADDR, - self.__class__.code_sentinelle) + self.jitter.add_breakpoint( + self.CALL_FINISH_ADDR, + self.__class__.code_sentinelle + ) def run(self, addr=None): """ diff --git a/miasm2/analysis/simplifier.py b/miasm2/analysis/simplifier.py index ca8e74fb..10d5e092 100644 --- a/miasm2/analysis/simplifier.py +++ b/miasm2/analysis/simplifier.py @@ -24,7 +24,7 @@ log.setLevel(logging.WARNING) def fix_point(func): @wraps(func) def ret_func(self, ircfg, head): - log.debug('[%s]: start', func.func_name) + log.debug('[%s]: start', func.__name__) has_been_modified = False modified = True while modified: @@ -32,7 +32,7 @@ def fix_point(func): has_been_modified |= modified log.debug( '[%s]: stop %r', - func.func_name, + func.__name__, has_been_modified ) return has_been_modified diff --git a/miasm2/analysis/ssa.py b/miasm2/analysis/ssa.py index 501cdd5e..54d17dc1 100644 --- a/miasm2/analysis/ssa.py +++ b/miasm2/analysis/ssa.py @@ -1,4 +1,5 @@ from collections import deque +from future.utils import viewitems, viewvalues from miasm2.expression.expression import ExprId, ExprAssign, ExprOp, \ ExprLoc, get_expr_ids @@ -246,7 +247,7 @@ class SSA(object): instructions = [] # insert SSA instructions for _ in assignblk: - instructions.append(ssa_iter.next()) + instructions.append(next(ssa_iter)) # replace instructions of assignblock in IRBlock new_irs.append(AssignBlock(instructions, assignblk.instr)) return IRBlock(irblock.loc_key, new_irs) @@ -576,7 +577,7 @@ class SSADiGraph(SSA): # if successor is in block's dominance frontier if successor in self._phinodes: # walk over all variables on LHS - for dst, src in self._phinodes[successor].iteritems(): + for dst, src in list(viewitems(self._phinodes[successor])): # transform variable on RHS in non-SSA form expr = self.reverse_variable(dst) # transform expr into it's SSA form using current stack @@ -618,7 +619,7 @@ class SSADiGraph(SSA): """ var_to_insert = set() for loc_key in self._phinodes: - for dst, sources in self._phinodes[loc_key].iteritems(): + for dst, sources in viewitems(self._phinodes[loc_key]): for src in sources.args: if src in self.ssa_variable_to_expr: continue @@ -641,14 +642,14 @@ class SSADiGraph(SSA): # Updt structure for loc_key in self._phinodes: - for dst, sources in self._phinodes[loc_key].items(): + for dst, sources in viewitems(self._phinodes[loc_key]): self._phinodes[loc_key][dst] = sources.replace_expr(var_to_newname) - for var, (loc_key, index) in self.ssa_to_location.items(): + for var, (loc_key, index) in list(viewitems(self.ssa_to_location)): if loc_key == head: self.ssa_to_location[var] = loc_key, index + 1 - for newname, var in newname_to_var.iteritems(): + for newname, var in viewitems(newname_to_var): self.ssa_to_location[newname] = head, 0 self.ssa_variable_to_expr[newname] = var self.expressions[newname] = var @@ -661,7 +662,7 @@ def irblock_has_phi(irblock): """ if not irblock.assignblks: return False - for src in irblock[0].itervalues(): + for src in viewvalues(irblock[0]): return src.is_op('Phi') return False @@ -765,7 +766,7 @@ class UnSSADiGraph(object): """ ircfg = self.ssa.graph - for irblock in ircfg.blocks.values(): + for irblock in list(viewvalues(ircfg.blocks)): if not irblock_has_phi(irblock): continue @@ -788,7 +789,7 @@ class UnSSADiGraph(object): for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src - for parent, parallel_copies in parent_to_parallel_copies.iteritems(): + for parent, parallel_copies in viewitems(parent_to_parallel_copies): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append(AssignBlock(parallel_copies, parent[-1].instr)) @@ -810,10 +811,10 @@ class UnSSADiGraph(object): node """ ircfg = self.ssa.graph - for irblock in ircfg.blocks.itervalues(): + for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue - for dst, sources in irblock[0].iteritems(): + for dst, sources in viewitems(irblock[0]): assert sources.is_op('Phi') new_var = self.create_copy_var(dst) self.phi_new_var[dst] = new_var @@ -836,7 +837,7 @@ class UnSSADiGraph(object): """ Generate trivial coalescing of phi variable and itself """ - for phi_new_var in self.phi_new_var.itervalues(): + for phi_new_var in viewvalues(self.phi_new_var): self.merge_state.setdefault(phi_new_var, set([phi_new_var])) def order_ssa_var_dom(self): @@ -1009,7 +1010,7 @@ class UnSSADiGraph(object): assignments. @parent: Optional parent location of the phi source for liveness tests """ - for dst, src in parallel_copies.iteritems(): + for dst, src in viewitems(parallel_copies): dst_merge = self.merge_state.setdefault(dst, set([dst])) src_merge = self.merge_state.setdefault(src, set([src])) if not self.merge_sets_interfere(dst_merge, src_merge, parent): @@ -1023,7 +1024,7 @@ class UnSSADiGraph(object): ircfg = self.ssa.graph # Run coalesce on the post phi parallel copy - for irblock in ircfg.blocks.values(): + for irblock in viewvalues(ircfg.blocks): if not irblock_has_phi(irblock): continue parallel_copies = {} @@ -1041,7 +1042,7 @@ class UnSSADiGraph(object): for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src - for parent, parallel_copies in parent_to_parallel_copies.iteritems(): + for parent, parallel_copies in viewitems(parent_to_parallel_copies): self.aggressive_coalesce_parallel_copy(parallel_copies, parent) def get_best_merge_set_name(self, merge_set): @@ -1069,7 +1070,7 @@ class UnSSADiGraph(object): # Elect representative for merge sets merge_set_to_name = {} - for merge_set in self.merge_state.itervalues(): + for merge_set in viewvalues(self.merge_state): frozen_merge_set = frozenset(merge_set) merge_sets.add(frozen_merge_set) var_name = self.get_best_merge_set_name(merge_set) @@ -1090,10 +1091,10 @@ class UnSSADiGraph(object): @ircfg: IRDiGraph instance """ - for irblock in self.ssa.graph.blocks.values(): + for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) out = {} - for dst, src in assignblks[0].iteritems(): + for dst, src in viewitems(assignblks[0]): if src.is_op('Phi'): assert set([dst]) == set(src.args) continue @@ -1105,11 +1106,11 @@ class UnSSADiGraph(object): """ Remove trivial expressions (a=a) in the current graph """ - for irblock in self.ssa.graph.blocks.values(): + for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) for i, assignblk in enumerate(assignblks): out = {} - for dst, src in assignblk.iteritems(): + for dst, src in viewitems(assignblk): if dst == src: continue out[dst] = src |