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 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++; } } }
uintptr_t next_opcode(uintptr_t address) { ud_t ud_obj; ud_init(&ud_obj, 32); ud_set_input_buffer(&ud_obj, (uint8_t*)address, (size_t)-1); return address + ud_decode(&ud_obj); }
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; }
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; } } }
/* * 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] = '_'; } } }
/* * 预读分析阶段,在分区处理是时进行,数据与代码区域 * 范围的界定,纯数据区域返回TRUE,反之为FALSE */ __INLINE__ __bool __INTERNAL_FUNC__ PredictBlockEnd(__memory pMem, __address ImageBase, __memory pCurr, __integer iSize, \ __integer *piOutSize, PANALYZE_CONFIGURE pAnalyzeConfigure) { __bool bBlock = FALSE; __offset ofOffset = 0; 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, pCurr, iSize); while (ud_disassemble(&ud_obj)) { enum ud_mnemonic_code mnemonic = ud_obj.mnemonic; if ((mnemonic == UD_Inop) || \ (mnemonic == UD_Iint3) || \ ((mnemonic == UD_Iadd) && (ud_obj.inp_ctr == 2) && (*(__word *)&(ud_obj.inp_sess) == 0))) { /* * 到达结束条件 * 检查是否到达了用户定义代码的最小范围,如果没到直接视为数据 * 如果大于等于则进入深入鉴别 */ if (ofOffset < pAnalyzeConfigure->bCodeMixSize) bBlock = TRUE; else // 进入深度分析 bBlock = DeepAnalyzeBlock(pMem, ImageBase, pCurr, ofOffset, pAnalyzeConfigure); *piOutSize = (__integer)ofOffset; return bBlock; }/* end if */ ofOffset += (__integer)ud_insn_len(&ud_obj); } // 这里做深度鉴别 bBlock = DeepAnalyzeBlock(pMem, ImageBase, pCurr, iSize, pAnalyzeConfigure); *piOutSize = (__integer)ofOffset; return bBlock; }
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; }
EASYHOOK_NT_INTERNAL LhDisassembleInstruction(void* InPtr, ULONG* length, PSTR buf, LONG buffSize, ULONG64 *nextInstr) { /* Description: Takes a pointer to machine code and returns the length and ASM code for the referenced instruction. Returns: STATUS_INVALID_PARAMETER The given pointer references invalid machine code. */ // some exotic instructions might not be supported see the project // at https://github.com/vmt/udis86. ud_t ud_obj; ud_init(&ud_obj); #ifdef _M_X64 ud_set_mode(&ud_obj, 64); #else ud_set_mode(&ud_obj, 32); #endif ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_asm_buffer(&ud_obj, buf, buffSize); ud_set_input_buffer(&ud_obj, (uint8_t *)InPtr, 32); *length = ud_disassemble(&ud_obj); *nextInstr = (ULONG64)InPtr + *length; if(length > 0) return STATUS_SUCCESS; else return STATUS_INVALID_PARAMETER; }
void WDbgArkUdis::Init(const unsigned __int8 mode) { std::memset(&m_udis_obj, 0, sizeof(m_udis_obj)); ud_init(&m_udis_obj); ud_set_mode(&m_udis_obj, mode); ud_set_syntax(&m_udis_obj, UD_SYN_INTEL); DEBUG_PROCESSOR_IDENTIFICATION_ALL processor_info; HRESULT result = g_Ext->m_Data->ReadProcessorSystemData(0, DEBUG_DATA_PROCESSOR_IDENTIFICATION, &processor_info, static_cast<unsigned __int32>(sizeof(processor_info)), nullptr); unsigned __int32 vendor = UD_VENDOR_ANY; if (SUCCEEDED(result) && (g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_I386 || g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_AMD64) ) { std::string vendor_string; if ( g_Ext->m_ActualMachine == IMAGE_FILE_MACHINE_I386 ) vendor_string = processor_info.X86.VendorString; else vendor_string = processor_info.Amd64.VendorString; if ( vendor_string == "GenuineIntel" ) vendor = UD_VENDOR_INTEL; else vendor = UD_VENDOR_AMD; } ud_set_vendor(&m_udis_obj, vendor); }
void Translator::Translate(uchar* native, int nativeSize, std::vector<NhoInstr>* nhos) { int c = 0; ud_t dis; ud_init(&dis); ud_set_mode(&dis, 32); ud_set_syntax(&dis, UD_SYN_INTEL); NhoInstr nho; while (c < nativeSize) { ud_set_input_buffer(&dis, &native[c], nativeSize - c >= MAX_INSN_LENGTH ? MAX_INSN_LENGTH : nativeSize - c); c += ud_disassemble(&dis); nho.mnemonic = dis.mnemonic ^ MNE_XOR; memcpy(&nho.operands, &dis.operand, sizeof(nho.operands)); nho.pfx_adr = dis.pfx_adr; nho.pfx_lock = dis.pfx_lock; nho.pfx_opr = dis.pfx_opr; nho.pfx_rep = dis.pfx_rep; nho.pfx_repe = dis.pfx_repe; nho.pfx_repne = dis.pfx_repne; nho.pfx_rex = dis.pfx_rex; nho.pfx_seg = dis.pfx_seg; nho.pfx_str = dis.pfx_str; } }
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; }
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; }
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; }
EASYHOOK_NT_INTERNAL LhGetInstructionLength(void* InPtr) { /* Description: Takes a pointer to machine code and returns the length of the referenced instruction in bytes. Returns: STATUS_INVALID_PARAMETER The given pointer references invalid machine code. */ LONG length = -1; // some exotic instructions might not be supported see the project // at https://github.com/vmt/udis86 and the forums. ud_t ud_obj; ud_init(&ud_obj); #ifdef _M_X64 ud_set_mode(&ud_obj, 64); #else ud_set_mode(&ud_obj, 32); #endif ud_set_input_buffer(&ud_obj, (uint8_t *)InPtr, 32); length = ud_disassemble(&ud_obj); // usually only between 1 and 5 if(length > 0) return length; else return STATUS_INVALID_PARAMETER; }
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); } }
struct _label * elf32_label_address (struct _elf32 * elf32, struct _map * memory, uint64_t address) { Elf32_Shdr * plt_shdr = elf32_shdr_by_name(elf32, ".plt"); uint64_t plt_bottom; uint64_t plt_top; if (plt_shdr == NULL) { plt_bottom = -1; plt_top = -1; } else { plt_bottom = plt_shdr->sh_addr; plt_top = plt_bottom + plt_shdr->sh_size; } // plt functions are a special case, as we try to identify their targets // in the got // address is within the plt if ( (address >= plt_bottom) && (address < plt_top)) { // disassemble instruction uint8_t * data = &(elf32->data[address - elf32_base_address(elf32)]); ud_t ud_obj; ud_init(&ud_obj); ud_set_mode (&ud_obj, 32); ud_set_input_buffer(&ud_obj, data, 0x20); ud_disassemble(&ud_obj); if ( (ud_obj.mnemonic == UD_Ijmp) && (udis86_sign_extend_lval(&(ud_obj.operand[0])) != -1)) { uint64_t target = udis86_sign_extend_lval(&(ud_obj.operand[0])); const char * name = elf32_rel_name_by_address(elf32, target); if (name != NULL) { char plttmp[256]; snprintf(plttmp, 256, "%s@plt", name); struct _label * label; label = label_create(address, plttmp, LABEL_FUNCTION); return label; } } } // look for a symbol const char * name = elf32_sym_name_by_address(elf32, address); // no symbol if ((name == NULL) || (strcmp(name, "") == 0)) { char tmp[128]; snprintf(tmp, 128, "fun_%llx", (unsigned long long) address); name = tmp; } // symbol exists struct _label * label = label_create(address, name, LABEL_FUNCTION); return label; }
DWORD DasmOp(LPVOID addr) { ud_init(&ud_obj); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_hook(&ud_obj, DasmInputHookEIP); dasmAddr = (LPBYTE) addr; return (DWORD) ud_disassemble(&ud_obj); }
/* * In this pass, we are fixing the edges from jmp-like instructions and their * targets */ void x8664_graph_1 (struct _graph * graph, uint64_t address) { struct _graph_it * it; ud_t ud_obj; for (it = graph_iterator(graph); it != NULL; it = graph_it_next(it)) { struct _list * ins_list = graph_it_data(it); struct _ins * ins = list_first(ins_list); ud_init (&ud_obj); ud_set_mode (&ud_obj, 64); ud_set_input_buffer(&ud_obj, ins->bytes, ins->size); ud_disassemble(&ud_obj); struct ud_operand * operand; switch (ud_obj.mnemonic) { case UD_Ijmp : 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 : operand = &(ud_obj.operand[0]); if (operand->type != UD_OP_JIMM) break; uint64_t head = graph_it_index(it); uint64_t tail = head + ud_insn_len(&ud_obj) + udis86_sign_extend_lval(operand); int type = INS_EDGE_JCC_TRUE; if (ud_obj.mnemonic == UD_Ijmp) type = INS_EDGE_JUMP; struct _ins_edge * ins_edge = ins_edge_create(type); graph_add_edge(graph, head, tail, ins_edge); object_delete(ins_edge); break; default : break; } } }
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"; } }
/* * 参数: * pMem:被保护程序的文件映射 * pProcFileAddress:函数的文件地址 * ofProcMemRVA:函数的RVA * iProcSize:函数的长度 * pProtectInstructions:要加密的指令 * iProtectInstCount:要保护指令的个数 * pPowerProtecterEncryptInstruction:加密指令结构的指针(写入点) * pPowerProtecterEncryptProcedure:加密函数的结构的指针(写入点) * * 介绍: * 加密指定的函数函数 */ __INLINE__ __integer __INTERNAL_FUNC__ PowerProtectProcedure(__memory pMem, __memory pProcFileAddress, __offset ofProcMemRVA, __integer iProcSize, \ PPOWER_PROTECTER_INSTRUCTION pProtectInstructions, __integer iProtectInstCount, PPOWER_PROTECTER_ENCRYPT_INSTRUCTION pPowerProtecterEncryptInstruction, \ PPOWER_PROTECTER_ENCRYPT_PROCEDURE pPowerProtecterEncryptProcedure) { __integer iFlowInstCount = 0; __integer iInstLength = 0; __offset ofOffset = 0; __memory pCurr = NULL; __offset ofCurrMemRVA = 0; PPOWER_PROTECTER_ENCRYPT_INSTRUCTION pEncryptInstruction = NULL; PPOWER_PROTECTER_INSTRUCTION pNowProtectInstruction = NULL; ud_t ud_obj = {0}; pCurr = pProcFileAddress; ofCurrMemRVA = ofProcMemRVA; pEncryptInstruction = pPowerProtecterEncryptInstruction; ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, pProcFileAddress, iProcSize); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); while (ud_disassemble(&ud_obj)) { iInstLength = ud_obj.inp_ctr;//指令长度 // 如果是其他指令则判断是否在保护范围内区域 pNowProtectInstruction = ThisInstructionIsNeedProtect(ofCurrMemRVA, pProtectInstructions, iProtectInstCount); if (pNowProtectInstruction) { /* * 如果是用户指定的保护指令 */ PowerProtectThisInstruction(pMem, &ud_obj, ofCurrMemRVA, iProcSize, pNowProtectInstruction, pEncryptInstruction); pEncryptInstruction++;//移动到下一个加密指令结构 } else if (IsFlowInstructionByOffset(&ud_obj) != PPFT_NONE) { /* * 如果是流程指令则必进行保护 */ POWER_PROTECTER_INSTRUCTION PowerProtecterInstruction = {0}; PowerProtecterInstruction.bWatched = FALSE; PowerProtecterInstruction.Instruction.ofMemRVA = ofCurrMemRVA; PowerProtecterInstruction.Instruction.iSize = iInstLength; pNowProtectInstruction = &PowerProtecterInstruction; PowerProtectThisInstruction(pMem, &ud_obj, ofCurrMemRVA, iProcSize, pNowProtectInstruction, pEncryptInstruction); pEncryptInstruction++;//移动到下一个加密指令结构 iFlowInstCount++; } // 记录相关信息 ofOffset += iInstLength; pCurr += iInstLength; ofCurrMemRVA += iInstLength; } return iFlowInstCount; }
// if oldtree is not NULL, will continue adding to the oldtree. This has the // advantage of improving the finding the correct sizes of functions called from // previous calls of analyze_find_functions _aatree * analyze_find_functions (unsigned char * data, int data_size, int mode, uint_t * address, _aatree * old_tree) { int_t offset; int bytes_disassembled = 0; int_t tmp_address_signed; int_t base_address_signed; uint_t last_address_end; ud_t ud_obj; struct _analyze_function analyze_function; _aatree * tree; if (old_tree == NULL) tree = aatree_create(analyze_function_cmp, sizeof(analyze_function)); else tree = old_tree; // find the start of all functions ud_init(&ud_obj); ud_set_mode(&ud_obj, mode); ud_set_input_buffer(&ud_obj, data, data_size); int_t_uint_t(&base_address_signed, address); while (ud_disassemble(&ud_obj)) { bytes_disassembled += ud_insn_len(&ud_obj); if ( (ud_obj.mnemonic == UD_Icall) && (ud_obj.operand[0].type == UD_OP_JIMM)) { switch (ud_obj.operand[0].size) { case 32 : int_t_32_set(&offset, ud_obj.operand[0].lval.udword); break; case 64 : int_t_64_set(&offset, ud_obj.operand[0].lval.uqword); break; } int_t_set(&tmp_address_signed, &base_address_signed); int_t_add(&tmp_address_signed, &offset); int_t_add_int(&tmp_address_signed, bytes_disassembled); uint_t_int_t(&(analyze_function.address), &tmp_address_signed); analyze_function.size = -1; aatree_insert(tree, &analyze_function); } } uint_t_set(&last_address_end, address); uint_t_add_int(&last_address_end, data_size); tree = analyze_find_functions_sizes(tree, &last_address_end); return tree; }
int lt_tracer_new (lua_State * L) { ud_t * ud_obj; ud_obj = lua_newuserdata(L, sizeof(ud_t)); luaL_getmetatable(L, "ludis86.ud_t"); lua_setmetatable(L, -2); ud_init(ud_obj); return 1; }
// 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; }
/* * 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() { uint8_t raw[] = { 0xf0, 0x66, 0x36, 0x67, 0x65, 0x66, 0xf3, 0x67, 0xda }; uint8_t len = 9; ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 16); ud_set_input_buffer(&ud_obj, raw, len); ud_set_syntax(&ud_obj, UD_SYN_INTEL); if (ud_disassemble(&ud_obj) != 0) { return 0; } return 1; }
int test() { uint8_t raw[] = { 0xf0, 0x66, 0x36, 0x67, 0x65, 0x66, 0xf3, 0x67, 0xda }; uint8_t len = 9; ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 16); ud_set_input_buffer(&ud_obj, raw, len); ud_set_syntax(&ud_obj, UD_SYN_INTEL); // if (ud_disassemble(&ud_obj) != 0) { // fprintf(stdout,"%s",ud_insn_asm(&ud_obj)); // } return 0; }
int x86_prologue(u8 *code, u64 *ninstr, int *eaten, s8 *instr, int *count, u8 *sizes) { assert(!(*count)); assert(!(*eaten)); int total = 0, index = 0, remains = 5; // a JMP instruction takes 5 bytes ud_t ud_obj; ud_init(&ud_obj); ud_set_mode(&ud_obj, 64); ud_set_input_buffer(&ud_obj, code, 64); while (remains > 0) { if (!ud_disassemble(&ud_obj)) return -1; int eaten = ud_insn_len(&ud_obj); remains -= eaten; total += eaten; if (sizes) sizes[index] = eaten; index += 1; if (count) *count = index; } if (eaten) *eaten = total; if (instr) { if ((total < BRANCH_SIZE)) { memset(instr, I_NOP /* NOP */, BRANCH_SIZE); memcpy(instr, code, total); } else { return -1; } } // save last 3 bytes of first 64bits of codre we'll replace u64 head = *((u64*)code); head = bswap64(head); // back to memory representation head &= 0x0000000000FFFFFFLL; // keep only last 3 instructions bytes, first 5 will be replaced by JMP instr *ninstr &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes *ninstr |= (head & 0x0000000000FFFFFFLL); // set last 3 bytes return 0; }
uintptr_t next_opcode(uintptr_t address, uint8_t opcode, size_t length) { ud_t ud_obj; ud_init(&ud_obj, 32); ud_set_input_buffer(&ud_obj, (uint8_t*)address, (size_t)-1); size_t size = 0; do { size = ud_decode(&ud_obj); if ((size == length) && (*(uint8_t*)address == opcode)) break; address += size; } while (size); return address; }
bool MDBCode::isCallInstruction(uintptr_t address) { char buffer[32]; if (debugger->read(buffer, address, sizeof(buffer)) != sizeof(buffer)) { log.traceLn("Cannot read instruction memory."); } ud_t insn; ud_init(&insn); ud_set_input_buffer(&insn, (uint8_t*)buffer, 32); ud_set_mode(&insn, 32); ud_set_syntax(&insn, UD_SYN_INTEL); size_t length = ud_disassemble(&insn); log.traceLn("Instruction at 0x%X is %d bytes long.", address, length); return insn.mnemonic == UD_Icall; }