本帖最后由 hahacker 于 2016-12-6 16:04 编辑
网上的代码是错的,书上的解释是错的。一直不明白。后来看了看雪上有大牛的文章:也谈PE重定位表,这个文章是对的,重定位表有多少个,就是多少个,根本就没有所谓的:
直至某个块首结构的VirtualAddress为 0,表明重定位表结束。
网上的代码也是按这个思路这些写的,当然也是错的。
如某DLL,loadpe显示最后一个重定位块是:00025000
打开对应的十六进制模式为:
这已经是最后一个重定位块了,下面的00区域已经不是了,所以网上的:最后一个重定块的virtualaddress为零,是判断结束的条件,的确是错的,还好有大牛发文章指出来。
真的好久不写代码,已经不会写了,思路僵硬,想了半天,折腾了半天,终于算是搞出来了一段,测试没有问题。高手求放过。
[C++] 纯文本查看 复制代码 void CchongdingweiDlg::OnBnClickedBtnOpenfile()
{
//IDC_EDIT_FILEPATH
CString strFilePath;
CFileDialog fileDlg(TRUE);
if (fileDlg.DoModal() == IDOK)
{
strFilePath = fileDlg.GetPathName();
SetDlgItemText(IDC_EDIT_FILEPATH, strFilePath);
}
if (strFilePath.IsEmpty())
return;
hFile = CreateFile(strFilePath, GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
return;
HANDLE hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, 0);
if (hMap == NULL)
{
CloseHandle(hMap);
MessageBox("创建文件映像失败");
return;
}
LPVOID pMapData;
pMapData = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
if (pMapData == NULL)
{
CloseHandle(hMap);
MessageBox("映像数据为空!");
return;
}
PIMAGE_DOS_HEADER pImageDosHeader = NULL;
pImageDosHeader = (PIMAGE_DOS_HEADER)pMapData;
PIMAGE_NT_HEADERS pImageNtHeaders;
pImageNtHeaders = (PIMAGE_NT_HEADERS)((DWORD)pMapData + pImageDosHeader->e_lfanew);
if (pImageNtHeaders->Signature != IMAGE_NT_SIGNATURE)
{
MessageBox("这不是一个pe文件");
return;
}
DWORD dwRelocRva = 0;
DWORD dwRelocSize = 0;
dwRelocRva = pImageNtHeaders->OptionalHeader.DataDirectory[5].VirtualAddress;
dwRelocSize = pImageNtHeaders->OptionalHeader.DataDirectory[5].Size;
CString str;
str.Format("rva: 0x%08x, size: 0x%08x", dwRelocRva, dwRelocSize);
MessageBox(str);
DWORD dwOffset = 0;
CString strSectionName;
dwOffset = RvaToOffset(pImageNtHeaders, dwRelocRva, strSectionName);
str.Format("section: %s,offset: 0x%08x", strSectionName, dwOffset);
MessageBox(str);
DWORD SizeOfBlock = 0;
DWORD sum = 0;
int index = 0;
do
{
index++;
PIMAGE_BASE_RELOCATION pImageBaseRelocation;
pImageBaseRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pMapData + dwOffset + sum);
DWORD VirtualAddress = pImageBaseRelocation->VirtualAddress;
CString strSectionName;
RvaToOffset(pImageNtHeaders, VirtualAddress, strSectionName);
str.Format("项数:%d, 所属区段:%s, rva: 0x%08x", index, strSectionName, VirtualAddress);
OutputDebugString(str);
SizeOfBlock = pImageBaseRelocation->SizeOfBlock;
sum += SizeOfBlock;
dwRelocSize -= SizeOfBlock;
} while (dwRelocSize);
CloseHandle(hMap);
CloseHandle(hFile);
}
DWORD CchongdingweiDlg::RvaToOffset(PIMAGE_NT_HEADERS pImageNtHeaders, DWORD dwRva, CString & strSectionName)
{
DWORD dwOffset = 0;
int NumberOfSections = 0;
NumberOfSections = pImageNtHeaders->FileHeader.NumberOfSections;
PIMAGE_SECTION_HEADER pImageSectionHeader;
pImageSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pImageNtHeaders + sizeof(IMAGE_NT_HEADERS));
for (int i = 0; i < NumberOfSections; i++)
{
if ((dwRva >= pImageSectionHeader->VirtualAddress) && (dwRva < pImageSectionHeader->VirtualAddress + pImageSectionHeader->SizeOfRawData ))
{
dwOffset = dwRva - (pImageSectionHeader->VirtualAddress - pImageSectionHeader->PointerToRawData);
strSectionName = pImageSectionHeader->Name;
break;
}
pImageSectionHeader++;
}
return dwOffset;
}
这样和LoadPE的结果是一样的。
为方便后来人学习,把这个dll上传上来,
重定位测试DLL.rar
(22.6 KB, 下载次数: 44)
|