QEMUについて調査している。x86のコードをどのようにディスアセンブルしているのかを調査していると、gitのサブモジュールとしてcapstoneというツールが使われていることが分かった。capstoneは、マルチターゲットのディスアセンブラらしい。ディスアセンブラだけでプラットフォーム化されているのか。面白い。
これをライブラリとして、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
$ ./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
試しに、x86のバイナリの機械語を流し込んでみる。どのようになるだろうか。
$ ./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 ...
なるほど、このようにディスアセンブルできるのか。これは便利そうだ。