cwindowscapstone

How to print out the raw binary opcodes on the same line as the disassembly using Capstone


I'm trying to get the Capstone engine to print out the raw binary opcodes that are disassembled by the call to cs_disasm(). Here is a snippet of my code but it only prints out a single byte of raw binary opcode (the first byte only) not the entire binary opcodes that is translated into assembly.

if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK)
{
    return;
}
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);// != CS_ERR_OK)
cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
    
count = cs_disasm(handle, (uint8_t*)startofcode, sizeofcode, startofcode, 0, &insn);

if (count > 0)
{
    for (size_t j = 0; j < count; j++)
    {
        DbgPrint("0x%p\t%06x\t%s\t\t%s\n", (void*)(uintptr_t)insn[j].address, insn[j].bytes[0], insn[j].mnemonic, insn[j].op_str);
    }
    cs_free(insn, count);
}
cs_close(&handle);

For example take the following assembly line of code and its original raw binary opcode

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

But using the above call to DbgPrint I'm only able to output a single byte of opcode as shown in the following output.

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

Solution

  • The issue is that you're only printing the first byte of the opcode with insn[j].bytes[0]. The Capstone API provides the entire opcode in insn[j].bytes and its length in insn[j].size. You need to loop through those bytes to print the full machine code.

    Here’s the corrected snippet:

    if (count > 0) {
        for (size_t j = 0; j < count; j++) {
            // Print address
            DbgPrint("0x%p\t", (void*)(uintptr_t)insn[j].address);
    
            // Print full raw bytes
            for (size_t k = 0; k < insn[j].size; k++) {
                DbgPrint("%02x", insn[j].bytes[k]);
            }
    
            // Print mnemonic and operands
            DbgPrint("\t%s\t%s\n", insn[j].mnemonic, insn[j].op_str);
        }
        cs_free(insn, count);
    }
    cs_close(&handle);