int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { int oplen; struct ud u; ud_init (&u); ud_set_pc (&u, addr); ud_set_mode (&u, anal->bits); ud_set_syntax (&u, NULL); ud_set_input_buffer (&u, data, len); ud_disassemble (&u); memset (op, '\0', sizeof (RAnalOp)); op->addr = addr; op->jump = op->fail = -1; op->ref = op->value = -1; oplen = op->length = ud_insn_len (&u); switch (u.mnemonic) { case UD_Ijmp: op->type = R_ANAL_OP_TYPE_JMP; op->jump = addr + oplen + getval (&u.operand[0]); break; case UD_Ijz: case UD_Ijnz: case UD_Ijb: case UD_Ijbe: case UD_Ija: case UD_Ijs: case UD_Ijns: case UD_Ijo: case UD_Ijno: case UD_Ijp: case UD_Ijnp: case UD_Ijl: case UD_Ijge: case UD_Ijle: case UD_Ijg: case UD_Ijcxz: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + oplen + getval (&u.operand[0]); op->fail = addr+oplen; break; case UD_Icall: op->type = R_ANAL_OP_TYPE_CALL; op->jump = oplen + getval (&u.operand[0]); op->fail = addr+oplen; break; case UD_Iret: case UD_Iretf: case UD_Isysret: op->type = R_ANAL_OP_TYPE_RET; break; case UD_Isyscall: op->type = R_ANAL_OP_TYPE_SWI; break; case UD_Inop: op->type = R_ANAL_OP_TYPE_NOP; break; default: break; } return oplen; }
/* * len must be aligned to the sizeof(long) */ int cnt = len / sizeof(long); size_t memsz = 0; for (int x = 0; x < cnt; x++) { uint8_t *addr = (uint8_t *) pc + (int)(x * sizeof(long)); long ret = ptrace(PT_READ_D, pid, addr, NULL); if (errno != 0) { LOGMSG_P(l_WARN, "Couldn't PT_READ_D on pid %d, addr: %p", pid, addr); break; } memsz += sizeof(long); memcpy(&buf[x * sizeof(long)], &ret, sizeof(long)); } return memsz; } #if defined(__i386__) || defined(__x86_64__) #ifndef MAX_OP_STRING #define MAX_OP_STRING 32 #endif /* MAX_OP_STRING */ static void arch_getX86InstrStr(pid_t pid, char *instr, void *pc) { /* * MAX_INSN_LENGTH is actually 15, but we need a value aligned to 8 * which is sizeof(long) on 64bit CPU archs (on most of them, I hope;) */ uint8_t buf[16]; size_t memsz; if ((memsz = arch_getProcMem(pid, buf, sizeof(buf), pc)) == 0) { snprintf(instr, MAX_OP_STRING, "%s", "[NOT_MMAPED]"); return; } ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 64); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_pc(&ud_obj, (uint64_t) (long)pc); ud_set_input_buffer(&ud_obj, buf, memsz); if (!ud_disassemble(&ud_obj)) { LOGMSG(l_WARN, "Couldn't disassemble the x86/x86-64 instruction stream"); return; } snprintf(instr, MAX_OP_STRING, "%s", ud_insn_asm(&ud_obj)); for (int x = 0; instr[x] && x < MAX_OP_STRING; x++) { if (instr[x] == '/' || instr[x] == '\\' || isspace(instr[x]) || !isprint(instr[x])) { instr[x] = '_'; } } }
void Analysis::set_label_address(pCodeBufferInfo pinfo, AddressArray & _addra, std::map<long,int> & _map) { 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); std::vector <ud_t> ud_obj_array; int label = 0; while (ud_disassemble(&ud_obj) != 0) { if (ud_obj.insn_offset > _addra[label]) { //printf("当前地址不可能比分支地址大"); } if (ud_obj.insn_offset == _addra[label]) { _map.insert(std::make_pair(ud_obj.insn_offset,label)); //printf("地址:%08x,标签:%d\n",ud_obj.insn_offset,label); label++; } } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { int opsize; static ud_t d = {0}; static int osyntax = 0; if (!d.dis_mode) ud_init (&d); if (osyntax != a->syntax) { ud_set_syntax (&d, (a->syntax==R_ASM_SYNTAX_ATT)? UD_SYN_ATT: UD_SYN_INTEL); osyntax = a->syntax; } ud_set_input_buffer (&d, (uint8_t*) buf, len); ud_set_pc (&d, a->pc); ud_set_mode (&d, a->bits); opsize = ud_disassemble (&d); strncpy (op->buf_asm, ud_insn_asm (&d), R_ASM_BUFSIZE-1); op->buf_asm[R_ASM_BUFSIZE-1] = 0; if (opsize<1 || strstr (op->buf_asm, "invalid")) opsize = 0; op->size = opsize; if (a->syntax == R_ASM_SYNTAX_JZ) { if (!strncmp (op->buf_asm, "je ", 3)) { memcpy (op->buf_asm, "jz", 2); } else if (!strncmp (op->buf_asm, "jne ", 4)) { memcpy (op->buf_asm, "jnz", 3); } } return opsize; }
pCodeInformation EquivalentInstruct::code_equivalent_replacement(pCodeInformation info,unsigned long imagebase) { ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_pc(&ud_obj,info->base); ud_set_input_buffer(&ud_obj, info->buf, info->size); ud_set_syntax(&ud_obj, UD_SYN_INTEL); char buff[0xFFF]; int error; while (ud_disassemble(&ud_obj) != 0) { switch (ud_obj.mnemonic) { case UD_NONE: break; case UD_Imov: { // dword_ptr() } break; } } }
status_t DisassemblerX8664::Init(target_addr_t address, const void* code, size_t codeSize) { // unset old data delete fUdisData; fUdisData = NULL; // set new data fUdisData = new(std::nothrow) UdisData; if (fUdisData == NULL) return B_NO_MEMORY; fAddress = address; fCode = (const uint8*)code; fCodeSize = codeSize; // init udis ud_init(fUdisData); ud_set_input_buffer(fUdisData, (unsigned char*)fCode, fCodeSize); ud_set_mode(fUdisData, 64); ud_set_pc(fUdisData, (uint64_t)fAddress); ud_set_syntax(fUdisData, UD_SYN_ATT); ud_set_vendor(fUdisData, UD_VENDOR_INTEL); // TODO: Set the correct vendor! return B_OK; }
void DisassembleEp(hadesmem::Process const& process, hadesmem::PeFile const& pe_file, std::uintptr_t ep_rva, void* ep_va, std::size_t tabs) { if (!ep_va) { return; } std::wostream& out = GetOutputStreamW(); // Get the number of bytes from the EP to the end of the file. std::size_t max_buffer_size = GetBytesToEndOfFile(pe_file, ep_va); // Clamp the amount of data read to the theoretical maximum. std::size_t const kMaxInstructions = 10U; std::size_t const kMaxInstructionLen = 15U; std::size_t const kMaxInstructionsBytes = kMaxInstructions * kMaxInstructionLen; max_buffer_size = (std::min)(max_buffer_size, kMaxInstructionsBytes); auto const disasm_buf = hadesmem::ReadVector<std::uint8_t>(process, ep_va, max_buffer_size); std::uint64_t const ip = hadesmem::GetRuntimeBase(process, pe_file) + ep_rva; ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, disasm_buf.data(), max_buffer_size); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_pc(&ud_obj, ip); ud_set_mode(&ud_obj, pe_file.Is64() ? 64 : 32); // Be pessimistic. Use the minimum theoretical amount of instrutions we could // fit in our buffer. std::size_t const instruction_count = max_buffer_size / kMaxInstructionLen; for (std::size_t i = 0U; i < instruction_count; ++i) { std::uint32_t const len = ud_disassemble(&ud_obj); if (len == 0) { WriteNormal(out, L"WARNING! Disassembly failed.", tabs); // If we can't disassemble at least 5 instructions there's probably // something strange about the function. Even in the case of a nullsub // there is typically some INT3 or NOP padding after it... WarnForCurrentFile(i < 5U ? WarningType::kUnsupported : WarningType::kSuspicious); break; } char const* const asm_str = ud_insn_asm(&ud_obj); HADESMEM_DETAIL_ASSERT(asm_str); char const* const asm_bytes_str = ud_insn_hex(&ud_obj); HADESMEM_DETAIL_ASSERT(asm_bytes_str); auto const diasm_line = hadesmem::detail::MultiByteToWideChar(asm_str) + L" (" + hadesmem::detail::MultiByteToWideChar(asm_bytes_str) + L")"; WriteNormal(out, diasm_line, tabs); } }
/* ============================================================================= * ud_init() - Initializes ud_t object. * ============================================================================= */ extern void ud_init (struct ud *u) { memset ((void *) u, 0, sizeof (struct ud)); ud_set_mode (u, 16); u->mnemonic = UD_Iinvalid; ud_set_pc (u, 0); #ifndef __UD_STANDALONE__ ud_set_input_file (u, stdin); #endif /* __UD_STANDALONE__ */ }
/** HookEngine_Disassemble Obtain the minimum number of instruction bytes that need to be copied from the target function, in order to accomodate our jump instruction */ static DWORD HookEngine_Disassemble(DWORD cbRequired, LPVOID pTargetFunctionAddress, DISASSEMBLY_DATA& DisassemblyData ) { CONST SIZE_T Page = 4096; ud_t ud_obj = { 0 }; ud_init(&ud_obj); #if defined(_M_IX86) ud_set_mode(&ud_obj, 32); #elif defined(_M_X64) ud_set_mode(&ud_obj, 64); #else #error Unsuported platform #endif ud_set_pc(&ud_obj, uint64_t(pTargetFunctionAddress)); ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); ud_set_input_buffer(&ud_obj, (unsigned char*)pTargetFunctionAddress, Page); DWORD instrlen = 0; DisassemblyData.Count = 0; DisassemblyData.Length = 0; HookEngine_Memset(DisassemblyData.Instructions, 0, sizeof(DisassemblyData.Instructions)); HookEngine_Memset(DisassemblyData.InstuctionBuffer, 0, sizeof(DisassemblyData.InstuctionBuffer)); HookEngine_Memset(DisassemblyData.InstructionLengths, 0, sizeof(DisassemblyData.InstructionLengths)); do { instrlen = ud_disassemble(&ud_obj); if (instrlen) { if ((DisassemblyData.Length + instrlen) < MAX_INSTRUCTION_BUFFER) { DisassemblyData.Instructions[DisassemblyData.Count] = ud_obj; DisassemblyData.InstructionLengths[DisassemblyData.Count] = instrlen; DisassemblyData.Count++; HookEngine_Memcpy(&DisassemblyData.InstuctionBuffer[DisassemblyData.Length], ((BYTE*)pTargetFunctionAddress) + DisassemblyData.Length, instrlen); DisassemblyData.Length += instrlen; } } } while (DisassemblyData.Length < cbRequired && DisassemblyData.Count < MAX_INSTRUCTIONS && instrlen != 0); return DisassemblyData.Length; }
void Analysis::analysis_address_table(pCodeBufferInfo pinfo, std::vector<long> & addr_entry_table, long addr_min, long addr_max) //jmp [addr_table + reg] 查找addr_table里面的值 { /*#define WINDOWS #include <Windows.h> HMODULE module = LoadLibrary(""); #endif */ 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); while(ud_disassemble(&ud_obj) != 0) { if (ud_obj.operand[0].type == UD_OP_MEM) { if (ud_obj.operand[0].offset == 32) { long addr = ud_obj.operand[0].lval.sdword; if (addr <= addr_max && addr >= addr_min) addr_entry_table.push_back(addr); } } if (ud_obj.operand[1].type == UD_OP_MEM) { if (ud_obj.operand[1].offset == 32) { long addr = ud_obj.operand[1].lval.sdword; if (addr <= addr_max && addr >= addr_min) addr_entry_table.push_back(addr); } } //if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp && ud_obj.operand[0].type == UD_OP_MEM) //{ //} } }
Client::Client() { base = (DWORD)GetModuleHandle(nullptr); auto idh = (PIMAGE_DOS_HEADER)base; auto inh = (PIMAGE_NT_HEADERS)(base + idh->e_lfanew); auto ioh = &inh->OptionalHeader; imports = (PIMAGE_IMPORT_DESCRIPTOR)(base + ioh->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); codeBase = (BYTE*)(base + ioh->BaseOfCode); codeEnd = codeBase + ioh->SizeOfCode; dataBase = (BYTE*)(base + ioh->BaseOfData); dataEnd = dataBase + ioh->SizeOfInitializedData; ud ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, nullptr); ud_set_input_buffer(&ud_obj, codeBase, codeEnd - codeBase); ud_set_pc(&ud_obj, (UINT)codeBase); data.reserve(0x100000); while (ud_disassemble(&ud_obj)) { if (ud_obj.mnemonic == UD_Iint3 || ud_obj.mnemonic == UD_Inop)//useless continue; ud_instr instr; instr.op = ud_obj.mnemonic | (ud_obj.inp_ctr << 16); for (int i = 0; i < 2; i++) { if ((instr.args[i].type = ud_obj.operand[i].type) == UD_NONE) break; if (instr.args[i].type == UD_OP_MEM) instr.args[i].size = ud_obj.operand[i].offset; else instr.args[i].size = ud_obj.operand[i].size; instr.args[i].base = ud_obj.operand[i].base; instr.args[i].lval = ud_obj.operand[i].lval.udword; } instr.offset = (LPVOID)ud_obj.insn_offset; data.push_back(instr); } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, ut64 len) { static ud_t disasm_obj; ud_init (&disasm_obj); ud_set_syntax (&disasm_obj, a->syntax==R_ASM_SYNTAX_ATT? UD_SYN_ATT: UD_SYN_INTEL); ud_set_mode (&disasm_obj, a->bits); ud_set_pc (&disasm_obj, a->pc); ud_set_input_buffer (&disasm_obj, buf, len); op->inst_len = ud_disassemble (&disasm_obj); //op->inst_len = ud_insn_len (&disasm_obj); snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s", ud_insn_asm (&disasm_obj)); if (!op->inst_len || strstr (op->buf_asm, "invalid")) op->inst_len = -1; if (op->inst_len<1) op->inst_len = -1; return op->inst_len; }
int ludis86_ud_set_pc (lua_State * L) { ud_t * ud_obj; uint64_t rip; ud_obj = ludis86_check_ud_t(L, 1); if (lua_isnumber(L, 2)) rip = luaL_checkint(L, 2); else rip = strtoull(luaL_checkstring(L, 2), NULL, 0); lua_pop(L, 2); ud_set_pc(ud_obj, rip); return 0; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { int opsize; static ud_t d = {0}; static int osyntax = 0; if (!d.dis_mode) ud_init (&d); if (osyntax != a->syntax) { ud_set_syntax (&d, (a->syntax==R_ASM_SYNTAX_ATT)? UD_SYN_ATT: UD_SYN_INTEL); osyntax = a->syntax; } ud_set_input_buffer (&d, (uint8_t*) buf, len); ud_set_pc (&d, a->pc); ud_set_mode (&d, a->bits); opsize = ud_disassemble (&d); snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s", ud_insn_asm (&d)); op->size = opsize; if (opsize<1 || strstr (op->buf_asm, "invalid")) opsize = -1; return opsize; }
int main(int argc, char *argv[]) { ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, (unsigned char *)func, 100); ud_set_syntax(&ud_obj, UD_SYN_ATT); ud_set_mode(&ud_obj, 64); ud_set_pc(&ud_obj, (unsigned long)func); unsigned int pointer = 0, cur_insn_length = 0; while ( (cur_insn_length = ud_disassemble(&ud_obj)) != 0 ) { printf("func(%d): %s\n", pointer, ud_insn_asm(&ud_obj)); pointer += cur_insn_length; } return EXIT_SUCCESS; }
static const char *disassemble(unsigned char *insn, int len, uint64_t rip, int cr0_pe, int eflags_vm, int cs_d, int cs_l) { int mode; if (!cr0_pe) mode = 16; else if (eflags_vm) mode = 16; else if (cs_l) mode = 64; else if (cs_d) mode = 32; else mode = 16; ud_set_pc(&ud, rip); ud_set_mode(&ud, mode); ud_set_input_buffer(&ud, insn, len); ud_disassemble(&ud); return ud_insn_asm(&ud); }
bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out) { ud_t disassembler; ud_init(&disassembler); ud_set_input_buffer(&disassembler, static_cast<unsigned char*>(codePtr.executableAddress()), size); #if CPU(X86_64) ud_set_mode(&disassembler, 64); #else ud_set_mode(&disassembler, 32); #endif ud_set_pc(&disassembler, bitwise_cast<uintptr_t>(codePtr.executableAddress())); ud_set_syntax(&disassembler, UD_SYN_ATT); uint64_t currentPC = disassembler.pc; while (ud_disassemble(&disassembler)) { char pcString[20]; print(pcString, sizeof(pcString), currentPC); out.printf("%s%16s: %s\n", prefix, pcString, ud_insn_asm(&disassembler)); currentPC = disassembler.pc; } return true; }
void lp_disassemble(const void* func) { #ifdef HAVE_UDIS86 ud_t ud_obj; uint64_t max_jmp_pc; uint inst_no; boolean emit_addrs = TRUE, emit_line_nos = FALSE; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, (void*)func, 0xffff); max_jmp_pc = (uint64_t) (uintptr_t) func; ud_set_pc(&ud_obj, max_jmp_pc); #ifdef PIPE_ARCH_X86 ud_set_mode(&ud_obj, 32); #endif #ifdef PIPE_ARCH_X86_64 ud_set_mode(&ud_obj, 64); #endif ud_set_syntax(&ud_obj, UD_SYN_ATT); while (ud_disassemble(&ud_obj)) { if (emit_addrs) { #ifdef PIPE_ARCH_X86 debug_printf("0x%08lx:\t", (unsigned long)ud_insn_off(&ud_obj)); #endif #ifdef PIPE_ARCH_X86_64 debug_printf("0x%016llx:\t", (unsigned long long)ud_insn_off(&ud_obj)); #endif } else if (emit_line_nos) { debug_printf("%6d:\t", inst_no); inst_no++; } #if 0 debug_printf("%-16s ", ud_insn_hex(&ud_obj)); #endif debug_printf("%s\n", ud_insn_asm(&ud_obj)); if(ud_obj.mnemonic != UD_Icall) { unsigned i; for(i = 0; i < 3; ++i) { const struct ud_operand *op = &ud_obj.operand[i]; if (op->type == UD_OP_JIMM){ uint64_t pc = ud_obj.pc; switch (op->size) { case 8: pc += op->lval.sbyte; break; case 16: pc += op->lval.sword; break; case 32: pc += op->lval.sdword; break; default: break; } if(pc > max_jmp_pc) max_jmp_pc = pc; } } } if (ud_obj.mnemonic == UD_Iinvalid || (ud_insn_off(&ud_obj) >= max_jmp_pc && (ud_obj.mnemonic == UD_Iret || ud_obj.mnemonic == UD_Ijmp))) break; } #if 0 /* Print GDB command, useful to verify udis86 output */ debug_printf("disassemble %p %p\n", func, (void*)(uintptr_t)ud_obj.pc); #endif debug_printf("\n"); #else (void)func; #endif }
virtual void Apply() override { if (applied_) { return; } if (detached_) { HADESMEM_DETAIL_ASSERT(false); return; } // Reset the trampolines here because we don't do it in remove, otherwise // there's a potential race condition where we want to unhook and unload // safely, so we unhook the function, then try waiting on our ref count to // become zero, but we haven't actually called the trampoline yet, so we end // up jumping to the memory we just free'd! trampoline_ = nullptr; trampolines_.clear(); stub_gate_ = nullptr; SuspendedProcess const suspended_process{process_->GetId()}; std::uint32_t const kMaxInstructionLen = 15; std::uint32_t const kTrampSize = kMaxInstructionLen * 3; trampoline_ = std::make_unique<Allocator>(*process_, kTrampSize); auto tramp_cur = static_cast<std::uint8_t*>(trampoline_->GetBase()); auto const detour_raw = detour_.target<DetourFuncRawT>(); if (detour_raw || detour_) { HADESMEM_DETAIL_TRACE_FORMAT_A( "Target = %p, Detour = %p, Trampoline = %p.", target_, detour_raw, trampoline_->GetBase()); } else { HADESMEM_DETAIL_TRACE_FORMAT_A( "Target = %p, Detour = INVALID, Trampoline = %p.", target_, trampoline_->GetBase()); } auto const buffer = ReadVector<std::uint8_t>(*process_, target_, kTrampSize); ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, buffer.data(), buffer.size()); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_pc(&ud_obj, reinterpret_cast<std::uint64_t>(target_)); #if defined(HADESMEM_DETAIL_ARCH_X64) ud_set_mode(&ud_obj, 64); #elif defined(HADESMEM_DETAIL_ARCH_X86) ud_set_mode(&ud_obj, 32); #else #error "[HadesMem] Unsupported architecture." #endif stub_gate_ = detail::AllocatePageNear(*process_, target_); std::size_t const patch_size = GetPatchSize(); std::uint32_t instr_size = 0; do { std::uint32_t const len = ud_disassemble(&ud_obj); if (len == 0) { HADESMEM_DETAIL_THROW_EXCEPTION(Error{} << ErrorString{"Disassembly failed."}); } #if !defined(HADESMEM_NO_TRACE) char const* const asm_str = ud_insn_asm(&ud_obj); char const* const asm_bytes_str = ud_insn_hex(&ud_obj); HADESMEM_DETAIL_TRACE_FORMAT_A( "%s. [%s].", (asm_str ? asm_str : "Invalid."), (asm_bytes_str ? asm_bytes_str : "Invalid.")); #endif ud_operand_t const* const op = ud_insn_opr(&ud_obj, 0); bool is_jimm = op && op->type == UD_OP_JIMM; // Handle JMP QWORD PTR [RIP+Rel32]. Necessary for hook chain support. bool is_jmem = op && op->type == UD_OP_MEM && op->base == UD_R_RIP && op->index == UD_NONE && op->scale == 0 && op->size == 0x40; if ((ud_obj.mnemonic == UD_Ijmp || ud_obj.mnemonic == UD_Icall) && op && (is_jimm || is_jmem)) { std::uint16_t const size = is_jimm ? op->size : op->offset; HADESMEM_DETAIL_TRACE_FORMAT_A("Operand/offset size is %hu.", size); std::int64_t const insn_target = [&]() -> std::int64_t { switch (size) { case sizeof(std::int8_t) * CHAR_BIT: return op->lval.sbyte; case sizeof(std::int16_t) * CHAR_BIT: return op->lval.sword; case sizeof(std::int32_t) * CHAR_BIT: return op->lval.sdword; case sizeof(std::int64_t) * CHAR_BIT: return op->lval.sqword; default: HADESMEM_DETAIL_ASSERT(false); HADESMEM_DETAIL_THROW_EXCEPTION( Error{} << ErrorString{"Unknown instruction size."}); } }(); auto const resolve_rel = [](std::uint64_t base, std::int64_t target, std::uint32_t insn_len) { return reinterpret_cast<std::uint8_t*>( static_cast<std::uintptr_t>(base)) + target + insn_len; }; std::uint64_t const insn_base = ud_insn_off(&ud_obj); std::uint32_t const insn_len = ud_insn_len(&ud_obj); auto const resolved_target = resolve_rel(insn_base, insn_target, insn_len); void* const jump_target = is_jimm ? resolved_target : Read<void*>(*process_, resolved_target); HADESMEM_DETAIL_TRACE_FORMAT_A("Jump/call target = %p.", jump_target); if (ud_obj.mnemonic == UD_Ijmp) { HADESMEM_DETAIL_TRACE_A("Writing resolved jump."); tramp_cur += detail::WriteJump( *process_, tramp_cur, jump_target, true, &trampolines_); } else { HADESMEM_DETAIL_ASSERT(ud_obj.mnemonic == UD_Icall); HADESMEM_DETAIL_TRACE_A("Writing resolved call."); tramp_cur += detail::WriteCall(*process_, tramp_cur, jump_target, trampolines_); } } else { std::uint8_t const* const raw = ud_insn_ptr(&ud_obj); Write(*process_, tramp_cur, raw, raw + len); tramp_cur += len; } instr_size += len; } while (instr_size < patch_size); HADESMEM_DETAIL_TRACE_A("Writing jump back to original code."); tramp_cur += detail::WriteJump(*process_, tramp_cur, reinterpret_cast<std::uint8_t*>(target_) + instr_size, true, &trampolines_); FlushInstructionCache( *process_, trampoline_->GetBase(), trampoline_->GetSize()); detail::WriteStubGate<TargetFuncT>(*process_, stub_gate_->GetBase(), &*stub_, &GetOriginalArbitraryUserPtrPtr); orig_ = ReadVector<std::uint8_t>(*process_, target_, patch_size); detail::VerifyPatchThreads(process_->GetId(), target_, orig_.size()); WritePatch(); FlushInstructionCache(*process_, target_, instr_size); applied_ = true; }
int x86_udis86_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len) { const char *pc = anal->bits==64? "rip": anal->bits==32? "eip": "ip"; const char *sp = anal->bits==64? "rsp": anal->bits==32? "esp": "sp"; const char *bp = anal->bits==64? "rbp": anal->bits==32? "ebp": "bp"; int oplen, regsz = 4; char str[64], src[32], dst[32]; struct ud u; switch (anal->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } UDis86Esil *handler; UDis86OPInfo info = {0, anal->bits, (1LL << anal->bits) - 1, regsz, 0, pc, sp, bp}; memset (op, '\0', sizeof (RAnalOp)); r_strbuf_init (&op->esil); op->addr = addr; op->jump = op->fail = -1; op->ptr = op->val = -1; ud_init (&u); ud_set_pc (&u, addr); ud_set_mode (&u, anal->bits); ud_set_syntax (&u, NULL); ud_set_input_buffer (&u, data, len); ud_disassemble (&u); oplen = op->size = ud_insn_len (&u); if (anal->decode && (handler = udis86_esil_get_handler (u.mnemonic))) { info.oplen = oplen; if (handler->argc > 0) { info.n = getval (u.operand); getarg (dst, &u, info.bitmask, 0); if (handler->argc > 1) { getarg (src, &u, info.bitmask, 1); if (handler->argc > 2) getarg (str, &u, info.bitmask, 2); } } handler->callback (&info, op, dst, src, str); } switch (u.mnemonic) { case UD_Iinvalid: oplen = op->size = -1; return -1; break; case UD_Itest: case UD_Icmp: op->type = R_ANAL_OP_TYPE_CMP; break; case UD_Isalc: // ?? // al = cf break; case UD_Ixor: op->type = R_ANAL_OP_TYPE_XOR; break; case UD_Ior: op->type = R_ANAL_OP_TYPE_OR; break; case UD_Iand: op->type = R_ANAL_OP_TYPE_AND; break; case UD_Isar: op->type = R_ANAL_OP_TYPE_SAR; break; // XXX: sal ?!? case UD_Ishl: op->type = R_ANAL_OP_TYPE_SHL; break; case UD_Ishr: op->type = R_ANAL_OP_TYPE_SHR; break; case UD_Irol: op->type = R_ANAL_OP_TYPE_ROL; break; case UD_Iror: op->type = R_ANAL_OP_TYPE_ROR; break; case UD_Iint3: op->type = R_ANAL_OP_TYPE_TRAP; break; case UD_Iint: op->type = R_ANAL_OP_TYPE_SWI; op->val = u.operand[0].lval.uword; break; case UD_Ilea: case UD_Imov: op->type = R_ANAL_OP_TYPE_MOV; switch (u.operand[1].type) { case UD_OP_MEM: op->type = R_ANAL_OP_TYPE_MOV; if (u.operand[1].base == UD_R_RIP) { int delta = u.operand[1].lval.uword; op->ptr = addr + oplen + delta; } break; default: op->type = R_ANAL_OP_TYPE_MOV; op->ptr = getval (&u.operand[1]); // XX break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case UD_Ipush: case UD_Ipusha: case UD_Ipushad: case UD_Ipushfq: case UD_Ipushfd: case UD_Ipushfw: switch (u.operand[0].type) { case UD_OP_CONST: case UD_OP_JIMM: case UD_OP_IMM: op->type = R_ANAL_OP_TYPE_PUSH; op->ptr = getval (&u.operand[0]); break; case UD_OP_REG: case UD_OP_PTR: case UD_OP_MEM: default: op->type = R_ANAL_OP_TYPE_UPUSH; op->ptr = 0; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case UD_Ipop: case UD_Ipopa: case UD_Ipopad: case UD_Ipopfw: case UD_Ipopfd: case UD_Ipopfq: op->type = R_ANAL_OP_TYPE_POP; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Ileave: op->type = R_ANAL_OP_TYPE_MOV; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Iadd: case UD_Isub: op->type = (u.mnemonic==UD_Iadd)? R_ANAL_OP_TYPE_ADD: R_ANAL_OP_TYPE_SUB; op->ptr = 0; op->stackptr = 0; if (u.operand[0].type == UD_OP_REG) { if (u.operand[0].base == UD_R_RSP) { int o = (int)getval (&u.operand[1]); op->stackop = R_ANAL_STACK_INC; if (u.mnemonic ==UD_Iadd) { op->stackptr = -o; } else { op->stackptr = o; } } if (u.operand[1].type != UD_OP_REG) op->val = getval (&u.operand[1]); } op->stackptr = 4; break; case UD_Iadc: case UD_Iinc: op->type = R_ANAL_OP_TYPE_ADD; break; case UD_Isbb: case UD_Idec: op->type = R_ANAL_OP_TYPE_SUB; break; case UD_Ijmp: switch (u.operand[0].type) { case UD_OP_MEM: case UD_OP_REG: op->type = R_ANAL_OP_TYPE_UJMP; break; default: op->type = R_ANAL_OP_TYPE_JMP; #if 0 { ut16 a = (op->lval.ptr.seg & 0xFFFF); ut16 b = (op->lval.ptr.off); switch (op->size) { case 32: sprintf (src, "%04x:%04x", a, b & 0xFFFF); break; case 48: sprintf (src, "%04x:%04x", a, b); break; default: eprintf ("F**K YOU\n"); } } #endif if (u.operand[0].type==UD_OP_PTR) { op->jump = getval (&u.operand[0]); } else { if (anal->bits==16) { // honor segment op->jump = (addr&0xf0000) + oplen + \ (((addr&0xffff)+getval (&u.operand[0])&0xffff)); } else { op->jump = addr + oplen + (int)getval (&u.operand[0]); } } } break; case UD_Ije: case UD_Ijne: case UD_Ijb: case UD_Ijbe: case UD_Ija: case UD_Ijae: case UD_Ijs: case UD_Ijns: case UD_Ijo: case UD_Ijno: case UD_Ijp: case UD_Ijnp: case UD_Ijl: case UD_Ijge: case UD_Ijle: case UD_Ijg: case UD_Ijcxz: case UD_Iloop: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = addr + oplen + (int)getval (&u.operand[0]); op->fail = addr+oplen; break; case UD_Icall: op->type = R_ANAL_OP_TYPE_CALL; switch (u.operand[0].type) { case UD_OP_REG: op->jump = 0; // EAX, EBX, ... use anal->reg break; case UD_OP_IMM: case UD_OP_MEM: case UD_OP_PTR: default: op->jump = addr + oplen + (int)getval (&u.operand[0]); } op->fail = addr + oplen; break; case UD_Ihlt: //op->type = R_ANAL_OP_TYPE_HALT; break; case UD_Iret: case UD_Iretf: case UD_Isysret: op->type = R_ANAL_OP_TYPE_RET; op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case UD_Isyscall: op->type = R_ANAL_OP_TYPE_SWI; break; case UD_Inop: op->type = R_ANAL_OP_TYPE_NOP; break; default: break; } return oplen; }
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); } } }
pAssemblerTree Analysis::disasm(pCodeBufferInfo pinfo) { std::vector<CodePiece> piece_test; disasm(pinfo,piece_test) ; for (std::vector<CodePiece>::iterator iter = piece_test.begin(); iter != piece_test.end();iter++) { printf("\033[31m标签:%08x,\033[34m跳转到:%08x\033[0m,条件跳转:%d\n",iter->get_label(),iter->get_jmplabel(),iter->get_is_jcc()); for (std::list<ud_t>::iterator xiter = iter->get_piece().begin(); xiter != iter->get_piece().end();xiter++) { printf("%s\n",xiter->insn_buffer); } } //__asm("int3"); 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; std::vector <long> address_array; //pAssemblerTree root = new AssemblerTree; // pAssemblerTree nowtree = root; std::vector <ud_t> ud_obj_array; address_array.push_back(pinfo->addr); address_array.push_back(pinfo->addr + pinfo->size); while (ud_disassemble(&ud_obj) != 0) { ud_obj_array.push_back(ud_obj); // nowtree.asmpiect.push_back(ud_obj); if (ud_obj.operand[0].type == UD_OP_JIMM || ud_obj.mnemonic == UD_Icall )//&& ud_obj.mnemonic != 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) { address_array.push_back(addr); address_array.push_back(ud_obj.pc); } } } long count = 0; long *a_array; size_t address_size = address_array.size(); a_array = new long[address_size]; for (std::vector <long>::iterator iter = address_array.begin() ; iter != address_array.end() ; ++iter) { bool fk = true; for (int i = 0; i < count; ++i) { if (*iter == a_array[i]) { fk = false; } } if (fk) a_array[count++] = *iter; } for (int i = 0; i < count; ++i) { for (int j = i; j < count ; ++j) { if (a_array[i] > a_array[j]) { long t = a_array[i]; a_array[i] = a_array[j]; a_array[j] = t; } } } for (int i = 0; i < count; ++i) { printf("%08x\r\n",a_array[i]); } int point = 0; pAssemblerTree nowtree = NULL; pAssemblerTree parent = NULL; const bool begin = true; const bool end = false; bool status = end; for (std::vector <ud_t>::iterator iter = ud_obj_array.begin(); iter != ud_obj_array.end(); ++iter) { //typedef true begin; //typedef false end; // ud_t *p = iter; ud_t ud = *iter; if (ud.insn_offset == a_array[point] && status == end) { point++; status = begin; nowtree = new AssemblerTree; root ? NULL : root = nowtree; nowtree->LeftChild = NULL; nowtree->RightChild = NULL; nowtree->id = point - 1; // nowtree.asmpiect.push_back(ud); } if (nowtree) { nowtree->asmpiece.push_back(ud); } if (ud.pc == a_array[point] && status == begin) { nowtree->base = a_array[point-1]; //point++; nowtree->size = ud.pc - a_array[point-1]; //代码块大小 status = end; parent = add_tree(parent,nowtree,L); //nowtree = new AssemblerTree; //nowtree->LeftChild = NULL; //nowtree->RightChild = NULL; } nowtree->reloc_address = -1; nowtree->next_instruction = ud.pc; } block_count = point; link_tree(); #ifdef DEBUG show_tree(root,"false:"); #endif delete [] a_array; // show_tree(root); /*for (std::vector <long>::iterator iter = address_array.begin() ; iter != address_array.end() ; ++iter) { int addr = *iter; printf("%08x\r\n",addr); }*/ return NULL; }
AddressArray Analysis::analysis_code_piece_address(pCodeBufferInfo pinfo) { 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; std::vector <long> address_array; //pAssemblerTree root = new AssemblerTree; // pAssemblerTree nowtree = root; address_array.push_back(pinfo->addr); address_array.push_back(pinfo->addr + pinfo->size); while (ud_disassemble(&ud_obj) != 0) { //if (ud_obj.operand[0].type == UD_OP_JIMM || ud_obj.mnemonic == UD_Icall )//&& ud_obj.mnemonic != UD_Icall) if (ud_obj.pfx_rep != 0 || ud_obj.pfx_repe != 0 || ud_obj.pfx_repne != 0) //有前缀 { address_array.push_back(ud_obj.pc); address_array.push_back(ud_obj.insn_offset); } if (ud_obj.operand[0].type == UD_OP_JIMM ) { 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) { address_array.push_back(addr); address_array.push_back(ud_obj.pc); } else { //address_array.push_back(ud_obj.pc); if (ud_obj.mnemonic != UD_Icall && ud_obj.mnemonic != UD_Ijmp) { printf("%x:跳转的地址无法找到:",ud_obj.insn_offset); printf("%x\n",addr); // __asm("int3"); //表示跳转地址是一个jcc指令 } else { address_array.push_back(ud_obj.pc); } } } if (ud_obj.mnemonic == UD_Iret || ud_obj.mnemonic == UD_Icall || ud_obj.mnemonic == UD_Ijmp) { address_array.push_back(ud_obj.pc); } /*if (ud_obj.mnemonic == UD_Icall || ud_obj.mnemonic == UD_Iret) { address_array.push_back(ud_obj.pc); }*/ } long count = 0; size_t address_size = address_array.size(); AddressArray a_array(address_size); for (std::vector <long>::iterator iter = address_array.begin() ; iter != address_array.end() ; ++iter) { bool fk = true; for (int i = 0; i < count; ++i) { if (*iter == a_array[i]) { fk = false; } } if (fk) a_array[count++] = *iter; } for (int i = 0; i < count; ++i) { for (int j = i; j < count ; ++j) { if (a_array[i] > a_array[j]) { long t = a_array[i]; a_array[i] = a_array[j]; a_array[j] = t; } } } a_array.set_size(count); #ifdef DEBUG //printf("a_array size:%08x",a_array.get_size()); for (int i = 0; i < count - 1; ++i) { printf("标签%x,分支地址:%08x - %08x\n",i,a_array[i],a_array[i+1]-1); } //__asm ("int3"); #endif return a_array; }