class CPeInfo
{
public:
struct IAT_THUNK
{
IMAGE_THUNK_DATA * pThunkDat;
IMAGE_IMPORT_BY_NAME * pName;
CHAR * pApiName;
DWORD dwApiAddres;
};
struct PE_IATMOD
{
IMAGE_IMPORT_DESCRIPTOR * pImportDsp;
std::vector<IAT_THUNK *> ThunkList;
CHAR * pModName;
};
struct PE_INFO
{
IMAGE_DOS_HEADER * pDosHead;
IMAGE_NT_HEADERS * pNtHead;
std::vector<IMAGE_SECTION_HEADER *> SectionList;
std::vector<PE_IATMOD *> ModList;
std::vector<DWORD> RelocOffsetList;
};
CPeInfo()
{
}
~CPeInfo()
{
Clear();
}
BOOL Clear()
{
std::vector<PE_IATMOD *>::iterator ModIter;
std::vector<IAT_THUNK *>::iterator ThunkIter;
PE_IATMOD * pMod;
IAT_THUNK * pThunk;
for(ModIter = m_PeInfo.ModList.begin();
ModIter != m_PeInfo.ModList.end();
ModIter ++)
{
pMod = *ModIter;
if(pMod == NULL)
continue;
for(ThunkIter = pMod->ThunkList.begin();
ThunkIter != pMod->ThunkList.end();
ThunkIter ++)
{
pThunk = *ThunkIter;
if(pThunk == NULL)
continue;
delete pThunk;
}
delete pMod;
}
return TRUE;
}
BOOL LoadDll(CHAR *pFileName)
{
BOOL bRetVal;
Clear();
m_hMod = ::LoadLibraryA(pFileName);
if(m_hMod == NULL)
return FALSE;
NLog::DbgLog("Load: %s", pFileName);
bRetVal = CreatePEInfo();
return bRetVal;
}
BOOL CreatePEInfo()
{
BYTE * pImgData;
int nCount;
DWORD dwSize;
DWORD dwOffset;
int i, j, k;
IMAGE_IMPORT_DESCRIPTOR * pTempImpDsp;
if(m_hMod == NULL)
return FALSE;
pImgData = (BYTE *)m_hMod;
m_PeInfo.pDosHead = (IMAGE_DOS_HEADER *)pImgData;
m_PeInfo.pNtHead = (IMAGE_NT_HEADERS *)(pImgData + m_PeInfo.pDosHead->e_lfanew);
if(m_PeInfo.pNtHead->FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32))
return FALSE;
if(m_PeInfo.pNtHead->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)
return FALSE;
if (m_PeInfo.pNtHead->FileHeader.NumberOfSections < 1)
return FALSE;
// Section
IMAGE_SECTION_HEADER *pSection;
m_PeInfo.SectionList.clear();
nCount = m_PeInfo.pNtHead->FileHeader.NumberOfSections;
pSection = IMAGE_FIRST_SECTION(m_PeInfo.pNtHead);
for(i=1; i<nCount; i++)
{
m_PeInfo.SectionList.push_back(pSection);
pSection ++;
}
// IAT
PE_IATMOD * pOneMod;
dwOffset = m_PeInfo.pNtHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
m_PeInfo.ModList.clear();
pTempImpDsp = (IMAGE_IMPORT_DESCRIPTOR *)(pImgData + dwOffset);
for(i=0; ;i++)
{
if(pTempImpDsp->TimeDateStamp == 0 &&
pTempImpDsp->Name == 0)
break;
pOneMod = new PE_IATMOD;
pOneMod->pImportDsp = pTempImpDsp;
pOneMod->pModName = (CHAR *)(pImgData + pTempImpDsp->Name);
m_PeInfo.ModList.push_back(pOneMod);
NLog::DbgLog("Mods: %s", pOneMod->pModName);
ProcesIatMod(pImgData, pTempImpDsp, pOneMod);
pTempImpDsp ++;
}
// Relocation
IMAGE_BASE_RELOCATION * pReloca;
WORD * pOffsetDat;
DWORD dwTolOffset;
DWORD dwBlockOffset;
WORD wOneDat;
WORD wOneType;
DWORD dwOneOffset;
m_PeInfo.RelocOffsetList.clear();
dwOffset = m_PeInfo.pNtHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
if(dwOffset == 0)
goto RelocationEnd;
pReloca = (IMAGE_BASE_RELOCATION *)(pImgData + dwOffset);
for(;;)
{
if(pReloca->VirtualAddress == 0 ||
pReloca->SizeOfBlock == 0)
break;
dwBlockOffset = pReloca->VirtualAddress;
nCount = (pReloca->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
pOffsetDat = (WORD *)(pReloca + 1);
for(i=0; i<nCount; i++)
{
wOneDat = *pOffsetDat;
wOneType = wOneDat >> 12;
dwOneOffset = wOneDat & 0x0FFF;
if(wOneType == 0x03)
{
dwTolOffset = dwBlockOffset + dwOneOffset;
NLog::DbgLog("Relocation: %08X", dwTolOffset);
m_PeInfo.RelocOffsetList.push_back(dwTolOffset);
}
else
{
NLog::DbgLog("Relocation Unknow Type!");
}
}
pReloca = (IMAGE_BASE_RELOCATION *)((BYTE *)pReloca + pReloca->SizeOfBlock);
}
RelocationEnd:
return TRUE;
}
BOOL ProcesIatMod(BYTE * pImgData, IMAGE_IMPORT_DESCRIPTOR * pImportDsp, PE_IATMOD * pMod)
{
DWORD dwOffset;
int i;
PE_IATMOD * pCurMod;
IAT_THUNK * pOneThunk;
IMAGE_THUNK_DATA * pThunkData;
if(pImportDsp->OriginalFirstThunk != 0)
dwOffset = pImportDsp->OriginalFirstThunk;
else
dwOffset = pImportDsp->FirstThunk;
pThunkData = (IMAGE_THUNK_DATA *)(pImgData + dwOffset);
pCurMod = pMod;
for(i=0; ; i++)
{
if(pThunkData->u1.AddressOfData == 0)
break;
pOneThunk = new IAT_THUNK;
pOneThunk->pThunkDat = pThunkData;
dwOffset = pThunkData->u1.AddressOfData;
if(dwOffset & 0x80000000)
{
pOneThunk->pName = NULL;
pOneThunk->pApiName = NULL;
pOneThunk->dwApiAddres = dwOffset & 0x7FFFFFFF;
NLog::DbgLog(" API: %08X", pOneThunk->dwApiAddres);
}
else
{
pOneThunk->pName = (IMAGE_IMPORT_BY_NAME *)(pImgData + dwOffset);
pOneThunk->pApiName = (CHAR *)pOneThunk->pName->Name;
pOneThunk->dwApiAddres = 0;
NLog::DbgLog(" API: %s", pOneThunk->pApiName);
}
pCurMod->ThunkList.push_back(pOneThunk);
pThunkData ++;
}
return TRUE;
}
PE_INFO m_PeInfo;
HMODULE m_hMod;
};