diff options
Diffstat (limited to 'example')
| -rw-r--r-- | example/expression/access_c.py | 55 | ||||
| -rw-r--r-- | example/expression/expr_c.py | 9 | ||||
| -rw-r--r-- | example/expression/expr_reduce.py | 10 | ||||
| -rw-r--r-- | example/ida/ctype_propagation.py | 108 |
4 files changed, 96 insertions, 86 deletions
diff --git a/example/expression/access_c.py b/example/expression/access_c.py index 48da53ff..f285eb55 100644 --- a/example/expression/access_c.py +++ b/example/expression/access_c.py @@ -1,16 +1,3 @@ -import sys - -from miasm2.analysis.machine import Machine -from miasm2.analysis.binary import Container -from miasm2.expression.expression import ExprOp, ExprCompose, ExprId, ExprInt -from miasm2.analysis.depgraph import DependencyGraph - -from miasm2.arch.x86.ctype import CTypeAMD64_unk - -from miasm2.core.objc import CTypeAnalyzer, ExprToAccessC, CHandler -from miasm2.core.objc import CTypesManagerNotPacked -from miasm2.core.ctypesmngr import CAstTypes, CTypePtr, CTypeStruct - """ This example demonstrates the recovering of possible C types for an arbitrary @@ -54,6 +41,20 @@ ExprCompose(var1, 0) => var1 """ +import sys + +from miasm2.analysis.machine import Machine +from miasm2.analysis.binary import Container +from miasm2.expression.expression import ExprOp, ExprCompose, ExprId, ExprInt +from miasm2.analysis.depgraph import DependencyGraph + +from miasm2.arch.x86.ctype import CTypeAMD64_unk + +from miasm2.core.objc import ExprToAccessC, CHandler +from miasm2.core.objc import CTypesManagerNotPacked +from miasm2.core.ctypesmngr import CAstTypes, CTypePtr, CTypeStruct + + def find_call(ira): """Returns (irb, index) which call""" @@ -74,24 +75,10 @@ def find_call(ira): yield irb, index -class MyCTypeAnalyzer(CTypeAnalyzer): - """Custom CTypeAnalyzer to complete type analysis""" - - def reduce_compose(self, node, _): - """Custom reduction rule: {XXX, 0} -> typeof(XXX)""" - if not (isinstance(node.expr, ExprCompose) and - len(node.expr.args) == 2 and - node.expr.args[1].is_int(0)): - return None - return node.args[0].info - - reduction_rules = CTypeAnalyzer.reduction_rules + [reduce_compose] - - class MyExprToAccessC(ExprToAccessC): """Custom ExprToAccessC to complete expression traduction to C""" - def reduce_compose(self, node, _): + def reduce_compose(self, node, **kwargs): """Custom reduction rule: {XXX, 0} -> XXX""" if not (isinstance(node.expr, ExprCompose) and len(node.expr.args) == 2 and @@ -123,7 +110,6 @@ def get_funcs_arg0(ctx, ira, lbl_head): class MyCHandler(CHandler): """Custom CHandler to add complementary C handling rules""" - cTypeAnalyzer_cls = MyCTypeAnalyzer exprToAccessC_cls = MyExprToAccessC @@ -177,11 +163,6 @@ mychandler = MyCHandler(types_mngr, expr_types) for expr in get_funcs_arg0(ctx, ir_arch_a, lbl_head): print "Access:", expr - target_types = mychandler.expr_to_types(expr) - for target_type in target_types: - print '\tType:', target_type - c_strs = mychandler.expr_to_c(expr) - for c_str in c_strs: - print "\tC access:", c_str - print - + for c_str, ctype in mychandler.expr_to_c_and_types(expr): + print '\taccess:', c_str + print '\tc type:', ctype diff --git a/example/expression/expr_c.py b/example/expression/expr_c.py index 7adc7b50..ca92153a 100644 --- a/example/expression/expr_c.py +++ b/example/expression/expr_c.py @@ -41,9 +41,8 @@ types_mngr = CTypesManagerNotPacked(types_ast, base_types) ptr_rectangle = types_mngr.get_objc(CTypePtr(CTypeStruct('rectangle'))) ptr = ExprId('ptr', 64) -expr_types = {ptr.name: ptr_rectangle} - -mychandler = CHandler(types_mngr, expr_types) +c_context = {ptr.name: ptr_rectangle} +mychandler = CHandler(types_mngr, {}) # Parse some C accesses c_acceses = ["ptr->width", @@ -55,8 +54,8 @@ c_acceses = ["ptr->width", ] for c_str in c_acceses: - expr = mychandler.c_to_expr(c_str) - c_type = mychandler.c_to_type(c_str) + expr = mychandler.c_to_expr(c_str, c_context) + c_type = mychandler.c_to_type(c_str, c_context) print 'C access:', c_str print '\tExpr:', expr print '\tType:', c_type diff --git a/example/expression/expr_reduce.py b/example/expression/expr_reduce.py index b5fc96c8..bb94ceb9 100644 --- a/example/expression/expr_reduce.py +++ b/example/expression/expr_reduce.py @@ -20,7 +20,7 @@ class StructLookup(ExprReducer): FIELD_A_PTR = "FIELD_A_PTR" FIELD_A = "FIELD_A" - def reduce_int(self, node, _): + def reduce_int(self, node, **kwargs): """ Reduction: int -> CST """ @@ -28,7 +28,7 @@ class StructLookup(ExprReducer): return self.CST return None - def reduce_ptr_struct(self, node, _): + def reduce_ptr_struct(self, node, **kwargs): """ Reduction: ECX -> FIELD_A_PTR """ @@ -36,7 +36,7 @@ class StructLookup(ExprReducer): return self.FIELD_A_PTR return None - def reduce_ptr_plus_int(self, node, _): + def reduce_ptr_plus_int(self, node, **kwargs): """ Reduction: ECX + CST -> FIELD_A_PTR """ @@ -46,7 +46,7 @@ class StructLookup(ExprReducer): return self.FIELD_A_PTR return None - def reduce_cst_op(self, node, _): + def reduce_cst_op(self, node, **kwargs): """ Reduction: CST + CST -> CST """ @@ -56,7 +56,7 @@ class StructLookup(ExprReducer): return self.CST return None - def reduce_at_struct_ptr(self, node, _): + def reduce_at_struct_ptr(self, node, **kwargs): """ Reduction: @FIELD_A_PTR -> FIELD_A """ diff --git a/example/ida/ctype_propagation.py b/example/ida/ctype_propagation.py index cb342213..5b23e6a8 100644 --- a/example/ida/ctype_propagation.py +++ b/example/ida/ctype_propagation.py @@ -10,13 +10,14 @@ 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 miasm2.arch.x86.ctype import CTypeAMD64_unk +from miasm2.arch.x86.ctype import CTypeAMD64_unk, CTypeX86_unk from miasm2.expression.expression import ExprId -from miasm2.core.objc import CTypesManagerNotPacked, CTypeAnalyzer, ExprToAccessC, CHandler +from miasm2.core.objc import CTypesManagerNotPacked, 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 +from miasm2.ir.symbexec import SymbolicExecutionEngine, SymbolicState from utils import guess_machine @@ -25,7 +26,6 @@ class TypePropagationForm(ida_kernwin.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"] @@ -35,12 +35,12 @@ class TypePropagationForm(ida_kernwin.Form): BUTTON CANCEL NONE Dependency Graph Settings <##Header file :{headerFile}> -<Architecture/complator:{cbReg}> +<Architecture/complator:{arch}> <Types informations:{strTypesInfo}> <Unalias stack:{rUnaliasStack}>{cMethod}> """, { 'headerFile': ida_kernwin.Form.FileInput(swidth=20, open=True), - 'cbReg': ida_kernwin.Form.DropdownListControl( + 'arch': ida_kernwin.Form.DropdownListControl( items=archs, readonly=False, selval=archs[0]), @@ -48,11 +48,7 @@ Dependency Graph Settings flags=ida_kernwin.Form.MultiLineTextControl.TXTF_FIXEDFONT), 'cMethod': ida_kernwin.Form.ChkGroupControl(("rUnaliasStack",)), }) - self.Compile() - - @property - def unalias_stack(self): - return self.cMethod.value & 1 or self.stk_unalias_force + form, args = self.Compile() def get_block(ir_arch, mdis, addr): @@ -67,9 +63,14 @@ def get_block(ir_arch, mdis, addr): return irblock -def get_types_mngr(headerFile): +def get_types_mngr(headerFile, arch): text = open(headerFile).read() - base_types = CTypeAMD64_unk() + if arch == "AMD64_unk": + base_types = CTypeAMD64_unk() + elif arch =="X86_32_unk": + base_types = CTypeX86_unk() + else: + raise NotImplementedError("Unsupported arch") types_ast = CAstTypes() # Add C types definition @@ -79,16 +80,11 @@ def get_types_mngr(headerFile): return types_mngr -class MyCTypeAnalyzer(CTypeAnalyzer): - allow_none_result = True - - class MyExprToAccessC(ExprToAccessC): allow_none_result = True class MyCHandler(CHandler): - cTypeAnalyzer_cls = MyCTypeAnalyzer exprToAccessC_cls = MyExprToAccessC @@ -109,25 +105,37 @@ class SymbExecCTypeFix(SymbExecCType): @irb: irblock instance @step: display intermediate steps """ + offset2cmt = {} - for assignblk in irb.irs: + for index, assignblk in enumerate(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 + tmp_r = assignblk.get_r() + tmp_w = assignblk.get_w() + + todo = set() + + # Replace PC with value to match IR args + pc_fixed = {self.ir_arch.pc: m2_expr.ExprInt(instr.offset + instr.l, self.ir_arch.pc.size)} + args = instr.args + for arg in args: + arg = expr_simp(arg.replace_expr(pc_fixed)) + + if arg in tmp_w and not arg.is_mem(): + continue + todo.add(arg) + + for expr in todo: + if expr.is_int(): + continue + + for c_str, c_type in self.chandler.expr_to_c_and_types(expr, self.symbols): offset2cmt.setdefault(instr.offset, set()).add( - "%s: %s" % (arg, str(objc))) - self.eval_ir(assignblk) + "\n%s\n%s" % (c_str, c_type)) + self.eval_ir(assignblk) for offset, value in offset2cmt.iteritems(): idc.MakeComm(offset, '\n'.join(value)) + print "%x\n" % offset, '\n'.join(value) return self.eval_expr(self.ir_arch.IRDst) @@ -141,6 +149,25 @@ class CTypeEngineFixer(SymbExecCTypeFix): mychandler) +def get_ira_call_fixer(ira): + + class iraCallStackFixer(ira): + + def call_effects(self, ad, instr): + print hex(instr.offset), instr + stk_before = idc.GetSpd(instr.offset) + stk_after = idc.GetSpd(instr.offset + instr.l) + stk_diff = stk_after - stk_before + print hex(stk_diff) + return [AssignBlock([ExprAff(self.ret_reg, ExprOp('call_func_ret', ad)), + ExprAff(self.sp, self.sp + ExprInt(stk_diff, self.sp.size)) + ], + instr + )] + + return iraCallStackFixer + + def add_state(ir_arch, todo, states, addr, state): addr = ir_arch.get_label(addr) if addr not in states: @@ -159,7 +186,11 @@ def analyse_function(): bs = bin_stream_ida() mdis = dis_engine(bs, dont_dis_nulstart_bloc=True) - ir_arch = ira(mdis.symbol_pool) + + + iraCallStackFixer = get_ira_call_fixer(ira) + ir_arch = iraCallStackFixer(mdis.symbol_pool) + # Get the current function func = ida_funcs.get_func(idc.ScreenEA()) @@ -169,13 +200,15 @@ def analyse_function(): for block in blocks: ir_arch.add_block(block) + # Get settings settings = TypePropagationForm(ir_arch) ret = settings.Execute() if not ret: return - types_mngr = get_types_mngr(settings.headerFile.value) + + types_mngr = get_types_mngr(settings.headerFile.value, settings.arch.value) mychandler = MyCHandler(types_mngr, {}) infos_types = {} for line in settings.strTypesInfo.value.split('\n'): @@ -184,14 +217,13 @@ def analyse_function(): 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( + ast = mychandler.types_mngr.types_ast.parse_c_type( ctype_str) - ctype = mychandler.type_analyzer.types_mngr.types_ast.ast_parse_declaration(ast.ext[ - 0]) + ctype = mychandler.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 + infos_types[expr] = set([objc]) # Add fake head lbl_real_start = ir_arch.symbol_pool.getby_offset(addr) @@ -228,9 +260,7 @@ def analyse_function(): ir_arch._graph = None sons = ir_arch.graph.successors(lbl) for son in sons: - if son.offset is None: - continue - add_state(ir_arch, todo, states, son.offset, + add_state(ir_arch, todo, states, son, symbexec_engine.get_state()) for lbl, state in states.iteritems(): |