重定位表的移动

很笨的方法

(写过才能知道,哪些地方,需要注意,开始想的很简单,就三部,写了 一个多小时!!)

001void TestMoveRelocDirectory(LPSTR lpszFile)
002{
003    /*
004    1 新增一个节
005    2 把重定位的表 移动到那个节中
006    3 更改标志位
007    */
008    LPVOID pFileBuffer = NULL;
009    pFileBuffer= ReadPEFile(lpszFile);
010    if(!pFileBuffer)
011    {
012        printf("文件读取失败\n");
013        return;
014    }
015     
016    PIMAGE_DOS_HEADER pDosHeader = NULL;
017    PIMAGE_NT_HEADERS pNTHeader = NULL;
018    PIMAGE_FILE_HEADER pPEHeader = NULL;
019    PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
020    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
021    PIMAGE_SECTION_HEADER pSectionHeader_ADD = NULL;
022    PIMAGE_DATA_DIRECTORY DataDirectory=NULL;
023     
024    //Header信息
025    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
026    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
027    pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
028    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
029    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
030    pSectionHeader_ADD = pSectionHeader;
031     
032    //1 判断能否添加节
033    DWORD Header_size = pDosHeader->e_lfanew + 4 + 20 + pPEHeader->SizeOfOptionalHeader + pPEHeader->NumberOfSections*40;
034    if(pOptionHeader->SizeOfHeaders-Header_size<80)
035    {
036        printf("没有可用空间填充节表\n");
037        free(pFileBuffer);
038        return;
039    }
040     
041    printf("空间:%d\n",pOptionHeader->SizeOfHeaders-Header_size);
042     
043 
044    //添加一个节
045    //确定参数
046    PIMAGE_SECTION_HEADER pSectionHeader_LAST = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);
047    pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader_ADD+(pPEHeader->NumberOfSections)*40);
048    //="NewSec";
049    strcpy((char*)pSectionHeader_ADD->Name,"NewSec");
050    pSectionHeader_ADD->Misc.VirtualSize = 0x2000;
051    pSectionHeader_ADD->VirtualAddress = pOptionHeader->SizeOfImage;
052    pSectionHeader_ADD->SizeOfRawData = 0x2000;
053    pSectionHeader_ADD->PointerToRawData = pSectionHeader_LAST->PointerToRawData+pSectionHeader_LAST->SizeOfRawData;
054    pSectionHeader_ADD->Characteristics = pSectionHeader->Characteristics;
055 
056    //填充0
057    LPVOID pSectionEND = (LPVOID)((DWORD)pSectionHeader_ADD+40);
058    memset(pSectionEND,0,IMAGE_SIZEOF_SECTION_HEADER);
059 
060     
061    //修改PE头信息
062    pPEHeader->NumberOfSections = pPEHeader->NumberOfSections +1;
063    pOptionHeader->SizeOfImage  = pOptionHeader->SizeOfImage+0x2000;
064 
065    //写入到文件
066    FILE *pOutFile = NULL; 
067    //打开文件
068    pOutFile = fopen("C://addSec.dll","a+b");
069     
070    if(!pOutFile)
071    {
072        printf("无法打开文件EXE文件");
073        return;
074    }
075    //写出第一部分
076    printf("length: %x \n ",pSectionHeader_ADD->PointerToRawData+pSectionHeader_ADD->SizeOfRawData);
077 
078    size_t writeSize = fwrite(pFileBuffer,pSectionHeader_ADD->PointerToRawData,1,pOutFile);
079    printf("WirteSize:%d\n",writeSize);
080    //写出第二部分
081    LPVOID pNewBuffer=(LPVOID)malloc(0x2000);
082    if(pNewBuffer==NULL)
083    {
084        printf("pNewBuffer分配空间失败\n");
085        return;
086    }
087    memset(pNewBuffer,0,0x2000);
088    writeSize = fwrite(pNewBuffer,0x2000,1,pOutFile);
089    //关闭文件
090    fclose(pOutFile);
091    free(pFileBuffer);
092    free(pNewBuffer);
093 
094    //读入添加好节的文件
095    pFileBuffer= ReadPEFile("C://addSec.dll");
096     
097    //将重定位表的信息,放到最后一个节中
098        //Header信息
099    pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
100    pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew);
101    pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4);
102    pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
103    pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader+pPEHeader->SizeOfOptionalHeader);
104    //最后一个节
105    pSectionHeader_ADD=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+(pPEHeader->NumberOfSections-1)*40);
106 
107    //定位Directory_Data;
108    DataDirectory = pOptionHeader->DataDirectory;
109     
110    //重定位表
111 
112    printf("IMAGE_DIRECTORY_ENTRY_BASERELOC: Address: %x ,Size: %x \n",DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
113        DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
114 
115    //DWORD RVAToFileOffset(LPVOID pFileBuffer,DWORD dwRva)
116    DWORD FoA = RVAToFileOffset(pFileBuffer,0x2df10);
117     
118    DWORD BaseReloc_Directory_Address = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
119    DWORD BaseReloc_Directory_Size = DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
120    FoA = RVAToFileOffset(pFileBuffer,BaseReloc_Directory_Address);
121     
122 
123    //定位到第一个重定位块
124    PIMAGE_BASE_RELOCATION pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);
125    PIMAGE_BASE_RELOCATION pRelocData_Start = (PIMAGE_BASE_RELOCATION)((DWORD)pFileBuffer + FoA);
126 
127    DWORD sizeOfRelocDirectory = 0;
128    //计算重定位表的大小
129    while(pRelocData->VirtualAddress||pRelocData->SizeOfBlock)
130    {
131        DWORD RelocVirtualAddress = pRelocData->VirtualAddress;
132        DWORD RelocSize = pRelocData->SizeOfBlock;
133 
134        sizeOfRelocDirectory = sizeOfRelocDirectory + RelocSize;
135 
136        pRelocData = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocData + RelocSize);
137    }
138 
139    //起始位置pRelocData
140     
141     
142    //移动
143    PDWORD myRelocLoc = (PDWORD)pSectionHeader_ADD->PointerToRawData;
144    printf("Reloc: %x , Size: %x \n",pRelocData,sizeOfRelocDirectory);
145     
146 
147    //memcpy(myRelocLoc,pRelocData,sizeOfRelocDirectory);
148    LPVOID destStart = (LPVOID)((DWORD)pFileBuffer + (DWORD)myRelocLoc);
149 
150    printf("pFileBuffer:%x, myRelocLoc: %x \n",pFileBuffer,destStart);
151 
152    LPVOID srcStart = (LPVOID)(pRelocData_Start);
153     
154    memcpy(destStart,srcStart,sizeOfRelocDirectory);
155     
156     
157    //修改重定位表的参数
158    DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = FileOffsetToRVA(pFileBuffer,pSectionHeader_ADD->PointerToRawData);
159 
160    //写出到dll中
161    DWORD FileSize = pSectionHeader_ADD->PointerToRawData + pSectionHeader_ADD->SizeOfRawData;
162 
163    WirteToFile(pFileBuffer,FileSize,"C://addNewSec.dll");
164 
165}

 

原文链接: 重定位表的移动 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( http://www.gyarmy.com/?post=312 )

发表评论

0则评论给“重定位表的移动”