You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Capstone在反汇编代码同一行打印完整原始二进制操作码

如何使用Capstone在反汇编代码同一行打印完整原始二进制操作码

问题根源分析

你当前的代码只打印了指令操作码的第一个字节,核心原因是:你在DbgPrint里直接引用了insn[j].bytes[0]——这只是cs_insn结构体中存储指令字节数组的第一个元素。而x86指令的长度是可变的(从1到15字节不等),Capstone会把当前指令的完整长度存在insn[j].size成员里,你需要利用这个值遍历整个bytes数组才能打印出完整的原始操作码。

解决方案:遍历完整的指令字节数组

下面提供两种实用的修改方案,你可以根据需求选择:

方案1:直接循环打印每个字节

这种方式最直接,无需额外缓冲区,在输出地址后,循环遍历当前指令的所有字节并逐个打印:

if (count > 0) {
    for (size_t j = 0; j < count; j++) {
        // 先打印指令地址
        DbgPrint("0x%p\t", (void*)(uintptr_t)insn[j].address);
        
        // 遍历当前指令的所有字节,以两位十六进制格式打印
        for (size_t k = 0; k < insn[j].size; k++) {
            DbgPrint("%02x", insn[j].bytes[k]);
        }
        
        // 最后打印助记符和操作数
        DbgPrint("\t%s\t\t%s\n", insn[j].mnemonic, insn[j].op_str);
    }
    cs_free(insn, count);
}

方案2:先拼接成格式化字符串再打印(更整洁)

如果想要操作码部分的格式更统一(比如对齐输出),可以先把所有字节拼接成一个连续的十六进制字符串,再一次性输出:

if (count > 0) {
    for (size_t j = 0; j < count; j++) {
        char opcode_buf[32] = {0}; // x86最长指令为15字节,15*2=30字符,预留足够空间
        
        // 拼接所有指令字节到缓冲区
        for (size_t k = 0; k < insn[j].size; k++) {
            snprintf(opcode_buf + (k * 2), sizeof(opcode_buf) - (k * 2), "%02x", insn[j].bytes[k]);
        }
        
        // 一次性输出完整的反汇编行
        DbgPrint("0x%p\t%s\t%s\t\t%s\n", 
            (void*)(uintptr_t)insn[j].address, 
            opcode_buf, 
            insn[j].mnemonic, 
            insn[j].op_str
        );
    }
    cs_free(insn, count);
}

效果验证

以你提到的指令push qword ptr [rbp + 8]为例,假设它的原始操作码是08 75 ff(长度3字节),修改后的代码会输出:

0x0000000000391334  0875ff  push        qword ptr [rbp + 8]

完全匹配你期望的完整操作码输出效果。

关键注意事项

  1. 必须依赖insn[j].size:不要硬编码遍历的字节数,不同x86指令的长度差异极大,size成员是Capstone提供的准确指令长度标识。
  2. 缓冲区大小预留:方案2中的opcode_buf要足够容纳最长x86指令的十六进制字符串(15字节需要30个字符,加上终止符,32字节完全足够)。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 08:38:03