由PE装载器将PE文件加到虚拟内存时使用的地址均是RVA地址, 而在文件中存放的数据的地址是基于文件的偏移地址, 因此存在一个从RVA到偏移地址的转换过程。当我们通过内存映射文件的方式获取文件数据内容时使用的是基于文件的偏移地址,这样才能正确获取我们所要获取的数据。
template <class T> void DumpImportsSection(PBYTE pImageBase, T * pNTHeader) // 'T' = PIMAGE_NT_HEADERS
{
PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
DWORD importsStartRVA;
// Look up where the imports section is (normally in the .idata section)
// but not necessarily so. Therefore, grab the RVA from the data dir.
importsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT);
if ( !importsStartRVA )
return;
pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)GetPtrFromRVA(importsStartRVA,pNTHeader,pImageBase);
for (;pImportDesc->Name;pImportDesc++)
{
if (pImportDesc->Name ==NULL)
return;
LPSTR pszDllName = (LPSTR)GetPtrFromRVA(pImportDesc->Name,pNTHeader,pImageBase);
//寻找我们想要的函数
DWORD dwThunkRVA = pImportDesc->OriginalFirstThunk;
if (dwThunkRVA == 0)
{
dwThunkRVA = pImportDesc->FirstThunk;
}
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA) GetPtrFromRVA(dwThunkRVA,pNTHeader,pImageBase);//IAT
for (;pThunk->u1.Function;pThunk++)
{
DWORD dwImportNameRVA = pThunk->u1.AddressOfData;
PIMAGE_IMPORT_BY_NAME pImportName = (PIMAGE_IMPORT_BY_NAME) GetPtrFromRVA(dwImportNameRVA,pNTHeader,pImageBase);//IAT
int i = 0;
}
if ( !pImportDesc )
return;
}
}
template <class T> LPVOID GetPtrFromRVA( DWORD rva, T* pNTHeader, PBYTE imageBase ) // 'T' = PIMAGE_NT_HEADERS
{
PIMAGE_SECTION_HEADER pSectionHdr;
INT delta;
pSectionHdr = GetEnclosingSectionHeader( rva, pNTHeader );
if ( !pSectionHdr )
return 0;
delta = (INT)(pSectionHdr->VirtualAddress-pSectionHdr->PointerToRawData);
return (PVOID) ( imageBase + rva - delta );
}