Example #1
0
static const char *disassemble(unsigned char *insn, int len, uint64_t rip,
			       int cr0_pe, int eflags_vm,
			       int cs_d, int cs_l)
{
	int mode;

	if (!cr0_pe)
		mode = 16;
	else if (eflags_vm)
		mode = 16;
	else if (cs_l)
		mode = 64;
	else if (cs_d)
		mode = 32;
	else
		mode = 16;

	ud_set_pc(&ud, rip);
	ud_set_mode(&ud, mode);
	ud_set_input_buffer(&ud, insn, len);
	ud_disassemble(&ud);
	return ud_insn_asm(&ud);
}
Example #2
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;
}
Example #3
0
/*
 * 如果是纯数据区域直接返回TRUE,反之返回FALSE
 */
__INLINE__ __bool __INTERNAL_FUNC__ DeepAnalyzeBlock(__memory pMem, __address ImageBase, __memory pCurr, __integer iSize, PANALYZE_CONFIGURE pAnalyzeConfigure) {
	__bool bBlock = FALSE;
	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_Iinvalid) && (!(pAnalyzeConfigure->bDisInvalidOpcodeIsData))) {
			bBlock = TRUE;
			return bBlock;
		}
	}

	/*
	 * 进行深度分析
	 */
	bBlock = AbyssAnalyze(pMem, ImageBase, pCurr, iSize);

	return bBlock;
}
bool tryToDisassemble(const MacroAssemblerCodePtr& codePtr, size_t size, const char* prefix, PrintStream& out)
{
    ud_t disassembler;
    ud_init(&disassembler);
    ud_set_input_buffer(&disassembler, static_cast<unsigned char*>(codePtr.executableAddress()), size);
#if CPU(X86_64)
    ud_set_mode(&disassembler, 64);
#else
    ud_set_mode(&disassembler, 32);
#endif
    ud_set_pc(&disassembler, bitwise_cast<uintptr_t>(codePtr.executableAddress()));
    ud_set_syntax(&disassembler, UD_SYN_ATT);
    
    uint64_t currentPC = disassembler.pc;
    while (ud_disassemble(&disassembler)) {
        char pcString[20];
        print(pcString, sizeof(pcString), currentPC);
        out.printf("%s%16s: %s\n", prefix, pcString, ud_insn_asm(&disassembler));
        currentPC = disassembler.pc;
    }
    
    return true;
}
Example #5
0
MDBCodeRegion *
MDBCodeRegion::fromProcedure(MDBDebugger *debugger, uintptr_t address) {
    size_t bufferSize = 128;
    char buffer[bufferSize]; 
    
    if (debugger->read(buffer, address, sizeof(buffer)) != (int) sizeof(buffer)) {
        log.traceLn("Cannot read procedure memory.");
    }
    
    ud_t ud_obj;
    ud_init(&ud_obj); 
    ud_set_input_buffer(&ud_obj, (uint8_t*)buffer, bufferSize);
    ud_set_mode(&ud_obj, 32);
    ud_set_syntax(&ud_obj, UD_SYN_INTEL);
    
    size_t remaining = bufferSize;
    do {
        int pc = ud_obj.pc;
        size_t instructionSize = ud_disassemble(&ud_obj);
        remaining -= instructionSize;
        log.traceLn("decoded: 0x%llx %s", pc, ud_insn_asm(&ud_obj));
    } while (remaining > 0);
    return NULL;
}
Example #6
0
//--------------------------------------------------------------------------------------
PVOID Hook(PVOID Function, PVOID Handler, PULONG pBytesPatched)
{  
#ifdef _X86_

#define SIZEOFJUMP 6

#elif _AMD64_

#define SIZEOFJUMP 14

#endif

    ULONG Size = 0, CollectedSpace = 0;
    PUCHAR pInst = (PUCHAR)Function;

    if (pBytesPatched)
    {
        *pBytesPatched = NULL;
    }

    // initialize disassembler engine
    ud_t ud_obj;
    ud_init(&ud_obj);

    // set mode, syntax and vendor
    ud_set_mode(&ud_obj, UD_MODE);
    ud_set_syntax(&ud_obj, UD_SYN_INTEL);
    ud_set_vendor(&ud_obj, UD_VENDOR_INTEL);

    while (CollectedSpace < SIZEOFJUMP)
    {
        ud_set_input_buffer(&ud_obj, pInst, MAX_INST_LEN);

        // get length of instruction
        ULONG dwInstLen = ud_disassemble(&ud_obj);
        if (dwInstLen == 0)
        {
            // error while disassembling instruction
            DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Can't disassemble instruction at "IFMT"\n", pInst);
            return NULL;
        }

        if (ud_obj.mnemonic == UD_Ijmp ||
            ud_obj.mnemonic == UD_Icall)
        {
            // call/jmp with relative address
            DbgMsg(__FILE__, __LINE__, __FUNCTION__"() call/jmp/jxx instruction at "IFMT"\n", pInst);
            return NULL;
        }

        for (int i = 0; i < 3; i++)
        {
            if (ud_obj.operand[i].type == UD_OP_JIMM)
            {
                // jxx with relative address
                DbgMsg(__FILE__, __LINE__, __FUNCTION__"() jxx instruction at "IFMT"\n", pInst);
                return NULL;
            }
        }

        pInst += dwInstLen;
        CollectedSpace += dwInstLen;

        if (ud_obj.mnemonic == UD_Iret  ||
            ud_obj.mnemonic == UD_Iretf ||
            ud_obj.mnemonic == UD_Iiretw   ||
            ud_obj.mnemonic == UD_Iiretq   ||
            ud_obj.mnemonic == UD_Iiretd)
        {
            // end of the function thunk?
            DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ret/retn/iret instruction at "IFMT"\n", pInst);
            break;
        }
    }

    if (SIZEOFJUMP > CollectedSpace)
    {
        DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: not enough memory for jump\n");
        return NULL;
    }

    ULONG CallGateSize = CollectedSpace + SIZEOFJUMP;

    // allocate memory for callgate
    PVOID CallGate = M_ALLOC(CallGateSize);
    if (CallGate)
    {
        // generate callgate
        memset(CallGate, 0x90, CallGateSize);    

        // save begining of the function
        memcpy(CallGate, Function, CollectedSpace);        
        
#ifdef _X86_

        // jump from callgate to function body
        // push imm32
        *(PUCHAR)((PUCHAR)CallGate + CollectedSpace) = 0x68;
        *(PUCHAR *)((PUCHAR)CallGate + CollectedSpace + 1) = (PUCHAR)Function + SIZEOFJUMP;
        // ret
        *(PUCHAR)((PUCHAR)CallGate + CollectedSpace + 5) = 0xC3;                            

#elif _AMD64_

        // jmp qword [addr]
        *(PUSHORT)((PUCHAR)CallGate + CollectedSpace) = 0x25FF;
        *(PULONG)((PUCHAR)CallGate + CollectedSpace + 2) = 0;
        // addr dq XXXh
        *(PULONGLONG)((PUCHAR)CallGate + CollectedSpace + 6) = (ULONGLONG)Function + SIZEOFJUMP;

#endif
       
        // jump from the function to callgate
        memset(Function, 0x90, CollectedSpace);        

#ifdef _X86_

        // push imm32
        *(PUCHAR)Function = 0x68;
        *(PUCHAR *)((PUCHAR)Function + 1) = (PUCHAR)Handler;
        // ret
        *(PUCHAR)((PUCHAR)Function + 5) = 0xC3;                            

#elif _AMD64_

        // jmp qword [addr]
        *(PUSHORT)Function = 0x25FF;
        *(PULONG)((PUCHAR)Function + 2) = 0;
        // addr dq XXXh
        *(PULONGLONG)((PUCHAR)Function + 6) = (ULONGLONG)Handler;

#endif            
        *pBytesPatched = CollectedSpace;

        return CallGate;
    }
    else
    {
        DbgMsg(__FILE__, __LINE__, "M_ALLOC() fails\n");
    }

    return NULL;
}
Example #7
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;
}
Example #8
0
AddressArray Analysis::analysis_code_piece_address(pCodeBufferInfo pinfo)
{
  ud_t ud_obj;
  ud_init(&ud_obj);

#ifndef PROTECT_X64
  ud_set_mode(&ud_obj,32);
#else
  ud_set_mode(&ud_obj,64);
#endif
  ud_set_pc(&ud_obj,pinfo->addr);
  ud_set_input_buffer(&ud_obj, (uint8_t*)pinfo->buf, pinfo->size);
  ud_set_syntax(&ud_obj,UD_SYN_INTEL);

  base = pinfo->addr;
  size = pinfo->size;
  
  std::vector <long> address_array;
  //pAssemblerTree root =  new AssemblerTree;
  //  pAssemblerTree nowtree = root;
  
  address_array.push_back(pinfo->addr);
  address_array.push_back(pinfo->addr + pinfo->size);
  while (ud_disassemble(&ud_obj) != 0)
  {
    //if (ud_obj.operand[0].type == UD_OP_JIMM || ud_obj.mnemonic == UD_Icall )//&& ud_obj.mnemonic != UD_Icall)
    if (ud_obj.pfx_rep != 0 || ud_obj.pfx_repe != 0 || ud_obj.pfx_repne != 0)   //有前缀
    {
      address_array.push_back(ud_obj.pc);
      address_array.push_back(ud_obj.insn_offset);
    }
    if (ud_obj.operand[0].type == UD_OP_JIMM )
    {

          long addr = ud_obj.operand[0].size == 8
            ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) :
            (ud_obj.operand[0].lval.sdword + ud_obj.pc);

      if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size)
      {
         address_array.push_back(addr);
         address_array.push_back(ud_obj.pc);        
      }
      else
      {
        //address_array.push_back(ud_obj.pc);
        if (ud_obj.mnemonic != UD_Icall && ud_obj.mnemonic != UD_Ijmp)
        {
          printf("%x:跳转的地址无法找到:",ud_obj.insn_offset);
          printf("%x\n",addr);
         // __asm("int3");         //表示跳转地址是一个jcc指令
        }
        else
        {
          address_array.push_back(ud_obj.pc);
        }
      }
    }
    if (ud_obj.mnemonic == UD_Iret || ud_obj.mnemonic == UD_Icall || ud_obj.mnemonic == UD_Ijmp)
    {
      address_array.push_back(ud_obj.pc);
    }
    /*if (ud_obj.mnemonic == UD_Icall || ud_obj.mnemonic == UD_Iret)
    {
      address_array.push_back(ud_obj.pc);
    }*/
  }
  long count = 0;
  
  size_t address_size = address_array.size();
  AddressArray a_array(address_size);  
  for (std::vector <long>::iterator iter = address_array.begin() ;
       iter != address_array.end() ; ++iter)
  {
    bool fk = true;
    for (int i = 0; i < count; ++i)
    {
      if (*iter == a_array[i])
      {
        fk = false;
      }
    }
    if (fk)
      a_array[count++] = *iter;
  }
  for (int i = 0; i < count; ++i)
  {
    for (int j = i; j < count ; ++j)
    {
      if (a_array[i] > a_array[j])
      {
        long t = a_array[i];
        a_array[i] = a_array[j];
        a_array[j] = t;
      }
    }
  }
  a_array.set_size(count); 
#ifdef DEBUG
  //printf("a_array size:%08x",a_array.get_size()); 
  for (int i = 0; i < count - 1; ++i)
  {
    
    printf("标签%x,分支地址:%08x - %08x\n",i,a_array[i],a_array[i+1]-1);
  }
//__asm ("int3");
#endif
  
  return a_array;
} 
Example #9
0
/*
 * 获取单个函数帧
 * 使用IsProcEnd函数鉴别末尾,不处理中间遇到的CALL指令
 */
__INLINE__ PPROCEDURE __INTERNAL_FUNC__ GetProcFrame(__memory pMem, __memory pStart, __integer iBlockMaxSize, PPROGRAM pParents) {
	PPROCEDURE pProcedure = InitProcedure(pParents);
	PX86INSTRUCTION pInstructionPrev = NULL, *pInstructionPoint = &(pProcedure->pInstruction);
	__address ImageBase = pParents->ImageBase;
	__offset ofOffset = 0;
	__integer iContinueSize = 0, iInstCount = 0;
	__bool bPredictProcEnd = FALSE;//是否启用预测函数结尾
	ud_t ud_obj;
	ud_init(&ud_obj);
	ud_set_mode(&ud_obj, 32);
	ud_set_input_buffer(&ud_obj, pStart, iBlockMaxSize);
	ud_set_syntax(&ud_obj, UD_SYN_INTEL);

	/*
	 * 预测结尾分析
	 * 可以在为遍历完指令流时,预先知道函数的末尾
	 */
	// 获取整个函数框架
	while (ud_disassemble(&ud_obj)) {
		__memory pCurrent = pStart + ofOffset;

		// 如果是未知指令,则记录它的数量
		if (ud_obj.mnemonic == UD_Iinvalid)
			(pProcedure->iInvalidOpcodeCount)++;

		*pInstructionPoint = InitInstruction(pProcedure, pInstructionPrev);
		AnalyzeInstructionPass1(&ud_obj, pMem, ImageBase, pCurrent, ofOffset, *pInstructionPoint);
		pInstructionPrev = *pInstructionPoint;

		// 判断是否到达函数末尾,常规分析
		if (IsProcEnd(&ud_obj, pProcedure->pInstruction, *pInstructionPoint, &bPredictProcEnd, &iContinueSize)) {
			ofOffset += ud_obj.inp_ctr;
			iInstCount++;
			goto _end_while;
		}

		/*
		 * 如果进入这里则说明当前指令必定是ret指令
		 */
		if (bPredictProcEnd) {
			// 将反汇编的缓冲区长度设置为
			// 从当前指令到预测出的函数结尾
			__memory pRetNextInstruction = (*pInstructionPoint)->pCurrFileAddress + ud_obj.inp_ctr;//得到ret指令下一条指令的位置
			ofOffset += ud_obj.inp_ctr;//将当前指令的长度加入偏移值内
			ud_set_input_buffer(&ud_obj, pRetNextInstruction, (size_t)iContinueSize);//ud_obj会重新初始化
			pInstructionPoint = &((*pInstructionPoint)->pNext);
			iInstCount++;
			bPredictProcEnd = FALSE;
			continue;//直接进入下一轮
		}

		// 移动指针
		pInstructionPoint = &((*pInstructionPoint)->pNext);
		ofOffset += ud_obj.inp_ctr;
		iInstCount++;
	}/* end while */
_end_while:

	// 填充函数基本信息
	pProcedure->addrMemoryStartAddress = pParents->ImageBase + AnalyzerRaw2Rva(pMem, (__integer)(pStart - pMem));
	pProcedure->pFileStartAddress = pStart;
	pProcedure->iSize = (__integer)ofOffset;
	pProcedure->iInstCount = iInstCount;
	pProcedure->pInstructionJmp = GetInstructionJmpListHeader(pProcedure);
	return pProcedure;
}
Example #10
0
void Analysis::disasm(pCodeBufferInfo pinfo,std::vector<CodePiece> & code)
{
    ud_t ud_obj;
    ud_init(&ud_obj);

#ifndef PROTECT_X64
    ud_set_mode(&ud_obj,32);
#else
    ud_set_mode(&ud_obj,64);
#endif
    ud_set_pc(&ud_obj,pinfo->addr);
    ud_set_input_buffer(&ud_obj, (uint8_t*)pinfo->buf, pinfo->size);
    ud_set_syntax(&ud_obj,UD_SYN_INTEL);

    base = pinfo->addr;
    size = pinfo->size;
    AddressArray a_array = analysis_code_piece_address(pinfo);

    int point = 0;
    const bool begin = true;
    const bool end = false;
    bool status = end;
    std::map<long,int> addr_id;

    set_label_address(pinfo,a_array,addr_id);
    CodePiece *piece = NULL;
    while (ud_disassemble(&ud_obj) != 0)
    {

        if (ud_obj.insn_offset == a_array[point] && status == end)
        {
            piece = new CodePiece;
            piece->set_label(point);
            point++;
            status = begin;
        }
        if (a_array.get_size() > point)
        {
            if (ud_obj.pc == a_array[point])
            {
                if (addr_id.find(ud_obj.pc) == addr_id.end()) //下条指令没有找到
                {
#ifdef DEBUG
                    printf("没有查找到数据,地址%08x\n",ud_obj.pc)  ;
#endif
                    //piece->set_jmplabel(PC_NONE);
                    if (ud_obj.mnemonic == UD_Iret)
                    {
                        //piece->set_jmplabel(PC_NONE);
                        piece->set_opcode_attribute(OPCODE_ATTRIBUTE_RET);
                    }
                    else if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp)
                    {
                        long addr = ud_obj.operand[0].size == 8
                                            ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) :
                                    (ud_obj.operand[0].lval.sdword + ud_obj.pc);
                        if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size
                                && ud_obj.operand[0].type == UD_OP_JIMM)
                        {
                            piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JMP);
                            piece->set_jmplabel(addr_id[addr]);
                        }
                        else
                        {
                           piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP);
                           if (ud_obj.operand[0].type == UD_OP_JIMM)
                               piece->set_jmplabel(addr);
                           else
                               piece->set_jmplabel(PC_NONE);

                        }
                    }
                    else if (ud_insn_mnemonic(&ud_obj) == UD_Icall)
                    {
                        long addr = ud_obj.operand[0].size == 8
                                            ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) :
                                    (ud_obj.operand[0].lval.sdword + ud_obj.pc);
                        //if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size &&
                        if (addr >= pinfo->addr && addr < pinfo->addr + pinfo->size &&
                                ud_obj.operand[0].type == UD_OP_JIMM)
                        {
                            piece->set_opcode_attribute(OPCODE_ATTRIBUTE_CALL);
                            piece->set_jmplabel(addr_id[addr]);
                        }
                        else
                        {
                           piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL);
                           if (ud_obj.operand[0].type == UD_OP_JIMM)
                               piece->set_jmplabel(addr);
                           else
                               piece->set_jmplabel(PC_NONE);
                        }
                    }
                    else
                    {
                        piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXIT);
                        piece->set_jmplabel(ud_obj.pc);
                    }
                }
                else
                {
                    if (ud_obj.operand[0].type == UD_OP_JIMM
                            || ud_obj.mnemonic == UD_Icall
                            || ud_obj.mnemonic == UD_Ijmp)//&& ud_obj.mnemonic != UD_Icall)
                    {
                        piece->set_is_jcc(ud_obj.mnemonic != UD_Icall &&
                                        ud_obj.mnemonic != UD_Iret &&
                                        ud_obj.mnemonic != UD_Ijmp);
                        if (ud_obj.operand[0].type == UD_OP_MEM
                                || ud_obj.operand[0].type == UD_OP_REG)
                        {
                            if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp)
                            {
                                piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP);
                            }
                            else if (ud_insn_mnemonic(&ud_obj) == UD_Icall)
                            {
                                piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL);
                            }
                            else
                            {
                               //piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC);
                            }
                            piece->set_jmplabel(PC_NONE);
                        }
                        else
                        {
                            long addr = ud_obj.operand[0].size == 8
                                            ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) :
                                    (ud_obj.operand[0].lval.sdword + ud_obj.pc);
                            if (addr >= pinfo->addr && addr < pinfo->addr + pinfo->size) //<=pinfo->addr + pinfo->size将导致跳转到最后一条指令的下一条还是在范围之内
                            {
                                if (addr_id.find(addr) == addr_id.end())
                                {
                                    printf("没有找到跳转地址:%08x\n",addr );
                                }
                                if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp)
                                {
                                   piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JMP);
                                   piece->set_jmplabel(addr_id[addr]);
                                }
                                else if (ud_insn_mnemonic(&ud_obj) == UD_Icall)
                                {
                                   piece->set_opcode_attribute(OPCODE_ATTRIBUTE_CALL);
                                   piece->set_jmplabel(addr);
                                }
                                else
                                {
                                   piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC);
                                   piece->set_jmplabel( addr_id[addr] );
                                }
                            }
                            else
                            {
                                if (ud_insn_mnemonic(&ud_obj) == UD_Ijmp)
                                {
                                   piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_JMP);
                                   //piece->set_jmplabel(addr_id[addr]);
                                }
                                else if (ud_insn_mnemonic(&ud_obj) == UD_Icall)
                                {
                                   piece->set_opcode_attribute(OPCODE_ATTRIBUTE_EXTERNAL_CALL);
                                   //piece->set_jmplabel(addr);
                                }
                                else
                                {
                                   //piece->set_opcode_attribute(OPCODE_ATTRIBUTE_JCC);
                                   printf("jcc不能跳转到虚拟机外部\n");
                                   //piece->set_jmplabel( addr_id[addr] );
                                }
                                piece->set_jmplabel(addr);
                            }
                        }
                    }
                    else
                    {
                        piece->set_jmplabel( addr_id[ud_obj.pc] );
                        piece->set_opcode_attribute(OPCODE_ATTRIBUTE_NORMAL);
                    }
                }
                if (ud_obj.mnemonic == UD_Iret)
                {
                    piece->set_jmplabel(PC_NONE);
                    piece->set_opcode_attribute(OPCODE_ATTRIBUTE_RET);
                    //piece->set_jmplabel(PC_RET);
                }
                piece->add_assemble(ud_obj);
                code.push_back(*piece);
                delete piece;
                piece = NULL;
                status = end;

            }
        }
        if (status == begin)
        {
            if (piece == NULL) {
                printf("没有为piece分配空间");
            }
            piece->add_assemble(ud_obj);
        }

    }
}
Example #11
0
pAssemblerTree Analysis::disasm(pCodeBufferInfo pinfo)
{
  std::vector<CodePiece> piece_test;
  disasm(pinfo,piece_test) ;
  for (std::vector<CodePiece>::iterator iter = piece_test.begin();
      iter != piece_test.end();iter++)
  {
    printf("\033[31m标签:%08x,\033[34m跳转到:%08x\033[0m,条件跳转:%d\n",iter->get_label(),iter->get_jmplabel(),iter->get_is_jcc());   
    for (std::list<ud_t>::iterator xiter = iter->get_piece().begin();
        xiter != iter->get_piece().end();xiter++)
    {
        printf("%s\n",xiter->insn_buffer);
    }
  }

  //__asm("int3");
  ud_t ud_obj;
  ud_init(&ud_obj);

#ifndef PROTECT_X64
  ud_set_mode(&ud_obj,32);
#else
  ud_set_mode(&ud_obj,64);
#endif
  ud_set_pc(&ud_obj,pinfo->addr);
  ud_set_input_buffer(&ud_obj, (uint8_t*)pinfo->buf, pinfo->size);
  ud_set_syntax(&ud_obj,UD_SYN_INTEL);

  base = pinfo->addr;
  size = pinfo->size;
  
  std::vector <long> address_array;
  //pAssemblerTree root =  new AssemblerTree;
  //  pAssemblerTree nowtree = root;
  std::vector <ud_t> ud_obj_array;
  address_array.push_back(pinfo->addr);
  address_array.push_back(pinfo->addr + pinfo->size);
  while (ud_disassemble(&ud_obj) != 0)
  {
    ud_obj_array.push_back(ud_obj);
    //    nowtree.asmpiect.push_back(ud_obj);
    if (ud_obj.operand[0].type == UD_OP_JIMM || ud_obj.mnemonic == UD_Icall )//&& ud_obj.mnemonic != UD_Icall)
    {
          long addr = ud_obj.operand[0].size == 8
            ? ((signed char)ud_obj.operand[0].lval.sbyte + ud_obj.pc) :
            (ud_obj.operand[0].lval.sdword + ud_obj.pc);
      if (addr >= pinfo->addr && addr <= pinfo->addr + pinfo->size)
      {
         address_array.push_back(addr);
         address_array.push_back(ud_obj.pc);        
      }
    }
  }

  long count = 0;
  long *a_array;
  size_t address_size = address_array.size();
  a_array = new long[address_size];
  for (std::vector <long>::iterator iter = address_array.begin() ;
       iter != address_array.end() ; ++iter)
  {
    bool fk = true;
    for (int i = 0; i < count; ++i)
    {
      if (*iter == a_array[i])
      {
        fk = false;
      }
    }
    if (fk)
      a_array[count++] = *iter;
  }
  for (int i = 0; i < count; ++i)
  {
    for (int j = i; j < count ; ++j)
    {
      if (a_array[i] > a_array[j])
      {
        long t = a_array[i];
        a_array[i] = a_array[j];
        a_array[j] = t;
      }
    }
  }

  for (int i = 0; i < count; ++i)
  {
    printf("%08x\r\n",a_array[i]);
  }
  int point = 0;
  pAssemblerTree nowtree = NULL;
  pAssemblerTree parent = NULL;
      const bool begin = true;
    const bool end = false;
    bool status = end;
  for (std::vector <ud_t>::iterator iter = ud_obj_array.begin();
       iter != ud_obj_array.end(); ++iter)
  {
    //typedef  true begin;
    //typedef false end;
    // ud_t *p = iter;
    ud_t ud = *iter;
    if (ud.insn_offset == a_array[point] && status == end)
    {
      point++;
      status = begin;
      nowtree = new AssemblerTree;
      root ? NULL : root = nowtree;
      nowtree->LeftChild = NULL;
      nowtree->RightChild = NULL;

      nowtree->id = point - 1;


      //      nowtree.asmpiect.push_back(ud);
    }
    if (nowtree)
    {
      nowtree->asmpiece.push_back(ud);
    }
    if (ud.pc == a_array[point] && status == begin)
    {
      nowtree->base = a_array[point-1];
      
      //point++;
      nowtree->size = ud.pc - a_array[point-1]; //代码块大小
      status = end;
      parent = add_tree(parent,nowtree,L);
      
      //nowtree = new AssemblerTree;
      //nowtree->LeftChild = NULL;
      //nowtree->RightChild = NULL;
    }
    nowtree->reloc_address = -1;    
    nowtree->next_instruction = ud.pc;   
  }
  block_count = point;
  link_tree();
#ifdef DEBUG
  show_tree(root,"false:");
#endif
  delete [] a_array;
  // show_tree(root);
  
  /*for (std::vector <long>::iterator iter = address_array.begin() ;
       iter != address_array.end() ; ++iter)
  {
    int addr = *iter;
    printf("%08x\r\n",addr);
    }*/
  return NULL;
}
Example #12
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;
}
Example #13
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:
		if (u.operand[0].type == UD_OP_REG) {
			op->type = R_ANAL_OP_TYPE_UJMP;
		} else {
			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;
}
Example #14
0
/**
 * Recursively generate code regions by statically analyzing machine code.
 */
bool
MDBCode::scanProcedure(uintptr_t address) {
    if (getRegion(address)) {
        log.traceLn("a region already exists");
        // A region already exists for this address.
        return true;
    }

    log.traceLn("scanning address %llx", address);
    
    size_t bufferSize = 1024 * 8;
    char buffer[bufferSize];
    
    if (debugger->read(buffer, address, sizeof(buffer)) != (int) sizeof(buffer)) {
        log.traceLn("Cannot read procedure memory.");
    }
    
    MBList<uintptr_t> callTargets;
    
    ud_t insn;
    ud_init(&insn); 
    ud_set_input_buffer(&insn, (uint8_t*)buffer, bufferSize);
    ud_set_mode(&insn, 32);
    ud_set_syntax(&insn, UD_SYN_INTEL);
    
    size_t remainingBytes = bufferSize;
    while (remainingBytes > 0) {
        int offset = insn.pc;
        size_t insnSize = ud_disassemble(&insn);
        remainingBytes -= insnSize;
        if (insnSize == 0) {
            error("cannot disassemble");
            break;
        }
        log.traceLn("decoded: 0x%-8llx 0x%-8llx %s",
            address + offset,
            offset,
            ud_insn_asm(&insn));
        switch (insn.mnemonic) {
            case UD_Icall: {
                uintptr_t target = 0;
                if (insn.operand[0].type == UD_OP_JIMM) {
                    if (insn.operand[0].size == 32) {
                        target = address + insn.pc + insn.operand[0].lval.sdword;
                    }
                }
                if (target) {
                    if (callTargets.contains(target) == false) {
                        log.traceLn("discovered new call target 0x%llx", target);
                        callTargets.append(target);
                    }
                }
                break;
            }
            case UD_Iret: {
                MDBCodeRegion *region = new MDBCodeRegion(this, address, findSymbolByNameOrAddress(NULL, address), insn.pc);
                regions.append(region);
                remainingBytes = 0;
                break;
            }
            default:
                break;
        }
    }
    
    for (uint32_t i = 0; i < callTargets.length(); i++) {
        scanProcedure(callTargets[i]);
    }
    
    return true;
}
Example #15
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;
}
Example #16
0
File: elf32.c Project: TDKPS/rdis
struct _map * elf32_functions (struct _elf32 * elf32, struct _map * memory)
{
    struct _list * entries   = list_create();

    // add the entry point
    struct _function * function = function_create(elf32_entry(elf32));
    list_append(entries, function);
    object_delete(function);

    // check for __libc_start_main loader
    uint64_t target_offset = elf32_entry(elf32) - elf32_base_address(elf32) + 0x17;
    if (target_offset + 0x10 < elf32->data_size) {
        uint8_t * data = &(elf32->data[target_offset]);
        size_t    size = elf32->data_size - target_offset;

        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, data, size);
        ud_disassemble(&ud_obj);
        if (ud_obj.mnemonic == UD_Ipush) {
            printf("found __libc_start_main loader, main at %llx\n",
                   (unsigned long long) udis86_sign_extend_lval(&(ud_obj.operand[0])));

            // add main to function tree
            struct _function * function;
            function = function_create(udis86_sign_extend_lval(&(ud_obj.operand[0])));
            list_append(entries, function);
            object_delete(function);

        }
        else
            printf("disassembled: %s\n disassembled at %llx\n",
                   ud_insn_asm(&ud_obj),
                   (unsigned long long) target_offset);
    }

    struct _map * functions = elf32_functions_wqueue(elf32, memory, entries);

    // these are the reachable functions
    struct _map_it * mit;
    for (mit = map_iterator(functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        function->flags |= FUNCTION_REACHABLE;
    }

    // reset entries
    object_delete(entries);
    entries = list_create();

    // symbols are easy
    int sec_i;
    for (sec_i = 0; sec_i < elf32->ehdr->e_shnum; sec_i++) {
        Elf32_Shdr * shdr = elf32_shdr(elf32, sec_i);
        if (shdr == NULL)
            break;

        if ((shdr->sh_type != SHT_SYMTAB) && (shdr->sh_type != SHT_DYNSYM))
            continue;

        int sym_i;
        for (sym_i = 0; sym_i < shdr->sh_size / shdr->sh_entsize; sym_i++) {
            Elf32_Sym * sym = elf32_section_element(elf32, sec_i, sym_i);
            if (sym == NULL)
                break;

            if (ELF32_ST_TYPE(sym->st_info) != STT_FUNC)
                continue;

            if (sym->st_value == 0)
                continue;

            struct _function * function = function_create(sym->st_value);
            list_append(entries, function);
            object_delete(function);
        }
    }

    struct _map * sym_functions = elf32_functions_wqueue(elf32, memory, entries);
    for (mit = map_iterator(sym_functions); mit != NULL; mit = map_it_next(mit)) {
        struct _function * function = map_it_data(mit);
        if (map_fetch(functions, function->address) == NULL)
            map_insert(functions, function->address, function);
    }

    object_delete(sym_functions);
    object_delete(entries);

    return functions;
}
Example #17
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;
  }
Example #18
0
File: utils.c Project: Veejay/elfs
telf_status
binary_to_asm(char *bin,
              size_t bin_len,
              char **bufp,
              size_t *buf_lenp)
{
        telf_status ret;
        char *buf = NULL;
        size_t buf_len = 0;
        ud_t ud_obj;
        char *tmpbuf = NULL;

        ud_init(&ud_obj);
        ud_set_input_buffer(&ud_obj, bin, bin_len);
        ud_set_mode(&ud_obj, 64);
        ud_set_syntax(&ud_obj, UD_SYN_INTEL);

        if (! bin_len || ! bin) {
                ret = ELF_SUCCESS;
                goto end;
        }

        while (ud_disassemble(&ud_obj)) {
                char line[64] = "";
                size_t len;

                len = sprintf(line, "%s\n", ud_insn_asm(&ud_obj));

                tmpbuf = realloc(buf, buf_len + len);
                if (! tmpbuf) {
                        ERR("realloc: %s", strerror(errno));
                        free(buf);
                        buf = NULL;
                        ret = ELF_ENOMEM;
                        goto end;
                }

                buf = tmpbuf;
                memmove(buf + buf_len, line, len);
                buf_len += len;
        }

        /* we didn't reserve any room for the nul-terminaison char */
        if (buf) {
                tmpbuf = realloc(buf, buf_len + 1);
                if (! tmpbuf) {
                        ERR("realloc: %s", strerror(errno));
                        free(buf);
                        buf = NULL;
                        ret = ELF_ENOMEM;
                        goto end;
                }

                tmpbuf[buf_len] = 0;
                buf_len++;
                buf = tmpbuf;
        }

        ret = ELF_SUCCESS;
  end:
        if (bufp)
                *bufp = buf;
        else
                free(buf);

        if (buf_lenp)
                *buf_lenp = buf_len;

        return ret;
}
Example #19
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;
    }
}
Example #20
0
File: x86.c Project: 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;
}
Example #21
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;
    }
}
Example #22
0
void debugger_proc(pid_t child_proc, struct execute_context *ctx)
{
    /* about child process */
    int child_stat;
    kern_return_t kret;
    mach_port_t task;
    int wait_cnt = 0;
    char **args = ctx->passing_args;

    /* related analysys of target process binary. */
    int i;
    int nsym;
    int text_section;
    uint64_t text_section_offset;
    uint64_t text_section_size;
    uint64_t text_section_vmaddr;
    struct symbol_info *psymbol_table;
    int init = 0;
    struct breakpoint_entry top;

    int stack_depth = 0;

    /* error check */
    if (child_proc == 0 || child_proc == -1)	return;

    /* initialize */
    memset(&top, 0x00, sizeof(top));

    /* open the port (do as an administrator) */
    kret = task_for_pid(mach_task_self(), child_proc, &task);
    if (kret != KERN_SUCCESS) {
        fprintf(stderr, "task_for_pid() failed\n");
        fprintf(stderr, "%s\n", mach_error_string(kret));
        exit(0);
    }

    fprintf(stderr, "[Tracer] child_proc: %d\n", child_proc);
    /* main loop */
    while(waitpid(child_proc, &child_stat, WUNTRACED)) {    /* {{{ */
        char buffer[128];
        char w_buf[128];
        w_buf[0] = 0x90;	/* nop */

        if (WIFEXITED(child_stat)) {
            /* Child Process Terminated */
            fprintf(stderr, "[Tracer]  Process :%d Terminated\n", child_proc);
            return;
        }
        memset(buffer, 0x00, 128);
        if(wait_cnt == 0) {
            /* The First time trapped   {{{ */
            /* -- The debugee program has not been expanded.-- */
            /* -- 	lookup named symbol	-- */
            struct file_info bininfo;
            ud_t ud_obj;
            uint64_t previous_eip;
            uint64_t func_start_addr;
            uint64_t func_end_addr;

            nsym = get_func_table(args[0], &psymbol_table, &text_section, &text_section_offset, &text_section_size, &text_section_vmaddr);
            debug_printf("nsym: %d\n", nsym);
            debug_printf("text section = %d\n", text_section);
            debug_printf("text section offset: 0x%llx\n", text_section_offset);
            debug_printf("text section size: 0x%llx\n", text_section_size);
            debug_printf("text section vmaddr: 0x%llx\n", text_section_vmaddr);

            qsort(psymbol_table, nsym, sizeof(struct symbol_info), symbolinfo_comp);

            /* XXX for debugging  */
            /*display_symbol_table(psymbol_table, nsym);  */

            /* code analysys */
            map_binary(args[0], &bininfo);
            ud_init(&ud_obj);
            ud_set_input_buffer(&ud_obj, bininfo.top + text_section_offset, text_section_size);
            ud_set_mode(&ud_obj, 64);

            previous_eip = text_section_vmaddr;
            /* set breakpoint at the entry and exit points of functions */
            for(i = 0; i < nsym; i++) {
                /* Set breakpoints {{{ */
                if (is_exclude_func(psymbol_table + i) == 1) {
                    continue;
                }
                /* 1, specifying the region of the function */
                func_start_addr = psymbol_table[i].nlist64.n_value;
                if (i != nsym - 1) {
                    /* next section's entry point - 1 */
                    func_end_addr = psymbol_table[i + 1].nlist64.n_value;
                } else {
                    func_end_addr = text_section_vmaddr + text_section_size + 1;
                }
                printf("%s: 0x%llx --> 0x%llx\n", psymbol_table[i].name, func_start_addr, func_end_addr);
                /*
                if (strstr(psymbol_table[i].name, "main") != NULL) {
                    __asm__("int3");
                }
                */
                psymbol_table[i].ret_address_num = 0;

                previous_eip = ud_obj.pc + text_section_vmaddr;

                while(ud_disassemble(&ud_obj) && previous_eip < func_start_addr) {
                    previous_eip = ud_obj.pc + text_section_vmaddr;
                }
                while(ud_disassemble(&ud_obj) && previous_eip < func_end_addr) {
                    if (func_start_addr <= previous_eip && ud_obj.mnemonic == UD_Iret) {
                        set_breakpoint(task, previous_eip, &top);
                        psymbol_table[i].ret_inst_address[ psymbol_table[i].ret_address_num ] = previous_eip;
                        psymbol_table[i].ret_address_num++;
                    }
                    previous_eip = ud_obj.pc + text_section_vmaddr;
                }
                /*
                if (0 < psymbol_table[i].ret_address_num) {
                    set_breakpoint(task, psymbol_table[i].nlist64.n_value, &top);
                }
                */
                set_breakpoint(task, psymbol_table[i].nlist64.n_value, &top);
                /* }}} */
            }
            debug_printf("break point insert\n");
            unmap_binary(&bininfo);
            /* }}} */
        } else {
            /* {{{ */
            /* break point */
            /* 1, Get current address from RIP value.
            * 2, Find current function name by EIP, and Logging.
            * 3, Substitute original instruction code for current break point code(0x90).
            * 4, Decrement EIP value.
            * 5, Execute only one op-code.
            * 6, Substitute 0x90 for oroginal code (located in entrance of function).
            * */
            uint64_t rip;
            read_process_register_64(task, RIP, &rip);
            if (is_breakpoint(rip - 1, &top) == 1) {
                stack_depth = breakpoint_handler(task, rip - 1, psymbol_table, nsym, stack_depth);
                write_process_register_64(task, RIP, RELATIVE_VAL, -1);
                disable_breakpoint(task, rip - 1, &top);
                ptrace(PT_STEP, child_proc, (caddr_t)1, 0);
                set_breakpoint(task, rip - 1, &top);
            }
            /* }}} */
        }
        wait_cnt++;
        ptrace(PT_CONTINUE, child_proc, (caddr_t)1, 0);
    }   /* }}} */
}
Example #23
0
  void LLVMState::show_machine_code(void* buffer, size_t size) {

#if defined(IS_X86) || defined(IS_X8664)
#ifndef RBX_WINDOWS
    ud_t ud;

    ud_init(&ud);
#ifdef IS_64BIT_ARCH
    ud_set_mode(&ud, 64);
#else
    ud_set_mode(&ud, 32);
#endif
    ud_set_syntax(&ud, UD_SYN_ATT);
    ud_set_input_buffer(&ud, reinterpret_cast<uint8_t*>(buffer), size);

    while(ud_disassemble(&ud)) {
      void* address = reinterpret_cast<void*>(
          reinterpret_cast<uintptr_t>(buffer) + ud_insn_off(&ud));

      llvm::outs() << format("%10p", address) << "  ";
      llvm::outs() << format("%-24s", ud_insn_asm(&ud));
      if(ud.operand[0].type == UD_OP_JIMM) {
        const void* addr = (const void*)((uintptr_t)buffer + ud.pc + (int)ud.operand[0].lval.udword);
        llvm::outs() << " ; " << addr;
        if(ud.mnemonic == UD_Icall) {
          Dl_info info;
          if(dladdr((void*)addr, &info)) {
            int status = 0;
            char* cpp_name = abi::__cxa_demangle(info.dli_sname, 0, 0, &status);
            if(status >= 0) {
              // Chop off the arg info from the signature output
              char *paren = strstr(cpp_name, "(");
              *paren = 0;
              llvm::outs() << " " << cpp_name;
              free(cpp_name);
            } else {
              llvm::outs() << " " << info.dli_sname;
            }
          }
        }
      }

      for(uint8_t i = 0; i < 2; i++) {
        if(ud.operand[i].type == UD_OP_IMM) {
          Dl_info info;
          if(dladdr((void*)ud.operand[i].lval.uqword, &info)) {
            llvm::outs() << " ; " << info.dli_sname;
            break; // only do one
          }
        }
      }

      llvm::outs() << "\n";
    }
#endif  // !RBX_WINDOWS

#else
    JITDisassembler disassembler(buffer, size);
    std::string output = disassembler.print_machine_code();
    std::cout << output;
#endif // !IS_X86

  }
Example #24
0
void
lp_disassemble(const void* func)
{
#ifdef HAVE_UDIS86
   ud_t ud_obj;
   uint64_t max_jmp_pc;
   uint inst_no;
   boolean emit_addrs = TRUE, emit_line_nos = FALSE;

   ud_init(&ud_obj);

   ud_set_input_buffer(&ud_obj, (void*)func, 0xffff);

   max_jmp_pc = (uint64_t) (uintptr_t) func;
   ud_set_pc(&ud_obj, max_jmp_pc);

#ifdef PIPE_ARCH_X86
   ud_set_mode(&ud_obj, 32);
#endif
#ifdef PIPE_ARCH_X86_64
   ud_set_mode(&ud_obj, 64);
#endif

   ud_set_syntax(&ud_obj, UD_SYN_ATT);

   while (ud_disassemble(&ud_obj)) {

      if (emit_addrs) {
#ifdef PIPE_ARCH_X86
         debug_printf("0x%08lx:\t", (unsigned long)ud_insn_off(&ud_obj));
#endif
#ifdef PIPE_ARCH_X86_64
         debug_printf("0x%016llx:\t", (unsigned long long)ud_insn_off(&ud_obj));
#endif
      }
      else if (emit_line_nos) {
         debug_printf("%6d:\t", inst_no);
         inst_no++;
      }
#if 0
      debug_printf("%-16s ", ud_insn_hex(&ud_obj));
#endif

      debug_printf("%s\n", ud_insn_asm(&ud_obj));

      if(ud_obj.mnemonic != UD_Icall) {
         unsigned i;
         for(i = 0; i < 3; ++i) {
            const struct ud_operand *op = &ud_obj.operand[i];
            if (op->type == UD_OP_JIMM){
               uint64_t pc = ud_obj.pc;

               switch (op->size) {
               case 8:
                  pc += op->lval.sbyte;
                  break;
               case 16:
                  pc += op->lval.sword;
                  break;
               case 32:
                  pc += op->lval.sdword;
                  break;
               default:
                  break;
               }
               if(pc > max_jmp_pc)
                  max_jmp_pc = pc;
            }
         }
      }

      if (ud_obj.mnemonic == UD_Iinvalid ||
          (ud_insn_off(&ud_obj) >= max_jmp_pc &&
           (ud_obj.mnemonic == UD_Iret ||
            ud_obj.mnemonic == UD_Ijmp)))
         break;
   }

#if 0
   /* Print GDB command, useful to verify udis86 output */
   debug_printf("disassemble %p %p\n", func, (void*)(uintptr_t)ud_obj.pc);
#endif

   debug_printf("\n");
#else
   (void)func;
#endif
}