朱朱你堕落了 发表于 2016-12-6 16:00

PE 重定位表

本帖最后由 hahacker 于 2016-12-6 16:04 编辑

网上的代码是错的,书上的解释是错的。一直不明白。后来看了看雪上有大牛的文章:也谈PE重定位表,这个文章是对的,重定位表有多少个,就是多少个,根本就没有所谓的:
直至某个块首结构的VirtualAddress为 0,表明重定位表结束。

网上的代码也是按这个思路这些写的,当然也是错的。
如某DLL,loadpe显示最后一个重定位块是:00025000


打开对应的十六进制模式为:


这已经是最后一个重定位块了,下面的00区域已经不是了,所以网上的:最后一个重定块的virtualaddress为零,是判断结束的条件,的确是错的,还好有大牛发文章指出来。

真的好久不写代码,已经不会写了,思路僵硬,想了半天,折腾了半天,终于算是搞出来了一段,测试没有问题。高手求放过。

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.VirtualAddress;
      dwRelocSize = pImageNtHeaders->OptionalHeader.DataDirectory.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上传上来,


caroot1996 发表于 2016-12-6 17:38

谢谢你的教程~~

風走過的路 发表于 2016-12-7 20:27

看不懂哦,不过还是感谢分享!

墨香青瓷 发表于 2016-12-11 07:56

慢慢学习中

343424993 发表于 2016-12-11 19:27

厉害      膜拜您

sstm 发表于 2016-12-23 12:20

www52pojiecn 发表于 2017-2-6 18:05

赞,谢谢

_默默_ 发表于 2019-4-27 08:50

我咋觉得没头没尾的

ok318 发表于 2019-4-28 17:00

看不懂哦,不过还是感谢分享!

洞见未来 发表于 2019-10-21 14:13

谢谢哈,新人来学习下
页: [1]
查看完整版本: PE 重定位表