kimtetの日記

CTFのwriteupとか、勉強したこととか

SECCON 2014 横浜大会 CTF ネットワーク予選 write up 問6

続いて問6を解くよ。 06フォルダにはquestion.txtがあって、こんな感じ。

空欄となっている箇所の2バイトの値は?

00 66 77 88  99 AA 00 11  22 33 44 55  08 00 45 00
00 54 03 76  00 00 40 01  F3 DF C0 A8  01 01 C0 A8
01 02 08 00  48 FD 3B 04  00 6F 54 01  8D C5 00 0C
A6 B9 08 09  0A 0B 0C 0D  0E 0F 10 11  12 13 14 15
16 17 18 19  1A 1B 1C 1D  1E 1F 20 21  22 23 24 25
26 27 28 29  2A 2B 2C 2D  2E 2F 30 31  32 33 34 35
36 37

00 11 22 33  44 55 00 66  77 88 99 AA  08 00 45 00
00 54 1E 0A  00 00 40 01  D9 4B C0 A8  01 02 C0 A8
01 01 00 00  -- -- 3B 04  00 6F 54 01  8D C5 00 0C
A6 B9 08 09  0A 0B 0C 0D  0E 0F 10 11  12 13 14 15
16 17 18 19  1A 1B 1C 1D  1E 1F 20 21  22 23 24 25
26 27 28 29  2A 2B 2C 2D  2E 2F 30 31  32 33 34 35
36 37

ntpのパケットじゃないのが出てきた。
"-- --" って書いてあるところの正しい値を答えろってことみたい。

問題の考え方

パケットの並びから何のデータが入る場所か特定して、その場所に入るべき値を調べればいい。
2つあるのは多分関連しているパケットで、1個目の内容から2個目の内容を推測しろってことだと思う。

解法

時間内に解けなかった。

調べた結果

トランスポート層プロトコルの確認。
トランスポート層プロトコルがわかるのは2行目の8個目01。問3参照。01だとICMP。
2つのパケットデータの両方とも01なので、ICMPでのやり取りかなと推測できる。

ICMPのタイプとコードを確かめてみる。
3行目の3番目がタイプ、4番目がコードなので確認する。
1個目のフレーム

08 00

ICMPのエコー要求であることがわかる。
2個目のフレーム

00 00

ICMPのエコー応答であることがわかる。

以下は念のため送信元と送信先のIPアドレスを確認する。 送信元IPアドレスは2行目の11番目-14番目、送信先IPアドレスは2行目の15番目-3行目の2番目を見る。

  • 1個目のフレーム
    • 送信元:C0 A8 01 01 → 192.168.1.1
    • 送信先:C0 A8 01 02 → 192.168.1.2
  • 2個目のフレーム
    • 送信元:C0 A8 01 02 → 192.168.1.2
    • 送信先:C0 A8 01 01 → 192.168.1.1

うん、やっぱり往復の通信だね。

問題の個所はICMPヘッダーのチェックサムなので、ICMPのチェックサム計算手順に沿って計算してあげればOK。 ためしに手作業で計算してみる。手順は以下の通り。

  1. 計算に当たり、チェックサム部分の16bitはゼロ (00 00) とする。
  2. ICMPヘッダ部とデータ部全部を16bit区切りの値(要するに4桁ずつ)にする。
  3. すべての値の「1の補数和」を求める。
  4. 値の1の補数を求める。

実際に計算すると次のような式になる。
Windows関数電卓を16進数に設定してコピペすると計算してくれるので便利。Microsoftさんすごい。

0000+0000+3B04+006F+5401+8DC5+000C+A6B9+0809+0A0B+0C0D+0E0F+1011+1213+1415+1617+1819+1A1B+1C1D+1E1F+2021+2223+2425+2627+2829+2A2B+2C2D+2E2F+3031+3233+3435+3637 = 4AEFE

4AEFEはただの和なので、桁あふれ処理をして「1の補数和」にする。

AEFE+0004 = AF02

1の補数にする(ビット反転)

AF02 = 1010111100000010
ビット反転
0101000011111101 = 50FD

解は50FD。できたー。

最初計算したときに「1の補数和」と「1の補数する」の意味を正しく理解していなくて下の別解の結果と合わなくて悩んだ。 「りろんはしってる(実践はできない)」はいざというときつらい(手動でチェックサム計算するなんてどういうときだ)。

参考資料

別解1

ping ICMP echo のパケットの特性(ICMPタイプ以外は全部コピーして送り返される)を考えると、1個目のフレームの内容から類推して答えることもできる。

行きのパケットのチェックサムが 48 FD。
ICMP echo の場合、リクエストとレスポンスの違いは、タイプの違いだけ。
そうすると、タイプとコードの部分の数値が 08 00 か 00 00 かという違いだけ。
つまりチェックサムの値も 08 00 と 00 00 の差だけ異なる。
チェックサムの値は1の補数を取っているので、あれやこれや計算すると受信時のチェックサムの値は送信時のチェックサムの値に 0x0800 を足した値になる。

48FD + 0800 = 50FD

こっちのほうが速いね! ちくしょー!

別解2

問1で書いた通りtext2pcapを使用する。
ただし今回のデータはオフセット(行の初めの数値)がないので、オフセットを追加して、-- -- となっているところをテキトーな 値(FF FFとか)にしてからtext2pcapにかける。

するとなんと、パケットを見ると [incorrect, should be 0x50fd] と出てご丁寧に正しい値を教えてくれる。wiresharkさんマジステキ。惚れる。

f:id:kimtet:20141129145755p:plain