ChogeLog

主にセキュリティ関係の記録やWrite-up。たまーに日記も。

#24 Rights out (Write-up)

問題

ksnctf.sweetduet.info

exeファイルが配布されている。
とりあえず実行すると以下のようなパズルゲームが表示される。

これはライツアウトというパズルで、クリックしたボタンとその上下左右が反転する。全てのボタンを反転させることができればクリアとなる。

このパズル自体は知っていたが、「ライツアウト」という名前は初めて知った。
とりあえず攻略サイトを見つつ解いてみたが、お祝いされるだけだった。

問題にも書かれているが、ただ解くだけではダメらしい。

解法

ここから解析作業に入る。
まずはstringsコマンドを実行してみるが、特に情報は得られなかった。
binwalkとかも実行してみたが特に収穫なし。

次にghidraで解析してみるが、デコンパイルに失敗しているっぽい…。

色々調べてみると、元のコードはC#で書かれているっぽい。
ということでILSpyを使ってリバエンしてみる。
ILSpyでexeを開くとあっさりとデコンパイルが完了した。

コードを読んでいくと、checkメソッドでFLAGを表示するか否かの判定を行っていることが分かった。

ざっくりと読むと、全てのボタンを反転させた場合に「Congratulations!」というメッセージが表示され、さらにとある条件も満たしている場合だけフラグを表示するようになっているらしい。
このif(flag)以降のコードを実行させてフラグを取得するのもいいが、正攻法で解きたいので条件を調べてみる。

上記のコードをよく読むと、フラグを表示させる条件はhist[i] == array[i]の場合らしい。
array配列の中身は「1, 7, 16, 11, 14, 19, 20, 18」に設定されている。
hist配列のサイズは8に設定されており、中身は下記のbutton_Clickメソッドで設定されるようになっている。

上記のコードを読むと、hist配列は直近の8回分のボタンクリックの情報を保存しているらしい。
以上のことから、hist[i] == array[i]を満たすには、直近8回にクリックしたボタンが「1, 7, 16, 11, 14, 19, 20, 18」の順番である必要がある。さらにこの順番でボタンをクリックしたタイミングで全てのボタンを反転させておく必要もある。
ちなみにボタンNoについては、左上から右に数えていく。(だからボタンに「→」の文字が書かれているっぽい)

これで条件が判明したので、あとは実際にパズルを解いていく。
まずは全てのボタンを反転させる。

その後、ボタンNoが「1, 7, 16, 11, 14, 19, 20, 18」の順番で押していく。
このとき、左上のNoは0であることに注意!(ボタンNo.1は一番上の左から2番目になる)

その後、再び「1, 7, 16, 11, 14, 19, 20, 18」の順番で押していく。同じ場所を2回押すと元の形に戻るため、これで全てのボタンが反転される。
これでフラグが表示された。

所感

100ptの問題なのでそんなに難しくはなかった。ghidraでデコンパイルできなかったところで苦戦したが…。
簡単なリバーシングは解けるようになった気がする。
「ライツアウト」という単語は初めて知った。正しくは「Lights out」なのね。