2022-01-13 · 2분
専用レジスタ
CPU の専用レジスタ — アキュムレータ、プログラムカウンタ、命令レジスタ、MAR、MBR、状態・データ・アドレスレジスタ — とユーザー可視/不可視の区分に関する学習ノート。
2021-07-14 · 4분
この記事は公開から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/
使用したプログラム: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" を比較しているのが分かります。
使用したプログラム: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" であることが確認できます。
使用したプログラム: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"
使用したプログラム: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 の協力で作成されました。
…