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

📄 detours.cpp

📁 微软提供的截取Win32 API函数的开发包和例子detours-src-1.2.rar
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////////////
//
//	Module:		detours.lib
//  File:		detours.cpp
//	Author:		Galen Hunt
//
//	Detours for binary functions.  Version 1.2. (Build 35)
//
//	Copyright 1995-1999, Microsoft Corporation
//
//	http://research.microsoft.com/sn/detours
//

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

//////////////////////////////////////////////////////////////////////////////
//
enum {
	OP_JMP_DS		= 0x25,
	OP_JA			= 0x77,
	OP_NOP 			= 0x90,
	OP_CALL			= 0xe8,
	OP_JMP 			= 0xe9,
	OP_PREFIX 		= 0xff,
	OP_MOV_EAX		= 0xa1,
	OP_SET_EAX		= 0xb8,
	OP_JMP_EAX		= 0xe0,
	OP_RET_POP		= 0xc2,
	OP_RET			= 0xc3,
	OP_BRK			= 0xcc,

	SIZE_OF_JMP		= 5,
	SIZE_OF_NOP		= 1,
	SIZE_OF_BRK		= 1,
	SIZE_OF_TRP_OPS	= SIZE_OF_JMP /* + SIZE_OF_BRK */,
};

class CEnableWriteOnCodePage
{
public:
	CEnableWriteOnCodePage(PBYTE pbCode, LONG cbCode = DETOUR_TRAMPOLINE_SIZE)
	{
		m_pbCode = pbCode;
		m_cbCode = cbCode;
		m_dwOldPerm = 0;
		m_hProcess = GetCurrentProcess();

		if (m_pbCode && m_cbCode) {
			if (!FlushInstructionCache(m_hProcess, pbCode, cbCode)) {
				return;
			}
			if (!VirtualProtect(pbCode,
								cbCode,
								PAGE_EXECUTE_READWRITE,
								&m_dwOldPerm)) {
				return;
			}
		}
	}

	~CEnableWriteOnCodePage()
	{
		if (m_dwOldPerm && m_pbCode && m_cbCode) {
			DWORD dwTemp = 0;
			if (!FlushInstructionCache(m_hProcess, m_pbCode, m_cbCode)) {
				return;
			}
			if (!VirtualProtect(m_pbCode, m_cbCode, m_dwOldPerm, &dwTemp)) {
				return;
			}
		}
	}

	BOOL SetPermission(DWORD dwPerms)
	{
		if (m_dwOldPerm && m_pbCode && m_cbCode) {
			m_dwOldPerm = dwPerms;
			return TRUE;
		}
		return FALSE;
	}

	BOOL IsValid(VOID)
	{
		return m_pbCode && m_cbCode && m_dwOldPerm;
	}

private:
	HANDLE	m_hProcess;
	PBYTE 	m_pbCode;
	LONG	m_cbCode;
	DWORD	m_dwOldPerm;
};

//////////////////////////////////////////////////////////////////////////////
//
static BOOL detour_insert_jump(PBYTE pbCode, PBYTE pbDest, LONG cbCode)
{
	if (cbCode < SIZE_OF_JMP)
		return FALSE;
	
	*pbCode++ = OP_JMP;
	LONG offset = (LONG)pbDest - (LONG)(pbCode + 4);
	*((PDWORD&)pbCode)++ = offset;
	for (cbCode -= SIZE_OF_JMP; cbCode > 0; cbCode--)
		*pbCode++ = OP_BRK;
	return TRUE;
}

static BOOL detour_insert_detour(PBYTE pbTarget,
								 PBYTE pbTrampoline,
								 PBYTE pbDetour)
{
	PBYTE pbCont = pbTarget;
	for (LONG cbTarget = 0; cbTarget < SIZE_OF_TRP_OPS;) {
		BYTE bOp = *pbCont;
		pbCont = DetourCopyInstruction(NULL, pbCont, NULL);
		cbTarget = pbCont - pbTarget;

		if (bOp == OP_JMP ||
			bOp == OP_JMP_DS ||
			bOp == OP_JMP_EAX ||
			bOp == OP_RET_POP ||
			bOp == OP_RET) {

			break;
		}
	}
	if (cbTarget  < SIZE_OF_TRP_OPS) {
		// Too few instructions.
		return FALSE;
	}
	if (cbTarget > (DETOUR_TRAMPOLINE_SIZE - SIZE_OF_JMP - 1)) {
		// Too many instructions.
		return FALSE;
	}

	//////////////////////////////////////////////////////// Finalize Reroute.
	//
	CEnableWriteOnCodePage ewTrampoline(pbTrampoline, DETOUR_TRAMPOLINE_SIZE);
	CEnableWriteOnCodePage ewTarget(pbTarget, cbTarget);
	if (!ewTrampoline.SetPermission(PAGE_EXECUTE_READWRITE))
		return FALSE;
	if (!ewTarget.IsValid())
		return FALSE;
	
	PBYTE pbSrc = pbTarget;
	PBYTE pbDst = pbTrampoline;
	for (LONG cbCopy = 0; cbCopy < cbTarget;) {
		pbSrc = DetourCopyInstruction(pbDst, pbSrc, NULL);
		cbCopy = pbSrc - pbTarget;
		pbDst = pbTrampoline + cbCopy;
	}
	if (cbCopy != cbTarget)								// Count came out different!
		return FALSE;

	if (!detour_insert_jump(pbDst, pbTarget + cbTarget, SIZE_OF_JMP))
		return FALSE;

	pbTrampoline[DETOUR_TRAMPOLINE_SIZE-1] = (BYTE)cbTarget;

	if (!detour_insert_jump(pbTarget, pbDetour, cbTarget))
		return FALSE;
	
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////////
//
BOOL WINAPI DetourRemoveWithTrampoline(PBYTE pbTrampoline,
									   PBYTE pbDetour)
{
	pbTrampoline = DetourFindFinalCode(pbTrampoline);
	pbDetour = DetourFindFinalCode(pbDetour);

	////////////////////////////////////// Verify that Trampoline is in place.
	//
	LONG cbTarget = pbTrampoline[DETOUR_TRAMPOLINE_SIZE-1];
	if (cbTarget == 0 || cbTarget >= DETOUR_TRAMPOLINE_SIZE - 1) {
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}

	if (pbTrampoline[cbTarget] != OP_JMP) {
		SetLastError(ERROR_INVALID_HANDLE);
		return FALSE;
	}
		
	LONG offset = *((PDWORD)&pbTrampoline[cbTarget + 1]);
	PBYTE pbTarget = pbTrampoline + cbTarget + SIZE_OF_JMP + offset - cbTarget;

	if (pbTarget[0] != OP_JMP) {						// Missing detour.
		SetLastError(ERROR_INVALID_BLOCK);
		return FALSE;
	}

	offset = *((PDWORD)&pbTarget[1]);
	PBYTE pbTargetDetour = pbTarget + SIZE_OF_JMP + offset;
	if (pbTargetDetour != pbDetour) {
		SetLastError(ERROR_INVALID_ACCESS);
		return FALSE;
	}

	/////////////////////////////////////////////////////// Remove the Detour.
	CEnableWriteOnCodePage ewTarget(pbTarget, cbTarget);
	
	PBYTE pbSrc = pbTrampoline;
	PBYTE pbDst = pbTarget;
	for (LONG cbCopy = 0; cbCopy < cbTarget; pbDst = pbTarget + cbCopy) {
		pbSrc = DetourCopyInstruction(pbDst, pbSrc, NULL);
		cbCopy = pbSrc - pbTrampoline;
	}
	if (cbCopy != cbTarget) {							// Count came out different!
		SetLastError(ERROR_INVALID_DATA);
		return FALSE;
	}
	return TRUE;
}

PBYTE WINAPI DetourFunction(PBYTE pbTarget,
							PBYTE pbDetour)
{
	PBYTE pbTrampoline = new BYTE [DETOUR_TRAMPOLINE_SIZE];
	if (pbTrampoline == NULL)
		return NULL;

	pbTarget = DetourFindFinalCode(pbTarget);
	pbDetour = DetourFindFinalCode(pbDetour);

	if (detour_insert_detour(pbTarget, pbTrampoline, pbDetour))
		return pbTrampoline;

	delete[] pbTrampoline;
	return NULL;
}

BOOL WINAPI DetourFunctionWithEmptyTrampoline(PBYTE pbTrampoline,
											  PBYTE pbTarget,
											  PBYTE pbDetour)
{
	return DetourFunctionWithEmptyTrampolineEx(pbTrampoline, pbTarget, pbDetour,
											   NULL, NULL, NULL);
}

BOOL WINAPI DetourFunctionWithEmptyTrampolineEx(PBYTE pbTrampoline,
												PBYTE pbTarget,
												PBYTE pbDetour,
												PBYTE *ppbRealTrampoline,
												PBYTE *ppbRealTarget,
												PBYTE *ppbRealDetour)
{
	pbTrampoline = DetourFindFinalCode(pbTrampoline);
	pbTarget = DetourFindFinalCode(pbTarget);
	pbDetour = DetourFindFinalCode(pbDetour);
	
	if (ppbRealTrampoline)
		*ppbRealTrampoline = pbTrampoline;
	if (ppbRealTarget)
		*ppbRealTarget = pbTarget;
	if (ppbRealDetour)
		*ppbRealDetour = pbDetour;
	
	if (pbTrampoline == NULL || pbDetour == NULL || pbTarget == NULL)
		return FALSE;
	
	if (pbTrampoline[0] != OP_NOP ||
		pbTrampoline[1] != OP_NOP) {
		
		return FALSE;
	}
	
	return detour_insert_detour(pbTarget, pbTrampoline, pbDetour);
}

BOOL WINAPI DetourFunctionWithTrampoline(PBYTE pbTrampoline,
										 PBYTE pbDetour)
{
	return DetourFunctionWithTrampolineEx(pbTrampoline, pbDetour, NULL, NULL);
}

BOOL WINAPI DetourFunctionWithTrampolineEx(PBYTE pbTrampoline,
										   PBYTE pbDetour,
										   PBYTE *ppbRealTrampoline,
										   PBYTE *ppbRealTarget)
{
	PBYTE pbTarget = NULL;

	pbTrampoline = DetourFindFinalCode(pbTrampoline);
	pbDetour = DetourFindFinalCode(pbDetour);
	
	if (ppbRealTrampoline)
		*ppbRealTrampoline = pbTrampoline;
	if (ppbRealTarget)
		*ppbRealTarget = NULL;
	
	if (pbTrampoline == NULL || pbDetour == NULL)
		return FALSE;

	if (pbTrampoline[0] != OP_NOP 	||
		pbTrampoline[1] != OP_NOP 	||
		pbTrampoline[2] != OP_CALL 	||
		pbTrampoline[7] != OP_PREFIX 	||
		pbTrampoline[8] != OP_JMP_EAX) {
		
		return FALSE;
	}

	PVOID (__fastcall * pfAddr)(VOID);

	pfAddr = (PVOID (__fastcall *)(VOID))(pbTrampoline +
										  SIZE_OF_NOP + SIZE_OF_NOP + SIZE_OF_JMP +
										  *(LONG *)&pbTrampoline[3]);

	pbTarget = DetourFindFinalCode((PBYTE)(*pfAddr)());
	if (ppbRealTarget)
		*ppbRealTarget = pbTarget;

	return detour_insert_detour(pbTarget, pbTrampoline, pbDetour);
}

//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
//
//////////////////////////////////////////////////////////////////////////////
//
typedef LPAPI_VERSION (NTAPI *PF_ImagehlpApiVersionEx)(LPAPI_VERSION AppVersion);

typedef BOOL (NTAPI *PF_SymInitialize)(IN HANDLE hProcess,
									   IN LPSTR UserSearchPath,
									   IN BOOL fInvadeProcess);
typedef DWORD (NTAPI *PF_SymSetOptions)(IN DWORD SymOptions);
typedef DWORD (NTAPI *PF_SymGetOptions)(VOID);
typedef BOOL (NTAPI *PF_SymLoadModule)(IN HANDLE hProcess,
									   IN HANDLE hFile,
									   IN PSTR ImageName,
									   IN PSTR ModuleName,
									   IN DWORD BaseOfDll,
									   IN DWORD SizeOfDll);
typedef BOOL (NTAPI *PF_SymGetModuleInfo)(IN HANDLE hProcess,
										  IN DWORD dwAddr,
										  OUT PIMAGEHLP_MODULE ModuleInfo);
typedef BOOL (NTAPI *PF_SymGetSymFromName)(IN HANDLE hProcess,
										   IN LPSTR Name,
										   OUT PIMAGEHLP_SYMBOL Symbol);
typedef BOOL (NTAPI *PF_BindImage)(IN LPSTR pszImageName,
								   IN LPSTR pszDllPath,
								   IN LPSTR pszSymbolPath);

static HANDLE 					s_hProcess = NULL;
static HINSTANCE				s_hImageHlp = NULL;
static PF_ImagehlpApiVersionEx	s_pfImagehlpApiVersionEx = NULL;
static PF_SymInitialize			s_pfSymInitialize = NULL;
static PF_SymSetOptions			s_pfSymSetOptions = NULL;
static PF_SymGetOptions			s_pfSymGetOptions = NULL;
static PF_SymLoadModule			s_pfSymLoadModule = NULL;
static PF_SymGetModuleInfo		s_pfSymGetModuleInfo = NULL;
static PF_SymGetSymFromName		s_pfSymGetSymFromName = NULL;
static PF_BindImage				s_pfBindImage = NULL;

static BOOL LoadImageHlp(VOID)
{
	if (s_hImageHlp)
		return TRUE;
	
	if (s_hProcess == NULL) {
		s_hProcess = GetCurrentProcess();

		s_hImageHlp = LoadLibraryA("imagehlp.dll");
		if (s_hImageHlp == NULL)
			return FALSE;

		s_pfImagehlpApiVersionEx
			= (PF_ImagehlpApiVersionEx)GetProcAddress(s_hImageHlp,
													  "ImagehlpApiVersionEx");
		s_pfSymInitialize
			= (PF_SymInitialize)GetProcAddress(s_hImageHlp, "SymInitialize");
		s_pfSymSetOptions
			= (PF_SymSetOptions)GetProcAddress(s_hImageHlp, "SymSetOptions");
		s_pfSymGetOptions
			= (PF_SymGetOptions)GetProcAddress(s_hImageHlp, "SymGetOptions");
		s_pfSymLoadModule
			= (PF_SymLoadModule)GetProcAddress(s_hImageHlp, "SymLoadModule");
		s_pfSymGetModuleInfo
			= (PF_SymGetModuleInfo)GetProcAddress(s_hImageHlp, "SymGetModuleInfo");
		s_pfSymGetSymFromName
			= (PF_SymGetSymFromName)GetProcAddress(s_hImageHlp, "SymGetSymFromName");
		s_pfBindImage
			= (PF_BindImage)GetProcAddress(s_hImageHlp, "BindImage");

		API_VERSION av;
		ZeroMemory(&av, sizeof(av));
		av.MajorVersion = API_VERSION_NUMBER;
			
		if (s_pfImagehlpApiVersionEx) {
			(*s_pfImagehlpApiVersionEx)(&av);
		}

		if (s_pfImagehlpApiVersionEx == NULL || av.MajorVersion < API_VERSION_NUMBER) {
			FreeLibrary(s_hImageHlp);
			s_hImageHlp = NULL;
			return FALSE;

⌨️ 快捷键说明

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