def jit_instructions(mn_str): """JIT instructions and return the jitter object.""" # Get the miasm2 Machine machine = Machine("mepb") mn_mep = machine.mn() # Assemble the instructions asm = "" for instr_str in mn_str.split("\n"): instr = mn_mep.fromstring(instr_str, "b") instr.mode = "b" asm += mn_mep.asm(instr)[0] # Init the jitter and add the assembled instructions to memory jitter = machine.jitter(jit_type="gcc") jitter.vm.add_memory_page(0, PAGE_READ | PAGE_WRITE, asm) # Set the breakpoint jitter.add_breakpoint(len(asm), lambda x: False) # Jit the instructions #jitter.init_stack() jitter.init_run(0) jitter.continue_run() return jitter
def run(self): # Architecture architecture = False if self.args.architecture: architecture = self.args.architecture else: with open(self.args.filename) as fdesc: architecture = ArchHeuristic(fdesc).guess() if not architecture: raise ValueError("Unable to recognize the architecture, please specify it") if self.args.verbose: print "Guessed architecture: %s" % architecture cont = Container.from_stream(open(self.args.filename)) machine = Machine(architecture) addr_size = machine.ira().pc.size / 4 fh = FuncHeuristic(cont, machine) # Enable / disable heuristics for name in self.args.enable_heuristic: heur = fh.name2heuristic(name) if heur not in fh.heuristics: fh.heuristics.append(heur) for name in self.args.disable_heuristic: heur = fh.name2heuristic(name) fh.heuristics.remove(heur) if self.args.verbose: print "Heuristics to run: %s" % ", ".join(fh.heuristic_names) # Launch guess fmt = "0x{:0%dx}" % addr_size for addr in fh.guess(): print fmt.format(addr)
def symexec(handler): inst_bytes = handler.bytes_without_jmp machine = Machine("x86_32") cont = Container.from_string(inst_bytes) bs = cont.bin_stream mdis = machine.dis_engine(bs, symbol_pool=cont.symbol_pool) end_offset = len(inst_bytes) mdis.dont_dis = [end_offset] asm_block = mdis.dis_block(0) # print asm_block ira = machine.ira(mdis.symbol_pool) ira.add_block(asm_block) symb = SymbolicExecutionEngine(ira, symbols_init) cur_addr = symb.emul_ir_block(0) count = 0 while cur_addr != ExprInt(end_offset, 32): # execute to end cur_addr = symb.emul_ir_block(cur_addr) count += 1 if count > 1000: print '[!] to many loop at %s' % handler.name break return symb
def run(self): # Architecture architecture = False if self.args.architecture: architecture = self.args.architecture else: with open(self.args.filename) as fdesc: architecture = ArchHeuristic(fdesc).guess() if not architecture: raise ValueError( "Unable to recognize the architecture, please specify it") if self.args.verbose: print "Guessed architecture: %s" % architecture cont = Container.from_stream(open(self.args.filename)) machine = Machine(architecture) addr_size = machine.ira().pc.size / 4 fh = FuncHeuristic(cont, machine) # Enable / disable heuristics for name in self.args.enable_heuristic: heur = fh.name2heuristic(name) if heur not in fh.heuristics: fh.heuristics.append(heur) for name in self.args.disable_heuristic: heur = fh.name2heuristic(name) fh.heuristics.remove(heur) if self.args.verbose: print "Heuristics to run: %s" % ", ".join(fh.heuristic_names) # Launch guess fmt = "0x{:0%dx}" % addr_size for addr in fh.guess(): print fmt.format(addr)
def __init__(self, code, architecture): self.code = code self.machine = Machine(architecture) self.mdis = self.machine.dis_engine(code) self.ira = SubIRA64(self.mdis.symbol_pool) self.se_engine = SymbolicExecutionEngine( self.ira, self.machine.mn.regs.regs_init)
def __init__(self, jitter_engine): self.machine = Machine(self.arch_name) self.myjit = self.machine.jitter(jitter_engine) self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False
def main(): global cfg global block global data #Paint the cfg_before image from disassembly cont = Container.from_stream(open('300.bin')) bin_stream = cont.bin_stream adr = 0x401550 machine = Machine(cont.arch) mdis = machine.dis_engine(bin_stream) blocks = mdis.dis_multibloc(adr) open("cfg_before.dot", "w").write(blocks.dot()) #Get filename parser = Sandbox_Linux_x86_64.parser(description="300.bin") parser.add_argument("filename", help="filename") options = parser.parse_args() options.mimic_env = True #Start Sandbox sb = Sandbox_Linux_x86_64(options.filename, options, globals()) sb.jitter.init_run(sb.entry_point) sb.jitter.add_breakpoint(sb.entry_point, stop) machine = Machine("x86_64") sb.run() #Get bytecode interpret() #Paint cfg open("vm_graph.dot", "w").write(cfg.dot())
def r2m2_dis(opcode): """Disassemble an instruction using miasm.""" machine = Machine("x86_64") mode = machine.dis_engine().attrib instr = machine.mn().dis(opcode, mode) return [instr.l, str(instr)]
def __init__(self, jitter_engine): self.myjit = Machine(self.arch_name).jitter(jitter_engine) self.myjit.stack_base = 0x1000 self.myjit.stack_size = 0x1000 self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False
def guess_machine(): "Return an instance of Machine corresponding to the IDA guessed processor" processor_name = GetLongPrm(INF_PROCNAME) info = idaapi.get_inf_structure() if info.is_64bit(): size = 64 elif info.is_32bit(): size = 32 else: size = None if processor_name == "metapc": size2machine = { 64: "x86_64", 32: "x86_32", None: "x86_16", } machine = Machine(size2machine[size]) elif processor_name == "ARM": # TODO ARM/thumb # hack for thumb: set armt = True in globals :/ # set bigendiant = True is bigendian # Thumb, size, endian info2machine = { (True, 32, True): "armtb", (True, 32, False): "armtl", (False, 32, True): "armb", (False, 32, False): "arml", (False, 64, True): "aarch64b", (False, 64, False): "aarch64l", } is_armt = globals().get('armt', False) is_bigendian = globals().get('bigendian', False) infos = (is_armt, size, is_bigendian) if not infos in info2machine: raise NotImplementedError('not fully functional') machine = Machine(info2machine[infos]) from miasm2.analysis.disasm_cb import guess_funcs, guess_multi_cb from miasm2.analysis.disasm_cb import arm_guess_subcall, arm_guess_jump_table guess_funcs.append(arm_guess_subcall) guess_funcs.append(arm_guess_jump_table) elif processor_name == "msp430": machine = Machine("msp430") elif processor_name == "mipsl": machine = Machine("mips32l") elif processor_name == "mipsb": machine = Machine("mips32b") else: print repr(processor_name) raise NotImplementedError('not fully functional') return machine
def main(): #Setup Machine for arm, get filename machine = Machine('armtl') parser = ArgumentParser("Description") parser.add_argument('filename', help='filename') args = parser.parse_args() #Setup disassembly stream in container, get blocks and draw the graph cont = Container.from_stream(open(args.filename)) bin_stream = cont.bin_stream mdis = machine.dis_engine(bin_stream) blocks = mdis.dis_multibloc(0x614) open("cfg.dot", "w").write(blocks.dot()) #Create a template for matching blocks in the control flow graph #Requirement 1) Don't get block 0xdf8, it can't disassemble #Requirement 2) Get ones that start with LDR #Requirement 3) Get ones where the second to last instruction is CMP #No restructions for in going and out going edges mblock = MatchGraphJoker( name='mblock', restrict_in=False, restrict_out=False, filt=lambda block: block.label.offset != 0xdf8 and "LDR" in block. lines[0].name and "CMP" in block.lines[-2].name) #Basic block matcher nblock = MatchGraphJoker(name="next", restrict_in=False, restrict_out=False) #Now it should match the blocks we want with the checks matcher = nblock >> mblock flag_storage = {} #Loop through matching template blocks for sol in matcher.match(blocks): try: #Grab position line pline = sol[mblock].lines[3] #Grab character check line cline = sol[mblock].lines[-2] #Transform character and position to integer pos = int(pline.arg2str(pline.args[1]), 16) c = int(cline.arg2str(cline.args[1]), 16) #If its NULL, ignore if c != 0: flag_storage.update({pos: c}) except ValueError: #The F at the beginning is a NULL check pass #Print Flag flag = "".join(map(lambda x: chr(flag_storage[x]), sorted(flag_storage))).replace("F", "I") print "F" + flag pass
def execc(self, code): machine = Machine('x86_32') mdis = machine.dis_engine(code) blocs = mdis.dis_multibloc(0) ira = machine.ira() for b in blocs: ira.add_bloc(b) sb = symbexec(ira, machine.mn.regs.regs_init) sb.emul_ir_blocs(ira, 0) return sb
class ReverseFlashairBinary(object): """ Frequent operations on the flashair binary """ def __init__(self, filename, offset=0, r2_options=None): """ Initialize the object """ # Remember the file offset self.offset = offset # Get a r2pipe handle self.r2p = get_r2pipe(filename, offset, r2_options) # Create the miasm Machine self.machine = Machine("mepl") self.mn = self.machine.mn() def strings(self): """ get_strings wrapper """ return get_strings(self.r2p) def prologues(self): """ get_prologues wrapper """ return get_prologues(self.r2p) def nearest_prologue(self, address): """ find the nearest function prologue """ tmp = [(address - p, p) for p in self.prologues() if p < address] prologues = sorted(tmp) if len(prologues): return prologues[0][1] return prologues def assemble( self, instruction, ): """ Assemble one instructtion with miasm2 """ mode = self.machine.dis_engine().attrib instr = self.mn.fromstring(instruction, mode) instr.mode = mode return self.mn.asm(instr, mode)
def do_trace(self): '''Run miasm and construct the trace''' self.trace = Trace() # Retrieve miasm tools machine = Machine(self.machine) jitter = machine.jitter("python") # Set the jitter to use our custom emulator jitter.jit.symbexec = CustomEmulatedSymbExec(jitter.cpu, jitter.vm, jitter.jit.ir_arch, {}) jitter.jit.symbexec.enable_emulated_simplifications() jitter.jit.symbexec.reset_regs() elf = vm_load_elf(jitter.vm, open(self.program, "rb").read()) # Init segment jitter.ir_arch.do_stk_segm = True jitter.ir_arch.do_ds_segm = True jitter.ir_arch.do_str_segm = True jitter.ir_arch.do_all_segm = True FS_0_ADDR = 0x7ff70000 jitter.cpu.FS = 0x4 jitter.cpu.set_segm_base(jitter.cpu.FS, FS_0_ADDR) jitter.vm.add_memory_page(FS_0_ADDR + 0x28, PAGE_READ, "\x42\x42\x42\x42\x42\x42\x42\x42") # Init stack and push main args jitter.init_stack() jitter.push_uint64_t(1) jitter.vm.add_memory_page(0x800000, PAGE_READ, self.program) jitter.push_uint64_t(0x800000) jitter.push_uint64_t(0xDEADDEAD) jitter.add_breakpoint(0xDEADDEAD, self.end_do_trace) jitter.add_breakpoint(0x1337beef, self.end_func) jitter.add_breakpoint(self.address, self.begin_func) # Run the execution if self.main_address is None: jitter.init_run(elf.Ehdr.entry) else: jitter.init_run(self.main_address) for addr, info in jitter.vm.get_all_memory().iteritems(): self.segments += [(addr, addr + info['size'])] jitter.continue_run() assert jitter.run == False return self.trace
def __init__(self, testcreator): ''' @testcreator: TestCreator instance with associated information ''' self.trace = testcreator.trace self.prototype = testcreator.prototype self.learnexceptiontext = testcreator.learnexceptiontext self.types = testcreator.types self.printer = Printer() self.headerfile = testcreator.headerfile self.ira = Machine(testcreator.machine).ira() self.ptr_size = self.ira.sizeof_pointer() / 8 self.logger = testcreator.logger
def r2m2_asm(mn_str): """Assemble an instruction using miasm.""" # miasm2 only parses upper case mnemonics mn_str = mn_str.upper() mn_str = mn_str.replace("X", "x") # hexadecimal machine = Machine("x86_64") mode = machine.dis_engine().attrib mn = machine.mn() instr = mn.fromstring(mn_str, mode) asm_instr = [i for i in mn.asm(instr)][0] return [struct.unpack("!B", byte)[0] for byte in asm_instr]
def guess_machine(): "Return an instance of Machine corresponding to the IDA guessed processor" processor_name = GetLongPrm(INF_PROCNAME) if processor_name == "metapc": # HACK: check 32/64 using INF_START_SP max_size = GetLongPrm(INF_START_SP) if max_size == 0x80: # TODO XXX check machine = Machine("x86_16") elif max_size == 0xFFFFFFFF: machine = Machine("x86_32") elif max_size == 0xFFFFFFFFFFFFFFFF: machine = Machine("x86_64") else: raise ValueError('cannot guess 32/64 bit! (%x)' % max_size) elif processor_name == "ARM": # TODO ARM/thumb # hack for thumb: set armt = True in globals :/ # set bigendiant = True is bigendian is_armt = globals().get('armt', False) is_bigendian = globals().get('bigendian', False) if is_armt: if is_bigendian: machine = Machine("armtb") else: machine = Machine("armtl") else: if is_bigendian: machine = Machine("armb") else: machine = Machine("arml") from miasm2.analysis.disasm_cb import guess_funcs, guess_multi_cb from miasm2.analysis.disasm_cb import arm_guess_subcall, arm_guess_jump_table guess_funcs.append(arm_guess_subcall) guess_funcs.append(arm_guess_jump_table) elif processor_name == "msp430": machine = Machine("msp430") elif processor_name == "mipsl": machine = Machine("mipsl") elif processor_name == "mipsb": machine = Machine("mipsb") else: print repr(processor_name) raise NotImplementedError('not fully functional') return machine
def init_jitter(): global data, run_addr # Create jitter myjit = Machine("x86_32").jitter(sys.argv[1]) myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, data) # Init jitter myjit.init_stack() myjit.set_trace_log() myjit.push_uint32_t(0x1337beef) myjit.add_breakpoint(0x1337beef, code_sentinelle) return myjit
def main(): native_code = assemble_text(asm_helloworld, [("L_MAIN", 0)]) mach = Machine("x86_64") jitter = mach.jitter(jit_type="tcc") run_addr =0x40000000 jitter.init_stack() jitter.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, native_code) jitter.push_uint64_t(0xdeadbeef) jitter.add_breakpoint(0xdeadbeef, on_exit) jitter.jit.log_mn = True jitter.init_run(run_addr) jitter.continue_run()
def __init__(self, filename, offset=0, r2_options=None): """ Initialize the object """ # Remember the file offset self.offset = offset # Get a r2pipe handle self.r2p = get_r2pipe(filename, offset, r2_options) # Create the miasm Machine self.machine = Machine("mepl") self.mn = self.machine.mn()
def do_trace(self): '''Run miasm and construct the trace''' self.trace = Trace() # Retrieve miasm tools machine = Machine(self.machine) jitter = machine.jitter("python") # Set the jitter to use our custom emulator jitter.jit.symbexec = CustomEmulatedSymbExec( jitter.cpu, jitter.vm, jitter.jit.ir_arch, {}) jitter.jit.symbexec.enable_emulated_simplifications() jitter.jit.symbexec.reset_regs() elf = vm_load_elf(jitter.vm, open(self.program, "rb").read()) # Init segment jitter.ir_arch.do_stk_segm = True jitter.ir_arch.do_ds_segm = True jitter.ir_arch.do_str_segm = True jitter.ir_arch.do_all_segm = True FS_0_ADDR = 0x7ff70000 jitter.cpu.FS = 0x4 jitter.cpu.set_segm_base(jitter.cpu.FS, FS_0_ADDR) jitter.vm.add_memory_page( FS_0_ADDR + 0x28, PAGE_READ, "\x42\x42\x42\x42\x42\x42\x42\x42") # Init stack and push main args jitter.init_stack() jitter.push_uint64_t(1) jitter.vm.add_memory_page(0x800000, PAGE_READ, self.program) jitter.push_uint64_t(0x800000) jitter.push_uint64_t(0xDEADDEAD) jitter.add_breakpoint(0xDEADDEAD, self.end_do_trace) jitter.add_breakpoint(0x1337beef, self.end_func) jitter.add_breakpoint(self.address, self.begin_func) # Run the execution if self.main_address is None: jitter.init_run(elf.Ehdr.entry) else: jitter.init_run(self.main_address) jitter.continue_run() assert jitter.run == False return self.trace
def miasm_machine(): """Retrieve a miasm2 machine using the R2M2_ARCH environment variable.""" r2m2_arch = os.getenv("R2M2_ARCH") available_archs = Machine.available_machine() if not r2m2_arch or not r2m2_arch in available_archs: message = "Please specify a valid miasm2 arch in the R2M2_ARCH " \ "environment variable !\n" \ "The following are available: " message += ", ".join(available_archs) print >> sys.stderr, message + "\n" else: return Machine(r2m2_arch)
class ethRE: def __init__(self): self.machine = Machine("evm") self.mn = self.machine.mn def get_bytecode(self, account_addr): code = evm_env.code(int(account_addr[2:],16)) code = code[2:] # To remove '0x'.. if len(code) % 2 == 1: code = "0"+code code = binascii.unhexlify(code) return code def from_bytecode(self, bytecode): container = Container.from_string(bytecode) mdis = self.machine.dis_engine(container.bin_stream) self.blks = mdis.dis_multibloc(0) def from_asm(self, asm_text): all_bloc, symbol_pool = parse_asm.parse_txt(self.mn,0, asm_text) self.blks = all_bloc raise Exception("Not correctly implemented") def graph(self): if not self.blks: raise Exception("Need to parse bytecode before") return self.blks.dot()
class Generator(object): ''' Abstract class used to represent a generator A generator is a class that create a test from a snapshot Here a test is a sibyl test init function and a sibyl test check function ''' def __init__(self, trace, functionname, nb_arg, learnexceptiontext, abicls, machine): ''' @snapshot: snapshot used to create the test @number: index used to distinguish init and check functions' names between two snapshots @nb_arg: number of argument of the learned function @abicls: ABI of the program used during the learning @machine: machine of the program used during the learning ''' self.trace = trace self.functionname = functionname self.nb_arg = nb_arg self.learnexceptiontext = learnexceptiontext self.abicls = abicls self.printer = Printer() self.ira = Machine(machine).ira() self.ptr_size = self.ira.sizeof_pointer() / 8 def generate_test(self): '''Abstract method that should return the string corresponding to the code of the init test''' raise NotImplementedError("Abstract method")
class MiasmSEOracle: def __init__(self, code, architecture): self.code = code self.machine = Machine(architecture) self.mdis = self.machine.dis_engine(code) self.ira = SubIRA64(self.mdis.symbol_pool) self.se_engine = SymbolicExecutionEngine( self.ira, self.machine.mn.regs.regs_init) def determine_ira(self, architecture): if architecture == "x86_64": return SubIRA64(self.mdis.symbol_pool) elif architecture == "x86_32": return SubIRA32(self.mdis.symbol_pool) else: raise NotImplementedError( "Architecture {} not supported".format(architecture)) def execute(self): addr = 0 while addr < len(self.code): basic_block = self.mdis.dis_block(addr) self.ira.add_block(basic_block) ira_block = self.ira.get_block(addr) self.se_engine.emulbloc(ira_block) addr = basic_block.get_range()[1]
def main(): global dse #Argparse wrapper is within Sandbox_Linux_x86_64, but it also return a jitter object so w/e parser = Sandbox_Linux_x86_64.parser(description="Sandbox") parser.add_argument('filename', help="filename") args = parser.parse_args() #start sandbox sb = Sandbox_Linux_x86_64(args.filename, args, globals()) sb.jitter.init_run(sb.entry_point) #Stack cookies sb.jitter.vm.add_memory_page(0x28, PAGE_READ | PAGE_WRITE, "B" * 100, "stack cookies") #Setup Dynamic Sym Engine and the machine machine = Machine("x86_64") dse = DSEPathConstraint( machine, produce_solution=DSEPathConstraint.PRODUCE_SOLUTION_PATH_COV) dse.attach(sb.jitter) dse.update_state_from_concrete() #dse.jitter.jit.log_mn = True #DSE stubs are handled by functions in the globals, aka you the programmer dse.add_lib_handler(sb.libs, globals()) #Run, print solutions sb.run() print dse.new_solutions pass
def __init__(self, testcreator, replayed_snapshot): ''' @testcreator: TestCreator instance with associated information @replayed_snapshot: snapshot to be used ''' self.isFuncFound = False self.filename = testcreator.program self.learned_addr = testcreator.address self.snapshot = replayed_snapshot self.replayexception = [] self.abicls = testcreator.abicls self.machine = Machine(testcreator.machine) self.trace = testcreator.trace self.logger = testcreator.logger self.ira = self.machine.ira() self.ptr_size = self.ira.sizeof_pointer() / 8
def main(): #Grab Filename parser = Sandbox_Linux_x86_64.parser(description="Sandbox") parser.add_argument('filename',help='filename') args = parser.parse_args() #Create Sandbox at entry of binary sb = Sandbox_Linux_x86_64(args.filename,args,globals()) sb.jitter.init_run(sb.entry_point) #Stack cookies sb.jitter.vm.add_memory_page(0x28,PAGE_READ|PAGE_WRITE,"B"*100,"stack cookies") #Create dynamic symbolic engine machine = Machine("x86_64") dse = DSEPathConstraint(machine,produce_solution=DSEPathConstraint.PRODUCE_SOLUTION_PATH_COV) dse.attach(sb.jitter) #Setup dse, all libraries are now handled by names in the globals dse.update_state_from_concrete() dse.add_lib_handler(sb.libs,globals()) #dse.jitter.jit.log_mn=True #Run sb.run() #Print answers dse.cur_solver.check() model = dse.cur_solver.model() print model
class ethRE: def __init__(self): self.machine = Machine("evm") self.mn = self.machine.mn def get_bytecode(self, account_addr): code = evm_env.code(int(account_addr[2:], 16)) code = code[2:] # To remove '0x'.. if len(code) % 2 == 1: code = "0" + code code = binascii.unhexlify(code) return code def from_bytecode(self, bytecode): container = Container.from_string(bytecode) mdis = self.machine.dis_engine(container.bin_stream) self.blks = mdis.dis_multibloc(0) def from_asm(self, asm_text): all_bloc, symbol_pool = parse_asm.parse_txt(self.mn, 0, asm_text) self.blks = all_bloc raise Exception("Not correctly implemented") def graph(self): if not self.blks: raise Exception("Need to parse bytecode before") return self.blks.dot()
def test(data): # Digest C informations text = """ struct human { unsigned short age; unsigned int height; char name[50]; }; struct ll_human { struct ll_human* next; struct human human; }; """ my_types = CTypeAMD64_unk() types_mngr = CTypesManagerNotPacked(my_types.types) types_mngr.add_c_decl(text) # Analyze binary cont = Container.fallback_container(data, None, addr=0) machine = Machine("x86_64") dis_engine, ira = machine.dis_engine, machine.ira mdis = dis_engine(cont.bin_stream, symbol_pool=cont.symbol_pool) addr_head = 0 blocks = mdis.dis_multibloc(addr_head) lbl_head = mdis.symbol_pool.getby_offset(addr_head) ir_arch_a = ira(mdis.symbol_pool) for block in blocks: ir_arch_a.add_bloc(block) open('graph_irflow.dot', 'w').write(ir_arch_a.graph.dot()) # Main function's first argument's type is "struct ll_human*" void_ptr = types_mngr.void_ptr ll_human = types_mngr.get_type(('ll_human',)) ptr_llhuman = ObjCPtr('noname', ll_human, void_ptr.align, void_ptr.size) arg0 = ExprId('ptr', 64) ctx = {ir_arch_a.arch.regs.RDI: arg0} expr_types = {arg0.name: ptr_llhuman} 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
def __init__(self, filename, learned_addr, replayed_snapshot, abicls, machine): ''' @filename: program to be used @learned_addr: addresse of the function to be tested @replayed_snapshot: snapshot to be used @abicls: ABI used by the program @machine: machine used by the program ''' self.isFuncFound = False self.filename = filename self.learned_addr = learned_addr self.snapshot = replayed_snapshot self.replayexception = [] self.abicls = abicls self.machine = Machine(machine) self.ira = self.machine.ira() self.ptr_size = self.ira.sizeof_pointer() / 8
def __init__(self, trace, functionname, nb_arg, learnexceptiontext, abicls, machine): ''' @snapshot: snapshot used to create the test @number: index used to distinguish init and check functions' names between two snapshots @nb_arg: number of argument of the learned function @abicls: ABI of the program used during the learning @machine: machine of the program used during the learning ''' self.trace = trace self.functionname = functionname self.nb_arg = nb_arg self.learnexceptiontext = learnexceptiontext self.abicls = abicls self.printer = Printer() self.ira = Machine(machine).ira() self.ptr_size = self.ira.sizeof_pointer() / 8
class Asm_Test(object): def __init__(self): self.myjit = Machine("x86_32").jitter() self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False def __call__(self): self.asm() self.run() self.check() def asm(self): blocs, symbol_pool = parse_asm.parse_txt(mn_x86, 32, self.TXT, symbol_pool = self.myjit.ir_arch.symbol_pool) # fix shellcode addr symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) s = StrPatchwork() patches = asmbloc.asm_resolve_final(mn_x86, blocs[0], symbol_pool) for offset, raw in patches.items(): s[offset] = raw s = str(s) self.assembly = s def run(self): run_addr = 0 self.myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, self.assembly) self.myjit.push_uint32_t(0x1337beef) self.myjit.add_breakpoint(0x1337beef, lambda x:False) self.myjit.init_run(run_addr) self.myjit.continue_run() assert(self.myjit.pc == 0x1337beef) def check(self): raise NotImplementedError('abstract method')
def __init__(self, jitter_engine): self.machine = Machine(self.arch_name) jitter = self.machine.jitter self.myjit = jitter(jitter_engine) self.myjit.init_stack() self.myjit.set_trace_log() self.dse = None self.assembly = None
def main(): sc = assemble_text(asm_helloworld, [("L_MAIN", 0)]) mach = Machine("x86_64") jitter = mach.jitter(jit_type="tcc") run_addr =0x40000000 jitter.init_stack() jitter.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, sc) jitter.push_uint64_t(0xdeadbeef) jitter.add_breakpoint(0xdeadbeef, on_exit) #jitter.jit.log_regs = True jitter.jit.log_mn = True init_syscall(jitter) jitter.vm.add_memory_page(ADDR_COUNTER, PAGE_READ | PAGE_WRITE, "\x00" * 8) jitter.init_run(run_addr) jitter.continue_run() print "MOV: %d" % unpack("I", jitter.vm.get_mem(ADDR_COUNTER, 4))[0]
class Arch(object): """ Parent class for Arch abstraction """ # Architecture name _ARCH_ = None def __init__(self): self.machine = Machine(self._ARCH_) self.jitter = self.machine.jitter(self.options.jitter) @classmethod def update_parser(cls, parser): pass
def __init__(self, testcreator, replayed_snapshot): ''' @testcreator: TestCreator instance with associated information @replayed_snapshot: snapshot to be used ''' self.isFuncFound = False self.filename = testcreator.program self.learned_addr = testcreator.address self.snapshot = replayed_snapshot self.replayexception = [] self.abicls = testcreator.abicls self.machine = Machine(testcreator.machine) self.trace = testcreator.trace self.logger = testcreator.logger self.ira = self.machine.ira() self.ptr_size = self.ira.sizeof_pointer()/8
class Asm_Test(object): def __init__(self, jitter): self.myjit = Machine("mips32l").jitter(jitter) self.myjit.init_stack() def __call__(self): self.asm() self.run() self.check() def asm(self): blocks, loc_db = parse_asm.parse_txt(mn_mips32, 'l', self.TXT, loc_db=self.myjit.ir_arch.loc_db) # fix shellcode addr loc_db.set_location_offset(loc_db.get_name_location("main"), 0x0) s = StrPatchwork() patches = asmblock.asm_resolve_final(mn_mips32, blocks, loc_db) for offset, raw in patches.items(): s[offset] = raw s = str(s) self.assembly = s def run(self): run_addr = 0 self.myjit.vm.add_memory_page( run_addr, PAGE_READ | PAGE_WRITE, self.assembly) self.myjit.cpu.RA = 0x1337beef self.myjit.add_breakpoint(0x1337beef, lambda x: False) self.myjit.init_run(run_addr) self.myjit.continue_run() assert(self.myjit.pc == 0x1337beef) def check(self): raise NotImplementedError('abstract method')
def __init__(self, abicls, machine): self.abicls = abicls self.input_reg = {} self.output_reg = {} self._previous_addr = 0 self._current_addr = 0 self._instr_count = 0 self._pending_call = [] # Function addr -> list of information on calls self.function_calls = {} self.paths = DiGraph() self.in_memory = {} self.out_memory = {} self._ira = Machine(machine).ira() self._ptr_size = self._ira.sizeof_pointer()/8 self.sp = self._ira.sp.name
class Asm_Test_16(Asm_Test): arch_name = "x86_16" arch_attrib = 16 ret_addr = 0x1337 def __init__(self, jitter_engine): self.myjit = Machine(self.arch_name).jitter(jitter_engine) self.myjit.stack_base = 0x1000 self.myjit.stack_size = 0x1000 self.myjit.init_stack() def init_machine(self): self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly) self.myjit.push_uint16_t(self.ret_addr) self.myjit.add_breakpoint(self.ret_addr, lambda x:False)
class Asm_Test(object): run_addr = 0x0 def __init__(self, jitter_engine): self.myjit = Machine(self.arch_name).jitter(jitter_engine) self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False def test_init(self): pass def prepare(self): pass def __call__(self): self.prepare() self.asm() self.init_machine() self.test_init() self.run() self.check() def run(self): self.myjit.init_run(self.run_addr) self.myjit.continue_run() assert(self.myjit.pc == self.ret_addr) def asm(self): blocks, symbol_pool = parse_asm.parse_txt(mn_x86, self.arch_attrib, self.TXT, symbol_pool = self.myjit.ir_arch.symbol_pool) # fix shellcode addr symbol_pool.set_offset(symbol_pool.getby_name("main"), 0x0) s = StrPatchwork() patches = asmblock.asm_resolve_final(mn_x86, blocks, symbol_pool) for offset, raw in patches.items(): s[offset] = raw s = str(s) self.assembly = s def check(self): raise NotImplementedError('abstract method')
def __init__(self, **kwargs): self.machine = Machine(self._ARCH_) self.jitter = self.machine.jitter(self.options.jitter)
execfile(filename) parser = ArgumentParser(description="x86 32 basic Jitter") parser.add_argument("filename", help="x86 32 shellcode filename") parser.add_argument("-j", "--jitter", help="Jitter engine. Possible values are : tcc (default), llvm", default="tcc") args = parser.parse_args() def code_sentinelle(jitter): jitter.run = False jitter.pc = 0 return True myjit = Machine("x86_32").jitter(args.jitter) myjit.init_stack() data = open(args.filename).read() run_addr = 0x40000000 myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, data) myjit.jit.log_regs = True myjit.jit.log_mn = True myjit.push_uint32_t(0x1337beef) myjit.add_breakpoint(0x1337beef, code_sentinelle) myjit.init_run(run_addr) myjit.continue_run()
from argparse import ArgumentParser from pdb import pm import json from miasm2.analysis.machine import Machine from miasm2.analysis.binary import Container from miasm2.analysis.depgraph import DependencyGraph from miasm2.expression.expression import ExprMem, ExprId, ExprInt32 parser = ArgumentParser("Dependency grapher") parser.add_argument("filename", help="Binary to analyse") parser.add_argument("func_addr", help="Function address") parser.add_argument("target_addr", help="Address to start") parser.add_argument("element", nargs="+", help="Elements to track") parser.add_argument("-m", "--architecture", help="Architecture (%s)" % Machine.available_machine()) parser.add_argument("-i", "--implicit", help="Use implicit tracking", action="store_true") parser.add_argument("--unfollow-mem", help="Stop on memory statements", action="store_true") parser.add_argument("--unfollow-call", help="Stop on call statements", action="store_true") parser.add_argument("--do-not-simplify", help="Do not simplify expressions", action="store_true") parser.add_argument("--rename-args", help="Rename common arguments (@32[ESP_init] -> Arg1)", action="store_true") parser.add_argument("--json", help="Output solution in JSON", action="store_true") args = parser.parse_args()
import subprocess from optparse import OptionParser from pdb import pm from miasm2.analysis.machine import Machine from miasm2.expression.expression import ExprInt, ExprCond, ExprId, \ get_expr_ids, ExprAff, ExprLoc from miasm2.core.bin_stream import bin_stream_str from miasm2.ir.symbexec import SymbolicExecutionEngine, get_block from miasm2.expression.simplifications import expr_simp 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 machine = Machine("x86_32") parser = OptionParser(usage="usage: %prog [options] file") parser.add_option('-a', "--address", dest="address", metavar="ADDRESS", help="address to disasemble", default="0") (options, args) = parser.parse_args(sys.argv[1:]) if not args: parser.print_help() sys.exit(0) def emul_symb(ir_arch, mdis, states_todo, states_done): while states_todo: addr, symbols, conds = states_todo.pop()
class Snapshot(object): @classmethod def get_byte(cls, value, byte): '''Return the byte @byte of the value''' return struct.pack('@B', (value & (0xFF << (8 * byte))) >> (8 * byte)) @classmethod def unpack_ptr(cls, value): return struct.unpack('@P', value)[0] def __init__(self, abicls, machine): self.abicls = abicls self.input_reg = {} self.output_reg = {} self._previous_addr = 0 self._current_addr = 0 self._instr_count = 0 self._pending_call = [] # Function addr -> list of information on calls self.function_calls = {} self.paths = DiGraph() self.in_memory = {} self.out_memory = {} self._ira = Machine(machine).ira() self._ptr_size = self._ira.sizeof_pointer()/8 self.sp = self._ira.sp.name def add_input_register(self, reg_name, reg_value): self.input_reg[reg_name] = reg_value def add_output_register(self, reg_name, reg_value): self.output_reg[reg_name] = reg_value def add_memory_read(self, address, size, value): for i in xrange(size): self.out_memory[address + i] = MemoryAccess(1, Snapshot.get_byte(value, i), 0, # Output access never used ) if address + i not in self.in_memory: self.in_memory[address + i] = MemoryAccess(1, Snapshot.get_byte(value, i), PAGE_READ, ) else: self.in_memory[address + i].access |= PAGE_READ def add_memory_write(self, address, size, value): for i in xrange(size): self.out_memory[address + i] = MemoryAccess(1, Snapshot.get_byte(value, i), 0, # Output access never used ) if address + i not in self.in_memory: self.in_memory[address + i] = MemoryAccess(1, "\x00", # The value is # not used by the # test PAGE_WRITE, ) else: self.in_memory[address + i].access |= PAGE_WRITE def add_executed_instruction(self, address): ''' Function called to signal that the address has been executed This function has to be called in the order of their executed instruction Else paths can not be updated correctly ''' self._previous_addr = self._current_addr self._current_addr = address self.paths.add_uniq_edge(self._previous_addr, self._current_addr) self._instr_count += 1 # Resolve call destination if (self._pending_call and self._previous_addr == self._pending_call[-1]["caller_addr"]): info = self._pending_call[-1] info["dest"] = address info["beg"] = self._instr_count def add_call(self, caller_addr, stack_ptr): ''' Function call, target is not determined yet called *before* instruction execution ''' info = {"stack_ptr": stack_ptr, "caller_addr": caller_addr, } self._pending_call.append(info) def add_ret(self, ret_addr, stack_ptr, value): ''' Function ret called *after* instruction execution ''' # Find corresponding call assert self._pending_call assert self._pending_call[-1]["stack_ptr"] >= stack_ptr info = self._pending_call.pop() info["end"] = self._instr_count info["ret"] = value current_interval = self.function_calls.setdefault(info["dest"], list()).append(info) def clean(self): """Clean the snapshot for further uses""" self.agglomerate_memory(self.in_memory) self.agglomerate_memory(self.out_memory) def agglomerate_memory(self, mem): ''' Assuming @mem is only composed of non-overlapping block this function agglomerate contiguous blocks having the same access right ''' for addr in sorted(mem.keys()): # if the addr is not already deleted if addr in mem: end_addr = addr + mem[addr].size while end_addr in mem: cur_mem = mem[addr] next_mem = mem[end_addr] # If access change, do not agglomerate if cur_mem.access != next_mem.access: break cur_mem.size += next_mem.size cur_mem.data += next_mem.data del mem[end_addr] end_addr += next_mem.size
def __init__(self): self.myjit = Machine("x86_32").jitter() self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False
import sys from miasm2.analysis.machine import Machine from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE, EXCEPT_BREAKPOINT_MEMORY, EXCEPT_ACCESS_VIOL machine = Machine("x86_32") jitter = machine.jitter(sys.argv[1]) # Prepare stack and reset memory accesses to avoid an exception jitter.vm.add_memory_page(0x10000, PAGE_READ|PAGE_WRITE, "\x00"*0x1000, "stack") print jitter.vm jitter.cpu.ESP = 0x10000 + 0x1000 jitter.push_uint32_t(0x0) jitter.push_uint32_t(0x1337beef) jitter.vm.reset_memory_access() print hex(jitter.vm.get_exception()) # Add code, and keep memory write pending jitter.vm.add_memory_page(0x1000, PAGE_READ|PAGE_WRITE, "\x00"*0x1000, "code page") # MOV EAX, 0x11223344 # RET jitter.vm.set_mem(0x1000, "B844332211C3".decode('hex')) jitter.set_trace_log() def do_not_raise_me(jitter): raise ValueError("Should not be here")
# Minimalist Symbol Exec example from miasm2.core.bin_stream import bin_stream_str from miasm2.ir.symbexec import SymbolicExecutionEngine from miasm2.analysis.machine import Machine START_ADDR = 0 machine = Machine("x86_32") # Assemble and disassemble a MOV ## Ensure that attributes 'offset' and 'l' are set line = machine.mn.fromstring("MOV EAX, EBX", 32) asm = machine.mn.asm(line)[0] # Get back block bin_stream = bin_stream_str(asm) mdis = machine.dis_engine(bin_stream) asm_block = mdis.dis_bloc(START_ADDR) # Translate ASM -> IR ira = machine.ira(mdis.symbol_pool) ira.add_bloc(asm_block) # Instanciate a Symbolic Execution engine with default value for registers ## EAX = EAX_init, ... symbols_init = ira.arch.regs.regs_init symb = SymbolicExecutionEngine(ira, symbols_init) # Emulate one IR basic block ## Emulation of several basic blocks can be done through .emul_ir_blocks cur_addr = symb.emul_ir_block(START_ADDR)
#! /usr/bin/env python2 #-*- coding:utf-8 -*- import unittest import logging from miasm2.analysis.machine import Machine import miasm2.os_dep.linux_stdlib as stdlib from miasm2.core.utils import pck32 from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE machine = Machine("x86_32") jit = machine.jitter() jit.init_stack() heap = stdlib.linobjs.heap class TestLinuxStdlib(unittest.TestCase): def test_xxx_sprintf(self): def alloc_str(s): s += "\x00" ptr = heap.alloc(jit, len(s)) jit.vm.set_mem(ptr, s) return ptr fmt = alloc_str("'%s' %d") str_ = alloc_str("coucou") buf = heap.alloc(jit,1024) jit.push_uint32_t(1111) jit.push_uint32_t(str_)
def __init__(self, jitter): self.myjit = Machine("aarch64l").jitter(jitter) self.myjit.init_stack()
import sys import subprocess from optparse import OptionParser from pdb import pm from miasm2.analysis.machine import Machine from miasm2.expression.expression import ExprInt, ExprCond, ExprId, \ get_expr_ids, ExprAssign, ExprLoc from miasm2.core.bin_stream import bin_stream_str from miasm2.ir.symbexec import SymbolicExecutionEngine, get_block from miasm2.expression.simplifications import expr_simp 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 machine = Machine("x86_32") parser = OptionParser(usage="usage: %prog [options] file") parser.add_option('-a', "--address", dest="address", metavar="ADDRESS", help="address to disasemble", default="0") (options, args) = parser.parse_args(sys.argv[1:]) if not args: parser.print_help() sys.exit(0) def emul_symb(ir_arch, ircfg, mdis, states_todo, states_done): while states_todo: addr, symbols, conds = states_todo.pop()
def __init__(self, jitter): self.myjit = Machine("aarch64l").jitter(jitter) self.myjit.init_stack() self.myjit.jit.log_regs = False self.myjit.jit.log_mn = False
console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) log.setLevel(logging.INFO) filename = os.environ.get('PYTHONSTARTUP') if filename and os.path.isfile(filename): execfile(filename) parser = ArgumentParser("Disassemble a binary") parser.add_argument('filename', help="File to disassemble") parser.add_argument('address', help="Starting address for disassembly engine", nargs="*") parser.add_argument('-m', '--architecture', help="architecture: " + \ ",".join(Machine.available_machine())) parser.add_argument('-f', "--followcall", action="store_true", help="Follow call instructions") parser.add_argument('-b', "--blockwatchdog", default=None, type=int, help="Maximum number of basic block to disassemble") parser.add_argument('-n', "--funcswatchdog", default=None, type=int, help="Maximum number of function to disassemble") parser.add_argument('-r', "--recurfunctions", action="store_true", help="Disassemble founded functions") parser.add_argument('-v', "--verbose", action="store_true", help="Verbose mode") parser.add_argument('-g', "--gen_ir", action="store_true", help="Compute the intermediate representation") parser.add_argument('-z', "--dis-nulstart-block", action="store_true", help="Do not disassemble NULL starting block") parser.add_argument('-l', "--dontdis-retcall", action="store_true", help="If set, disassemble only call destinations")
def __init__(self, jitter): self.myjit = Machine("mips32l").jitter(jitter) self.myjit.init_stack()