about summary refs log tree commit diff stats
path: root/example
diff options
context:
space:
mode:
Diffstat (limited to 'example')
-rw-r--r--example/disasm/full.py4
-rw-r--r--example/expression/solve_condition_stp.py213
-rw-r--r--example/ida/ctype_propagation.py5
-rw-r--r--example/ida/graph_ir.py12
-rw-r--r--example/ida/symbol_exec.py87
-rw-r--r--example/ida/utils.py118
-rwxr-xr-xexample/jitter/msp430.py2
-rw-r--r--example/jitter/sandbox_call.py2
-rw-r--r--example/symbol_exec/depgraph.py2
-rw-r--r--example/symbol_exec/dse_crackme.py2
-rw-r--r--example/symbol_exec/single_instr.py1
11 files changed, 252 insertions, 196 deletions
diff --git a/example/disasm/full.py b/example/disasm/full.py
index ad85f7dc..84c856e1 100644
--- a/example/disasm/full.py
+++ b/example/disasm/full.py
@@ -61,10 +61,10 @@ if args.verbose:
 log.info('Load binary')
 if args.rawbinary:
     shift = args.shiftoffset if args.shiftoffset is not None else 0
-    cont = Container.fallback_container(open(args.filename).read(),
+    cont = Container.fallback_container(open(args.filename, "rb").read(),
                                         None, addr=shift)
 else:
-    with open(args.filename) as fdesc:
+    with open(args.filename, "rb") as fdesc:
         cont = Container.from_stream(fdesc, addr=args.shiftoffset)
 
 default_addr = cont.entry_point
diff --git a/example/expression/solve_condition_stp.py b/example/expression/solve_condition_stp.py
index 438188ab..b3ee6938 100644
--- a/example/expression/solve_condition_stp.py
+++ b/example/expression/solve_condition_stp.py
@@ -1,24 +1,23 @@
 import sys
 import subprocess
-from collections import defaultdict
 from optparse import OptionParser
 from pdb import pm
 
-from miasm2.arch.x86.arch import *
-from miasm2.arch.x86.regs import *
-from miasm2.arch.x86.sem import *
+from miasm2.analysis.machine import Machine
+from miasm2.expression.expression import ExprInt, ExprCond, ExprId, \
+    get_expr_ids, ExprAff
+from miasm2.arch.x86.arch import ParseAst
 from miasm2.core.bin_stream import bin_stream_str
 from miasm2.core import asmblock
-from miasm2.expression.expression import get_rw
-from miasm2.expression.modint import uint32
 from miasm2.ir.symbexec import SymbolicExecutionEngine, get_block
 from miasm2.expression.simplifications import expr_simp
-from miasm2.expression import stp
 from miasm2.core import parse_asm
 from miasm2.arch.x86.disasm import dis_x86_32 as dis_engine
+from miasm2.ir.translators.translator  import Translator
 
 
-mn = mn_x86
+machine = Machine("x86_32")
+
 
 parser = OptionParser(usage="usage: %prog [options] file")
 parser.add_option('-a', "--address", dest="address", metavar="ADDRESS",
@@ -32,99 +31,81 @@ if not args:
 
 def emul_symb(ir_arch, mdis, states_todo, states_done):
     while states_todo:
-        ad, symbols, conds = states_todo.pop()
-        print '*' * 40, "addr", ad, '*' * 40
-        if (ad, symbols, conds) in states_done:
-            print 'skip', ad
+        addr, symbols, conds = states_todo.pop()
+        print '*' * 40, "addr", addr, '*' * 40
+        if (addr, symbols, conds) in states_done:
+            print 'Known state, skipping', addr
             continue
-        states_done.add((ad, symbols, conds))
-        sb = SymbolicExecutionEngine(ir_arch, {})
-        sb.symbols = symbols.copy()
-        if ir_arch.pc in sb.symbols:
-            del(sb.symbols[ir_arch.pc])
-        b = get_block(ir_arch, mdis, ad)
-
-        print 'run block'
-        print b
-        # print blocks[ad]
-        ad = sb.emulbloc(b)
-        print 'final state'
-        sb.dump_id()
-        print 'dataflow'
-        # data_flow_graph_from_expr(sb)
-
-        assert(ad is not None)
-        print "DST", ad
-
-        if isinstance(ad, ExprCond):
+        states_done.add((addr, symbols, conds))
+        symbexec = SymbolicExecutionEngine(ir_arch, {})
+        symbexec.symbols = symbols.copy()
+        if ir_arch.pc in symbexec.symbols:
+            del symbexec.symbols[ir_arch.pc]
+        irblock = get_block(ir_arch, mdis, addr)
+
+        print 'Run block:'
+        print irblock
+        addr = symbexec.emulbloc(irblock)
+        print 'Final state:'
+        symbexec.dump_id()
+
+        assert addr is not None
+
+        if isinstance(addr, ExprCond):
             # Create 2 states, each including complementary conditions
-            p1 = sb.symbols.copy()
-            p2 = sb.symbols.copy()
-            c1 = {ad.cond: ExprInt(0, ad.cond.size)}
-            c2 = {ad.cond: ExprInt(1, ad.cond.size)}
-            print ad.cond
-            p1[ad.cond] = ExprInt(0, ad.cond.size)
-            p2[ad.cond] = ExprInt(1, ad.cond.size)
-            ad1 = expr_simp(sb.eval_expr(ad.replace_expr(c1), {}))
-            ad2 = expr_simp(sb.eval_expr(ad.replace_expr(c2), {}))
-            if not (isinstance(ad1, ExprInt) or (isinstance(ad1, ExprId) and isinstance(ad1.name, asmblock.AsmLabel)) and
-                    isinstance(ad2, ExprInt) or (isinstance(ad2, ExprId) and isinstance(ad2.name, asmblock.AsmLabel))):
-                print str(ad1), str(ad2)
-                raise ValueError("zarb condition")
-            conds1 = list(conds) + c1.items()
-            conds2 = list(conds) + c2.items()
-            if isinstance(ad1, ExprId):
-                ad1 = ad1.name
-            if isinstance(ad2, ExprId):
-                ad2 = ad2.name
-            if isinstance(ad1, ExprInt):
-                ad1 = ad1.arg
-            if isinstance(ad2, ExprInt):
-                ad2 = ad2.arg
-            states_todo.add((ad1, p1, tuple(conds1)))
-            states_todo.add((ad2, p2, tuple(conds2)))
-        elif isinstance(ad, ExprInt):
-            ad = int(ad.arg)
-            states_todo.add((ad, sb.symbols.copy(), tuple(conds)))
-        elif isinstance(ad, ExprId) and isinstance(ad.name, asmblock.AsmLabel):
-            if isinstance(ad, ExprId):
-                ad = ad.name
-            states_todo.add((ad, sb.symbols.copy(), tuple(conds)))
-        elif ad == ret_addr:
-            print 'ret reached'
+            cond_group_a = {addr.cond: ExprInt(0, addr.cond.size)}
+            cond_group_b = {addr.cond: ExprInt(1, addr.cond.size)}
+            addr_a = expr_simp(symbexec.eval_expr(addr.replace_expr(cond_group_a), {}))
+            addr_b = expr_simp(symbexec.eval_expr(addr.replace_expr(cond_group_b), {}))
+            if not (addr_a.is_int() or asmblock.expr_is_label(addr_a) and
+                    addr_b.is_int() or asmblock.expr_is_label(addr_b)):
+                print str(addr_a), str(addr_b)
+                raise ValueError("Unsupported condition")
+            if isinstance(addr_a, ExprInt):
+                addr_a = int(addr_a.arg)
+            if isinstance(addr_b, ExprInt):
+                addr_b = int(addr_b.arg)
+            states_todo.add((addr_a, symbexec.symbols.copy(), tuple(list(conds) + cond_group_a.items())))
+            states_todo.add((addr_b, symbexec.symbols.copy(), tuple(list(conds) + cond_group_b.items())))
+        elif isinstance(addr, ExprInt):
+            addr = int(addr.arg)
+            states_todo.add((addr, symbexec.symbols.copy(), tuple(conds)))
+        elif asmblock.expr_is_label(addr):
+            addr = addr.name
+            states_todo.add((addr, symbexec.symbols.copy(), tuple(conds)))
+        elif addr == ret_addr:
+            print 'Return address reached'
             continue
         else:
-            raise ValueError("zarb eip")
+            raise ValueError("Unsupported destination")
 
 
 if __name__ == '__main__':
 
+    translator_smt2 = Translator.to_language("smt2")
     data = open(args[0]).read()
     bs = bin_stream_str(data)
 
     mdis = dis_engine(bs)
 
-    ad = int(options.address, 16)
+    addr = int(options.address, 16)
 
-    symbols_init = {}
-    for i, r in enumerate(all_regs_ids):
-        symbols_init[r] = all_regs_ids_init[i]
+    symbols_init = dict(machine.mn.regs.regs_init)
 
     # config parser for 32 bit
-    reg_and_id = dict(mn_x86.regs.all_regs_ids_byname)
+    reg_and_id = dict(machine.mn.regs.all_regs_ids_byname)
 
-    def my_ast_int2expr(a):
-        return ExprInt(a, 32)
+    def my_ast_int2expr(name):
+        return ExprInt(name, 32)
 
     # Modifify parser to avoid label creation in PUSH argc
     def my_ast_id2expr(string_parsed):
         if string_parsed in reg_and_id:
             return reg_and_id[string_parsed]
-        else:
-            return ExprId(string_parsed, size=32)
+        return ExprId(string_parsed, size=32)
 
     my_var_parser = ParseAst(my_ast_id2expr, my_ast_int2expr)
-    base_expr.setParseAction(my_var_parser)
+    machine.base_expr.setParseAction(my_var_parser)
 
     argc = ExprId('argc', 32)
     argv = ExprId('argv', 32)
@@ -135,13 +116,13 @@ if __name__ == '__main__':
 
     my_symbols = [argc, argv, ret_addr]
     my_symbols = dict([(x.name, x) for x in my_symbols])
-    my_symbols.update(mn_x86.regs.all_regs_ids_byname)
+    my_symbols.update(machine.mn.regs.all_regs_ids_byname)
 
-    ir_arch = ir_x86_32(mdis.symbol_pool)
+    ir_arch = machine.ir(mdis.symbol_pool)
 
-    sb = SymbolicExecutionEngine(ir_arch, symbols_init)
+    symbexec = SymbolicExecutionEngine(ir_arch, symbols_init)
 
-    blocks, symbol_pool = parse_asm.parse_txt(mn_x86, 32, '''
+    blocks, symbol_pool = parse_asm.parse_txt(machine.mn, 32, '''
     PUSH argv
     PUSH argc
     PUSH ret_addr
@@ -155,15 +136,15 @@ if __name__ == '__main__':
         line.offset, line.l = i, 1
     ir_arch.add_block(b)
     irb = get_block(ir_arch, mdis, 0)
-    sb.emulbloc(irb)
-    sb.dump_mem()
+    symbexec.emulbloc(irb)
+    symbexec.dump_mem()
 
     # reset ir_arch blocks
     ir_arch.blocks = {}
 
     states_todo = set()
     states_done = set()
-    states_todo.add((uint32(ad), sb.symbols, ()))
+    states_todo.add((addr, symbexec.symbols, ()))
 
     # emul blocks, propagate states
     emul_symb(ir_arch, mdis, states_todo, states_done)
@@ -171,57 +152,53 @@ if __name__ == '__main__':
     all_info = []
 
     print '*' * 40, 'conditions to match', '*' * 40
-    for ad, symbols, conds in sorted(states_done):
-        print '*' * 40, ad, '*' * 40
+    for addr, symbols, conds in sorted(states_done):
+        print '*' * 40, addr, '*' * 40
         reqs = []
         for k, v in conds:
             print k, v
             reqs.append((k, v))
-        all_info.append((ad, reqs))
+        all_info.append((addr, reqs))
 
     all_cases = set()
 
-    sb = SymbolicExecutionEngine(ir_arch, symbols_init)
-    for ad, reqs_cond in all_info:
+    symbexec = SymbolicExecutionEngine(ir_arch, symbols_init)
+    for addr, reqs_cond in all_info:
+        out = ['(set-logic QF_ABV)',
+               '(set-info :smt-lib-version 2.0)']
+
+        conditions = []
         all_ids = set()
-        for k, v in reqs_cond:
-            all_ids.update(get_expr_ids(k))
-
-        out = []
-
-        # declare variables
-        for v in all_ids:
-            out.append(str(v) + ":" + "BITVECTOR(%d);" % v.size)
-
-        all_csts = []
-        for k, v in reqs_cond:
-            cst = k.strcst()
-            val = v.arg
-            assert(val in [0, 1])
-            inv = ""
-            if val == 1:
-                inv = "NOT "
-            val = "0" * v.size
-            all_csts.append("(%s%s=0bin%s)" % (inv, cst, val))
-        if not all_csts:
+        for expr, value in reqs_cond:
+
+            all_ids.update(get_expr_ids(expr))
+            expr_test = ExprCond(expr,
+                                 ExprInt(1, value.size),
+                                 ExprInt(0, value.size))
+            cond = translator_smt2.from_expr(ExprAff(expr_test, value))
+            conditions.append(cond)
+
+        for name in all_ids:
+            out.append("(declare-fun %s () (_ BitVec %d))" % (name, name.size))
+        if not out:
             continue
-        rez = " AND ".join(all_csts)
-        out.append("QUERY(NOT (%s));" % rez)
-        end = "\n".join(out)
-        open('out.dot', 'w').write(end)
+
+        out += conditions
+        out.append('(check-sat)')
+        open('out.dot', 'w').write('\n'.join(out))
         try:
             cases = subprocess.check_output(["/home/serpilliere/tools/stp/stp",
-                                             "-p",
+                                             "-p", '--SMTLIB2',
                                              "out.dot"])
         except OSError:
-            print "ERF, cannot find stp"
+            print "Cannot find stp binary!"
             break
         for c in cases.split('\n'):
             if c.startswith('ASSERT'):
-                all_cases.add((ad, c))
+                all_cases.add((addr, c))
 
     print '*' * 40, 'ALL COND', '*' * 40
     all_cases = list(all_cases)
     all_cases.sort(key=lambda x: (x[0], x[1]))
-    for ad, val in all_cases:
-        print 'address', ad, 'is reachable using argc', val
+    for addr, val in all_cases:
+        print 'Address:', addr, 'is reachable using argc', val
diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py
index 76d4fa2d..8c64c6d2 100644
--- a/example/ida/ctype_propagation.py
+++ b/example/ida/ctype_propagation.py
@@ -11,6 +11,7 @@ from miasm2.expression.simplifications import expr_simp
 from miasm2.analysis.depgraph import DependencyGraph
 from miasm2.ir.ir import IRBlock, AssignBlock
 from miasm2.arch.x86.ctype import CTypeAMD64_unk, CTypeX86_unk
+from miasm2.arch.msp430.ctype import CTypeMSP430_unk
 from miasm2.expression.expression import ExprId
 from miasm2.core.objc import CTypesManagerNotPacked, ExprToAccessC, CHandler
 from miasm2.core.ctypesmngr import CAstTypes
@@ -29,7 +30,7 @@ class TypePropagationForm(ida_kernwin.Form):
         self.ira = ira
 
         default_types_info = r"""ExprId("RDX", 64): char *"""
-        archs = ["AMD64_unk", "X86_32_unk"]
+        archs = ["AMD64_unk", "X86_32_unk", "msp430_unk"]
 
         ida_kernwin.Form.__init__(self,
                       r"""BUTTON YES* Launch
@@ -59,6 +60,8 @@ def get_types_mngr(headerFile, arch):
         base_types = CTypeAMD64_unk()
     elif arch =="X86_32_unk":
         base_types = CTypeX86_unk()
+    elif arch =="msp430_unk":
+        base_types = CTypeMSP430_unk()
     else:
         raise NotImplementedError("Unsupported arch")
     types_ast = CAstTypes()
diff --git a/example/ida/graph_ir.py b/example/ida/graph_ir.py
index 9a65617b..8d9dea4f 100644
--- a/example/ida/graph_ir.py
+++ b/example/ida/graph_ir.py
@@ -95,18 +95,9 @@ class GraphMiasmIR(idaapi.GraphViewer):
     def OnClick(self, node_id):
         return True
 
-    def OnCommand(self, cmd_id):
-        if self.cmd_test == cmd_id:
-            print 'TEST!'
-            return
-        print "command:", cmd_id
-
     def Show(self):
         if not idaapi.GraphViewer.Show(self):
             return False
-        self.cmd_test = self.AddCommand("Test", "F2")
-        if self.cmd_test == 0:
-            print "Failed to add popup menu item!"
         return True
 
 
@@ -185,9 +176,6 @@ def build_graph(verbose=False, simplify=False):
 
     g = GraphMiasmIR(ir_arch, title, None)
 
-    g.cmd_a = g.AddCommand("cmd a", "x")
-    g.cmd_b = g.AddCommand("cmd b", "y")
-
     g.Show()
 
 if __name__ == "__main__":
diff --git a/example/ida/symbol_exec.py b/example/ida/symbol_exec.py
index 3d4a64fa..b65b97a1 100644
--- a/example/ida/symbol_exec.py
+++ b/example/ida/symbol_exec.py
@@ -8,6 +8,29 @@ from miasm2.expression.expression import ExprAff
 from utils import expr2colorstr, translatorForm
 
 
+
+class ActionHandler(idaapi.action_handler_t):
+    def activate(self, ctx):
+        view_index = get_focused_view()
+        if view_index is None:
+            return 1
+        self.custom_action(all_views[view_index])
+        return 1
+
+    def update(self, ctx):
+        return idaapi.AST_ENABLE_ALWAYS
+
+
+class ActionHandlerExpand(ActionHandler):
+    def custom_action(self, view):
+        view.expand_expr()
+
+
+class ActionHandlerTranslate(ActionHandler):
+    def custom_action(self, view):
+        view.translate_expr(view.GetLineNo())
+
+
 class symbolicexec_t(idaapi.simplecustviewer_t):
 
     def add(self, key, value):
@@ -48,10 +71,12 @@ class symbolicexec_t(idaapi.simplecustviewer_t):
 
         self.print_lines()
 
-        self.menu_expand = self.AddPopupMenu("Expand [E]")
-        self.menu_translate = self.AddPopupMenu("Translate [T]")
         return True
 
+    def expand_expr(self):
+        self.expand(self.GetLineNo())
+        self.print_lines()
+
     def OnPopupMenu(self, menu_id):
         if menu_id == self.menu_expand:
             self.expand(self.GetLineNo())
@@ -65,15 +90,29 @@ class symbolicexec_t(idaapi.simplecustviewer_t):
         if vkey == 27:
             self.Close()
             return True
-        # E (expand)
-        if vkey == 69:
-            self.OnPopupMenu(self.menu_expand)
-        # T (translate)
-        if vkey == 84:
-            self.OnPopupMenu(self.menu_translate)
+
+        if vkey == ord('E'):
+            self.expand_expr()
+
+        if vkey == ord('T'):
+            self.translate_expr(self.GetLineNo())
+
         return False
 
 
+def get_focused_view():
+    for i, view in enumerate(all_views):
+        if view.IsFocused():
+            return i
+    return None
+
+
+class Hooks(idaapi.UI_Hooks):
+    def finish_populating_tform_popup(self, form, popup):
+        idaapi.attach_action_to_popup(form, popup, 'my:expand', None)
+        idaapi.attach_action_to_popup(form, popup, 'my:translate', None)
+
+
 def symbolic_exec():
     from miasm2.ir.symbexec import SymbolicExecutionEngine
     from miasm2.core.bin_stream_ida import bin_stream_ida
@@ -109,17 +148,45 @@ def symbolic_exec():
 
 
     view = symbolicexec_t()
+    all_views.append(view)
     if not view.Create(modified, machine,
                        "Symbolic Execution - 0x%x to 0x%x" % (start, end)):
         return
 
     view.Show()
 
-if __name__ == "__main__":
+
+# Support ida 6.9 and ida 7
+all_views = []
+
+hooks = Hooks()
+hooks.hook()
+
+action_expand = idaapi.action_desc_t(
+    'my:expand',
+    'Expand',
+    ActionHandlerExpand(),
+    'E',
+    'Expand expression',
+    50)
+
+action_translate = idaapi.action_desc_t(
+    'my:translate',
+    'Translate',
+    ActionHandlerTranslate(),
+    'T',
+    'Translate expression in C/python/z3...',
+    103)
+
+idaapi.register_action(action_expand)
+idaapi.register_action(action_translate)
+
+
+if __name__ == '__main__':
     idaapi.CompileLine('static key_F3() { RunPythonStatement("symbolic_exec()"); }')
     idc.AddHotkey("F3", "key_F3")
 
     print "=" * 50
     print """Available commands:
-        symbolic_exec() - F3: Symbolic execution of current selection
+    symbolic_exec() - F3: Symbolic execution of current selection
     """
diff --git a/example/ida/utils.py b/example/ida/utils.py
index 3f7c3c8a..b147cde2 100644
--- a/example/ida/utils.py
+++ b/example/ida/utils.py
@@ -64,61 +64,81 @@ def guess_machine():
     return machine
 
 
+class TranslatorIDA(Translator):
+    """Translate a Miasm expression to a IDA colored string"""
+
+    # Implemented language
+    __LANG__ = "ida_w_color"
+
+    def __init__(self, regs_ids=None, **kwargs):
+        super(TranslatorIDA, self).__init__(**kwargs)
+        if regs_ids is None:
+            regs_ids = {}
+        self.regs_ids = regs_ids
+
+    def str_protected_child(self, child, parent):
+        return ("(%s)" % self.from_expr(child)) if m2_expr.should_parenthesize_child(child, parent) else self.from_expr(child)
+
+    def from_ExprInt(self, expr):
+        return idaapi.COLSTR(str(expr), idaapi.SCOLOR_NUMBER)
+
+    def from_ExprId(self, expr):
+        out = str(expr)
+        if expr in self.regs_ids:
+            out = idaapi.COLSTR(out, idaapi.SCOLOR_REG)
+        return out
+
+    def from_ExprMem(self, expr):
+        ptr = self.from_expr(expr.arg)
+        size = idaapi.COLSTR('@' + str(expr.size), idaapi.SCOLOR_RPTCMT)
+        out = '%s[%s]' % (size, ptr)
+        return out
+
+    def from_ExprSlice(self, expr):
+        base = self.from_expr(expr.arg)
+        start = idaapi.COLSTR(str(expr.start), idaapi.SCOLOR_RPTCMT)
+        stop = idaapi.COLSTR(str(expr.stop), idaapi.SCOLOR_RPTCMT)
+        out = "(%s)[%s:%s]" % (base, start, stop)
+        return out
+
+    def from_ExprCompose(self, expr):
+        out = "{"
+        out += ", ".join(["%s, %s, %s" % (self.from_expr(subexpr),
+                                          idaapi.COLSTR(str(idx), idaapi.SCOLOR_RPTCMT),
+                                          idaapi.COLSTR(str(idx + subexpr.size), idaapi.SCOLOR_RPTCMT))
+                          for idx, subexpr in expr.iter_args()])
+        out += "}"
+        return out
+
+    def from_ExprCond(self, expr):
+        cond = self.str_protected_child(expr.cond, expr)
+        src1 = self.from_expr(expr.src1)
+        src2 = self.from_expr(expr.src2)
+        out = "%s?(%s,%s)" % (cond, src1, src2)
+        return out
+
+    def from_ExprOp(self, expr):
+        if expr._op == '-':		# Unary minus
+            return '-' + self.str_protected_child(expr._args[0], expr)
+        if expr.is_associative() or expr.is_infix():
+            return (' ' + expr._op + ' ').join([self.str_protected_child(arg, expr)
+                                                for arg in expr._args])
+        return (expr._op + '(' +
+                ', '.join([self.from_expr(arg) for arg in expr._args]) + ')')
+
+    def from_ExprAff(self, expr):
+        return "%s = %s" % tuple(map(expr.from_expr, (expr.dst, expr.src)))
+
+
+
 def expr2colorstr(regs_ids, expr):
     """Colorize an Expr instance for IDA
     @regs_ids: list of ExprId corresponding to available registers
     @expr: Expr instance to colorize
     """
 
-    if isinstance(expr, m2_expr.ExprId):
-        s = str(expr)
-        if expr in regs_ids:
-            s = idaapi.COLSTR(s, idaapi.SCOLOR_REG)
-    elif isinstance(expr, m2_expr.ExprInt):
-        s = str(expr)
-        s = idaapi.COLSTR(s, idaapi.SCOLOR_NUMBER)
-    elif isinstance(expr, m2_expr.ExprMem):
-        s = '%s[%s]' % (idaapi.COLSTR('@' + str(expr.size),
-                                      idaapi.SCOLOR_RPTCMT),
-                         expr2colorstr(regs_ids, expr.arg))
-    elif isinstance(expr, m2_expr.ExprOp):
-        out = []
-        for a in expr.args:
-            s = expr2colorstr(regs_ids, a)
-            if isinstance(a, m2_expr.ExprOp):
-                s = "(%s)" % s
-            out.append(s)
-        if len(out) == 1:
-            s = "%s %s" % (expr.op, str(out[0]))
-        else:
-            s = (" " + expr.op + " ").join(out)
-    elif isinstance(expr, m2_expr.ExprAff):
-        s = "%s = %s" % (
-            expr2colorstr(regs_ids, expr.dst), expr2colorstr(regs_ids, expr.src))
-    elif isinstance(expr, m2_expr.ExprCond):
-        cond = expr2colorstr(regs_ids, expr.cond)
-        src1 = expr2colorstr(regs_ids, expr.src1)
-        src2 = expr2colorstr(regs_ids, expr.src2)
-        s = "(%s?%s:%s)" % (cond, src1, src2)
-    elif isinstance(expr, m2_expr.ExprSlice):
-        s = "(%s)[%s:%s]" % (expr2colorstr(regs_ids, expr.arg),
-                             idaapi.COLSTR(str(expr.start),
-                                           idaapi.SCOLOR_RPTCMT),
-                             idaapi.COLSTR(str(expr.stop),
-                                           idaapi.SCOLOR_RPTCMT))
-    elif isinstance(expr, m2_expr.ExprCompose):
-        s = "{"
-        s += ", ".join(["%s, %s, %s" % (expr2colorstr(regs_ids, subexpr),
-                                        idaapi.COLSTR(str(idx),
-                                                      idaapi.SCOLOR_RPTCMT),
-                                        idaapi.COLSTR(str(idx + subexpr.size),
-                                                      idaapi.SCOLOR_RPTCMT))
-                        for idx, subexpr in expr.iter_args()])
-        s += "}"
-    else:
-        s = str(expr)
-
-    return s
+    translator = TranslatorIDA(regs_ids)
+    return translator.from_expr(expr)
 
 
 class translatorForm(idaapi.Form):
diff --git a/example/jitter/msp430.py b/example/jitter/msp430.py
index b69f91c6..6dd67542 100755
--- a/example/jitter/msp430.py
+++ b/example/jitter/msp430.py
@@ -40,7 +40,7 @@ def jit_msp430_binary(args):
     myjit.jit.log_mn = args.log_mn
     myjit.jit.log_newbloc = args.log_newbloc
 
-    myjit.vm.add_memory_page(0, PAGE_READ | PAGE_WRITE, open(filepath).read())
+    myjit.vm.add_memory_page(0, PAGE_READ | PAGE_WRITE, open(filepath, "rb").read())
     myjit.add_breakpoint(0x1337, lambda _: exit(0))
 
 
diff --git a/example/jitter/sandbox_call.py b/example/jitter/sandbox_call.py
index 49365004..dc64af15 100644
--- a/example/jitter/sandbox_call.py
+++ b/example/jitter/sandbox_call.py
@@ -13,7 +13,7 @@ options = parser.parse_args()
 
 sb = Sandbox_Linux_arml(options.filename, options, globals())
 
-with open(options.filename) as fdesc:
+with open(options.filename, "rb") as fdesc:
     cont = Container.from_stream(fdesc)
     addr_to_call = cont.symbol_pool.getby_name("md5_starts").offset
 
diff --git a/example/symbol_exec/depgraph.py b/example/symbol_exec/depgraph.py
index 4d518cb3..c1d6174d 100644
--- a/example/symbol_exec/depgraph.py
+++ b/example/symbol_exec/depgraph.py
@@ -31,7 +31,7 @@ parser.add_argument("--json",
 args = parser.parse_args()
 
 # Get architecture
-with open(args.filename) as fstream:
+with open(args.filename, "rb") as fstream:
     cont = Container.from_stream(fstream)
 
 arch = args.architecture if args.architecture else cont.arch
diff --git a/example/symbol_exec/dse_crackme.py b/example/symbol_exec/dse_crackme.py
index 9ac4d6d1..303447a4 100644
--- a/example/symbol_exec/dse_crackme.py
+++ b/example/symbol_exec/dse_crackme.py
@@ -31,7 +31,7 @@ def xxx_fopen(jitter):
     global my_FILE_ptr
     ret_addr, args = jitter.func_args_systemv(['path', 'mode'])
     fname = jitter.get_str_ansi(args.path)
-    FILE_to_info[my_FILE_ptr] = FInfo(fname, open(fname))
+    FILE_to_info[my_FILE_ptr] = FInfo(fname, open(fname, "rb"))
     my_FILE_ptr += 1
     return jitter.func_ret_stdcall(ret_addr, my_FILE_ptr - 1)
 
diff --git a/example/symbol_exec/single_instr.py b/example/symbol_exec/single_instr.py
index 263c0252..d65702ba 100644
--- a/example/symbol_exec/single_instr.py
+++ b/example/symbol_exec/single_instr.py
@@ -14,6 +14,7 @@ asm = machine.mn.asm(line)[0]
 # Get back block
 bin_stream = bin_stream_str(asm)
 mdis = machine.dis_engine(bin_stream)
+mdis.lines_wd = 1
 asm_block = mdis.dis_block(START_ADDR)
 
 # Translate ASM -> IR