PE文件的两种状态 如下图,当PE文件于硬盘中存放时按照FileAlignment对齐,在内存中时按照SectionAlignment对齐,整个头可视为一体,在节表的最后和每个节区的最后按照格式对齐。
PE文件的拉伸与压缩 拉伸时将每个节区的PointerToRawData写入到VirtualAddress,反之亦然,头部直接按照SizeOfHeaders写入就行了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 LPVOID file2Image (LPVOID lpFileBuffer, DWORD *pdwBufferSize) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpFileBuffer; PIMAGE_NT_HEADERS pNT = (PIMAGE_NT_HEADERS)((DWORD)lpFileBuffer + pDos->e_lfanew); PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pNT + 4 ); PIMAGE_OPTIONAL_HEADER pOption = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER); PIMAGE_SECTION_HEADER pFirstSection = PIMAGE_SECTION_HEADER ((DWORD)pOption + pFile->SizeOfOptionalHeader); LPVOID lpImageBuffer = malloc (pOption->SizeOfImage); memset (lpImageBuffer, 0 , pOption->SizeOfImage); memcpy (lpImageBuffer, lpFileBuffer, pOption->SizeOfHeaders); PIMAGE_SECTION_HEADER pSectionHeader = pFirstSection; for (int i = 0 ; i < pFile->NumberOfSections; i++) { memcpy ( (LPVOID)((DWORD)lpImageBuffer + pSectionHeader->VirtualAddress), (LPVOID)((DWORD)lpFileBuffer + pSectionHeader->PointerToRawData), pSectionHeader->Misc.VirtualSize ); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER); } *pdwBufferSize = pOption->SizeOfImage; return lpImageBuffer; } LPVOID image2File (LPVOID lpImageBuffer, DWORD *pdwBufferSize) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImageBuffer; PIMAGE_NT_HEADERS pNT = (PIMAGE_NT_HEADERS)((DWORD)lpImageBuffer + pDos->e_lfanew); PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pNT + 4 ); PIMAGE_OPTIONAL_HEADER pOption = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER); PIMAGE_SECTION_HEADER pFirstSection = PIMAGE_SECTION_HEADER ((DWORD)pOption + pFile->SizeOfOptionalHeader); PIMAGE_SECTION_HEADER pLastSection = PIMAGE_SECTION_HEADER ((DWORD)pFirstSection + ((pFile->NumberOfSections - 1 ) * IMAGE_SIZEOF_SECTION_HEADER)); *pdwBufferSize = pLastSection->PointerToRawData + pLastSection->SizeOfRawData; LPVOID lpFileBuffer = malloc (*pdwBufferSize); memset (lpFileBuffer, 0 , *pdwBufferSize); memcpy (lpFileBuffer, lpImageBuffer, pOption->SizeOfHeaders); PIMAGE_SECTION_HEADER pSectionHeader = pFirstSection; for (int i = 0 ; i < pFile->NumberOfSections; i++) { memcpy ( (LPVOID)((DWORD)lpFileBuffer + pSectionHeader->PointerToRawData), (LPVOID)((DWORD)lpImageBuffer + pSectionHeader->VirtualAddress), pSectionHeader->SizeOfRawData ); pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER); } return lpFileBuffer; }
遍历目录项 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <Windows.h> #include <stdio.h> #include <stdlib.h> #include <PETool.h> #pragma comment(lib,"PETool.lib" ) #define FILEPATH TEXT("D:\\absolution\\temporary\\test.exe" ) #define OUTFILEPATH TEXT("D:\\absolution\\temporary\\output.exe" ) int main () { LPVOID lpFileBuffer = createFileBuffer (FILEPATH); if (!lpFileBuffer) { return 0 ; } DWORD dwSize; LPVOID lpImageBuffer = file2Image (lpFileBuffer, &dwSize); PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpImageBuffer; PIMAGE_NT_HEADERS pNT = (PIMAGE_NT_HEADERS)((DWORD)lpImageBuffer + pDos->e_lfanew); PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pNT + 4 ); PIMAGE_OPTIONAL_HEADER pOption = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER); PIMAGE_SECTION_HEADER pFirstSection = (PIMAGE_SECTION_HEADER)((DWORD)pOption + pFile->SizeOfOptionalHeader); for (int i = 0 ; i < pOption->NumberOfRvaAndSizes; i++) { IMAGE_DATA_DIRECTORY IDD = pOption->DataDirectory[i]; printf ("表项%d \n%X\n%X\n---------\n" , i, IDD.VirtualAddress, IDD.Size); } free (lpImageBuffer); free (lpFileBuffer); getchar (); }