Upgrade to Pro — share decks privately, control downloads, hide ads and more …

SECCON13 - SECCON Beginners Workshop - Reversing

Hi120ki
March 01, 2025

SECCON13 - SECCON Beginners Workshop - Reversing

Hi120ki

March 01, 2025
Tweet

More Decks by Hi120ki

Other Decks in Technology

Transcript

  1. 自己紹介 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
  2. 流れ 1. Reversingとは 2. バイナリ解析の基本 3. アセンブリの基礎 (講義課題1~4) 4. アセンブリの応用

    (講義課題5~8) 5. 演習課題 (演習課題1~2) ※ 初めての方は講義課題4まで・演習課題1が解くことができたら素晴 らしいです! Reversing基礎編 - SECCON 13 Beginners Workshop 4
  3. このプログラムをご覧になったことがありますか? main.c #include <stdio.h> int main() { printf("Hello, World!\n"); return

    0; } Linux上で gcc を使って a.out ファイルを作って... Reversing基礎編 - SECCON 13 Beginners Workshop 7
  4. 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
  5. 課題環境へのアクセス https://github.com/hi120ki/seccon13-ctf4b-workshop- reversing レポジトリをクローンして Docker コンテナを起動 $ docker compose up

    -d http://localhost:8080/ から演習課題へアクセスできます Reversing基礎編 - SECCON 13 Beginners Workshop 12
  6. 課題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
  7. 課題1 レジスタ - レジスタの使い方 固定の値を代入する mov rax, 0x12345 mov :

    命令 (オペコード) rax : 書き込むレジスタ (第一オペランド) 0x12345 : 書き込む値 (第二オペランド) レジスタの値を他のレジスタにコピーする mov rbx, rax mov : 命令 (オペコード) rbx : 書き込むレジスタ (第一オペランド) rax : コピー元のレジスタ (第二オペランド) Reversing基礎編 - SECCON 13 Beginners Workshop 17
  8. 課題2 複数の命令 - 解答例 mov rax, 0x12345 mov rdx, rax

    mov rbx, 0x54321 上から順に実行されます Reversing基礎編 - SECCON 13 Beginners Workshop 20
  9. 課題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
  10. 課題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
  11. 課題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
  12. 課題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
  13. 課題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
  14. 課題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
  15. 課題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
  16. 課題5 スタックのPush操作 スタックはデータを一時的に保存するためのメモリ領域 命令 意味 例 push スタックにプッシュ push rax

    push rax : RAXレジスタの値をスタックにプッシュ(保存) Reversing基礎編 - SECCON 13 Beginners Workshop 30
  17. 課題6 スタックのPop操作 命令 意味 例 pop スタックからポップ pop rax pop

    rax : スタックからポップ(取り出し)してRAXレジスタに格納 Reversing基礎編 - SECCON 13 Beginners Workshop 33
  18. 課題6 スタックのPop操作 - 解答例 mov rax, 0x12345 push rax push

    rax pop rbx Reversing基礎編 - SECCON 13 Beginners Workshop 35
  19. 課題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
  20. 課題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
  21. 課題7 システムコールの基礎 - ファイルディスク リプタ ファイルの操作対象を識別するための番号 ファイルディスクリプタ 意味 0 標準入力

    1 標準出力 2 標準エラー出力 他にも open システムコールでファイルを開いたり、 socket システムコ ールでソケットを作成するとファイルディスクリプタが返される 今回は標準出力に書き込むのでファイルディスクリプタは1 Reversing基礎編 - SECCON 13 Beginners Workshop 39
  22. 課題7 システムコールの基礎 - メモリでの文字列 今回扱うアーキテクチャはx86-64 レジスタのサイズは64bit メモリアドレスは64bit リトルエンディアン リトルエンディアン :

    複数バイトのデータをメモリに格納する際、下位 バイトから順にアドレスに配置する方式 4バイトのデータ 0x12345678 をリトルエンディアンでメモリに格納 → メモリのアドレス順に 78, 56, 34, 12 と配置 Reversing基礎編 - SECCON 13 Beginners Workshop 40
  23. 課題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
  24. 課題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
  25. 課題8 システムコールの発展 - システムコールの 順番 1. ファイル名 flag.txt をメモリに格納 2.

    open システムコールでファイルを開く 3. open システムコールでファイルディスクリプタを取得 4. ファイルディスクリプタから read システムコールで読み込む 5. 読み込んだ内容を write システムコールで標準出力に出力 → 合計3つのシステムコールを使う Reversing基礎編 - SECCON 13 Beginners Workshop 44
  26. 課題8 システムコールの発展 - 文字列の終端NULL 文字列の終端にはNULL文字を入れる NULL文字(0x00)によって文字列の終端を示す flag.txt は 0x7478742e67616c66 となり、さらにNULL文字を追加したい

    が、64bitのレジスタには余裕がない → NULL文字を追加するために事前にNULL文字をstackにpush Reversing基礎編 - SECCON 13 Beginners Workshop 45
  27. 課題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
  28. 課題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
  29. 課題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
  30. 課題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
  31. 課題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
  32. 課題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
  33. 演習課題 https://github.com/hi120ki/seccon13-ctf4b-workshop- reversing レポジトリをクローンして Docker コンテナを起動 $ docker compose up

    -d http://localhost:8080/ から演習課題へアクセスできます Reversing基礎編 - SECCON 13 Beginners Workshop 53
  34. 演習課題1 RAX に 0x12345 を代入し、RDX に 0x54321 を代入してください。 mov rax,

    0x12345 mov rdx, 0x54321 Reversing基礎編 - SECCON 13 Beginners Workshop 54
  35. 演習課題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
  36. 演習課題1 RAX に RAX と RAX の XOR を取った結果を代入してください。 RDX

    に RBX と RCX の AND を取った結果を代入してください。 xor rax, rax mov rdx, rbx and rdx, rcx Reversing基礎編 - SECCON 13 Beginners Workshop 56
  37. 演習課題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
  38. 演習課題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
  39. 演習課題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
  40. 演習課題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
  41. 演習課題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
  42. 演習課題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
  43. 演習課題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