From 7a01b36ee5bd751a2f2fd020cda9cac411d3eda0 Mon Sep 17 00:00:00 2001 From: echotyh <1648200150@qq.com> Date: Mon, 10 Oct 2016 15:16:56 +0800 Subject: [PATCH] cstool 1.0 (#788) * first cstool -- Segmentation fault: 11 * Modify the format of output. * Preprocess the input from user. The result of converting looks right but the disassembly is not unsatisfactory. * Skip the character not in set A = {'a'~'f','A'~'F','0'~'9'}. i Please enter the commit message for your changes. Lines starting * delete cstool binary * using isxdigit() to tests for any hexadecimal-digit character * write README * final version 1.0 for cstool --- cstool/Makefile | 9 ++ cstool/README | 7 ++ cstool/cstool.c | 263 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 279 insertions(+) create mode 100644 cstool/Makefile create mode 100644 cstool/README create mode 100644 cstool/cstool.c diff --git a/cstool/Makefile b/cstool/Makefile new file mode 100644 index 00000000..d7730560 --- /dev/null +++ b/cstool/Makefile @@ -0,0 +1,9 @@ +# Sample Makefile for Capstone Disassembly Engine + +LIBNAME = capstone + +cstool: cstool.o + ${CC} $< -O3 -Wall -l$(LIBNAME) -o $@ + +%.o: %.c + ${CC} -c $< -o $@ diff --git a/cstool/README b/cstool/README new file mode 100644 index 00000000..139d4adc --- /dev/null +++ b/cstool/README @@ -0,0 +1,7 @@ +This directory contains cstool of capstone engine. +To compile, simply run "make" on commandline. And after that, you could use +./cstool [start-address-in-hex-format] +to use directly capstone engine. + +To see options are supported, you could input ./cstool + diff --git a/cstool/cstool.c b/cstool/cstool.c new file mode 100644 index 00000000..2145b251 --- /dev/null +++ b/cstool/cstool.c @@ -0,0 +1,263 @@ +/* Tang Yuhang <1648200150@qq.com> 2016 */ +#include +#include +#include +#include +#include + +#include + + +// 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[]. +static uint8_t *preprocess(char *code, size_t *size) +{ + size_t i, j = 0; + uint8_t high, low; + uint8_t *result; + 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("Syntax: %s [start-address-in-hex-format]\n", prog); + printf("\nThe following options are supported:\n"); + + if (cs_support(CS_ARCH_ARM)) { + printf(" arm: arm\n"); + printf(" armb: arm + big endian\n"); + printf(" arml: arm + little endian\n"); + printf(" thumb: thumb mode\n"); + printf(" thumbbe: thumb + big endian\n"); + printf(" thumble: thumb + billtle endian\n"); + } + + if (cs_support(CS_ARCH_ARM64)) { + printf(" arm64: aarch64 mode\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_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-att\n"); + printf(" x32att: 32-bit mode (X86) syntax-att\n"); + printf(" x64att: 64-bit mode (X86) syntax-att\n"); + } + + if (cs_support(CS_ARCH_PPC)) { + printf(" ppc64: ppc64 + little endian\n"); + printf(" ppc64be: ppc64 + 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"); + } + + printf("\n"); +} + +int main(int argc, char **argv) +{ + csh handle; + char *mode; + uint8_t *assembly; + size_t count, size; + uint64_t address = 0; + cs_insn *insn; + cs_err err; + + if (argc != 3 && argc != 4) { + usage(argv[0]); + return -1; + } + + mode = argv[1]; + assembly = preprocess(argv[2], &size); + if (assembly == NULL) { + printf("ERROR: invalid assembler-string argument, quit!\n"); + return -3; + } + + if (argc == 4) { + // cstool
+ char *temp; + address = strtoull(argv[3], &temp, 16); + if (temp == argv[3] || *temp != '\0' || errno == ERANGE) { + printf("ERROR: invalid address argument, quit!\n"); + return -2; + } + } + + if (!strcmp(mode, "arm")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM, &handle); + } + + if (!strcmp(mode, "armb")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "arml")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode, "thumb")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode, "thumbbe")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "thumble")) { + err = cs_open(CS_ARCH_ARM, CS_MODE_ARM + CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode, "arm64")) { + err = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode, "mips")) { + err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode, "mipsbe")) { + err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "mips64")) { + err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "mips64be")) { + err = cs_open(CS_ARCH_MIPS, CS_MODE_MIPS64 + CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "x16")) { + err = cs_open(CS_ARCH_X86, CS_MODE_16, &handle); + } + + if (!strcmp(mode, "x32")) { + err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle); + } + + if (!strcmp(mode, "x64")) { + err = cs_open(CS_ARCH_X86, CS_MODE_64, &handle); + } + + if (!strcmp(mode, "x16att")) { + err = cs_open(CS_ARCH_X86, CS_MODE_16, &handle); + if (!err) { + cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + } + } + + if (!strcmp(mode,"x32att")) { + err = cs_open(CS_ARCH_X86, CS_MODE_32, &handle); + if (!err) { + cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + } + } + + if (!strcmp(mode,"x64att")) { + err = cs_open(CS_ARCH_X86, CS_MODE_64, &handle); + if (!err) { + cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); + } + } + + if (!strcmp(mode,"ppc64")) { + err = cs_open(CS_ARCH_PPC, CS_MODE_64+CS_MODE_LITTLE_ENDIAN, &handle); + } + + if (!strcmp(mode,"ppc64be")) { + err = cs_open(CS_ARCH_PPC,CS_MODE_64+CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode,"sparc")) { + err = cs_open(CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode, "systemz") || !strcmp(mode, "sysz") || !strcmp(mode, "s390x")) { + err = cs_open(CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN, &handle); + } + + if (!strcmp(mode,"xcore")) { + err = cs_open(CS_ARCH_XCORE, CS_MODE_BIG_ENDIAN, &handle); + } + + if (err) { + printf("ERROR: Failed on cs_open()\n"); + usage(argv[0]); + return -1; + } + + count = cs_disasm(handle, assembly, size, address, 0, &insn); + if (count > 0) { + size_t j; + int i; + + printf("\n"); + for (j = 0; j < count; j++) { + printf("%"PRIx64 "\t", insn[j].address); + for (i = 0; i < insn[j].size; i++) { + printf("%02x", insn[j].bytes[i]); + } + printf("\t%s\t%s\n", insn[j].mnemonic, insn[j].op_str); + } + cs_free(insn, count); + } else { + printf("ERROR: no any assembly instrution corresponding to your input, please check your input, quit!\n"); + return(-4); + } + + cs_close(&handle); + return 0; +} + +