[TryHackMe] Advent of Cyber 2, Day 17 - Walkthrough -


本稿では、TryHackMeにて提供されている「Advent of Cyber 2」ルームに関する攻略方法(Walkthrough)について検証します。
「Advent of Cyber 2」は「free room」(無料)で提供されています。購読を必要とせずに仮想マシンを「展開(Deploy)」することができます。

『Advent of Cyber 2』のWalkthroughインデックスを「[TryHackMe] Advent of Cyber 2に参加してみた」にて公開しました。

[Day 17] Reverse Engineering: ReverseELFneering

ストーリー

エルフ・McSkidyは低レベルの言語に触れたことがありません。 - これはクリスマスモンスターを倒すために彼らが学ばなければならないことです。

radare2は、バイナリのリバースエンジニアリングと分析のためのフレームワークです。バイナリを逆アセンブルし(マシンコードを実際に読み取り可能なアセンブリに変換し)、バイナリをデバッグする(ユーザーが実行をステップ実行してプログラムの状態を表示できるようにする)ために使用できます。

rahash2コマンドにて調査対象のファイルchallenge1について調べてみます。

$ ls -l challenge1 
-rwxr-xr-x 1 501 dialout 844648 Dec 17 19:46 challenge1
$ rahash2 -amd5 challenge1 
challenge1: 0x00000000-0x000ce367 md5: 702022338bfaa1bc23c325fd1e747d10
$ rahash2 -asha256 challenge1 
challenge1: 0x00000000-0x000ce367 sha256: 4507ad08b6ed1d5f3ef2a2e3f4a1064d0b8425cccb50ac8c28da8435a9d0f9e5

radare2の起動

引数に解析したいプログラムのファイル名challenge1を指定して、radare2を起動します。
dスイッチをつけることで、デバッグモードradare shellで起動することが可能です。

$ r2 -d challenge1 
Process with PID 3340 started...
= attach 3340 3340
bin.baddr 0x00400000
Using 0x400000
asm.bits 64
Warning: r_bin_file_hash: file exceeds bin.hashlimit
[0x00400a30]>

基本情報

バイナリの情報を調べたい場合、iIコマンド(Binary info)で表示できます。
radare2は「1文字 <-> 1命令」となっています。各々の文字に意味づけが行われています。各コマンドの末尾に?を付けることでコマンドのヘルプを参照できます。

[0x00400a30]> iI
arch     x86
baddr    0x400000
binsz    842534
bintype  elf
bits     64
canary   true
class    ELF64
compiler GCC: (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
crypto   false
endian   little
havecode true
laddr    0x0
lang     c
linenum  true
lsyms    true
machine  AMD x86-64 architecture
maxopsz  16
minopsz  1
nx       true
os       linux
pcalign  0
pic      false
relocs   true
rpath    NONE
sanitiz  false
static   true
stripped false
subsys   linux
va       true

bintypeclassosの各フィールドから、challenge1ファイルがLinuxで動作する32ビットの実行可能なELFファイルであることを示しています。
archbitsendianmachineの各フィールドから、そのファイルがx86コードでビルドされたことを示しています。
さらに、langフィールドから、ファイルがC言語からコンパイルされたことを示します。
これらの情報は、逆アセンブルやデバッグの際における前提情報として役立ちます。

解析

解析の依頼

バイナリが開いたら、最初にradare2に対して解析を依頼する必要があります。そのコマンドはa(nalyze)コマンドです。関数部のフラグを特定し、Visual Mode上で解析していきます。
最低限の解析であれば、aa(analyze all)を使用します。aaaaaaaとオプションを増やすことで解析の程度を広げていくことが可能です。
自動的に解析を行いたい場合には、radare2起動時に引数として-Aあるいは-AAを指定する方法もあります。

$ r2 -d -AA challenge1 
Process with PID 3512 started...
= attach 3512 3512
bin.baddr 0x00400000
Using 0x400000
asm.bits 64
Warning: r_bin_file_hash: file exceeds bin.hashlimit
[Invalid address from 0x004843acith sym. and entry0 (aa)
Invalid address from 0x0044efc6
[x] Analyze all flags starting with sym. and entry0 (aa)

関数名の調査

自動解析(aa,aaaなど)で取得した関数のリスト(list)をaflall function list)にて表示させることが可能です。
ほとんどの実行可能プログラムには、mainという名前のエントリポイントがあります。
ここでは、grepにてaflの実行結果からmainとして定義されたエントリポイントのみをフィルタリングします。

カレントアドレスの移動

main関数へ移動する場合にはseek)コマンドを使います。

[0x00400c81]> afl | grep main
0x00400de0  114 1657         sym.__libc_start_main
0x0048fa40   16 247  -> 237  sym._nl_unload_domain
0x00403ae0  308 5366 -> 5301 sym._nl_load_domain
0x00470430    1 49           sym._IO_switch_to_main_wget_area
0x00403840   39 672  -> 640  sym._nl_find_domain
0x00400b4d    1 35           main
0x0048f9f0    7 73   -> 69   sym._nl_finddomain_subfreeres
0x0044ce10    1 8            sym._dl_get_dl_main_map
0x00415ef0    1 43           sym._IO_switch_to_main_get_area
[0x00400c81]> s main
[0x00400b4d]> 

自動解析にてmain関数は(0x00400b4d 1 35 main)と特定できました。
ここで、プロンプトに注目してください。現在のアドレス([0x00400c81])からs mainにて[0x00400b4d]へ移動することができました。

グラフビュー表示

VVコマンドを使用すると、現在のアドレスを開始地点としてグラフビュー(Visual Mode)を表示することができます。

[0x00400b4d]> VV

この画面ではvimと同様にhjklで上下左右に移動することができます。
qキーでradare shellに戻ったり、:キーで一時的にradare shellを使用することが可能です。

逆アセンブル

逆アセンブルの結果を表示するには、p(rint)出力とdf(disassemble function)を組み合わせます。
ここでは、main関数を対象としています。

ここに表示されているのは、main関数のアセンブリ命令です。これよりデバッグツールを使用してインストラクションを解読していきます。

インストラクションの解読

まず、main関数に格納されている変数が3つ確認できます。

; var int64_t var_ch @ rbp-0xc
; var int64_t var_8h @ rbp-0x8
; var int64_t var_4h @ rbp-0x4

Day 17 - #1.

What is the value of local_ch when its corresponding movl instruction is called (first if multiple)?

最初のmovl命令に対する変数local_chの値について問われています。問われている箇所を抜粋しました。

0x00400b5f      8b45f4         mov eax, dword [var_ch]

ブレイクポイントの設定

radare shell画面にてdb(debug breakpoint)で設定することが可能です。
0x00400b5fにブレイクポイントを設定します。dcDebug Continue)にて、その時点まで実行します。

db 0x00400b5f
dc
hit breakpoint at: 400b5f

radare shell画面にてpx(Print heXdump)でlocal_chの値を確認します。

px @ rbp-0xc

Day 17 - #2.

What is the value of eax when the imull instruction is called?

ds(debug step)にて、imull命令まで実行させます。
dr(Debug cpu Registers)にて、EAX(rax)の値を確認します。

Day 17 - #3.

What is the value of local_4h before eax is set to 0?

次の命令の前における、local_4hの値を確認する必要があります。

0x00400b69      b800000000     mov eax, 0

次のコマンドで確認します。

px @ rbp-0x4

これにて、17日目のミッションが終了です。

参考情報

Walkthrough