2021-07-14 · 4

rev-basic 0~3 write-up

securityreversing

この記事は公開から2年以上経過しています。

rev-basic-0~3 write up

もっと見る

https://dreamhack.io/wargame/challenges/14/

https://dreamhack.io/wargame/challenges/15/

https://dreamhack.io/wargame/challenges/16/

https://dreamhack.io/wargame/challenges/17/


rev-basic-0 write up

使用したプログラム:radare2, ida7.2

main をアセンブリで見たとき、'Correct' と書かれた構文のすぐ上に 'test eax, eax' があります。

x86 アセンブリ言語で TEST 命令は、2 つのオペランドに対するビット演算である AND を行う。ならば eax 値を返すすぐ上の "call section..text" という所を分析する必要があります。

section..text のアセンブリは次のとおりです。一目で "Compar3_the_str1ng" が答えだと分かります。

IDA でデコンパイルしてみます。

次のとおりで、if 文で真になるには "sub_140001000" の返りが 0 でない数が返ればよいです。

"sub_140001000" をデコンパイルすると、a1(ユーザーの入力)と "Compar3_the_str1ng" を比較しているのが分かります。


rev-basic-1 write up

使用したプログラム:radare2, ida7.2

どこかで見たアセンブリコードのようだ。0 と main は同じなので、0 と同様に "section..text" を分析してみます。

上のように、続けて何らかの数字と比較しているのが分かります。その数字の大きさを見ると ASCII コードのようです。

Python や手で直接やってもよいですが、私たちは IDA を使ってみましょう。

"section..text" のデコンパイルです。IDA で ASCII コードにマウスを乗せて "r" を押すと Char 形式に変わります。また "h" を押すと int と hex 形式にも変えられます。上のような機能を通じて rev-basic-1 のフラグを突き止めました。

"Compar3_the_ch4ract3r" であることが確認できます。


rev-basic-2 write up

使用したプログラム:radare2, ida7.2

main は同じですね。同様に section..text を分析してみましょう。

うーん.... あそこにフラグが見える気もしますが、それでも分析すると、

rsp はスタックポインタレジスタです。つまり 0x18 分のスタックが生成されます。jmp で移動するのですが、次を

0x14000101e      4883f812       cmp rax, 0x12              ; 18
0x140001022      7324           jae 0x140001048

見ると 0x12(18) 回繰り返すようです。繰り返し文ですね。

次のアセンブリを読み続けると、4 バイト単位で間を空けて比較しているのが分かります。比較する配列は

"lea rcx, qword str.Comp4re_the_arr4y" ここのようです。確認すると

上のように 4 バイト空いたフラグが見えます。これも IDA で確認すると

私たちが分析したとおり 0x12(18) 回繰り返し、4 バイトずつ比較しているのが確認できます。aC の配列を確認すると

フラグが存在するのが見えます。"Comp4re_the_arr4y"


rev-basic-3 write up

使用したプログラム:radare2, ida7.2, python3

またメインは同じなので飛ばして "section..text" を分析します。

これも前の問題と同様に

0x14000101e      4883f818       cmp rax, 0x18              ; 24
0x140001022      732f           jae 0x140001053

繰り返し文があるのが分かり、繰り返し文の条件を i とすると、

0x14000102f      movzx eax, byte [rcx + rax] //eax = [rcx = 比較する文字列 + rax = [rsp] スタックポインタ]
0x140001033      movsxd rcx, dword [rsp] //rcx = [[rsp] スタックポインタ]
0x140001037      mov rdx, qword [arg_8h] //rdx = [ユーザー入力]
0x14000103c      movzx ecx, byte [rdx + rcx] //ecx = [ユーザー入力 + rcx : ここでは繰り返しの i 値]
0x140001040      xor ecx, dword [rsp] //ecx ^ rsp : (ユーザー入力 + i) と i を xor 演算する。
0x140001043      mov edx, dword [rsp] //edx = rsp : edx に i 値を入れる
0x140001046      lea ecx, dword [rcx + rdx*2] //ecx = rcx + rdx*2 : rcx = xor 演算した値 + rdx = i 値 * 2
0x140001049      cmp eax, ecx //eax と ecx を比較 : フラグと (rcx = xor 演算した値 + rdx = i 値 * 2) を比較

("str.I_gtcgBf"[i]) == ((*input[i]) ^ i) + i * 2

このように比較しているようです。これをやるのは面倒くさすぎます...

rdx, edx などが紛らわしければ [ハッキング] - [ハッキング] レジスタを見てください。

とにかくこう予想したので Python コードで書いてもよいですが、IDA で一度確認してみます。

なんだか違うように見えますが、私たちが予測したものと同じです!!!ならば演算を Python で書いてみましょうか?

values = [0x49, 0x60, 0x67, 0x74, 0x63, 0x67, 0x42, 0x66, 
        0x80, 0x78, 0x69, 0x69, 0x7b, 0x99, 0x6d, 0x88, 0x68,
        0x94, 0x9f, 0x8d, 0x4d, 0xa5, 0x9d, 0x45]

for i in range(0, len(values)):
    print(chr((values[i] - 2 * i) ^ i), end='')

((*input[i]) ^ i) + i * 2 の式を逆算して (input[i] - i * 2) ^ i で計算しました。

フラグ:"I_am_X0_xo_Xor_eXcit1ng"


原文(韓国語): tistory — 2021-07-14 公開、当ブログへ移行。この翻訳は AI の協力で作成されました。

コメント

コメントを削除しますか?

関連記事

rev-basic 0~3 write-up · 나봄하랑