⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 disasm.cpp

📁 微软提供的截取Win32 API函数的开发包和例子detours-src-1.2.rar
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//////////////////////////////////////////////////////////////////////////////
//
//	Module:		detours.lib
//  File:		disasm.cpp
//	Author:		Doug Brubacher
//
//	Detours for binary functions.  Version 1.2. (Build 35)
//  Includes support for all x86 chips prior to the Pentium III.
//
//	Copyright 1999, Microsoft Corporation
//
//	http://research.microsoft.com/sn/detours
//

#include <ole2.h>
#include <imagehlp.h>
#include "detours.h"
#include "disasm.h"

#undef ASSERT
#define ASSERT(x)

//////////////////////////////////////////////////////////////////////////////
//
//  Function:
//      DetourCopyInstruction(PBYTE pbDst, PBYTE pbSrc, PBYTE *ppbTarget)
//  Purpose:
//      Copy a single instruction from pbSrc to pbDst.
//  Arguments:
//      pbDst:
//          Destination address for the instruction.  May be NULL in which
//          case DetourCopyInstruction is used to measure an instruction.
//          If not NULL then the source instruction is copied to the
//          destination instruction and any relative arguments are adjusted.
//      pbSrc:
//          Source address of the instruction.
//      ppbTarget:
//          Out parameter for any target instruction address pointed to by
//          the instruction.  For example, a branch or a jump insruction has
//          a target, but a load or store instruction doesn't.  A target is
//          another instruction that may be executed as a result of this
//          instruction.  ppbTarget may be NULL.
//		plExtra:
//			Out parameter for the number of extra bytes needed by the
//			instruction to reach the target.  For example, lExtra = 3 if the
//			instruction had an 8-bit relative offset, but needs a 32-bit
//			relative offset.
//  Returns:
//      Returns the address of the next instruction (following in the source)
//      instruction.  By subtracting pbSrc from the return value, the caller
//      can determinte the size of the instruction copied.
//  Comments:
//      By following the pbTarget, the caller can follow alternate
//      instruction streams.  However, it is not always possible to determine
//      the target based on static analysis.  For example, the destination of
//      a jump relative to a register cannot be determined from just the
//      instruction stream.  The output value, pbTarget, can have any of the
//      following outputs:
//			DETOUR_INSTRUCTION_TARGET_NONE:
//          	The instruction has no targets.
//			DETOUR_INSTRUCTION_TARGET_DYNAMIC:
//          	The instruction has a non-deterministic (dynamic) target.
//				(i.e. the jump is to an address held in a register.)
//          Address:   The instruction has the specified target.
//
//      When copying instructions, DetourCopyInstruction insures that any
//      targets remain constant.  It does so by adjusting any IP relative
//      offsets.
//
PBYTE WINAPI DetourCopyInstructionEx(PBYTE pbDst,
									 PBYTE pbSrc,
									 PBYTE *ppbTarget,
									 LONG *plExtra)
{
	CDetourDis oDetourDisasm(ppbTarget, plExtra);
	return oDetourDisasm.CopyInstruction(pbDst, pbSrc);
}

PBYTE WINAPI DetourCopyInstruction(PBYTE pbDst, PBYTE pbSrc, PBYTE *ppbTarget)
{
	CDetourDis oDetourDisasm(ppbTarget, NULL);
	return oDetourDisasm.CopyInstruction(pbDst, pbSrc);
}

/////////////////////////////////////////////////////////// Disassembler Code.
//
CDetourDis::CDetourDis(PBYTE *ppbTarget, LONG *plExtra)
{
	Set32BitOperand();
	Set32BitAddress();

	m_ppbTarget = ppbTarget ? ppbTarget : &m_pbScratchTarget;
	m_plExtra = plExtra ? plExtra : &m_lScratchExtra;

	*m_ppbTarget = DETOUR_INSTRUCTION_TARGET_NONE;
	*m_plExtra = 0;
}

VOID CDetourDis::Set16BitOperand()
{
	m_b16BitOperand = TRUE;
}

VOID CDetourDis::Set32BitOperand()
{
	m_b16BitOperand = FALSE;
}

VOID CDetourDis::Set16BitAddress()
{
	m_b16BitAddress = TRUE;
}

VOID CDetourDis::Set32BitAddress()
{
	m_b16BitAddress = FALSE;
}

PBYTE CDetourDis::CopyInstruction(PBYTE pbDst, PBYTE pbSrc)
{
	// Configure scratch areas if real areas are not available.
	if (NULL == pbDst) {
		pbDst = m_rbScratchDst;
	}
	if (NULL == pbSrc) {
		// We can't copy a non-existent instruction.
		SetLastError(ERROR_INVALID_DATA);
		return NULL;
	}
	
	// Figure out how big the instruction is, do the appropriate copy,
	// and figure out what the target of the instruction is if any.
	//
	REFCOPYENTRY pEntry = &s_rceCopyTable[pbSrc[0]];
	return (this->*pEntry->pfCopy)(pEntry, pbDst, pbSrc);
}

PBYTE CDetourDis::CopyBytes(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
{
	LONG nBytesFixed = (pEntry->nFlagBits & ADDRESS)
		? (m_b16BitAddress ? pEntry->nFixedSize16 : pEntry->nFixedSize)
		: (m_b16BitOperand ? pEntry->nFixedSize16 : pEntry->nFixedSize);
	LONG nBytes = nBytesFixed;
	if (pEntry->nModOffset > 0) {
		BYTE bModRm = pbSrc[pEntry->nModOffset];
		BYTE bFlags = s_rbModRm[bModRm];
		
		if (bFlags & SIB) {
			BYTE bSib = pbSrc[pEntry->nModOffset + 1];
			
			if ((bSib & 0x07) == 0x05) {
				if ((bModRm & 0xc0) == 0x00) {
					nBytes += 4;
				}
				else if ((bModRm & 0xc0) == 0x40) {
					nBytes += 1;
				}
				else if ((bModRm & 0xc0) == 0x80) {
					nBytes += 4;
				}
			}
		}
		nBytes += bFlags & NOTSIB;
	}
	CopyMemory(pbDst, pbSrc, nBytes);

	if (pEntry->nRelOffset) {
		*m_ppbTarget = AdjustTarget(pbDst, pbSrc, nBytesFixed, pEntry->nRelOffset);
	}
	if (pEntry->nFlagBits & NOENLARGE) {
		*m_plExtra = -*m_plExtra;
	}
	if (pEntry->nFlagBits & DYNAMIC) {
		*m_ppbTarget = DETOUR_INSTRUCTION_TARGET_DYNAMIC;
	}
	return pbSrc + nBytes;
}

PBYTE CDetourDis::CopyBytesPrefix(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{
	CopyBytes(pEntry, pbDst, pbSrc);
	
	pEntry = &s_rceCopyTable[pbSrc[1]];
	return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
}

PBYTE CDetourDis::AdjustTarget(PBYTE pbDst, PBYTE pbSrc, LONG cbOp, LONG cbTargetOffset)
{
	LONG cbTargetSize = cbOp - cbTargetOffset;
	PBYTE pbTarget = NULL;
	PVOID pvTargetAddr = &pbDst[cbTargetOffset];
	LONG nOldOffset = 0;
	
	switch (cbTargetSize) {
	  case 1:
		nOldOffset = (LONG)*(PCHAR&)pvTargetAddr;
		*m_plExtra = 3;
		break;
	  case 2:
		nOldOffset = (LONG)*(PSHORT&)pvTargetAddr;
		*m_plExtra = 2;
		break;
	  case 4:
		nOldOffset = (LONG)*(PLONG&)pvTargetAddr;
		*m_plExtra = 0;
		break;
	  default:
		ASSERT(!"cbTargetSize is invalid.");
		break;
	}
	
	pbTarget = pbSrc + cbOp + nOldOffset;
	LONG nNewOffset = nOldOffset - (pbDst - pbSrc);
	
	switch (cbTargetSize) {
	  case 1:
		*(PCHAR&)pvTargetAddr = (CHAR)nNewOffset;
		break;
	  case 2:
		*(PSHORT&)pvTargetAddr = (SHORT)nNewOffset;
		break;
	  case 4:
		*(PLONG&)pvTargetAddr = (LONG)nNewOffset;
		break;
	}
	ASSERT(pbDst + cbOp + nNewOffset == pbTarget);
	return pbTarget;
}

PBYTE CDetourDis::Invalid(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{
	ASSERT(!"Invalid Instruction");
	return pbSrc + 1;
}

////////////////////////////////////////////////////// Individual Bytes Codes.
//
PBYTE CDetourDis::Copy0F(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc)
{
	CopyBytes(pEntry, pbDst, pbSrc);
	
	pEntry = &s_rceCopyTable0F[pbSrc[1]];
	return (this->*pEntry->pfCopy)(pEntry, pbDst + 1, pbSrc + 1);
}

PBYTE CDetourDis::Copy66(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{	// Operand-size override prefix
	Set16BitOperand();
	return CopyBytesPrefix(pEntry, pbDst, pbSrc);
}

PBYTE CDetourDis::Copy67(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{	// Address size override prefix
	Set16BitAddress();
	return CopyBytesPrefix(pEntry, pbDst, pbSrc);
}

PBYTE CDetourDis::CopyF6(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{
	// TEST BYTE /0
	if (0x00 == (0x38 & pbSrc[1])) {	// reg(bits 543) of ModR/M == 0
		const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod1 };
		return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
	}
	// DIV /6
	// IDIV /7
	// IMUL /5
	// MUL /4
	// NEG /3
	// NOT /2
	
	const COPYENTRY ce = { 0xf6, ENTRY_CopyBytes2Mod };
	return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
}

PBYTE CDetourDis::CopyF7(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{
	// TEST WORD /0
	if (0x00 == (0x38 & pbSrc[1])) {	// reg(bits 543) of ModR/M == 0
		const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2ModOperand };
		return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
	}
	
	// DIV /6
	// IDIV /7
	// IMUL /5
	// MUL /4
	// NEG /3
	// NOT /2
	const COPYENTRY ce = { 0xf7, ENTRY_CopyBytes2Mod };
	return (this->*ce.pfCopy)(&ce, pbDst, pbSrc);
}

PBYTE CDetourDis::CopyFF(REFCOPYENTRY pEntry, PBYTE pbDst, PBYTE pbSrc) 
{	// CALL /2
	// CALL /3
	// INC /0
	// JMP /4

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -