diff options
| -rw-r--r-- | miasm2/core/objc.py | 53 | ||||
| -rw-r--r-- | miasm2/ir/symbexec_types.py | 68 |
2 files changed, 66 insertions, 55 deletions
diff --git a/miasm2/core/objc.py b/miasm2/core/objc.py index a1604d99..de98993b 100644 --- a/miasm2/core/objc.py +++ b/miasm2/core/objc.py @@ -744,17 +744,20 @@ class CTypeAnalyzer(ExprReducer): def reduce_ptr_plus_cst(self, node, lvl): """Get type of ptr + CST""" - if not node.expr.is_op("+") or len(node.args) != 2: return None - args_types = set([self.get_solo_type(node.args[0]), - self.get_solo_type(node.args[1])]) - if args_types != set([ObjCInt, ObjCPtr]): + type_arg1 = self.get_solo_type(node.args[1]) + if type_arg1 != ObjCInt: return None + arg0, arg1 = node.args + if arg0.info is None: + return None out = [] ptr_offset = int(arg1.expr) for info in arg0.info: + if not isinstance(info, ObjCPtr): + continue ptr_basetype = info.objtype if ptr_basetype.size == 0: missing_definition(ptr_basetype) @@ -764,12 +767,10 @@ class CTypeAnalyzer(ExprReducer): ptr_offset % ptr_basetype.size, False, lvl) - return out def reduce_cst_op_cst(self, node, _): """Get type of CST + CST""" - if not node.expr.is_op("+") or len(node.args) != 2: return None if node.args[0] is None or node.args[1] is None: @@ -777,7 +778,7 @@ class CTypeAnalyzer(ExprReducer): args_types = set([self.get_solo_type(node.args[0]), self.get_solo_type(node.args[1])]) if args_types != set([ObjCInt]): - return None + return [] return [self.CST] def reduce_deref(self, node, lvl): @@ -786,7 +787,6 @@ class CTypeAnalyzer(ExprReducer): * @64[ptr<ptr<elem>>] -> ptr<elem> * @32[ptr<struct>] -> struct.00 """ - if not isinstance(node.expr, ExprMem): return None if node.arg.info is None: @@ -795,7 +795,7 @@ class CTypeAnalyzer(ExprReducer): for subtype in node.arg.info: # subtype : ptr<elem> if not isinstance(subtype, (ObjCPtr, ObjCArray)): - return None + continue target = subtype.objtype # target : type(elem) for ptr_target in self.get_typeof(target, 0, True, lvl): @@ -806,8 +806,6 @@ class CTypeAnalyzer(ExprReducer): r_target.size != node.expr.size / 8): continue found.append(r_target) - if not found: - return None return found reduction_rules = [reduce_id, reduce_int, @@ -818,7 +816,6 @@ class CTypeAnalyzer(ExprReducer): def get_type(self, expr): """Return the C type(s) of the native Miasm expression @expr @expr: Miasm expression""" - return self.reduce(expr) @@ -1011,9 +1008,9 @@ class ExprToAccessC(ExprReducer): node.expr.name in self.expr_types): return None - objc = self.expr_types[node.expr.name] - out = CGenId(objc, node.expr.name) - return [out] + objcs = self.expr_types[node.expr.name] + out = [CGenId(objc, node.expr.name) for objc in objcs] + return out def reduce_int(self, node, _): """Generate access for ExprInt""" @@ -1032,26 +1029,25 @@ class ExprToAccessC(ExprReducer): def reduce_op(self, node, lvl): """Generate access for ExprOp""" - if not node.expr.is_op("+") or len(node.args) != 2: return None - args_types = set([self.get_solo_type(node.args[0]), - self.get_solo_type(node.args[1])]) - if args_types != set([ObjCInt, ObjCPtr]): + type_arg1 = self.get_solo_type(node.args[1]) + if type_arg1 != ObjCInt: return None - arg0, arg1 = node.args + if arg0.info is None: + return None out = [] ptr_offset = int(arg1.expr) - for name in arg0.info: - assert isinstance(name.ctype, ObjCPtr) - ptr_basetype = name.ctype.objtype + for info in arg0.info: + if not isinstance(info.ctype, ObjCPtr): + continue + ptr_basetype = info.ctype.objtype # Array-like: int* ptr; ptr[1] = X - ret = self.cgen_access(name, + ret = self.cgen_access(info, ptr_basetype, ptr_offset, False, lvl) - for subcgenobj in ret: - out.append(subcgenobj) + out += ret return out def reduce_mem(self, node, lvl): @@ -1063,6 +1059,11 @@ class ExprToAccessC(ExprReducer): if not isinstance(node.expr, ExprMem): return None + if node.expr in self.expr_types: + objcs = self.expr_types[node.expr] + out = [CGenId(objc, str(node.expr)) for objc in objcs] + return out + if node.arg.info is None: return None assert isinstance(node.arg.info, list) diff --git a/miasm2/ir/symbexec_types.py b/miasm2/ir/symbexec_types.py index 2a99148f..bc5546de 100644 --- a/miasm2/ir/symbexec_types.py +++ b/miasm2/ir/symbexec_types.py @@ -111,6 +111,12 @@ class SymbExecCType(SymbolicExecutionEngine): return objc def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0): + ret = self._apply_expr_on_state_visit_cache(expr, state, cache, level) + if not ret: + return None + return tuple(ret) + + def _apply_expr_on_state_visit_cache(self, expr, state, cache, level=0): """ Deep First evaluate nodes: 1. evaluate node's sons @@ -118,56 +124,58 @@ class SymbExecCType(SymbolicExecutionEngine): """ expr = self.expr_simp(expr) - if expr in cache: return cache[expr] + elif expr in self.symbols: + ret = self.symbols[expr] + return ret elif expr in state: return state[expr] elif isinstance(expr, ExprInt): objc = self.get_type_int_by_size(expr.size) if objc is None: objc = self.chandler.type_analyzer.types_mngr.get_objc(CTypeId('int')) - return objc + return [objc] elif isinstance(expr, ExprId): if expr in state: return state[expr] return None elif isinstance(expr, ExprMem): - ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level + 1) - if ptr is None: - return None - self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = ptr + ptr_type = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level + 1) + if not ptr_type: + return ptr_type + self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = ptr_type ptr_expr = ExprId(self.OBJC_INTERNAL, expr.arg.size) objcs = self.chandler.expr_to_types(ExprMem(ptr_expr, expr.size)) - if objcs is None: - return None - objc = objcs[0] - return objc + return objcs elif isinstance(expr, ExprCond): src1 = self.apply_expr_on_state_visit_cache(expr.src1, state, cache, level + 1) src2 = self.apply_expr_on_state_visit_cache(expr.src2, state, cache, level + 1) - types = [src1, src2] - objc = self.is_offset_list(types, expr.size) - if objc: - return objc - return None + if src1 is None or src2 is None: + return None + # Return common types + types = list(set(src1).intersection(src2)) + return types elif isinstance(expr, ExprSlice): objc = self.get_type_int_by_size(expr.size) if objc is None: - # default size - objc = self.offset_types[0] - return objc + return None + return [objc] elif isinstance(expr, ExprOp): + if expr.op.startswith("call"): + return None args = [] types = [] for oarg in expr.args: - arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1) - types.append(arg) + arg_types = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1) + if arg_types is None: + return None + types += list(arg_types) if None in types: return None objc = self.is_offset_list(types, expr.size) if objc: - return objc + return [objc] # Find Base + int if expr.op != '+': return None @@ -176,21 +184,23 @@ class SymbExecCType(SymbolicExecutionEngine): offset = args.pop() types.pop() if len(args) == 1: - arg, arg_type = args.pop(), types.pop() - self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = arg_type + arg, arg_types = args.pop(), types + self.chandler.type_analyzer.expr_types[self.OBJC_INTERNAL] = arg_types ptr_expr = ExprId(self.OBJC_INTERNAL, arg.size) - objc = self.chandler.expr_to_types(ptr_expr + offset) - objc = objc[0] - return objc + objcs = self.chandler.expr_to_types(ptr_expr + offset) + return objcs return None elif isinstance(expr, ExprCompose): types = set() for oarg in expr.args: - arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1) - types.add(arg) + arg_types = self.apply_expr_on_state_visit_cache(oarg, state, cache, level + 1) + if arg_types is None: + return None + types.update(arg_types) objc = self.is_offset_list(types, expr.size) if objc: - return objc + return [objc] + return None else: raise TypeError("Unknown expr type") |