class TestHeader(Test): """Test extension with support for header parsing, and handling of struct offset, size, ... """ header = None def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) # Requirement check if pycparser is None: raise ImportError( "pycparser module is needed to launch tests based" "on header files") ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler( hdr.ctype_manager, { 'arg%d_%s' % (i, name): set([proto.args[name]]) for i, name in enumerate(proto.args_order) }) self.expr_types_from_C = { 'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order) } self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {} def sizeof(self, Clike): ret = self.cache_sizeof.get(Clike, None) if ret is None: ret = self.c_handler.c_to_type(Clike, self.expr_types_from_C).size * 8 self.cache_sizeof[Clike] = ret return ret def trad(self, Clike): ret = self.cache_trad.get(Clike, None) if ret is None: ret = self.c_handler.c_to_expr(Clike, self.expr_types_from_C) self.cache_trad[Clike] = ret return ret def field_addr(self, base, Clike, is_ptr=False): key = (base, Clike, is_ptr) ret = self.cache_field_addr.get(key, None) if ret is None: base_expr = self.trad(base) if is_ptr: access_expr = self.trad(Clike) else: access_expr = self.trad("&(%s)" % Clike) offset = int(expr_simp(access_expr - base_expr)) ret = offset self.cache_field_addr[key] = ret return ret
class TestHeader(Test): """Test extension with support for header parsing, and handling of struct offset, size, ... """ header = None def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) # Requirement check if pycparser is None: raise ImportError("pycparser module is needed to launch tests based" "on header files") ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler( hdr.ctype_manager, {'arg%d_%s' % (i, name): set([proto.args[name]]) for i, name in enumerate(proto.args_order)} ) self.expr_types_from_C = {'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order)} self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {} def sizeof(self, Clike): ret = self.cache_sizeof.get(Clike, None) if ret is None: ret = self.c_handler.c_to_type( Clike, self.expr_types_from_C ).size * 8 self.cache_sizeof[Clike] = ret return ret def trad(self, Clike): ret = self.cache_trad.get(Clike, None) if ret is None: ret = self.c_handler.c_to_expr(Clike, self.expr_types_from_C) self.cache_trad[Clike] = ret return ret def field_addr(self, base, Clike, is_ptr=False): key = (base, Clike, is_ptr) ret = self.cache_field_addr.get(key, None) if ret is None: base_expr = self.trad(base) if is_ptr: access_expr = self.trad(Clike) else: access_expr = self.trad("&(%s)" % Clike) offset = int(expr_simp(access_expr - base_expr)) ret = offset self.cache_field_addr[key] = ret return ret
def test(): """ C manipulation example """ # Digest C informations text = """ struct line { char color[20]; int size; }; struct rectangle { unsigned int width; unsigned int length; struct line* line; }; """ # Type manager for x86 64: structures not packed my_types = CTypeAMD64_unk() types_mngr = CTypesManagerNotPacked(my_types.types) # Add C types definition types_mngr.add_c_decl(text) # Create the ptr variable with type "struct rectangle*" void_ptr = types_mngr.void_ptr rectangle = types_mngr.get_type(('rectangle',)) ptr_rectangle = ObjCPtr('noname', rectangle, void_ptr.align, void_ptr.size) ptr = ExprId('ptr', 64) expr_types = {ptr.name: ptr_rectangle} mychandler = CHandler(types_mngr, expr_types) # Parse some C accesses c_acceses = ["ptr->width", "ptr->length", "ptr->line", "ptr->line->color", "ptr->line->color[3]", "ptr->line->size" ] for c_str in c_acceses: expr = mychandler.c_to_expr(c_str) c_type = mychandler.c_to_type(c_str) print 'C access:', c_str print '\tExpr:', expr print '\tType:', c_type
def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler( hdr.ctype_manager, { 'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order) }) self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {}
def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) # Requirement check if pycparser is None: raise ImportError( "pycparser module is needed to launch tests based" "on header files") ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler( hdr.ctype_manager, { 'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order) }) self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {}
def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler(hdr.ctype_manager, {'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order)}) self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {}
def __init__(self, *args, **kwargs): super(TestHeader, self).__init__(*args, **kwargs) # Requirement check if pycparser is None: raise ImportError("pycparser module is needed to launch tests based" "on header files") ctype_manager = CTypesManagerNotPacked(CAstTypes(), CTypeAMD64_unk()) hdr = HeaderFile(self.header, ctype_manager) proto = hdr.functions[self.func] self.c_handler = CHandler( hdr.ctype_manager, {'arg%d_%s' % (i, name): set([proto.args[name]]) for i, name in enumerate(proto.args_order)} ) self.expr_types_from_C = {'arg%d_%s' % (i, name): proto.args[name] for i, name in enumerate(proto.args_order)} self.cache_sizeof = {} self.cache_trad = {} self.cache_field_addr = {}
""" # Type manager for x86 64: structures not packed base_types = CTypeAMD64_unk() types_ast = CAstTypes() # Add C types definition types_ast.add_c_decl(text) types_mngr = CTypesManagerNotPacked(types_ast, base_types) # Create the ptr variable with type "struct rectangle*" ptr_rectangle = types_mngr.get_objc(CTypePtr(CTypeStruct('rectangle'))) ptr = ExprId('ptr', 64) c_context = {ptr.name: ptr_rectangle} mychandler = CHandler(types_mngr, {}) # Parse some C accesses c_acceses = [ "ptr->width", "ptr->length", "ptr->line", "ptr->line->color", "ptr->line->color[3]", "ptr->line->size" ] for c_str in c_acceses: 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
def prepare_symbexec(self, jitter, return_addr): # Activate callback on each instr jitter.jit.set_options(max_exec_per_call=1, jit_maxline=1) #jitter.jit.log_mn = True #jitter.jit.log_regs = True jitter.exec_cb = self.callback # Disassembler self.mdis = self.machine.dis_engine(bin_stream_vm(jitter.vm), lines_wd=1) # Symbexec engine ## Prepare the symbexec engine self.symb_ir = self.machine.ir() self.symb = EmulatedSymbExecWithModif(jitter.cpu, jitter.vm, self.symb_ir, {}) self.symb.enable_emulated_simplifications() ## Update registers value self.symb.reset_regs() self.symb.update_engine_from_cpu() ## Load the memory as ExprMem self.symb.func_read = None self.symb.func_write = None for base_addr, mem_segment in jitter.vm.get_all_memory().iteritems(): # Split into 8 bytes chunk for get_mem_overlapping for start in xrange(0, mem_segment["size"], 8): expr_mem = m2_expr.ExprMem(m2_expr.ExprInt(base_addr + start, size=64), size=8 * min(8, mem_segment["size"] - start)) # Its initialisation, self.symb.apply_change is not necessary self.symb.symbols[expr_mem] = self.symb._func_read(expr_mem) ## Save the initial state self.symbols_init = self.symb.symbols.copy() ## Save the returning address self.return_addr = return_addr # Inject argument # TODO # TODO: use abicls abi_order = ["RDI", "RSI", "RDX", "RCX", "R8", "R9"] self.init_values = {} struct_expr_types = {} self.args_symbols = [] for i, param_name in enumerate(self.prototype.args_order): cur_arg_abi = getattr(self.ira.arch.regs, abi_order[i]) cur_arg = m2_expr.ExprId("arg%d_%s" % (i, param_name), size=cur_arg_abi.size) arg_type = self.prototype.args[param_name] if objc_is_dereferenceable(arg_type): # Convert the argument to symbol to track access based on it self.init_values[cur_arg] = self.symb.symbols[cur_arg_abi] self.symb.apply_change(cur_arg_abi, cur_arg) struct_expr_types[cur_arg.name] = arg_type self.args_symbols.append(cur_arg) # Init Expr <-> C conversion # Strict access is deliberately not enforced (example: memcpy(struct)) self.c_handler = CHandler(self.types, struct_expr_types, enforce_strict_access=False) # Init output structures self.memories_read = set() self.memories_write = set()
ExprMem(ExprMem(ptr_test + ExprInt(0xb30 + 0x8 * 2, 64), 64), 64) + ExprInt(12 * 3 + 8, 64), 16), [("short", "((*(((ptr_Test)->tab5)[2]))[3]).z")]), # tab 6 (ExprMem( ptr_test + ExprInt(0xc30 + ((((3) * 4 + 2) * 4 + 0) * 4 + 1) * 8, 64), 64), [("int *", "(((((ptr_Test)->tab6)[3])[2])[0])[1]")]), (ExprMem( ExprMem( ptr_test + ExprInt(0xc30 + ((((3) * 4 + 2) * 4 + 0) * 4 + 1) * 8, 64), 64), 32), [("int", "*((((((ptr_Test)->tab6)[3])[2])[0])[1])")]), ] mychandler = CHandler(types_mngr, expr_types) exprc2expr = ExprCToExpr(expr_types, types_mngr) mychandler.updt_expr_types(expr_types) for (expr, result) in tests[4:]: print "*" * 80 print "Native expr:", expr result = set(result) expr_c = mychandler.expr_to_c(expr) types = mychandler.expr_to_types(expr) target_type = mychandler.expr_to_types(expr) access_c_gen = ExprToAccessC(expr_types, types_mngr) computed = set() for c_str, ctype in mychandler.expr_to_c_and_types(expr):
# tab 6 ( ExprMem(ptr_test + ExprInt(0xc30 + ((((3) * 4 + 2)*4 + 0)*4 + 1)*8, 64), 64), [("int *", "(((((ptr_Test)->tab6)[3])[2])[0])[1]")] ), ( ExprMem(ExprMem(ptr_test + ExprInt(0xc30 + ((((3) * 4 + 2)*4 + 0)*4 + 1)*8, 64), 64), 32), [("int", "*((((((ptr_Test)->tab6)[3])[2])[0])[1])")] ), ] mychandler = CHandler(types_mngr, expr_types) exprc2expr = ExprCToExpr(expr_types, types_mngr) mychandler.updt_expr_types(expr_types) for (expr, result) in tests[4:]: print "*" * 80 print "Native expr:", expr result = set(result) expr_c = mychandler.expr_to_c(expr) types = mychandler.expr_to_types(expr) target_type = mychandler.expr_to_types(expr) access_c_gen = ExprToAccessC(expr_types, types_mngr) computed = set()
# Type manager for x86 64: structures not packed base_types = CTypeAMD64_unk() types_ast = CAstTypes() # Add C types definition types_ast.add_c_decl(text) types_mngr = CTypesManagerNotPacked(types_ast, base_types) # Create the ptr variable with type "struct rectangle*" ptr_rectangle = types_mngr.get_objc(CTypePtr(CTypeStruct('rectangle'))) ptr = ExprId('ptr', 64) c_context = {ptr.name: ptr_rectangle} mychandler = CHandler(types_mngr, C_types=c_context) # Parse some C accesses c_acceses = ["ptr->width", "ptr->length", "ptr->line", "ptr->line->color", "ptr->line->color[3]", "ptr->line->size" ] for c_str in c_acceses: expr = mychandler.c_to_expr(c_str) c_type = mychandler.c_to_type(c_str) print 'C access:', c_str print '\tExpr:', expr
# Type manager for x86 64: structures not packed base_types = CTypeAMD64_unk() types_ast = CAstTypes() # Add C types definition types_ast.add_c_decl(text) types_mngr = CTypesManagerNotPacked(types_ast, base_types) # Create the ptr variable with type "struct rectangle*" ptr_rectangle = types_mngr.get_objc(CTypePtr(CTypeStruct('rectangle'))) ptr = ExprId('ptr', 64) c_context = {ptr.name: ptr_rectangle} mychandler = CHandler(types_mngr, {}) # Parse some C accesses c_acceses = ["ptr->width", "ptr->length", "ptr->line", "ptr->line->color", "ptr->line->color[3]", "ptr->line->size" ] for c_str in c_acceses: 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