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

📄 image.cpp

📁 微软提供的截取Win32 API函数的开发包和例子detours-src-1.2.rar
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//////////////////////////////////////////////////////////////////////////////
//
//	Module:		detours.lib
//  File:		image.cpp
//  Summary:	Image manipulation functions (for payloads, byways, and imports).
//	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"

namespace Detour
{
///////////////////////////////////////////////////////////////////////////////
//
class CImageData
{
	friend class CImage;
	
public:
	CImageData(PBYTE pbData, DWORD cbData);
	~CImageData();

	PBYTE 					Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
	PBYTE					Find(REFGUID rguid, DWORD *pcbData);
	PBYTE					Set(REFGUID rguid, PBYTE pbData, DWORD cbData);
	
	BOOL					Delete(REFGUID rguid);
	BOOL					Purge();

	BOOL					IsEmpty()			{ return m_cbData == 0; }
	BOOL					IsValid();
	
protected:
	BOOL					SizeTo(DWORD cbData);

protected:
	PBYTE					m_pbData;
	DWORD					m_cbData;
	DWORD					m_cbAlloc;
};

class CImageImportFile
{
	friend class CImage;
	friend class CImageImportName;

public:
	CImageImportFile();
	~CImageImportFile();
	
public:
	CImageImportFile *		m_pNextFile;
	BOOL					m_bByway;

	CImageImportName *		m_pImportNames;
	DWORD					m_nImportNames;

	PIMAGE_THUNK_DATA		m_rvaOriginalFirstThunk;
	PIMAGE_THUNK_DATA		m_rvaFirstThunk;
	
	DWORD					m_nForwarderChain;
	PCHAR					m_pszOrig;
	PCHAR					m_pszName;
};

class CImageImportName
{
	friend class CImage;
	friend class CImageImportFile;
	
public:
	CImageImportName();
	~CImageImportName();
	
public:
	WORD		m_nHint;
	DWORD		m_nOrdinal;
	PCHAR		m_pszOrig;
	PCHAR		m_pszName;
};

class CImage
{
	friend class CImageThunks;
	friend class CImageChars;
	friend class CImageImportFile;
	friend class CImageImportName;

public:
	CImage();
	~CImage();

	static CImage *			IsValid(PDETOUR_BINARY pBinary);
	
public:													// File Functions
	BOOL					Read(HANDLE hFile);
	BOOL					Write(HANDLE hFile);
	BOOL 					Close();

public:													// Manipulation Functions
	PBYTE 					DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator);
	PBYTE					DataFind(REFGUID rguid, DWORD *pcbData);
	PBYTE					DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData);
	BOOL					DataDelete(REFGUID rguid);
	BOOL					DataPurge();

	BOOL					EditImports(PVOID pContext,
										PF_DETOUR_BINARY_BYWAY_CALLBACK pfBywayCallback,
										PF_DETOUR_BINARY_FILE_CALLBACK pfFileCallback,
										PF_DETOUR_BINARY_SYMBOL_CALLBACK pfSymbolCallback,
										PF_DETOUR_BINARY_FINAL_CALLBACK pfFinalCallback);
	
protected:
	BOOL 					CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData);
	BOOL 					ZeroFileData(HANDLE hFile, DWORD cbData);
	BOOL					AlignFileData(HANDLE hFile);

	BOOL					SizeOutputBuffer(DWORD cbData);
	PBYTE					AllocateOutput(DWORD cbData, DWORD *pnVirtAddr);
	
	PVOID 					RvaToVa(DWORD nRva);
	DWORD					RvaToFileOffset(DWORD nRva);
	
	DWORD					FileAlign(DWORD nAddr);
	DWORD					SectionAlign(DWORD nAddr);
		
	BOOL					CheckImportsNeeded(DWORD *pnTables,
											   DWORD *pnThunks,
											   DWORD *pnChars);

	CImageImportFile *		NewByway(PCHAR pszName);

private:
	DWORD					m_dwValidSignature;
	CImageData *			m_pImageData;				// Read & Write
	
	HANDLE					m_hMap;						// Read & Write
	PBYTE					m_pMap;						// Read & Write

	DWORD					m_nNextFileAddr;			// Write
	DWORD					m_nNextVirtAddr;			// Write

	IMAGE_NT_HEADERS		m_NtHeader;					// Read & Write
	IMAGE_SECTION_HEADER	m_SectionHeaders[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
	
	DWORD					m_nPeOffset;
	DWORD					m_nSectionsOffset;
	DWORD					m_nExtraOffset;
	DWORD					m_nFileSize;

	DWORD					m_nOutputVirtAddr;
	DWORD					m_nOutputVirtSize;
	DWORD					m_nOutputFileAddr;
	
	PBYTE					m_pbOutputBuffer;
	DWORD					m_cbOutputBuffer;

	CImageImportFile *		m_pImportFiles;
	DWORD					m_nImportFiles;

private:
	enum {
		DETOUR_IMAGE_VALID_SIGNATURE = 0xfedcba01,		// "Dtr\0"
	};
};

//////////////////////////////////////////////////////////////////////////////
//
static inline DWORD Max(DWORD a, DWORD b) 
{
	return a > b ? a : b;
}

static inline DWORD Align(DWORD a, DWORD size)
{
	size--;
	return (a + size) & ~size;
}

static inline DWORD QuadAlign(DWORD a)
{
	return Align(a, 8);
}

static PCHAR DuplicateString(PCHAR pszIn)
{
	if (pszIn) {
		UINT nIn = strlen(pszIn);
		PCHAR pszOut = new CHAR [nIn + 1];
		if (pszOut == NULL) {
			SetLastError(ERROR_OUTOFMEMORY);
		}
		else {
			CopyMemory(pszOut, pszIn, nIn + 1);
		}
		return pszOut;
	}
	return NULL;
}

static PCHAR ReplaceString(PCHAR *ppsz, PCHAR pszIn)
{
	if (ppsz == NULL) {
		return NULL;
	}

	if (strcmp(*ppsz, pszIn) != 0) {
		UINT nIn = strlen(pszIn);
		
		if (strlen(*ppsz) == nIn) {
			CopyMemory(*ppsz, pszIn, nIn + 1);
			return *ppsz;
		}
		else {
			delete[] *ppsz;	
			*ppsz = new CHAR [nIn + 1];
			if (*ppsz == NULL) {
				SetLastError(ERROR_OUTOFMEMORY);
			}
			else {
				CopyMemory(*ppsz, pszIn, nIn + 1);
			}
			return *ppsz;
		}
	}
	return *ppsz;

}

//////////////////////////////////////////////////////////////////////////////
//
CImageImportFile::CImageImportFile()
{
	m_pNextFile = NULL;
	m_bByway = FALSE;
		
	m_pImportNames = NULL;
	m_nImportNames = 0;

	m_rvaOriginalFirstThunk = 0;
	m_rvaFirstThunk = 0;

	m_nForwarderChain = -1;
	m_pszName = NULL;
	m_pszOrig = NULL;
}

CImageImportFile::~CImageImportFile()
{
	if (m_pNextFile) {
		delete m_pNextFile;
		m_pNextFile = NULL;
	}
	if (m_pImportNames) {
		delete[] m_pImportNames;
		m_pImportNames = NULL;
		m_nImportNames = 0;
	}
	if (m_pszName) {
		delete[] m_pszName;
		m_pszName = NULL;
	}
	if (m_pszOrig) {
		delete[] m_pszOrig;
		m_pszOrig = NULL;
	}
}

CImageImportName::CImageImportName()
{
	m_nOrdinal = 0;
	m_nHint = 0;
	m_pszName = NULL;
	m_pszOrig = NULL;
}
	
CImageImportName::~CImageImportName()
{
	if (m_pszName) {
		delete[] m_pszName;
		m_pszName = NULL;
	}
	if (m_pszOrig) {
		delete[] m_pszOrig;
		m_pszOrig = NULL;
	}
}

//////////////////////////////////////////////////////////////////////////////
//
CImageData::CImageData(PBYTE pbData, DWORD cbData)
{
	m_pbData = pbData;
	m_cbData = cbData;
	m_cbAlloc = 0;
}

CImageData::~CImageData()
{
	IsValid();
	
	if (m_cbAlloc == 0) {
		m_pbData = NULL;
	}
	if (m_pbData) {
		delete[] m_pbData;
		m_pbData = NULL;
	}
	m_cbData = 0;
	m_cbAlloc = 0;
}

BOOL CImageData::SizeTo(DWORD cbData)
{
	IsValid();
	
	if (cbData <= m_cbAlloc) {
		return TRUE;
	}
	
	PBYTE pbNew = new BYTE [cbData];
	if (pbNew == NULL) {
		SetLastError(ERROR_OUTOFMEMORY);
		return FALSE;
	}
	
	if (m_pbData) {
		CopyMemory(pbNew, m_pbData, m_cbData);
		if (m_cbAlloc > 0) {
			delete[] m_pbData;
		}
		m_pbData = NULL;
	}
	m_pbData = pbNew;
	m_cbAlloc = cbData;

	IsValid();
	
	return TRUE;
}

BOOL CImageData::Purge()
{
	m_cbData = 0;
	
	IsValid();
	
	return TRUE;
}

BOOL CImageData::IsValid()
{
	if (m_pbData == NULL) {
		return TRUE;
	}

	PBYTE pbBeg = m_pbData;
	PBYTE pbEnd = m_pbData + m_cbData;
	
	for (PBYTE pbIter = pbBeg; pbIter < pbEnd;) {
		PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)pbIter;

		if (pRecord->cbBytes < sizeof(DETOUR_SECTION_RECORD)) {
			__asm int 3;
		}
		if (pRecord->nReserved != 0) {
			__asm int 3;
		}
		
		pbIter += pRecord->cbBytes;
	}
	return TRUE;
}

PBYTE CImageData::Enumerate(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
{
	IsValid();

	PBYTE pbEnd = m_pbData + m_cbData;
	
	if (pnIterator == NULL ||
		m_cbData < *pnIterator + sizeof(DETOUR_SECTION_RECORD)) {
		
		if (pcbData) {
			*pcbData = 0;
		}
		if (pGuid) {
			ZeroMemory(pGuid, sizeof(*pGuid));
		}
		return NULL;
	}
	
	PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + *pnIterator);

	if (pGuid) {
		*pGuid = pRecord->guid;
	}
	if (pcbData) {
		*pcbData = pRecord->cbBytes - sizeof(DETOUR_SECTION_RECORD);
	}
	*pnIterator = ((PBYTE)pRecord - m_pbData) + pRecord->cbBytes;
	
	return (PBYTE)(pRecord + 1);
}

PBYTE CImageData::Find(REFGUID rguid, DWORD *pcbData)
{
	IsValid();
	
	DWORD cbBytes = sizeof(DETOUR_SECTION_RECORD);
	for (DWORD nOffset = 0; nOffset < m_cbData; nOffset += cbBytes) {
		PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + nOffset);

		cbBytes = pRecord->cbBytes;
		if (cbBytes > m_cbData)
			break;
		if (cbBytes < sizeof(DETOUR_SECTION_RECORD))
			continue;

		if (IsEqualGUID(pRecord->guid, rguid)) {
			*pcbData = cbBytes - sizeof(DETOUR_SECTION_RECORD);
			return (PBYTE)(pRecord + 1);
		}
	}
	
	if (pcbData) {
		*pcbData = 0;
	}
	return NULL;
}

BOOL CImageData::Delete(REFGUID rguid)
{
	IsValid();

	PBYTE pbFound = NULL;
	DWORD cbFound = 0;

	pbFound = Find(rguid, &cbFound);
	if (pbFound == NULL) {
		SetLastError(ERROR_MOD_NOT_FOUND);
		return FALSE;
	}

	pbFound -= sizeof(DETOUR_SECTION_RECORD);
	cbFound += sizeof(DETOUR_SECTION_RECORD);
	
	PBYTE pbRestData = pbFound + cbFound;
	DWORD cbRestData = m_cbData - (pbRestData - m_pbData);

	if (cbRestData)
		MoveMemory(pbFound, pbRestData, cbRestData);
	m_cbData -= cbFound;

	IsValid();
	return TRUE;
}

PBYTE CImageData::Set(REFGUID rguid, PBYTE pbData, DWORD cbData)
{
	IsValid();
	Delete(rguid);

	DWORD cbAlloc = QuadAlign(cbData);

⌨️ 快捷键说明

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