Esempio n. 1
0
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;
}
Esempio n. 2
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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));
}
Esempio n. 5
0
/*
* 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;
        }
    }
}
Esempio n. 6
0
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));
}
Esempio n. 7
0
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;
}
Esempio n. 8
0
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;
}
Esempio n. 10
0
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);
}
Esempio n. 11
0
/* =============================================================================
 * 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);
}
Esempio n. 12
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;
}
Esempio n. 13
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;
}
Esempio n. 14
0
/* =============================================================================
 * 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;
}
Esempio n. 15
0
/* =============================================================================
 * 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;
}
Esempio n. 16
0
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;
}
Esempio n. 17
0
// 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, &regfile);
  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;
}
Esempio n. 18
0
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;
}
Esempio n. 19
0
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;
}
Esempio n. 20
0
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, &regs);

	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, &regs, 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;
}
Esempio n. 21
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;
  }
Esempio n. 22
0
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;
}
Esempio n. 23
0
File: x86.c Progetto: TDKPS/rdis2
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;
}
Esempio n. 24
0
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;
}
Esempio n. 25
0
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;
    }
}
Esempio n. 26
0
/*
* 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;
    }
}
Esempio n. 27
0
/*
 * 进行分区处理
 * 以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;
}