daily alpacahack twilight
はじめに
みなさん、Daily alpacahack楽しんでますか?
簡単な問題も難しい問題も含めて様々なものが用意されているので、是非楽しんで、新しいことを学んでいってください。ただ、苦しい時もあるかもしれませんがCTFはTry Harderの精神があるので、それもまた一興で楽しんでください。
問題
今回はreversingのtwilightという問題を解いていきます。
解説
添付してあるのは実行ファイルと出力されたであろうファイルです。
実行ファイルに関してはx86-64のアーキテクチャのようです。お手元にあるデコンパイラでデコンパイルして中を解析してみましょうという問題です。(私はidaで解析していきます。)

デコンパイル
デコンパイルした結果です。読みやすいように変数名を変えます。

変数名は、カーソルを合わせて右クリック→Rename lvarから行うことができます。(ショートカットはNです)
ここでは、以下を変更しています。
- v6をFUNCTIONS
- sをINPUT

様々な処理がありますが、重要なのは以下の点です。
- 11行目にあるscanfで32文字の入力を受け取り、INPUT変数に格納します。
- 12行目~13行目でFUNCTIONSに「a」、「b」の関数を格納しています。
- 14行目~18行目のfor文でループ処理をしています。(この時ループ回数を
iとしています。) - 16行目で、
INPUTのi番目とループ回数iを引数としてFUNCTIONSのi%2番目を実行しています。 - 16、17行目で、FUNCTIONSのi%2番目を実行した結果を
v3に格納して16進数で表示しています。

それでは、各関数を見ていきましょう
関数a
この関数はa1,a2の引数をとって足し算しているように見えます。
なので、読みやすくするために関数名の書き換えを実施します。(idaはカーソルを関数名に合わせてnで書き換えられます。)
書き換え前

書き換え後

関数b
この関数はa1,a2の引数をとって排他的論理和しているように見えます。
なので、読みやすくするために関数名の書き換えを実施します。(idaはカーソルを関数名に合わせてnで書き換えられます。)
書き換え前

書き換え後

再度mainへ
再度mainへ戻り(idaでは、funcionタブにあるmainやESCキーを押すことで戻れます)デコンパイル結果を見てみるとFUNCTIONSの関数名が先ほど書き換えた内容になり少しは読みやすくなっていると思います。

具体的には…?
ここから1ループだけ具体的な内容と共に追っていきます。
for文のiは0から始まるため、i=0として考えます。そうすると、16行目は以下のように見なすことができます。
v3 = FUNCTIONS[0](INPUT[0],0);
更に、FUNCTIONS[0]というのは12行目にあるようにadd関数なので書き換えることができます。
v3 = add(INPUT[0],0);
このことから出力の最初にある値は、flagの0番目とループ回数の0が足された値になることがわかります。この時、出力v3とループ回数が既知であることからINPUT[0]は逆算可能になることがわかります。
逆算してみよう
先の内容から、v3とループ回数が既知の状態でINPUT[i]を求めるような逆関数を考えればよさそうです。
以下がPythonで関数と逆関数を書いた結果です。一つ注意として、XORの逆関数はXORそのものなため新しく定義をしていません。
1 | def add(a1, a2): |
これらを使って、for文も含めてデコンパイル結果をPythonで表現すると、以下になります。
1 |
|
逆算するPythonコードは以下です。
1 | OUT = [0x41, 0x6D, 0x72, 0x62, 0x67, 0x64, 0x81, 0x46, 0x74, 0x79, 0x6B, 0x68, 0x6D, 0x45, 0x6F, 0x6C, 0x7B, 0x4E, 0x7B, 0x7D, 0x73, 0x42, 0x85, 0x79, 0x7C, 0x7C, 0x8C, 0x77, 0x7D, 0x73, 0x82, 0x62] |
最後に
この問題に対する解き方は様々な方法があると思います。今回は、これからのrevでよく使うであろうデコンパイラで解析してみようという問題にしました。(デコンパイラ使わなくてもできると思いますが…)
この小さいバイナリーを使って命名や各関数のチェックをする方法を学んでいただければ今後に生かすことができると考えていますので、是非デコンパイラを使って解いてみてください。ご参加いただき、ありがとうございました。