LoginSignup
1
1

More than 5 years have passed since last update.

ksnctf 21 Perfect Cipher 200pt

Last updated at Posted at 2019-01-14

問題

image.png

解いてみた

問題文を翻訳してみます。

image.png

暗号に関する説明ですね。

image.png

zipファイルをダウンロードして、解凍すると以下のファイルが保存されていました。

image.png

pcapじゃないけどWiresharkに紐づいてるファイルが2つあったので読み込ませてみるとエラーになりました。

image.png

pcap以外よく知りませんが、一応encというファイルも使用できるようです。

image.png

まぁ今回はたまたま拡張子が一緒だったというだけのことだと思います。

encrypt.cppを見てみると、main関数があったので、こっちがメインのプログラムだと推測されます。
main中を見てみると

image.png

と書かれています。
encrypt.keyを使ってencrypt.cppを暗号化したものがencrypt.encと推測できます。
flagの方も一緒ですね。

たぶん最終的にやりたいこととしてはflag.jpgを作れば答えが書いてあるんだと思います。

encrypt関数を見てみると以下のような感じでしょうか。

  • encrypt.cppを読み込む
  • encrypt.cppのバイト数を先頭4バイトを使ってencrypt.encに書き込む
  • 乱数を生成する
  • 生成した乱数とencrypt.cppをxorする
  • 生成した乱数をencrypt.keyに書き込み、xorした結果をencrypt.encに書き込む

xorの性質を確認しておきます。

A xor B = C のとき
B xor C = A
C xor A = Bがなりたつ

xorする順番は逆でもなりたつ。

なのでまとめると

encrypt.cpp xor encrypt.key = encrypt.enc
ということをしているので、encrypt.keyを算出するには
encrypt.cpp xor encrypt.enc = encrypt.key
をすればいい

ということになります。
さっきの話だとencrypt.cppとencrypt.encのバイト数が4違うはずなので一応確認してみます。

image.png

あってるみたいです。
事前に先頭4バイトを削ってからxorします。
∵先頭4バイトにファイルサイズが書かれているため。

image.png

いい感じのkeyファイルができました。あってると信じます。

さて、ここから何をすればいいんでしょう。
一度立ち戻ってみます。

全体の流れとしては以下です。

  • encrypt.cppとencrypt.encからencrypt.keyを出す
  • encrypt.keyからflag.keyを出す
  • flag.keyとflag.encからflag.jpgを出す
  • flag.jpgに答えが書いてあるはず

今ようやく1つ目が終わったところです。
まだ2つ目かと思ったけど3番目はxorすればいいだけで4番目は画像ファイル見ればいいだけなので、実質2が最後の関門っぽい。

2をやるにあたって流れとしては乱数を予測するんだと思うんですよね。

例えば
1,2,3,4 とくれば次は5
1,2,4,8 とくれば次は16
みたいな。

main関数をもう一度見てみると

image.png

となっているので、flagを暗号化したflag.keyはencrypt.keyの続きを予測すればおのずと見えてくる的な。

2をやるには乱数生成のところを見るしかないです。
ここでもう一つのcppファイルmt19937ar.cppが出てきます。
乱数を生成しているファイルです。
開いてみると先頭にかなりコメントがあって、急造した感じではなかった。

image.png

一般に作られてそうなので検索してみます。

image.png

だそうです。乱数の世界は未知の領域です。

短所のところを見ると予測可能と書かれていました。

image.png

具体的な予測方法が書かれてなかったので、検索してみます。
Mersenne Twisterの出力を推測してみる - ももいろテクノロジー

すごい人がいるもんです。
624個ランダム数が与えられれば次から予測できるらしい。
ちなみにPythonのRandomもこれを使ってるみたいなので、Pythonの乱数も同じ方法で予測できるらしいです。
このサイトに書いてあったプログラムを使って、encrypt.keyの先頭から624個取得して、そこから続きを予測するように編集。

ちなみにflag.encは78560バイトでした。

image.png

先頭4バイトはflag.jpgのバイト数が書かれているので78560-4をした78556バイト必要。
78556バイトというのは乱数でいうと19639個の乱数が必要。
∵乱数は4バイトずつ使ってるので78556÷4=19639。

混乱してきました。まとめると

  • encrypt.keyの先頭から4バイトずつ624個取得するとそれ以降の乱数を予測できるようになる。
  • encrypt.keyは2600バイト。
  • 今2496バイト(4バイトずつ624個)は使ったので予測する最初の104バイト(2600-2496)はencrypt.keyの残りなので使わない。
  • その続きの78556バイト(19639個の乱数)をflag.keyとして保存する。

まとめたところでなんかよくわかりませんね。書き間違いとかありそうな気がしています。。。

まぁ上記プログラムを実行したところ、flag.keyができあがりました。

image.png

さて、これを使ってflag.encとflag.keyのXORを計算します。
flag.encは先頭4バイトを事前に削除しておきます。
そして実行してjpgファイルが作成できました。

image.png

まさかの失敗。。。
一応バイナリエディタで開いてみます。

image.png

まさかの画像ファイル開けないけど中に書いてあるパターン。

image.png

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