from autorop import PwnState, Pipe, arutil
from pwn import log, ELF
import requests
from typing import Dict
[docs]class Rip(Pipe):
[docs] def __init__(self) -> None:
"""Acquire libc version using https://libc.rip.
We can programmatically find and download libc based on function address leaks
(two or more preferred). This pipe will set ``state.libc``, including setting
``state.libc.address`` for ready-to-use address calculation.
"""
super().__init__(())
[docs] def __call__(self, state: PwnState) -> PwnState:
"""Acquire libc version using https://libc.rip.
We can programmatically find and download libc based on function address leaks
(two or more preferred). This function sets ``state.libc``, including setting
``state.libc.address`` for ready-to-use address calculation.
Arguments:
state: The current ``PwnState`` with the following set
- ``leaks``: Leaked symbols of libc.
Returns:
Mutated ``PwnState``, with the following updated
- ``libc``: Path to ``target``'s libc, according to https://libc.rip.
- ``libc_base``: Base address of ``libc``.
"""
assert state.leaks is not None
URL = "https://libc.rip/api/find"
LIBC_FILE = ".autorop.libc"
formatted_leaks: Dict[str, str] = {}
for symbol, address in state.leaks.items():
formatted_leaks[symbol] = hex(address)
log.info("Searching for libc based on leaks using libc.rip")
r = requests.post(URL, json={"symbols": formatted_leaks})
arutil.debug_requests(r)
json = r.json()
log.debug(repr(json))
if len(json) == 0:
log.error("could not find any matching libc!")
if len(json) > 1:
log.warning(f"{len(json)} matching libc's found, picking first one")
log.info("Downloading libc")
r = requests.get(json[0]["download_url"])
arutil.debug_requests(r)
with open(LIBC_FILE, "wb") as f:
f.write(r.content)
libc = ELF(LIBC_FILE)
# pick first leak and use that to calculate base
some_symbol, its_address = next(iter(state.leaks.items()))
libc.address = its_address - libc.symbols[some_symbol]
state.libc = LIBC_FILE
state.libc_base = libc.address
# sanity check
for symbol, address in state.leaks.items():
assert state.libc is not None
diff = address - libc.symbols[symbol]
if diff != 0:
log.warning(
f"symbol {symbol} has delta with actual libc of {hex(diff)}"
)
return state