2章 アセンブラとコンピュータアーキテクチャ

  • バイナリ
    • 実行ファイル, バイナリコードのこと

本書では,このバイナリを解析することを目的としているらしい.

C言語でバイナリに触れてみる

適当なC言語で書かれたソースコードを書きます.

#include <stdio.h>

int main() {
    printf("%d\n", 2 + 3);
    return 0;
}

このソースコードをgccでコンパイルしてあげるとa.outと呼ばれるバイナリが生成されます.このバイナリファイルを実行すると,予想した結果が得られます.

❯ gcc compile_2-1.c
❯ ./a.out
5

ここから,バイナリ解析っぽくなります.本書ではhexeditと呼ばれるバイナリエディタを使用していますが,私はxxdと呼ばれるコマンドを用いて読みます.

❯ xxd a.out > a.bin
❯ cat a.bin
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: a.bin
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │ 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000  .ELF............
   2   │ 00000010: 0300 3e00 0100 0000 4010 0000 0000 0000  ..>.....@.......
   3   │ 00000020: 4000 0000 0000 0000 0847 0000 0000 0000  @........G......
   4   │ 00000030: 0000 0000 4000 3800 0d00 4000 2500 2400  ....@.8...@.%.$.
   5   │ 00000040: 0600 0000 0400 0000 4000 0000 0000 0000  ........@.......
   6   │ 00000050: 4000 0000 0000 0000 4000 0000 0000 0000  @.......@.......
   7   │ 00000060: d802 0000 0000 0000 d802 0000 0000 0000  ................
   8   │ 00000070: 0800 0000 0000 0000 0300 0000 0400 0000  ................
   9   │ 00000080: 1803 0000 0000 0000 1803 0000 0000 0000  ................
  10   │ 00000090: 1803 0000 0000 0000 1c00 0000 0000 0000  ................
  11   │ 000000a0: 1c00 0000 0000 0000 0100 0000 0000 0000  ................
  12   │ 000000b0: 0100 0000 0400 0000 0000 0000 0000 0000  ................
  13   │ 000000c0: 0000 0000 0000 0000 0000 0000 0000 0000  ................
  14   │ 000000d0: 3006 0000 0000 0000 3006 0000 0000 0000  0.......0.......
  15   │ 000000e0: 0010 0000 0000 0000 0100 0000 0500 0000  ................
...

次に,gcc機能である,アセンブリコードを吐き出すコマンドを実行してみます.すると,.sのアセンブリファイルがあることがわかります.

❯ gcc compile_2-1.c -S
❯ ls
a.bin  a.out  compile_2-1.c  compile_2-1.s
❯ cat compile_2-1.s
───────┬──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
       │ File: compile_2-1.s
───────┼──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
   1   │     .file   "compile_2-1.c"
   2   │     .text
   3   │     .section    .rodata
   4   │ .LC0:
   5   │     .string "%d\n"
   6   │     .text
   7   │     .globl  main
   8   │     .type   main, @function
   9   │ main:
  10   │ .LFB0:
  11   │     .cfi_startproc
  12   │     pushq   %rbp
  13   │     .cfi_def_cfa_offset 16
  14   │     .cfi_offset 6, -16
  15   │     movq    %rsp, %rbp
  16   │     .cfi_def_cfa_register 6
  17   │     movl    $5, %esi
  18   │     leaq    .LC0(%rip), %rax
  19   │     movq    %rax, %rdi
  20   │     movl    $0, %eax
  21   │     call    printf@PLT
  22   │     movl    $0, %eax
  23   │     popq    %rbp
  24   │     .cfi_def_cfa 7, 8
  25   │     ret
  26   │     .cfi_endproc
  27   │ .LFE0:
  28   │     .size   main, .-main
  29   │     .ident  "GCC: (GNU) 12.1.0"
  30   │     .section    .note.GNU-stack,"",@progbits
───────┴──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

3章 ASCIIコードとバイトオーダ

  • ASCIIコード
    • 128文字を表現する,ビット列と文字の対応のことを指す
    • アルファベットや,特殊な意味を持つ文字(NULや改行など)

C++で書かれた認証プログラムをハックする

本書の演習にあって,とても興味深かった内容です.標準入力とパスが一致したかを評価するプログラムですが,この実行ファイルからパスを推測する手法です.

#include <iostream>
#include <string>

int main(){
    std::string input;
    std::cin >> input;
    if (input == "chizuchizu") {
        std::cout << "success" << std::endl;
    } else {
        std::cout << "fail" << std::endl;
    }

    return 0;
}

実行すると想定どおりの答えが帰ってきます.

❯ g++ strings_3-2.cpp
❯ ./a.out
asdfasdf
fail
❯ ./a.out
chizuchizu
success

実行ファイルからパスを探すためにstringsコマンドを使います.

strings コマンドは、ファイル内で表示可能な文字列を探します。 文字列とは、改行文字または null 文字で終わる 4 文字以上の印刷可能文字の任意の順序列です。 strings コマンドは、ランダム・オブジェクト・ファイルを識別するのに便利です。
strings コマンド - IBM Documentation

実際にやってみると,今回設定したパスであるchizuchizuが出てくることがわかります.プログラムの中に文字列を入れれば,それを取り出せる脆弱性があるそうです.こわい.

❯ strings a.out | grep "^[^_.]"
/lib64/ld-linux-x86-64.so.2
libstdc++.so.6
libm.so.6
libgcc_s.so.1
libc.so.6
GCC_3.0
GLIBC_2.4
GLIBC_2.34
GLIBC_2.2.5
CXXABI_1.3
GLIBCXX_3.4
GLIBCXX_3.4.21
PTE1
u3UH
chizuchizu
success
fail
...