2016年4月のコミットまとめ
hakatashi (Koki Takahashi) · GitHub
今月はだいぶプルリクを送った。
主な成果
Sugoi Converter をアップデート
1.6.6 から 1.7.2 になった。新機能は以下のとおり。
- NFCおよびNFKCの変換を実装
- Node.js v6 のリリースにともなって
new Buffer()
をコードから駆逐。これがかなり手間取った。なんとDefinitelyTypedのNode定義にBuffer.from
が定義されていなかったり、BrowserifyのBufferにBuffer.from
が実装されていなかったり(これはすぐ解消されたが)であちこち奔走する羽目になった。 - HTTPからHTTPSに強制リダイレクト
npmモジュール“textlint-rule-blacklist-ja”を製作開始
「NGワードでフィルタリングする汎用textlintルール」の予定。
テストにmochifyを使っているのだが、トークナイザであるkuromoji.jsとの相性が悪くて実装が進んでいない。いちおう解決するためのプルリクをmochifyに投げたが、音沙汰なしである。
2016年3月のコミットまとめ
hakatashi (Koki Takahashi) · GitHub
主な成果
Sugoi Converter をアップデート
1.4.9 から 1.6.6 になった。新機能は以下のとおり。
npmモジュール“mona-width”を公開
与えられた文字のMSPゴシックにおける幅を返すモジュール。
README書かなきゃ……
npmモジュール“power-ascii”を製作開始
GitHub - hakatashi/power-ascii: Powerful ASCII Characters
進捗ダメです
Internetwache CTF 2016 writeup
TSG (東京大学理論科学グループ) のメンバーに誘われたので、2月20日から22日にかけて、チームTSGの一員として Internetwache CTF 2016 に参加した。
参加して初めて知ったがどうやらガチ初心者向けのCTFであるらしく(CSAWよりも簡単な印象)、メンバーがほいほい解いていくので僕の出番はほとんどなかったと言っていい。が、この広いインターネットで誰かの役に立つかもしれないので、いちおう一通りWriteupを書いてみる。
すでに書かれた他のメンバーのWriteupは以下を参照。
ちなみにチーム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
こんな画像が与えられる。
この時点で既に殺意しか湧かない。
Photoshopでぐりぐりいじって元のバーコードを復元する。
スマホのバーコードリーダーで読み取ると、上から順に 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でスペクトログラムを見ながら元の番号に復号する。
軽く苦行だ。元の番号に戻すとこうなる。
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 (略)
アナログな方法だが、これを一枚ずつ根気よくスマホのバーコードリーダーで読み取っていく。するとこうなる。
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 ██████████████████████████████████████████████ ██ ██ ██ ██ ██ ██ ██ ██████████ ██████████ ██ ██████████ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██ ██████████ ██ ██ ██ ██ ██ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██████████ ████ ██ ██ ██████████ ██ (略)
2016年1月のコミットまとめ
https://github.com/hakatashi?tab=contributions&from=2016-01-01&to=2016-01-31
主な成果
npmモジュール“chars”の2.0.0をリリース
JavaScriptの文字列を““““正しく””””文字に分割するnpmモジュール、charsの2.0.0をリリースした。
詳しくはまた別エントリで。
npmモジュール“general-category”の1.0.0をリリース
与えられた文字からUnicodeのGeneral_Categoryプロパティを判別する簡単なnpmモジュール、general-categoryの1.0.0をリリースした。
こういうしょうもないモジュールを小出しにしていきたい。
greenkeeperを導入し、各種JavaScriptライブラリの依存関係を最新に更新
上のリンクを詳しく精査してもらうとわかるが、実は1月のコミットのうちほとんどがマージコミットである。これはgreenkeeperというサービスを導入してみたことによるもので、依存しているnpmモジュールのバージョンを常に最新に保ってくれるというユニークなサービスである。
下のQiitaの記事で知った。説明もここに解りやすく書いてある。
一ヶ月近く使ってみての感想だが、なかなか良い。依存ライブラリのアップデートがあるたびにPRを送ってくれるので通知で気付けるし、CIと連携してpatchバージョンのアップデートでも試しにコミットしてビルドを実行してくれるので、依存ライブラリのアップデートがビルドを壊したことにも気付けるようになっている。これでよりカジュアルにdependencyを追加してatomicityの高いモジュールを作りやすくなると思われる。
難点が一つ。このgreenkeeperのbotはnpmのサーバーと密につながっていて、アップデートがあれば即座にプルリクを送ってくれるのだが、どうもnpmのサーバーとの間にラグがあるらしく、CI側でライブラリのアップデートに失敗して「ビルドを壊した」と誤判定されることが多々ある。Travis-CIであればビルドを再実行すればよいのだが、この部分の精度はもう少し上がってほしい。
技術ブログはじめました
hakatashi.github.io や blog.hakatashi.com は無かったことになりました。南無八幡。
技術ってなんだろう。