/* Capstone Disassembly Engine */ /* By Nguyen Anh Quynh, 2018 */ #include #include // offsetof macro // alternatively #include "../../utils.h" like everyone else #include "EVMDisassembler.h" #include "EVMMapping.h" static short opcodes[256] = { 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, 0, offsetof(cs_detail, evm)+sizeof(cs_evm)); EVM_get_insn_id((cs_struct *)ud, MI->flat_insn, opcode); 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) { default: break; 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; }