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 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 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 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 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 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 scode(data, length, key, shellcode): def code_sentinelle(jitter): jitter.run = False jitter.pc = 0 return True myjit = Machine("x86_32").jitter("tcc") myjit.init_stack() run_addr = 0x40000000 myjit.vm.add_memory_page(run_addr, PAGE_READ | PAGE_WRITE, shellcode) #myjit.jit.log_regs = True #myjit.jit.log_mn = True #myjit.jit.log_newbloc = True myjit.add_breakpoint(0x1337beef, code_sentinelle) myjit.vm.add_memory_page(0x10000000, PAGE_READ | PAGE_WRITE, data) #myjit.add_breakpoint(0x40000000, code_sentinelle) myjit.push_uint32_t(key) myjit.push_uint32_t(len(data)) myjit.push_uint32_t(0x10000000) myjit.push_uint32_t(0x1337beef) myjit.init_run(run_addr) myjit.continue_run() return myjit.cpu.get_mem(0x10000000, len(data))
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
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 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 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 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 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 __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 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
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.jit.log_regs = True self.myjit.jit.log_mn = True self.dse = None self.assembly = None
def test_learn(args): machine = Machine("x86_64") # Compil tests log_info("Remove old files") os.system("make clean") log_info("Compile C files") status = os.system("make") assert status == 0 # Find test names c_files = [] for cur_dir, sub_dir, files in os.walk("."): c_files += [x[:-2] for x in files if x.endswith(".c")] for c_file in c_files: cont = Container.from_stream(open(c_file)) func_name = c_file main_addr = cont.symbol_pool["main"].offset func_addr = cont.symbol_pool[func_name].offset log_info("Learning " + func_name + " over " + func_name + ".c") cmd = [ "sibyl", "learn", "-t", "miasm", "-m", hex(main_addr), func_name, c_file ] sibyl = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = sibyl.communicate() assert sibyl.returncode == 0 log_info("Testing generated class") mod = imp.new_module("testclass") exec stdout in mod.__dict__ classTest = getattr(mod, "Test" + c_file) tl = TestLauncher(c_file, machine, ABI_AMD64_SYSTEMV, [classTest], "gcc") possible_funcs = tl.run(func_addr) if tl.possible_funcs: log_success("Generated class recognize the function " + func_name) else: log_error("Generated class failed to recognize the function " + func_name) log_info("Remove old files") os.system("make clean")
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 guess_machine(): "Return an instance of Machine corresponding to the IDA guessed processor" processor_name = GetLongPrm(INF_PROCNAME) max_size = GetLongPrm(INF_START_SP) size = max_size_to_size(max_size) if processor_name == "metapc": # HACK: check 32/64 using INF_START_SP if max_size == 0x80: # TODO XXX check machine = Machine("x86_16") elif size == 32: machine = Machine("x86_32") elif size == 64: 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 # 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("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 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 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 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)
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 assemble_text(src_text, symbols=[], mach_name="x86_64", mach_attr=64): # 指定アーキテクチャのニーモニックを取得 mnemo = Machine(mach_name).mn # セクションとシンボルの取得 sections, symbol_pool = parse_asm.parse_txt(mnemo, mach_attr, src_text) # シンボル毎のアドレスを設定 for name, addr in symbols: symbol_pool.set_offset(symbol_pool.getby_name(name), addr) # アセンブル patches = asmbloc.asm_resolve_final(mnemo, sections[0], symbol_pool) # アセンブル結果の構築 patch_worker = StrPatchwork() for offset, raw in patches.items(): patch_worker[offset] = raw return str(patch_worker)
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