FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

QEMUで使用されているマルチターゲットディスアセンブラcapstoneを調査する

QEMUについて調査している。x86のコードをどのようにディスアセンブルしているのかを調査していると、gitのサブモジュールとしてcapstoneというツールが使われていることが分かった。capstoneは、マルチターゲットのディスアセンブラらしい。ディスアセンブラだけでプラットフォーム化されているのか。面白い。

github.com

www.capstone-engine.org

これをライブラリとして、x86のディスアセンブラが実装されているらしい。少し調査してみよう。

まずはダウンロードしてビルドしてみる。

$ git clone https://github.com/aquynh/capstone.git
$ cd capstone
$ mkdir build
$ cd build
$ ../configure
$ make

cstoolというツールがビルドされた。

CMakeCache.txt       capstone.pc          install_manifest.txt  libcapstone.so.5.0.0  test_basic            test_iter   test_mos65xx   test_systemz
CMakeFiles           cmake_install.cmake  libcapstone.a         test_arm              test_customized_mnem  test_m680x  test_ppc       test_tms320c64x
CTestTestfile.cmake  cstool               libcapstone.so        test_arm64            test_detail           test_m68k   test_skipdata  test_x86
Makefile             fuzz_disasm          libcapstone.so.5      test_arm_regression   test_evm              test_mips   test_sparc     test_xcore

cstoolを使ってみる。

$ ./cstool --help
Cstool for Capstone Disassembler Engine v5.0.0

Syntax: ./cstool [-u|-d|-s|-v] <arch+mode> <assembly-hexstring> [start-address-in-hex-format]

The following <arch+mode> options are supported:
        x16         16-bit mode (X86)
        x32         32-bit mode (X86)
        x64         64-bit mode (X86)
        x16att      16-bit mode (X86), syntax AT&T
        x32att      32-bit mode (X86), syntax AT&T
        x64att      64-bit mode (X86), syntax AT&T
        arm         arm
        armbe       arm + big endian
        thumb       thumb mode
        thumbbe     thumb + big endian
        cortexm     thumb + cortex-m extensions
        arm64       aarch64 mode
        arm64be     aarch64 + big endian
        mips        mips32 + little endian
        mipsbe      mips32 + big endian
        mips64      mips64 + little endian
        mips64be    mips64 + big endian
        ppc64       ppc64 + little endian
        ppc64be     ppc64 + big endian
        sparc       sparc
        systemz     systemz (s390x)
        xcore       xcore
        m68k        m68k + big endian
        m68k40      m68k_040
        tms320c64x  TMS320C64x
        m6800       M6800/2
        m6801       M6801/3
        m6805       M6805
        m6808       M68HC08
        m6809       M6809
        m6811       M68HC11
        cpu12       M68HC12/HCS12
        hd6301      HD6301/3
        hd6309      HD6309
        hcs08       HCS08
        evm         Ethereum Virtual Machine
        mos65xx     MOS65XX family

Extra options:
        -d show detailed information of the instructions
        -u show immediates as unsigned
        -s decode in SKIPDATA mode
        -v show version & Capstone core build info

例えば、単体のx86のバイナリをディスアセンブルしてみる。

$ ./cstool -d x64 0x48c7855800000000000000

なるほど、このように情報が表示されるのか。これは面白い。

 0  48 c7 85 58 00 00 00 00 00 00 00                 mov        qword ptr [rbp + 0x58], 0
        Prefix:0x00 0x00 0x00 0x00
        Opcode:0xc7 0x00 0x00 0x00
        rex: 0x48
        addr_size: 8
        modrm: 0x85
        disp: 0x58
        sib: 0x0
        imm_count: 1
                imms[1]: 0x0
        op_count: 2
                operands[0].type: MEM
                        operands[0].mem.base: REG = rbp
                        operands[0].mem.disp: 0x58
                operands[0].size: 8
                operands[0].access: WRITE
                operands[1].type: IMM = 0x0
                operands[1].size: 8
        Registers read: rbp
f:id:msyksphinz:20200908000952p:plain

試しに、x86のバイナリの機械語を流し込んでみる。どのようになるだろうか。

f:id:msyksphinz:20200908000936p:plain
$ ./cstool x64 "`cat load_test_extract.log`"
 0  48 c7 85 58 00 00 00 00 00 00 00                 mov        qword ptr [rbp + 0x58], 0
 b  48 8b 85 58 00 00 00                             mov        rax, qword ptr [rbp + 0x58]
12  05 84 00 00 00                                   add        eax, 0x84
17  48 89 85 58 00 00 00                             mov        qword ptr [rbp + 0x58], rax
1e  48 b9 20 06 09 00 40 00 00 00                    movabs     rcx, 0x4000090620
28  48 8b 85 58 00 00 00                             mov        rax, qword ptr [rbp + 0x58]
2f  48 03 c1                                         add        rax, rcx
32  48 8b 80 00 00 00 00                             mov        rax, qword ptr [rax]
39  48 89 85 60 00 00 00                             mov        qword ptr [rbp + 0x60], rax
40  48 b9 20 06 09 00 40 00 00 00                    movabs     rcx, 0x4000090620
...

なるほど、このようにディスアセンブルできるのか。これは便利そうだ。