def bp_attach(self, jitter): """Attach a DSE in the current jitter""" self.dse = DSEEngine(self.machine, self.loc_db) self.dse.attach(self.myjit) self.dse.update_state_from_concrete() self.dse.update_state({ self._regs.EBX: self._testid, }) # Additional call to the exec callback is necessary, as breakpoints are # honored AFTER exec callback jitter.exec_cb(jitter) return True
def bp_attach(self, jitter): """Attach a DSE in the current jitter""" self.dse = DSEEngine(self.machine) self.dse.attach(self.myjit) self.dse.update_state_from_concrete() self.dse.update_state({ self._regs.EBX: self._testid, }) # Additional call to the exec callback is necessary, as breakpoints are # honored AFTER exec callback jitter.exec_cb(jitter) return True
class DSEAttachInBreakpoint(DSETest): """ Test that DSE is "attachable" in a jitter breakpoint """ TXT = ''' main: MOV EAX, 5 ADD EBX, 6 INC EBX RET ''' def __init__(self, *args, **kwargs): super(DSEAttachInBreakpoint, self).__init__(*args, **kwargs) self._dse = None ircls = self.machine.ir self._regs = ircls().arch.regs self._testid = ExprId("TEST", self._regs.EBX.size) def bp_attach(self, jitter): """Attach a DSE in the current jitter""" self.dse = DSEEngine(self.machine) self.dse.attach(self.myjit) self.dse.update_state_from_concrete() self.dse.update_state({ self._regs.EBX: self._testid, }) # Additional call to the exec callback is necessary, as breakpoints are # honored AFTER exec callback jitter.exec_cb(jitter) return True def prepare(self): pass def init_machine(self): super(DSEAttachInBreakpoint, self).init_machine() self.myjit.add_breakpoint(5, self.bp_attach) # On ADD EBX, 6 def check(self): value = self.dse.eval_expr(self._regs.EBX) # EBX = TEST # ADD EBX, 6 # INC EBX # -> EBX_final = TEST + 7 assert value == self._testid + ExprInt(7, self._regs.EBX.size)
elif dst in vm_registers_symb and vm_registers_symb[dst] == ExprId( "VM_PC", 64): vm_instr += "VM_PC = {}\n".format(dse.eval_expr(src)) print(vm_instr.strip()) # remove callback del dse.instrumentation[NEXT_ADDR] return True parser = Sandbox_Linux_x86_64.parser("Disassembler for keykoolol challenge") parser.add_argument("filename", help="Challenge filename") options = parser.parse_args() sb = Sandbox_Linux_x86_64(options.filename, options, globals()) dse = DSEEngine(sb.machine) dse.add_lib_handler(sb.libs, globals()) DISPATCHER_ADDR = 0xa5D NEXT_ADDR = 0xa77 vm_registers_symb = {} already_disass = {} dse.add_instrumentation(DISPATCHER_ADDR, symbolize_vm) sb.run()
def _process_func(self, func): dse = DSEEngine(self.sb.machine) dse.attach( self.sb.jitter ) # needs to be attached before setting exec_cb to overwrite it with ours bak_snap = dse.take_snapshot() dse.add_lib_handler(self.sb.libs, globals()) occurances = {} addr = func.loc_db.get_location_offset(LocKey(0)) asmb = func.loc_key_to_block(LocKey(0)) strings = set() self.sb.jitter.exec_cb = lambda x: self._exec_callback( dse, func, occurances, x, strings, self._get_strings_from_dse) self.sb.jitter.init_run(addr) try: self.sb.jitter.run_until(asmb.lines[-1].offset) except: pass dse.update_state_from_concrete() initial_snap = dse.take_snapshot() # prepared initial context strings.update(self._get_strings_from_dse(dse)) dse.restore_snapshot(initial_snap) for loc_key in func.walk_breadth_first_forward(LocKey(0)): addr = func.loc_db.get_location_offset(loc_key) if not addr: continue occurances.clear() self.sb.jitter.init_run(addr) dse.symb.reset_modified() # wipe errors from previous execution try: self.sb.jitter.continue_run() except Exception as e: pass dse.update_state_from_concrete() strings.update(self._get_strings_from_dse(dse)) dse.restore_snapshot(initial_snap) dse.restore_snapshot(bak_snap) strings = self._get_top_level_strings(strings) return strings
def prepare(self): self.myjit.cpu.ECX = 4 self.myjit.cpu.EDX = 5 self.dse = DSEEngine(self.machine, self.loc_db) self.dse.attach(self.myjit)
class DSETest(object): """Inspired from TEST/ARCH/X86 Test the symbolic execution correctly follow generated labels """ TXT = ''' main: SHL EDX, CL RET ''' arch_name = "x86_32" arch_attrib = 32 ret_addr = 0x1337beef run_addr = 0x0 def __init__(self, jitter_engine): self.loc_db = LocationDB() self.machine = Machine(self.arch_name) jitter = self.machine.jitter self.myjit = jitter(self.loc_db, jitter_engine) self.myjit.init_stack() self.myjit.set_trace_log() self.dse = None self.assembly = None def init_machine(self): self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly) self.myjit.push_uint32_t(self.ret_addr) self.myjit.add_breakpoint(self.ret_addr, lambda x: False) def prepare(self): self.myjit.cpu.ECX = 4 self.myjit.cpu.EDX = 5 self.dse = DSEEngine(self.machine, self.loc_db) self.dse.attach(self.myjit) def __call__(self): self.asm() self.init_machine() self.prepare() 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): mn_x86 = self.machine.mn asmcfg = parse_asm.parse_txt(mn_x86, self.arch_attrib, self.TXT, self.loc_db) # fix shellcode addr self.loc_db.set_location_offset(self.loc_db.get_name_location("main"), 0x0) output = StrPatchwork() patches = asm_resolve_final(mn_x86, asmcfg) for offset, raw in viewitems(patches): output[offset] = raw self.assembly = bytes(output) def check(self): regs = self.dse.lifter.arch.regs value = self.dse.eval_expr(regs.EDX) # The expected value should contains '<<', showing it has been in the # corresponding generated label expected = ExprOp( '<<', regs.EDX, ExprCompose(regs.ECX[0:8], ExprInt(0x0, 24)) & ExprInt(0x1F, 32)) assert value == expected
def prepare(self): self.myjit.cpu.ECX = 4 self.myjit.cpu.EDX = 5 self.dse = DSEEngine(self.machine) self.dse.attach(self.myjit)
class DSETest(object): """Inspired from TEST/ARCH/X86 Test the symbolic execution correctly follow generated labels """ TXT = ''' main: SHL EDX, CL RET ''' arch_name = "x86_32" arch_attrib = 32 ret_addr = 0x1337beef run_addr = 0x0 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 init_machine(self): self.myjit.vm.add_memory_page(self.run_addr, PAGE_READ | PAGE_WRITE, self.assembly) self.myjit.push_uint32_t(self.ret_addr) self.myjit.add_breakpoint(self.ret_addr, lambda x: False) def prepare(self): self.myjit.cpu.ECX = 4 self.myjit.cpu.EDX = 5 self.dse = DSEEngine(self.machine) self.dse.attach(self.myjit) def __call__(self): self.asm() self.init_machine() self.prepare() 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): mn_x86 = self.machine.mn blocks, loc_db = parse_asm.parse_txt( mn_x86, self.arch_attrib, 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) output = StrPatchwork() patches = asm_resolve_final(mn_x86, blocks, loc_db) for offset, raw in viewitems(patches): output[offset] = raw self.assembly = bytes(output) def check(self): regs = self.dse.ir_arch.arch.regs value = self.dse.eval_expr(regs.EDX) # The expected value should contains '<<', showing it has been in the # corresponding generated label expected = ExprOp('<<', regs.EDX, ExprCompose(regs.ECX[0:8], ExprInt(0x0, 24)) & ExprInt(0x1F, 32)) assert value == expected