📄 image.cpp
字号:
if (!SizeTo(m_cbData + cbAlloc + sizeof(DETOUR_SECTION_RECORD))) {
return NULL;
}
PDETOUR_SECTION_RECORD pRecord = (PDETOUR_SECTION_RECORD)(m_pbData + m_cbData);
pRecord->cbBytes = cbAlloc + sizeof(DETOUR_SECTION_RECORD);
pRecord->nReserved = 0;
pRecord->guid = rguid;
PBYTE pbDest = (PBYTE)(pRecord + 1);
if (pbData) {
CopyMemory(pbDest, pbData, cbData);
if (cbData < cbAlloc) {
ZeroMemory(pbDest + cbData, cbAlloc - cbData);
}
}
else {
if (cbAlloc > 0) {
ZeroMemory(pbDest, cbAlloc);
}
}
m_cbData += cbAlloc + sizeof(DETOUR_SECTION_RECORD);
IsValid();
return pbDest;
}
//////////////////////////////////////////////////////////////////////////////
//
class CImageThunks
{
private:
CImage * m_pImage;
PIMAGE_THUNK_DATA m_pThunks;
DWORD m_nThunks;
DWORD m_nThunksMax;
DWORD m_nThunkVirtAddr;
public:
CImageThunks(CImage *pImage, DWORD nThunksMax, DWORD *pnAddr)
{
m_pImage = pImage;
m_nThunks = 0;
m_nThunksMax = nThunksMax;
m_pThunks = (PIMAGE_THUNK_DATA)
m_pImage->AllocateOutput(sizeof(IMAGE_THUNK_DATA) * nThunksMax,
&m_nThunkVirtAddr);
*pnAddr = m_nThunkVirtAddr;
}
PIMAGE_THUNK_DATA Current(DWORD *pnVirtAddr)
{
if (m_nThunksMax > 1) {
*pnVirtAddr = m_nThunkVirtAddr;
return m_pThunks;
}
*pnVirtAddr = 0;
return NULL;
}
PIMAGE_THUNK_DATA Allocate(DWORD nData, DWORD *pnVirtAddr)
{
if (m_nThunks < m_nThunksMax) {
*pnVirtAddr = m_nThunkVirtAddr;
m_nThunks++;
m_nThunkVirtAddr += sizeof(IMAGE_THUNK_DATA);
m_pThunks->u1.Ordinal = nData;
return m_pThunks++;
}
*pnVirtAddr = 0;
return NULL;
}
DWORD Size()
{
return m_nThunksMax * sizeof(IMAGE_THUNK_DATA);
}
};
//////////////////////////////////////////////////////////////////////////////
//
class CImageChars
{
private:
CImage * m_pImage;
PCHAR m_pChars;
DWORD m_nChars;
DWORD m_nCharsMax;
DWORD m_nCharVirtAddr;
public:
CImageChars(CImage *pImage, DWORD nCharsMax, DWORD *pnAddr)
{
m_pImage = pImage;
m_nChars = 0;
m_nCharsMax = nCharsMax;
m_pChars = (PCHAR)m_pImage->AllocateOutput(nCharsMax, &m_nCharVirtAddr);
*pnAddr = m_nCharVirtAddr;
}
PCHAR Allocate(PCHAR pszString, DWORD *pnVirtAddr)
{
DWORD nLen = strlen(pszString) + 1;
nLen += (nLen & 1);
if (m_nChars + nLen > m_nCharsMax) {
*pnVirtAddr = 0;
return NULL;
}
*pnVirtAddr = m_nCharVirtAddr;
strcpy(m_pChars, pszString);
pszString = m_pChars;
m_pChars += nLen;
m_nChars += nLen;
m_nCharVirtAddr += nLen;
return pszString;
}
PCHAR Allocate(PCHAR pszString, DWORD nHint, DWORD *pnVirtAddr)
{
DWORD nLen = strlen(pszString) + 1 + sizeof(USHORT);
nLen += (nLen & 1);
if (m_nChars + nLen > m_nCharsMax) {
*pnVirtAddr = 0;
return NULL;
}
*pnVirtAddr = m_nCharVirtAddr;
*(USHORT *)m_pChars = (USHORT)nHint;
strcpy(m_pChars + sizeof(USHORT), pszString);
pszString = m_pChars + sizeof(USHORT);
m_pChars += nLen;
m_nChars += nLen;
m_nCharVirtAddr += nLen;
return pszString;
}
DWORD Size()
{
return m_nChars;
}
};
//////////////////////////////////////////////////////////////////////////////
//
CImage * CImage::IsValid(PDETOUR_BINARY pBinary)
{
if (pBinary) {
CImage *pImage = (CImage *)pBinary;
if (pImage->m_dwValidSignature == DETOUR_IMAGE_VALID_SIGNATURE) {
return pImage;
}
}
SetLastError(ERROR_INVALID_HANDLE);
return NULL;
}
CImage::CImage()
{
m_dwValidSignature = DETOUR_IMAGE_VALID_SIGNATURE;
m_hMap = NULL;
m_pMap = NULL;
m_nPeOffset = 0;
m_nSectionsOffset = 0;
m_pbOutputBuffer = NULL;
m_cbOutputBuffer = 0;
m_pImageData = NULL;
m_pImportFiles = NULL;
m_nImportFiles = 0;
}
CImage::~CImage()
{
Close();
m_dwValidSignature = 0;
}
BOOL CImage::Close()
{
if (m_pImportFiles) {
delete m_pImportFiles;
m_pImportFiles = NULL;
m_nImportFiles = 0;
}
if (m_pImageData) {
delete m_pImageData;
m_pImageData = NULL;
}
if (m_pMap != NULL) {
UnmapViewOfFile(m_pMap);
m_pMap = NULL;
}
if (m_hMap) {
CloseHandle(m_hMap);
m_hMap = NULL;
}
if (m_pbOutputBuffer) {
delete[] m_pbOutputBuffer;
m_pbOutputBuffer = NULL;
m_cbOutputBuffer = 0;
}
return TRUE;
}
//////////////////////////////////////////////////////////////////////////////
//
PBYTE CImage::DataEnum(GUID *pGuid, DWORD *pcbData, DWORD *pnIterator)
{
if (m_pImageData == NULL) {
return NULL;
}
return m_pImageData->Enumerate(pGuid, pcbData, pnIterator);
}
PBYTE CImage::DataFind(REFGUID rguid, DWORD *pcbData)
{
if (m_pImageData == NULL) {
return NULL;
}
return m_pImageData->Find(rguid, pcbData);
}
PBYTE CImage::DataSet(REFGUID rguid, PBYTE pbData, DWORD cbData)
{
if (m_pImageData == NULL) {
return NULL;
}
return m_pImageData->Set(rguid, pbData, cbData);
}
BOOL CImage::DataDelete(REFGUID rguid)
{
if (m_pImageData == NULL) {
return FALSE;
}
return m_pImageData->Delete(rguid);
}
BOOL CImage::DataPurge()
{
if (m_pImageData == NULL) {
return TRUE;
}
return m_pImageData->Purge();
}
//////////////////////////////////////////////////////////////////////////////
//
BOOL CImage::SizeOutputBuffer(DWORD cbData)
{
if (m_cbOutputBuffer < cbData) {
if (cbData < 1024) //65536
cbData = 1024;
cbData = FileAlign(cbData);
PBYTE pOutput = new BYTE [cbData];
if (pOutput == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return FALSE;
}
if (m_pbOutputBuffer) {
CopyMemory(pOutput, m_pbOutputBuffer, m_cbOutputBuffer);
delete[] m_pbOutputBuffer;
m_pbOutputBuffer = NULL;
}
ZeroMemory(pOutput + m_cbOutputBuffer, cbData - m_cbOutputBuffer),
m_pbOutputBuffer = pOutput;
m_cbOutputBuffer = cbData;
}
return TRUE;
}
PBYTE CImage::AllocateOutput(DWORD cbData, DWORD *pnVirtAddr)
{
cbData = QuadAlign(cbData);
PBYTE pbData = m_pbOutputBuffer + m_nOutputVirtSize;
*pnVirtAddr = m_nOutputVirtAddr + m_nOutputVirtSize;
m_nOutputVirtSize += cbData;
if (m_nOutputVirtSize > m_cbOutputBuffer) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
ZeroMemory(pbData, cbData);
return pbData;
}
//////////////////////////////////////////////////////////////////////////////
//
DWORD CImage::FileAlign(DWORD nAddr)
{
return Align(nAddr, m_NtHeader.OptionalHeader.FileAlignment);
}
DWORD CImage::SectionAlign(DWORD nAddr)
{
return Align(nAddr, m_NtHeader.OptionalHeader.SectionAlignment);
}
//////////////////////////////////////////////////////////////////////////////
//
PVOID CImage::RvaToVa(DWORD nRva)
{
if (nRva == 0) {
return NULL;
}
for (DWORD n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
if (nRva >= vaStart && nRva < vaEnd) {
return (PBYTE)m_pMap
+ m_SectionHeaders[n].PointerToRawData
+ nRva - m_SectionHeaders[n].VirtualAddress;
}
}
return NULL;
}
DWORD CImage::RvaToFileOffset(DWORD nRva)
{
DWORD n;
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
DWORD vaStart = m_SectionHeaders[n].VirtualAddress;
DWORD vaEnd = vaStart + m_SectionHeaders[n].SizeOfRawData;
if (nRva >= vaStart && nRva < vaEnd) {
return m_SectionHeaders[n].PointerToRawData
+ nRva - m_SectionHeaders[n].VirtualAddress;
}
}
return 0;
}
//////////////////////////////////////////////////////////////////////////////
//
BOOL CImage::CopyFileData(HANDLE hFile, DWORD nOldPos, DWORD cbData)
{
DWORD cbDone = 0;
return WriteFile(hFile, m_pMap + nOldPos, cbData, &cbDone, NULL);
}
BOOL CImage::ZeroFileData(HANDLE hFile, DWORD cbData)
{
if (!SizeOutputBuffer(4096)) {
return FALSE;
}
ZeroMemory(m_pbOutputBuffer, 4096);
for (DWORD cbLeft = cbData; cbLeft > 0;) {
DWORD cbStep = cbLeft > sizeof(m_pbOutputBuffer)
? sizeof(m_pbOutputBuffer) : cbLeft;
DWORD cbDone = 0;
if (!WriteFile(hFile, m_pbOutputBuffer, cbDone, &cbDone, NULL)) {
return FALSE;
}
if (cbDone == 0)
break;
cbLeft -= cbDone;
}
return TRUE;
}
BOOL CImage::AlignFileData(HANDLE hFile)
{
DWORD nLastFileAddr = m_nNextFileAddr;
m_nNextFileAddr = FileAlign(m_nNextFileAddr);
m_nNextVirtAddr = SectionAlign(m_nNextVirtAddr);
if (hFile != INVALID_HANDLE_VALUE) {
if (m_nNextFileAddr > nLastFileAddr) {
if (SetFilePointer(hFile, nLastFileAddr, NULL, FILE_BEGIN) == ~0u) {
return FALSE;
}
return ZeroFileData(hFile, m_nNextFileAddr - nLastFileAddr);
}
}
return TRUE;
}
BOOL CImage::Read(HANDLE hFile)
{
DWORD n;
PBYTE pbData = NULL;
DWORD cbData = 0;
if (hFile == INVALID_HANDLE_VALUE) {
SetLastError(ERROR_INVALID_HANDLE);
return FALSE;
}
///////////////////////////////////////////////////////// Create mapping.
//
m_nFileSize = GetFileSize(hFile, NULL);
if (m_nFileSize == (DWORD)-1) {
return FALSE;
}
m_hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (m_hMap == NULL) {
return FALSE;
}
m_pMap = (PBYTE)MapViewOfFile(m_hMap, FILE_MAP_COPY, 0, 0, 0);
if (m_pMap == NULL) {
return FALSE;
}
////////////////////////////////////////////////////// Process DOS Header.
//
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)m_pMap;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
m_nPeOffset = pDosHeader->e_lfanew;
/////////////////////////////////////////////////////// Process PE Header.
//
CopyMemory(&m_NtHeader, m_pMap + m_nPeOffset, sizeof(m_NtHeader));
if (m_NtHeader.Signature != IMAGE_NT_SIGNATURE) {
SetLastError(ERROR_INVALID_EXE_SIGNATURE);
return FALSE;
}
if (m_NtHeader.FileHeader.SizeOfOptionalHeader == 0) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
m_nSectionsOffset = m_nPeOffset
+ sizeof(m_NtHeader.Signature)
+ sizeof(m_NtHeader.FileHeader)
+ m_NtHeader.FileHeader.SizeOfOptionalHeader;
///////////////////////////////////////////////// Process Section Headers.
//
if (m_NtHeader.FileHeader.NumberOfSections > (sizeof(m_SectionHeaders) /
sizeof(m_SectionHeaders[0]))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -