/* Tang Yuhang 2016 */ /* pancake 2017 */ #include #include #include #include "getopt.h" #include #include "cstool.h" void print_string_hex(const char *comment, unsigned char *str, size_t len); static struct { const char *name; cs_arch arch; cs_mode mode; } all_archs[] = { { "arm", CS_ARCH_ARM, CS_MODE_ARM }, { "armb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN }, { "armbe", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN }, { "arml", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN }, { "armle", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_LITTLE_ENDIAN }, { "armv8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 }, { "thumbv8", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 }, { "armv8be", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_V8 | CS_MODE_BIG_ENDIAN }, { "thumbv8be", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_V8 | CS_MODE_BIG_ENDIAN }, { "cortexm", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS }, { "cortexv8m", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS | CS_MODE_V8 }, { "thumb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB }, { "thumbbe", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_BIG_ENDIAN }, { "thumble", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_LITTLE_ENDIAN }, { "aarch64", CS_ARCH_AARCH64, CS_MODE_LITTLE_ENDIAN }, { "aarch64be", CS_ARCH_AARCH64, CS_MODE_BIG_ENDIAN }, { "mips", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_LITTLE_ENDIAN }, { "mipsmicro", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_MICRO }, { "mipsbemicro", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_MICRO | CS_MODE_BIG_ENDIAN }, { "mipsbe32r6", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN}, { "mipsbe32r6micro", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_BIG_ENDIAN | CS_MODE_MICRO }, { "mips32r6", CS_ARCH_MIPS, CS_MODE_MIPS32R6 }, { "mips32r6micro", CS_ARCH_MIPS, CS_MODE_MIPS32R6 | CS_MODE_MICRO }, { "mipsbe", CS_ARCH_MIPS, CS_MODE_MIPS32 | CS_MODE_BIG_ENDIAN }, { "mips64", CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_LITTLE_ENDIAN }, { "mips64be", CS_ARCH_MIPS, CS_MODE_MIPS64 | CS_MODE_BIG_ENDIAN }, { "x16", CS_ARCH_X86, CS_MODE_16 }, // CS_MODE_16 { "x16att", CS_ARCH_X86, CS_MODE_16 }, // CS_MODE_16 , CS_OPT_SYNTAX_ATT { "x32", CS_ARCH_X86, CS_MODE_32 }, // CS_MODE_32 { "x32att", CS_ARCH_X86, CS_MODE_32 }, // CS_MODE_32, CS_OPT_SYNTAX_ATT { "x64", CS_ARCH_X86, CS_MODE_64 }, // CS_MODE_64 { "x64att", CS_ARCH_X86, CS_MODE_64 }, // CS_MODE_64, CS_OPT_SYNTAX_ATT { "ppc32", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_LITTLE_ENDIAN }, { "ppc32be", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_BIG_ENDIAN }, { "ppc32qpx", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN }, { "ppc32beqpx", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN }, { "ppc32ps", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_PS | CS_MODE_LITTLE_ENDIAN }, { "ppc32beps", CS_ARCH_PPC, CS_MODE_32 | CS_MODE_PS | CS_MODE_BIG_ENDIAN }, { "ppc64", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_LITTLE_ENDIAN }, { "ppc64be", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_BIG_ENDIAN }, { "ppc64qpx", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_LITTLE_ENDIAN }, { "ppc64beqpx", CS_ARCH_PPC, CS_MODE_64 | CS_MODE_QPX | CS_MODE_BIG_ENDIAN }, { "sparc", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN }, { "sparcv9", CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN | CS_MODE_V9 }, { "systemz", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN }, { "sysz", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN }, { "s390x", CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN }, { "xcore", CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN }, { "m68k", CS_ARCH_M68K, CS_MODE_BIG_ENDIAN }, { "m68k40", CS_ARCH_M68K, CS_MODE_M68K_040 }, { "tms320c64x", CS_ARCH_TMS320C64X, CS_MODE_BIG_ENDIAN }, { "m6800", CS_ARCH_M680X, CS_MODE_M680X_6800 }, { "m6801", CS_ARCH_M680X, CS_MODE_M680X_6801 }, { "m6805", CS_ARCH_M680X, CS_MODE_M680X_6805 }, { "m6808", CS_ARCH_M680X, CS_MODE_M680X_6808 }, { "m6809", CS_ARCH_M680X, CS_MODE_M680X_6809 }, { "m6811", CS_ARCH_M680X, CS_MODE_M680X_6811 }, { "cpu12", CS_ARCH_M680X, CS_MODE_M680X_CPU12 }, { "hd6301", CS_ARCH_M680X, CS_MODE_M680X_6301 }, { "hd6309", CS_ARCH_M680X, CS_MODE_M680X_6309 }, { "hcs08", CS_ARCH_M680X, CS_MODE_M680X_HCS08 }, { "evm", CS_ARCH_EVM, 0 }, { "wasm", CS_ARCH_WASM, 0 }, { "bpf", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_CLASSIC }, { "bpfbe", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_CLASSIC }, { "ebpf", CS_ARCH_BPF, CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED }, { "ebpfbe", CS_ARCH_BPF, CS_MODE_BIG_ENDIAN | CS_MODE_BPF_EXTENDED }, { "riscv32", CS_ARCH_RISCV, CS_MODE_RISCV32 | CS_MODE_RISCVC }, { "riscv64", CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC }, { "6502", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_6502 }, { "65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65C02 }, { "w65c02", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_W65C02 }, { "65816", CS_ARCH_MOS65XX, CS_MODE_MOS65XX_65816_LONG_MX }, { "sh", CS_ARCH_SH, CS_MODE_BIG_ENDIAN }, { "sh2", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_BIG_ENDIAN}, { "sh2e", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_SHFPU | CS_MODE_BIG_ENDIAN}, { "sh-dsp", CS_ARCH_SH, CS_MODE_SH2 | CS_MODE_SHDSP | CS_MODE_BIG_ENDIAN}, { "sh2a", CS_ARCH_SH, CS_MODE_SH2A | CS_MODE_BIG_ENDIAN}, { "sh2a-fpu", CS_ARCH_SH, CS_MODE_SH2A | CS_MODE_SHFPU | CS_MODE_BIG_ENDIAN}, { "sh3", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 }, { "sh3be", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 }, { "sh3e", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 | CS_MODE_SHFPU}, { "sh3ebe", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 | CS_MODE_SHFPU}, { "sh3-dsp", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH3 | CS_MODE_SHDSP }, { "sh3-dspbe", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH3 | CS_MODE_SHDSP }, { "sh4", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4 | CS_MODE_SHFPU }, { "sh4be", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4 | CS_MODE_SHFPU }, { "sh4a", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4A | CS_MODE_SHFPU }, { "sh4abe", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4A | CS_MODE_SHFPU }, { "sh4al-dsp", CS_ARCH_SH, CS_MODE_LITTLE_ENDIAN | CS_MODE_SH4A | CS_MODE_SHDSP | CS_MODE_SHFPU }, { "sh4al-dspbe", CS_ARCH_SH, CS_MODE_BIG_ENDIAN | CS_MODE_SH4A | CS_MODE_SHDSP | CS_MODE_SHFPU }, { "tc110", CS_ARCH_TRICORE, CS_MODE_TRICORE_110 }, { "tc120", CS_ARCH_TRICORE, CS_MODE_TRICORE_120 }, { "tc130", CS_ARCH_TRICORE, CS_MODE_TRICORE_130 }, { "tc131", CS_ARCH_TRICORE, CS_MODE_TRICORE_131 }, { "tc160", CS_ARCH_TRICORE, CS_MODE_TRICORE_160 }, { "tc161", CS_ARCH_TRICORE, CS_MODE_TRICORE_161 }, { "tc162", CS_ARCH_TRICORE, CS_MODE_TRICORE_162 }, { "alpha", CS_ARCH_ALPHA, CS_MODE_LITTLE_ENDIAN }, { "alphabe", CS_ARCH_ALPHA, CS_MODE_BIG_ENDIAN }, { "hppa11", CS_ARCH_HPPA, CS_MODE_HPPA_11 | CS_MODE_LITTLE_ENDIAN }, { "hppa11be", CS_ARCH_HPPA, CS_MODE_HPPA_11 | CS_MODE_BIG_ENDIAN }, { "hppa20", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_LITTLE_ENDIAN }, { "hppa20be", CS_ARCH_HPPA, CS_MODE_HPPA_20 | CS_MODE_BIG_ENDIAN }, { "hppa20w", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_LITTLE_ENDIAN }, { "hppa20wbe", CS_ARCH_HPPA, CS_MODE_HPPA_20W | CS_MODE_BIG_ENDIAN }, { "loongarch32", CS_ARCH_LOONGARCH, CS_MODE_LOONGARCH32 }, { "loongarch64", CS_ARCH_LOONGARCH, CS_MODE_LOONGARCH64 }, { NULL } }; static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins); void print_string_hex(const char *comment, unsigned char *str, size_t len) { unsigned char *c; printf("%s", comment); for (c = str; c < str + len; c++) { printf("0x%02x ", *c & 0xff); } printf("\n"); } // convert hexchar to hexnum static uint8_t char_to_hexnum(char c) { if (c >= '0' && c <= '9') { return (uint8_t)(c - '0'); } if (c >= 'a' && c <= 'f') { return (uint8_t)(10 + c - 'a'); } // c >= 'A' && c <= 'F' return (uint8_t)(10 + c - 'A'); } // convert user input (char[]) to uint8_t[], each element of which is // valid hexadecimal, and return actual length of uint8_t[] in @size. static uint8_t *preprocess(char *code, size_t *size) { size_t i = 0, j = 0; uint8_t high, low; uint8_t *result; if (strlen(code) == 0) return NULL; result = (uint8_t *)malloc(strlen(code)); if (result != NULL) { while (code[i] != '\0') { if (isxdigit(code[i]) && isxdigit(code[i+1])) { high = 16 * char_to_hexnum(code[i]); low = char_to_hexnum(code[i+1]); result[j] = high + low; i++; j++; } i++; } *size = j; } return result; } static void usage(char *prog) { printf("Cstool for Capstone Disassembler Engine v%u.%u.%u\n\n", CS_VERSION_MAJOR, CS_VERSION_MINOR, CS_VERSION_EXTRA); printf("Syntax: %s [-d|-a|-r|-s|-u|-v] [start-address-in-hex-format]\n", prog); printf("\nThe following options are supported:\n"); if (cs_support(CS_ARCH_X86)) { printf(" x16 16-bit mode (X86)\n"); printf(" x32 32-bit mode (X86)\n"); printf(" x64 64-bit mode (X86)\n"); printf(" x16att 16-bit mode (X86), syntax AT&T\n"); printf(" x32att 32-bit mode (X86), syntax AT&T\n"); printf(" x64att 64-bit mode (X86), syntax AT&T\n"); } if (cs_support(CS_ARCH_ARM)) { printf(" arm arm\n"); printf(" armbe arm + big endian\n"); printf(" thumb thumb mode\n"); printf(" thumbbe thumb + big endian\n"); printf(" cortexm thumb + cortex-m extensions\n"); printf(" cortexv8m thumb + cortex-m extensions + v8\n"); printf(" armv8 arm v8\n"); printf(" thumbv8 thumb v8\n"); printf(" armv8be arm v8 + big endian\n"); printf(" thumbv8be thumb v8 + big endian\n"); } if (cs_support(CS_ARCH_AARCH64)) { printf(" aarch64 aarch64 mode\n"); printf(" aarch64be aarch64 + big endian\n"); } if (cs_support(CS_ARCH_ALPHA)) { printf(" alpha alpha + little endian\n"); printf(" alphabe alpha + big endian\n"); } if (cs_support(CS_ARCH_HPPA)) { printf(" hppa11 hppa V1.1 + little endian\n"); printf(" hppa11be hppa V1.1 + big endian\n"); printf(" hppa20 hppa V2.0 + little endian\n"); printf(" hppa20be hppa V2.0 + big endian\n"); printf(" hppa20w hppa V2.0 wide + little endian\n"); printf(" hppa20wbe hppa V2.0 wide + big endian\n"); } if (cs_support(CS_ARCH_MIPS)) { printf(" mips mips32 + little endian\n"); printf(" mipsbe mips32 + big endian\n"); printf(" mips64 mips64 + little endian\n"); printf(" mips64be mips64 + big endian\n"); } if (cs_support(CS_ARCH_PPC)) { printf(" ppc32 ppc32 + little endian\n"); printf(" ppc32be ppc32 + big endian\n"); printf(" ppc32qpx ppc32 + qpx + little endian\n"); printf(" ppc32beqpx ppc32 + qpx + big endian\n"); printf(" ppc32ps ppc32 + ps + little endian\n"); printf(" ppc32beps ppc32 + ps + big endian\n"); printf(" ppc64 ppc64 + little endian\n"); printf(" ppc64be ppc64 + big endian\n"); printf(" ppc64qpx ppc64 + qpx + little endian\n"); printf(" ppc64beqpx ppc64 + qpx + big endian\n"); } if (cs_support(CS_ARCH_SPARC)) { printf(" sparc sparc\n"); } if (cs_support(CS_ARCH_SYSZ)) { printf(" systemz systemz (s390x)\n"); } if (cs_support(CS_ARCH_XCORE)) { printf(" xcore xcore\n"); } if (cs_support(CS_ARCH_M68K)) { printf(" m68k m68k + big endian\n"); printf(" m68k40 m68k_040\n"); } if (cs_support(CS_ARCH_TMS320C64X)) { printf(" tms320c64x TMS320C64x\n"); } if (cs_support(CS_ARCH_M680X)) { printf(" m6800 M6800/2\n"); printf(" m6801 M6801/3\n"); printf(" m6805 M6805\n"); printf(" m6808 M68HC08\n"); printf(" m6809 M6809\n"); printf(" m6811 M68HC11\n"); printf(" cpu12 M68HC12/HCS12\n"); printf(" hd6301 HD6301/3\n"); printf(" hd6309 HD6309\n"); printf(" hcs08 HCS08\n"); } if (cs_support(CS_ARCH_EVM)) { printf(" evm Ethereum Virtual Machine\n"); } if (cs_support(CS_ARCH_MOS65XX)) { printf(" 6502 MOS 6502\n"); printf(" 65c02 WDC 65c02\n"); printf(" w65c02 WDC w65c02\n"); printf(" 65816 WDC 65816 (long m/x)\n"); } if (cs_support(CS_ARCH_WASM)) { printf(" wasm: Web Assembly\n"); } if (cs_support(CS_ARCH_BPF)) { printf(" bpf Classic BPF\n"); printf(" bpfbe Classic BPF + big endian\n"); printf(" ebpf Extended BPF\n"); printf(" ebpfbe Extended BPF + big endian\n"); } if (cs_support(CS_ARCH_RISCV)) { printf(" riscv32 riscv32\n"); printf(" riscv64 riscv64\n"); } if (cs_support(CS_ARCH_SH)) { printf(" sh superh SH1\n"); printf(" sh2 superh SH2\n"); printf(" sh2e superh SH2E\n"); printf(" sh2dsp superh SH2-DSP\n"); printf(" sh2a superh SH2A\n"); printf(" sh2afpu superh SH2A-FPU\n"); printf(" sh3 superh SH3\n"); printf(" sh3be superh SH3 big endian\n"); printf(" sh3e superh SH3E\n"); printf(" sh3ebe superh SH3E big endian\n"); printf(" sh3-dsp superh SH3-DSP\n"); printf(" sh3-dspbe superh SH3-DSP big endian\n"); printf(" sh4 superh SH4\n"); printf(" sh4be superh SH4 big endian\n"); printf(" sh4a superh SH4A\n"); printf(" sh4abe superh SH4A big endian\n"); printf(" sh4al-dsp superh SH4AL-DSP\n"); printf(" sh4al-dspbe superh SH4AL-DSP big endian\n"); } if (cs_support(CS_ARCH_TRICORE)) { printf(" tc110 tricore V1.1\n"); printf(" tc120 tricore V1.2\n"); printf(" tc130 tricore V1.3\n"); printf(" tc131 tricore V1.3.1\n"); printf(" tc160 tricore V1.6\n"); printf(" tc161 tricore V1.6.1\n"); printf(" tc162 tricore V1.6.2\n"); } if (cs_support(CS_ARCH_LOONGARCH)) { printf(" loongarch32 LoongArch32\n"); printf(" loongarch64 LoongArch64\n"); } printf("\nExtra options:\n"); printf(" -d show detailed information of the instructions\n"); printf(" -r show detailed information of the real instructions (even for alias)\n"); printf(" -a Print Capstone register alias (if any). Otherwise LLVM register names are emitted.\n"); printf(" -s decode in SKIPDATA mode\n"); printf(" -u show immediates as unsigned\n"); printf(" -f Dev fuzzing: Disassembles to 0xffffffff.\n\n"); printf(" -v show version & Capstone core build info\n\n"); } static void print_details(csh handle, cs_arch arch, cs_mode md, cs_insn *ins) { printf("\tID: %u (%s)\n", ins->id, cs_insn_name(handle, ins->id)); if (ins->is_alias) { printf("\tIs alias: %" PRIu64 " (%s) ", ins->alias_id, cs_insn_name(handle, ins->alias_id)); printf("with %s operand set\n", ins->usesAliasDetails ? "ALIAS" : "REAL"); } switch(arch) { case CS_ARCH_X86: print_insn_detail_x86(handle, md, ins); break; case CS_ARCH_ARM: print_insn_detail_arm(handle, ins); break; case CS_ARCH_AARCH64: print_insn_detail_aarch64(handle, ins); break; case CS_ARCH_MIPS: print_insn_detail_mips(handle, ins); break; case CS_ARCH_PPC: print_insn_detail_ppc(handle, ins); break; case CS_ARCH_SPARC: print_insn_detail_sparc(handle, ins); break; case CS_ARCH_SYSZ: print_insn_detail_sysz(handle, ins); break; case CS_ARCH_XCORE: print_insn_detail_xcore(handle, ins); break; case CS_ARCH_M68K: print_insn_detail_m68k(handle, ins); break; case CS_ARCH_TMS320C64X: print_insn_detail_tms320c64x(handle, ins); break; case CS_ARCH_M680X: print_insn_detail_m680x(handle, ins); break; case CS_ARCH_EVM: print_insn_detail_evm(handle, ins); break; case CS_ARCH_WASM: print_insn_detail_wasm(handle, ins); break; case CS_ARCH_MOS65XX: print_insn_detail_mos65xx(handle, ins); break; case CS_ARCH_BPF: print_insn_detail_bpf(handle, ins); break; case CS_ARCH_RISCV: print_insn_detail_riscv(handle, ins); break; case CS_ARCH_SH: print_insn_detail_sh(handle, ins); break; case CS_ARCH_TRICORE: print_insn_detail_tricore(handle, ins); break; case CS_ARCH_ALPHA: print_insn_detail_alpha(handle, ins); break; case CS_ARCH_HPPA: print_insn_detail_hppa(handle, ins); break; case CS_ARCH_LOONGARCH: print_insn_detail_loongarch(handle, ins); break; default: break; } if (ins->detail && ins->detail->groups_count) { int j; printf("\tGroups: "); for(j = 0; j < ins->detail->groups_count; j++) { printf("%s ", cs_group_name(handle, ins->detail->groups[j])); } printf("\n"); } printf("\n"); } static uint32_t read_le(uint8_t *buf, size_t size) { uint32_t res = 0; for (size_t i = 0, j = size - 1; i < size; ++i, --j) { res |= buf[i] << j * 8; } return res; } static void to_buf(uint32_t num, uint8_t *buf) { for (size_t i = 0, j = 3; i < 4; ++i, --j) { buf[i] = (num >> j) & 0xff; } } static void run_dev_fuzz(csh handle, uint8_t *bytes, uint32_t size) { uint8_t buf[4] = {0}; uint32_t bytes_as_num = read_le(bytes, size); uint32_t address = 0xffffffff; printf("Run dev fuzz\n"); printf("Start: 0x%" PRIx32 "\n", bytes_as_num); printf("End: 0xffffffff\n" "Address: 0x%" PRIx32 "\n", address); cs_insn *insn; while (true) { printf("\rProgress: 0x%08x\t\t", bytes_as_num); fflush(stdout); cs_disasm(handle, buf, 4, address, 0, &insn); if (insn && insn->detail) free(insn->detail); free(insn); bytes_as_num++; to_buf(bytes_as_num, buf); if (bytes_as_num == 0xffffffff) { printf("\rProgress: 0x%08x\t\t", bytes_as_num); fflush(stdout); cs_disasm(handle, (uint8_t*)&buf, 4, address, 0, &insn); if (insn && insn->detail) free(insn->detail); free(insn); printf("\n"); return; } } } int main(int argc, char **argv) { int i, c; csh handle; char *mode; uint8_t *assembly; size_t count, size; uint64_t address = 0LL; cs_insn *insn; cs_err err; cs_mode md; cs_arch arch = CS_ARCH_ALL; bool detail_flag = false; bool unsigned_flag = false; bool skipdata = false; bool custom_reg_alias = false; bool set_real_detail = false; bool dev_fuzz = false; int args_left; while ((c = getopt (argc, argv, "rasudhvf")) != -1) { switch (c) { case 'a': custom_reg_alias = true; break; case 'r': set_real_detail = true; break; case 's': skipdata = true; break; case 'u': unsigned_flag = true; break; case 'd': detail_flag = true; break; case 'v': printf("cstool for Capstone Disassembler, v%u.%u.%u\n", CS_VERSION_MAJOR, CS_VERSION_MINOR, CS_VERSION_EXTRA); printf("Capstone build: "); if (cs_support(CS_ARCH_X86)) { printf("x86=1 "); } if (cs_support(CS_ARCH_ARM)) { printf("arm=1 "); } if (cs_support(CS_ARCH_AARCH64)) { printf("aarch64=1 "); } if (cs_support(CS_ARCH_MIPS)) { printf("mips=1 "); } if (cs_support(CS_ARCH_PPC)) { printf("ppc=1 "); } if (cs_support(CS_ARCH_SPARC)) { printf("sparc=1 "); } if (cs_support(CS_ARCH_SYSZ)) { printf("sysz=1 "); } if (cs_support(CS_ARCH_XCORE)) { printf("xcore=1 "); } if (cs_support(CS_ARCH_M68K)) { printf("m68k=1 "); } if (cs_support(CS_ARCH_TMS320C64X)) { printf("tms320c64x=1 "); } if (cs_support(CS_ARCH_M680X)) { printf("m680x=1 "); } if (cs_support(CS_ARCH_EVM)) { printf("evm=1 "); } if (cs_support(CS_ARCH_WASM)) { printf("wasm=1 "); } if (cs_support(CS_ARCH_MOS65XX)) { printf("mos65xx=1 "); } if (cs_support(CS_ARCH_BPF)) { printf("bpf=1 "); } if (cs_support(CS_ARCH_RISCV)) { printf("riscv=1 "); } if (cs_support(CS_ARCH_SH)) { printf("sh=1 "); } if (cs_support(CS_SUPPORT_DIET)) { printf("diet=1 "); } if (cs_support(CS_SUPPORT_X86_REDUCE)) { printf("x86_reduce=1 "); } if (cs_support(CS_ARCH_TRICORE)) { printf("tricore=1 "); } if (cs_support(CS_ARCH_ALPHA)) { printf("alpha=1 "); } if (cs_support(CS_ARCH_HPPA)) { printf("hppa=1 "); } if (cs_support(CS_ARCH_LOONGARCH)) { printf("loongarch=1 "); } printf("\n"); return 0; case 'f': dev_fuzz = true; break; case 'h': usage(argv[0]); return 0; default: usage(argv[0]); return -1; } } args_left = argc - optind; if (args_left < 2 || args_left > 3) { usage(argv[0]); return -1; } mode = argv[optind]; assembly = preprocess(argv[optind + 1], &size); if (!assembly) { usage(argv[0]); return -1; } if (args_left == 3) { char *temp, *src = argv[optind + 2]; address = strtoull(src, &temp, 16); if (temp == src || *temp != '\0' || errno == ERANGE) { printf("ERROR: invalid address argument, quit!\n"); return -2; } } for (i = 0; all_archs[i].name; i++) { if (!strcmp(all_archs[i].name, mode)) { arch = all_archs[i].arch; err = cs_open(all_archs[i].arch, all_archs[i].mode, &handle); if (!err) { md = all_archs[i].mode; if (strstr (mode, "att")) { cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); } // turn on SKIPDATA mode if (skipdata) cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); } break; } } if (arch == CS_ARCH_ALL) { printf("ERROR: Invalid : \"%s\", quit!\n", mode); usage(argv[0]); return -1; } if (err) { printf("ERROR: Failed on cs_open(), quit!\n"); usage(argv[0]); return -1; } if (detail_flag) { cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); } if (unsigned_flag) { cs_option(handle, CS_OPT_UNSIGNED, CS_OPT_ON); } if (custom_reg_alias) { cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_CS_REG_ALIAS); } if (set_real_detail) { cs_option(handle, CS_OPT_DETAIL, CS_OPT_DETAIL_REAL); } if (dev_fuzz) { run_dev_fuzz(handle, assembly, size); cs_close(&handle); return 0; } count = cs_disasm(handle, assembly, size, address, 0, &insn); if (count > 0) { for (i = 0; i < count; i++) { int j; printf("%2"PRIx64" ", insn[i].address); for (j = 0; j < insn[i].size; j++) { if (j > 0) putchar(' '); printf("%02x", insn[i].bytes[j]); } // Align instruction when it varies in size. // ex: x86, s390x or compressed riscv if (arch == CS_ARCH_RISCV) { for (; j < 4; j++) { printf(" "); } } else if (arch == CS_ARCH_X86) { for (; j < 16; j++) { printf(" "); } } else if (arch == CS_ARCH_SYSZ) { for (; j < 6; j++) { printf(" "); } } printf(" %s\t%s\n", insn[i].mnemonic, insn[i].op_str); if (detail_flag) { print_details(handle, arch, md, &insn[i]); } } cs_free(insn, count); free(assembly); } else { printf("ERROR: invalid assembly code\n"); cs_close(&handle); free(assembly); return(-4); } cs_close(&handle); return 0; }