LoginSignup
1
1

More than 5 years have passed since last update.

#ssmjp で #seccon CTFオンライン予選のWrite upのデモをしてきました

Posted at

1月下旬に行われたSECCON CTFのオンライン予選のネットワーク・Webの200点問題、 "Find the key!" をdpktを使って解くデモをしてきました。

SECCON CTF自体については公式サイト http://2013.seccon.jp/ をご覧ください。
また、問題や解き方については、既に多くの方がWrite upを書いているので、そちらもご覧ください。

この問題は、pcapファイルが渡されて、その中からキーを見つけると言う問題でした。
pcapファイルの中身はPingの通信で、Pingのデータ部分にHTTPの通信がトンネルされていて、その中で kagi.png という画像がGETされていました。要はその画像を復元してやればよいという問題でした。

まずは問題のファイルを開きます。

>>> import dpkt
>>> p=dpkt.pcap.Reader(open("seccon_q1_pcap.pcap","rb"))

Wiresharkでパケットを眺めていると、大体100バイトより大きいパケットに目当てのデータが含まれているコトが分かります。そこで、100バイトより大きいパケットのデータ部分をリストに抜き出します。

>>> pl=[]
>>> for t,b in p.readpkts():
...     ip=dpkt.ethernet.Ethernet(b).data
...     if ip.len > 100:
...             pl.append(ip.data.data.data)

リストの中身を見ていくと、 pl[2] から  pl[6] に画像が入っていることが分かります。

まずは pl[2] を見ます。これにはHTTPのレスポンスヘッダも含まれているので、それを取り除いてやります。PNGファイルは先頭1バイトが 0x89 ではじまり、続く3バイトがASCIIでPNGなので、PNGを探してその1バイト前からを抜き出すようにします。

>>> pl[2].index("PNG")
285
>>> PNG=pl[2][284:]

次に pl[3] から pl[6] ですが、これをすべて PNG につなげるとうまくいきません。
PNG画像(の一部)以外の何かが入っています。
kagi.png の中身はレスポンスヘッダの Content-Lengthの値から2795バイトであることが分かっています。

>>> pl[2][216:238]
'Content-Length: 2795\r\n'

それに対し、 pl[3] から pl[6] を全部つなげると、上記の値より大きくなってしまいます。

>>> len(PNG)
768
>>> l=len(PNG)
>>> for n in range(3,7):
...     l+=len(pl[n])
... 
>>> l
2908

というわけで、 pl[3] から pl[6] の各パケットにどれだけ余計なのがついてるんだろうか、としらべてみると、28バイト取り除いてあげればよさそうということが分かります。

>>> 2908 - 2795
113
>>> 113 / 4
28

余りが1あるのと、取り除くのは先頭か最後か、は pl[6] の最後を見ると分かります。

>>> pl[6][-10:]
'\x00IEND\xaeB`\x82\x00'

というわけで、 pl[3-6][28:] をつなげて、最後の1バイトを取り除いてあげればよいことが分かりました。

285
>>> PNG=pl[2][284:]
>>> for n in range(3,7):
...     PNG=PNG+pl[n][28:]
... 
>>> len(PNG)
2796
>>> PNG=PNG[:-1]
>>> open("kagi.png","w").write(PNG)

あとは、書き込んだ kagi.png を適当な画像ビューワで開いてあげるとフラグが見えます。

後で気づいたのですが、 pl[2] で HTTPのレスポンスが始まる位置を調べても、先頭28バイトを取り除いてあげればよいことが分かります。

>>> pl[2][:50]
'\xd5 \x08\x80\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x02\x00\x00\x00\x01\x00\x00\x04\x00\x00\x01\x028HTTP/1.1 200 OK\r\nDate:'
>>> pl[2].index("HTTP")
28
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1