きゅうり。

主にCTF関係のことを書いていく気がします

HITCON CTF 2017 Secret Server writeup

elfやらcrypto+pwnやらと暗号担当でもバイナリ解析前提の時代がもう来てますね、といった印象でした。

そんな中でpythonが読めれば解けるSecret Server のwriteupです。

チーム内の勉強会で取り扱ってわかったんですが、道中ちょいちょい別解があるっぽいです。(最終的な求め方はないっぽいですが)

 

具体的な動作の説明については読めばわかるので飛ばします。

重要なのは以下の3点。

・暗号化の際のIVは既知

・復号の際のIVは任意に送れる

・unpad は脆弱(長さ判定、paddingの中身判定ともに無し)

 

ここまではよくある共通鍵暗号問題。

 

まずはじめに、Welcome!!の暗号文しか手に入らないため、IVを細工してget-flagを実行させます。

f:id:Kyuri:20171106144618p:plain

 これでフラグの暗号文を手に入れることができる。

同様にIVの細工をしてフラグの出だしを特定していくことを考える。

f:id:Kyuri:20171106145202p:plain

なお、get-flag が実行されたのか command not found となったのかどうかは暗号文の長さを見ることで判定ができる。

同様に、exit-here・get-sha256を利用することでフラグが3文字特定できる。

具体的には、hitcon{Pad までわかる。

(フラグからもパディングを利用していくことは想像できる)

 

さて、フラグの暗号文は3ブロックあるが、2ブロック目の最後1バイトを適当に変えてやると、復号結果の最終バイトすなわちunpadでの判定に利用されるバイトを変えることができる。

unpadの際にサイズ判定をしていないので、255バイト取り除くような状態でも動く。

これを利用してやると、get-sha256がギリギリ残って実行されるような範囲を調べることができる。

f:id:Kyuri:20171106145734p:plain

これをすると38通りの成功パターンが出てくる。

これらの値から、C3を復号直後の中間ブロックの最終バイトが計算でき、m3のパディングの値も計算ができる。(z3を使うとシュッと計算できる)

言葉で書くとわかりにくいが、なんとか図から読み取ってもらいたい。

 

この計算から、フラグは32文字でm3はすべてパディングのブロックであることが判明する。

 

パディングを利用して平文を任意の長さに削ることができるようになった。

そこで、get-sha256+1文字だけ残すようにC2の最終バイトを変えてやる。

すると、sha256の候補としては256通り(asciiなので本当はもっと少ない)しかない。

256通りの候補を手元で計算し、それぞれに対してget-flagとなるようなIVを計算して送ってやる。

f:id:Kyuri:20171106150501p:plain

もしget-flagとなったら、そのIVを計算するのに使ったsha256の元の平文がフラグの1文字となる。

これをget-sha256+n文字についてやっていくと、フラグの16文字目までが特定できる。

ただし、C2をいじるとフラグの2ブロック目が壊れてしまう。

そこで、適当にC4を追加してやり、C3をいじって同様のことを行うとフラグをすべて復元できる。

 

 

hitcon{Paddin9_15_ve3y_h4rd__!!}}

 

 

だれかSecret Server Revenge を教えてください