about summary refs log tree commit diff stats
path: root/example/ida
diff options
context:
space:
mode:
authorFabrice Desclaux <fabrice.desclaux@cea.fr>2017-06-07 18:47:10 +0200
committerFabrice Desclaux <fabrice.desclaux@cea.fr>2017-06-14 09:57:12 +0200
commit1b31144531590ba3b1f1645cc4042b070b51704b (patch)
treef328153e661203fecb6376b541e30517251fb34e /example/ida
parent8e8e6e472bec908eb9cc63cb3a8c042ba5b93279 (diff)
downloadmiasm-1b31144531590ba3b1f1645cc4042b070b51704b.tar.gz
miasm-1b31144531590ba3b1f1645cc4042b070b51704b.zip
Example: c type propagation ida plugin
Diffstat (limited to 'example/ida')
-rw-r--r--example/ida/ctype_propagation.py266
1 files changed, 266 insertions, 0 deletions
diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py
new file mode 100644
index 00000000..e9986522
--- /dev/null
+++ b/example/ida/ctype_propagation.py
@@ -0,0 +1,266 @@
+import os
+import tempfile
+
+from miasm2.core.bin_stream_ida import bin_stream_ida
+from miasm2.expression import expression as m2_expr
+
+from miasm2.expression.simplifications import expr_simp
+from miasm2.analysis.depgraph import DependencyGraph
+from miasm2.ir.ir import IRBlock, AssignBlock
+
+from utils import guess_machine
+
+from miasm2.arch.x86.ctype import CTypeAMD64_unk
+from miasm2.expression.expression import ExprId
+
+from miasm2.core.objc import CTypesManagerNotPacked, CTypeAnalyzer, ExprToAccessC, CHandler
+from miasm2.core.ctypesmngr import CAstTypes
+from miasm2.expression.expression import ExprMem, ExprId, ExprInt, ExprOp, ExprAff
+from miasm2.ir.symbexec_types import SymbExecCType
+
+from miasm2.expression.parser import str_to_expr
+
+
+class TypePropagationForm(Form):
+
+    def __init__(self, ira):
+
+        self.ira = ira
+        self.stk_unalias_force = False
+
+        default_types_info = r"""ExprId("RDX", 64): char *
+"""
+        archs = ["AMD64_unk", "X86_32_unk"]
+
+        Form.__init__(self,
+r"""BUTTON YES* Launch
+BUTTON CANCEL NONE
+Dependency Graph Settings
+<##Header file :{headerFile}>
+<Architecture/complator:{cbReg}>
+<Types informations:{strTypesInfo}>
+<Unalias stack:{rUnaliasStack}>{cMethod}>
+""", {
+    'headerFile': Form.FileInput(swidth=20, open=True),
+    'cbReg': Form.DropdownListControl(
+        items=archs,
+        readonly=False,
+        selval=archs[0]),
+    'strTypesInfo': Form.MultiLineTextControl(text=default_types_info,
+                                              flags=Form.MultiLineTextControl.TXTF_FIXEDFONT),
+    'cMethod': Form.ChkGroupControl(("rUnaliasStack",)),
+    })
+        self.Compile()
+
+    @property
+    def unalias_stack(self):
+        return self.cMethod.value & 1 or self.stk_unalias_force
+
+
+def get_block(ir_arch, mdis, addr):
+    """Get IRBlock at address @addr"""
+    mdis.job_done.clear()
+    lbl = ir_arch.get_label(addr)
+    if not lbl in ir_arch.blocks:
+        block = mdis.dis_bloc(lbl.offset)
+        ir_arch.add_bloc(block)
+    irblock = ir_arch.get_bloc(lbl)
+    if irblock is None:
+        raise LookupError('No block found at that address: %s' % lbl)
+    return irblock
+
+
+def get_types_mngr(headerFile):
+    text = open(headerFile).read()
+    base_types = CTypeAMD64_unk()
+    types_ast = CAstTypes()
+
+    # Add C types definition
+    types_ast.add_c_decl(text)
+
+    types_mngr = CTypesManagerNotPacked(types_ast, base_types)
+    return types_mngr
+
+
+
+# add stack alignment simpl
+def simp_stack_align(expr_simp, expr):
+    if not expr.is_op("&"):
+        return expr
+    if len(expr.args) != 2:
+        return expr
+    if not expr.args[1].is_int(0xFFFFFFF0):
+        return expr
+    if expr.args[0] != ir_arch.arch.regs.ESP_init:
+        return expr
+    return expr.args[0]
+
+expr_simp.enable_passes({m2_expr.ExprOp: [simp_stack_align]})
+
+# Init
+machine = guess_machine()
+mn, dis_engine, ira = machine.mn, machine.dis_engine, machine.ira
+
+bs = bin_stream_ida()
+mdis = dis_engine(bs, dont_dis_nulstart_bloc=True)
+ir_arch = ira(mdis.symbol_pool)
+
+# Get the current function
+func = idaapi.get_func(ScreenEA())
+addr = func.startEA
+blocks = mdis.dis_multibloc(addr)
+# Generate IR
+for block in blocks:
+    ir_arch.add_bloc(block)
+
+
+class MyCTypeAnalyzer(CTypeAnalyzer):
+    allow_none_result = True
+
+
+class MyExprToAccessC(ExprToAccessC):
+    allow_none_result = True
+
+
+class MyCHandler(CHandler):
+    cTypeAnalyzer_cls = MyCTypeAnalyzer
+    exprToAccessC_cls = MyExprToAccessC
+
+
+# Get settings
+settings = TypePropagationForm(ir_arch)
+ret = settings.Execute()
+if ret:
+
+    ir_arch = ir_arch
+
+
+    types_mngr = get_types_mngr(settings.headerFile.value)
+    mychandler = MyCHandler(types_mngr, {})
+
+    #print 'Expr', settings.iStr1.value
+    #print 'Type', settings.iStr2.value
+    #print 'Header', settings.headerFile.value
+    print 'InfoTypes', settings.strTypesInfo.value
+    infos_types = {}
+    for line in settings.strTypesInfo.value.split('\n'):
+        if not line:
+            continue
+        expr_str, ctype_str = line.split(':')
+        expr_str, ctype_str = expr_str.strip(), ctype_str.strip()
+        expr = str_to_expr(expr_str)
+        ast = mychandler.type_analyzer.types_mngr.types_ast.parse_c_type(ctype_str)
+        ctype = mychandler.type_analyzer.types_mngr.types_ast.ast_parse_declaration(ast.ext[0])
+        objc = types_mngr.get_objc(ctype)
+        print '='*20
+        print expr, objc
+        infos_types[expr] = objc
+
+    # Add fake head
+    lbl_real_start = ir_arch.symbol_pool.getby_offset(addr)
+    lbl_head = ir_arch.symbol_pool.getby_name_create("start")
+
+    first_block = blocks.label2block(lbl_real_start)
+
+    assignblk_head = AssignBlock([ExprAff(ir_arch.IRDst, ExprId(lbl_real_start, ir_arch.IRDst.size)),
+                                  ExprAff(ir_arch.sp, ir_arch.arch.regs.regs_init[ir_arch.sp])
+                                 ], first_block.lines[0])
+    irb_head = IRBlock(lbl_head, [assignblk_head])
+    ir_arch.blocks[lbl_head] = irb_head
+    ir_arch.graph.add_uniq_edge(lbl_head, lbl_real_start)
+
+    class Engine(SymbExecCType):
+        def __init__(self, state):
+            mychandler = MyCHandler(types_mngr, state.infos_types)
+            super(Engine, self).__init__(ir_arch,
+                                         state.symbols,
+                                         state.infos_types,
+                                         mychandler)
+
+
+    def add_state(todo, states, addr, state):
+        addr = ir_arch.get_label(addr)
+        if addr not in states:
+            states[addr] = state
+            todo.add(addr)
+        else:
+            todo.add(addr)
+            states[addr] = states[addr].merge(state)
+
+
+    state = Engine.StateEngine(infos_types, infos_types)
+    states = {lbl_head:state}
+    todo = set([lbl_head])
+    done = set()
+
+    while todo:
+        lbl = todo.pop()
+        state = states[lbl]
+        if (lbl, state) in done:
+            continue
+        done.add((lbl, state))
+        symbexec_engine = Engine(state)
+
+        get_block(ir_arch, mdis, lbl)
+
+        addr = symbexec_engine.emul_ir_block(lbl)
+        symbexec_engine.del_mem_above_stack(ir_arch.sp)
+
+        ir_arch._graph = None
+        sons = ir_arch.graph.successors(lbl)
+        for son in sons:
+            if son.offset is None:
+                continue
+            add_state(todo, states, son.offset, symbexec_engine.get_state())
+
+
+    class SymbExecCTypeFix(SymbExecCType):
+        def emulbloc(self, irb, step=False):
+            """
+            Symbolic execution of the @irb on the current state
+            @irb: irblock instance
+            @step: display intermediate steps
+            """
+            offset2cmt = {}
+            for assignblk in irb.irs:
+                instr = assignblk.instr
+                tmp_rw = assignblk.get_rw()
+                for dst, src in assignblk.iteritems():
+                    for arg in set(instr.args).union(set([src])):
+                        if arg in tmp_rw and arg not in tmp_rw.values():
+                            continue
+                        objc = self.eval_expr(arg)
+                        if objc is None:
+                            continue
+                        if self.is_type_offset(objc):
+                            continue
+                        offset2cmt.setdefault(instr.offset, set()).add("%s: %s" % (arg, str(objc)))
+                self.eval_ir(assignblk)
+
+            for offset, value in offset2cmt.iteritems():
+                idc.MakeComm(offset, '\n'.join(value))
+
+            return self.eval_expr(self.ir_arch.IRDst)
+
+
+    class Engine(SymbExecCTypeFix):
+        def __init__(self, state):
+            mychandler = MyCHandler(types_mngr, state.infos_types)
+            super(Engine, self).__init__(ir_arch,
+                                         state.symbols,
+                                         state.infos_types,
+                                         mychandler)
+
+
+    for lbl, state in states.iteritems():
+        symbexec_engine = Engine(state)
+        addr = symbexec_engine.emul_ir_block(lbl)
+        symbexec_engine.del_mem_above_stack(ir_arch.sp)
+
+
+
+
+
+
+
+