static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = 0; int n, ret; ut64 off = a->pc; cs_insn* insn; int mode = (a->big_endian)? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (handle && mode != omode) { cs_close (&handle); handle = 0; } op->size = 0; omode = mode; op->buf_asm[0] = 0; if (handle == 0) { ret = cs_open (CS_ARCH_PPC, mode, &handle); if (ret) return 0; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (handle, (const ut8*)buf, len, off, 1, &insn); op->size = 4; if (n > 0 && insn->size > 0) { snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); cs_free (insn, n); return op->size; } //op->size = -1; cs_free (insn, n); return 4; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = 0; int mode, n, ret; ut64 off = a->pc; cs_insn* insn = NULL; mode = CS_MODE_BIG_ENDIAN; if (cd && mode != omode) { cs_close (&cd); cd = 0; } op->size = 0; omode = mode; if (cd == 0) { ret = cs_open (CS_ARCH_SYSZ, mode, &cd); if (ret) return 0; cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } n = cs_disasm (cd, (const ut8*)buf, len, off, 1, &insn); if (n>0) { if (insn->size>0) { op->size = insn->size; char *ptrstr; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); ptrstr = strstr (op->buf_asm, "ptr "); if (ptrstr) { memmove (ptrstr, ptrstr+4, strlen (ptrstr+4)+1); } } cs_free (insn, n); } return op->size; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { csh handle; cs_insn* insn; int mode, n, ret = -1; mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (a->cpu && *a->cpu) { if (!strcmp (a->cpu, "v9")) { mode |= CS_MODE_V9; } } memset (op, 0, sizeof (RAsmOp)); op->size = 4; ret = cs_open (CS_ARCH_SPARC, mode, &handle); if (ret) goto fin; cs_option (handle, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (handle, (ut8*)buf, len, a->pc, 1, &insn); if (n<1) { strcpy (op->buf_asm, "invalid"); op->size = 4; ret = -1; goto beach; } else ret = 4; if (insn->size<1) goto beach; op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); // TODO: remove the '$'<registername> in the string cs_free (insn, n); beach: cs_close (&handle); fin: return ret; }
//Function parsing needs all of the instructions, and translating into C needs all of the instructions, but storing all of the instructions between those two points in time //takes up an enourmous amount of memory. So we need a seperate function from the init function to disassemble all of the instructions in a jump block a second time. void parse_instructions (jump_block* to_parse) { uint8_t* current = file_buf + addr_to_index (to_parse->start); size_t size = to_parse->end - to_parse->start; cs_disasm (handle, current, size, 0x0000, 0, &(to_parse->instructions)); }
size_t eat_instructions(void *func, size_t target) { csh handle; cs_insn *insn; size_t cnt; size_t len_cnt = 0; #ifdef __x86_64__ if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle) != CS_ERR_OK) return 0; #elif __i386__ if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) return 0; #endif cnt = cs_disasm(handle, func, 0xF, 0x0, 0, &insn); for (int k = 0; k < 0xF || !(len_cnt >= target); k++) { if (len_cnt < target) { len_cnt+=insn[k].size; } } if (len_cnt < target) { return 0; } return len_cnt; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; if (!strcmp (a->cpu, "v9")) mode |= CS_MODE_V9; ret = cs_open (CS_ARCH_XCORE, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; switch (insn->id) { case XCORE_INS_DRET: case XCORE_INS_KRET: case XCORE_INS_RETSP: op->type = R_ANAL_OP_TYPE_RET; break; case XCORE_INS_DCALL: case XCORE_INS_KCALL: case XCORE_INS_ECALLF: case XCORE_INS_ECALLT: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; /* ??? */ case XCORE_INS_BL: case XCORE_INS_BLA: case XCORE_INS_BLAT: case XCORE_INS_BT: case XCORE_INS_BF: case XCORE_INS_BU: case XCORE_INS_BRU: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; case XCORE_INS_SUB: case XCORE_INS_LSUB: op->type = R_ANAL_OP_TYPE_SUB; break; case XCORE_INS_ADD: case XCORE_INS_LADD: op->type = R_ANAL_OP_TYPE_ADD; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
unsigned int HookFw::GetAlignedOpcodeForHook() { csh cshHandle; cs_insn *pInsn; unsigned int uiIndex; unsigned int uiCount; unsigned int uiSizeOfStolenOpcode; uiSizeOfStolenOpcode = 0; if (cs_open(CS_ARCH_X86, ARCH_MODE, &cshHandle) != CS_ERR_OK) { return ERR_CANNOT_RESOLVE_ASM; } uiCount = (unsigned int)cs_disasm(cshHandle, (unsigned char *)this->pvSrc, 0x50, 0x100, 0, &pInsn); if (uiCount > 0) { uiIndex = 0; while ((this->nHookLen > uiSizeOfStolenOpcode) && (uiCount >= uiIndex)) { uiSizeOfStolenOpcode += pInsn[uiIndex++].size; } } else return ERR_CANNOT_RESOLVE_ASM; return uiSizeOfStolenOpcode; }
DWORD PLH::AbstractDetour::CalculateLength(BYTE* Src, DWORD NeededLength) { //Grab First 100 bytes of function, disasm until invalid instruction cs_insn* InstructionInfo; size_t InstructionCount = cs_disasm(m_CapstoneHandle, Src, 0x100, (uint64_t)Src, 0, &InstructionInfo); //Loop over instructions until we have at least NeededLength's Size XTrace("\nORIGINAL:\n"); DWORD InstructionSize = 0; bool BigEnough = false; for (int i = 0; i < InstructionCount && !BigEnough; i++) { cs_insn* CurIns = (cs_insn*)&InstructionInfo[i]; InstructionSize += CurIns->size; if (InstructionSize >= NeededLength) BigEnough = true; XTrace("%I64X [%d]: ", CurIns->address, CurIns->size); for (int j = 0; j < CurIns->size; j++) XTrace("%02X ", CurIns->bytes[j]); XTrace("%s %s\n", CurIns->mnemonic, CurIns->op_str); } if (!BigEnough) InstructionSize = 0; cs_free(InstructionInfo, InstructionCount); return InstructionSize; }
static void test() { #define M68K_CODE "\xf0\x10\xf0\x00\x48\xaf\xff\xff\x7f\xff\x11\xb0\x01\x37\x7f\xff\xff\xff\x12\x34\x56\x78\x01\x33\x10\x10\x10\x10\x32\x32\x32\x32\x4C\x00\x54\x04\x48\xe7\xe0\x30\x4C\xDF\x0C\x07\xd4\x40\x87\x5a\x4e\x71\x02\xb4\xc0\xde\xc0\xde\x5c\x00\x1d\x80\x71\x12\x01\x23\xf2\x3c\x44\x22\x40\x49\x0e\x56\x54\xc5\xf2\x3c\x44\x00\x44\x7a\x00\x00\xf2\x00\x0a\x28\x4E\xB9\x00\x00\x00\x12\x4E\x75" struct platform platforms[] = { { CS_ARCH_M68K, (cs_mode)(CS_MODE_BIG_ENDIAN | CS_MODE_M68K_040), (unsigned char*)M68K_CODE, sizeof(M68K_CODE) - 1, "M68K", }, }; uint64_t address = 0x01000; 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++) { assert(address == insn[j].address && "this means the size of the previous instruction was incorrect"); address += insn[j].size; printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); print_insn_detail(&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); } }
cs_insn *get_insn(void *addr) { cs_insn *insn; size_t ret = cs_disasm(capstone, addr, 16, (uintptr_t)addr, 1, &insn); if (ret == 0) return NULL; return insn; }
static void test() { #define SYSZ_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78\xec\x18\x00\x00\xc1\x7f" struct platform platforms[] = { { CS_ARCH_SYSZ, CS_MODE_BIG_ENDIAN, (unsigned char*)SYSZ_CODE, sizeof(SYSZ_CODE) - 1, "SystemZ", }, }; uint64_t address = 0x1000; 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); continue; } 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(&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"); } printf("\n"); cs_close(&handle); } }
int main(int argc, char **argv, char **envp) { csh handle; if (cs_open(CS_ARCH_X86, CS_MODE_64, &handle)) { printf("cs_open(…) failed\n"); return 1; } cs_insn *insn; cs_disasm(handle, (uint8_t *)BINARY, sizeof(BINARY) - 1, 0x1000, 0, &insn); return 0; }
/* Disassemble code */ size_t r_disa_code(r_disa_s *dis, byte_t *code, len_t len, addr_t addr, size_t count) { assert(dis != NULL); assert(code != NULL); r_disa_free_instr_lst(dis); dis->instr_lst.count = cs_disasm(dis->handle, code, len, addr, count, &dis->instr_lst.head); return dis->instr_lst.count; }
bool Capstone::Disassemble(uint addr, const unsigned char* data, int size) { if(!data) return false; if(mInstr) //free last disassembled instruction { cs_free(mInstr, 1); mInstr = nullptr; } return !!cs_disasm(mHandle, data, size, addr, 1, &mInstr); }
int lde(void *addr) { cs_insn *insn; size_t ret = cs_disasm(capstone, addr, 16, (uintptr_t)addr, 1, &insn); if (ret == 0) return 0; ret = insn->size; cs_free(insn, 1); return (int)ret; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { cs_insn* insn = NULL; cs_mode mode = 0; int ret, n = 0; csh cd; mode = (a->bits==16)? CS_MODE_THUMB: CS_MODE_ARM; if (a->big_endian) mode |= CS_MODE_BIG_ENDIAN; else mode |= CS_MODE_LITTLE_ENDIAN; if (a->cpu && strstr (a->cpu, "m")) mode |= CS_MODE_MCLASS; if (a->cpu && strstr (a->cpu, "v8")) mode |= CS_MODE_V8; op->size = 4; op->buf_asm[0] = 0; ret = (a->bits==64)? cs_open (CS_ARCH_ARM64, mode, &cd): cs_open (CS_ARCH_ARM, mode, &cd); if (ret) { ret = -1; goto beach; } if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (cd, buf, R_MIN (4, len), a->pc, 1, &insn); if (n<1) { ret = -1; goto beach; } if (insn->size<1) { ret = -1; goto beach; } op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); r_str_rmch (op->buf_asm, '#'); cs_free (insn, n); beach: cs_close (&cd); if (!op->buf_asm[0]) strcpy (op->buf_asm, "invalid"); return op->size; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { cs_insn* insn; int mode, n, ret = -1; mode = CS_MODE_BIG_ENDIAN; if (!op) { return 0; } // mode |= (a->bits == 64)? CS_MODE_64: CS_MODE_32; memset (op, 0, sizeof (RAsmOp)); op->size = 4; if (cd != 0) { cs_close (&cd); } ret = cs_open (CS_ARCH_TMS320C64X, mode, &cd); if (ret) { goto fin; } if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); } cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (cd, (ut8*)buf, len, a->pc, 1, &insn); if (n < 1) { strcpy (op->buf_asm, "invalid"); op->size = 4; goto beach; } else { ret = 4; } if (insn->size < 1) { goto beach; } op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); // r_str_replace_in (op->buf_asm, sizeof (op->buf_asm), "*+", "", 1); // nasty, the disasm output comes with tabs and uppercase :( r_str_replace_char (op->buf_asm, '\t', 0); // r_str_replace_in (op->buf_asm, sizeof (op->buf_asm), "\t", "", 1); r_str_case (op->buf_asm, false); cs_free (insn, n); beach: // cs_close (&cd); fin: return op->size; }
static cs_insn * disassemble_instruction_at (gconstpointer address) { csh capstone; cs_insn * insn = NULL; cs_open (CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &capstone); cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON); cs_disasm (capstone, address, 16, GPOINTER_TO_SIZE (address), 1, &insn); cs_close (&capstone); return insn; }
void check_disassembly (const unsigned char * buf, size_t size) { unsigned int i; struct _wtfile_writer * ww = wtfile_writer_open("disassembly.txt"); if (size < DISASM_SIZE) return; for (i = 0; capstone_ops[i].description != NULL; i++) { struct _capstone_op * cop = &capstone_ops[i]; csh handle; cs_insn * insn; size_t count; if (cs_open(cop->arch, cop->mode, &handle) != CS_ERR_OK) { fprintf(stderr, "error opening %s in capstone, results may be incomplete\n", cop->description); continue; } size_t offset = 0; for (offset = 0; offset < size - DISASM_SIZE; offset++) { if (offset > DISASM_LIMIT) break; count = cs_disasm(handle, &(buf[offset]), DISASM_SIZE, 0, 0, &insn); if (count > (DISASM_SIZE / 8)) { char tmp[4096]; /*************************** RESET INDENT *******************************/ uint32_t t; t = snprintf(tmp, 4096, "--------------------------------------\n"); t += snprintf(&(tmp[t]), 4096 - t, "Possible disassembly for %s starting at 0x%x\n", cop->description, offset); unsigned int j; for (j = 0; j < 4; j++) { t += snprintf(&(tmp[t]), 4096 - t, "%s\t%s\n", insn[j].mnemonic, insn[j].op_str); } t += snprintf(&(tmp[t]), 4096 - t, "\n"); wtfile_writer_write(ww, tmp, strlen(tmp)); } if (count > 0) cs_free(insn, count); } cs_close(&handle); } }
int DisassembleCapOffset(unsigned char *buffer, char opt, unsigned char *second_option, int file_len, unsigned char *third_option) { // this option (third option) is responsible for disassemble where it find what and stop unsigned char *length = third_option; int offset = 0; int offset_file = 0; int buf_len=0; int offset_address = 0; // some unit testing ;) int offsets = strtoul(second_option, NULL, 16); offset = RealFileOffset(buffer, offsets); offset_address = offset; //printf("the real offset is %x\n", offset); printf("file len is %d\n", file_len); unsigned char *buf = (unsigned char *)malloc(file_len-offset); for(offset_file=0 ; offset_file+offset != file_len ; offset_file++) { buf[offset_file] = buffer[offset+offset_file]; buf_len++; } csh handle; cs_insn *insn; size_t count; if(cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) return -1; cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); count = cs_disasm(handle, buf, buf_len, offset, 0, &insn); if(count > 0) { size_t j; for(j=0; j<count; j++) { if (strcmp(length, insn[j].mnemonic)==0 || strcmp("retf", insn[j].mnemonic) == 0) { printf("\x1B[35m\t[ 0x%08x ] : \t\x1B[32m%s\t%s\n", offset_address, insn[j].mnemonic, insn[j].op_str); break; } printf("\x1B[35m\t[ 0x%08x ] : \t\x1B[32m%s\t%s\n", offset_address, insn[j].mnemonic, insn[j].op_str); offset_address += insn[j].size; } cs_free(insn, count); } else { printf("failed disassemble\n"); } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = -1, obits = -1; int n, ret; ut64 off = a->pc; cs_insn* insn; int mode = (a->bits == 64) ? CS_MODE_64 : (a->bits == 32) ? CS_MODE_32 : 0; mode |= a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; if (a->cpu && strncmp (a->cpu, "vle", 3) == 0) { // vle is big-endian only if (!a->big_endian) { return -1; } ret = decompile_vle (a, op, buf, len); if (ret >= 0) { return op->size; } } if (mode != omode || a->bits != obits) { cs_close (&handle); handle = 0; omode = mode; obits = a->bits; } if (handle == 0) { ret = cs_open (CS_ARCH_PPC, mode, &handle); if (ret != CS_ERR_OK) { return -1; } } op->size = 4; op->buf_asm[0] = 0; cs_option (handle, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (handle, (const ut8*) buf, len, off, 1, &insn); op->size = 4; if (n > 0 && insn->size > 0) { snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0] ? " " : "", insn->op_str); cs_free (insn, n); return op->size; } //op->size = -1; cs_free (insn, n); return 4; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { csh handle; cs_insn* insn; int mode, n, ret = -1; mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (a->cpu && *a->cpu) { if (!strcmp (a->cpu, "gp64")) { mode |= CS_MODE_MIPSGP64; } else if (!strcmp (a->cpu, "micro")) { mode |= CS_MODE_MICRO; } else if (!strcmp (a->cpu, "r6")) { mode |= CS_MODE_MIPS32R6; } else if (!strcmp (a->cpu, "v3")) { mode |= CS_MODE_MIPS3; } } mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; memset (op, 0, sizeof (RAsmOp)); op->size = 4; ret = cs_open (CS_ARCH_MIPS, mode, &handle); if (ret) goto fin; if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else cs_option (handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); cs_option (handle, CS_OPT_DETAIL, CS_OPT_OFF); n = cs_disasm (handle, (ut8*)buf, len, a->pc, 1, &insn); if (n<1) { strcpy (op->buf_asm, "invalid"); op->size = 4; ret = -1; goto beach; } else ret = 4; if (insn->size<1) goto beach; op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); // remove the '$'<registername> in the string r_str_replace_char (op->buf_asm, '$', 0); cs_free (insn, n); beach: cs_close (&handle); fin: return op->size; }
signed int HookFw::GetAddressForSafeHook() { /* * this routine analyze the code flow and detect redirect to another function * this code work with AnalyzeStartOfCodeForSafePatch */ csh cshHandle; cs_insn *pInsn; unsigned int uiCount; unsigned int uiByteCounter; unsigned int uiRemoteAddress; if (cs_open(CS_ARCH_X86, ARCH_MODE, &cshHandle) != CS_ERR_OK) { return ERR_CANNOT_RESOLVE_ASM; } for (unsigned int uiLoop = 0; uiLoop < 3; uiLoop++) { uiCount = (unsigned int)cs_disasm(cshHandle, (unsigned char *)this->pvSrc, 0x50, (addr)this->pvSrc, 0, &pInsn); if (uiCount >= this->nHookLen) { for (unsigned int uiIndex = 0; uiIndex < uiCount; uiIndex++) { if (strncmp(pInsn[uiIndex].mnemonic, "jmp", 3) == 0) { if (pInsn[uiIndex].size == 2) { printf("sort jump : error\n"); return -1; } sscanf(pInsn[uiIndex].op_str + 2, "%p", &uiRemoteAddress); this->pvSrc = (void *)uiRemoteAddress; uiByteCounter = 0; } else { uiByteCounter += pInsn[uiIndex].size; if (uiByteCounter >= this->nHookLen) return 0; } } } } return -1; }
static cs_insn * disassemble_instruction_at (gconstpointer address) { csh capstone; cs_err err; cs_insn * insn = NULL; err = cs_open (CS_ARCH_ARM, CS_MODE_ARM, &capstone); g_assert (err == CS_ERR_OK); err = cs_option (capstone, CS_OPT_DETAIL, CS_OPT_ON); g_assert (err == CS_ERR_OK); cs_disasm (capstone, address, 4, GPOINTER_TO_SIZE (address), 1, &insn); cs_close (&capstone); return insn; }
static int tms320c64x_disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { cs_insn* insn; int n = -1, ret = -1; int mode = 0; if (op) { memset (op, 0, sizeof (RAsmOp)); op->size = 4; } if (cd != 0) { cs_close (&cd); } ret = cs_open (CS_ARCH_TMS320C64X, mode, &cd); if (ret) { goto fin; } cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); if (!op) { return 0; } n = cs_disasm (cd, buf, len, a->pc, 1, &insn); if (n < 1) { r_asm_op_set_asm (op, "invalid"); op->size = 4; ret = -1; goto beach; } else { ret = 4; } if (insn->size < 1) { goto beach; } op->size = insn->size; char *buf_asm = sdb_fmt ("%s%s%s", insn->mnemonic, insn->op_str[0]? " ": "", insn->op_str); r_str_replace_char (buf_asm, '%', 0); r_str_case (buf_asm, false); r_asm_op_set_asm (op, buf_asm); cs_free (insn, n); beach: // cs_close (&cd); fin: return ret; }
static const char * disarm64(insn_t insn, address_t pc) { cs_insn *csi; size_t count; if (!cshandle && !open_capstone()) return "<capstone open failed>"; count = cs_disasm(cshandle, (const uint8_t *) &insn, sizeof(insn), pc, 1, &csi); if (count == 1) { snprintf(disarm64_buf, DISARM64_BUFSIZE-2, "%s\t%s", csi->mnemonic, csi->op_str); cs_free(csi, 1); } else { cs_err err = cs_errno(cshandle); if (err != CS_ERR_OK) { error("Capstone disassembler failed: %s", cs_strerror(err)); return "<capstone error>"; } return "<unrecognised>"; } return disarm64_buf; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle = 0; cs_insn *insn = NULL; int mode = (a->bits==16)? CS_MODE_THUMB: CS_MODE_ARM; int n, ret; mode |= (a->big_endian)? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; ret = (a->bits==64)? cs_open (CS_ARCH_ARM64, mode, &handle): cs_open (CS_ARCH_ARM, mode, &handle); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); op->type = R_ANAL_OP_TYPE_NULL; op->size = (a->bits==16)? 2: 4; op->delay = 0; op->jump = op->fail = -1; op->addr = addr; op->ptr = op->val = -1; op->refptr = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; if (a->bits == 64) { anop64 (op, insn); } else { anop32 (op, insn); } if (a->decode) { analop_esil (a, op, addr, buf, len, &handle, insn); } cs_free (insn, n); } cs_close (&handle); } return op->size; }
instr_type disas_block(CPUArchState* env, target_ulong pc, int size) { unsigned char *buf = (unsigned char *) malloc(size); int err = panda_virtual_memory_rw(ENV_GET_CPU(env), pc, buf, size, 0); if (err == -1) printf("Couldn't read TB memory!\n"); instr_type res = INSTR_UNKNOWN; #if defined(TARGET_I386) csh handle = (env->hflags & HF_LMA_MASK) ? cs_handle_64 : cs_handle_32; #elif defined(TARGET_ARM) || defined(TARGET_PPC) csh handle = cs_handle_32; #endif cs_insn *insn; cs_insn *end; size_t count = cs_disasm(handle, buf, size, pc, 0, &insn); if (count <= 0) goto done2; for (end = insn + count - 1; end >= insn; end--) { if (!cs_insn_group(handle, end, CS_GRP_INVALID)) { break; } } if (end < insn) goto done; if (cs_insn_group(handle, end, CS_GRP_CALL)) { res = INSTR_CALL; } else if (cs_insn_group(handle, end, CS_GRP_RET)) { res = INSTR_RET; } else { res = INSTR_UNKNOWN; } done: cs_free(insn, count); done2: free(buf); return res; }
static int tms320c64x_analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static csh handle = 0; static int omode; cs_insn *insn; int mode = 0, n, ret; if (mode != omode) { cs_close (&handle); handle = 0; omode = mode; } if (handle == 0) { ret = cs_open (CS_ARCH_TMS320C64X, mode, &handle); if (ret != CS_ERR_OK) { return -1; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; op->val = UT64_MAX; op->ptr = UT64_MAX; r_strbuf_init (&op->esil); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n < 1) { op->type = R_ANAL_OP_TYPE_ILL; } else { opex (&op->opex, handle, insn); op->size = insn->size; op->id = insn->id; switch (insn->id) { case TMS320C64X_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case TMS320C64X_INS_AND: case TMS320C64X_INS_ANDN: op->type = R_ANAL_OP_TYPE_AND; break; case TMS320C64X_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case TMS320C64X_INS_NEG: op->type = R_ANAL_OP_TYPE_NOT; break; case TMS320C64X_INS_SWAP2: case TMS320C64X_INS_SWAP4: op->type = R_ANAL_OP_TYPE_MOV; op->type = R_ANAL_OP_TYPE_MOV; break; case TMS320C64X_INS_BNOP: case TMS320C64X_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case TMS320C64X_INS_CMPEQ: case TMS320C64X_INS_CMPEQ2: case TMS320C64X_INS_CMPEQ4: case TMS320C64X_INS_CMPGT: case TMS320C64X_INS_CMPGT2: case TMS320C64X_INS_CMPGTU4: case TMS320C64X_INS_CMPLT: case TMS320C64X_INS_CMPLTU: op->type = R_ANAL_OP_TYPE_CMP; break; case TMS320C64X_INS_B: op->type = R_ANAL_OP_TYPE_JMP; // higher 32bits of the 64bit address is lost, lets clone op->jump = INSOP(0).imm + (addr & 0xFFFFFFFF00000000); break; case TMS320C64X_INS_LDB: case TMS320C64X_INS_LDBU: case TMS320C64X_INS_LDDW: case TMS320C64X_INS_LDH: case TMS320C64X_INS_LDHU: case TMS320C64X_INS_LDNDW: case TMS320C64X_INS_LDNW: case TMS320C64X_INS_LDW: case TMS320C64X_INS_LMBD: op->type = R_ANAL_OP_TYPE_LOAD; break; case TMS320C64X_INS_STB: case TMS320C64X_INS_STDW: case TMS320C64X_INS_STH: case TMS320C64X_INS_STNDW: case TMS320C64X_INS_STNW: case TMS320C64X_INS_STW: op->type = R_ANAL_OP_TYPE_STORE; break; case TMS320C64X_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case TMS320C64X_INS_SSUB: case TMS320C64X_INS_SUB: case TMS320C64X_INS_SUB2: case TMS320C64X_INS_SUB4: case TMS320C64X_INS_SUBAB: case TMS320C64X_INS_SUBABS4: case TMS320C64X_INS_SUBAH: case TMS320C64X_INS_SUBAW: case TMS320C64X_INS_SUBC: case TMS320C64X_INS_SUBU: op->type = R_ANAL_OP_TYPE_SUB; break; case TMS320C64X_INS_ADD: case TMS320C64X_INS_ADD2: case TMS320C64X_INS_ADD4: case TMS320C64X_INS_ADDAB: case TMS320C64X_INS_ADDAD: case TMS320C64X_INS_ADDAH: case TMS320C64X_INS_ADDAW: case TMS320C64X_INS_ADDK: case TMS320C64X_INS_ADDKPC: case TMS320C64X_INS_ADDU: case TMS320C64X_INS_SADD: case TMS320C64X_INS_SADD2: case TMS320C64X_INS_SADDU4: case TMS320C64X_INS_SADDUS2: op->type = R_ANAL_OP_TYPE_ADD; break; } cs_free (insn, n); } return op->size; }
static void test() { //#define ARM64_CODE "\xe1\x0b\x40\xb9" // ldr w1, [sp, #0x8] //#define ARM64_CODE "\x21\x7c\x00\x53" // lsr w1, w1, #0x0 //#define ARM64_CODE "\x21\x7c\x02\x9b" //#define ARM64_CODE "\x20\x04\x81\xda" // csneg x0, x1, x1, eq | cneg x0, x1, ne //#define ARM64_CODE "\x20\x08\x02\x8b" // add x0, x1, x2, lsl #2 //#define ARM64_CODE "\x20\xcc\x20\x8b" //#define ARM64_CODE "\xe2\x8f\x40\xa9" // ldp x2, x3, [sp, #8] //#define ARM64_CODE "\x20\x40\x60\x1e" // fmov d0, d1 //#define ARM64_CODE "\x20\x7c\x7d\x93" // sbfiz x0, x1, #3, #32 //#define ARM64_CODE "\x20\x88\x43\xb3" // bfxil x0, x1, #3, #32 //#define ARM64_CODE "\x01\x71\x08\xd5" // sys #0, c7, c1, #0, x1 //#define ARM64_CODE "\x00\x71\x28\xd5" // sysl x0, #0, c7, c1, #0 //#define ARM64_CODE "\x20\xf4\x18\x9e" // fcvtzs x0, s1, #3 //#define ARM64_CODE "\x20\x74\x0b\xd5" // dc zva, x0: FIXME: handle as "sys" insn //#define ARM64_CODE "\x00\x90\x24\x1e" // fmov s0, ##10.00000000 //#define ARM64_CODE "\xe1\x0b\x40\xb9" // ldr w1, [sp, #0x8] //#define ARM64_CODE "\x20\x78\x62\xf8" // ldr x0, [x1, x2, lsl #3] //#define ARM64_CODE "\x41\x14\x44\xb3" // bfm x1, x2, #4, #5 //#define ARM64_CODE "\x80\x23\x29\xd5" // sysl x0, #1, c2, c3, #4 //#define ARM64_CODE "\x20\x00\x24\x1e" // fcvtas w0, s1 //#define ARM64_CODE "\x41\x04\x40\xd2" // eor x1, x2, #0x3 //#define ARM64_CODE "\x9f\x33\x03\xd5" // dsb osh //#define ARM64_CODE "\x41\x10\x23\x8a" // bic x1, x2, x3, lsl #4 //#define ARM64_CODE "\x16\x41\x3c\xd5" // mrs x22, sp_el1 //#define ARM64_CODE "\x41\x1c\x63\x0e" // bic v1.8b, v2.8b, v3.8b //#define ARM64_CODE "\x41\xd4\xe3\x6e" // fabd v1.2d, v2.2d, v3.2d //#define ARM64_CODE "\x20\x8c\x62\x2e" // cmeq v0.4h, v1.4h, v2.4h //#define ARM64_CODE "\x20\x98\x20\x4e" // cmeq v0.16b, v1.16b, #0 //#define ARM64_CODE "\x20\x2c\x05\x4e" // smov x0, v1.b[2] //#define ARM64_CODE "\x21\xe4\x00\x2f" // movi d1, #0xff //#define ARM64_CODE "\x60\x78\x08\xd5" // at s1e0w, x0 // FIXME: same problem with dc ZVA //#define ARM64_CODE "\x20\x00\xa0\xf2" // movk x0, #1, lsl #16 //#define ARM64_CODE "\x20\x08\x00\xb1" // adds x0, x1, #0x2 //#define ARM64_CODE "\x41\x04\x00\x0f" // movi v1.2s, #0x2 //#define ARM64_CODE "\x06\x00\x00\x14" // b 0x44 //#define ARM64_CODE "\x00\x90\x24\x1e" // fmov s0, ##10.00000000 //#define ARM64_CODE "\x5f\x3f\x03\xd5" // clrex //#define ARM64_CODE "\x5f\x3e\x03\xd5" // clrex #14 //#define ARM64_CODE "\x20\x00\x02\xab" // adds x0, x1, x2 (alias of adds x0, x1, x2, lsl #0) //#define ARM64_CODE "\x20\xf4\x18\x9e" // fcvtzs x0, s1, #3 //#define ARM64_CODE "\x20\xfc\x02\x9b" // mneg x0, x1, x2 //#define ARM64_CODE "\xd0\xb6\x1e\xd5" // msr s3_6_c11_c6_6, x16 //#define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b" //#define ARM64_CODE "\x09\x00\x38\xd5" // DBarrier //#define ARM64_CODE "\x20\xe4\x3d\x0f\xa2\x00\xae\x9e" //#define ARM64_CODE "\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5" // DBarrier //#define ARM64_CODE "\x10\x5b\xe8\x3c" //#define ARM64_CODE "\x00\x18\xa0\x5f\xa2\x00\xae\x9e" #define ARM64_CODE "\x09\x00\x38\xd5\xbf\x40\x00\xd5\x0c\x05\x13\xd5\x20\x50\x02\x0e\x20\xe4\x3d\x0f\x00\x18\xa0\x5f\xa2\x00\xae\x9e\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b\x10\x5b\xe8\x3c" struct platform platforms[] = { { CS_ARCH_ARM64, CS_MODE_ARM, (unsigned char *)ARM64_CODE, sizeof(ARM64_CODE) - 1, "ARM-64" }, }; uint64_t address = 0x2c; 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); continue; } 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(&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"); } printf("\n"); cs_close(&handle); } }