2016wapjpc 发表于 2019-7-28 12:18

【笔记】重定位表的修复

在做重定位表的修复这个代码的时候,我写了1个小时,调试正确,没有错误,可是复制到程序目录下地运行就错了,用od一加载,出错,没有加载dll.
我的dll的基址原来是0x100000000,现在修改为0x20000000,要dll复制到程序目录下地运行程序,那么加载成功的话,dll加载到内存就是20000000这地址,
那重定位就正确了。

在写代码时,把dll放到内存的代码是

size = ReadPEFile(FILEPATH_IN,&pFileBuffer);
printf("path: %s\t size :%d byte\n",FILEPATH_IN,size );

          
                if(size == 0 || !pFileBuffer)
                {

                        printf("read fileBuffer error! \n");

                                return;
                }

                if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)

                {
                        printf("invalid mz \n");

                        free(pFileBuffer);
                        return ;
                }
              pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

       if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
                {
                        printf("invalid pe signature \n");
                        free(pFileBuffer);
                        return;

                }
        pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
      pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pFileBuffer+(pDosHeader->e_lfanew + 0x4));
      printf(" ImageBase = %x \n", pNTHeader->OptionalHeader.ImageBase;

       //复制新的pNewBuffer
                pNewBuffer = malloc(size);
                if(!pNewBuffer)
                {
                printf("add new buffer for pefailure");
                                free(pNewBuffer);

                return ;
      }
               //置新申请的空间为0
                  memset(pNewBuffer,0,size);
                memcpy(pNewBuffer,pFileBuffer,size);
                pDosHeader = (PIMAGE_DOS_HEADER)pNewBuffer;
                pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pNewBuffer+pDosHeader->e_lfanew);
                pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNewBuffer+(pDosHeader->e_lfanew + 0x4));
      
         
                //重定位表的foa地址
          DWORD dwRva=        pNTHeader->OptionalHeader.DataDirectory.VirtualAddress;

          printf("Reloaction data dierctory VirtualAddress = %x \n",dwRva );

                        //relaction data tablefoa offset 转化为文件地址的偏移
         DWORD ReloactionFileAddr = RvaToFileOffset( pNewBuffer, dwRva);
           printf("Relocation DD FileAddr =%x \n",ReloactionFileAddr );

            //relaction data table文件开始+ 文件地址的偏移第一个重定位块

           PIMAGE_BASE_RELOCATION pRelcation =(PIMAGE_BASE_RELOCATION)((DWORD)pNewBuffer+ ReloactionFileAddr );
      
           DWORD OldImage = pNTHeader->OptionalHeader.ImageBase;

         pNTHeader->OptionalHeader.ImageBase = 0x20000000;

                                     
                //对需要重定位的数据文件地址定位
                  DWORD Relocationfoa =RvaToFileOffset( pNewBuffer,RelocAddress);
                   //取到这个rva地址上的值,再修改
                   PDWORD Relocataddess = (PDWORD)((DWORD)pNewBuffer+Relocationfoa);
                                  
                   //2019 7 27 修正
                               
                  *Relocataddess +=pNTHeader->OptionalHeader.ImageBase -OldImage;
      
      isOK =MemoryToFile(pNewBuffer, size , FILEPATH_OUT15);
         if(isOK)
               {
                printf(" 修改imagebase BaseRelocation tableOK,%s ! (^_^)\n",FILEPATH_OUT15);
                                return ;
         }
       
    free(pFileBuffer);
    free(pNewBuffer);
}
我在写代码时,把地址用的还是pFIleBuffer ,而不是pNewBuffer,所以错了,后来改过来就对了,上两张图,以做记念大热天的学习生活。




页: [1]
查看完整版本: 【笔记】重定位表的修复