1# Capstone-Engine API Documentation 2 3| Version | 4.0.2 | 4| ------- | ----- | 5 6**Official API document by [kabeor](https://github.com/kabeor)** 7 8[Capstone Engine](https://github.com/capstone-engine/capstone)是一个支持多种硬件架构的二进制反汇编引擎。 9 10 11## 0x0 开发准备 12 13 Capstone官网: http://www.capstone-engine.org 14 15### 自行编译lib和dll方法 16 17 源码: https://github.com/capstone-engine/capstone.git 18 19 git clone下来 20 文件结构如下: 21 22``` 23 . <- 主要引擎core engine + README + 编译文档COMPILE.TXT 等 24├── arch <- 各语言反编译支持的代码实现 25│ ├── AArch64 <- ARM64 (aka ARMv8) 引擎 26│ ├── ARM <- ARM 引擎 27│ ├── EVM <- Ethereum 引擎 28│ ├── M680X <- M680X 引擎 29│ ├── M68K <- M68K 引擎 30| ├── MOS65XX <- MOS65XX 引擎 31│ ├── Mips <- Mips 引擎 32│ ├── PowerPC <- PowerPC 引擎 33│ ├── Sparc <- Sparc 引擎 34│ ├── SystemZ <- SystemZ 引擎 35│ ├── TMS320C64x <- TMS320C64x 引擎 36│ ├── X86 <- X86 引擎 37│ └── XCore <- XCore 引擎 38├── bindings <- 绑定 39│ ├── java <- Java 绑定 + 测试代码 40│ ├── ocaml <- Ocaml 绑定 + 测试代码 41│ ├── powershell <- powershell 绑定 + 测试代码 42│ ├── python <- python 绑定 + 测试代码 43│ └── vb6 <- vb6 绑定 + 测试代码 44├── contrib <- 社区代码 45├── cstool <- Cstool 检测工具源码 46├── docs <- 文档,主要是capstone的实现思路 47├── include <- C头文件 48├── msvc <- Microsoft Visual Studio 支持(Windows) 49├── packages <- Linux/OSX/BSD包 50├── suite <- 项目开发所需工具 51├── tests <- C语言测试用例 52├── windows <- Windows 支持(Windows内核驱动编译) 53├── windowsce <- Windows CE 支持 54└── xcode <- Xcode 支持 (MacOSX 编译) 55``` 56 57下面演示Windows10使用Visual Studio2019编译 58 59复制msvc文件夹到一个比较清爽的位置,内部结构如下: 60 61 62 63VS打开capstone.sln项目文件,解决方案自动载入这些 64 65 66 67可以看到支持的所有语言都在这里了,如果都需要的话,直接编译就好了,只需要其中几种,则右键解决方案->属性->配置属性 如下 68 69 70 71生成选项中勾选你需要的支持项即可 72编译后会在当前文件夹Debug目录下生成capstone.lib静态编译库和capstone.dll动态库这样就可以开始使用Capstone进行开发了 73 74如果不想自己编译,官方也提供了官方编译版本 75 76Win32: https://github.com/capstone-engine/capstone/releases/download/4.0.2/capstone-4.0.2-win32.zip 77 78Win64: https://github.com/capstone-engine/capstone/releases/download/4.0.2/capstone-4.0.2-win64.zip 79 80选x32或x64将影响后面开发的位数 81 82 83 84### 引擎调用测试 85 86新建一个VS项目,将capstone\include\capstone中的头文件以及编译好的lib和dll文件全部拷贝到新建项目的主目录下 87 88 89 90在VS解决方案中,头文件添加现有项capstone.h,资源文件中添加capstone.lib,重新生成解决方案 91 92 93 94那么现在来测试一下我们自己的capstone引擎吧 95 96主文件写入如下代码 97 98<details><summary> Code </summary> 99 100```c++ 101#include <iostream> 102#include <stdio.h> 103#include <cinttypes> 104#include "capstone.h" 105using namespace std; 106 107#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00" 108 109int main(void) 110{ 111 csh handle; 112 cs_insn* insn; 113 size_t count; 114 115 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 116 printf("ERROR: Failed to initialize engine!\n"); 117 return -1; 118 } 119 120 count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn); 121 if (count) { 122 size_t j; 123 124 for (j = 0; j < count; j++) { 125 printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); 126 } 127 128 cs_free(insn, count); 129 } 130 else 131 printf("ERROR: Failed to disassemble given code!\n"); 132 133 cs_close(&handle); 134 135 return 0; 136} 137``` 138 139</details> 140 141运行结果 142 143 144 145 146## 0x1 数据类型 147 148### csh 149 150用于生成调用capstone API的句柄 151 152```cpp 153size_t csh 154``` 155 156> 用法: `csh handle;` 157 158 159### cs_arch 160 161架构选择 162 163<details><summary> Code </summary> 164 165```cpp 166 enum cs_arch { 167 CS_ARCH_ARM = 0, ///< ARM 架构 (包括 Thumb, Thumb-2) 168 CS_ARCH_ARM64, ///< ARM-64, 也叫 AArch64 169 CS_ARCH_MIPS, ///< Mips 架构 170 CS_ARCH_X86, ///< X86 架构 (包括 x86 & x86-64) 171 CS_ARCH_PPC, ///< PowerPC 架构 172 CS_ARCH_SPARC, ///< Sparc 架构 173 CS_ARCH_SYSZ, ///< SystemZ 架构 174 CS_ARCH_XCORE, ///< XCore 架构 175 CS_ARCH_M68K, ///< 68K 架构 176 CS_ARCH_TMS320C64X, ///< TMS320C64x 架构 177 CS_ARCH_M680X, ///< 680X 架构 178 CS_ARCH_EVM, ///< Ethereum 架构 179 CS_ARCH_MAX, 180 CS_ARCH_ALL = 0xFFFF, // All 架构 - for cs_support() 181} cs_arch; 182``` 183 184</details> 185 186> 用法:API中cs_arch参数填入枚举内容,如API中cs_open(cs_arch arch, cs_mode mode, csh *handle);第一个参数填CS_ARCH_X86则支持X86 架构 187 188 189### cs_mode 190 191模式选择 192 193<details><summary> Code </summary> 194 195```cpp 196enum cs_mode { 197 CS_MODE_LITTLE_ENDIAN = 0, ///< little-endian 模式 (default 模式) 198 CS_MODE_ARM = 0, ///< 32-bit ARM 199 CS_MODE_16 = 1 << 1, ///< 16-bit 模式 (X86) 200 CS_MODE_32 = 1 << 2, ///< 32-bit 模式 (X86) 201 CS_MODE_64 = 1 << 3, ///< 64-bit 模式 (X86, PPC) 202 CS_MODE_THUMB = 1 << 4, ///< ARM's Thumb 模式, 包括 Thumb-2 203 CS_MODE_MCLASS = 1 << 5, ///< ARM's Cortex-M 系列 204 CS_MODE_V8 = 1 << 6, ///< ARMv8 A32解码方式 205 CS_MODE_MICRO = 1 << 4, ///< MicroMips 模式 (MIPS) 206 CS_MODE_MIPS3 = 1 << 5, ///< Mips III ISA 207 CS_MODE_MIPS32R6 = 1 << 6, ///< Mips32r6 ISA 208 CS_MODE_MIPS2 = 1 << 7, ///< Mips II ISA 209 CS_MODE_V9 = 1 << 4, ///< SparcV9 模式 (Sparc) 210 CS_MODE_QPX = 1 << 4, ///< Quad Processing eXtensions 模式 (PPC) 211 CS_MODE_SPE = 1 << 5, ///< Signal Processing Engine 模式 (PPC) 212 CS_MODE_BOOKE = 1 << 6, ///< Book-E 模式 (PPC) 213 CS_MODE_M68K_000 = 1 << 1, ///< M68K 68000 模式 214 CS_MODE_M68K_010 = 1 << 2, ///< M68K 68010 模式 215 CS_MODE_M68K_020 = 1 << 3, ///< M68K 68020 模式 216 CS_MODE_M68K_030 = 1 << 4, ///< M68K 68030 模式 217 CS_MODE_M68K_040 = 1 << 5, ///< M68K 68040 模式 218 CS_MODE_M68K_060 = 1 << 6, ///< M68K 68060 模式 219 CS_MODE_BIG_ENDIAN = 1 << 31, ///< big-endian 模式 220 CS_MODE_MIPS32 = CS_MODE_32, ///< Mips32 ISA (Mips) 221 CS_MODE_MIPS64 = CS_MODE_64, ///< Mips64 ISA (Mips) 222 CS_MODE_M680X_6301 = 1 << 1, ///< M680X Hitachi 6301,6303 模式 223 CS_MODE_M680X_6309 = 1 << 2, ///< M680X Hitachi 6309 模式 224 CS_MODE_M680X_6800 = 1 << 3, ///< M680X Motorola 6800,6802 模式 225 CS_MODE_M680X_6801 = 1 << 4, ///< M680X Motorola 6801,6803 模式 226 CS_MODE_M680X_6805 = 1 << 5, ///< M680X Motorola/Freescale 6805 模式 227 CS_MODE_M680X_6808 = 1 << 6, ///< M680X Motorola/Freescale/NXP 68HC08 模式 228 CS_MODE_M680X_6809 = 1 << 7, ///< M680X Motorola 6809 模式 229 CS_MODE_M680X_6811 = 1 << 8, ///< M680X Motorola/Freescale/NXP 68HC11 模式 230 CS_MODE_M680X_CPU12 = 1 << 9, ///< M680X Motorola/Freescale/NXP CPU12 231 ///< 用于 M68HC12/HCS12 232 CS_MODE_M680X_HCS08 = 1 << 10, ///< M680X Freescale/NXP HCS08 模式 233 CS_MODE_BPF_CLASSIC = 0, ///< Classic BPF 模式 (默认) 234 CS_MODE_BPF_EXTENDED = 1 << 0, ///< Extended BPF 模式 235 CS_MODE_RISCV32 = 1 << 0, ///< RISCV RV32G 236 CS_MODE_RISCV64 = 1 << 1, ///< RISCV RV64G 237 CS_MODE_RISCVC = 1 << 2, ///< RISCV 压缩指令模式 238 CS_MODE_MOS65XX_6502 = 1 << 1, ///< MOS65XXX MOS 6502 239 CS_MODE_MOS65XX_65C02 = 1 << 2, ///< MOS65XXX WDC 65c02 240 CS_MODE_MOS65XX_W65C02 = 1 << 3, ///< MOS65XXX WDC W65c02 241 CS_MODE_MOS65XX_65816 = 1 << 4, ///< MOS65XXX WDC 65816, 8-bit m/x 242 CS_MODE_MOS65XX_65816_LONG_M = (1 << 5), ///< MOS65XXX WDC 65816, 16-bit m, 8-bit x 243 CS_MODE_MOS65XX_65816_LONG_X = (1 << 6), ///< MOS65XXX WDC 65816, 8-bit m, 16-bit x 244 CS_MODE_MOS65XX_65816_LONG_MX = CS_MODE_MOS65XX_65816_LONG_M | CS_MODE_MOS65XX_65816_LONG_X, 245} cs_mode; 246``` 247 248</details> 249 250> 用法:API中cs_mode参数填入枚举内容,如API中cs_open(cs_arch arch, cs_mode mode, csh *handle);第二个参数填CS_MODE_64则支持X64模式 251 252 253### cs_opt_mem 254 255内存操作 256 257<details><summary> Code </summary> 258 259```cpp 260struct cs_opt_mem { 261 cs_malloc_t malloc; 262 cs_calloc_t calloc; 263 cs_realloc_t realloc; 264 cs_free_t free; 265 cs_vsnprintf_t vsnprintf; 266} cs_opt_mem; 267``` 268 269</details> 270 271> 用法:可使用用户自定义的malloc/calloc/realloc/free/vsnprintf()函数,默认使用系统自带malloc(), calloc(), realloc(), free() & vsnprintf() 272 273 274### cs_opt_mnem 275 276自定义助记符 277 278<details><summary> Code </summary> 279 280```cpp 281struct cs_opt_mnem { 282 /// 需要自定义的指令ID 283 unsigned int id; 284 /// 自定义的助记符 285 const char *mnemonic; 286} cs_opt_mnem; 287``` 288 289</details> 290 291 292### cs_opt_type 293 294反编译的运行时选项 295 296<details><summary> Code </summary> 297 298```cpp 299enum cs_opt_type { 300 CS_OPT_INVALID = 0, ///< 无特殊要求 301 CS_OPT_SYNTAX, ///< 汇编输出语法 302 CS_OPT_DETAIL, ///< 将指令结构分解为多个细节 303 CS_OPT_MODE, ///< 运行时改变引擎模式 304 CS_OPT_MEM, ///< 用户定义的动态内存相关函数 305 CS_OPT_SKIPDATA, ///< 在反汇编时跳过数据。然后引擎将处于SKIPDATA模式 306 CS_OPT_SKIPDATA_SETUP, ///< 为SKIPDATA选项设置用户定义函数 307 CS_OPT_MNEMONIC, ///<自定义指令助记符 308 CS_OPT_UNSIGNED, ///< 以无符号形式打印立即操作数 309} cs_opt_type; 310``` 311 312</details> 313 314> 用法:API cs_option(csh handle, cs_opt_type type, size_t value);中第二个参数 315 316 317### cs_opt_value 318 319运行时选项值(与cs_opt_type关联) 320 321<details><summary> Code </summary> 322 323```cpp 324enum cs_opt_value { 325 CS_OPT_OFF = 0, ///< 关闭一个选项 - 默认为CS_OPT_DETAIL, CS_OPT_SKIPDATA, CS_OPT_UNSIGNED. 326 CS_OPT_ON = 3, ///< 打开一个选项 (CS_OPT_DETAIL, CS_OPT_SKIPDATA). 327 CS_OPT_SYNTAX_DEFAULT = 0, ///< 默认asm语法 (CS_OPT_SYNTAX). 328 CS_OPT_SYNTAX_INTEL, ///< X86 Intel asm语法 - 默认开启 X86 (CS_OPT_SYNTAX). 329 CS_OPT_SYNTAX_ATT, ///< X86 ATT 汇编语法 (CS_OPT_SYNTAX). 330 CS_OPT_SYNTAX_NOREGNAME, ///< 只打印寄存器名和编号 (CS_OPT_SYNTAX) 331 CS_OPT_SYNTAX_MASM, ///< X86 Intel Masm 语法 (CS_OPT_SYNTAX). 332 CS_OPT_SYNTAX_MOTOROLA, ///< MOS65XX 用 $ 作为hex头 333} cs_opt_value; 334``` 335 336</details> 337 338> 用法:API cs_option(csh handle, cs_opt_type type, size_t value);中第三个参数 339 340 341### cs_op_type 342 343通用指令操作数类型,在所有架构中保持一致 344 345<details><summary> Code </summary> 346 347```cpp 348enum cs_op_type { 349 CS_OP_INVALID = 0, ///< 未初始化/无效的操作数 350 CS_OP_REG, ///< 寄存器操作数 351 CS_OP_IMM, ///< 立即操作数 352 CS_OP_MEM, ///< 内存操作数 353 CS_OP_FP, ///< 浮点数 354} cs_op_type; 355``` 356 357</details> 358 359> 目前开放的API中未调用 360 361 362### cs_ac_type 363 364通用指令操作数访问类型,在所有架构中保持一致 365可以组合访问类型,例如:CS_AC_READ | CS_AC_WRITE 366 367<details><summary> Code </summary> 368 369```cpp 370enum cs_ac_type { 371 CS_AC_INVALID = 0, ///< 未初始化/无效的访问类型 372 CS_AC_READ = 1 << 0, ///< 操作数从内存或寄存器中读取 373 CS_AC_WRITE = 1 << 1, ///< 操作数从内存或寄存器中写入 374} cs_ac_type; 375``` 376 377</details> 378 379> 目前开放的API中未调用 380 381 382### cs_group_type 383 384公共指令组,在所有架构中保持一致 385 386<details><summary> Code </summary> 387 388```cpp 389cs_group_type { 390 CS_GRP_INVALID = 0, ///< 未初始化/无效指令组 391 CS_GRP_JUMP, ///< 所有跳转指令(条件跳转+直接跳转+间接跳转) 392 CS_GRP_CALL, ///< 所有调用指令 393 CS_GRP_RET, ///< 所有返回指令 394 CS_GRP_INT, ///< 所有中断指令(int+syscall) 395 CS_GRP_IRET, ///< 所有中断返回指令 396 CS_GRP_PRIVILEGE, ///< 所有特权指令 397 CS_GRP_BRANCH_RELATIVE, ///< 所有相关分支指令 398} cs_group_type; 399``` 400 401</details> 402 403> 目前开放的API中未调用 404 405 406### cs_opt_skipdata 407 408用户自定义设置SKIPDATA选项 409 410<details><summary> Code </summary> 411 412```cpp 413struct cs_opt_skipdata { 414 /// Capstone认为要跳过的数据是特殊的“指令” 415 /// 用户可以在这里指定该指令的“助记符”字符串 416 /// 默认情况下(@mnemonic为NULL), Capstone使用“.byte” 417 const char *mnemonic; 418 419 /// 用户定义的回调函数,当Capstone命中数据时调用 420 /// 如果这个回调返回的值是正数(>0),Capstone将跳过这个字节数并继续。如果回调返回0,Capstone将停止反汇编并立即从cs_disasm()返回 421 /// 注意:如果这个回调指针为空,Capstone会根据架构跳过一些字节,如下所示: 422 /// Arm: 2 bytes (Thumb mode) or 4 bytes. 423 /// Arm64: 4 bytes. 424 /// Mips: 4 bytes. 425 /// M680x: 1 byte. 426 /// PowerPC: 4 bytes. 427 /// Sparc: 4 bytes. 428 /// SystemZ: 2 bytes. 429 /// X86: 1 bytes. 430 /// XCore: 2 bytes. 431 /// EVM: 1 bytes. 432 /// RISCV: 4 bytes. 433 /// WASM: 1 bytes. 434 /// MOS65XX: 1 bytes. 435 /// BPF: 8 bytes. 436 cs_skipdata_cb_t callback; // 默认值为 NULL 437 438 /// 用户自定义数据将被传递给@callback函数指针 439 void *user_data; 440} cs_opt_skipdata; 441``` 442 443</details> 444 445> 目前开放的API中未调用 446 447 448### cs_detail 449 450注意:只有当CS_OPT_DETAIL = CS_OPT_ON时,cs_detail中的所有信息才可用 451 452在arch/ARCH/ARCHDisassembler.c的ARCH_getInstruction中初始化为memset(., 0, offsetof(cs_detail, ARCH)+sizeof(cs_ARCH)) 453 454如果cs_detail发生了变化,特别是在union之后添加了字段,那么相应地更新arch/ arch/ archdisassembly.c 455 456<details><summary> Code </summary> 457 458```cpp 459struct cs_detail { 460 uint16_t regs_read[16]; ///< 这个参数读取隐式寄存器列表 461 uint8_t regs_read_count; ///< 这个参数读取隐式寄存器计数 462 463 uint16_t regs_write[20]; ///< 这个参数修改隐式寄存器列表 464 uint8_t regs_write_count; ///< 这个参数修改隐式寄存器计数 465 466 uint8_t groups[8]; ///< 此指令所属的指令组的列表 467 uint8_t groups_count; ///< 此指令所属的组的数 468 469 /// 特定于体系结构的信息 470 union { 471 cs_x86 x86; ///< X86 架构, 包括 16-bit, 32-bit & 64-bit 模式 472 cs_arm64 arm64; ///< ARM64 架构 (aka AArch64) 473 cs_arm arm; ///< ARM 架构 (包括 Thumb/Thumb2) 474 cs_m68k m68k; ///< M68K 架构 475 cs_mips mips; ///< MIPS 架构 476 cs_ppc ppc; ///< PowerPC 架构 477 cs_sparc sparc; ///< Sparc 架构 478 cs_sysz sysz; ///< SystemZ 架构 479 cs_xcore xcore; ///< XCore 架构 480 cs_tms320c64x tms320c64x; ///< TMS320C64x 架构 481 cs_m680x m680x; ///< M680X 架构 482 cs_evm evm; ///< Ethereum 架构 483 cs_mos65xx mos65xx; ///< MOS65XX 架构 (包含 MOS6502) 484 cs_wasm wasm; ///< Web Assembly 架构 485 cs_bpf bpf; ///< Berkeley Packet Filter 架构 (包含 eBPF) 486 cs_riscv riscv; ///< RISCV 架构 487 }; 488} cs_detail; 489``` 490 491</details> 492 493 494### cs_insn 495 496指令的详细信息 497 498<details><summary> Code </summary> 499 500```cpp 501struct cs_insn { 502 /// 指令ID(基本上是一个用于指令助记符的数字ID) 503 /// 应在相应架构的头文件中查找'[ARCH]_insn' enum中的指令id,如ARM.h中的'arm_insn'代表ARM, X86.h中的'x86_insn'代表X86等… 504 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 505 /// 注意:在Skipdata模式下,这个id字段的“data”指令为0 506 unsigned int id; 507 508 /// 指令地址 (EIP) 509 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 510 uint64_t address; 511 512 /// 指令长度 513 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 514 uint16_t size; 515 516 /// 此指令的机器码,其字节数由上面的@size表示 517 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 518 uint8_t bytes[24]; 519 520 /// 指令的Ascii文本助记符 521 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 522 char mnemonic[CS_MNEMONIC_SIZE]; 523 524 /// 指令操作数的Ascii文本 525 /// 即使在CS_OPT_DETAIL = CS_OPT_OFF时也可以使用此信息 526 char op_str[160]; 527 528 /// cs_detail指针 529 /// 注意:只有同时满足以下两个要求时,detail指针才有效: 530 /// (1) CS_OP_DETAIL = CS_OPT_ON 531 /// (2) 引擎未处于Skipdata模式(CS_OP_SKIPDATA选项设置为CS_OPT_ON) 532 /// 533 /// 注意2:当处于Skipdata模式或detail模式关闭时,即使这个指针不是NULL,它的内容仍然是不相关的。 534 cs_detail *detail; 535} cs_insn; 536``` 537 538</details> 539 540 541### cs_err 542 543Capstone API遇到的各类型的错误时cs_errno()的返回值 544 545<details><summary> Code </summary> 546 547```cpp 548typedef enum cs_err { 549 CS_ERR_OK = 0, ///< 无错误 550 CS_ERR_MEM, ///< 内存不足: cs_open(), cs_disasm(), cs_disasm_iter() 551 CS_ERR_ARCH, ///< 不支持的架构: cs_open() 552 CS_ERR_HANDLE, ///<句柄不可用: cs_op_count(), cs_op_index() 553 CS_ERR_CSH, ///< csh参数不可用: cs_close(), cs_errno(), cs_option() 554 CS_ERR_MODE, ///< 无效的或不支持的模式: cs_open() 555 CS_ERR_OPTION, ///< 无效的或不支持的选项: cs_option() 556 CS_ERR_DETAIL, ///< 信息不可用,因为detail选项是关闭的 557 CS_ERR_MEMSETUP, ///< 动态内存管理未初始化(见 CS_OPT_MEM) 558 CS_ERR_VERSION, ///< 不支持版本 (bindings) 559 CS_ERR_DIET, ///< 在“diet”引擎中访问不相关的数据 560 CS_ERR_SKIPDATA, ///< 在SKIPDATA模式下访问与“数据”指令无关的数据 561 CS_ERR_X86_ATT, ///< X86 AT&T 语法不支持(在编译时退出) 562 CS_ERR_X86_INTEL, ///< X86 Intel 语法不支持(在编译时退出) 563 CS_ERR_X86_MASM, ///< X86 Intel 语法不支持(在编译时退出) 564} cs_err; 565``` 566 567</details> 568 569 570## 0x2 API 571 572### cs_version 573 574`unsigned int CAPSTONE_API cs_version(int *major, int *minor);` 575 576用来输出capstone版本号 577 578``` 579major: API主版本 580minor: API次版本 581return: 返回主次版本的16进制,如4.0版本返回 0x0400 582``` 583 584该版本定义于cs.c中,编译后不可更改,不接受自定义版本 585 586 587 588 589 590 591<details><summary> 示例1 </summary> 592 593```c 594#include <stdio.h> 595#include <stdlib.h> 596 597#include "platform.h" 598#include "capstone.h" 599 600static int test() 601{ 602 return cs_version(NULL, NULL); 603} 604 605int main() 606{ 607 int version = test(); 608 printf("%X", version); 609 return 0; 610} 611``` 612 613</details> 614 615 616 617 618<details><summary> 示例2,强行修改版本 </summary> 619 620```cpp 621#include <stdio.h> 622#include <stdlib.h> 623 624#include "platform.h" 625#include "capstone.h" 626 627static int test() 628{ 629 int ma[] = { 5 }; 630 int mi[] = { 6 }; 631 632 return cs_version(ma, mi); 633} 634 635int main() 636{ 637 int version = test(); 638 printf("%X", version); 639 return 0; 640} 641``` 642 643</details> 644 645 646 647可见并不能改变 648 649### cs_support 650 651`bool CAPSTONE_API cs_support(int query);` 652 653用来检查capstone库是否支持参数输入的架构或处于某编译选项 654 655<details><summary> 源码实现 </summary> 656 657 658```cpp 659bool CAPSTONE_API cs_support(int query) 660{ 661 if (query == CS_ARCH_ALL) 662 return all_arch == ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_ARM64) | 663 (1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) | 664 (1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) | 665 (1 << CS_ARCH_SYSZ) | (1 << CS_ARCH_XCORE) | 666 (1 << CS_ARCH_M68K) | (1 << CS_ARCH_TMS320C64X) | 667 (1 << CS_ARCH_M680X) | (1 << CS_ARCH_EVM)); 668 669 if ((unsigned int)query < CS_ARCH_MAX) 670 return all_arch & (1 << query); 671 672 if (query == CS_SUPPORT_DIET) { 673#ifdef CAPSTONE_DIET 674 return true; 675#else 676 return false; 677#endif 678 } 679 680 if (query == CS_SUPPORT_X86_REDUCE) { 681#if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE) 682 return true; 683#else 684 return false; 685#endif 686 } 687 688 // unsupported query 689 return false; 690} 691``` 692 693</details> 694 695示例1(CS_ARCH_ALL,检查是否支持所有架构) 696 697 698 699示例2(CS_ARCH_*,检查是否支持指定架构) 700 701 702 703示例3(检查是否处于DIET编译模式): 704 705 706 707示例4(检查是否处于X86_REDUCE编译模式) 708 709 710 711 712### cs_malloc_t 713 714`void* (CAPSTONE_API *cs_malloc_t)(size_t size);` 715 716cs的动态内存分配,用于 717 718```cpp 719struct cs_opt_mem { 720 cs_malloc_t malloc; 721 cs_calloc_t calloc; 722 cs_realloc_t realloc; 723 cs_free_t free; 724 cs_vsnprintf_t vsnprintf; 725} cs_opt_mem; 726``` 727 728在用户模式下,cs_mem_malloc默认使用系统malloc 729 730Windows driver模式下,`cs_malloc_t cs_mem_malloc = cs_winkernel_malloc;` 731 732cs_winkernel_malloc定义于\capstone-4.0.1\windows\winkernel_mm.c, 733 734<details><summary> 源码实现 </summary> 735 736```cpp 737void * CAPSTONE_API cs_winkernel_malloc(size_t size) 738{ 739 // 长度不能分配为0 740 NT_ASSERT(size); 741 742 // FP; NonPagedPool用于支持 Windows 7 743#pragma prefast(suppress : 30030) // 分配可执行的POOL_TYPE内存 744 size_t number_of_bytes = 0; 745 CS_WINKERNEL_MEMBLOCK *block = NULL; 746 // 特定的值能造成溢出 747 // 如果value中的和超出或低于类型容量,函数将返回NULL。 748 if (!NT_SUCCESS(RtlSizeTAdd(size, sizeof(CS_WINKERNEL_MEMBLOCK), &number_of_bytes))) { 749 return NULL; 750 } 751 block = (CS_WINKERNEL_MEMBLOCK *)ExAllocatePoolWithTag( 752 NonPagedPool, number_of_bytes, CS_WINKERNEL_POOL_TAG); 753 if (!block) { 754 return NULL; 755 } 756 block->size = size; 757 758 return block->data; 759} 760``` 761 762</details> 763 764> OSX kernel模式下,`cs_malloc_t cs_mem_malloc = kern_os_malloc;`,这里暂且不探讨。 765 766 767### cs_calloc_t 768 769`void* (CAPSTONE_API *cs_calloc_t)(size_t nmemb, size_t size);` 770 771cs申请内存并初始化 772 773用于`struct cs_opt_mem`,定义于cs.c 774 775用户模式: `cs_calloc_t cs_mem_calloc = calloc;`,使用系统calloc 776 777Windows driver模式: `cs_calloc_t cs_mem_calloc = cs_winkernel_calloc;` 778 779<details><summary> 源码实现 </summary> 780 781```cpp 782void * CAPSTONE_API cs_winkernel_calloc(size_t n, size_t size) 783{ 784 size_t total = n * size; 785 786 void *new_ptr = cs_winkernel_malloc(total); 787 if (!new_ptr) { 788 return NULL; 789 } 790 791 return RtlFillMemory(new_ptr, total, 0); 792} 793``` 794 795</details> 796 797> OSX kernel模式: `cs_calloc_t cs_mem_calloc = cs_kern_os_calloc;` 直接调用kern_os_malloc 798 799 800### cs_realloc_t 801 802`void* (CAPSTONE_API *cs_realloc_t)(void *ptr, size_t size);` 803 804cs重新分配内存 805 806用于`struct cs_opt_mem`,定义于cs.c 807 808用户模式: `cs_realloc_t cs_mem_realloc = realloc;`,调用系统realloc 809 810Windows driver模式: `cs_realloc_t cs_mem_realloc = cs_winkernel_realloc;` 811 812<details><summary> 源码实现 </summary> 813 814```cpp 815void * CAPSTONE_API cs_winkernel_realloc(void *ptr, size_t size) 816{ 817 void *new_ptr = NULL; 818 size_t current_size = 0; 819 size_t smaller_size = 0; 820 821 if (!ptr) { 822 return cs_winkernel_malloc(size); 823 } 824 825 new_ptr = cs_winkernel_malloc(size); 826 if (!new_ptr) { 827 return NULL; 828 } 829 830 current_size = CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data)->size; 831 smaller_size = (current_size < size) ? current_size : size; 832 RtlCopyMemory(new_ptr, ptr, smaller_size); 833 cs_winkernel_free(ptr); 834 835 return new_ptr; 836} 837``` 838 839</details> 840 841> OSX kernel模式: `cs_realloc_t cs_mem_realloc = kern_os_realloc;` 842 843 844### cs_free_t 845 846`typedef void (CAPSTONE_API *cs_free_t)(void *ptr);` 847 848cs释放内存 849 850用于`struct cs_opt_mem`,定义于cs.c 851 852用户模式: `cs_free_t cs_mem_free = free;`,调用系统free 853 854Windows driver模式: `cs_free_t cs_mem_free = cs_winkernel_free;` 855 856<details><summary> 源码实现 </summary> 857 858```cpp 859void CAPSTONE_API cs_winkernel_free(void *ptr) 860{ 861 if (ptr) { 862 ExFreePoolWithTag(CONTAINING_RECORD(ptr, CS_WINKERNEL_MEMBLOCK, data), CS_WINKERNEL_POOL_TAG); 863 } 864} 865``` 866 867</details> 868 869> OSX kernel模式: `cs_free_t cs_mem_free = kern_os_free;` 870 871 872 873### cs_vsnprintf_t 874 875`int (CAPSTONE_API *cs_vsnprintf_t)(char *str, size_t size, const char *format, va_list ap);` 876 877按size大小输出到字符串str中 878 879如果系统为wince,将使用_vsnprintf函数 880 881vsnprintf ()和_vsnprintf()对于驱动程序都是可用的,但是它们有一些不同 882 883在需要返回值和设置空终止符时应使用vsnprintf() 884 885Windows driver模式: `cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf;` 886 887<details><summary> 源码实现 </summary> 888 889```cpp 890int CAPSTONE_API cs_winkernel_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr) 891{ 892 int result = _vsnprintf(buffer, count, format, argptr); 893 894 // _vsnprintf()在字符串被截断时返回-1,在整个字符串被存储但“buffer”末尾没有“\0”时返回“count”。在这两种情况下,都需要手动添加空终止符。 895 if (result == -1 || (size_t)result == count) { 896 buffer[count - 1] = '\0'; 897 } 898 899 if (result == -1) { 900 // 在返回-1时,函数必须获取并返回一些本来要写入的字符。因此,通过重试使用temp buffer进行相同的转换,这个缓冲区就可能足够大来完成格式化,并且获得很多本应写入的字符。 901 char* tmp = cs_winkernel_malloc(0x1000); 902 if (!tmp) { 903 return result; 904 } 905 906 result = _vsnprintf(tmp, 0x1000, format, argptr); 907 NT_ASSERT(result != -1); 908 cs_winkernel_free(tmp); 909 } 910 911 return result; 912} 913``` 914 915</details> 916 917> OSX kernel模式: `cs_vsnprintf_t cs_vsnprintf = vsnprintf;`,使用默认vsnprintf 918 919 920 921### cs_skipdata_cb_t 922 923`size_t (CAPSTONE_API *cs_skipdata_cb_t)(const uint8_t *code, size_t code_size, size_t offset, void *user_data);` 924 925SKIPDATA选项的用户自定义回调函数。 926 927``` 928code:包含要分解的代码的输入缓冲区。和传递给cs_disasm()的缓冲区相同。 929code_size:上面的code缓冲区的大小(以字节为单位)。 930offset:上面提到的输入缓冲区code中当前检查字节的位置。 931user_data:用户数据通过cs_opt_skipdata结构中的@user_data字段传递给cs_option()。 932return:返回要跳过的字节数,或者0表示立即停止反汇编。 933``` 934 935cs_skipdata_cb_t在`struct cs_opt_skipdata`中调用 936 937<details><summary> 示例 </summary> 938 939```cpp 940#include <stdio.h> 941#include <stdlib.h> 942 943#include "platform.h" 944#include "capstone.h" 945 946struct platform { 947 cs_arch arch; 948 cs_mode mode; 949 unsigned char* code; 950 size_t size; 951 const char* comment; 952 cs_opt_type opt_type; 953 cs_opt_value opt_value; 954 cs_opt_type opt_skipdata; 955 size_t skipdata; 956}; 957 958static void print_string_hex(unsigned char* str, size_t len) //输出机器码 959{ 960 unsigned char* c; 961 962 printf("Code: "); 963 for (c = str; c < str + len; c++) { 964 printf("0x%02x ", *c & 0xff); 965 } 966 printf("\n"); 967} 968 969static void test() 970{ 971 972#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92" //测试用机器码 973 974#define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" 975 976 cs_opt_skipdata skipdata = { 977 // 把默认 "data" 描述符从 ".byte" 重命名为 "db" 978 "db", 979 }; 980 981 struct platform platforms[2] = { //以默认描述符和自定义描述符两种方式建立一个数组 982 { 983 CS_ARCH_X86, 984 CS_MODE_32, 985 (unsigned char*)X86_CODE32, 986 sizeof(X86_CODE32) - 1, 987 "X86 32 (Intel syntax) - Skip data", 988 }, 989 { 990 CS_ARCH_X86, 991 CS_MODE_32, 992 (unsigned char*)X86_CODE32, 993 sizeof(X86_CODE32) - 1, 994 "X86 32 (Intel syntax) - Skip data with custom mnemonic", 995 CS_OPT_INVALID, 996 CS_OPT_OFF, 997 CS_OPT_SKIPDATA_SETUP, 998 (size_t)& skipdata, 999 }, 1000 1001 }; 1002 1003 csh handle; //建立capstone句柄 1004 uint64_t address = 0x1000; //设置起始地址 1005 cs_insn* insn; //具体信息结构体 1006 cs_err err; //错误枚举 1007 int i; 1008 size_t count; //成功反汇编行数 1009 1010 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 1011 printf("****************\n"); 1012 printf("Platform: %s\n", platforms[i].comment); 1013 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); //错误检查 1014 if (err) { 1015 printf("Failed on cs_open() with error returned: %u\n", err); 1016 abort(); 1017 } 1018 1019 if (platforms[i].opt_type) 1020 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 1021 1022 // 打开SKIPDATA 模式 1023 cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); 1024 cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata); 1025 1026 count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); 1027 if (count) { 1028 size_t j; 1029 1030 print_string_hex(platforms[i].code, platforms[i].size); 1031 printf("Disasm:\n"); 1032 1033 for (j = 0; j < count; j++) { //输出汇编 1034 printf("0x%" PRIx64 ":\t%s\t\t%s\n", 1035 insn[j].address, insn[j].mnemonic, insn[j].op_str); 1036 } 1037 1038 // 最后一行代码后打印偏移 1039 printf("0x%" PRIx64 ":\n", insn[j - 1].address + insn[j - 1].size); 1040 1041 // 释放cs_disasm()申请的内存 1042 cs_free(insn, count); 1043 } 1044 else { 1045 printf("****************\n"); 1046 printf("Platform: %s\n", platforms[i].comment); 1047 print_string_hex(platforms[i].code, platforms[i].size); 1048 printf("ERROR: Failed to disasm given code!\n"); 1049 abort(); 1050 } 1051 1052 printf("\n"); 1053 1054 cs_close(&handle); 1055 } 1056} 1057 1058int main() 1059{ 1060 test(); 1061 1062 return 0; 1063} 1064``` 1065 1066</details> 1067 1068运行结果如下,默认的.byte数据类型被改为db描述符 1069 1070 1071 1072 1073 1074 1075### cs_open 1076 1077`cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle);` 1078 1079初始化cs句柄 1080 1081``` 1082arch: 架构类型 (CS_ARCH_*) 1083mode: 硬件模式. CS_MODE_*在cs_mode数据类型中可查 1084handle: 指向句柄, 返回时更新 1085return: 创建成功返回CS_ERR_OK,否则返回cs_err枚举中对应的错误信息 1086``` 1087 1088<details><summary> 源码实现 </summary> 1089 1090```cpp 1091cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle) 1092{ 1093 cs_err err; 1094 struct cs_struct *ud; 1095 if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc || !cs_mem_free || !cs_vsnprintf) 1096 // Error: 使用cs_open()前, 必须使用cs_option(CS_OPT_MEM)进行动态内存管理的初始化 1097 return CS_ERR_MEMSETUP; 1098 1099 if (arch < CS_ARCH_MAX && cs_arch_init[arch]) { 1100 // 验证架构是否使用,方式:架构在枚举中且可初始化 1101 if (mode & cs_arch_disallowed_mode_mask[arch]) { 1102 *handle = 0; 1103 return CS_ERR_MODE; 1104 } 1105 1106 ud = cs_mem_calloc(1, sizeof(*ud)); 1107 if (!ud) { 1108 // 内存不足 1109 return CS_ERR_MEM; 1110 } 1111 1112 ud->errnum = CS_ERR_OK; 1113 ud->arch = arch; 1114 ud->mode = mode; 1115 // 默认情况指令不打开detail模式 1116 ud->detail = CS_OPT_OFF; 1117 1118 // 默认skipdata设置 1119 ud->skipdata_setup.mnemonic = SKIPDATA_MNEM; 1120 1121 err = cs_arch_init[ud->arch](ud); 1122 if (err) { 1123 cs_mem_free(ud); 1124 *handle = 0; 1125 return err; 1126 } 1127 1128 *handle = (uintptr_t)ud; 1129 1130 return CS_ERR_OK; 1131 } else { 1132 *handle = 0; 1133 return CS_ERR_ARCH; 1134 } 1135} 1136``` 1137 1138其中,cs_struct结构体包含更多细节设定,如下 1139 1140```cpp 1141struct cs_struct { 1142 cs_arch arch; 1143 cs_mode mode; 1144 Printer_t printer; // 打印asm 1145 void *printer_info; // 打印信息 1146 Disasm_t disasm; // 反编译 1147 void *getinsn_info; // 打印辅助信息 1148 GetName_t reg_name; 1149 GetName_t insn_name; 1150 GetName_t group_name; 1151 GetID_t insn_id; 1152 PostPrinter_t post_printer; 1153 cs_err errnum; 1154 ARM_ITStatus ITBlock; // ARM特殊选项 1155 cs_opt_value detail, imm_unsigned; 1156 int syntax; //ARM, Mips & PPC等架构的基本asm语法打印 1157 bool doing_mem; // 在InstPrinter代码中处理内存操作数 1158 unsigned short *insn_cache; //为mapping.c建立缓存索引 1159 GetRegisterName_t get_regname; 1160 bool skipdata; // 如果反编译时要跳过数据,该项设置为True 1161 uint8_t skipdata_size; //要跳过bytes的数量 1162 cs_opt_skipdata skipdata_setup; // 自定义skipdata设置 1163 const uint8_t *regsize_map; //映射register大小 (目前仅支持x86) 1164 GetRegisterAccess_t reg_access; 1165 struct insn_mnem *mnem_list; // 自定义指令助记符的链接list 1166}; 1167``` 1168 1169</details> 1170 1171示例(创建一个x86_64类型的cs句柄) 1172 1173`cs_open(CS_ARCH_X86, CS_MODE_64, &handle)` 1174 1175 1176### cs_close 1177 1178`cs_err CAPSTONE_API cs_close(csh *handle);` 1179 1180释放句柄 1181 1182``` 1183handle: 指向一个cs_open()打开的句柄 1184return: 释放成功返回CS_ERR_OK,否则返回cs_err枚举的错误信息 1185``` 1186 1187释放句柄实质为将句柄值设置为0 1188 1189<details><summary> 源码实现 </summary> 1190 1191```cpp 1192cs_err CAPSTONE_API cs_close(csh *handle) 1193{ 1194 struct cs_struct *ud; 1195 struct insn_mnem *next, *tmp; 1196 1197 if (*handle == 0) 1198 // 句柄不可用 1199 return CS_ERR_CSH; 1200 1201 ud = (struct cs_struct *)(*handle); 1202 1203 if (ud->printer_info) 1204 cs_mem_free(ud->printer_info); 1205 1206 // 释放自定义助记符的链接list 1207 tmp = ud->mnem_list; 1208 while(tmp) { 1209 next = tmp->next; 1210 cs_mem_free(tmp); 1211 tmp = next; 1212 } 1213 1214 cs_mem_free(ud->insn_cache); 1215 1216 memset(ud, 0, sizeof(*ud)); 1217 cs_mem_free(ud); 1218 1219 // handle值设置为0,保证这个句柄在cs_close()释放后不可使用 1220 *handle = 0; 1221 1222 return CS_ERR_OK; 1223} 1224``` 1225 1226</details> 1227 1228示例 1229 1230`cs_close(&handle);` 1231 1232 1233### cs_option 1234 1235`cs_err CAPSTONE_API cs_option(csh handle, cs_opt_type type, size_t value);` 1236 1237反编译引擎的运行时选项 1238 1239``` 1240handle: cs_open()打开的句柄 1241type: 设置选项的类型 1242value: 与type对应的选项值 1243return: 设置成功返回CS_ERR_OK,否则返回cs_err枚举的错误信息 1244``` 1245 1246注意: 在CS_OPT_MEM的情况下,handle可以是任何值,因此cs_option(handle, CS_OPT_MEM, value)必须在cs_open()之前被调用 1247 1248<details><summary> 源码实现 </summary> 1249 1250```cpp 1251cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value) 1252{ 1253 struct cs_struct *handle; 1254 cs_opt_mnem *opt; 1255 1256 // 支持在所有API前支持 (even cs_open()) 1257 if (type == CS_OPT_MEM) { 1258 cs_opt_mem *mem = (cs_opt_mem *)value; 1259 1260 cs_mem_malloc = mem->malloc; 1261 cs_mem_calloc = mem->calloc; 1262 cs_mem_realloc = mem->realloc; 1263 cs_mem_free = mem->free; 1264 cs_vsnprintf = mem->vsnprintf; 1265 1266 return CS_ERR_OK; 1267 } 1268 1269 handle = (struct cs_struct *)(uintptr_t)ud; 1270 if (!handle) 1271 return CS_ERR_CSH; 1272 1273 switch(type) { 1274 default: 1275 break; 1276 1277 case CS_OPT_UNSIGNED: 1278 handle->imm_unsigned = (cs_opt_value)value; 1279 return CS_ERR_OK; 1280 1281 case CS_OPT_DETAIL: 1282 handle->detail = (cs_opt_value)value; 1283 return CS_ERR_OK; 1284 1285 case CS_OPT_SKIPDATA: 1286 handle->skipdata = (value == CS_OPT_ON); 1287 if (handle->skipdata) { 1288 if (handle->skipdata_size == 0) { 1289 handle->skipdata_size = skipdata_size(handle); 1290 } 1291 } 1292 return CS_ERR_OK; 1293 1294 case CS_OPT_SKIPDATA_SETUP: 1295 if (value) 1296 handle->skipdata_setup = *((cs_opt_skipdata *)value); 1297 return CS_ERR_OK; 1298 1299 case CS_OPT_MNEMONIC: 1300 opt = (cs_opt_mnem *)value; 1301 if (opt->id) { 1302 if (opt->mnemonic) { 1303 struct insn_mnem *tmp; 1304 1305 // 添加新指令或替换现有指令 1306 // 查看当前insn释放在list中 1307 tmp = handle->mnem_list; 1308 while(tmp) { 1309 if (tmp->insn.id == opt->id) { 1310 // f找到指令,替换助记符 1311 (void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1); 1312 tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0'; 1313 break; 1314 } 1315 tmp = tmp->next; 1316 } 1317 1318 // 2. 如果没有就添加这条指令 1319 if (!tmp) { 1320 tmp = cs_mem_malloc(sizeof(*tmp)); 1321 tmp->insn.id = opt->id; 1322 (void)strncpy(tmp->insn.mnemonic, opt->mnemonic, sizeof(tmp->insn.mnemonic) - 1); 1323 tmp->insn.mnemonic[sizeof(tmp->insn.mnemonic) - 1] = '\0'; 1324 // 新指令放在list最前面 1325 tmp->next = handle->mnem_list; 1326 handle->mnem_list = tmp; 1327 } 1328 return CS_ERR_OK; 1329 } else { 1330 struct insn_mnem *prev, *tmp; 1331 1332 tmp = handle->mnem_list; 1333 prev = tmp; 1334 while(tmp) { 1335 if (tmp->insn.id == opt->id) { 1336 // 删除指令 1337 if (tmp == prev) { 1338 handle->mnem_list = tmp->next; 1339 } else { 1340 prev->next = tmp->next; 1341 } 1342 cs_mem_free(tmp); 1343 break; 1344 } 1345 prev = tmp; 1346 tmp = tmp->next; 1347 } 1348 } 1349 } 1350 return CS_ERR_OK; 1351 1352 case CS_OPT_MODE: 1353 // 验证所请求的模式是否有效 1354 if (value & cs_arch_disallowed_mode_mask[handle->arch]) { 1355 return CS_ERR_OPTION; 1356 } 1357 break; 1358 } 1359 1360 return cs_arch_option[handle->arch](handle, type, value); 1361} 1362``` 1363</details> 1364 1365 1366<details><summary> 示例,更改反汇编后显示的语法 </summary> 1367 1368```cpp 1369#include <iostream> 1370#include <stdio.h> 1371 1372#include "capstone.h" 1373#include "platform.h" 1374 1375using namespace std; 1376 1377#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00" 1378 1379int main(void) 1380{ 1381 csh handle; 1382 cs_insn* insn; 1383 size_t count; 1384 1385 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 1386 printf("ERROR: Failed to initialize engine!\n"); 1387 return -1; 1388 } 1389 cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); // 以AT&T语法显示 1390 count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn); 1391 if (count) { 1392 size_t j; 1393 1394 for (j = 0; j < count; j++) { 1395 printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); 1396 } 1397 1398 cs_free(insn, count); 1399 } 1400 else 1401 printf("ERROR: Failed to disassemble given code!\n"); 1402 1403 cs_close(&handle); 1404 1405 return 0; 1406} 1407``` 1408 1409</details> 1410 1411输出 1412 1413 1414 1415 1416### cs_errno 1417 1418`cs_err CAPSTONE_API cs_errno(csh handle);` 1419 1420API出错时返回错误消息 1421 1422``` 1423handle: cs_open()打开的句柄 1424return: 无错误返回CS_ERR_OK,否则返回cs_err枚举的错误信息 1425``` 1426 1427判断到句柄不存在直接返回CS_ERR_CSH 1428 1429<details><summary> 示例 </summary> 1430 1431```cpp 1432#include <iostream> 1433#include <stdio.h> 1434 1435#include "capstone.h" 1436#include "platform.h" 1437 1438using namespace std; 1439 1440#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00" 1441 1442int main(void) 1443{ 1444 csh handle = 0; 1445 cs_insn* insn; 1446 size_t count; 1447 1448 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 1449 printf("ERROR: Failed to initialize engine!\n"); 1450 return -1; 1451 } 1452 1453 cs_close(&handle); 1454 std::cout << cs_errno(handle); //关闭句柄后检查将报错 1455 return 0; 1456} 1457``` 1458 1459</details> 1460 1461输出,错误码4即CS_ERR_CSH 1462 1463 1464 1465 1466### cs_strerror 1467 1468`const char * CAPSTONE_API cs_strerror(cs_err code);` 1469 1470将上个API输出的错误码转换为详细错误信息 1471 1472<details><summary> 源码实现 </summary> 1473 1474```cpp 1475const char * CAPSTONE_API cs_strerror(cs_err code) 1476{ 1477 switch(code) { 1478 default: 1479 return "Unknown error code"; 1480 case CS_ERR_OK: 1481 return "OK (CS_ERR_OK)"; 1482 case CS_ERR_MEM: 1483 return "Out of memory (CS_ERR_MEM)"; 1484 case CS_ERR_ARCH: 1485 return "Invalid/unsupported architecture(CS_ERR_ARCH)"; 1486 case CS_ERR_HANDLE: 1487 return "Invalid handle (CS_ERR_HANDLE)"; 1488 case CS_ERR_CSH: 1489 return "Invalid csh (CS_ERR_CSH)"; 1490 case CS_ERR_MODE: 1491 return "Invalid mode (CS_ERR_MODE)"; 1492 case CS_ERR_OPTION: 1493 return "Invalid option (CS_ERR_OPTION)"; 1494 case CS_ERR_DETAIL: 1495 return "Details are unavailable (CS_ERR_DETAIL)"; 1496 case CS_ERR_MEMSETUP: 1497 return "Dynamic memory management uninitialized (CS_ERR_MEMSETUP)"; 1498 case CS_ERR_VERSION: 1499 return "Different API version between core & binding (CS_ERR_VERSION)"; 1500 case CS_ERR_DIET: 1501 return "Information irrelevant in diet engine (CS_ERR_DIET)"; 1502 case CS_ERR_SKIPDATA: 1503 return "Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA)"; 1504 case CS_ERR_X86_ATT: 1505 return "AT&T syntax is unavailable (CS_ERR_X86_ATT)"; 1506 case CS_ERR_X86_INTEL: 1507 return "INTEL syntax is unavailable (CS_ERR_X86_INTEL)"; 1508 case CS_ERR_X86_MASM: 1509 return "MASM syntax is unavailable (CS_ERR_X86_MASM)"; 1510 } 1511} 1512``` 1513</details> 1514 1515 1516<details><summary> 示例,结合cs_errno使用 </summary> 1517 1518```cpp 1519#include <iostream> 1520#include <stdio.h> 1521 1522#include "capstone.h" 1523#include "platform.h" 1524 1525using namespace std; 1526 1527#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00" 1528 1529int main(void) 1530{ 1531 csh handle = 0; 1532 cs_insn* insn; 1533 size_t count; 1534 1535 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 1536 printf("ERROR: Failed to initialize engine!\n"); 1537 return -1; 1538 } 1539 1540 cs_close(&handle); 1541 std::cout << cs_strerror(cs_errno(handle)); //直接输出报错信息 1542 return 0; 1543} 1544``` 1545 1546</details> 1547 1548输出 1549 1550 1551 1552 1553### cs_disasm 1554 1555```cpp 1556size_t CAPSTONE_API cs_disasm(csh handle, 1557 const uint8_t *code, size_t code_size, 1558 uint64_t address, 1559 size_t count, 1560 cs_insn **insn); 1561``` 1562 1563给定缓冲区、大小、地址和编号,反编译机器码 1564 1565API动态地分配内存来包含分解的指令,生成的指令将放在*insn中 1566 1567注意: 必须释放分配的内存,以避免内存泄漏。对于需要动态分配稀缺内存的系统(如OS内核或固件),API cs_disasm_iter()可能是比cs_disasm()更好的选择。原因是,使用cs_disasm()时,基于有限的可用内存,必须预先计算要分解多少条指令。 1568 1569``` 1570handle: cs_open()返回的句柄 1571code: 包含要反汇编的机器码的缓冲区。 1572code_size:上面代码缓冲区的大小。 1573address:给定原始代码缓冲区中的第一条指令的地址。 1574insn: 由这个API填写的指令数组。注意: insn将由这个函数分配,应该用cs_free () API释放 1575count: 需要分解的指令数量,或输入0分解所有指令 1576return:成功反汇编指令的数量,如果该函数未能反汇编给定的代码,则为0,失败时,调用cs_errno()获取错误代码。 1577``` 1578 1579<details><summary> 源码实现 </summary> 1580 1581```cpp 1582size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn) 1583{ 1584 struct cs_struct *handle; 1585 MCInst mci; 1586 uint16_t insn_size; 1587 size_t c = 0, i; 1588 unsigned int f = 0; // 缓存中下一条指令的索引 1589 cs_insn *insn_cache; // 缓存反汇编后的指令 1590 void *total = NULL; 1591 size_t total_size = 0; //所有insn的输出缓冲区的总大小 1592 bool r; 1593 void *tmp; 1594 size_t skipdata_bytes; 1595 uint64_t offset_org; // 保存缓冲区的所有原始信息 1596 size_t size_org; 1597 const uint8_t *buffer_org; 1598 unsigned int cache_size = INSN_CACHE_SIZE; 1599 size_t next_offset; 1600 1601 handle = (struct cs_struct *)(uintptr_t)ud; 1602 if (!handle) { 1603 // 修复方式: 1604 // handle->errnum = CS_ERR_HANDLE; 1605 return 0; 1606 } 1607 1608 handle->errnum = CS_ERR_OK; 1609 1610 // 重设ARM架构的IT block 1611 if (handle->arch == CS_ARCH_ARM) 1612 handle->ITBlock.size = 0; 1613 1614#ifdef CAPSTONE_USE_SYS_DYN_MEM 1615 if (count > 0 && count <= INSN_CACHE_SIZE) 1616 cache_size = (unsigned int) count; 1617#endif 1618 1619 // 保存SKIPDATA原始偏移量 1620 buffer_org = buffer; 1621 offset_org = offset; 1622 size_org = size; 1623 1624 total_size = sizeof(cs_insn) * cache_size; 1625 total = cs_mem_malloc(total_size); 1626 if (total == NULL) { 1627 // 内存不足 1628 handle->errnum = CS_ERR_MEM; 1629 return 0; 1630 } 1631 1632 insn_cache = total; 1633 1634 while (size > 0) { 1635 MCInst_Init(&mci); 1636 mci.csh = handle; 1637 1638 mci.address = offset; 1639 1640 if (handle->detail) { 1641 //给detail指针分配内存 1642 insn_cache->detail = cs_mem_malloc(sizeof(cs_detail)); 1643 } else { 1644 insn_cache->detail = NULL; 1645 } 1646 1647 // 为non-detailed模式保存所有信息 1648 mci.flat_insn = insn_cache; 1649 mci.flat_insn->address = offset; 1650#ifdef CAPSTONE_DIET 1651 //mnemonic & op_str0填充 1652 mci.flat_insn->mnemonic[0] = '\0'; 1653 mci.flat_insn->op_str[0] = '\0'; 1654#endif 1655 1656 r = handle->disasm(ud, buffer, size, &mci, &insn_size, offset, handle->getinsn_info); 1657 if (r) { 1658 SStream ss; 1659 SStream_Init(&ss); 1660 1661 mci.flat_insn->size = insn_size; 1662 1663 //将内部指令操作码映射到公共insn ID 1664 handle->insn_id(handle, insn_cache, mci.Opcode); 1665 1666 handle->printer(&mci, &ss, handle->printer_info); 1667 fill_insn(handle, insn_cache, ss.buffer, &mci, handle->post_printer, buffer); 1668 1669 // 调整opcode (X86) 1670 if (handle->arch == CS_ARCH_X86) 1671 insn_cache->id += mci.popcode_adjust; 1672 1673 next_offset = insn_size; 1674 } else { 1675 // 遇到中断指令 1676 1677 // 为detail指针释放内存 1678 if (handle->detail) { 1679 cs_mem_free(insn_cache->detail); 1680 } 1681 1682 if (!handle->skipdata || handle->skipdata_size > size) 1683 break; 1684 1685 if (handle->skipdata_setup.callback) { 1686 skipdata_bytes = handle->skipdata_setup.callback(buffer_org, size_org, 1687 (size_t)(offset - offset_org), handle->skipdata_setup.user_data); 1688 if (skipdata_bytes > size) 1689 break; 1690 1691 if (!skipdata_bytes) 1692 break; 1693 } else 1694 skipdata_bytes = handle->skipdata_size; 1695 1696 insn_cache->id = 0; 1697 insn_cache->address = offset; 1698 insn_cache->size = (uint16_t)skipdata_bytes; 1699 memcpy(insn_cache->bytes, buffer, skipdata_bytes); 1700#ifdef CAPSTONE_DIET 1701 insn_cache->mnemonic[0] = '\0'; 1702 insn_cache->op_str[0] = '\0'; 1703#else 1704 strncpy(insn_cache->mnemonic, handle->skipdata_setup.mnemonic, 1705 sizeof(insn_cache->mnemonic) - 1); 1706 skipdata_opstr(insn_cache->op_str, buffer, skipdata_bytes); 1707#endif 1708 insn_cache->detail = NULL; 1709 1710 next_offset = skipdata_bytes; 1711 } 1712 1713 // 一条新指令进入缓存 1714 f++; 1715 1716 // 反汇编了一条指令 1717 c++; 1718 if (count > 0 && c == count) 1719 break; 1720 1721 if (f == cache_size) { 1722 cache_size = cache_size * 8 / 5; 1723 total_size += (sizeof(cs_insn) * cache_size); 1724 tmp = cs_mem_realloc(total, total_size); 1725 if (tmp == NULL) { //内存不足 1726 if (handle->detail) { 1727 insn_cache = (cs_insn *)total; 1728 for (i = 0; i < c; i++, insn_cache++) 1729 cs_mem_free(insn_cache->detail); 1730 } 1731 1732 cs_mem_free(total); 1733 *insn = NULL; 1734 handle->errnum = CS_ERR_MEM; 1735 return 0; 1736 } 1737 1738 total = tmp; 1739 //在最后一条指令之后继续填充缓存 1740 insn_cache = (cs_insn *)((char *)total + sizeof(cs_insn) * c); 1741 1742 // 将f重置为0,从一开始就填入缓存 1743 f = 0; 1744 } else 1745 insn_cache++; 1746 1747 buffer += next_offset; 1748 size -= next_offset; 1749 offset += next_offset; 1750 } 1751 1752 if (!c) { 1753 //未反汇编任何指令 1754 cs_mem_free(total); 1755 total = NULL; 1756 } else if (f != cache_size) { 1757 // 没有完全使用最后一个缓存,缩小大小 1758 tmp = cs_mem_realloc(total, total_size - (cache_size - f) * sizeof(*insn_cache)); 1759 if (tmp == NULL) { // 内存不足 1760 // 释放所有detail指针 1761 if (handle->detail) { 1762 insn_cache = (cs_insn *)total; 1763 for (i = 0; i < c; i++, insn_cache++) 1764 cs_mem_free(insn_cache->detail); 1765 } 1766 1767 cs_mem_free(total); 1768 *insn = NULL; 1769 1770 handle->errnum = CS_ERR_MEM; 1771 return 0; 1772 } 1773 1774 total = tmp; 1775 } 1776 1777 *insn = total; 1778 1779 return c; 1780} 1781``` 1782 1783</details> 1784 1785 1786<details><summary> 示例,x86_64 </summary> 1787 1788```cpp 1789#include <iostream> 1790#include <stdio.h> 1791 1792#include "capstone.h" 1793#include "platform.h" 1794 1795using namespace std; 1796 1797#define CODE "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 1798 1799int main(void) 1800{ 1801 csh handle = 0; 1802 cs_insn* insn; 1803 size_t count; 1804 1805 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 1806 printf("ERROR: Failed to initialize engine!\n"); 1807 return -1; 1808 } 1809 1810 count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn); //所有指令,基址0x1000,放入insn 1811 if (count) { 1812 size_t j; 1813 1814 for (j = 0; j < count; j++) { 1815 printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); 1816 } 1817 1818 cs_free(insn, count); 1819 } 1820 else 1821 printf("ERROR: Failed to disassemble given code!\n"); 1822 1823 cs_close(&handle); 1824 1825 return 0; 1826} 1827``` 1828 1829</details> 1830 1831输出 1832 1833 1834 1835 1836### cs_free 1837 1838`void CAPSTONE_API cs_free(cs_insn *insn, size_t count);` 1839 1840释放被 cs_malloc() 或 cs_disasm() 分配的内存(insn参数) 1841 1842``` 1843insn: 由cs_disasm()或cs_malloc()中的@insn参数返回的指针 1844count: 赋值由cs_disasm()返回的cs_insn结构的数量,或赋值为1表示由cs_malloc()分配给空闲内存的数量 1845``` 1846 1847<details><summary> 源码实现 </summary> 1848 1849```cpp 1850void CAPSTONE_API cs_free(cs_insn *insn, size_t count) 1851{ 1852 size_t i; 1853 1854 // free 所有 detail 指针 1855 for (i = 0; i < count; i++) 1856 cs_mem_free(insn[i].detail); 1857 1858 cs_mem_free(insn); 1859} 1860``` 1861 1862直接调用cs_mem_free,也就是默认的free 1863 1864</details> 1865 1866 1867<details><summary> 示例(释放cs_disasm申请的内存) </summary> 1868 1869```cpp 1870 count = cs_disasm(handle, (unsigned char*)CODE, sizeof(CODE) - 1, 0x1000, 0, &insn); //计数由cs_disasm申请的内存 1871 if (count) { 1872 size_t j; 1873 1874 for (j = 0; j < count; j++) { 1875 printf("0x%""Ix"":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); 1876 } 1877 1878 cs_free(insn, count); //循环依次释放每条insn的内存 1879 } 1880``` 1881 1882</details> 1883 1884 1885### cs_malloc 1886 1887`cs_insn * CAPSTONE_API cs_malloc(csh handle);` 1888 1889被用于在API cs_disasm_iter()中为一条指令分配内存 1890 1891``` 1892handle: cs_open()返回的句柄 1893``` 1894 1895<details><summary> 源码实现 </summary> 1896 1897```cpp 1898cs_insn * CAPSTONE_API cs_malloc(csh ud) 1899{ 1900 cs_insn *insn; 1901 struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; 1902 1903 insn = cs_mem_malloc(sizeof(cs_insn)); 1904 if (!insn) { 1905 // insufficient memory 1906 handle->errnum = CS_ERR_MEM; 1907 return NULL; 1908 } else { 1909 if (handle->detail) { 1910 // allocate memory for @detail pointer 1911 insn->detail = cs_mem_malloc(sizeof(cs_detail)); 1912 if (insn->detail == NULL) { // insufficient memory 1913 cs_mem_free(insn); 1914 handle->errnum = CS_ERR_MEM; 1915 return NULL; 1916 } 1917 } else 1918 insn->detail = NULL; 1919 } 1920 1921 return insn; 1922} 1923``` 1924 1925</details> 1926 1927当这条指令所占的内存不再使用时,使用cs_free(insn, 1)释放,示例在下面cs_disasm_iter处 1928 1929 1930### cs_disasm_iter 1931 1932```cpp 1933bool CAPSTONE_API cs_disasm_iter(csh handle, 1934 const uint8_t **code, size_t *size, 1935 uint64_t *address, cs_insn *insn); 1936``` 1937 1938给定buff、大小、地址和要解码的指令数,更快速的反汇编机器码, 1939这个API将生成的指令放入insn中的给定的缓存中。 1940 1941注意1: 此API将更新code、size和address以指向输入缓冲区中的下一条指令。所以,虽然每次反汇编一条指令可以使用cs_disasm(count=1)来实现,但一些基准测试显示,在循环中使用cs_disasm_iter()可以方便地快速迭代所有指令,在随机输入时可以快30%。 1942 1943注意2:可以使用cs_malloc()创建insn中的缓存。 1944 1945注意3:对于动态分配内存可能产生内存不足的系统(比如OS内核或固件),建议使用cs_disasm()这个API, 因为cs_disasm()是根据要分解的指令的数量来分配内存。 1946 1947``` 1948handle: cs_open()返回的句柄 1949code: 要反汇编的机器码所在的缓冲区 1950size: 机器码缓冲区的大小 1951address: 所给机器码缓冲区中第一个insn的地址 1952insn: 指向这个API要填充的指令的指针。 1953return:如果这个API成功反汇编了一条指令返回true,否则将返回false。 1954``` 1955 1956失败时,调用cs_errno()获取错误代码。 1957 1958<details><summary> 代码实现,在cs_disasm基础上使用动态内存分配 </summary> 1959 1960```cpp 1961bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size, 1962 uint64_t *address, cs_insn *insn) 1963{ 1964 struct cs_struct *handle; 1965 uint16_t insn_size; 1966 MCInst mci; 1967 bool r; 1968 1969 handle = (struct cs_struct *)(uintptr_t)ud; 1970 if (!handle) { 1971 return false; 1972 } 1973 1974 handle->errnum = CS_ERR_OK; 1975 1976 MCInst_Init(&mci); 1977 mci.csh = handle; 1978 1979 mci.address = *address; 1980 1981 // 为无detail模式保存相关信息 1982 mci.flat_insn = insn; 1983 mci.flat_insn->address = *address; 1984#ifdef CAPSTONE_DIET 1985 mci.flat_insn->mnemonic[0] = '\0'; 1986 mci.flat_insn->op_str[0] = '\0'; 1987#endif 1988 1989 r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address, handle->getinsn_info); 1990 if (r) { 1991 SStream ss; 1992 SStream_Init(&ss); 1993 1994 mci.flat_insn->size = insn_size; 1995 1996 // 将内部指令操作码映射到公共insn ID 1997 handle->insn_id(handle, insn, mci.Opcode); 1998 1999 handle->printer(&mci, &ss, handle->printer_info); 2000 2001 fill_insn(handle, insn, ss.buffer, &mci, handle->post_printer, *code); 2002 2003 // 调整伪操作码(X86) 2004 if (handle->arch == CS_ARCH_X86) 2005 insn->id += mci.popcode_adjust; 2006 2007 *code += insn_size; 2008 *size -= insn_size; 2009 *address += insn_size; 2010 } else { // 遇到中断指令 2011 size_t skipdata_bytes; 2012 2013 // 如果没有跳过数据的请求,或者剩余数据太小,则退出 2014 if (!handle->skipdata || handle->skipdata_size > *size) 2015 return false; 2016 2017 if (handle->skipdata_setup.callback) { 2018 skipdata_bytes = handle->skipdata_setup.callback(*code, *size, 2019 0, handle->skipdata_setup.user_data); 2020 if (skipdata_bytes > *size) 2021 // 剩余数据太小 2022 return false; 2023 2024 if (!skipdata_bytes) 2025 return false; 2026 } else 2027 skipdata_bytes = handle->skipdata_size; 2028 2029 // 基于架构和模式跳过一些数据 2030 insn->id = 0; // 此“数据”指令的ID无效 2031 insn->address = *address; 2032 insn->size = (uint16_t)skipdata_bytes; 2033#ifdef CAPSTONE_DIET 2034 insn->mnemonic[0] = '\0'; 2035 insn->op_str[0] = '\0'; 2036#else 2037 memcpy(insn->bytes, *code, skipdata_bytes); 2038 strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic, 2039 sizeof(insn->mnemonic) - 1); 2040 skipdata_opstr(insn->op_str, *code, skipdata_bytes); 2041#endif 2042 2043 *code += skipdata_bytes; 2044 *size -= skipdata_bytes; 2045 *address += skipdata_bytes; 2046 } 2047 2048 return true; 2049} 2050``` 2051 2052</details> 2053 2054 2055<details><summary> 示例 </summary> 2056 2057```cpp 2058#include <iostream> 2059#include <stdio.h> 2060 2061#include "capstone.h" 2062#include "platform.h" 2063 2064using namespace std; 2065 2066struct platform { 2067 cs_arch arch; 2068 cs_mode mode; 2069 unsigned char* code; 2070 size_t size; 2071 const char* comment; 2072 cs_opt_type opt_type; 2073 cs_opt_value opt_value; 2074}; 2075 2076static void print_string_hex(unsigned char* str, size_t len) 2077{ 2078 unsigned char* c; 2079 2080 printf("Code: "); 2081 for (c = str; c < str + len; c++) { 2082 printf("0x%02x ", *c & 0xff); 2083 } 2084 printf("\n"); 2085} 2086 2087static void test() 2088{ 2089#define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" 2090#define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" 2091#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00" 2092 2093 struct platform platforms[4] = { //架构及模式 2094 { 2095 CS_ARCH_X86, 2096 CS_MODE_16, 2097 (unsigned char*)X86_CODE16, 2098 sizeof(X86_CODE32) - 1, 2099 "X86 16bit (Intel syntax)" 2100 }, 2101 { 2102 CS_ARCH_X86, 2103 CS_MODE_32, 2104 (unsigned char*)X86_CODE32, 2105 sizeof(X86_CODE32) - 1, 2106 "X86 32bit (ATT syntax)", 2107 CS_OPT_SYNTAX, 2108 CS_OPT_SYNTAX_ATT, 2109 }, 2110 { 2111 CS_ARCH_X86, 2112 CS_MODE_32, 2113 (unsigned char*)X86_CODE32, 2114 sizeof(X86_CODE32) - 1, 2115 "X86 32 (Intel syntax)" 2116 }, 2117 { 2118 CS_ARCH_X86, 2119 CS_MODE_64, 2120 (unsigned char*)X86_CODE64, 2121 sizeof(X86_CODE64) - 1, 2122 "X86 64 (Intel syntax)" 2123 }, 2124 2125 csh handle; 2126 uint64_t address; 2127 cs_insn* insn; 2128 cs_detail* detail; 2129 int i; 2130 cs_err err; 2131 const uint8_t* code; 2132 size_t size; 2133 2134 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 2135 printf("****************\n"); 2136 printf("Platform: %s\n", platforms[i].comment); 2137 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 2138 if (err) { 2139 printf("Failed on cs_open() with error returned: %u\n", err); 2140 abort(); 2141 } 2142 2143 if (platforms[i].opt_type) 2144 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 2145 2146 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 2147 2148 // 为cs_disasm_iter()分配内存 2149 insn = cs_malloc(handle); 2150 2151 print_string_hex(platforms[i].code, platforms[i].size); //原机器码 2152 printf("Disasm:\n"); 2153 2154 address = 0x1000; 2155 code = platforms[i].code; 2156 size = platforms[i].size; 2157 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { //cs_disasm_iter反汇编 2158 int n; 2159 2160 printf("0x%" PRIx64 ":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n", 2161 insn->address, insn->mnemonic, insn->op_str, 2162 insn->id, cs_insn_name(handle, insn->id)); 2163 2164 // 打印此指令使用的隐式寄存器 2165 detail = insn->detail; 2166 2167 if (detail->regs_read_count > 0) { 2168 printf("\tImplicit registers read: "); 2169 for (n = 0; n < detail->regs_read_count; n++) { 2170 printf("%s ", cs_reg_name(handle, detail->regs_read[n])); 2171 } 2172 printf("\n"); 2173 } 2174 2175 // 打印此指令修改的隐式寄存器 2176 if (detail->regs_write_count > 0) { 2177 printf("\tImplicit registers modified: "); 2178 for (n = 0; n < detail->regs_write_count; n++) { 2179 printf("%s ", cs_reg_name(handle, detail->regs_write[n])); 2180 } 2181 printf("\n"); 2182 } 2183 2184 // 打印此指令所属指令集 2185 if (detail->groups_count > 0) { 2186 printf("\tThis instruction belongs to groups: "); 2187 for (n = 0; n < detail->groups_count; n++) { 2188 printf("%s ", cs_group_name(handle, detail->groups[n])); 2189 } 2190 printf("\n"); 2191 } 2192 } 2193 2194 printf("\n"); 2195 2196 // 释放cs_malloc()分配的内存 2197 cs_free(insn, 1); 2198 2199 cs_close(&handle); 2200 } 2201} 2202 2203int main() 2204{ 2205 test(); 2206 2207 return 0; 2208} 2209``` 2210 2211</details> 2212 2213输出 2214 2215 2216 2217 2218### cs_reg_name 2219 2220`const char * CAPSTONE_API cs_reg_name(csh handle, unsigned int reg_id);` 2221 2222获取寄存器的名字(string类型) 2223寄存器id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到 2224 2225注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名 2226 2227``` 2228handle: cs_open()返回的句柄 2229reg_id: 寄存器id 2230return: 寄存器的字符名, 如果reg_id不可用返回NULL 2231``` 2232 2233<details><summary> 源码实现 </summary> 2234 2235```cpp 2236const char * CAPSTONE_API cs_reg_name(csh ud, unsigned int reg) 2237{ 2238 struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; 2239 2240 if (!handle || handle->reg_name == NULL) { 2241 return NULL; 2242 } 2243 2244 return handle->reg_name(ud, reg); 2245} 2246``` 2247 2248</details> 2249 2250 2251<details><summary> 示例(打印RAX) </summary> 2252 2253```cpp 2254#include <iostream> 2255#include <stdio.h> 2256 2257#include "capstone.h" 2258#include "platform.h" 2259 2260using namespace std; 2261 2262int main(void) 2263{ 2264 csh handle = 0; 2265 cs_insn* insn; 2266 size_t count; 2267 2268 if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { 2269 printf("ERROR: Failed to initialize engine!\n"); 2270 return -1; 2271 } 2272 2273 printf("%s", cs_reg_name(handle, X86_REG_RAX)); 2274 cs_close(&handle); 2275 2276 return 0; 2277} 2278``` 2279 2280</details> 2281 2282输出 2283 2284 2285 2286 2287### cs_insn_name 2288 2289`const char * CAPSTONE_API cs_insn_name(csh handle, unsigned int insn_id);` 2290 2291获取指令的名字(string类型) 2292 2293指令id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到 2294 2295注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名 2296 2297``` 2298handle: cs_open()返回的句柄 2299insn_id: 指令id 2300return: 指令的字符名, 如果insn_id不可用返回NULL 2301``` 2302 2303<details><summary> 源码实现 </summary> 2304 2305```cpp 2306const char * CAPSTONE_API cs_insn_name(csh ud, unsigned int insn) 2307{ 2308 struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud; 2309 2310 if (!handle || handle->insn_name == NULL) { 2311 return NULL; 2312 } 2313 2314 return handle->insn_name(ud, insn); 2315} 2316``` 2317 2318</details> 2319 2320 2321<details><summary> 示例 </summary> 2322 2323```cpp 2324#include <iostream> 2325#include <stdio.h> 2326 2327#include "capstone.h" 2328#include "platform.h" 2329 2330using namespace std; 2331 2332struct platform { 2333 cs_arch arch; 2334 cs_mode mode; 2335 unsigned char* code; 2336 size_t size; 2337 const char* comment; 2338 cs_opt_type opt_type; 2339 cs_opt_value opt_value; 2340}; 2341 2342static void print_string_hex(unsigned char* str, size_t len) 2343{ 2344 unsigned char* c; 2345 2346 printf("Code: "); 2347 for (c = str; c < str + len; c++) { 2348 printf("0x%02x ", *c & 0xff); 2349 } 2350 printf("\n"); 2351} 2352 2353static void test() 2354{ 2355 2356#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 2357 2358 struct platform platforms[] = { 2359 { 2360 CS_ARCH_X86, 2361 CS_MODE_64, 2362 (unsigned char*)X86_CODE64, 2363 sizeof(X86_CODE64) - 1, 2364 "X86 64 (Intel syntax)" 2365 }, 2366 }; 2367 2368 csh handle; 2369 uint64_t address; 2370 cs_insn* insn; 2371 cs_detail* detail; 2372 int i; 2373 cs_err err; 2374 const uint8_t* code; 2375 size_t size; 2376 2377 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 2378 printf("****************\n"); 2379 printf("Platform: %s\n", platforms[i].comment); 2380 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 2381 if (err) { 2382 printf("Failed on cs_open() with error returned: %u\n", err); 2383 abort(); 2384 } 2385 2386 if (platforms[i].opt_type) 2387 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 2388 2389 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 2390 2391 insn = cs_malloc(handle); 2392 2393 print_string_hex(platforms[i].code, platforms[i].size); 2394 printf("Disasm:\n"); 2395 2396 address = 0x1000; 2397 code = platforms[i].code; 2398 size = platforms[i].size; 2399 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { 2400 int n; 2401 2402 printf("0x%" PRIx64 ":\t%s\t\t%s", 2403 insn->address, insn->mnemonic, insn->op_str); 2404 printf(" instruction: %s", cs_insn_name(handle, insn->id)); //输出该行的操作指令 2405 cout << endl; 2406 2407 printf("\n"); 2408 cs_free(insn, 1); 2409 cs_close(&handle); 2410 } 2411} 2412 2413int main() 2414{ 2415 test(); 2416 2417 return 0; 2418} 2419``` 2420 2421</details> 2422 2423输出 2424 2425 2426 2427 2428### cs_group_name 2429 2430`const char * CAPSTONE_API cs_group_name(csh handle, unsigned int group_id);` 2431 2432输出指令类型名字 2433 2434指令id可在相关架构的头文件(建立项目时复制到项目文件夹的那些头文件)内找到 2435 2436注意: 当处于diet模式时此API不可用,因为引擎不会存储寄存器名 2437 2438``` 2439handle: cs_open()返回的句柄 2440insn_id: 指令类型id 2441return: 指令类型的字符名, 如果insn_id不可用返回NULL 2442``` 2443 2444示例都与上面类似,略。 2445 2446 2447### cs_insn_group 2448 2449`bool CAPSTONE_API cs_insn_group(csh handle, const cs_insn *insn, unsigned int group_id);` 2450 2451检查反汇编后的指令是否属于某个特定指令类型 2452 2453注意:只有当detail选项为ON时这个API可用 (默认OFF). 2454 2455在“diet”模式下,此API没有用,因为引擎不更新insn->groups数组 2456 2457``` 2458handle: cs_open()返回的句柄 2459insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构 2460group_id: 要检查此指令是否属于的指令类型。 2461return: 如果该指令确实属于给定的指令类型,则为true,否则为false。 2462``` 2463 2464<details><summary> 源码实现 </summary> 2465 2466```cpp 2467bool CAPSTONE_API cs_insn_group(csh ud, const cs_insn *insn, unsigned int group_id) 2468{ 2469 struct cs_struct *handle; 2470 if (!ud) 2471 return false; 2472 2473 handle = (struct cs_struct *)(uintptr_t)ud; 2474 2475 if (!handle->detail) { 2476 handle->errnum = CS_ERR_DETAIL; 2477 return false; 2478 } 2479 2480 if (!insn->id) { 2481 handle->errnum = CS_ERR_SKIPDATA; 2482 return false; 2483 } 2484 2485 if (!insn->detail) { 2486 handle->errnum = CS_ERR_DETAIL; 2487 return false; 2488 } 2489 2490 return arr_exist8(insn->detail->groups, insn->detail->groups_count, group_id); 2491} 2492``` 2493 2494</details> 2495 2496 2497<details><summary> 示例(判断是否属于跳转指令) </summary> 2498 2499```cpp 2500#include <iostream> 2501#include <stdio.h> 2502 2503#include "capstone.h" 2504#include "platform.h" 2505 2506using namespace std; 2507 2508struct platform { 2509 cs_arch arch; 2510 cs_mode mode; 2511 unsigned char* code; 2512 size_t size; 2513 const char* comment; 2514 cs_opt_type opt_type; 2515 cs_opt_value opt_value; 2516}; 2517 2518static void print_string_hex(unsigned char* str, size_t len) 2519{ 2520 unsigned char* c; 2521 2522 printf("Code: "); 2523 for (c = str; c < str + len; c++) { 2524 printf("0x%02x ", *c & 0xff); 2525 } 2526 printf("\n"); 2527} 2528 2529static void test() 2530{ 2531 2532#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 2533 2534 struct platform platforms[] = { 2535 { 2536 CS_ARCH_X86, 2537 CS_MODE_64, 2538 (unsigned char*)X86_CODE64, 2539 sizeof(X86_CODE64) - 1, 2540 "X86 64 (Intel syntax)" 2541 }, 2542 }; 2543 2544 csh handle; 2545 uint64_t address; 2546 cs_insn* insn; 2547 cs_detail* detail; 2548 int i; 2549 cs_err err; 2550 const uint8_t* code; 2551 size_t size; 2552 2553 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 2554 printf("****************\n"); 2555 printf("Platform: %s\n", platforms[i].comment); 2556 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 2557 if (err) { 2558 printf("Failed on cs_open() with error returned: %u\n", err); 2559 abort(); 2560 } 2561 2562 if (platforms[i].opt_type) 2563 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 2564 2565 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 2566 2567 insn = cs_malloc(handle); 2568 2569 print_string_hex(platforms[i].code, platforms[i].size); 2570 printf("Disasm:\n"); 2571 2572 address = 0x1000; 2573 code = platforms[i].code; 2574 size = platforms[i].size; 2575 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { 2576 int n; 2577 2578 printf("0x%" PRIx64 ":\t%s\t\t%s ", 2579 insn->address, insn->mnemonic, insn->op_str); 2580 cout << "is JUMP: " <<cs_insn_group(handle, insn, CS_GRP_JUMP) << endl; //判断是否为跳转指令 2581 cout << endl; 2582 2583 printf("\n"); 2584 cs_free(insn, 1); 2585 cs_close(&handle); 2586 } 2587} 2588 2589int main() 2590{ 2591 test(); 2592 2593 return 0; 2594} 2595``` 2596 2597</details> 2598 2599输出 2600 2601 2602 2603 2604### cs_reg_read 2605 2606`bool CAPSTONE_API cs_reg_read(csh handle, const cs_insn *insn, unsigned int reg_id);` 2607 2608检查反汇编指令是否隐式使用特定寄存器。 2609 2610注意:此API仅在启用detail选项时有效(默认为关闭) 2611 2612在“diet”模式下,此API没有用,因为引擎不更新insn->regs_read数组 2613 2614``` 2615insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构 2616reg_id: 标注想要检查的这个指令是否使用了它。 2617return: 如果该指令确实隐式使用了给定寄存器,则为true,否则为false。 2618``` 2619 2620<details><summary> 源码实现 </summary> 2621 2622```cpp 2623bool CAPSTONE_API cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id) 2624{ 2625 struct cs_struct *handle; 2626 if (!ud) 2627 return false; 2628 2629 handle = (struct cs_struct *)(uintptr_t)ud; 2630 2631 if (!handle->detail) { 2632 handle->errnum = CS_ERR_DETAIL; 2633 return false; 2634 } 2635 2636 if (!insn->id) { 2637 handle->errnum = CS_ERR_SKIPDATA; 2638 return false; 2639 } 2640 2641 if (!insn->detail) { 2642 handle->errnum = CS_ERR_DETAIL; 2643 return false; 2644 } 2645 2646 return arr_exist(insn->detail->regs_read, insn->detail->regs_read_count, reg_id); 2647} 2648``` 2649</details> 2650 2651示例同API cs_disasm_iter 2652 2653 2654### cs_reg_write 2655 2656`bool CAPSTONE_API cs_reg_write(csh handle, const cs_insn *insn, unsigned int reg_id);` 2657 2658检查反汇编指令是否隐式修改了特定寄存器。 2659 2660注意:此API仅在启用detail选项时有效(默认为关闭) 2661 2662在“diet”模式下,此API没有用,因为引擎不更新insn->regs_read数组 2663 2664``` 2665insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构 2666reg_id: 标注想要检查的这个指令是否修改了它。 2667return: 如果该指令确实隐式修改了给定寄存器,则为true,否则为false。 2668``` 2669 2670<details><summary> 源码实现 </summary> 2671 2672```cpp 2673bool CAPSTONE_API cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id) 2674{ 2675 struct cs_struct *handle; 2676 if (!ud) 2677 return false; 2678 2679 handle = (struct cs_struct *)(uintptr_t)ud; 2680 2681 if (!handle->detail) { 2682 handle->errnum = CS_ERR_DETAIL; 2683 return false; 2684 } 2685 2686 if (!insn->id) { 2687 handle->errnum = CS_ERR_SKIPDATA; 2688 return false; 2689 } 2690 2691 if (!insn->detail) { 2692 handle->errnum = CS_ERR_DETAIL; 2693 return false; 2694 } 2695 2696 return arr_exist(insn->detail->regs_write, insn->detail->regs_write_count, reg_id); 2697} 2698``` 2699</details> 2700 2701示例同API cs_disasm_iter 2702 2703 2704### cs_op_count 2705 2706`int CAPSTONE_API cs_op_count(csh handle, const cs_insn *insn, unsigned int op_type);` 2707 2708计算给定类型的操作数的数量 2709 2710注意:只有当detail选项为ON时这个API可用 (默认OFF). 2711 2712``` 2713handle: cs_open()返回的句柄 2714insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构 2715op_type: 要找到的操作数类型。 2716return: 指令insn中给定类型op_type的操作数的数量,返回-1表示查找失败。 2717``` 2718 2719<details><summary> 源码实现 </summary> 2720 2721```cpp 2722int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type) 2723{ 2724 struct cs_struct *handle; 2725 unsigned int count = 0, i; 2726 if (!ud) 2727 return -1; 2728 2729 handle = (struct cs_struct *)(uintptr_t)ud; 2730 2731 if (!handle->detail) { 2732 handle->errnum = CS_ERR_DETAIL; 2733 return -1; 2734 } 2735 2736 if (!insn->id) { 2737 handle->errnum = CS_ERR_SKIPDATA; 2738 return -1; 2739 } 2740 2741 if (!insn->detail) { 2742 handle->errnum = CS_ERR_DETAIL; 2743 return -1; 2744 } 2745 2746 handle->errnum = CS_ERR_OK; 2747 2748 switch (handle->arch) { 2749 default: 2750 handle->errnum = CS_ERR_HANDLE; 2751 return -1; 2752 case CS_ARCH_ARM: 2753 for (i = 0; i < insn->detail->arm.op_count; i++) 2754 if (insn->detail->arm.operands[i].type == (arm_op_type)op_type) 2755 count++; 2756 break; 2757 case CS_ARCH_ARM64: 2758 for (i = 0; i < insn->detail->arm64.op_count; i++) 2759 if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type) 2760 count++; 2761 break; 2762 case CS_ARCH_X86: 2763 for (i = 0; i < insn->detail->x86.op_count; i++) 2764 if (insn->detail->x86.operands[i].type == (x86_op_type)op_type) 2765 count++; 2766 break; 2767 case CS_ARCH_MIPS: 2768 for (i = 0; i < insn->detail->mips.op_count; i++) 2769 if (insn->detail->mips.operands[i].type == (mips_op_type)op_type) 2770 count++; 2771 break; 2772 case CS_ARCH_PPC: 2773 for (i = 0; i < insn->detail->ppc.op_count; i++) 2774 if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type) 2775 count++; 2776 break; 2777 case CS_ARCH_SPARC: 2778 for (i = 0; i < insn->detail->sparc.op_count; i++) 2779 if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type) 2780 count++; 2781 break; 2782 case CS_ARCH_SYSZ: 2783 for (i = 0; i < insn->detail->sysz.op_count; i++) 2784 if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type) 2785 count++; 2786 break; 2787 case CS_ARCH_XCORE: 2788 for (i = 0; i < insn->detail->xcore.op_count; i++) 2789 if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type) 2790 count++; 2791 break; 2792 case CS_ARCH_M68K: 2793 for (i = 0; i < insn->detail->m68k.op_count; i++) 2794 if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type) 2795 count++; 2796 break; 2797 case CS_ARCH_TMS320C64X: 2798 for (i = 0; i < insn->detail->tms320c64x.op_count; i++) 2799 if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type) 2800 count++; 2801 break; 2802 case CS_ARCH_M680X: 2803 for (i = 0; i < insn->detail->m680x.op_count; i++) 2804 if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type) 2805 count++; 2806 break; 2807 case CS_ARCH_EVM: 2808#if 0 2809 for (i = 0; i < insn->detail->evm.op_count; i++) 2810 if (insn->detail->evm.operands[i].type == (evm_op_type)op_type) 2811 count++; 2812#endif 2813 break; 2814 } 2815 2816 return count; 2817} 2818``` 2819 2820</details> 2821 2822 2823<details><summary> x86指令操作码类型示例(判断寄存操作码) </summary> 2824 2825```cpp 2826typedef enum x86_op_type { 2827 X86_OP_INVALID = 0, ///< = CS_OP_INVALID (未初始化). 2828 X86_OP_REG, ///< = CS_OP_REG (寄存操作码). 2829 X86_OP_IMM, ///< = CS_OP_IMM (立即操作码). 2830 X86_OP_MEM, ///< = CS_OP_MEM (内存操作码). 2831} x86_op_type; 2832``` 2833 2834```cpp 2835#include <iostream> 2836#include <stdio.h> 2837 2838#include "capstone.h" 2839#include "platform.h" 2840 2841using namespace std; 2842 2843struct platform { 2844 cs_arch arch; 2845 cs_mode mode; 2846 unsigned char* code; 2847 size_t size; 2848 const char* comment; 2849 cs_opt_type opt_type; 2850 cs_opt_value opt_value; 2851}; 2852 2853static void print_string_hex(unsigned char* str, size_t len) 2854{ 2855 unsigned char* c; 2856 2857 printf("Code: "); 2858 for (c = str; c < str + len; c++) { 2859 printf("0x%02x ", *c & 0xff); 2860 } 2861 printf("\n"); 2862} 2863 2864static void test() 2865{ 2866 2867#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 2868 2869 struct platform platforms[] = { 2870 { 2871 CS_ARCH_X86, 2872 CS_MODE_64, 2873 (unsigned char*)X86_CODE64, 2874 sizeof(X86_CODE64) - 1, 2875 "X86 64 (Intel syntax)" 2876 }, 2877 }; 2878 2879 csh handle; 2880 uint64_t address; 2881 cs_insn* insn; 2882 cs_detail* detail; 2883 int i; 2884 cs_err err; 2885 const uint8_t* code; 2886 size_t size; 2887 2888 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 2889 printf("****************\n"); 2890 printf("Platform: %s\n", platforms[i].comment); 2891 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 2892 if (err) { 2893 printf("Failed on cs_open() with error returned: %u\n", err); 2894 abort(); 2895 } 2896 2897 if (platforms[i].opt_type) 2898 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 2899 2900 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 2901 2902 insn = cs_malloc(handle); 2903 2904 print_string_hex(platforms[i].code, platforms[i].size); 2905 printf("Disasm:\n"); 2906 2907 address = 0x1000; 2908 code = platforms[i].code; 2909 size = platforms[i].size; 2910 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { 2911 int n; 2912 2913 printf("0x%" PRIx64 ":\t%s\t\t%s ", 2914 insn->address, insn->mnemonic, insn->op_str); 2915 cout << "is REG: " << cs_op_count(handle, insn, X86_OP_REG) << endl; //判断是否为寄存操作码 2916 cout << endl; 2917 2918 printf("\n"); 2919 cs_free(insn, 1); 2920 cs_close(&handle); 2921 } 2922} 2923 2924int main() 2925{ 2926 test(); 2927 2928 return 0; 2929} 2930``` 2931 2932</details> 2933 2934输出 2935 2936 2937 2938 2939### cs_op_index 2940 2941`int CAPSTONE_API cs_op_index(csh handle, const cs_insn *insn, unsigned int op_type, unsigned int position);` 2942 2943检索给定类型的操作数在`<arch>.operands[]`数组中的位置, 使用返回的位置访问操作数 2944 2945注意:只有当detail选项为ON时这个API可用 (默认OFF). 2946 2947``` 2948handle: cs_open()返回的句柄 2949insn: 从cs_disasm()或cs_disasm_iter()接收的反汇编指令结构 2950op_type: 要找到的操作数类型。 2951position: 要查找的操作数的位置。范围一定在`[1, cs_op_count(handle, insn, op_type)]`内 2952return: 指令insn的`<arch>.operands[]`数组中给定类型op_type的操作数的索引,失败时返回-1。 2953``` 2954 2955<details><summary> 源码实现 </summary> 2956 2957```cpp 2958int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type, 2959 unsigned int post) 2960{ 2961 struct cs_struct *handle; 2962 unsigned int count = 0, i; 2963 if (!ud) 2964 return -1; 2965 2966 handle = (struct cs_struct *)(uintptr_t)ud; 2967 2968 if (!handle->detail) { 2969 handle->errnum = CS_ERR_DETAIL; 2970 return -1; 2971 } 2972 2973 if (!insn->id) { 2974 handle->errnum = CS_ERR_SKIPDATA; 2975 return -1; 2976 } 2977 2978 if (!insn->detail) { 2979 handle->errnum = CS_ERR_DETAIL; 2980 return -1; 2981 } 2982 2983 handle->errnum = CS_ERR_OK; 2984 2985 switch (handle->arch) { 2986 default: 2987 handle->errnum = CS_ERR_HANDLE; 2988 return -1; 2989 case CS_ARCH_ARM: 2990 for (i = 0; i < insn->detail->arm.op_count; i++) { 2991 if (insn->detail->arm.operands[i].type == (arm_op_type)op_type) 2992 count++; 2993 if (count == post) 2994 return i; 2995 } 2996 break; 2997 case CS_ARCH_ARM64: 2998 for (i = 0; i < insn->detail->arm64.op_count; i++) { 2999 if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type) 3000 count++; 3001 if (count == post) 3002 return i; 3003 } 3004 break; 3005 case CS_ARCH_X86: 3006 for (i = 0; i < insn->detail->x86.op_count; i++) { 3007 if (insn->detail->x86.operands[i].type == (x86_op_type)op_type) 3008 count++; 3009 if (count == post) 3010 return i; 3011 } 3012 break; 3013 case CS_ARCH_MIPS: 3014 for (i = 0; i < insn->detail->mips.op_count; i++) { 3015 if (insn->detail->mips.operands[i].type == (mips_op_type)op_type) 3016 count++; 3017 if (count == post) 3018 return i; 3019 } 3020 break; 3021 case CS_ARCH_PPC: 3022 for (i = 0; i < insn->detail->ppc.op_count; i++) { 3023 if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type) 3024 count++; 3025 if (count == post) 3026 return i; 3027 } 3028 break; 3029 case CS_ARCH_SPARC: 3030 for (i = 0; i < insn->detail->sparc.op_count; i++) { 3031 if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type) 3032 count++; 3033 if (count == post) 3034 return i; 3035 } 3036 break; 3037 case CS_ARCH_SYSZ: 3038 for (i = 0; i < insn->detail->sysz.op_count; i++) { 3039 if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type) 3040 count++; 3041 if (count == post) 3042 return i; 3043 } 3044 break; 3045 case CS_ARCH_XCORE: 3046 for (i = 0; i < insn->detail->xcore.op_count; i++) { 3047 if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type) 3048 count++; 3049 if (count == post) 3050 return i; 3051 } 3052 break; 3053 case CS_ARCH_M68K: 3054 for (i = 0; i < insn->detail->m68k.op_count; i++) { 3055 if (insn->detail->m68k.operands[i].type == (m68k_op_type)op_type) 3056 count++; 3057 if (count == post) 3058 return i; 3059 } 3060 break; 3061 case CS_ARCH_TMS320C64X: 3062 for (i = 0; i < insn->detail->tms320c64x.op_count; i++) { 3063 if (insn->detail->tms320c64x.operands[i].type == (tms320c64x_op_type)op_type) 3064 count++; 3065 if (count == post) 3066 return i; 3067 } 3068 break; 3069 case CS_ARCH_M680X: 3070 for (i = 0; i < insn->detail->m680x.op_count; i++) { 3071 if (insn->detail->m680x.operands[i].type == (m680x_op_type)op_type) 3072 count++; 3073 if (count == post) 3074 return i; 3075 } 3076 break; 3077 } 3078 3079 return -1; 3080} 3081``` 3082</details> 3083 3084 3085<details><summary> 示例 </summary> 3086 3087```cpp 3088#include <iostream> 3089#include <stdio.h> 3090 3091#include "capstone.h" 3092#include "platform.h" 3093 3094using namespace std; 3095 3096struct platform { 3097 cs_arch arch; 3098 cs_mode mode; 3099 unsigned char* code; 3100 size_t size; 3101 const char* comment; 3102 cs_opt_type opt_type; 3103 cs_opt_value opt_value; 3104}; 3105 3106static void print_string_hex(unsigned char* str, size_t len) 3107{ 3108 unsigned char* c; 3109 3110 printf("Code: "); 3111 for (c = str; c < str + len; c++) { 3112 printf("0x%02x ", *c & 0xff); 3113 } 3114 printf("\n"); 3115} 3116 3117static void test() 3118{ 3119#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 3120 struct platform platforms[] = { 3121 { 3122 CS_ARCH_X86, 3123 CS_MODE_64, 3124 (unsigned char*)X86_CODE64, 3125 sizeof(X86_CODE64) - 1, 3126 "X86 64 (Intel syntax)" 3127 }, 3128 }; 3129 3130 csh handle; 3131 uint64_t address; 3132 cs_insn* insn; 3133 cs_detail* detail; 3134 int i; 3135 cs_err err; 3136 const uint8_t* code; 3137 size_t size; 3138 3139 cs_x86* x86; 3140 3141 int count; 3142 3143 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 3144 printf("****************\n"); 3145 printf("Platform: %s\n", platforms[i].comment); 3146 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 3147 if (err) { 3148 printf("Failed on cs_open() with error returned: %u\n", err); 3149 abort(); 3150 } 3151 3152 if (platforms[i].opt_type) 3153 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 3154 3155 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 3156 3157 insn = cs_malloc(handle); 3158 x86 = &(insn->detail->x86); 3159 print_string_hex(platforms[i].code, platforms[i].size); 3160 printf("Disasm:\n"); 3161 3162 address = 0x1000; 3163 code = platforms[i].code; 3164 size = platforms[i].size; 3165 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { 3166 int n; 3167 3168 printf("0x%" PRIx64 ":\t%s\t\t%s ", 3169 insn->address, insn->mnemonic, insn->op_str); 3170 cout << endl; 3171 3172 count = cs_op_count(handle, insn, X86_OP_IMM); //查找立即数 3173 if (count) { 3174 printf("\timm_count: %u\n", count); 3175 for (i = 1; i < count + 1; i++) { 3176 int index = cs_op_index(handle, insn, X86_OP_IMM, i); 3177 printf("\timms[%u]: 0x%" PRIx64 "\n", i, x86->operands[index].imm); 3178 if (x86->encoding.imm_offset != 0) { 3179 printf("\timm_offset: 0x%x\n", x86->encoding.imm_offset); 3180 } 3181 if (x86->encoding.imm_size != 0) { 3182 printf("\timm_size: 0x%x\n", x86->encoding.imm_size); 3183 } 3184 } 3185 } 3186 } 3187 3188 printf("\n"); 3189 cs_free(insn, 1); 3190 cs_close(&handle); 3191 } 3192} 3193 3194int main() 3195{ 3196 test(); 3197 return 0; 3198} 3199``` 3200 3201</details> 3202 3203输出 3204 3205 3206 3207### cs_regs_access 3208 3209```cpp 3210cs_err CAPSTONE_API cs_regs_access(csh handle, const cs_insn *insn, 3211 cs_regs regs_read, uint8_t *regs_read_count, 3212 cs_regs regs_write, uint8_t *regs_write_count); 3213``` 3214 3215检索由一条指令显式或隐式访问的所有寄存器 3216 3217注意: 在“diet”模式下,此API不可用,因为引擎不存储寄存器 3218 3219``` 3220handle: cs_open()返回的句柄 3221insn: 从cs_disasm()或cs_disasm_iter()返回的反汇编指令结构 3222regs_read:返回时,这个数组包含所有按指令读取的寄存器。 3223regs_read_count:保存在regs_read数组中的寄存器数。 3224regs_write:返回时,这个数组包含所有由指令修改的寄存器。 3225regs_write_count:保存在regs_write数组中的寄存器数。 3226成功时返回CS_ERR_OK,失败时返回其他值(详细错误请参阅cs_err enum)。 3227``` 3228 3229<details><summary> 源码实现 </summary> 3230 3231```cpp 3232cs_err CAPSTONE_API cs_regs_access(csh ud, const cs_insn *insn, 3233 cs_regs regs_read, uint8_t *regs_read_count, 3234 cs_regs regs_write, uint8_t *regs_write_count) 3235{ 3236 struct cs_struct *handle; 3237 3238 if (!ud) 3239 return -1; 3240 3241 handle = (struct cs_struct *)(uintptr_t)ud; 3242 3243#ifdef CAPSTONE_DIET 3244 // This API does not work in DIET mode 3245 handle->errnum = CS_ERR_DIET; 3246 return CS_ERR_DIET; 3247#else 3248 if (!handle->detail) { 3249 handle->errnum = CS_ERR_DETAIL; 3250 return CS_ERR_DETAIL; 3251 } 3252 3253 if (!insn->id) { 3254 handle->errnum = CS_ERR_SKIPDATA; 3255 return CS_ERR_SKIPDATA; 3256 } 3257 3258 if (!insn->detail) { 3259 handle->errnum = CS_ERR_DETAIL; 3260 return CS_ERR_DETAIL; 3261 } 3262 3263 if (handle->reg_access) { 3264 handle->reg_access(insn, regs_read, regs_read_count, regs_write, regs_write_count); 3265 } else { 3266 // this arch is unsupported yet 3267 handle->errnum = CS_ERR_ARCH; 3268 return CS_ERR_ARCH; 3269 } 3270 3271 return CS_ERR_OK; 3272#endif 3273} 3274``` 3275 3276</details> 3277 3278 3279<details><summary> 示例 </summary> 3280 3281```cpp 3282#include <iostream> 3283#include <stdio.h> 3284 3285#include "capstone.h" 3286#include "platform.h" 3287 3288using namespace std; 3289 3290struct platform { 3291 cs_arch arch; 3292 cs_mode mode; 3293 unsigned char* code; 3294 size_t size; 3295 const char* comment; 3296 cs_opt_type opt_type; 3297 cs_opt_value opt_value; 3298}; 3299 3300static void print_string_hex(unsigned char* str, size_t len) 3301{ 3302 unsigned char* c; 3303 3304 printf("Code: "); 3305 for (c = str; c < str + len; c++) { 3306 printf("0x%02x ", *c & 0xff); 3307 } 3308 printf("\n"); 3309} 3310 3311static void test() 3312{ 3313#define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00\xe9\xea\xbe\xad\xde\xff\x25\x23\x01\x00\x00\xe8\xdf\xbe\xad\xde\x74\xff" 3314 struct platform platforms[] = { 3315 { 3316 CS_ARCH_X86, 3317 CS_MODE_64, 3318 (unsigned char*)X86_CODE64, 3319 sizeof(X86_CODE64) - 1, 3320 "X86 64 (Intel syntax)" 3321 }, 3322 }; 3323 3324 csh handle; 3325 uint64_t address; 3326 cs_insn* insn; 3327 cs_detail* detail; 3328 int i; 3329 cs_err err; 3330 const uint8_t* code; 3331 size_t size; 3332 3333 cs_x86* x86; 3334 cs_regs regs_read, regs_write; 3335 uint8_t regs_read_count, regs_write_count; 3336 3337 int count; 3338 3339 for (i = 0; i < sizeof(platforms) / sizeof(platforms[0]); i++) { 3340 printf("****************\n"); 3341 printf("Platform: %s\n", platforms[i].comment); 3342 err = cs_open(platforms[i].arch, platforms[i].mode, &handle); 3343 if (err) { 3344 printf("Failed on cs_open() with error returned: %u\n", err); 3345 abort(); 3346 } 3347 3348 if (platforms[i].opt_type) 3349 cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); 3350 3351 cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); 3352 3353 insn = cs_malloc(handle); 3354 x86 = &(insn->detail->x86); 3355 print_string_hex(platforms[i].code, platforms[i].size); 3356 printf("Disasm:\n"); 3357 3358 address = 0x1000; 3359 code = platforms[i].code; 3360 size = platforms[i].size; 3361 while (cs_disasm_iter(handle, &code, &size, &address, insn)) { 3362 int n; 3363 3364 printf("0x%" PRIx64 ":\t%s\t\t%s ", 3365 insn->address, insn->mnemonic, insn->op_str); 3366 cout << endl; 3367 3368 if (!cs_regs_access(handle, insn, //每条指令所有读取和修改的寄存器 3369 regs_read, ®s_read_count, 3370 regs_write, ®s_write_count)) { 3371 if (regs_read_count) { 3372 printf("\tRegisters read:"); 3373 for (i = 0; i < regs_read_count; i++) { 3374 printf(" %s", cs_reg_name(handle, regs_read[i])); 3375 } 3376 printf("\n"); 3377 } 3378 3379 if (regs_write_count) { 3380 printf("\tRegisters modified:"); 3381 for (i = 0; i < regs_write_count; i++) { 3382 printf(" %s", cs_reg_name(handle, regs_write[i])); 3383 } 3384 printf("\n"); 3385 } 3386 } 3387 } 3388 3389 printf("\n"); 3390 cs_free(insn, 1); 3391 cs_close(&handle); 3392 } 3393} 3394 3395int main() 3396{ 3397 test(); 3398 return 0; 3399} 3400``` 3401 3402</details> 3403 3404输出 3405 3406 3407