def build_cle_got(proj, state): debugger = get_debugger() try: got_start, got_end = debugger.get_got() except: print "angrdbg: cannot find .got.plt section" return state entry_len = proj.arch.bits / 8 got_start += 3 * entry_len # skip first 3 entries ''' print "## angr got - before ##" for a in xrange(got_start, got_end, entry_len): print "0x%x: 0x%x" % (a, state.solver.eval(getattr(state.mem[a], "uint%d_t" % proj.arch.bits).resolved)) print ''' empty_state = proj.factory.blank_state() state.memory.store(got_start, empty_state.memory.load(got_start, got_end - got_start)) ''' print "## angr got - final ##" for a in xrange(got_start, got_end, entry_len): print "0x%x: 0x%x" % (a, state.solver.eval(getattr(state.mem[a], "uint%d_t" % proj.arch.bits).resolved)) print ''' return state
def build_mixed_got(proj, state): debugger = get_debugger() try: got_start, got_end = debugger.get_got() except BaseException: print "angrdbg: cannot find .got.plt section" return state try: plt_start, plt_end = debugger.get_plt() except BaseException: print "angrdbg: cannot find .plt section" return state entry_len = proj.arch.bits / 8 get_mem = debugger.get_dword if entry_len == 4 else debugger.get_qword got_start += 3 * entry_len # skip first 3 entries ''' print "## angr got - before ##" for a in xrange(got_start, got_end, entry_len): print "0x%x: 0x%x" % (a, state.solver.eval(getattr(state.mem[a], "uint%d_t" % proj.arch.bits).resolved)) print ''' empty_state = proj.factory.blank_state() for a in xrange(got_start, got_end, entry_len): state_val = empty_state.solver.eval( getattr( empty_state.mem[a], "uint%d_t" % proj.arch.bits).resolved) if state_val in proj._sim_procedures: if proj._sim_procedures[state_val].is_stub: # real simprocs or not? dbg_val = get_mem(a) name = proj._sim_procedures[state_val].display_name if dbg_val >= plt_end or dbg_val < plt_start: # already resolved by the loader in the dbg setattr(state.mem[a], "uint%d_t" % proj.arch.bits, dbg_val) else: ea = debugger.resolve_name(name) if ea is not None: setattr(state.mem[a], "uint%d_t" % proj.arch.bits, ea) ''' print "## angr got - final ##" for a in xrange(got_start, got_end, entry_len): print "0x%x: 0x%x" % (a, state.solver.eval(getattr(state.mem[a], "uint%d_t" % proj.arch.bits).resolved)) print ''' return state
def load_mo(self, state, page_idx): """ Loads a memory object from memory. :param page_idx: the index into the page :returns: a tuple of the object """ mo = self._storage[page_idx - self._page_addr] #print filter(lambda x: x != None, self._storage) if mo is None and hasattr(self, "from_dbg"): byte_val = get_debugger().get_byte(page_idx) mo = SimMemoryObject(claripy.BVV(byte_val, 8), page_idx) self._storage[page_idx - self._page_addr] = mo return mo
def StateShot(regs={}, sync_brk=True, from_dump=False, **kwargs): debugger = get_debugger() if not from_dump: if not debugger.is_active(): raise RuntimeError( "The debugger must be active and suspended before calling StateShot" ) debugger.refresh_memory() project = load_project() debugger.before_stateshot() mem = SimSymbolicDbgMemory(memory_backer=project.loader.memory, permissions_backer=None, memory_id="mem") state = project.factory.blank_state(plugins={"memory": mem}, **kwargs) for reg in sorted(project.arch.registers, key=lambda x: project.arch.registers.get(x)[1]): if reg in ("sp", "bp", "ip"): continue try: if reg in regs: setattr(state.regs, reg, regs[reg]) else: setattr(state.regs, reg, debugger.get_reg(reg)) except BaseException: pass if project.simos.name == "Linux": # inject code to get brk if we are on linux x86/x86_64 if sync_brk and project.arch.name in ("AMD64", "X86"): state.posix.set_brk(get_linux_brk(project.arch.bits)) if get_memory_type() == SIMPROCS_FROM_CLE: # insert simprocs when possible or resolve the symbol state = build_mixed_got(project, state) elif get_memory_type() == ONLY_GOT_FROM_CLE: # load the entire got from cle with stubs state = build_cle_got(project, state) elif get_memory_type() == GET_ALL_DISCARD_CLE: # angr must not execute loader code so all symbols must be resolved state = build_bind_now_got(project, state) debugger.after_stateshot(state) return state
def get_dbg_brk_linux64(): ''' Return the current brk value in the debugged process (only x86_64 Linux) ''' # TODO this method is so weird, find a unused address to inject code not # the base address debugger = get_debugger() code = '\x0f\x05' # syscall rax = debugger.get_reg("rax") rdi = debugger.get_reg("rdi") rip = debugger.get_reg("rip") efl = debugger.get_reg("efl") debugger.set_reg("rax", 12) # sys_brk debugger.set_reg("rdi", 0) base = debugger.image_base() inj = base save = debugger.get_bytes(inj, len(code)) debugger.put_bytes(inj, code) debugger.set_reg("rip", inj) debugger.step_into() debugger.wait_ready() brk_res = debugger.get_reg("rax") debugger.set_reg("rax", rax) debugger.set_reg("rdi", rdi) debugger.set_reg("rip", rip) debugger.set_reg("efl", efl) debugger.put_bytes(inj, save) return brk_res
def get_dbg_brk_linux32(): ''' Return the current brk value in the debugged process (only x86 Linux) ''' # TODO this method is so weird, find a unused address to inject code not # the base address debugger = get_debugger() code = '\xcd\x80' # int 0x80 eax = debugger.get_reg("eax") ebx = debugger.get_reg("ebx") eip = debugger.get_reg("eip") efl = debugger.get_reg("efl") debugger.set_reg("eax", 45) # sys_brk debugger.set_reg("ebx", 0) base = debugger.image_base() inj = base save = debugger.get_bytes(inj, len(code)) debugger.put_bytes(inj, code) debugger.set_reg("eip", inj) debugger.step_into() debugger.wait_ready() brk_res = debugger.get_reg("eax") debugger.set_reg("eax", eax) debugger.set_reg("ebx", ebx) debugger.set_reg("eip", eip) debugger.set_reg("efl", efl) debugger.put_bytes(inj, save) return brk_res
def load_slice(self, state, start, end): """ Return the memory objects overlapping with the provided slice. :param start: the start address :param end: the end address (non-inclusive) :returns: tuples of (starting_addr, memory_object) """ items = [ ] if start > self._page_addr + self._page_size or end < self._page_addr: l.warning("Calling load_slice on the wrong page.") return items for addr in range(max(start, self._page_addr), min(end, self._page_addr + self._page_size)): i = addr - self._page_addr mo = self._storage[i] if mo is None and hasattr(self, "from_dbg"): byte_val = get_debugger().get_byte(addr) mo = SimMemoryObject(claripy.BVV(byte_val, 8), addr) self._storage[i] = mo if mo is not None and (not items or items[-1][1] is not mo): items.append((addr, mo)) #print filter(lambda x: x != None, self._storage) return items
def __init__(self, state=None): self.state = StateShot() if state is None else state self.symbolics = {} self.debugger = get_debugger()
def _initialize_page(self, n, new_page): if n in self._initialized: return False self._initialized.add(n) new_page_addr = n * self._page_size initialized = False if self.state is not None: self.state.scratch.push_priv(True) # if self._memory_backer is None: # pass project = load_project() debugger = get_debugger() # TODO handle simbolic address properly seg = None try: seg = debugger.seg_by_addr(new_page_addr) except BaseException: pass #print "LOADING 0x%x - 0x%x | 0x%x - 0x%x" % (new_page_addr, new_page_addr+self._page_size, seg.start, seg.end) if get_memory_type() == USE_CLE_MEMORY: # yes this is weird if isinstance(self._memory_backer, cle.Clemory): # first, find the right clemory backer for addr, backer in self._memory_backer.cbackers if self.byte_width == 8 else ( (x, y) for x, _, y in self._memory_backer.stride_repr): start_backer = new_page_addr - addr if isinstance(start_backer, BV): continue if start_backer < 0 and abs( start_backer) >= self._page_size: continue if start_backer >= len(backer): continue # find permission backer associated with the address # fall back to read-write if we can't find any... flags = DbgPage.PROT_READ | DbgPage.PROT_WRITE for start, end in self._permission_map: if start <= new_page_addr < end: flags = self._permission_map[(start, end)] break snip_start = max(0, start_backer) write_start = max(new_page_addr, addr + snip_start) write_size = self._page_size - write_start % self._page_size if self.byte_width == 8: snip = _ffi.buffer(backer)[snip_start:snip_start + write_size] mo = SimMemoryObject(claripy.BVV(snip), write_start, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) else: for i, byte in enumerate(backer): mo = SimMemoryObject(claripy.BVV( byte, self.byte_width), write_start + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) new_page.permissions = claripy.BVV(flags, 3) initialized = True elif len(self._memory_backer) <= self._page_size: for i in self._memory_backer: if new_page_addr <= i and i <= new_page_addr + self._page_size: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True elif len(self._memory_backer) > self._page_size: for i in range(self._page_size): try: if isinstance(self._memory_backer[i], claripy.ast.Base): backer = self._memory_backer[i] elif isinstance(self._memory_backer[i], bytes): backer = claripy.BVV(self._memory_backer[i]) else: backer = claripy.BVV(self._memory_backer[i], self.byte_width) mo = SimMemoryObject(backer, new_page_addr + i, byte_width=self.byte_width) self._apply_object_to_page(n * self._page_size, mo, page=new_page) initialized = True except KeyError: pass # page from debugger try: if seg is not None: perms = 0 if seg.perms & SEG_PROT_X: perms += DbgPage.PROT_EXEC if seg.perms & SEG_PROT_W: perms += DbgPage.PROT_WRITE if seg.perms & SEG_PROT_R: perms += DbgPage.PROT_READ new_page.permissions = claripy.BVV(perms, 3) #print "permissions setted %x %d" % (new_page_addr, perms) initialized = True setattr(new_page, "from_dbg", True) except Exception as ee: import traceback traceback.print_exc() if self.state is not None: self.state.scratch.pop_priv() return initialized