前提知識
- バイナリデータに関する導入知識
解説
ソースをチラッと見ると、与えられたキーを元にバイト列を生成している。
形式はimage/pngになっているので、先頭がPNGのヘッダーとなるように調整すれば良さそう。
バイナリデータの先頭は形式ごとに統一されていて、マジックナンバーが配置してある。
var bytes = []; // ここにエンコードされたデータが入る $.get("bytes", function(resp) { // jqueryの機能で、bytesファイルを取ってくる bytes = Array.from(resp.split(" "), x => Number(x)); // 空白で数が羅列されてるっぽい }); function assemble_png(u_in){ // u_inに入力データが入る var LEN = 16; var key = "0000000000000000"; // これがkeyらしい var shifter; if(u_in.length == LEN){ // 入力データの長さがLENならkeyとして採用しているので、16桁の数値が入力として必要 key = u_in; } var result = []; // resultデータ for(var i = 0; i < LEN; i++){ shifter = key.charCodeAt(i) - 48; // 48 -> '0'なので数に変換している for(var j = 0; j < (bytes.length / LEN); j ++){ result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i] // mod i毎に独立でshifter分だけシフトしている } } while(result[result.length-1] == 0){ // 末尾の0を消す処理(必要?) result = result.slice(0,result.length-1); } // base64に変換して入れる document.getElementById("Area").src = "data:image/png;base64," + btoa(String.fromCharCode.apply(null, new Uint8Array(result))); return false; }
こんな感じなので、とりあえずkeyが全部0のshiftしないやつを取ってきて、"bytes"の中身を得る。
0 | cc b6 5b c6 4a 42 3c fb d9 a3 00 00 00 ff b7 5b 1 | 52 b5 27 3f ad 0a ff 66 00 fb 00 0d 00 de 83 7f 2 | f7 9b 7f 2f 4b 00 5b f7 00 b6 9c 00 49 00 40 e3 3 | 49 e3 4e 75 e5 49 43 76 01 78 e8 ed 00 00 cd 00 4 | 89 45 4e b9 81 0c 54 82 54 2b b2 a3 9a 48 ff 00 5 | 00 50 01 b1 ae 01 d9 0a 21 00 2d 90 c8 c0 78 52 6 | a4 00 00 af 0d 54 ed 72 60 00 37 1e 64 4d 78 6c 7 | 30 00 85 02 00 9f 60 41 b6 00 80 de 14 37 00 dc 8 | 33 10 28 44 8f 90 1a 94 e3 78 20 91 78 bb 00 72 9 | 0c e9 3c 47 8b 99 01 d9 8c 07 8c 68 e4 55 44 99
こう出てくる。
ここを参考にPNGのフォーマットを確認する。
以下は全て16進数で書いてある。
- 先頭8バイト、ファイルシグネチャ
89 50 4E 47 0D 0A 1A 0A
- 次の4バイト、IHDRチャンクの長さ
00 00 00 0d
- 次の4バイト、IHDRチャンクの種類
49 48 44 52
- 次の4バイト、画像の幅
- 次の4バイト、画像の高さ
- 次の1バイト、ビット深度
01
or02
or04
or08
or10
- 次の1バイト、カラータイプ
00
or02
or03
or04
or06
- 次の1バイト、圧縮手法
- 次の1バイト、フィルター手法
- 次の1バイト、インターレース手法
まず先頭16バイトで複数の可能性を考えると、以下のようなスライドでないとダメ。
45396185 15012495 4 261 7
さて、画像の幅を考えると、3番目は4だろう。
カラータイプを考えると、10番目で7はありえない。
45496185 15012495 261
ここまで来れば8通りなので、全探索して答えを探す。
結局でseleniumで自動化してスクリーンショット撮ったから別に絞らなくても良かった。
「4549618526012495」が答え。QRコードが出てくるので、参照するとフラグ。