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; }
/* * 预读分析阶段,在分区处理是时进行,数据与代码区域 * 范围的界定,纯数据区域返回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_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; }
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)); }
/* * 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; } } }
int emulate_intn(ud_t *disasm) { struct ud_operand *op = &disasm->operand[0]; if(op->type != UD_OP_IMM) { debug(EMU_INSN, "intN bad operand\n"); return VM_FAIL; } return emulate_interrupt(op->lval.ubyte, ud_insn_len(disasm)); }
int ludis86_ud_insn_ptr (lua_State * L) { ud_t * ud_obj; ud_obj = ludis86_check_ud_t(L, 1); lua_pop(L, 1); lua_pushlstring(L, ud_insn_ptr(ud_obj), ud_insn_len(ud_obj)); return 1; }
int ludis86_ud_insn_len (lua_State * L) { ud_t * ud_obj; ud_obj = ludis86_check_ud_t(L, 1); lua_pop(L, 1); lua_pushinteger(L, ud_insn_len(ud_obj)); return 1; }
// 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 emulate() { int rc; size_t sz; if(!disassemble(&info->vm.cpu.disasm)) return VM_FAIL; rc = emulate_insn(&info->vm.cpu.disasm); sz = ud_insn_len(&info->vm.cpu.disasm); return emulate_done(rc, sz); }
/* ============================================================================= * ud_disassemble() - disassembles one instruction and returns the number of * bytes disassembled. A zero means end of disassembly. * ============================================================================= */ extern unsigned int ud_disassemble(struct ud* u) { if (ud_input_end(u)) return 0; u->asm_buf[0] = 0; if (ud_decode(u) == 0) return 0; if (u->translator) u->translator(u); return ud_insn_len(u); }
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; }
/* * 使用JMP指令进行鉴别 * 如果是纯数据区返回TRUE,反之返回FALSE */ __INLINE__ __bool __INTERNAL_FUNC__ AbyssAnalyze(__memory pMem, __address ImageBase, __memory pCurr, __integer iSize) { __address addrStartAddress = ImageBase + AnalyzerRaw2Rva(pMem, (__integer)(pCurr - pMem)); __offset ofOffset = 0; PX86INSTRUCTION pInstruction = NULL, pPrevInstruction = NULL, *pCurrInstructionPoint = &pInstruction; 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)) { __address addrCurrentAddress = addrStartAddress + ofOffset; *pCurrInstructionPoint = __logic_new__(X86INSTRUCTION, 1); __logic_memset__((*pCurrInstructionPoint), 0, sizeof(X86INSTRUCTION)); (*pCurrInstructionPoint)->addrCurrMemoryAddress = addrCurrentAddress; (*pCurrInstructionPoint)->addrMemoryBlockStart = addrStartAddress; (*pCurrInstructionPoint)->iBlockSize = iSize; (*pCurrInstructionPoint)->pMem = pMem; __logic_memcpy__(&((*pCurrInstructionPoint)->ud_obj), &ud_obj, sizeof(ud_t)); (*pCurrInstructionPoint)->pPrev = pPrevInstruction;//设置上层指令 (*pCurrInstructionPoint)->pNext = NULL; // 执行分析 InstructionDispatcher(g_pAnalyzeDataDispatcher, *pCurrInstructionPoint); if ((*pCurrInstructionPoint)->bErrorLogicInstruction) {//如果遇到逻辑错误指令则直接退出 ReleaseInstructionList(&pInstruction); return TRUE; } // 链接链表 if (pPrevInstruction) pPrevInstruction->pNext = (*pCurrInstructionPoint); pPrevInstruction = (*pCurrInstructionPoint); pCurrInstructionPoint = &((*pCurrInstructionPoint)->pNext);//下一个节点 ofOffset += (__integer)ud_insn_len(&ud_obj); }/* end while */ /* * 如果没有错误指令,则进入更加深入的分析流程 */ // 释放指令链表 ReleaseInstructionList(&pInstruction); return FALSE; }
/* ============================================================================= * ud_insn_hex() - Returns hex form of disassembled instruction. * ============================================================================= */ const char* ud_insn_hex(struct ud* u) { u->insn_hexcode[0] = 0; if (!u->error) { unsigned int i; const unsigned char *src_ptr = ud_insn_ptr(u); char* src_hex; src_hex = (char*) u->insn_hexcode; /* for each byte used to decode instruction */ for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; ++i, ++src_ptr) { sprintf(src_hex, "%02x", *src_ptr & 0xFF); src_hex += 2; } } return u->insn_hexcode; }
/* ============================================================================= * ud_insn_oct() - Returns octal form of disassembled instruction. * ============================================================================= */ const char* ud_insn_oct(struct ud* u) { u->insn_octcode[0] = 0; if (!u->error) { unsigned int i; const unsigned char *src_ptr = ud_insn_ptr(u); char* src_oct; src_oct = (char*) u->insn_octcode; /* for each byte used to decode instruction */ for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_octcode) / 4; ++i, ++src_ptr) { sprintf(src_oct, (i > 0 ? " %03o" : "%03o"), *src_ptr & 0xFF); src_oct += (i > 0 ? 4 : 3); } } return u->insn_octcode; }
static int dbg_hard_stp_event_fast_syscall(int tf) { int rc; size_t sz; dbg_hard_stp_restore_context(); sz = ud_insn_len(&info->vm.cpu.disasm); rc = emulate_done(emulate_insn(&info->vm.cpu.disasm), sz); info->vm.cpu.emu_sts = EMU_STS_AVL; /* stealth for db_pending() */ dbg_hard_stp_setup_context(); if(rc == VM_DONE_LET_RIP) { __rflags.tf = tf; __post_access(__rflags); } return rc; }
// 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; }
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; }
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; }
int check_status(int pid) { static int eip_range_size = 1024 - 1; static unsigned long eip_range = 0; ud_t ud_obj; unsigned char buff[16]; struct user_regs_struct regs; int i, len; ptrace(PTRACE_GETREGS, pid, 0, ®s); if(eip_range == 0) eip_range = regs.eip - 1; read_data(pid, regs.eip, buff, 16); ud_init(&ud_obj); ud_set_input_buffer(&ud_obj, buff, sizeof(buff)); ud_set_mode(&ud_obj, 32); ud_set_syntax(&ud_obj, UD_SYN_INTEL); if(!ud_disassemble(&ud_obj)) return -1; len = ud_insn_len(&ud_obj); printf("eax=%08lx, ecx=%08lx, edx=%08lx, ebx=%08lx\n", regs.eax, regs.ecx, regs.edx, regs.ebx); printf("esi=%08lx, edi=%08lx, esp=%08lx, ebp=%08lx\n", regs.esi, regs.edi, regs.esp, regs.ebp); printf("eip=%08lx, eflags=%08lx\n", regs.eip, regs.eflags); printf("\n"); printf("eip: "); for(i=0; i < len; i++) printf("%02x ", buff[i]); printf("( %s )\n", ud_insn_asm(&ud_obj)); printf("\n"); // check system call if(check_int80h(buff) || check_sysenter(buff)){ char str[64]; if(check_sys_write(pid, ®s, str, sizeof(str))){ printf("output:\n"); printf("%s", str); if(strcmp(str, "HelloASM") == 0){ printf("\nPassword: MagicaMadoca\n"); } } return -1; } // found int3 if(check_int3(buff)) return -1; // out of mem range if(regs.eip < eip_range || (eip_range + eip_range_size) < regs.eip) return -1; // found 0x00 if(check_00(buff, len)) return -1; return 0; }
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; }
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; }
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; }
void x8664_functions_r (struct _map * functions, struct _tree * disassembled, uint64_t address, struct _map * memory) { ud_t ud_obj; int continue_disassembling = 1; struct _buffer * buffer = map_fetch_max(memory, address); if (buffer == NULL) return; uint64_t base_address = map_fetch_max_key(memory, address); if (base_address + buffer->size < address) return; uint64_t offset = address - base_address; ud_init (&ud_obj); ud_set_mode (&ud_obj, 64); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, &(buffer->bytes[offset]), buffer->size - offset); while (continue_disassembling == 1) { size_t bytes_disassembled = ud_disassemble(&ud_obj); if (bytes_disassembled == 0) { break; } if ( (ud_obj.mnemonic == UD_Icall) && (ud_obj.operand[0].type == UD_OP_JIMM)) { uint64_t target_addr = address + ud_insn_len(&ud_obj) + udis86_sign_extend_lval(&(ud_obj.operand[0])); if (map_fetch(functions, target_addr) == NULL) { struct _function * function = function_create(target_addr); map_insert(functions, target_addr, function); object_delete(function); } } struct _index * index = index_create(address); if (tree_fetch(disassembled, index) != NULL) { object_delete(index); return; } tree_insert(disassembled, index); object_delete(index); // these mnemonics cause us to continue disassembly somewhere else struct ud_operand * operand; 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_Ijmp : case UD_Iloop : case UD_Icall : operand = &(ud_obj.operand[0]); if (operand->type == UD_OP_JIMM) { x8664_functions_r(functions, disassembled, address + ud_insn_len(&ud_obj) + udis86_sign_extend_lval(operand), memory); } break; default : break; } // these mnemonics cause disassembly to stop switch (ud_obj.mnemonic) { case UD_Iret : case UD_Ihlt : case UD_Ijmp : continue_disassembling = 0; break; default : break; } address += bytes_disassembled; } }
/* * This is the initial phase, used to populate the graph with all reachable * nodes. We will worry about fixing edges from jmp-like mnemonics later. */ void x8664_graph_0 (struct _graph * graph, uint64_t address, struct _map * memory) { ud_t ud_obj; int continue_disassembling = 1; uint64_t last_address = -1; int edge_type = INS_EDGE_NORMAL; struct _buffer * buffer = map_fetch_max(memory, address); if (buffer == NULL) return; uint64_t base_address = map_fetch_max_key(memory, address); if (base_address + buffer->size < address) return; uint64_t offset = address - base_address; ud_init (&ud_obj); ud_set_mode (&ud_obj, 64); ud_set_syntax(&ud_obj, UD_SYN_INTEL); ud_set_input_buffer(&ud_obj, &(buffer->bytes[offset]), buffer->size - offset); while (continue_disassembling == 1) { size_t bytes_disassembled = ud_disassemble(&ud_obj); if (bytes_disassembled == 0) { break; } // even if we have already added this node, make sure we add the edge // from the preceeding node, in case this node was added from a jump // previously. otherwise we won't have an edge from its preceeding // instruction if (graph_fetch_node(graph, address) != NULL) { if (last_address != -1) { // not concerned if this call fails struct _ins_edge * ins_edge = ins_edge_create(edge_type); graph_add_edge(graph, last_address, address, ins_edge); object_delete(ins_edge); } break; } // create graph node for this instruction struct _ins * ins = x8664_ins(address, &ud_obj); struct _list * ins_list = list_create(); list_append(ins_list, ins); graph_add_node(graph, address, ins_list); object_delete(ins_list); object_delete(ins); // add edge from previous instruction to this instruction if (last_address != -1) { struct _ins_edge * ins_edge = ins_edge_create(edge_type); graph_add_edge(graph, last_address, address, ins_edge); object_delete(ins_edge); } // these mnemonics cause us to continue disassembly somewhere else struct ud_operand * operand; 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_Ijmp : case UD_Iloop : //case UD_Icall : operand = &(ud_obj.operand[0]); if (operand->type != UD_OP_JIMM) break; if (ud_obj.mnemonic == UD_Icall) edge_type = INS_EDGE_NORMAL; else if (ud_obj.mnemonic == UD_Ijmp) edge_type = INS_EDGE_NORMAL; // not important, will terminate else edge_type = INS_EDGE_JCC_FALSE; if (operand->type == UD_OP_JIMM) { x8664_graph_0(graph, address + ud_insn_len(&ud_obj) + udis86_sign_extend_lval(operand), memory); } break; default : edge_type = INS_EDGE_NORMAL; break; } // these mnemonics cause disassembly to stop switch (ud_obj.mnemonic) { case UD_Iret : case UD_Ihlt : case UD_Ijmp : continue_disassembling = 0; break; default : break; } last_address = address; address += bytes_disassembled; } }
/* * 进行分区处理 * 以NOP,INT3,0,无效指令编码字符进行分区标志 * 遇到NOP或者INT3,0,无效指令编码则将扫描过的区域 * 作为一个区块摘出,继续查询,如果其后的数据有很长 * 一段为连续的 NOP,INT3,0字节则将此视做绝对无效区域, * 在扫描过程中,如果遇到无效指令直接忽略当作这个区域 * 的一部分如果遇到有效指令,则进入预分析阶段,尝试向前 * 分析如果分析的指令长度小于最小代码长度则直接忽略.如果 * 大于则将此区域继续分析,往返以上流程.直到完毕 */ __INLINE__ PPROCEDURE __INTERNAL_FUNC__ FormatBlock(__memory pMem, __address ImageBase, __memory pStart, __integer iSize, PANALYZE_CONFIGURE pAnalyzeConfigure) { __integer iBlockEndSignCount = 0; __offset ofOffset = 0; PPROCEDURE pBlock = NULL; PPROCEDURE *pCurrBlockPoint = &pBlock; 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, pStart, 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))) iBlockEndSignCount += (__integer)ud_insn_len(&ud_obj); else { /* * 遇到有效指令了 * 现在该进入预读分析阶段,这里还有一个判断 * 标志是剩余长度,如果其后的长度小于最小代码 * 长度直接将这段代码视作为数据 */ __integer iRemainSize = iSize - (__integer)ofOffset; __memory pCurr = pStart + (__integer)ofOffset; if (iRemainSize >= pAnalyzeConfigure->bCodeMixSize) { /* * 进入预读分析阶段 * 在这里开始判断,如果预读处理分析的结果为单纯的数据块则 * 与先前分析的区域进行合并 * 否则单独为前面分析的块分配内存 */ __integer iOutSize = 0; if (PredictBlockEnd(pMem, ImageBase, pCurr, iRemainSize, &iOutSize, pAnalyzeConfigure)) iBlockEndSignCount += iOutSize;//进行合并 else { /* * 判断上一组区块标记是否为0如果不为则分配空间存储它 */ if (iBlockEndSignCount) { (*pCurrBlockPoint) = __logic_new__(PROCEDURE, 1); __logic_memset__((*pCurrBlockPoint), 0, sizeof(PROCEDURE)); (*pCurrBlockPoint)->bBlock = TRUE;//数据区域 (*pCurrBlockPoint)->pFileStartAddress = pCurr - iBlockEndSignCount; (*pCurrBlockPoint)->addrMemoryStartAddress = ImageBase + AnalyzerRaw2Rva(pMem, (__integer)((*pCurrBlockPoint)->pFileStartAddress - pMem)); (*pCurrBlockPoint)->iSize = iBlockEndSignCount; pCurrBlockPoint = &((*pCurrBlockPoint)->pNext); iBlockEndSignCount = 0;//清空标志记录计数 } // 设定此段为代码区域 (*pCurrBlockPoint) = __logic_new__(PROCEDURE, 1); __logic_memset__((*pCurrBlockPoint), 0, sizeof(PROCEDURE)); (*pCurrBlockPoint)->bBlock = FALSE;//代码区域 (*pCurrBlockPoint)->pFileStartAddress = pCurr; (*pCurrBlockPoint)->addrMemoryStartAddress = ImageBase + AnalyzerRaw2Rva(pMem, (__integer)(pCurr - pMem)); (*pCurrBlockPoint)->iSize = iOutSize; pCurrBlockPoint = &((*pCurrBlockPoint)->pNext); } // 重新设定反汇编指针 pCurr += iOutSize; (__integer)ofOffset += iOutSize; iRemainSize -= iOutSize;//剩余长度 ud_set_input_buffer(&ud_obj, pCurr, iRemainSize); continue; } else { // 进入到这里就是进入到分析的末尾 (*pCurrBlockPoint) = __logic_new__(PROCEDURE, 1); __logic_memset__((*pCurrBlockPoint), 0, sizeof(PROCEDURE)); (*pCurrBlockPoint)->bBlock = TRUE;//表示有可能是数据 iBlockEndSignCount += iRemainSize; (*pCurrBlockPoint)->iSize = iBlockEndSignCount; (*pCurrBlockPoint)->pFileStartAddress = pCurr; (*pCurrBlockPoint)->addrMemoryStartAddress = ImageBase + AnalyzerRaw2Rva(pMem, (__integer)(pCurr - pMem)); pCurrBlockPoint = &((*pCurrBlockPoint)->pNext); iBlockEndSignCount = 0;//清空标志记录计数 } } (__integer)ofOffset += ud_insn_len(&ud_obj); } /* * 处理组后一个纯区域块 * 两种情况造成这种现象 * 1) 整个分析的数据都是纯数据区 * 2) 被分析的数据最后一个区域是纯数据区 */ if (iBlockEndSignCount) { __memory pBlockZoon = NULL; // 第一种情况 if (iBlockEndSignCount == iSize) pBlockZoon = pStart; else pBlockZoon = pStart + iSize - iBlockEndSignCount; (*pCurrBlockPoint) = __logic_new__(PROCEDURE, 1); __logic_memset__((*pCurrBlockPoint), 0, sizeof(PROCEDURE)); (*pCurrBlockPoint)->bBlock = TRUE;//表示有可能是数据 (*pCurrBlockPoint)->iSize = iBlockEndSignCount; (*pCurrBlockPoint)->pFileStartAddress = pBlockZoon; (*pCurrBlockPoint)->addrMemoryStartAddress = ImageBase + AnalyzerRaw2Rva(pMem, (__integer)(pBlockZoon - pMem)); pCurrBlockPoint = &((*pCurrBlockPoint)->pNext); iBlockEndSignCount = 0;//清空标志记录计数 } return pBlock; }