diff --git a/arch/EVM/EVMDisassembler.c b/arch/EVM/EVMDisassembler.c new file mode 100644 index 00000000..6cf68857 --- /dev/null +++ b/arch/EVM/EVMDisassembler.c @@ -0,0 +1,377 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#include + +#include "EVMDisassembler.h" +#include "EVMMapping.h" + +static short opcodes[] = { + EVM_INS_STOP, + EVM_INS_ADD, + EVM_INS_MUL, + EVM_INS_SUB, + EVM_INS_DIV, + EVM_INS_SDIV, + EVM_INS_MOD, + EVM_INS_SMOD, + EVM_INS_ADDMOD, + EVM_INS_MULMOD, + EVM_INS_EXP, + EVM_INS_SIGNEXTEND, + -1, + -1, + -1, + -1, + EVM_INS_LT, + EVM_INS_GT, + EVM_INS_SLT, + EVM_INS_SGT, + EVM_INS_EQ, + EVM_INS_ISZERO, + EVM_INS_AND, + EVM_INS_OR, + EVM_INS_XOR, + EVM_INS_NOT, + EVM_INS_BYTE, + -1, + -1, + -1, + -1, + -1, + EVM_INS_SHA3, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + EVM_INS_ADDRESS, + EVM_INS_BALANCE, + EVM_INS_ORIGIN, + EVM_INS_CALLER, + EVM_INS_CALLVALUE, + EVM_INS_CALLDATALOAD, + EVM_INS_CALLDATASIZE, + EVM_INS_CALLDATACOPY, + EVM_INS_CODESIZE, + EVM_INS_CODECOPY, + EVM_INS_GASPRICE, + EVM_INS_EXTCODESIZE, + EVM_INS_EXTCODECOPY, + EVM_INS_RETURNDATASIZE, + EVM_INS_RETURNDATACOPY, + -1, + EVM_INS_BLOCKHASH, + EVM_INS_COINBASE, + EVM_INS_TIMESTAMP, + EVM_INS_NUMBER, + EVM_INS_DIFFICULTY, + EVM_INS_GASLIMIT, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + EVM_INS_POP, + EVM_INS_MLOAD, + EVM_INS_MSTORE, + EVM_INS_MSTORE8, + EVM_INS_SLOAD, + EVM_INS_SSTORE, + EVM_INS_JUMP, + EVM_INS_JUMPI, + EVM_INS_PC, + EVM_INS_MSIZE, + EVM_INS_GAS, + EVM_INS_JUMPDEST, + -1, + -1, + -1, + -1, + EVM_INS_PUSH1, + EVM_INS_PUSH2, + EVM_INS_PUSH3, + EVM_INS_PUSH4, + EVM_INS_PUSH5, + EVM_INS_PUSH6, + EVM_INS_PUSH7, + EVM_INS_PUSH8, + EVM_INS_PUSH9, + EVM_INS_PUSH10, + EVM_INS_PUSH11, + EVM_INS_PUSH12, + EVM_INS_PUSH13, + EVM_INS_PUSH14, + EVM_INS_PUSH15, + EVM_INS_PUSH16, + EVM_INS_PUSH17, + EVM_INS_PUSH18, + EVM_INS_PUSH19, + EVM_INS_PUSH20, + EVM_INS_PUSH21, + EVM_INS_PUSH22, + EVM_INS_PUSH23, + EVM_INS_PUSH24, + EVM_INS_PUSH25, + EVM_INS_PUSH26, + EVM_INS_PUSH27, + EVM_INS_PUSH28, + EVM_INS_PUSH29, + EVM_INS_PUSH30, + EVM_INS_PUSH31, + EVM_INS_PUSH32, + EVM_INS_DUP1, + EVM_INS_DUP2, + EVM_INS_DUP3, + EVM_INS_DUP4, + EVM_INS_DUP5, + EVM_INS_DUP6, + EVM_INS_DUP7, + EVM_INS_DUP8, + EVM_INS_DUP9, + EVM_INS_DUP10, + EVM_INS_DUP11, + EVM_INS_DUP12, + EVM_INS_DUP13, + EVM_INS_DUP14, + EVM_INS_DUP15, + EVM_INS_DUP16, + EVM_INS_SWAP1, + EVM_INS_SWAP2, + EVM_INS_SWAP3, + EVM_INS_SWAP4, + EVM_INS_SWAP5, + EVM_INS_SWAP6, + EVM_INS_SWAP7, + EVM_INS_SWAP8, + EVM_INS_SWAP9, + EVM_INS_SWAP10, + EVM_INS_SWAP11, + EVM_INS_SWAP12, + EVM_INS_SWAP13, + EVM_INS_SWAP14, + EVM_INS_SWAP15, + EVM_INS_SWAP16, + EVM_INS_LOG0, + EVM_INS_LOG1, + EVM_INS_LOG2, + EVM_INS_LOG3, + EVM_INS_LOG4, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + -1, + EVM_INS_CREATE, + EVM_INS_CALL, + EVM_INS_CALLCODE, + EVM_INS_RETURN, + EVM_INS_DELEGATECALL, + EVM_INS_CALLBLACKBOX, + -1, + -1, + -1, + -1, + EVM_INS_STATICCALL, + -1, + -1, + EVM_INS_REVERT, + -1, + EVM_INS_SUICIDE, +}; + +bool EVM_getInstruction(csh ud, const uint8_t *code, size_t code_len, + MCInst *MI, uint16_t *size, uint64_t address, void *inst_info) +{ + unsigned char opcode; + + if (code_len == 0) + return false; + + opcode = code[0]; + if (opcodes[opcode] == -1) { + // invalid opcode + return false; + } + + // valid opcode + MI->address = address; + MI->OpcodePub = MI->Opcode = opcode; + + if (opcode >= EVM_INS_PUSH1 && opcode <= EVM_INS_PUSH32) { + unsigned char len = (opcode - EVM_INS_PUSH1 + 1); + if (code_len < 1 + len) { + // not enough data + return false; + } + + *size = 1 + len; + memcpy(MI->evm_data, code + 1, len); + } else + *size = 1; + + if (MI->flat_insn->detail) { + memset(&MI->flat_insn->detail->evm, 0, sizeof(cs_evm)); + EVM_get_insn_id((cs_struct *)ud, MI->flat_insn, opcode); + + MI->flat_insn->detail->groups_count = 0; + + if (MI->flat_insn->detail->evm.pop) { + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STACK_READ; + MI->flat_insn->detail->groups_count++; + } + + if (MI->flat_insn->detail->evm.push) { + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STACK_WRITE; + MI->flat_insn->detail->groups_count++; + } + + // setup groups + switch(opcode) { + case EVM_INS_ADD: + case EVM_INS_MUL: + case EVM_INS_SUB: + case EVM_INS_DIV: + case EVM_INS_SDIV: + case EVM_INS_MOD: + case EVM_INS_SMOD: + case EVM_INS_ADDMOD: + case EVM_INS_MULMOD: + case EVM_INS_EXP: + case EVM_INS_SIGNEXTEND: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MATH; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_MSTORE: + case EVM_INS_MSTORE8: + case EVM_INS_CALLDATACOPY: + case EVM_INS_CODECOPY: + case EVM_INS_EXTCODECOPY: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MEM_WRITE; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_MLOAD: + case EVM_INS_CREATE: + case EVM_INS_CALL: + case EVM_INS_CALLCODE: + case EVM_INS_RETURN: + case EVM_INS_DELEGATECALL: + case EVM_INS_REVERT: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_MEM_READ; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_SSTORE: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STORE_WRITE; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_SLOAD: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_STORE_READ; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_JUMP: + case EVM_INS_JUMPI: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_JUMP; + MI->flat_insn->detail->groups_count++; + break; + + case EVM_INS_STOP: + case EVM_INS_SUICIDE: + MI->flat_insn->detail->groups[MI->flat_insn->detail->groups_count] = EVM_GRP_HALT; + MI->flat_insn->detail->groups_count++; + break; + + } + } + + return true; +} diff --git a/arch/EVM/EVMDisassembler.h b/arch/EVM/EVMDisassembler.h new file mode 100644 index 00000000..afd7e469 --- /dev/null +++ b/arch/EVM/EVMDisassembler.h @@ -0,0 +1,12 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#ifndef CS_EVMDISASSEMBLER_H +#define CS_EVMDISASSEMBLER_H + +#include "../../MCInst.h" + +bool EVM_getInstruction(csh ud, const uint8_t *code, size_t code_len, + MCInst *instr, uint16_t *size, uint64_t address, void *info); + +#endif diff --git a/arch/EVM/EVMInstPrinter.c b/arch/EVM/EVMInstPrinter.c new file mode 100644 index 00000000..7f452800 --- /dev/null +++ b/arch/EVM/EVMInstPrinter.c @@ -0,0 +1,20 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#include "EVMInstPrinter.h" +#include "EVMMapping.h" + + +void EVM_printInst(MCInst *MI, struct SStream *O, void *PrinterInfo) +{ + SStream_concat(O, EVM_insn_name((csh)MI->csh, MI->Opcode)); + + if (MI->Opcode >= EVM_INS_PUSH1 && MI->Opcode <= EVM_INS_PUSH32) { + unsigned int i; + + SStream_concat0(O, "\t"); + for (i = 0; i < MI->Opcode - EVM_INS_PUSH1 + 1; i++) { + SStream_concat(O, "%02x", MI->evm_data[i]); + } + } +} diff --git a/arch/EVM/EVMInstPrinter.h b/arch/EVM/EVMInstPrinter.h new file mode 100644 index 00000000..2f1ac2cf --- /dev/null +++ b/arch/EVM/EVMInstPrinter.h @@ -0,0 +1,17 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#ifndef CS_EVMINSTPRINTER_H +#define CS_EVMINSTPRINTER_H + + +#include "capstone/capstone.h" +#include "../../MCInst.h" +#include "../../SStream.h" +#include "../../cs_priv.h" + +struct SStream; + +void EVM_printInst(MCInst *MI, struct SStream *O, void *Info); + +#endif diff --git a/arch/EVM/EVMMapping.c b/arch/EVM/EVMMapping.c new file mode 100644 index 00000000..212a815b --- /dev/null +++ b/arch/EVM/EVMMapping.c @@ -0,0 +1,350 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#ifdef CAPSTONE_HAS_EVM + +#include + +#include "../../cs_priv.h" +#include "../../utils.h" + +#include "EVMMapping.h" + +#ifndef CAPSTONE_DIET +static cs_evm insns[] = { +#include "EVMMappingInsn.inc" +}; +#endif + +// look for @id in @insns, given its size in @max. first time call will update @cache. +// return 0 if not found +static int evm_insn_find(cs_evm *insns, unsigned int max, unsigned int id) +{ + if (id > max) + return -1; + + if (insns[id].fee == 0xffffffff) + // unused opcode + return -1; + + return (int)id; +} + +// fill in details +void EVM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id) +{ +#ifndef CAPSTONE_DIET + int i = evm_insn_find(insns, ARR_SIZE(insns), id); + //printf(">> id = %u\n", id); + if (i >= 0) { + if (h->detail) { + cs_struct handle; + handle.detail = h->detail; + + memcpy(&insn->detail->evm, &insns[i], sizeof(insns[i])); + } + } +#endif +} + +#ifndef CAPSTONE_DIET +static name_map insn_name_maps[] = { + { EVM_INS_STOP, "stop" }, + { EVM_INS_ADD, "add" }, + { EVM_INS_MUL, "mul" }, + { EVM_INS_SUB, "sub" }, + { EVM_INS_DIV, "div" }, + { EVM_INS_SDIV, "sdiv" }, + { EVM_INS_MOD, "mod" }, + { EVM_INS_SMOD, "smod" }, + { EVM_INS_ADDMOD, "addmod" }, + { EVM_INS_MULMOD, "mulmod" }, + { EVM_INS_EXP, "exp" }, + { EVM_INS_SIGNEXTEND, "signextend" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_LT, "lt" }, + { EVM_INS_GT, "gt" }, + { EVM_INS_SLT, "slt" }, + { EVM_INS_SGT, "sgt" }, + { EVM_INS_EQ, "eq" }, + { EVM_INS_ISZERO, "iszero" }, + { EVM_INS_AND, "and" }, + { EVM_INS_OR, "or" }, + { EVM_INS_XOR, "xor" }, + { EVM_INS_NOT, "not" }, + { EVM_INS_BYTE, "byte" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_SHA3, "sha3" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_ADDRESS, "address" }, + { EVM_INS_BALANCE, "balance" }, + { EVM_INS_ORIGIN, "origin" }, + { EVM_INS_CALLER, "caller" }, + { EVM_INS_CALLVALUE, "callvalue" }, + { EVM_INS_CALLDATALOAD, "calldataload" }, + { EVM_INS_CALLDATASIZE, "calldatasize" }, + { EVM_INS_CALLDATACOPY, "calldatacopy" }, + { EVM_INS_CODESIZE, "codesize" }, + { EVM_INS_CODECOPY, "codecopy" }, + { EVM_INS_GASPRICE, "gasprice" }, + { EVM_INS_EXTCODESIZE, "extcodesize" }, + { EVM_INS_EXTCODECOPY, "extcodecopy" }, + { EVM_INS_RETURNDATASIZE, "returndatasize" }, + { EVM_INS_RETURNDATACOPY, "returndatacopy" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_BLOCKHASH, "blockhash" }, + { EVM_INS_COINBASE, "coinbase" }, + { EVM_INS_TIMESTAMP, "timestamp" }, + { EVM_INS_NUMBER, "number" }, + { EVM_INS_DIFFICULTY, "difficulty" }, + { EVM_INS_GASLIMIT, "gaslimit" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_POP, "pop" }, + { EVM_INS_MLOAD, "mload" }, + { EVM_INS_MSTORE, "mstore" }, + { EVM_INS_MSTORE8, "mstore8" }, + { EVM_INS_SLOAD, "sload" }, + { EVM_INS_SSTORE, "sstore" }, + { EVM_INS_JUMP, "jump" }, + { EVM_INS_JUMPI, "jumpi" }, + { EVM_INS_PC, "pc" }, + { EVM_INS_MSIZE, "msize" }, + { EVM_INS_GAS, "gas" }, + { EVM_INS_JUMPDEST, "jumpdest" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_PUSH1, "push1" }, + { EVM_INS_PUSH2, "push2" }, + { EVM_INS_PUSH3, "push3" }, + { EVM_INS_PUSH4, "push4" }, + { EVM_INS_PUSH5, "push5" }, + { EVM_INS_PUSH6, "push6" }, + { EVM_INS_PUSH7, "push7" }, + { EVM_INS_PUSH8, "push8" }, + { EVM_INS_PUSH9, "push9" }, + { EVM_INS_PUSH10, "push10" }, + { EVM_INS_PUSH11, "push11" }, + { EVM_INS_PUSH12, "push12" }, + { EVM_INS_PUSH13, "push13" }, + { EVM_INS_PUSH14, "push14" }, + { EVM_INS_PUSH15, "push15" }, + { EVM_INS_PUSH16, "push16" }, + { EVM_INS_PUSH17, "push17" }, + { EVM_INS_PUSH18, "push18" }, + { EVM_INS_PUSH19, "push19" }, + { EVM_INS_PUSH20, "push20" }, + { EVM_INS_PUSH21, "push21" }, + { EVM_INS_PUSH22, "push22" }, + { EVM_INS_PUSH23, "push23" }, + { EVM_INS_PUSH24, "push24" }, + { EVM_INS_PUSH25, "push25" }, + { EVM_INS_PUSH26, "push26" }, + { EVM_INS_PUSH27, "push27" }, + { EVM_INS_PUSH28, "push28" }, + { EVM_INS_PUSH29, "push29" }, + { EVM_INS_PUSH30, "push30" }, + { EVM_INS_PUSH31, "push31" }, + { EVM_INS_PUSH32, "push32" }, + { EVM_INS_DUP1, "dup1" }, + { EVM_INS_DUP2, "dup2" }, + { EVM_INS_DUP3, "dup3" }, + { EVM_INS_DUP4, "dup4" }, + { EVM_INS_DUP5, "dup5" }, + { EVM_INS_DUP6, "dup6" }, + { EVM_INS_DUP7, "dup7" }, + { EVM_INS_DUP8, "dup8" }, + { EVM_INS_DUP9, "dup9" }, + { EVM_INS_DUP10, "dup10" }, + { EVM_INS_DUP11, "dup11" }, + { EVM_INS_DUP12, "dup12" }, + { EVM_INS_DUP13, "dup13" }, + { EVM_INS_DUP14, "dup14" }, + { EVM_INS_DUP15, "dup15" }, + { EVM_INS_DUP16, "dup16" }, + { EVM_INS_SWAP1, "swap1" }, + { EVM_INS_SWAP2, "swap2" }, + { EVM_INS_SWAP3, "swap3" }, + { EVM_INS_SWAP4, "swap4" }, + { EVM_INS_SWAP5, "swap5" }, + { EVM_INS_SWAP6, "swap6" }, + { EVM_INS_SWAP7, "swap7" }, + { EVM_INS_SWAP8, "swap8" }, + { EVM_INS_SWAP9, "swap9" }, + { EVM_INS_SWAP10, "swap10" }, + { EVM_INS_SWAP11, "swap11" }, + { EVM_INS_SWAP12, "swap12" }, + { EVM_INS_SWAP13, "swap13" }, + { EVM_INS_SWAP14, "swap14" }, + { EVM_INS_SWAP15, "swap15" }, + { EVM_INS_SWAP16, "swap16" }, + { EVM_INS_LOG0, "log0" }, + { EVM_INS_LOG1, "log1" }, + { EVM_INS_LOG2, "log2" }, + { EVM_INS_LOG3, "log3" }, + { EVM_INS_LOG4, "log4" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_CREATE, "create" }, + { EVM_INS_CALL, "call" }, + { EVM_INS_CALLCODE, "callcode" }, + { EVM_INS_RETURN, "return" }, + { EVM_INS_DELEGATECALL, "delegatecall" }, + { EVM_INS_CALLBLACKBOX, "callblackbox" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_STATICCALL, "staticcall" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_REVERT, "revert" }, + { EVM_INS_INVALID, NULL }, + { EVM_INS_SUICIDE, "suicide" }, +}; +#endif + +const char *EVM_insn_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + if (id >= ARR_SIZE(insn_name_maps)) + return NULL; + else + return insn_name_maps[id].name; +#else + return NULL; +#endif +} + +#ifndef CAPSTONE_DIET +static name_map group_name_maps[] = { + // generic groups + { EVM_GRP_INVALID, NULL }, + { EVM_GRP_JUMP, "jump" }, + // special groups + { EVM_GRP_MATH, "math" }, + + { EVM_GRP_MATH, "math" }, + { EVM_GRP_STACK_WRITE, "stack_write" }, + { EVM_GRP_STACK_READ, "stack_read" }, + { EVM_GRP_MEM_WRITE, "mem_write" }, + { EVM_GRP_MEM_READ, "mem_read" }, + { EVM_GRP_STORE_WRITE, "store_write" }, + { EVM_GRP_STORE_READ, "store_read" }, + { EVM_GRP_HALT, "halt" }, +}; +#endif + +const char *EVM_group_name(csh handle, unsigned int id) +{ +#ifndef CAPSTONE_DIET + return id2name(group_name_maps, ARR_SIZE(group_name_maps), id); +#else + return NULL; +#endif +} +#endif diff --git a/arch/EVM/EVMMapping.h b/arch/EVM/EVMMapping.h new file mode 100644 index 00000000..576e0041 --- /dev/null +++ b/arch/EVM/EVMMapping.h @@ -0,0 +1,8 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#include + +void EVM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id); +const char *EVM_insn_name(csh handle, unsigned int id); +const char *EVM_group_name(csh handle, unsigned int id); diff --git a/arch/EVM/EVMMappingInsn.inc b/arch/EVM/EVMMappingInsn.inc new file mode 100644 index 00000000..64f072fe --- /dev/null +++ b/arch/EVM/EVMMappingInsn.inc @@ -0,0 +1,258 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +{ 0, 0, 0 }, // STOP +{ 2, 1, 3 }, // ADD +{ 2, 1, 5 }, // MUL +{ 2, 1, 3 }, // SUB +{ 2, 1, 5 }, // DIV +{ 2, 1, 5 }, // SDIV +{ 2, 1, 5 }, // MOD +{ 2, 1, 5 }, // SMOD +{ 3, 1, 8 }, // ADDMOD +{ 3, 1, 8 }, // MULMOD +{ 2, 1, 10 }, // EXP +{ 2, 1, 5 }, // SIGNEXTEND +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 2, 1, 3 }, // LT +{ 2, 1, 3 }, // GT +{ 2, 1, 3 }, // SLT +{ 2, 1, 3 }, // SGT +{ 2, 1, 3 }, // EQ +{ 1, 1, 3 }, // ISZERO +{ 2, 1, 3 }, // AND +{ 2, 1, 3 }, // OR +{ 2, 1, 3 }, // XOR +{ 1, 1, 3 }, // NOT +{ 2, 1, 3 }, // BYTE +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 2, 1, 30 }, // SHA3 +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 1, 2 }, // ADDRESS +{ 1, 1, 20 }, // BALANCE +{ 0, 1, 2 }, // ORIGIN +{ 0, 1, 2 }, // CALLER +{ 0, 1, 2 }, // CALLVALUE +{ 1, 1, 3 }, // CALLDATALOAD +{ 0, 1, 2 }, // CALLDATASIZE +{ 3, 0, 3 }, // CALLDATACOPY +{ 0, 1, 2 }, // CODESIZE +{ 3, 0, 3 }, // CODECOPY +{ 0, 1, 2 }, // GASPRICE +{ 1, 1, 20 }, // EXTCODESIZE +{ 4, 0, 20 }, // EXTCODECOPY +{ 0, 1, 2 }, // RETURNDATASIZE +{ 3, 0, 3 }, // RETURNDATACOPY +{ 0, 0, 0xffffffff }, // unused +{ 1, 1, 20 }, // BLOCKHASH +{ 0, 1, 2 }, // COINBASE +{ 0, 1, 2 }, // TIMESTAMP +{ 0, 1, 2 }, // NUMBER +{ 0, 1, 2 }, // DIFFICULTY +{ 0, 1, 2 }, // GASLIMIT +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 1, 0, 2 }, // POP +{ 1, 1, 3 }, // MLOAD +{ 2, 0, 3 }, // MSTORE +{ 2, 0, 3 }, // MSTORE8 +{ 1, 1, 50 }, // SLOAD +{ 2, 0, 0 }, // SSTORE +{ 1, 0, 8 }, // JUMP +{ 2, 0, 10 }, // JUMPI +{ 0, 1, 2 }, // GETPC +{ 0, 1, 2 }, // MSIZE +{ 0, 1, 2 }, // GAS +{ 0, 0, 1 }, // JUMPDEST +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 1, 3 }, // PUSH1 +{ 0, 1, 3 }, // PUSH2 +{ 0, 1, 3 }, // PUSH3 +{ 0, 1, 3 }, // PUSH4 +{ 0, 1, 3 }, // PUSH5 +{ 0, 1, 3 }, // PUSH6 +{ 0, 1, 3 }, // PUSH7 +{ 0, 1, 3 }, // PUSH8 +{ 0, 1, 3 }, // PUSH9 +{ 0, 1, 3 }, // PUSH10 +{ 0, 1, 3 }, // PUSH11 +{ 0, 1, 3 }, // PUSH12 +{ 0, 1, 3 }, // PUSH13 +{ 0, 1, 3 }, // PUSH14 +{ 0, 1, 3 }, // PUSH15 +{ 0, 1, 3 }, // PUSH16 +{ 0, 1, 3 }, // PUSH17 +{ 0, 1, 3 }, // PUSH18 +{ 0, 1, 3 }, // PUSH19 +{ 0, 1, 3 }, // PUSH20 +{ 0, 1, 3 }, // PUSH21 +{ 0, 1, 3 }, // PUSH22 +{ 0, 1, 3 }, // PUSH23 +{ 0, 1, 3 }, // PUSH24 +{ 0, 1, 3 }, // PUSH25 +{ 0, 1, 3 }, // PUSH26 +{ 0, 1, 3 }, // PUSH27 +{ 0, 1, 3 }, // PUSH28 +{ 0, 1, 3 }, // PUSH29 +{ 0, 1, 3 }, // PUSH30 +{ 0, 1, 3 }, // PUSH31 +{ 0, 1, 3 }, // PUSH32 +{ 1, 2, 3 }, // DUP1 +{ 2, 3, 3 }, // DUP2 +{ 3, 4, 3 }, // DUP3 +{ 4, 5, 3 }, // DUP4 +{ 5, 6, 3 }, // DUP5 +{ 6, 7, 3 }, // DUP6 +{ 7, 8, 3 }, // DUP7 +{ 8, 9, 3 }, // DUP8 +{ 9, 10, 3 }, // DUP9 +{ 10, 11, 3 }, // DUP10 +{ 11, 12, 3 }, // DUP11 +{ 12, 13, 3 }, // DUP12 +{ 13, 14, 3 }, // DUP13 +{ 14, 15, 3 }, // DUP14 +{ 15, 16, 3 }, // DUP15 +{ 16, 17, 3 }, // DUP16 +{ 2, 2, 3 }, // SWAP1 +{ 3, 3, 3 }, // SWAP2 +{ 4, 4, 3 }, // SWAP3 +{ 5, 5, 3 }, // SWAP4 +{ 6, 6, 3 }, // SWAP5 +{ 7, 7, 3 }, // SWAP6 +{ 8, 8, 3 }, // SWAP7 +{ 9, 9, 3 }, // SWAP8 +{ 10, 10, 3 }, // SWAP9 +{ 11, 11, 3 }, // SWAP10 +{ 12, 12, 3 }, // SWAP11 +{ 13, 13, 3 }, // SWAP12 +{ 14, 14, 3 }, // SWAP13 +{ 15, 15, 3 }, // SWAP14 +{ 16, 16, 3 }, // SWAP15 +{ 17, 17, 3 }, // SWAP16 +{ 2, 0, 375 }, // LOG0 +{ 3, 0, 750 }, // LOG1 +{ 4, 0, 1125 }, // LOG2 +{ 5, 0, 1500 }, // LOG3 +{ 6, 0, 1875 }, // LOG4 +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 3, 1, 32000 }, // CREATE +{ 7, 1, 40 }, // CALL +{ 7, 1, 40 }, // CALLCODE +{ 2, 0, 0 }, // RETURN +{ 6, 1, 40 }, // DELEGATECALL +{ 7, 1, 40 }, // CALLBLACKBOX +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 6, 1, 40 }, // STATICCALL +{ 0, 0, 0xffffffff }, // unused +{ 0, 0, 0xffffffff }, // unused +{ 2, 0, 0 }, // REVERT +{ 0, 0, 0xffffffff }, // unused +{ 1, 0, 0 }, // SUICIDE diff --git a/arch/EVM/EVMModule.c b/arch/EVM/EVMModule.c new file mode 100644 index 00000000..faf809e0 --- /dev/null +++ b/arch/EVM/EVMModule.c @@ -0,0 +1,41 @@ +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh, 2018 */ + +#ifdef CAPSTONE_HAS_ARM + +#include "../../cs_priv.h" +#include "EVMDisassembler.h" +#include "EVMInstPrinter.h" +#include "EVMMapping.h" + +static cs_err init(cs_struct *ud) +{ + // verify if requested mode is valid + if (ud->mode) + return CS_ERR_MODE; + + ud->printer = EVM_printInst; + ud->printer_info = NULL; + ud->insn_id = EVM_get_insn_id; + ud->insn_name = EVM_insn_name; + ud->group_name = EVM_group_name; + ud->disasm = EVM_getInstruction; + + return CS_ERR_OK; +} + +static cs_err option(cs_struct *handle, cs_opt_type type, size_t value) +{ + return CS_ERR_OK; +} + +void EVM_enable(void) +{ + cs_arch_init[CS_ARCH_EVM] = init; + cs_arch_option[CS_ARCH_EVM] = option; + + // support this arch + all_arch |= (1 << CS_ARCH_EVM); +} + +#endif diff --git a/bindings/java/capstone/Evm_const.java b/bindings/java/capstone/Evm_const.java new file mode 100644 index 00000000..bfb301ce --- /dev/null +++ b/bindings/java/capstone/Evm_const.java @@ -0,0 +1,159 @@ +// For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT +package capstone; + +public class Evm_const { + + // EVM instruction + + public static final int EVM_INS_STOP = 0; + public static final int EVM_INS_ADD = 1; + public static final int EVM_INS_MUL = 2; + public static final int EVM_INS_SUB = 3; + public static final int EVM_INS_DIV = 4; + public static final int EVM_INS_SDIV = 5; + public static final int EVM_INS_MOD = 6; + public static final int EVM_INS_SMOD = 7; + public static final int EVM_INS_ADDMOD = 8; + public static final int EVM_INS_MULMOD = 9; + public static final int EVM_INS_EXP = 10; + public static final int EVM_INS_SIGNEXTEND = 11; + public static final int EVM_INS_LT = 16; + public static final int EVM_INS_GT = 17; + public static final int EVM_INS_SLT = 18; + public static final int EVM_INS_SGT = 19; + public static final int EVM_INS_EQ = 20; + public static final int EVM_INS_ISZERO = 21; + public static final int EVM_INS_AND = 22; + public static final int EVM_INS_OR = 23; + public static final int EVM_INS_XOR = 24; + public static final int EVM_INS_NOT = 25; + public static final int EVM_INS_BYTE = 26; + public static final int EVM_INS_SHA3 = 32; + public static final int EVM_INS_ADDRESS = 48; + public static final int EVM_INS_BALANCE = 49; + public static final int EVM_INS_ORIGIN = 50; + public static final int EVM_INS_CALLER = 51; + public static final int EVM_INS_CALLVALUE = 52; + public static final int EVM_INS_CALLDATALOAD = 53; + public static final int EVM_INS_CALLDATASIZE = 54; + public static final int EVM_INS_CALLDATACOPY = 55; + public static final int EVM_INS_CODESIZE = 56; + public static final int EVM_INS_CODECOPY = 57; + public static final int EVM_INS_GASPRICE = 58; + public static final int EVM_INS_EXTCODESIZE = 59; + public static final int EVM_INS_EXTCODECOPY = 60; + public static final int EVM_INS_RETURNDATASIZE = 61; + public static final int EVM_INS_RETURNDATACOPY = 62; + public static final int EVM_INS_BLOCKHASH = 64; + public static final int EVM_INS_COINBASE = 65; + public static final int EVM_INS_TIMESTAMP = 66; + public static final int EVM_INS_NUMBER = 67; + public static final int EVM_INS_DIFFICULTY = 68; + public static final int EVM_INS_GASLIMIT = 69; + public static final int EVM_INS_POP = 80; + public static final int EVM_INS_MLOAD = 81; + public static final int EVM_INS_MSTORE = 82; + public static final int EVM_INS_MSTORE8 = 83; + public static final int EVM_INS_SLOAD = 84; + public static final int EVM_INS_SSTORE = 85; + public static final int EVM_INS_JUMP = 86; + public static final int EVM_INS_JUMPI = 87; + public static final int EVM_INS_PC = 88; + public static final int EVM_INS_MSIZE = 89; + public static final int EVM_INS_GAS = 90; + public static final int EVM_INS_JUMPDEST = 91; + public static final int EVM_INS_PUSH1 = 96; + public static final int EVM_INS_PUSH2 = 97; + public static final int EVM_INS_PUSH3 = 98; + public static final int EVM_INS_PUSH4 = 99; + public static final int EVM_INS_PUSH5 = 100; + public static final int EVM_INS_PUSH6 = 101; + public static final int EVM_INS_PUSH7 = 102; + public static final int EVM_INS_PUSH8 = 103; + public static final int EVM_INS_PUSH9 = 104; + public static final int EVM_INS_PUSH10 = 105; + public static final int EVM_INS_PUSH11 = 106; + public static final int EVM_INS_PUSH12 = 107; + public static final int EVM_INS_PUSH13 = 108; + public static final int EVM_INS_PUSH14 = 109; + public static final int EVM_INS_PUSH15 = 110; + public static final int EVM_INS_PUSH16 = 111; + public static final int EVM_INS_PUSH17 = 112; + public static final int EVM_INS_PUSH18 = 113; + public static final int EVM_INS_PUSH19 = 114; + public static final int EVM_INS_PUSH20 = 115; + public static final int EVM_INS_PUSH21 = 116; + public static final int EVM_INS_PUSH22 = 117; + public static final int EVM_INS_PUSH23 = 118; + public static final int EVM_INS_PUSH24 = 119; + public static final int EVM_INS_PUSH25 = 120; + public static final int EVM_INS_PUSH26 = 121; + public static final int EVM_INS_PUSH27 = 122; + public static final int EVM_INS_PUSH28 = 123; + public static final int EVM_INS_PUSH29 = 124; + public static final int EVM_INS_PUSH30 = 125; + public static final int EVM_INS_PUSH31 = 126; + public static final int EVM_INS_PUSH32 = 127; + public static final int EVM_INS_DUP1 = 128; + public static final int EVM_INS_DUP2 = 129; + public static final int EVM_INS_DUP3 = 130; + public static final int EVM_INS_DUP4 = 131; + public static final int EVM_INS_DUP5 = 132; + public static final int EVM_INS_DUP6 = 133; + public static final int EVM_INS_DUP7 = 134; + public static final int EVM_INS_DUP8 = 135; + public static final int EVM_INS_DUP9 = 136; + public static final int EVM_INS_DUP10 = 137; + public static final int EVM_INS_DUP11 = 138; + public static final int EVM_INS_DUP12 = 139; + public static final int EVM_INS_DUP13 = 140; + public static final int EVM_INS_DUP14 = 141; + public static final int EVM_INS_DUP15 = 142; + public static final int EVM_INS_DUP16 = 143; + public static final int EVM_INS_SWAP1 = 144; + public static final int EVM_INS_SWAP2 = 145; + public static final int EVM_INS_SWAP3 = 146; + public static final int EVM_INS_SWAP4 = 147; + public static final int EVM_INS_SWAP5 = 148; + public static final int EVM_INS_SWAP6 = 149; + public static final int EVM_INS_SWAP7 = 150; + public static final int EVM_INS_SWAP8 = 151; + public static final int EVM_INS_SWAP9 = 152; + public static final int EVM_INS_SWAP10 = 153; + public static final int EVM_INS_SWAP11 = 154; + public static final int EVM_INS_SWAP12 = 155; + public static final int EVM_INS_SWAP13 = 156; + public static final int EVM_INS_SWAP14 = 157; + public static final int EVM_INS_SWAP15 = 158; + public static final int EVM_INS_SWAP16 = 159; + public static final int EVM_INS_LOG0 = 160; + public static final int EVM_INS_LOG1 = 161; + public static final int EVM_INS_LOG2 = 162; + public static final int EVM_INS_LOG3 = 163; + public static final int EVM_INS_LOG4 = 164; + public static final int EVM_INS_CREATE = 240; + public static final int EVM_INS_CALL = 241; + public static final int EVM_INS_CALLCODE = 242; + public static final int EVM_INS_RETURN = 243; + public static final int EVM_INS_DELEGATECALL = 244; + public static final int EVM_INS_CALLBLACKBOX = 245; + public static final int EVM_INS_STATICCALL = 250; + public static final int EVM_INS_REVERT = 253; + public static final int EVM_INS_SUICIDE = 255; + public static final int EVM_INS_INVALID = 512; + public static final int EVM_INS_ENDING = 513; + + // Group of EVM instructions + + public static final int EVM_GRP_INVALID = 0; + public static final int EVM_GRP_JUMP = 1; + public static final int EVM_GRP_MATH = 8; + public static final int EVM_GRP_STACK_WRITE = 9; + public static final int EVM_GRP_STACK_READ = 10; + public static final int EVM_GRP_MEM_WRITE = 11; + public static final int EVM_GRP_MEM_READ = 12; + public static final int EVM_GRP_STORE_WRITE = 13; + public static final int EVM_GRP_STORE_READ = 14; + public static final int EVM_GRP_HALT = 15; + public static final int EVM_GRP_ENDING = 16; +} \ No newline at end of file diff --git a/bindings/ocaml/evm_const.ml b/bindings/ocaml/evm_const.ml new file mode 100644 index 00000000..cbe4ee90 --- /dev/null +++ b/bindings/ocaml/evm_const.ml @@ -0,0 +1,155 @@ +(* For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [evm_const.ml] *) + +(* EVM instruction *) + +let _EVM_INS_STOP = 0;; +let _EVM_INS_ADD = 1;; +let _EVM_INS_MUL = 2;; +let _EVM_INS_SUB = 3;; +let _EVM_INS_DIV = 4;; +let _EVM_INS_SDIV = 5;; +let _EVM_INS_MOD = 6;; +let _EVM_INS_SMOD = 7;; +let _EVM_INS_ADDMOD = 8;; +let _EVM_INS_MULMOD = 9;; +let _EVM_INS_EXP = 10;; +let _EVM_INS_SIGNEXTEND = 11;; +let _EVM_INS_LT = 16;; +let _EVM_INS_GT = 17;; +let _EVM_INS_SLT = 18;; +let _EVM_INS_SGT = 19;; +let _EVM_INS_EQ = 20;; +let _EVM_INS_ISZERO = 21;; +let _EVM_INS_AND = 22;; +let _EVM_INS_OR = 23;; +let _EVM_INS_XOR = 24;; +let _EVM_INS_NOT = 25;; +let _EVM_INS_BYTE = 26;; +let _EVM_INS_SHA3 = 32;; +let _EVM_INS_ADDRESS = 48;; +let _EVM_INS_BALANCE = 49;; +let _EVM_INS_ORIGIN = 50;; +let _EVM_INS_CALLER = 51;; +let _EVM_INS_CALLVALUE = 52;; +let _EVM_INS_CALLDATALOAD = 53;; +let _EVM_INS_CALLDATASIZE = 54;; +let _EVM_INS_CALLDATACOPY = 55;; +let _EVM_INS_CODESIZE = 56;; +let _EVM_INS_CODECOPY = 57;; +let _EVM_INS_GASPRICE = 58;; +let _EVM_INS_EXTCODESIZE = 59;; +let _EVM_INS_EXTCODECOPY = 60;; +let _EVM_INS_RETURNDATASIZE = 61;; +let _EVM_INS_RETURNDATACOPY = 62;; +let _EVM_INS_BLOCKHASH = 64;; +let _EVM_INS_COINBASE = 65;; +let _EVM_INS_TIMESTAMP = 66;; +let _EVM_INS_NUMBER = 67;; +let _EVM_INS_DIFFICULTY = 68;; +let _EVM_INS_GASLIMIT = 69;; +let _EVM_INS_POP = 80;; +let _EVM_INS_MLOAD = 81;; +let _EVM_INS_MSTORE = 82;; +let _EVM_INS_MSTORE8 = 83;; +let _EVM_INS_SLOAD = 84;; +let _EVM_INS_SSTORE = 85;; +let _EVM_INS_JUMP = 86;; +let _EVM_INS_JUMPI = 87;; +let _EVM_INS_PC = 88;; +let _EVM_INS_MSIZE = 89;; +let _EVM_INS_GAS = 90;; +let _EVM_INS_JUMPDEST = 91;; +let _EVM_INS_PUSH1 = 96;; +let _EVM_INS_PUSH2 = 97;; +let _EVM_INS_PUSH3 = 98;; +let _EVM_INS_PUSH4 = 99;; +let _EVM_INS_PUSH5 = 100;; +let _EVM_INS_PUSH6 = 101;; +let _EVM_INS_PUSH7 = 102;; +let _EVM_INS_PUSH8 = 103;; +let _EVM_INS_PUSH9 = 104;; +let _EVM_INS_PUSH10 = 105;; +let _EVM_INS_PUSH11 = 106;; +let _EVM_INS_PUSH12 = 107;; +let _EVM_INS_PUSH13 = 108;; +let _EVM_INS_PUSH14 = 109;; +let _EVM_INS_PUSH15 = 110;; +let _EVM_INS_PUSH16 = 111;; +let _EVM_INS_PUSH17 = 112;; +let _EVM_INS_PUSH18 = 113;; +let _EVM_INS_PUSH19 = 114;; +let _EVM_INS_PUSH20 = 115;; +let _EVM_INS_PUSH21 = 116;; +let _EVM_INS_PUSH22 = 117;; +let _EVM_INS_PUSH23 = 118;; +let _EVM_INS_PUSH24 = 119;; +let _EVM_INS_PUSH25 = 120;; +let _EVM_INS_PUSH26 = 121;; +let _EVM_INS_PUSH27 = 122;; +let _EVM_INS_PUSH28 = 123;; +let _EVM_INS_PUSH29 = 124;; +let _EVM_INS_PUSH30 = 125;; +let _EVM_INS_PUSH31 = 126;; +let _EVM_INS_PUSH32 = 127;; +let _EVM_INS_DUP1 = 128;; +let _EVM_INS_DUP2 = 129;; +let _EVM_INS_DUP3 = 130;; +let _EVM_INS_DUP4 = 131;; +let _EVM_INS_DUP5 = 132;; +let _EVM_INS_DUP6 = 133;; +let _EVM_INS_DUP7 = 134;; +let _EVM_INS_DUP8 = 135;; +let _EVM_INS_DUP9 = 136;; +let _EVM_INS_DUP10 = 137;; +let _EVM_INS_DUP11 = 138;; +let _EVM_INS_DUP12 = 139;; +let _EVM_INS_DUP13 = 140;; +let _EVM_INS_DUP14 = 141;; +let _EVM_INS_DUP15 = 142;; +let _EVM_INS_DUP16 = 143;; +let _EVM_INS_SWAP1 = 144;; +let _EVM_INS_SWAP2 = 145;; +let _EVM_INS_SWAP3 = 146;; +let _EVM_INS_SWAP4 = 147;; +let _EVM_INS_SWAP5 = 148;; +let _EVM_INS_SWAP6 = 149;; +let _EVM_INS_SWAP7 = 150;; +let _EVM_INS_SWAP8 = 151;; +let _EVM_INS_SWAP9 = 152;; +let _EVM_INS_SWAP10 = 153;; +let _EVM_INS_SWAP11 = 154;; +let _EVM_INS_SWAP12 = 155;; +let _EVM_INS_SWAP13 = 156;; +let _EVM_INS_SWAP14 = 157;; +let _EVM_INS_SWAP15 = 158;; +let _EVM_INS_SWAP16 = 159;; +let _EVM_INS_LOG0 = 160;; +let _EVM_INS_LOG1 = 161;; +let _EVM_INS_LOG2 = 162;; +let _EVM_INS_LOG3 = 163;; +let _EVM_INS_LOG4 = 164;; +let _EVM_INS_CREATE = 240;; +let _EVM_INS_CALL = 241;; +let _EVM_INS_CALLCODE = 242;; +let _EVM_INS_RETURN = 243;; +let _EVM_INS_DELEGATECALL = 244;; +let _EVM_INS_CALLBLACKBOX = 245;; +let _EVM_INS_STATICCALL = 250;; +let _EVM_INS_REVERT = 253;; +let _EVM_INS_SUICIDE = 255;; +let _EVM_INS_INVALID = 512;; +let _EVM_INS_ENDING = 513;; + +(* Group of EVM instructions *) + +let _EVM_GRP_INVALID = 0;; +let _EVM_GRP_JUMP = 1;; +let _EVM_GRP_MATH = 8;; +let _EVM_GRP_STACK_WRITE = 9;; +let _EVM_GRP_STACK_READ = 10;; +let _EVM_GRP_MEM_WRITE = 11;; +let _EVM_GRP_MEM_READ = 12;; +let _EVM_GRP_STORE_WRITE = 13;; +let _EVM_GRP_STORE_READ = 14;; +let _EVM_GRP_HALT = 15;; +let _EVM_GRP_ENDING = 16;; diff --git a/bindings/python/capstone/evm.py b/bindings/python/capstone/evm.py new file mode 100644 index 00000000..5ddec6ab --- /dev/null +++ b/bindings/python/capstone/evm.py @@ -0,0 +1,17 @@ +# Capstone Python bindings, by Nguyen Anh Quynnh + +import ctypes +from . import copy_ctypes_list +from .evm_const import * + +# define the API +class CsEvm(ctypes.Structure): + _fields_ = ( + ('pop', ctypes.c_byte), + ('push', ctypes.c_byte), + ('fee', ctypes.c_uint), + ) + +def get_arch_info(a): + return (a.pop, a.push, a.fee) + diff --git a/bindings/python/capstone/evm_const.py b/bindings/python/capstone/evm_const.py new file mode 100644 index 00000000..b952a505 --- /dev/null +++ b/bindings/python/capstone/evm_const.py @@ -0,0 +1,155 @@ +# For Capstone Engine. AUTO-GENERATED FILE, DO NOT EDIT [evm_const.py] + +# EVM instruction + +EVM_INS_STOP = 0 +EVM_INS_ADD = 1 +EVM_INS_MUL = 2 +EVM_INS_SUB = 3 +EVM_INS_DIV = 4 +EVM_INS_SDIV = 5 +EVM_INS_MOD = 6 +EVM_INS_SMOD = 7 +EVM_INS_ADDMOD = 8 +EVM_INS_MULMOD = 9 +EVM_INS_EXP = 10 +EVM_INS_SIGNEXTEND = 11 +EVM_INS_LT = 16 +EVM_INS_GT = 17 +EVM_INS_SLT = 18 +EVM_INS_SGT = 19 +EVM_INS_EQ = 20 +EVM_INS_ISZERO = 21 +EVM_INS_AND = 22 +EVM_INS_OR = 23 +EVM_INS_XOR = 24 +EVM_INS_NOT = 25 +EVM_INS_BYTE = 26 +EVM_INS_SHA3 = 32 +EVM_INS_ADDRESS = 48 +EVM_INS_BALANCE = 49 +EVM_INS_ORIGIN = 50 +EVM_INS_CALLER = 51 +EVM_INS_CALLVALUE = 52 +EVM_INS_CALLDATALOAD = 53 +EVM_INS_CALLDATASIZE = 54 +EVM_INS_CALLDATACOPY = 55 +EVM_INS_CODESIZE = 56 +EVM_INS_CODECOPY = 57 +EVM_INS_GASPRICE = 58 +EVM_INS_EXTCODESIZE = 59 +EVM_INS_EXTCODECOPY = 60 +EVM_INS_RETURNDATASIZE = 61 +EVM_INS_RETURNDATACOPY = 62 +EVM_INS_BLOCKHASH = 64 +EVM_INS_COINBASE = 65 +EVM_INS_TIMESTAMP = 66 +EVM_INS_NUMBER = 67 +EVM_INS_DIFFICULTY = 68 +EVM_INS_GASLIMIT = 69 +EVM_INS_POP = 80 +EVM_INS_MLOAD = 81 +EVM_INS_MSTORE = 82 +EVM_INS_MSTORE8 = 83 +EVM_INS_SLOAD = 84 +EVM_INS_SSTORE = 85 +EVM_INS_JUMP = 86 +EVM_INS_JUMPI = 87 +EVM_INS_PC = 88 +EVM_INS_MSIZE = 89 +EVM_INS_GAS = 90 +EVM_INS_JUMPDEST = 91 +EVM_INS_PUSH1 = 96 +EVM_INS_PUSH2 = 97 +EVM_INS_PUSH3 = 98 +EVM_INS_PUSH4 = 99 +EVM_INS_PUSH5 = 100 +EVM_INS_PUSH6 = 101 +EVM_INS_PUSH7 = 102 +EVM_INS_PUSH8 = 103 +EVM_INS_PUSH9 = 104 +EVM_INS_PUSH10 = 105 +EVM_INS_PUSH11 = 106 +EVM_INS_PUSH12 = 107 +EVM_INS_PUSH13 = 108 +EVM_INS_PUSH14 = 109 +EVM_INS_PUSH15 = 110 +EVM_INS_PUSH16 = 111 +EVM_INS_PUSH17 = 112 +EVM_INS_PUSH18 = 113 +EVM_INS_PUSH19 = 114 +EVM_INS_PUSH20 = 115 +EVM_INS_PUSH21 = 116 +EVM_INS_PUSH22 = 117 +EVM_INS_PUSH23 = 118 +EVM_INS_PUSH24 = 119 +EVM_INS_PUSH25 = 120 +EVM_INS_PUSH26 = 121 +EVM_INS_PUSH27 = 122 +EVM_INS_PUSH28 = 123 +EVM_INS_PUSH29 = 124 +EVM_INS_PUSH30 = 125 +EVM_INS_PUSH31 = 126 +EVM_INS_PUSH32 = 127 +EVM_INS_DUP1 = 128 +EVM_INS_DUP2 = 129 +EVM_INS_DUP3 = 130 +EVM_INS_DUP4 = 131 +EVM_INS_DUP5 = 132 +EVM_INS_DUP6 = 133 +EVM_INS_DUP7 = 134 +EVM_INS_DUP8 = 135 +EVM_INS_DUP9 = 136 +EVM_INS_DUP10 = 137 +EVM_INS_DUP11 = 138 +EVM_INS_DUP12 = 139 +EVM_INS_DUP13 = 140 +EVM_INS_DUP14 = 141 +EVM_INS_DUP15 = 142 +EVM_INS_DUP16 = 143 +EVM_INS_SWAP1 = 144 +EVM_INS_SWAP2 = 145 +EVM_INS_SWAP3 = 146 +EVM_INS_SWAP4 = 147 +EVM_INS_SWAP5 = 148 +EVM_INS_SWAP6 = 149 +EVM_INS_SWAP7 = 150 +EVM_INS_SWAP8 = 151 +EVM_INS_SWAP9 = 152 +EVM_INS_SWAP10 = 153 +EVM_INS_SWAP11 = 154 +EVM_INS_SWAP12 = 155 +EVM_INS_SWAP13 = 156 +EVM_INS_SWAP14 = 157 +EVM_INS_SWAP15 = 158 +EVM_INS_SWAP16 = 159 +EVM_INS_LOG0 = 160 +EVM_INS_LOG1 = 161 +EVM_INS_LOG2 = 162 +EVM_INS_LOG3 = 163 +EVM_INS_LOG4 = 164 +EVM_INS_CREATE = 240 +EVM_INS_CALL = 241 +EVM_INS_CALLCODE = 242 +EVM_INS_RETURN = 243 +EVM_INS_DELEGATECALL = 244 +EVM_INS_CALLBLACKBOX = 245 +EVM_INS_STATICCALL = 250 +EVM_INS_REVERT = 253 +EVM_INS_SUICIDE = 255 +EVM_INS_INVALID = 512 +EVM_INS_ENDING = 513 + +# Group of EVM instructions + +EVM_GRP_INVALID = 0 +EVM_GRP_JUMP = 1 +EVM_GRP_MATH = 8 +EVM_GRP_STACK_WRITE = 9 +EVM_GRP_STACK_READ = 10 +EVM_GRP_MEM_WRITE = 11 +EVM_GRP_MEM_READ = 12 +EVM_GRP_STORE_WRITE = 13 +EVM_GRP_STORE_READ = 14 +EVM_GRP_HALT = 15 +EVM_GRP_ENDING = 16 diff --git a/bindings/python/test_evm.py b/bindings/python/test_evm.py new file mode 100755 index 00000000..345424f5 --- /dev/null +++ b/bindings/python/test_evm.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +# Capstone Python bindings, by Nguyen Anh Quynnh + +from __future__ import print_function +from capstone import * + +cs = Cs(CS_ARCH_EVM, 0) +cs.detail = True + +for i in cs.disasm("\x60\x61\x55", 0x100): + print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str)) + if i.pop > 0: + print("\tPop: %u" %i.pop) + if i.push > 0: + print("\tPush: %u" %i.push) + if i.fee > 0: + print("\tGas fee: %u" %i.fee) + if len(i.groups) > 0: + print("\tThis instruction belongs to groups: ", end=''), + for m in i.groups: + print("%s " % i.group_name(m), end=''), + print() diff --git a/cstool/cstool_evm.c b/cstool/cstool_evm.c new file mode 100644 index 00000000..18b31920 --- /dev/null +++ b/cstool/cstool_evm.c @@ -0,0 +1,27 @@ +#include +#include + +#include + +void print_string_hex(char *comment, unsigned char *str, size_t len); + +void print_insn_detail_evm(csh handle, cs_insn *ins) +{ + cs_evm *evm; + int i; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + evm = &(ins->detail->evm); + + if (evm->pop) + printf("\tPop: %u\n", evm->pop); + + if (evm->push) + printf("\tPush: %u\n", evm->push); + + if (evm->fee) + printf("\tGas fee: %u\n", evm->fee); +} diff --git a/include/capstone/evm.h b/include/capstone/evm.h new file mode 100644 index 00000000..94f25b03 --- /dev/null +++ b/include/capstone/evm.h @@ -0,0 +1,188 @@ +#ifndef CAPSTONE_EVM_H +#define CAPSTONE_EVM_H + +/* Capstone Disassembly Engine */ +/* By Nguyen Anh Quynh , 2013-2018 */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "platform.h" + +#ifdef _MSC_VER +#pragma warning(disable:4201) +#endif + +// Instruction structure +typedef struct cs_evm { + unsigned char pop; // number of items popped from the stack + unsigned char push; // number of items pushed into the stack + unsigned int fee; // gas fee for the instruction +} cs_evm; + +//> EVM instruction +typedef enum evm_insn { + EVM_INS_STOP = 0, + EVM_INS_ADD = 1, + EVM_INS_MUL = 2, + EVM_INS_SUB = 3, + EVM_INS_DIV = 4, + EVM_INS_SDIV = 5, + EVM_INS_MOD = 6, + EVM_INS_SMOD = 7, + EVM_INS_ADDMOD = 8, + EVM_INS_MULMOD = 9, + EVM_INS_EXP = 10, + EVM_INS_SIGNEXTEND = 11, + EVM_INS_LT = 16, + EVM_INS_GT = 17, + EVM_INS_SLT = 18, + EVM_INS_SGT = 19, + EVM_INS_EQ = 20, + EVM_INS_ISZERO = 21, + EVM_INS_AND = 22, + EVM_INS_OR = 23, + EVM_INS_XOR = 24, + EVM_INS_NOT = 25, + EVM_INS_BYTE = 26, + EVM_INS_SHA3 = 32, + EVM_INS_ADDRESS = 48, + EVM_INS_BALANCE = 49, + EVM_INS_ORIGIN = 50, + EVM_INS_CALLER = 51, + EVM_INS_CALLVALUE = 52, + EVM_INS_CALLDATALOAD = 53, + EVM_INS_CALLDATASIZE = 54, + EVM_INS_CALLDATACOPY = 55, + EVM_INS_CODESIZE = 56, + EVM_INS_CODECOPY = 57, + EVM_INS_GASPRICE = 58, + EVM_INS_EXTCODESIZE = 59, + EVM_INS_EXTCODECOPY = 60, + EVM_INS_RETURNDATASIZE = 61, + EVM_INS_RETURNDATACOPY = 62, + EVM_INS_BLOCKHASH = 64, + EVM_INS_COINBASE = 65, + EVM_INS_TIMESTAMP = 66, + EVM_INS_NUMBER = 67, + EVM_INS_DIFFICULTY = 68, + EVM_INS_GASLIMIT = 69, + EVM_INS_POP = 80, + EVM_INS_MLOAD = 81, + EVM_INS_MSTORE = 82, + EVM_INS_MSTORE8 = 83, + EVM_INS_SLOAD = 84, + EVM_INS_SSTORE = 85, + EVM_INS_JUMP = 86, + EVM_INS_JUMPI = 87, + EVM_INS_PC = 88, + EVM_INS_MSIZE = 89, + EVM_INS_GAS = 90, + EVM_INS_JUMPDEST = 91, + EVM_INS_PUSH1 = 96, + EVM_INS_PUSH2 = 97, + EVM_INS_PUSH3 = 98, + EVM_INS_PUSH4 = 99, + EVM_INS_PUSH5 = 100, + EVM_INS_PUSH6 = 101, + EVM_INS_PUSH7 = 102, + EVM_INS_PUSH8 = 103, + EVM_INS_PUSH9 = 104, + EVM_INS_PUSH10 = 105, + EVM_INS_PUSH11 = 106, + EVM_INS_PUSH12 = 107, + EVM_INS_PUSH13 = 108, + EVM_INS_PUSH14 = 109, + EVM_INS_PUSH15 = 110, + EVM_INS_PUSH16 = 111, + EVM_INS_PUSH17 = 112, + EVM_INS_PUSH18 = 113, + EVM_INS_PUSH19 = 114, + EVM_INS_PUSH20 = 115, + EVM_INS_PUSH21 = 116, + EVM_INS_PUSH22 = 117, + EVM_INS_PUSH23 = 118, + EVM_INS_PUSH24 = 119, + EVM_INS_PUSH25 = 120, + EVM_INS_PUSH26 = 121, + EVM_INS_PUSH27 = 122, + EVM_INS_PUSH28 = 123, + EVM_INS_PUSH29 = 124, + EVM_INS_PUSH30 = 125, + EVM_INS_PUSH31 = 126, + EVM_INS_PUSH32 = 127, + EVM_INS_DUP1 = 128, + EVM_INS_DUP2 = 129, + EVM_INS_DUP3 = 130, + EVM_INS_DUP4 = 131, + EVM_INS_DUP5 = 132, + EVM_INS_DUP6 = 133, + EVM_INS_DUP7 = 134, + EVM_INS_DUP8 = 135, + EVM_INS_DUP9 = 136, + EVM_INS_DUP10 = 137, + EVM_INS_DUP11 = 138, + EVM_INS_DUP12 = 139, + EVM_INS_DUP13 = 140, + EVM_INS_DUP14 = 141, + EVM_INS_DUP15 = 142, + EVM_INS_DUP16 = 143, + EVM_INS_SWAP1 = 144, + EVM_INS_SWAP2 = 145, + EVM_INS_SWAP3 = 146, + EVM_INS_SWAP4 = 147, + EVM_INS_SWAP5 = 148, + EVM_INS_SWAP6 = 149, + EVM_INS_SWAP7 = 150, + EVM_INS_SWAP8 = 151, + EVM_INS_SWAP9 = 152, + EVM_INS_SWAP10 = 153, + EVM_INS_SWAP11 = 154, + EVM_INS_SWAP12 = 155, + EVM_INS_SWAP13 = 156, + EVM_INS_SWAP14 = 157, + EVM_INS_SWAP15 = 158, + EVM_INS_SWAP16 = 159, + EVM_INS_LOG0 = 160, + EVM_INS_LOG1 = 161, + EVM_INS_LOG2 = 162, + EVM_INS_LOG3 = 163, + EVM_INS_LOG4 = 164, + EVM_INS_CREATE = 240, + EVM_INS_CALL = 241, + EVM_INS_CALLCODE = 242, + EVM_INS_RETURN = 243, + EVM_INS_DELEGATECALL = 244, + EVM_INS_CALLBLACKBOX = 245, + EVM_INS_STATICCALL = 250, + EVM_INS_REVERT = 253, + EVM_INS_SUICIDE = 255, + + EVM_INS_INVALID = 512, + EVM_INS_ENDING, // <-- mark the end of the list of instructions +} evm_insn; + +//> Group of EVM instructions +typedef enum evm_insn_group { + EVM_GRP_INVALID = 0, // = CS_GRP_INVALID + + EVM_GRP_JUMP, // all jump instructions + + EVM_GRP_MATH = 8, // math instructions + EVM_GRP_STACK_WRITE, // instructions write to stack + EVM_GRP_STACK_READ, // instructions read from stack + EVM_GRP_MEM_WRITE, // instructions write to memory + EVM_GRP_MEM_READ, // instructions read from memory + EVM_GRP_STORE_WRITE, // instructions write to storage + EVM_GRP_STORE_READ, // instructions read from storage + EVM_GRP_HALT, // instructions halt execution + + EVM_GRP_ENDING, // <-- mark the end of the list of groups +} evm_insn_group; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/test_evm.c b/tests/test_evm.c new file mode 100644 index 00000000..1d1d88a8 --- /dev/null +++ b/tests/test_evm.c @@ -0,0 +1,126 @@ +/* Capstone Disassembler Engine */ +/* By Nguyen Anh Quynh , 2018 */ + +#include +#include + +#include +#include + +static csh handle; + +struct platform { + cs_arch arch; + cs_mode mode; + unsigned char *code; + size_t size; + char *comment; +}; + +static void print_string_hex(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"); +} + +static void print_insn_detail(csh cs_handle, cs_insn *ins) +{ + cs_evm *evm; + + // detail can be NULL on "data" instruction if SKIPDATA option is turned ON + if (ins->detail == NULL) + return; + + evm = &(ins->detail->evm); + + if (evm->pop) + printf("\tPop: %u\n", evm->pop); + + if (evm->push) + printf("\tPush: %u\n", evm->push); + + if (evm->fee) + printf("\tGas fee: %u\n", evm->fee); + + if (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"); + } +} + +static void test() +{ +#define EVM_CODE "\x60\x61\x50" + + struct platform platforms[] = { + { + CS_ARCH_EVM, + 0, + (unsigned char *)EVM_CODE, + sizeof(EVM_CODE) - 1, + "EVM" + }, + }; + + uint64_t address = 0x80001000; + cs_insn *insn; + int i; + size_t count; + + for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { + cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle); + if (err) { + printf("Failed on cs_open() with error returned: %u\n", err); + abort(); + } + + cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); + + count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); + if (count) { + size_t j; + printf("****************\n"); + printf("Platform: %s\n", platforms[i].comment); + print_string_hex("Code:", platforms[i].code, platforms[i].size); + printf("Disasm:\n"); + + for (j = 0; j < count; j++) { + printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); + print_insn_detail(handle, &insn[j]); + } + printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size); + + // free memory allocated by cs_disasm() + cs_free(insn, count); + } else { + printf("****************\n"); + printf("Platform: %s\n", platforms[i].comment); + print_string_hex("Code:", platforms[i].code, platforms[i].size); + printf("ERROR: Failed to disasm given code!\n"); + abort(); + } + + printf("\n"); + + cs_close(&handle); + } +} + +int main() +{ + test(); + + return 0; +} +