扩大节、合并节

如果pe头部没有足够的空间插入一个新的节表,可以考虑扩大最后一个节; 注意是最后一个节,如果扩大中间的节,很可能造成后面的节整体偏移而找不到;   1.扩大节的大概步骤 1】读取文件到缓冲区; 2】拉伸文件镜像; 3】分配一个新的空间:SizeOfImage + Ex; 4】修改最后一个节表的数据:     SizeOfRawData = Misc.VirtualSize = N;    ->因为无法确定这两个数哪个大     N = (SizeOfRawData或VirtualSize内存对齐后的值) + Ex; 5】修改SizeOfImage的大小; 7】压缩、存盘 扩大节、合并节扩大节、合并节   2.用代码实现扩大节 #include "stdafx.h" #include "petool.h" #include "string.h"   #define SRC "C:\\Users\\Administrator\\Desktop\\TraceMe.exe" #define DEST "C:\\Users\\Administrator\\Desktop\\copy1.exe"   //扩大最后一个节 void lastSecInc(){     //定义头结构指针     PIMAGE_DOS_HEADER dosHeader = NULL;        //dos头指针     PIMAGE_FILE_HEADER peHeader = NULL;        //pe头指针     PIMAGE_OPTIONAL_HEADER32 opHeader = NULL;    //可选pe头指针     PIMAGE_SECTION_HEADER seHeader = NULL;    //节表指针     PIMAGE_SECTION_HEADER lastSeHeader = NULL;    //最后一个节表指针          LPVOID pFileBuffer = NULL;         //1.加载文件到内存     DWORD size = ReadPEFile(SRC, &pFileBuffer);     if(!pFileBuffer){         printf("读取文件失败\n");         return;     }     //2.拉伸文件镜像     LPVOID pImageBuffer = NULL;     DWORD imageSize = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);     if(!imageSize){         printf("拉伸文件失败\n");         free(pFileBuffer);         return;     }     //4.扩大内存镜像     LPVOID newImageBuffer = NULL;     DWORD newImageSize = imageSize + 0x1000;    //目标文件的内存对齐是1000文件对齐是200,就扩大1000正好为两个数的整数倍     newImageBuffer = malloc(newImageSize);         if(! newImageBuffer){         printf("给扩大后的内存镜像申请内存失败\n");         free(pFileBuffer);         free(pImageBuffer);         return;     }     //初始化内存空间     memset(newImageBuffer, 0, newImageSize);     //复制内存镜像到新的空间     memcpy(newImageBuffer, pImageBuffer, imageSize);     //4.初始化头指针     dosHeader = (PIMAGE_DOS_HEADER) newImageBuffer;     peHeader = (PIMAGE_FILE_HEADER)((DWORD)newImageBuffer + dosHeader->e_lfanew + 4);     opHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)peHeader + IMAGE_SIZEOF_FILE_HEADER);     seHeader = (PIMAGE_SECTION_HEADER)((DWORD)opHeader + peHeader->SizeOfOptionalHeader);     //5.修改头部信息     //修改节表信息     lastSeHeader = seHeader + (peHeader->NumberOfSections - 1);     lastSeHeader->Misc.VirtualSize = lastSeHeader->Misc.VirtualSize + 0x1000;     lastSeHeader->SizeOfRawData = lastSeHeader->SizeOfRawData + 0x1000;       //修改SizeOfImage     opHeader->SizeOfImage = opHeader->SizeOfImage+0x1000;     //6.压缩新内存镜像     LPVOID newBuffer = NULL;     DWORD newBufferSize = CopyImageBufferToNewBuffer(newImageBuffer, &newBuffer);     if(!newBufferSize){         printf("压缩新内存镜像失败\n");         free(pFileBuffer);         free(pImageBuffer);         free(newImageBuffer);         return;     }     //7.写出文件     BOOL isOk = MemeryTOFile(newBuffer, newBufferSize, DEST);     if(!isOk){         printf("存盘失败\n");     }else{         printf("存盘成功\n");     }     //8.释放内存     free(pFileBuffer);     free(pImageBuffer);     free(newImageBuffer);     free(newBuffer);     return;   }   int main(int argc, char* argv[]) {     lastSecInc();     getchar();     return 0; }     3.合并节 合并节是将多个节合并; 例如所有节合并为一个节:     1】只保留一个节表;     2】所有的节当作一个节,将描述信息写在第一个节表中;   意义:     合并节后,原来节表的地方空出来了,可以方便插入新节;     有多个节时,拉伸时需要循环遍历各个节表做对齐之类的操作;合并节表后减少了这些操作;   影响:文件可能变大;   步骤:        1)拉伸到内存     2)将第一个节的内存大小、文件大小改成一样        Max = SizeOfRawData>VirtualSize?SizeOfRawData:VirtualSize        SizeOfRawData = VirtualSize = 最后一个节的VirtualAddress + Max - SizeOfHeaders内存对齐后的大小     3)将第一个节的属性改为包含所有节的属性     4)修改节的数量为1 扩大节、合并节扩大节、合并节   4.程序实现合并节 内存对齐的工具方法: //对齐 DWORD align(int size, int fileSize){     //如果尺寸小于对齐尺寸则按对齐尺寸算     if(size <= fileSize){         return fileSize;     }     //向上取整*对齐尺寸的倍数     int n = size%fileSize;     if(n == 0){         n = size/fileSize;             }else{         n = seze/fileSize + 1;     }     return n*fileSize; } 合并节: //失败了,先放着        
上一篇:手写PE结构解析工具


下一篇:WindowsPE 导入表