📄 image.cpp
字号:
//////////////////////////////////////////////////////////////////////////////
//
// 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 + -