PE合并节
把所有節合并成一個節,好處是可以騰出節表空間,保證能成功新增節。
方法是先拉伸成imagebuffer,修改第一個節的VirtualSize = SizeOfRawData = SizeOfImage - VirtualAddress,因為PE文件本身就對齊好了,所以不用關心對齊問題。由于修改了SizeOfRawData ,處理后PE文件會變大。除此之外還要修改節的數量,和第一個節必須具有其他節的屬性。
代碼
// 合并所有節 BOOL MergeSection(LPVOID pImageBuffer, LPVOID *pNewImageBuffer, DWORD dwImageSize) {*pNewImageBuffer = malloc(dwImageSize);if (*pNewImageBuffer == NULL){printf("分配內存失敗\n");return FALSE;}memcpy(*pNewImageBuffer, pImageBuffer, dwImageSize);PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)*pNewImageBuffer;PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pDosHeader + pDosHeader->e_lfanew + 4);PIMAGE_OPTIONAL_HEADER32 pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + sizeof(IMAGE_FILE_HEADER));PIMAGE_SECTION_HEADER pSectionHeader = \(PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);PIMAGE_SECTION_HEADER pLastSectionHeader = pSectionHeader + pPEHeader->NumberOfSections - 1;// 修改第一個節的范圍以覆蓋其他所有節pSectionHeader->SizeOfRawData = pSectionHeader->Misc.VirtualSize = \pOptionHeader->SizeOfImage - pSectionHeader->VirtualAddress;pSectionHeader->SizeOfRawData = Align(pSectionHeader->SizeOfRawData, pOptionHeader->FileAlignment);// 屬性包含所有節的屬性for (int i = 1; i < pPEHeader->NumberOfSections; i++){pSectionHeader[0].Characteristics |= pSectionHeader[i].Characteristics;}// 清空其他節表的數據,這步是為了合并節后新增節方便memset(pSectionHeader + 1, 0, sizeof(IMAGE_SECTION_HEADER) * (pPEHeader->NumberOfSections - 1));// 節的數量 = 1pPEHeader->NumberOfSections = 1;return TRUE; }結果
測試了幾個32位GUI程序,擴大后均能正常運行。
下圖是notepad合并節后的結果對比:
可以看到,文件大小改變了,節的數量也由原來的3變成了1。
總結