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; }
/* * 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] = '_'; } } }
BOOL isValidPreOpCode(BYTE *buffer, UINT nsize) { ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, buffer, nsize); ud_set_mode(&ud_obj, 64); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_t temp_ud_obj; while (ud_disassemble(&ud_obj)) { temp_ud_obj = ud_obj; } char *str = ud_insn_asm(&temp_ud_obj); if(!_stricmp(str, "ret ")) return true; if(!_stricmp(str, "nop ")) return true; if(!_stricmp(str, "int3 ")) return true; return false; }
int x86_epilogue(u8 *code, u16 require, struct x86_prologue *x86_prologue) { ud_t obj; ud_init(&obj); ud_set_mode(&obj, 64); ud_set_input_buffer(&obj, code, 64); for (int index = 0, total = 0; require > 0; ) { if (!ud_disassemble(&obj)) return -1; int len = ud_insn_len(&obj); require -= len; total += len; x86_prologue->instr[index].size = len; printf("asm: %s\n", ud_insn_asm(&obj)); //if (sizes) sizes[index] = eaten; index += 1; //count = index; } return 0; }
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; }
int main(void) { ud_t ud_obj; char x[4]; unsigned char buff[256]; int i, j; printf("Content-Type: text/html\r\n"); printf("\r\n"); char *qs = getenv("QUERY_STRING"); if(qs == NULL) return 1; for(i=0, j=0; qs[i] == '%'; i+=3, j++){ if(j >= sizeof(buff)) break; x[0] = *(qs+i+1); x[1] = *(qs+i+2); x[2] = '\0'; buff[j] = (unsigned char)strtoul(x, NULL, 16); } ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, buff, j); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); while(ud_disassemble(&ud_obj)){ //printf("%d:%s", ud_insn_len(&ud_obj), ud_insn_asm(&ud_obj)); printf("%10s: %s\n", ud_insn_hex(&ud_obj), ud_insn_asm(&ud_obj)); } return 0; }
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); } }
static void vmx_vmexit_show_insn() { ud_t disasm; if(disassemble(&disasm) == VM_DONE) printf("\n- insn : \"%s\" (len %d)\n" ,ud_insn_asm(&disasm),ud_insn_len(&disasm)); }
void LLVMState::show_machine_code(void* buffer, size_t size) { ud_t ud; ud_init(&ud); #ifdef IS_X8664 ud_set_mode(&ud, 64); #else ud_set_mode(&ud, 32); #endif ud_set_syntax(&ud, UD_SYN_ATT); ud_set_input_buffer(&ud, reinterpret_cast<uint8_t*>(buffer), size); while(ud_disassemble(&ud)) { void* address = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(buffer) + ud_insn_off(&ud)); std::cout << std::setw(10) << std::right << address << " "; std::cout << std::setw(24) << std::left << ud_insn_asm(&ud); if(ud.operand[0].type == UD_OP_JIMM) { const void* addr = (const void*)((uintptr_t)buffer + ud.pc + (int)ud.operand[0].lval.udword); std::cout << " ; " << addr; if(ud.mnemonic == UD_Icall) { Dl_info info; if(dladdr(addr, &info)) { int status = 0; char* cpp_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &status); if(status >= 0) { // Chop off the arg info from the signature output char *paren = strstr(cpp_name, "("); *paren = 0; std::cout << " " << cpp_name; free(cpp_name); } else { std::cout << " " << info.dli_sname; } } } } for(uint8_t i = 0; i < 2; i++) { if(ud.operand[i].type == UD_OP_IMM) { Dl_info info; if(dladdr((void*)ud.operand[i].lval.uqword, &info)) { std::cout << " ; " << info.dli_sname; break; // only do one } } } std::cout << "\n"; } }
BOOL isValidPostOpCode(BYTE *buffer, UINT nsize) { ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, buffer, nsize); ud_set_mode(&ud_obj, 64); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_disassemble(&ud_obj); char *str = ud_insn_asm(&ud_obj); char str1[10]; _mbsnbcpy((unsigned char*)str1, (unsigned char*)strtok(str," "), 10); ud_disassemble(&ud_obj); str = ud_insn_asm(&ud_obj); char str2[10]; _mbsnbcpy((unsigned char*)str2, (unsigned char*)strtok(str," "), 10); ud_disassemble(&ud_obj); str = ud_insn_asm(&ud_obj); char str3[10]; _mbsnbcpy((unsigned char*)str3, (unsigned char*)strtok(str," "), 10); ud_disassemble(&ud_obj); str = ud_insn_asm(&ud_obj); char str4[10]; _mbsnbcpy((unsigned char*)str4, (unsigned char*)strtok(str," "), 10); ud_disassemble(&ud_obj); str = ud_insn_asm(&ud_obj); char str5[10]; _mbsnbcpy((unsigned char*)str5, (unsigned char*)strtok(str," "), 10); if(!_stricmp(str1, "mov") && !_stricmp(str2, "push") && !_stricmp(str3, "call") && !_stricmp(str4, "pop") && !_stricmp(str5, "ret")) return false; if(!_stricmp(str1, "mov") && !_stricmp(str2, "ret")) return false; return true; }
int ludis86_ud_insn_asm (lua_State * L) { ud_t * ud_obj; ud_obj = ludis86_check_ud_t(L, 1); lua_pop(L, 1); lua_pushstring(L, ud_insn_asm(ud_obj)); return 1; }
/* * Function do_trace assumes that itrace as been attached (successfully) * to a process. It then output to stdout all the x86 instructions being * executed by traced program */ static void do_trace() { struct user_regs_struct registers; /* A struct to hold all registers of process */ size_t read_size = 15; /* how many bytes the disassembler should read */ unsigned char *buff; long eip_data[4]; /* a holding place for all the 15 bytes of eip (max intruction size) */ buff = (unsigned char *) malloc(sizeof(unsigned char)*15); int stop_status = 0; /* Loops until no more instructinos are being read */ do { ptrace(PTRACE_GETREGS, tr_pid, NULL, ®isters); eip_data[0]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip, NULL); eip_data[1]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+4, NULL); eip_data[2]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+8, NULL); eip_data[3]= ptrace(PTRACE_PEEKDATA, tr_pid, registers.eip+12, NULL); memcpy(buff, eip_data, 15); /* Initialization of 3rd part disassembler */ ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, buff, read_size); ud_disassemble(&ud_obj); /* Prints the disassembled x86 code */ printf("\t%s\n", ud_insn_asm(&ud_obj)); /* Tells the tracee to go to the next instruction, then wait */ ptrace(PTRACE_SINGLESTEP,tr_pid, 0,NULL); /* Waits until the tracee program as gon to the next intSruction and STOPPED before itrace continues */ waitpid(tr_pid, &stop_status, WUNTRACED|WCONTINUED); if(!stop_status) { printf("Something has gone wrong"); } }while (eip_data[0] != -1); return; }
int main() { ud_t u; ud_init(&u); ud_set_mode(&u, 32); ud_set_syntax(&u, UD_SYN_INTEL); ud_set_input_buffer(&u, buf, 3); ud_disassemble(&u); printf("%s\n", ud_insn_asm(&u)); printf("op0.size = %d\n", u.operand[0].size); return 0; }
void SDMDaodanWriteSubroutine(struct SDMSTSubroutine *subroutine, CoreRange range, struct SDMDisasm *disasm, FILE *file) { char *subroutineDefine = calloc(0x1, sizeof(char)*(strlen(subroutine->name)+0x4)); sprintf(subroutineDefine, "\n%s:\n",subroutine->name); FWRITE_STRING_TO_FILE(subroutineDefine, file); free(subroutineDefine); if (range.length) { SDM_disasm_setbuffer(disasm, (uintptr_t)range.offset, range.length); while (SDM_disasm_parse(disasm)) { char *line = Ptr(ud_insn_asm(&(disasm->obj))); char *printLine = calloc(0x1, sizeof(char)*(strlen(line)+0x3)); sprintf(printLine,"\t%s\n",line); FWRITE_STRING_TO_FILE(printLine, file); free(printLine); } } }
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; }
// use libudis to give human readable output of ASM void DasosPreproc::printDisasm_viaLib (uint8_t* raw, unsigned len) { ud_t ud_obj; ud_init (&ud_obj); ud_set_mode (&ud_obj, 32); ud_set_syntax (&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, raw, len); unsigned insn_len = 0; if ((insn_len = ud_disassemble (&ud_obj) ) != len) { s2e()->getDebugStream() << "disasm didn't do all insn bytes: " << insn_len << "/" << len << "\n"; return; } char buf[64]; snprintf (buf, sizeof (buf), " %-24s", ud_insn_asm (&ud_obj) ); s2e()->getDebugStream() << buf; return; } // end fn printDisasm_viaLib
int MDBCodeRegion::disassemble(char *buffer, size_t bufferSize) { void *localBuffer = malloc(size); code->debugger->read(localBuffer, address, size); ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, (uint8_t*)localBuffer, size); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); uint32_t remainingBytes = size; do { int pc = ud_obj.pc; size_t insnSize = ud_disassemble(&ud_obj); remainingBytes -= insnSize; appendString(buffer, "0x%llx: %-16s %s\n", address + pc, ud_insn_hex(&ud_obj), ud_insn_asm(&ud_obj)); } while (remainingBytes > 0); free(localBuffer); return 0; }
int main(int argc, char* argv[]) { ud_t ud_obj; ud_init(&ud_obj); FILE* f = fopen(argv[1], "r"); ud_set_input_file(&ud_obj, f); ud_set_vendor(&ud_obj, UD_VENDOR_INTEL); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_mode(&ud_obj, 32); while (ud_disassemble(&ud_obj)) { printf("\t%s\n", ud_insn_asm(&ud_obj)); } 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; }
// Function to read and disassemble one instrution after ptrace stopped on singlestep // written by Xiao Lin static void handle_singelstep() { struct user_regs_struct regfile; ptrace(PTRACE_GETREGS, tr_pid, NULL, ®file); unsigned long addr = regfile.eip; fprintf(stdout, "Address = 0x%08lx\n", addr); unsigned long data = 0; data = ptrace(PTRACE_PEEKTEXT, tr_pid, addr, NULL); fprintf(stdout, "Data = 0x%08lx\n", data); ud_t ud_obj; unsigned char buff[15]; memcpy(buff, (char*)&data, sizeof(long)); // setup udis86 ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, buff, 15); // disassemble and have udis86 guess instruction length ud_disassemble(&ud_obj); unsigned int instr_len = ud_insn_len(&ud_obj); fprintf(stdout, "Instruction length = %d Bytes\n", instr_len); // get more byte via ptrace if intruction length > 4bytes int i = 4; while (i < instr_len) { data = ptrace(PTRACE_PEEKTEXT, tr_pid, addr+i, NULL); memcpy(buff+i, (char*)&data, sizeof(long)); i = i + 4; } // disassemble second time and print ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, buff, 15); if (ud_disassemble(&ud_obj) != 0) { printf("Disassemble: %s %s\n", ud_insn_hex(&ud_obj), ud_insn_asm(&ud_obj)); } return; }
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); }
status_t DisassemblerX8664::GetNextInstruction(BString& line, target_addr_t& _address, target_size_t& _size, bool& _breakpointAllowed) { unsigned int size = ud_disassemble(fUdisData); if (size < 1) return B_ENTRY_NOT_FOUND; target_addr_t address = ud_insn_off(fUdisData); 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! line = buffer; _address = address; _size = size; _breakpointAllowed = true; // TODO: Implement (rep!)! return B_OK; }
struct _ins * redis_x86_create_ins (struct _redis_x86 * redis_x86) { ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, redis_x86->ins_bytes, redis_x86->ins_size); if (ud_disassemble(&ud_obj) == 0) { fprintf(stderr, "disassembly error %p %d\n", redis_x86->ins_bytes, (int) redis_x86->ins_size); return NULL; } struct _ins * ins = ins_create(redis_x86->ins_addr, ud_insn_ptr(&ud_obj), ud_insn_len(&ud_obj), ud_insn_asm(&ud_obj), NULL); return ins; }
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; }
MDBCodeRegion * MDBCodeRegion::fromProcedure(MDBDebugger *debugger, uintptr_t address) { size_t bufferSize = 128; char buffer[bufferSize]; if (debugger->read(buffer, address, sizeof(buffer)) != (int) sizeof(buffer)) { log.traceLn("Cannot read procedure memory."); } ud_t ud_obj; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, (uint8_t*)buffer, bufferSize); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); size_t remaining = bufferSize; do { int pc = ud_obj.pc; size_t instructionSize = ud_disassemble(&ud_obj); remaining -= instructionSize; log.traceLn("decoded: 0x%llx %s", pc, ud_insn_asm(&ud_obj)); } while (remaining > 0); return NULL; }
void LLVMState::show_machine_code(void* buffer, size_t size) { #if defined(IS_X86) || defined(IS_X8664) #ifndef RBX_WINDOWS ud_t ud; ud_init(&ud); #ifdef IS_64BIT_ARCH ud_set_mode(&ud, 64); #else ud_set_mode(&ud, 32); #endif ud_set_syntax(&ud, UD_SYN_ATT); ud_set_input_buffer(&ud, reinterpret_cast<uint8_t*>(buffer), size); while(ud_disassemble(&ud)) { void* address = reinterpret_cast<void*>( reinterpret_cast<uintptr_t>(buffer) + ud_insn_off(&ud)); llvm::outs() << format("%10p", address) << " "; llvm::outs() << format("%-24s", ud_insn_asm(&ud)); if(ud.operand[0].type == UD_OP_JIMM) { const void* addr = (const void*)((uintptr_t)buffer + ud.pc + (int)ud.operand[0].lval.udword); llvm::outs() << " ; " << addr; if(ud.mnemonic == UD_Icall) { Dl_info info; if(dladdr((void*)addr, &info)) { int status = 0; char* cpp_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &status); if(status >= 0) { // Chop off the arg info from the signature output char *paren = strstr(cpp_name, "("); *paren = 0; llvm::outs() << " " << cpp_name; free(cpp_name); } else { llvm::outs() << " " << info.dli_sname; } } } } for(uint8_t i = 0; i < 2; i++) { if(ud.operand[i].type == UD_OP_IMM) { Dl_info info; if(dladdr((void*)ud.operand[i].lval.uqword, &info)) { llvm::outs() << " ; " << info.dli_sname; break; // only do one } } } llvm::outs() << "\n"; } #endif // !RBX_WINDOWS #else JITDisassembler disassembler(buffer, size); std::string output = disassembler.print_machine_code(); std::cout << output; #endif // !IS_X86 }
struct _ins * x8664_ins (uint64_t address, ud_t * ud_obj) { struct _ins * ins; ins = ins_create(address, ud_insn_ptr(ud_obj), ud_insn_len(ud_obj), ud_insn_asm(ud_obj), NULL); if (udis86_target(address, &(ud_obj->operand[0])) != -1) { char * mnemonic_str = NULL; switch (ud_obj->mnemonic) { case UD_Ijo : mnemonic_str = "jo"; break; case UD_Ijno : mnemonic_str = "jno"; break; case UD_Ijb : mnemonic_str = "jb"; break; case UD_Ijae : mnemonic_str = "jae"; break; case UD_Ijz : mnemonic_str = "jz"; break; case UD_Ijnz : mnemonic_str = "jnz"; break; case UD_Ijbe : mnemonic_str = "jbe"; break; case UD_Ija : mnemonic_str = "ja"; break; case UD_Ijs : mnemonic_str = "js"; break; case UD_Ijns : mnemonic_str = "jns"; break; case UD_Ijp : mnemonic_str = "jp"; break; case UD_Ijnp : mnemonic_str = "jnp"; break; case UD_Ijl : mnemonic_str = "jl"; break; case UD_Ijge : mnemonic_str = "jge"; break; case UD_Ijle : mnemonic_str = "jle"; break; case UD_Ijg : mnemonic_str = "jg"; break; case UD_Ijmp : mnemonic_str = "jmp"; break; case UD_Iloop : mnemonic_str = "loop"; break; case UD_Icall : mnemonic_str = "call"; break; default : break; } uint64_t destination; destination = ud_insn_len(ud_obj); destination += udis86_target(address, &(ud_obj->operand[0])); if (mnemonic_str != NULL) { char tmp[64]; snprintf(tmp, 64, "%s %llx", mnemonic_str, (unsigned long long) destination); ins_s_description(ins, tmp); ins_s_target(ins, destination); } else { struct _reference * reference; reference = reference_create(REFERENCE_STORE, address, destination); ins_add_reference(ins, reference); object_delete(reference); } } else if (udis86_target(address, &(ud_obj->operand[1])) != -1) { uint64_t destination; destination = ud_insn_len(ud_obj); destination += udis86_target(address, &(ud_obj->operand[1])); struct _reference * reference; reference = reference_create(REFERENCE_LOAD, address, destination); ins_add_reference(ins, reference); object_delete(reference); } else if ( (ud_obj->operand[1].type == UD_OP_IMM) && (ud_obj->operand[1].size >= 32)) { int64_t tmp = udis86_sign_extend_lval(&(ud_obj->operand[1])); if (tmp > 0x1000) { struct _reference * reference; reference = reference_create(REFERENCE_CONSTANT, address, udis86_sign_extend_lval(&(ud_obj->operand[1]))); ins_add_reference(ins, reference); object_delete(reference); } } if (ud_obj->mnemonic == UD_Icall) ins_s_call(ins); return ins; }
struct _ins * x86_disassemble_ins_ (const struct _map * mem_map, const uint64_t address, uint8_t mode) { struct _buffer * buf = map_fetch_max(mem_map, address); uint64_t buf_addr = map_fetch_max_key(mem_map, address); if (buf == NULL) return NULL; size_t offset = address - buf_addr; ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, mode); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, &(buf->bytes[offset]), buf->size - offset); if (ud_disassemble(&ud_obj) == 0) return NULL; struct _ins * ins = ins_create(address, ud_insn_ptr(&ud_obj), ud_insn_len(&ud_obj), ud_insn_asm(&ud_obj), NULL); switch (ud_obj.mnemonic) { case UD_Ijo : case UD_Ijno : case UD_Ijb : case UD_Ijae : case UD_Ijz : case UD_Ijnz : case UD_Ijbe : case UD_Ija : case UD_Ijs : case UD_Ijns : case UD_Ijp : case UD_Ijnp : case UD_Ijl : case UD_Ijge : case UD_Ijle : case UD_Ijg : case UD_Iloop : ins_add_successor(ins, address + ud_insn_len(&ud_obj), INS_SUC_JCC_FALSE); if (ud_obj.operand[0].type == UD_OP_JIMM) { ins_add_successor(ins, address + ud_insn_len(&ud_obj) + x86_sign_extend_lval(&(ud_obj.operand[0])), INS_SUC_JCC_TRUE); } break; case UD_Ijmp : if (ud_obj.operand[0].type == UD_OP_JIMM) { ins_add_successor(ins, address + ud_insn_len(&ud_obj) + x86_sign_extend_lval(&(ud_obj.operand[0])), INS_SUC_JUMP); } break; case UD_Icall : ins_add_successor(ins, address + ud_insn_len(&ud_obj), INS_SUC_NORMAL); if (ud_obj.operand[0].type == UD_OP_JIMM) { ins_add_successor(ins, address + ud_insn_len(&ud_obj) + x86_sign_extend_lval(&(ud_obj.operand[0])), INS_SUC_CALL); } break; case UD_Iret : case UD_Ihlt : break; default : ins_add_successor(ins, address + ud_insn_len(&ud_obj), INS_SUC_NORMAL); } return ins; }
/** * Recursively generate code regions by statically analyzing machine code. */ bool MDBCode::scanProcedure(uintptr_t address) { if (getRegion(address)) { log.traceLn("a region already exists"); // A region already exists for this address. return true; } log.traceLn("scanning address %llx", address); size_t bufferSize = 1024 * 8; char buffer[bufferSize]; if (debugger->read(buffer, address, sizeof(buffer)) != (int) sizeof(buffer)) { log.traceLn("Cannot read procedure memory."); } MBList<uintptr_t> callTargets; ud_t insn; ud_init(&insn); ud_set_input_buffer(&insn, (uint8_t*)buffer, bufferSize); ud_set_mode(&insn, 32); ud_set_syntax(&insn, UD_SYN_INTEL); size_t remainingBytes = bufferSize; while (remainingBytes > 0) { int offset = insn.pc; size_t insnSize = ud_disassemble(&insn); remainingBytes -= insnSize; if (insnSize == 0) { error("cannot disassemble"); break; } log.traceLn("decoded: 0x%-8llx 0x%-8llx %s", address + offset, offset, ud_insn_asm(&insn)); switch (insn.mnemonic) { case UD_Icall: { uintptr_t target = 0; if (insn.operand[0].type == UD_OP_JIMM) { if (insn.operand[0].size == 32) { target = address + insn.pc + insn.operand[0].lval.sdword; } } if (target) { if (callTargets.contains(target) == false) { log.traceLn("discovered new call target 0x%llx", target); callTargets.append(target); } } break; } case UD_Iret: { MDBCodeRegion *region = new MDBCodeRegion(this, address, findSymbolByNameOrAddress(NULL, address), insn.pc); regions.append(region); remainingBytes = 0; break; } default: break; } } for (uint32_t i = 0; i < callTargets.length(); i++) { scanProcedure(callTargets[i]); } return true; }