def get_assembly(self, code): fil = tempfile.mkstemp(suffix='.S')[1] ofil = tempfile.mkstemp()[1] F1 = 'MAINKAPPA' F2 = 'MAINKAPPA_END' code = norm_ins(code) s = f''' {'.THUMB' if self.thumb else ''} .global {F1} {F1}: {code} .global {F2} {F2}: ''' open(fil, 'w').write(s) print('fil', fil, 'ofile', ofil) sp.check_call(f'{self.compiler} -c {self.opts} -o {ofil} {fil}'.format( **locals()), shell=True) from chdrft.emu.elf import ElfUtils x = ElfUtils(ofil) f1 = x.get_symbol(F1) f2 = x.get_symbol(F2) data = x.get_range(f1, f2) return data
def __init__(self, fname, mc, ofile=None, dry=False): from chdrft.emu.elf import ElfUtils self.elf_file = ElfUtils(fname) self.fname = fname self.mc = mc self.patches = [] self.dry = dry self.ofile = ofile
class FilePatcher: def __init__(self, fname, mc, ofile=None, dry=False): from chdrft.emu.elf import ElfUtils self.elf_file = ElfUtils(fname) self.fname = fname self.mc = mc self.patches = [] self.dry = dry self.ofile = ofile def apply(self): tgt_file = self.fname if self.ofile is not None: shutil.copy2(self.fname, self.ofile) tgt_file = self.ofile with open(tgt_file, 'r+b') as f: mm = mmap.mmap(f.fileno(), 0) for patch in self.patches: pos = patch.pos content = patch.content if self.dry: before = mm[pos:pos + len(content)] before_ins = self.mc.ins_str( self.mc.get_ins(before, patch.addr)) next_ins = self.mc.ins_str( self.mc.get_ins(content, patch.addr)) print('fuu ', next_ins, content) print('Applying patch ', patch.to_dict(), next_ins, 'replaceing >> ', before_ins) else: mm[pos:pos + len(content)] = content mm.close() def add_patch(self, pos, content, addr=0): assert pos is not None self.patches.append(Attributize(pos=pos, content=content, addr=addr)) def patch(self, addr, content): self.add_patch(self.elf_file.get_pos(addr), content, addr=addr) def patch_one_ins(self, addr, content): one_ins = self.elf_file.get_one_ins(addr) if isinstance(content, str): content = self.mc.get_disassembly(content, addr=addr) assert len(content) <= len( one_ins.bytes), 'Cannot replace %s with %s(%s)' % ( one_ins.bytes, one_ins.bytes, content) self.patch(addr, Format(content).pad(len(one_ins.bytes), self.mc.nop[0]).v) def nop_ins(self, addr): return self.patch_one_ins(addr, b'')
def get_entry_address(self): if 1: return ElfUtils(self.get_file_path()).get_entry_address() else: s = self.do_execute('info files') print(s) addr = self.entry_regex.search(s).group(1) return int(addr, 16)
def test_uc(ctx): ctx.stack_params = (2**30, 2**20) ctx.heap_params = (2**29, 2**20) kern, elf = load_kern(ctx) event_log = open('/tmp/evens_{}.out'.format(ctx.runid), 'w') vmop_log = open('/tmp/vmop_{}.out'.format(ctx.runid), 'w') kern.tracer.cb = lambda x: event_handle(x, event_log, vmop_log) ef = ElfUtils(ctx.binary) kern.tracer.diff_mode = False runner = KernelRunner(kern) caller = AsyncMachineCaller(runner, kern.arch, kern.regs, kern.mem) client = Client() fc = FuncCallWrapperGen(ef, code_db=client.g_code, caller=caller) bufacc = MemBufAccessor(kern.mem) bufgen = SimpleBufGen(bufacc.read, bufacc.write) allocator = DummyAllocator(ctx.heap_params[0], ctx.heap_params[1], bufgen) fcaller = AsyncFunctionCaller(allocator, fc) ctx.client = client handler = AsyncHandler(ctx, kern, fcaller) sol = get_sol(kern) open('./data.in', 'wb').write(struct.pack('<I', len(sol)) + sol) start_addr = elf.get_symbol('_start') kern.mu.hook_add(uc.UC_HOOK_CODE, kernel.safe_hook(handler), None, start_addr, start_addr + 1) #kern.mu.hook_add(uc.UC_HOOK_CODE, kernel.safe_hook(handler), None, end_addr, end_addr+1) #input_addr = elf.get_symbol('opa_input') #output_addr = elf.get_symbol('opa_output') #kern.mem.write_u32(input_addr, 12) #kern.mem.write_u32(input_addr+4, 88) try: kern.start() except uc.UcError as e: print('%s' % e) tb.print_exc() #print(kern.mem.read(output_addr, 20)) return
def test_uc(ctx): kern, elf = load_kern(ctx) event_log = open('/tmp/evens_{}.out'.format(ctx.runid), 'w') vmop_log = open('/tmp/vmop_{}.out'.format(ctx.runid), 'w') kern.tracer.cb = lambda x: event_handle(x, event_log, vmop_log) ef = ElfUtils(ctx.binary) kern.tracer.diff_mode = False solver = UCSolver(kern) global charset kern.ignore_mem_access = True clist = list([ bytearray(x.rstrip(b'\n')) for x in open('./test.in', 'rb').readlines() ]) solver.go(clist) #runner = KernelRunner(kern) #caller = AsyncMachineCaller(runner, kern.arch, kern.regs, kern.mem) #client = Client() #fc = FuncCallWrapperGen(ef, code_db=client.g_code, caller=caller) #bufacc = MemBufAccessor(kern.mem) #bufgen = SimpleBufGen(bufacc.read, bufacc.write) #allocator = DummyAllocator(ctx.heap_params[0], ctx.heap_params[1], bufgen) #fcaller = AsyncFunctionCaller(allocator, fc) #ctx.client = client #handler = AsyncHandler(ctx, kern, fcaller) #kern.mu.hook_add(uc.UC_HOOK_CODE, kernel.safe_hook(handler), None, start_addr, start_addr+1) #kern.mu.hook_add(uc.UC_HOOK_CODE, kernel.safe_hook(handler), None, end_addr, end_addr+1) try: kern.start() except uc.UcError as e: print('%s' % e) tb.print_exc() #print(kern.mem.read(output_addr, 20)) return
def load_elf(kern, fil): assert fil if not isinstance(fil, ElfUtils): elf = ElfUtils(fil) else: elf = fil need_load = [] for seg in elf.elf.iter_segments(): s = Attributize(seg.header) print('GOT SEG ', hex(s.p_vaddr), hex(s.p_offset), s) if s.p_type == 'PT_LOAD' and s.p_memsz > 0: need_load.append(s) flag_mp = [ (MEM_FLAGS.PF_X, uc.UC_PROT_EXEC), (MEM_FLAGS.PF_R, uc.UC_PROT_READ), (MEM_FLAGS.PF_W, uc.UC_PROT_WRITE), ] for s in need_load: flag_mem = 0 for seg_flag, uc_flag in flag_mp: if seg_flag & s.p_flags: flag_mem = flag_mem | uc_flag flag_mem |= uc.UC_PROT_EXEC addr = s.p_vaddr sz = s.p_memsz align = s.p_align align = max(align, 4096) if s.p_paddr != 0: #base_addr = addr - s.p_offset base_addr = addr base_addr = base_addr - base_addr % align else: addr =base_addr = s.p_vaddr #base_addr = base_addr - addr % align seg_sz = sz + addr % align seg_sz = (sz + align - 1) & ~(align - 1) seg_sz = (seg_sz +4095) & ~4095 print('LOADING ', flag_mem, hex(base_addr), hex(addr), seg_sz, hex(s.p_offset)) kern.mem_map(base_addr, seg_sz, flag_mem) content = elf.get_seg_content(s) print('WRITTING ', hex(addr), len(content)) kern.mu.mem_write(addr, content) kern.post_load() regs = kern.regs for note in elf.notes: if note.n_type != 'NT_PRSTATUS': continue print(len(note.status.raw)) print(len(note.data)) if kern.arch.typ == Arch.arm64: assert len(note.data) == 392 buf = BufferParser(note.data[76+32+4:], arch=kern.arch) for i in range(31): regs[f'x{i}'] = buf.read_u64() regs.sp = buf.read_u64() regs.pc = buf.read_u64() regs.cpacr_el1 = buf.read_u64() glog.info(f'Loaded sp={regs.sp:x}, pc={regs.pc:x} cpacr={regs.cpacr_el1:x}') continue if 'status' in note: for r in note.status.pr_reg._fields: vx = r if not vx in regs: glog.info('could not load reg %s', r) continue v = note.status.pr_reg[r].get() regs[r] = v if kern.arch.typ == Arch.x86_64: fsbase = note.status.pr_reg.fs_base.get() gsbase = note.status.pr_reg.gs_base.get() kern.set_fs_base(fsbase) kern.set_gs_base(gsbase) assert kern.get_gs_base() == gsbase assert kern.get_fs_base() == fsbase print(note.status.pr_reg) return elf
def LoadFrom( pe=None, elf=None, stack_params=None, heap_params=None, arch=None, hook_imports=False, orig_elf=None, qemu_state=None, bochs_state=None, base=0, core=False, **kwargs ): arch = norm_arch(arch) lib = None if elf: lib = ElfUtils(elf, core=core) if arch is None: arch = lib.arch elif qemu_state: assert arch is not None lib = qemu_state elif bochs_state: assert arch is not None lib = bochs_state elif pe: lib = pefile.PE(pe) assert arch is not None else: lib = None mu = uc.Uc(arch.uc_arch, arch.uc_mode) kern = Kernel(mu, arch, **kwargs) if elf: assert base == 0 lib = load_elf(kern, lib) if not lib.core: kern.regs[arch.reg_pc] = lib.get_entry_address() elif qemu_state: lib = load_qemu_state(kern, lib) elif bochs_state: lib = load_bochs_state(kern, lib) elif pe: lib = load_pe(kern, lib, base=base) else: kern.post_load() kern.lib = lib if stack_params: print('MAPPING stack ', stack_params) if stack_params[1] < 0: stack_params = list(stack_params) stack_params[1] = -stack_params[1] stack_params[0] -= stack_params[1] self.mem_map(stack_params[0], stack_params[1], uc.UC_PROT_READ | uc.UC_PROT_WRITE) self.stack_seg = tuple(stack_params) if heap_params: print('MAPPING heap ', heap_params) self.heap_seg = tuple(self.heap_params) self.mem_map(heap_params[0], heap_params[1], uc.UC_PROT_READ | uc.UC_PROT_WRITE) if hook_imports: celf = elf if orig_elf: celf = ElfUtils(orig_elf) kern.hook_imports(celf.plt) kern.post_init() return kern, lib
def get_elf(self): return ElfUtils(self.get_file_path())