in Detours/image.cpp [1052:1361]
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 = CreateFileMappingW(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
if (m_hMap == NULL) {
return FALSE;
}
m_pMap = (PBYTE)MapViewOfFileEx(m_hMap, FILE_MAP_READ, 0, 0, 0, NULL);
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;
m_nPrePE = 0;
m_cbPrePE = QuadAlign(pDosHeader->e_lfanew);
if (m_nPeOffset > m_nFileSize ||
m_nPeOffset + sizeof(m_NtHeader) > m_nFileSize) {
SetLastError(ERROR_BAD_EXE_FORMAT);
return FALSE;
}
CopyMemory(&m_DosHeader, m_pMap + m_nPrePE, sizeof(m_DosHeader));
/////////////////////////////////////////////////////// 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 > ARRAYSIZE(m_SectionHeaders)) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
CopyMemory(&m_SectionHeaders,
m_pMap + m_nSectionsOffset,
sizeof(m_SectionHeaders[0]) * m_NtHeader.FileHeader.NumberOfSections);
/////////////////////////////////////////////////// Parse .detour Section.
//
DWORD rvaOriginalImageDirectory = 0;
DWORD rvaDetourBeg = 0;
DWORD rvaDetourEnd = 0;
_Analysis_assume_(m_NtHeader.FileHeader.NumberOfSections <= ARRAYSIZE(m_SectionHeaders));
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
DETOUR_SECTION_HEADER dh;
CopyMemory(&dh,
m_pMap + m_SectionHeaders[n].PointerToRawData,
sizeof(dh));
rvaOriginalImageDirectory = dh.nOriginalImportVirtualAddress;
if (dh.cbPrePE != 0) {
m_nPrePE = m_SectionHeaders[n].PointerToRawData + sizeof(dh);
m_cbPrePE = dh.cbPrePE;
}
rvaDetourBeg = m_SectionHeaders[n].VirtualAddress;
rvaDetourEnd = rvaDetourBeg + m_SectionHeaders[n].SizeOfRawData;
}
}
//////////////////////////////////////////////////////// Get Import Table.
//
DWORD rvaImageDirectory = m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
PIMAGE_IMPORT_DESCRIPTOR iidp
= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaImageDirectory);
PIMAGE_IMPORT_DESCRIPTOR oidp
= (PIMAGE_IMPORT_DESCRIPTOR)RvaToVa(rvaOriginalImageDirectory);
if (oidp == NULL) {
oidp = iidp;
}
if (iidp == NULL || oidp == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
return FALSE;
}
DWORD nFiles = 0;
for (; iidp[nFiles].OriginalFirstThunk != 0 || iidp[nFiles].FirstThunk != 0; nFiles++) {
}
CImageImportFile **ppLastFile = &m_pImportFiles;
m_pImportFiles = NULL;
for (n = 0; n < nFiles; n++, iidp++) {
ULONG_PTR rvaName = iidp->Name;
PCHAR pszName = (PCHAR)RvaToVa(rvaName);
if (pszName == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
goto fail;
}
CImageImportFile *pImportFile = new NOTHROW CImageImportFile;
if (pImportFile == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
goto fail;
}
*ppLastFile = pImportFile;
ppLastFile = &pImportFile->m_pNextFile;
m_nImportFiles++;
pImportFile->m_pszName = DuplicateString(pszName);
if (pImportFile->m_pszName == NULL) {
goto fail;
}
pImportFile->m_rvaOriginalFirstThunk = iidp->OriginalFirstThunk;
pImportFile->m_rvaFirstThunk = iidp->FirstThunk;
pImportFile->m_nForwarderChain = iidp->ForwarderChain;
pImportFile->m_pImportNames = NULL;
pImportFile->m_nImportNames = 0;
pImportFile->m_fByway = FALSE;
if ((ULONG)iidp->FirstThunk >= rvaDetourBeg &&
(ULONG)iidp->FirstThunk < rvaDetourEnd) {
pImportFile->m_pszOrig = NULL;
pImportFile->m_fByway = TRUE;
continue;
}
rvaName = oidp->Name;
pszName = (PCHAR)RvaToVa(rvaName);
if (pszName == NULL) {
SetLastError(ERROR_EXE_MARKED_INVALID);
goto fail;
}
pImportFile->m_pszOrig = DuplicateString(pszName);
if (pImportFile->m_pszOrig == NULL) {
goto fail;
}
DWORD rvaThunk = iidp->OriginalFirstThunk;
if( !rvaThunk ) {
rvaThunk = iidp->FirstThunk;
}
PIMAGE_THUNK_DATA pAddrThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
rvaThunk = oidp->OriginalFirstThunk;
if( !rvaThunk ) {
rvaThunk = oidp->FirstThunk;
}
PIMAGE_THUNK_DATA pLookThunk = (PIMAGE_THUNK_DATA)RvaToVa(rvaThunk);
DWORD nNames = 0;
if (pAddrThunk) {
for (; pAddrThunk[nNames].u1.Ordinal; nNames++) {
}
}
if (pAddrThunk && nNames) {
pImportFile->m_nImportNames = nNames;
pImportFile->m_pImportNames = new NOTHROW CImageImportName [nNames];
if (pImportFile->m_pImportNames == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
goto fail;
}
CImageImportName *pImportName = &pImportFile->m_pImportNames[0];
for (DWORD f = 0; f < nNames; f++, pImportName++) {
pImportName->m_nOrig = 0;
pImportName->m_nOrdinal = 0;
pImportName->m_nHint = 0;
pImportName->m_pszName = NULL;
pImportName->m_pszOrig = NULL;
rvaName = pAddrThunk[f].u1.Ordinal;
if (rvaName & IMAGE_ORDINAL_FLAG) {
pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
pImportName->m_nOrdinal = pImportName->m_nOrig;
}
else {
PIMAGE_IMPORT_BY_NAME pName
= (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
if (pName) {
pImportName->m_nHint = pName->Hint;
pImportName->m_pszName = DuplicateString((PCHAR)pName->Name);
if (pImportName->m_pszName == NULL) {
goto fail;
}
}
rvaName = pLookThunk[f].u1.Ordinal;
if (rvaName & IMAGE_ORDINAL_FLAG) {
pImportName->m_nOrig = (ULONG)IMAGE_ORDINAL(rvaName);
pImportName->m_nOrdinal = (ULONG)IMAGE_ORDINAL(rvaName);
}
else {
pName = (PIMAGE_IMPORT_BY_NAME)RvaToVa(rvaName);
if (pName) {
pImportName->m_pszOrig
= DuplicateString((PCHAR)pName->Name);
if (pImportName->m_pszOrig == NULL) {
goto fail;
}
}
}
}
}
}
oidp++;
}
////////////////////////////////////////////////////////// Parse Sections.
//
m_nExtraOffset = 0;
for (n = 0; n < m_NtHeader.FileHeader.NumberOfSections; n++) {
m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
m_SectionHeaders[n].SizeOfRawData,
m_nExtraOffset);
if (strcmp((PCHAR)m_SectionHeaders[n].Name, ".detour") == 0) {
DETOUR_SECTION_HEADER dh;
CopyMemory(&dh,
m_pMap + m_SectionHeaders[n].PointerToRawData,
sizeof(dh));
if (dh.nDataOffset == 0) {
dh.nDataOffset = dh.cbHeaderSize;
}
cbData = dh.cbDataSize - dh.nDataOffset;
pbData = (m_pMap +
m_SectionHeaders[n].PointerToRawData +
dh.nDataOffset);
m_nExtraOffset = Max(m_SectionHeaders[n].PointerToRawData +
m_SectionHeaders[n].SizeOfRawData,
m_nExtraOffset);
m_NtHeader.FileHeader.NumberOfSections--;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress
= dh.nOriginalImportVirtualAddress;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size
= dh.nOriginalImportSize;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress
= dh.nOriginalBoundImportVirtualAddress;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size
= dh.nOriginalBoundImportSize;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress
= dh.nOriginalIatVirtualAddress;
m_NtHeader.OptionalHeader
.DataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size
= dh.nOriginalIatSize;
m_NtHeader.OptionalHeader.CheckSum = 0;
m_NtHeader.OptionalHeader.SizeOfImage
= dh.nOriginalSizeOfImage;
m_fHadDetourSection = TRUE;
}
}
m_pImageData = new NOTHROW CImageData(pbData, cbData);
if (m_pImageData == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
}
return TRUE;
fail:
return FALSE;
}