status_t DisassemblerX8664::GetNextInstructionInfo(InstructionInfo& _info, CpuState* state) { unsigned int size = ud_disassemble(fUdisData); if (size < 1) return B_ENTRY_NOT_FOUND; target_addr_t address = ud_insn_off(fUdisData); instruction_type type = INSTRUCTION_TYPE_OTHER; target_addr_t targetAddress = 0; ud_mnemonic_code mnemonic = ud_insn_mnemonic(fUdisData); if (mnemonic == UD_Icall) type = INSTRUCTION_TYPE_SUBROUTINE_CALL; else if (mnemonic == UD_Ijmp) type = INSTRUCTION_TYPE_JUMP; if (state != NULL) targetAddress = GetInstructionTargetAddress(state); char buffer[256]; snprintf(buffer, sizeof(buffer), "0x%016" B_PRIx64 ": %16.16s %s", address, ud_insn_hex(fUdisData), ud_insn_asm(fUdisData)); // TODO: Resolve symbols! if (!_info.SetTo(address, targetAddress, size, type, true, buffer)) return B_NO_MEMORY; return B_OK; }
void Analysis::disasm(pCodeBufferInfo pinfo,std::vector<CodePiece> & code) { ud_t ud_obj; ud_init(&ud_obj); #ifndef PROTECT_X64 ud_set_mode(&ud_obj,32); #else ud_set_mode(&ud_obj,64); #endif ud_set_pc(&ud_obj,pinfo->addr); ud_set_input_buffer(&ud_obj, (uint8_t*)pinfo->buf, pinfo->size); ud_set_syntax(&ud_obj,UD_SYN_INTEL); base = pinfo->addr; size = pinfo->size; AddressArray a_array = analysis_code_piece_address(pinfo); int point = 0; const bool begin = true; const bool end = false; bool status = end; std::map<long,int> addr_id; set_label_address(pinfo,a_array,addr_id); CodePiece *piece = NULL; while (ud_disassemble(&ud_obj) != 0) { if (ud_obj.insn_offset == a_array[point] && status == end) { piece = new CodePiece; piece->set_label(point); point++; status = begin; } if (a_array.get_size() > point) { if (ud_obj.pc == a_array[point]) { if (addr_id.find(ud_obj.pc) == addr_id.end()) //下条指令没有找到 { #ifdef DEBUG printf("没有查找到数据,地址%08x\n",ud_obj.pc) ; #endif //piece->set_jmplabel(PC_NONE); if (ud_obj.mnemonic == UD_Iret) { //piece->set_jmplabel(PC_NONE); piece->set_opcode_attribute(OPCODE_ATTRIBUTE_RET); } else if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp) { long addr = ud_obj.operand[0].size == 8 ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) : (ud_obj.operand[0].lval.sdword + ud_obj.pc); if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size && ud_obj.operand[0].type == UD_OP_JIMM) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JMP); piece->set_jmplabel(addr_id[addr]); } else { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP); if (ud_obj.operand[0].type == UD_OP_JIMM) piece->set_jmplabel(addr); else piece->set_jmplabel(PC_NONE); } } else if (ud_insn_mnemonic(&ud_obj) == UD_Icall) { long addr = ud_obj.operand[0].size == 8 ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) : (ud_obj.operand[0].lval.sdword + ud_obj.pc); //if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size && if (addr >= pinfo->addr && addr < pinfo->addr + pinfo->size && ud_obj.operand[0].type == UD_OP_JIMM) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_CALL); piece->set_jmplabel(addr_id[addr]); } else { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL); if (ud_obj.operand[0].type == UD_OP_JIMM) piece->set_jmplabel(addr); else piece->set_jmplabel(PC_NONE); } } else { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXIT); piece->set_jmplabel(ud_obj.pc); } } else { if (ud_obj.operand[0].type == UD_OP_JIMM || ud_obj.mnemonic == UD_Icall || ud_obj.mnemonic == UD_Ijmp)//&& ud_obj.mnemonic != UD_Icall) { piece->set_is_jcc(ud_obj.mnemonic != UD_Icall && ud_obj.mnemonic != UD_Iret && ud_obj.mnemonic != UD_Ijmp); if (ud_obj.operand[0].type == UD_OP_MEM || ud_obj.operand[0].type == UD_OP_REG) { if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP); } else if (ud_insn_mnemonic(&ud_obj) == UD_Icall) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL); } else { //piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC); } piece->set_jmplabel(PC_NONE); } else { long addr = ud_obj.operand[0].size == 8 ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) : (ud_obj.operand[0].lval.sdword + ud_obj.pc); if (addr >= pinfo->addr && addr < pinfo->addr + pinfo->size) //<=pinfo->addr + pinfo->size将导致跳转到最后一条指令的下一条还是在范围之内 { if (addr_id.find(addr) == addr_id.end()) { printf("没有找到跳转地址:%08x\n",addr ); } if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JMP); piece->set_jmplabel(addr_id[addr]); } else if (ud_insn_mnemonic(&ud_obj) == UD_Icall) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_CALL); piece->set_jmplabel(addr); } else { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC); piece->set_jmplabel( addr_id[addr] ); } } else { if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP); //piece->set_jmplabel(addr_id[addr]); } else if (ud_insn_mnemonic(&ud_obj) == UD_Icall) { piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL); //piece->set_jmplabel(addr); } else { //piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC); printf("jcc不能跳转到虚拟机外部\n"); //piece->set_jmplabel( addr_id[addr] ); } piece->set_jmplabel(addr); } } } else { piece->set_jmplabel( addr_id[ud_obj.pc] ); piece->set_opcode_attribute(OPCODE_ATTRIBUTE_NORMAL); } } if (ud_obj.mnemonic == UD_Iret) { piece->set_jmplabel(PC_NONE); piece->set_opcode_attribute(OPCODE_ATTRIBUTE_RET); //piece->set_jmplabel(PC_RET); } piece->add_assemble(ud_obj); code.push_back(*piece); delete piece; piece = NULL; status = end; } } if (status == begin) { if (piece == NULL) { printf("没有为piece分配空间"); } piece->add_assemble(ud_obj); } } }
target_addr_t DisassemblerX8664::GetInstructionTargetAddress(CpuState* state) const { ud_mnemonic_code mnemonic = ud_insn_mnemonic(fUdisData); if (mnemonic != UD_Icall && mnemonic != UD_Ijmp) return 0; CpuStateX8664* x64State = dynamic_cast<CpuStateX8664*>(state); if (x64State == NULL) return 0; target_addr_t targetAddress = 0; const struct ud_operand* op = ud_insn_opr(fUdisData, 0); switch (op->type) { case UD_OP_REG: { targetAddress = x64State->IntRegisterValue( RegisterNumberFromUdisIndex(op->base)); targetAddress += op->offset; } break; case UD_OP_MEM: { targetAddress = x64State->IntRegisterValue( RegisterNumberFromUdisIndex(op->base)); targetAddress += x64State->IntRegisterValue( RegisterNumberFromUdisIndex(op->index)) * op->scale; off_t offset = 0; switch (op->offset) { case 8: offset = op->lval.sbyte; break; case 16: offset = op->lval.sword; break; case 32: offset = op->lval.sdword; break; case 64: offset = op->lval.sqword; break; } targetAddress += offset; } break; case UD_OP_JIMM: { targetAddress = ud_insn_off(fUdisData) + ud_insn_len(fUdisData); if (op->size == 32) targetAddress += op->lval.sdword; else targetAddress += op->lval.sqword; } break; case UD_OP_IMM: case UD_OP_CONST: { if (op->size == 32) targetAddress = op->lval.udword; else if (op->size == 64) targetAddress = op->lval.uqword; } break; default: break; } return targetAddress; }