Share
Embed
Transcript
64 slides
-
自己紹介 Hi120ki - Hiroki Akamatsu 株式会社メルカリ Platform Security Engineer GitHub
Security Google Cloud / AWS Security Identity and Access Management CTFチーム Wani Hackase でWeb・Reversing担当 Reversing基礎編 - SECCON 13 Beginners Workshop 2 -
流れ 1. Reversingとは 2. バイナリ解析の基本 3. アセンブリの基礎 (講義課題1~4) 4. アセンブリの応用
(講義課題5~8) 5. 演習課題 (演習課題1~2) ※ 初めての方は講義課題4まで・演習課題1が解くことができたら素晴 らしいです! Reversing基礎編 - SECCON 13 Beginners Workshop 4 -
Reversingとは 機械や製品・プログラムの内部の構造や動作の解析 CTFでの解析対象 実行可能ファイル Linux ELF Windows PE モバイルアプリ スクリプトファイル
pcapファイル ファームウェア ゲームプログラム Reversing基礎編 - SECCON 13 Beginners Workshop 5 -
何の役に立つの? マルウェア解析 悪意を持ってシステムを破壊・改ざん・盗聴するプログラム 解析する技術でマルウェアの動作を理解し対策を講じる マルウェアは様々な手法で解析を困難にする 難読化 パッキング サーバーと通信して動作を変更 デバッガーを検知して動作を変更 気づかれないように混入
プログラムの動作を理解し、マルウェアの解析に役立てる Reversing基礎編 - SECCON 13 Beginners Workshop 6 -
このプログラムをご覧になったことがありますか? main.c #include <stdio.h> int main() { printf("Hello, World!\n"); return
0; } Linux上で gcc を使って a.out ファイルを作って... Reversing基礎編 - SECCON 13 Beginners Workshop 7 -
ELFファイルとは Executable and Linkable Format 多くのLinux系やBSD系のOSで実行可能ファイル形式として採用 C言語を含むさまざまなプログラミング言語のソースコードをコンパイ ルして作成できる gcc main.c
-o a.out 実行権限を与えた上で実行すると,ソースコード main.c に記述された処 理が実行される $ chmod +x ./a.out # 実行権限を与える $ ./a.out # 実行する Hello, World! Reversing基礎編 - SECCON 13 Beginners Workshop 8 -
プログラムをコンピューターが実行するまで コンパイルにより、ソースコードを機械語に変換 → CPUが直接実行できるように 機械語は人間にとって理解しにくい → 機械語に1対1で対応するアセンブリコードを使って解析 → CPUの気持ちになる Reversing基礎編
- SECCON 13 Beginners Workshop 9 -
CPUの構成 CPUは機械語の命令を実行する → 演算や比較や分岐・特別な命令を実行 実行するだけでは、できることが限られる → 保存領域にデータを読み書きする CPU内にある高速な保存領域を使ってデータを読み書き → レジスタ
関数のローカル変数や関数呼び出しの戻りアドレスなど、一時的なデー タを保存する → スタック Reversing基礎編 - SECCON 13 Beginners Workshop 11 -
課題環境へのアクセス https://github.com/hi120ki/seccon13-ctf4b-workshop- reversing レポジトリをクローンして Docker コンテナを起動 $ docker compose up
-d http://localhost:8080/ から演習課題へアクセスできます Reversing基礎編 - SECCON 13 Beginners Workshop 12 -
課題1 レジスタ - レジスタの種類 レジスタ名 名前の意味 使われ方 RAX Accumulator 汎用
RBX Base 汎用 RCX Counter 汎用 RDX Data 汎用 RSI Source Index コピー元のアドレス RDI Destination Index コピー先のアドレス RBP Base Pointer スタックフレームのベースポインタ RSP Stack Pointer スタックの先頭 RIP Instruction Pointer 次に実行する命令のアドレス Reversing基礎編 - SECCON 13 Beginners Workshop 15 -
課題1 レジスタ - レジスタの使い方 固定の値を代入する mov rax, 0x12345 mov :
命令 (オペコード) rax : 書き込むレジスタ (第一オペランド) 0x12345 : 書き込む値 (第二オペランド) レジスタの値を他のレジスタにコピーする mov rbx, rax mov : 命令 (オペコード) rbx : 書き込むレジスタ (第一オペランド) rax : コピー元のレジスタ (第二オペランド) Reversing基礎編 - SECCON 13 Beginners Workshop 17 -
課題1 レジスタ - 解答例 RAXレジスタに0x12345を代入してください mov rax, 0x12345 「解答例を表示」ボタンから確認できます Reversing基礎編
- SECCON 13 Beginners Workshop 18 -
課題2 複数の命令 - 解答例 mov rax, 0x12345 mov rdx, rax
mov rbx, 0x54321 上から順に実行されます Reversing基礎編 - SECCON 13 Beginners Workshop 20 -
課題3 演算 - CPUの四則演算命令 命令 意味 例 add 加算 add
rbx, rax sub 減算 sub rcx, rdx mul 符号なし乗算 mul rdx imul 符号付き乗算 imul rdx div 符号なし除算 div rdx idiv 符号付き除算 idiv rdx add rbx, rax : RBXレジスタにRAXレジスタの値を足して結果をRBXレ ジスタに代入 mul rdx : RAXの値とRDXの値を乗算し、結果をRDX:RAXに格納(上位ビ ットはRDX、下位ビットはRAX) div rdx : RDX:RAXをRDXで割り、商をRAXに、剰余をRDXに格納 Reversing基礎編 - SECCON 13 Beginners Workshop 22 -
課題3 演算 - CPUの論理演算命令 命令 意味 例 and 論理積 and
rax, rcx or 論理和 or rax, rcx xor 排他的論理和 xor rax, rcx xor rax, rcx : RAXレジスタとRCXレジスタの値をXORして結果をRAX レジスタに代入 Reversing基礎編 - SECCON 13 Beginners Workshop 23 -
課題3 演算 - 解答例 mov rax, 0x12345 mov rdx, 0x54321
mov rbx, rax add rbx, rdx mov rcx, rdx sub rcx, rax xor rax, rcx Reversing基礎編 - SECCON 13 Beginners Workshop 24 -
課題4 比較 - ジャンプ命令 命令 意味 例 jmp ジャンプ jmp
label jmp label : ラベル label にジャンプ jmp命令を使うことで、プログラムの実行を途中で切り替えることがで きる jmp label mov rax, 0x100 label: mov rax, 0x200 RAXレジスタに0x100が代入されず、0x200が代入される Reversing基礎編 - SECCON 13 Beginners Workshop 26 -
課題4 比較 - 比較命令 命令 意味 例 cmp 比較 cmp
rax, rdx cmp rax, rdx : RAXレジスタの値とRDXレジスタの値を比較して、結果 をフラグレジスタに格納 命令 意味 例 je 等しい je label jne 等しくない jne label jl (符号付き)未満 jl label jle (符号付き)以下 jle label jg (符号付き)より大きい jg label jge (符号付き)以上 jge label je label : 直前の比較命令で等しい場合、ラベル label にジャンプ Reversing基礎編 - SECCON 13 Beginners Workshop 27 -
課題4 比較 - ラベル label: ... cmp rax, rdx je
equal jmp not_equal equal: mov rdx, 0x100 jmp end not_equal: mov rdx, 0x200 end: Reversing基礎編 - SECCON 13 Beginners Workshop 28 -
課題4 比較 - 解答例 mov rax, 0x12345 mov rdx, 0xabcde
cmp rax, rdx jne not_equal mov rdx, 0x100 jmp done not_equal: mov rdx, 0x200 done: Reversing基礎編 - SECCON 13 Beginners Workshop 29 -
課題5 スタックのPush操作 スタックはデータを一時的に保存するためのメモリ領域 命令 意味 例 push スタックにプッシュ push rax
push rax : RAXレジスタの値をスタックにプッシュ(保存) Reversing基礎編 - SECCON 13 Beginners Workshop 30 -
課題5 スタックのPush操作 - スタックの仕組み RSPレジスタ : スタック領域の先頭アドレスを指す Reversing基礎編 - SECCON
13 Beginners Workshop 31 -
課題5 スタックのPush操作 - 解答例 mov rax, 0x12345 push rax Reversing基礎編
- SECCON 13 Beginners Workshop 32 -
課題6 スタックのPop操作 命令 意味 例 pop スタックからポップ pop rax pop
rax : スタックからポップ(取り出し)してRAXレジスタに格納 Reversing基礎編 - SECCON 13 Beginners Workshop 33 -
課題6 スタックのPop操作 - 解答例 mov rax, 0x12345 push rax push
rax pop rbx Reversing基礎編 - SECCON 13 Beginners Workshop 35 -
課題7 システムコールの基礎 システムコールはOSの機能を呼び出すための命令 例 標準出力・標準入力・標準エラー出力 ファイルの読み書き ファイルの作成 ファイルの削除 プロセスの作成 プロセスの終了
ネットワーク通信 ... 一覧 - Linux System Call Table for x86 64 Reversing基礎編 - SECCON 13 Beginners Workshop 36 -
課題7 システムコールの基礎 - システムコール 命令 意味 例 syscall システムコール syscall
Linuxのシステムコールは syscall 命令を使って呼び出す レジスタ 引数の役割 RAX システムコール番号 (例: 1 = write) RDI 第1引数 RSI 第2引数 RDX 第3引数 RCX 第4引数 R8 第5引数 R9 第6引数 Reversing基礎編 - SECCON 13 Beginners Workshop 37 -
課題7 システムコールの基礎 - 標準出力 一覧 - Linux System Call Table
for x86 64 rax syscall rdi rsi rdx 1 write unsigned int fd const char *buf size_t count syscall 命令を実行する前に、適切なレジスタに引数をセットする RAX : システムコール番号 (1とすることで write システムコール) RDI : 第1引数 (ファイルディスクリプタ) RSI : 第2引数 (書き込むデータのアドレス) RDX : 第3引数 (書き込むデータのサイズ) Reversing基礎編 - SECCON 13 Beginners Workshop 38 -
課題7 システムコールの基礎 - ファイルディスク リプタ ファイルの操作対象を識別するための番号 ファイルディスクリプタ 意味 0 標準入力
1 標準出力 2 標準エラー出力 他にも open システムコールでファイルを開いたり、 socket システムコ ールでソケットを作成するとファイルディスクリプタが返される 今回は標準出力に書き込むのでファイルディスクリプタは1 Reversing基礎編 - SECCON 13 Beginners Workshop 39 -
課題7 システムコールの基礎 - メモリでの文字列 今回扱うアーキテクチャはx86-64 レジスタのサイズは64bit メモリアドレスは64bit リトルエンディアン リトルエンディアン :
複数バイトのデータをメモリに格納する際、下位 バイトから順にアドレスに配置する方式 4バイトのデータ 0x12345678 をリトルエンディアンでメモリに格納 → メモリのアドレス順に 78, 56, 34, 12 と配置 Reversing基礎編 - SECCON 13 Beginners Workshop 40 -
課題7 システムコールの基礎 - ASCIIコード 標準的な文字と数値の対応 : ASCIIコード表 H : 0x48
(72) e : 0x65 (101) l : 0x6c (108) l : 0x6c (108) o : 0x6f (111) ! : 0x21 (33) つまりメモリに格納する値は 0x216f6c6c6548 Reversing基礎編 - SECCON 13 Beginners Workshop 41 -
課題7 システムコールの基礎 - 解答例 mov rax, 0x216f6c6c6548 # "Hello!" push
rax # スタックに文字列を格納 mov rax, 1 # write システムコール mov rdi, 1 # 標準出力 mov rsi, rsp # スタックの先頭アドレスを第2 引数に mov rdx, 0x6 # 文字列の長さ syscall Reversing基礎編 - SECCON 13 Beginners Workshop 42 -
課題8 システムコールの発展 - システムコールの 順番 1. ファイル名 flag.txt をメモリに格納 2.
open システムコールでファイルを開く 3. open システムコールでファイルディスクリプタを取得 4. ファイルディスクリプタから read システムコールで読み込む 5. 読み込んだ内容を write システムコールで標準出力に出力 → 合計3つのシステムコールを使う Reversing基礎編 - SECCON 13 Beginners Workshop 44 -
課題8 システムコールの発展 - 文字列の終端NULL 文字列の終端にはNULL文字を入れる NULL文字(0x00)によって文字列の終端を示す flag.txt は 0x7478742e67616c66 となり、さらにNULL文字を追加したい
が、64bitのレジスタには余裕がない → NULL文字を追加するために事前にNULL文字をstackにpush Reversing基礎編 - SECCON 13 Beginners Workshop 45 -
課題8 システムコールの発展 - ファイルを開く rax syscall rdi rsi rdx 2
open const char *filename int flags int mode RAX : システムコール番号 (2とすることで open システムコール) RDI : 第1引数 (ファイル名へのアドレス) RSI : 第2引数 (ファイルのオープンモード) RDX : 第3引数 (ファイルのパーミッション) Reversing基礎編 - SECCON 13 Beginners Workshop 46 -
課題8 システムコールの発展 - ファイルを開く open システムコールの第2引数はファイルのオープンモード オープンモードとしてアクセスモードを指定する 0 : O_RDONLY
(読み込み専用) 1 : O_WRONLY (書き込み専用) 2 : O_RDWR (読み書き両方) Reversing基礎編 - SECCON 13 Beginners Workshop 47 -
課題8 システムコールの発展 - ファイルを開く mov rax, 0 # null terminate
push rax # push null to stack mov rax, 0x7478742e67616c66 # "flag.txt" push rax # push file name to stack mov rdi, rsp # file name buffer pointer mov rsi, 0 # O_RDONLY mov rax, 2 # syscall number syscall # sys_open syscallの返り値であるRAXレジスタにファイルディスクリプタが入る Reversing基礎編 - SECCON 13 Beginners Workshop 48 -
課題8 システムコールの発展 - ファイル読み込み rax syscall rdi rsi rdx 0
read unsigned int fd char *buf size_t count RAX : システムコール番号 (0とすることで read システムコール) RDI : 第1引数 (ファイルディスクリプタ) RSI : 第2引数 (読み込むデータのアドレス) RDX : 第3引数 (読み込むデータのサイズ) → RSIレジスタにRSPレジスタを指定することで、スタック上に読み込 んだデータを読み込む Reversing基礎編 - SECCON 13 Beginners Workshop 49 -
課題8 システムコールの発展 - ファイル読み込み mov rdi, rax # fd mov
rsi, rsp # buffer pointer mov rdx, 1024 # buffer size mov rax, 0 # syscall number syscall # sys_read Reversing基礎編 - SECCON 13 Beginners Workshop 50 -
課題8 システムコールの発展 - 標準出力 read システムコールでの返り値RAXは読み込んだバイト数 rax syscall rdi rsi
rdx 1 write unsigned int fd const char *buf size_t count mov rdx, rax # buffer size mov rsi, rsp # buffer pointer mov rdi, 1 # stdout mov rax, 1 # syscall number syscall # sys_write Reversing基礎編 - SECCON 13 Beginners Workshop 51 -
課題8 システムコールの発展 - 解答例 mov rax, 0 # null terminate
push rax # push null to stack mov rax, 0x7478742e67616c66 # "flag.txt" push rax # push file name to stack mov rdi, rsp # file name buffer pointer mov rsi, 0 # O_RDONLY mov rax, 2 # syscall number syscall # sys_open mov rdi, rax # fd mov rsi, rsp # buffer pointer mov rdx, 1024 # buffer size mov rax, 0 # syscall number syscall # sys_read mov rdx, rax # buffer size mov rsi, rsp # buffer pointer mov rdi, 1 # stdout mov rax, 1 # syscall number syscall # sys_write Reversing基礎編 - SECCON 13 Beginners Workshop 52 -
演習課題 https://github.com/hi120ki/seccon13-ctf4b-workshop- reversing レポジトリをクローンして Docker コンテナを起動 $ docker compose up
-d http://localhost:8080/ から演習課題へアクセスできます Reversing基礎編 - SECCON 13 Beginners Workshop 53 -
演習課題1 RAX に 0x12345 を代入し、RDX に 0x54321 を代入してください。 mov rax,
0x12345 mov rdx, 0x54321 Reversing基礎編 - SECCON 13 Beginners Workshop 54 -
演習課題1 RBX に RAX と RDX の和を代入してください。 RCX に RDX
から RAX を引いた値を代入してください。 mov rbx, rax add rbx, rdx mov rcx, rdx sub rcx, rax Reversing基礎編 - SECCON 13 Beginners Workshop 55 -
演習課題1 RAX に RAX と RAX の XOR を取った結果を代入してください。 RDX
に RBX と RCX の AND を取った結果を代入してください。 xor rax, rax mov rdx, rbx and rdx, rcx Reversing基礎編 - SECCON 13 Beginners Workshop 56 -
演習課題1 RAX が 0 なら、RDX に 0xFFFFF を代入してください。 RAX が
0 でないなら、RDX に 0xBEEF を代入してください。 cmp rax, 0 jne not_equal mov rdx, 0xFFFFF jmp done not_equal: mov rdx, 0xBEEF done: Reversing基礎編 - SECCON 13 Beginners Workshop 57 -
演習課題1 - 解答 mov rax, 0x12345 mov rdx, 0x54321 mov
rbx, rax add rbx, rdx mov rcx, rdx sub rcx, rax xor rax, rax mov rdx, rbx and rdx, rcx cmp rax, 0 jne not_equal mov rdx, 0xFFFFF jmp done not_equal: mov rdx, 0xBEEF done: Reversing基礎編 - SECCON 13 Beginners Workshop 58 -
演習課題2 flag.txtファイルに「 ctf4b{we1come_t0_the_SECCON_13_Beg1nner3_W0rksh0p} 」を書き込んでくだ さい 1. ファイルに書き込む文字列をスタックに格納する 2. "flag.txt"ファイル名をスタックに格納する 3.
openシステムコールでファイルを開く 4. writeシステムコールでファイルに書き込む 5. closeシステムコールでファイルを閉じる Reversing基礎編 - SECCON 13 Beginners Workshop 59 -
演習課題2 mov rax, 0x7d703068736b7230 push rax mov rax, 0x575f3372656e6e31 push
rax mov rax, 0x6765425f33315f4e push rax mov rax, 0x4f434345535f6568 push rax mov rax, 0x745f30745f656d6f push rax mov rax, 0x633165777b623466 push rax mov rax, 0x7463000000000000 push rax Reversing基礎編 - SECCON 13 Beginners Workshop 61 -
演習課題2 rax syscall rdi rsi rdx 2 open const char
*filename int flags int mode 書き込みアクセスモード( O_WRONLY )に加えて、ファイルが存在しない場 合にファイルを作成するためのフラグ( O_CREAT )を指定する また、ファイルのパーミッション( 0644 )を指定する mov rax, 0x7478742e67616c66 # "flag.txt" push rax # push file name to stack mov rdi, rsp # file name buffer pointer mov rsi, 0x41 # O_WRONLY | O_CREAT mov rdx, 0644 # permission mov rax, 2 # syscall number for sys_open syscall Reversing基礎編 - SECCON 13 Beginners Workshop 62 -
演習課題2 スタック上には "flag.txt" が残っているので、 rsp を調整して削除 RSPレジスタの値( ctf{~ がスタックの先頭にある)をRSIレジスタに移動 add
rsp, 14 # remove "flag.txt" from stack mov rdi, rax # fd mov rsi, rsp # buffer pointer mov rdx, 50 # flag length mov rax, 1 # syscall number for sys_write syscall Reversing基礎編 - SECCON 13 Beginners Workshop 63 -
演習課題2 - おまけ ファイルディスクリプタをRDIレジスタに移動して、ファイルを閉じる mov rdi, rax # fd mov
rax, 3 # syscall number for sys_close syscall プログラムを正常終了する mov rax, 60 # syscall number for sys_exit xor rdi, rdi # status 0 syscall Reversing基礎編 - SECCON 13 Beginners Workshop 64