I made the most secure login page ever, obviously it's uncrackable if I used Wasm!
Webカテゴリの問題のはずが、wasmファイルを解析する問題だった。カテゴリの付け間違えではないかと思いつつ、静的解析をサボりにサボって解いたのが楽しかったので、メモを残しておく。
Google Chromeで与えられたURLにアクセスしてみると、以下のようなログインフォームが表示された。適当なユーザ名とパスワードを入力すると Login failed
と表示される。DevToolsのNetworkタブを開きつつ同じ作業をやってみても、どこにもリクエストは飛んでいない。全部ローカルでやってるっぽい。wasmを解析して正しいユーザ名とパスワードを当てる必要がありそう。
$web_sys::features::gen_HtmlTextAreaElement::HtmlTextAreaElement::value::…
のような関数名や、以下のようなファイル末尾にある文字列(Producers Section
というやつだろうか)から、Rustのコードをコンパイルしたものであろうと推測できる。真面目に静的解析するのは面倒くさそうだ。
strings
で怪しげな文字列がないか探してみると、それっぽいものが見つかった。ユーザ名は admin
で、その上にある2つの文字列がパスワードに関連するものだろう。一方はhexデコードすると73バイト、もう一方も73バイトということでペアで使いそう。これらをXORして過程をすっ飛ばしたくなる気持ちを抑えて、解析を進める。
$ strings index-9fa740b956e0b1c4_bg.wasm … bsrc/main.rs 1311061b2a000603173c0136001f050b112b1a0a0d2d0c070000090c130731173e121f04002d1037031a2f0e0d1c184b01251b1e010c1e52275f1c5e5e40390d533c0a00190d1c575b exclusive_disjunction_is_amazing_also_this_entire_string_might_be_relevant admin Login successful, here's your flag: D Login faileddivh1LoginformidusernameplaceholderUsernametypetext brpasswordPassword …
どこかにユーザが入力した認証情報と正解のものを比較しているような処理はないか。DevToolsのSourcesタブからwasmファイルを開き、strcmp
やら compare
やらそれっぽい関数名を検索する。$memcmp
という関数があった。ここにブレークポイントを置いておく。
ユーザ名に admin
を、パスワードに A
を入力して Login
ボタンを押してみると、$memcmp
で実行が止まった。引数である $var0
と $var1
に入っているのはメモリのアドレスだろう。
Module
→ memories
→ $memory
からMemory Inspectorを開く。
1179576
と 1048876
を見に行ってみると、いずれも admin
というバイト列を指していることがわかる。周囲にある文字列から推測するに、前者がユーザ入力で、後者が正解のユーザ名だろう。
このまま実行を再開するが、A
というバイト列のアドレスが引数として渡ってくることはなかった。おそらく、パスワードの長さをチェックして、もし正しい長さでなければ $memcmp
をそもそも呼ばないというような作りになっているのだろう。しらんけど。
さきほど strings
で手に入れた文字列から推測して、パスワードに A
を73回繰り返した文字列を入力した上でもう一度試してみる。今度は入力したパスワードとそれっぽい文字列を比較している様子が見られた。
ブレークポイントの設定を解除し、ユーザ名に admin
を、パスワードに view_source_super_secret_admin_password_jipkchq9dzhjsep5x2u964fo6cxeuhj65
を入力する。Login
ボタンを押すとフラグが表示された。
vsctf{w45m_i5_4w350m3_A8GiQVbn9f}