博多電光

blog.hkt.sh

Internetwache CTF 2016 writeup

TSG (東京大学理論科学グループ) のメンバーに誘われたので、2月20日から22日にかけて、チームTSGの一員として Internetwache CTF 2016 に参加した。

参加して初めて知ったがどうやらガチ初心者向けのCTFであるらしく(CSAWよりも簡単な印象)、メンバーがほいほい解いていくので僕の出番はほとんどなかったと言っていい。が、この広いインターネットで誰かの役に立つかもしれないので、いちおう一通りWriteupを書いてみる。

すでに書かれた他のメンバーのWriteupは以下を参照。

satos.hatenablog.jp

ちなみにチームTSGは2問を残して全完し、1492チーム中45位だった。

以下、解いた順。

misc50

こんなテキストファイルが与えられる。

0000000 126 062 126 163 142 103 102 153 142 062 065 154 111 121 157 113
0000020 122 155 170 150 132 172 157 147 123 126 144 067 124 152 102 146
0000040 115 107 065 154 130 062 116 150 142 154 071 172 144 104 102 167
0000060 130 063 153 167 144 130 060 113 012
0000071

これを8進数としてデコードしたあとASCIIコードとして復号する。

V2VsbCBkb25lIQoKRmxhZzogSVd7TjBfMG5lX2Nhbl9zdDBwX3kwdX0K

これをBase64でデコードする。

Well done!

Flag: IW{N0_0ne_can_st0p_y0u}

おしまい。

スクリプト

$ lsc -d
ls> require \fs .read-file-sync \README.txt |> (.to-string! / /\s/) |> filter (.length is 3) |> map parse-int _, 8 |> map String.from-code-point |> join '' |> Buffer _, \base64 |> (.to-string!) |> console.log
Well done!

Flag: IW{N0_0ne_can_st0p_y0u}

misc90

こんな画像が与えられる。

f:id:hakatashi:20160201143233j:plain

この時点で既に殺意しか湧かない。

Photoshopでぐりぐりいじって元のバーコードを復元する。

f:id:hakatashi:20160222223511j:plain

スマホバーコードリーダーで読み取ると、上から順に C0d3s}, _B4r_, IW{Bar となる。

Flag: IW{Bar_B4r_C0d3s}

web80

こんな文章とURLが与えられる。

I stumbled across this kinda oldskool blog. I bet it is unhackable, I mean, there's only static HTML.

https://0ldsk00lblog.ctf.internetwache.org/

static HTML と言われたら .git を確認するしかない。 https://0ldsk00lblog.ctf.internetwache.org/.git/config にアクセスすると、

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true

と表示されビンゴ。dvcs-ripper でまるっと落としてくる。

コミットログを見てみるとこの通り。

$ git show HEAD
commit 8c46583a968da7955c13559693b3b8c5e5d5f510
Author: Sebastian Gehaxelt <github@gehaxelt.in>
Date:   Fri Jan 22 02:58:01 2016 +0100

    My recent blogpost

diff --git a/index.html b/index.html
index 5508adb..25a3f35 100644
--- a/index.html
+++ b/index.html
@@ -3,9 +3,15 @@
        <title>0ldsk00l</title>
 </head>
 <body>
-       <h2>2000</h2>
+
+       <h1>Welcome to my 0ldsk00l blog.</h1>
+       <p>
+               Now this is some oldskool classic shit. Writing your blog manually without all this crappy bling-bling CSS / JS stuff.
+       </p>
+
+       <h2>2016</h2>
        <p>
-               Oh, did I say that I like kittens? I like flags, too: IW{G1T_1S_4W3SOME}
+               It's 2016 now and I need to somehow keep track of my changes to this document as it grows and grows. All people are talking about a tool called 'Git'. I think I might give this a try.
        </p>

        <h2>1990-2015</h2>

Flag: IW{G1T_1S_4W3SOME}

cry60

こんな公開鍵が3つと、

-----BEGIN PUBLIC KEY-----
MDgwDQYJKoZIhvcNAQEBBQADJwAwJAIdDVZLl4+dIzUElY7ti3RDcyge0UGLKfHs
+oCT2M8CAwEAAQ==
-----END PUBLIC KEY-----

こんな暗号文が与えられる。

DK9dt2MTybMqRz/N2RUMq2qauvqFIOnQ89mLjXY=

AK/WPYsK5ECFsupuW98bCFKYUApgrQ6LTcm3KxY=

CiLSeTUCCKkyNf8NVnifGKKS2FJ7VnWKnEdygXY=

公開鍵がえらく短い。中身を見てみると、

$ openssl pkey -in bob.pub -pubin -text
-----BEGIN PUBLIC KEY-----
MDgwDQYJKoZIhvcNAQEBBQADJwAwJAIdDVZLl4+dIzUElY7ti3RDcyge0UGLKfHs
+oCT2M8CAwEAAQ==
-----END PUBLIC KEY-----
Public-Key: (228 bit)
Modulus:
    0d:56:4b:97:8f:9d:23:35:04:95:8e:ed:8b:74:43:
    73:28:1e:d1:41:8b:29:f1:ec:fa:80:93:d8:cf
Exponent: 65537 (0x10001)

鍵長 228bit である。これなら変なテクニックを使わずとも力技で因数分解できる。

$ sage
┌────────────────────────────────────────────────────────────────────┐
│ SageMath Version 7.0, Release Date: 2016-01-19                     │
│ Type "notebook()" for the browser-based notebook interface.        │
│ Type "help()" for help.                                            │
└────────────────────────────────────────────────────────────────────┘
WARNING: Attempting to work in a virtualenv. If you encounter problems, please install IPython inside the virtualenv.
sage: factor(0x0d564b978f9d233504958eed8b744373281ed1418b29f1ecfa8093d8cf)
17963604736595708916714953362445519 * 20016431322579245244930631426505729
sage: e = 0x10001
sage: p = 17963604736595708916714953362445519
sage: q = 20016431322579245244930631426505729
sage: from base64 import b64decode
sage: c = int(b64decode('DK9dt2MTybMqRz/N2RUMq2qauvqFIOnQ89mLjXY=').encode('hex'), 16)
sage: d = inverse_mod(e, (p - 1) * (q - 1))
sage: m = pow(c, d, p * q)
sage: ('0' + format(int(m), 'x')).decode('hex')
'\x02\x99\xa0\xc1\xe2I\x90~\x87z\xc9\xc0\x88\xda\xaf8\xd0\x00IW{WEAK_R\n'

フラグの一部が見える。同じようにbob2.pubとbob3.pubも因数分解して復号したが、bob.pubと違ってまともな文字列にならない。これでしばらく悩んだが、あれこれ試してみたところ、どうもbob2.pubが3番目の暗号文に、bob3.pubが2番目の暗号文に対応してるようだった。なんじゃそりゃ。

2番目と3番目の復号後の文字列は以下のとおり。

'\x02\xa1\x06\xc7\x8c\xeaa\x90\x9aNyj\xc0\xfaVa\x00SA_K3YS_4R\n'
'\x02o\x03\x0e\xc9ba\x8e\xf65\x99\xbe\xe7\x80\x1a\xe3\x003_SO_BAD!}\n'

Flag: IW{WEAK_RSA_K3YS_4R3_SO_BAD!}

cry80

謎の踊る男のPV動画が与えられる。

とりあえず中身を見てみる。

$ ffprobe song.webm
ffprobe version 2.5.2 Copyright (c) 2007-2014 the FFmpeg developers
  built on Dec 30 2014 17:29:04 with gcc 4.9.2 (GCC)
  configuration: --disable-static --enable-shared --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-iconv --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libfreetype --enable-libgme --enable-libgsm --enable-libilbc --enable-libmodplug --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx264 --enable-libx265 --enable-libxavs --enable-libxvid --enable-lzma --enable-decklink --enable-zlib
  libavutil      54. 15.100 / 54. 15.100
  libavcodec     56. 13.100 / 56. 13.100
  libavformat    56. 15.102 / 56. 15.102
  libavdevice    56.  3.100 / 56.  3.100
  libavfilter     5.  2.103 /  5.  2.103
  libswscale      3.  1.101 /  3.  1.101
  libswresample   1.  1.100 /  1.  1.100
  libpostproc    53.  3.100 / 53.  3.100
Input #0, matroska,webm, from 'song.webm':
  Metadata:
    encoder         : Lavf56.40.101
  Duration: 00:00:36.04, start: 0.000000, bitrate: 520 kb/s
    Stream #0:0: Video: vp8, yuv420p, 320x240, SAR 1:1 DAR 4:3, 1k fps, 30 tbr, 1k tbn, 1k tbc (default)
    Stream #0:1: Audio: vorbis, 44100 Hz, stereo, fltp (default)
    Stream #0:2: Audio: vorbis, 8000 Hz, mono, fltp

副音声があるので取り出して聞いてみる。

$ ffmpeg -i song.webm -map 0:2 out.wav
ffmpeg version N-50911-g9efcfbe Copyright (c) 2000-2013 the FFmpeg developers
  built on Mar 13 2013 21:26:48 with gcc 4.7.2 (GCC)
  configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-avisynth --enable-bzlib --enable-fontconfig --enable-frei0r --enable-gnutls --enable-libass --enable-libbluray --enable-libcaca --enable-libfreetype --enable-libgsm --enable-libilbc --enable-libmp3lame --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libopus --enable-librtmp --enable-libschroedinger --enable-libsoxr --enable-libspeex --enable-libtheora --enable-libtwolame --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib
  libavutil      52. 19.100 / 52. 19.100
  libavcodec     55.  0.100 / 55.  0.100
  libavformat    55.  0.100 / 55.  0.100
  libavdevice    54.  4.100 / 54.  4.100
  libavfilter     3. 45.103 /  3. 45.103
  libswscale      2.  2.100 /  2.  2.100
  libswresample   0. 17.102 /  0. 17.102
  libpostproc    52.  2.100 / 52.  2.100
Input #0, matroska,webm, from 'song.webm':
  Duration: 00:00:36.04, start: 0.000000, bitrate: 520 kb/s
    Stream #0:0: Video: vp8, yuv420p, 320x240, SAR 1:1 DAR 4:3, 1k fps, 1k tbr, 1k tbn, 1k tbc (default)
    Stream #0:1: Audio: vorbis, 44100 Hz, stereo, fltp (default)
    Stream #0:2: Audio: vorbis, 8000 Hz, mono, fltp
Output #0, wav, to 'out.wav':
  Metadata:
    ISFT            : Lavf55.0.100
    Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 8000 Hz, mono, s16, 128 kb/s
Stream mapping:
  Stream #0:2 -> #0:0 (vorbis -> pcm_s16le)
Press [q] to stop, [?] for help
size=     560kB time=00:00:35.84 bitrate= 127.9kbits/s
video:0kB audio:560kB subtitle:0 global headers:0kB muxing overhead 0.013963%

ダイヤル音が聞こえる。DTMFである。Audacityでスペクトログラムを見ながら元の番号に復号する。

f:id:hakatashi:20160222233339p:plain

軽く苦行だ。元の番号に戻すとこうなる。

0111 0127 0173 0104 0122 060 0116 063 0123 0137 0127 061 0124 0110 0137 0120 0110 060 0116 063 0123 0175

また8進数だ。8進数としてデコードしたあとASCIIコードとして復号する。

IW{DR0N3S_W1TH_PH0N3S}

思うにこれはcryptoではなくstegoではないだろうか。

スクリプト

$ lsc -d
ls> '0111 0127 0173 0104 0122 060 0116 063 0123 0137 0127 061 0124 0110 0137 0120 0110 060 0116 063 0123 0175' |> split ' ' |> map parse-int _, 8 |> map String.from-code-point |> join ''
'IW{DR0N3S_W1TH_PH0N3S}'

misc60

こんな感じのテキストファイルが降ってくる。

4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI
4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI4paI
4paI4paI4paI4paI4paI4paI4paI4paICuKWiOKWiCAgICAgICAgICAgICAg4paI4paIICDiloji
loggIOKWiOKWiCAg4paI4paIICAgICAgICAgICAgICDilojilogK4paI4paIICDilojilojiloji
lojilojilojilojilojilojiloggIOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiOKWiCAg4paI
4paIICDilojilojilojilojilojilojilojilojilojiloggIOKWiOKWiArilojiloggIOKWiOKW
iCAgICAgIOKWiOKWiCAg4paI4paIICDilojilojilojiloggICAg4paI4paIICDilojiloggICAg
ICDilojiloggIOKWiOKWiArilojiloggIOKWiOKWiCAgICAgIOKWiOKWiCAg4paI4paI4paI4paI
4paI4paI4paI4paI4paI4paIICDilojiloggIOKWiOKWiCAgICAgIOKWiOKWiCAg4paI4paICuKW
iOKWiCAg4paI4paIICAgICAg4paI4paIICDilojiloggIOKWiOKWiOKWiOKWiCAg4paI4paI4paI
(略)

Base64としてデコードするとQRコードになる。

f:id:hakatashi:20160222234201p:plain

アナログな方法だが、これを一枚ずつ根気よくスマホバーコードリーダーで読み取っていく。するとこうなる。

Flagis:IW{QR_C0DES_RUL3}

スクリプト

$ lsc -d
ls> require \fs .read-file-sync \README.txt |> (.to-string!) |> split '\n' |> map(-> if it.length is 76 then it else it + ',') |> join '' |> split ',' |> map Buffer _, \base64 |> map (.to-string!) |> each console.log
██████████████████████████████████████████████
██              ██  ██  ██  ██              ██
██  ██████████  ██████████  ██  ██████████  ██
██  ██      ██  ██  ████    ██  ██      ██  ██
██  ██      ██  ██████████  ██  ██      ██  ██
██  ██      ██  ██  ████  ████  ██      ██  ██
██  ██████████  ████    ██  ██  ██████████  ██
(略)