PE文件添加新区块时间:2022-02-09 19:04:21 PE文件添加新区块 1.NT头 typedef struct _IMAGE_NT_HEADERS { DWORD Signature; IMAGE_FILE_HEADER FileHeader; IMAGE_OPTIONAL_HEADER32 OptionalHeader; } IMAGE_NT_HEADERS32, *PIMAGE_NT_HEADERS32; 2.可选头 typedef struct _IMAGE_OPTIONAL_HEADER { // // Standard fields. // WORD Magic; BYTE MajorLinkerVersion; BYTE MinorLinkerVersion; DWORD SizeOfCode; DWORD SizeOfInitializedData; DWORD SizeOfUninitializedData; DWORD AddressOfEntryPoint; DWORD BaseOfCode; DWORD BaseOfData; // // NT additional fields. // DWORD ImageBase; DWORD SectionAlignment; // 内存中的区块对齐值 NT头偏移38h DWORD FileAlignment; // 文件中的区块对齐值 NT头偏移3Ch WORD MajorOperatingSystemVersion; WORD MinorOperatingSystemVersion; WORD MajorImageVersion; WORD MinorImageVersion; WORD MajorSubsystemVersion; WORD MinorSubsystemVersion; DWORD Win32VersionValue; DWORD SizeOfImage; DWORD SizeOfHeaders; DWORD CheckSum; WORD Subsystem; WORD DllCharacteristics; DWORD SizeOfStackReserve; DWORD SizeOfStackCommit; DWORD SizeOfHeapReserve; DWORD SizeOfHeapCommit; DWORD LoaderFlags; DWORD NumberOfRvaAndSizes; IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32; 3.数据目录 typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; DWORD Size; } IMAGE_DATA_DIRECTORY, *PIMAGE_DATA_DIRECTORY; #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 4.区块表 #define IMAGE_SIZEOF_SHORT_NAME 8 typedef struct _IMAGE_SECTION_HEADER { BYTE Name[IMAGE_SIZEOF_SHORT_NAME]; union { DWORD PhysicalAddress; DWORD VirtualSize; // 区块实际大小 } Misc; DWORD VirtualAddress; // 区块在内存中的偏移(SectionAlignment的整数倍) DWORD SizeOfRawData; // 区块在文件中的大小(FileAlignment的整数倍) DWORD PointerToRawData; // 区块在文件中的偏移(FileAlignment的整数倍) DWORD PointerToRelocations; DWORD PointerToLinenumbers; WORD NumberOfRelocations; WORD NumberOfLinenumbers; DWORD Characteristics; // 区块属性 } IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; DWORD GetAlignmentSize(DWORD dwSize, DWORD dwAlign) { DWORD dwMod = dwSize % dwAlign; if(dwMod == 0) return dwSize; else return dwSize + (dwAlign - dwMod); } 1.设置新的文件大小 newFileSize = GetAlignmentSize(INSERT_SIZE + oldFileSize, dwFileAlign); 2.新区块表的设置: Name: 区块名, 最长为8个字节 VirtualSize: 填入区块数据的实际大小 VirtualAddress: y = pPreSec->VirtualAddress; y += GetAlignmentSize(pPreSec->Misc.VirtualSize, dwSectionAlign); SizeOfRawData: y = GetAlignmentSize(INSERT_SIZE, dwFileAlign); PointerToRawData: y = pPreSec->PointerToRawData y += GetAlignmentSize(pPreSec->SizeOfRawData, dwFileAlign); 其他字段设置为0即可 3.设置镜像大小和区块表数目 SizeOfImage: y = newSectionTable.Misc.VirtualSize + newSectionTable.VirtualAddress NumberOfSections: y += 1; 4.根据newSectionTable.PointerToRawData拷贝数据到目标文件 #include <stdio.h> #include <stdlib.h> #define INSERT_SIZE 1024 DWORD GetAlignSize(DWORD dwSize, DWORD dwAlignSize) { DWORD dwMod = dwSize % dwAlignSize; if(dwMod != 0) { return dwSize + (dwAlignSize - dwMod); } else return dwSize; } int main(int argc, char* argv[]) { char *pszSouFile = "C://Server.exe"; char *pNewByte = new char[INSERT_SIZE + 1]; HANDLE hFile = NULL; HANDLE hFileMap = NULL; void *pMapView = NULL; BYTE *pbyteNtHeader = NULL; hFile = CreateFile(pszSouFile, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); if((HANDLE)-1 == hFile) { printf("打开文件失败!/n"); return 0; } hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, 0); if(hFileMap == NULL) { printf("创建FileMap失败!/n"); CloseHandle(hFile); return 0; } pMapView = MapViewOfFile(hFileMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); if(pMapView == NULL) { printf("MapViewOfFile失败!/n"); CloseHandle(hFileMap); CloseHandle(hFile); return 0; } if(*(WORD *)pMapView != 0x5A4D) { printf("不是PE文件!/n"); return 0; } pbyteNtHeader = (BYTE *) ( (*(DWORD *)((BYTE *)pMapView + 0x3C) + (DWORD)pMapView) ); DWORD dwSectionAlign = *((DWORD *)(pbyteNtHeader + 0x38)); printf("内存对齐粒度: %x/n", dwSectionAlign); DWORD dwFileAlign = *((DWORD *)(pbyteNtHeader + 0x3C)); printf("文件对齐粒度: %x/n", dwFileAlign); DWORD dwOldFileSize = GetFileSize(hFile, 0); DWORD dwNewFileSize = GetAlignSize(dwOldFileSize + INSERT_SIZE, dwFileAlign); printf("新文件对齐后的大小: %x/n", dwNewFileSize); UnmapViewOfFile(pMapView); CloseHandle(hFileMap); hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, dwNewFileSize, 0); if(hFileMap == NULL) { CloseHandle(hFile); printf("创建FileMap失败!/n"); return 0; } pMapView = MapViewOfFile(hFileMap, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0); if(pMapView == NULL) { printf("MapViewOfFile失败!/n"); CloseHandle(hFileMap); CloseHandle(hFile); return 0; } pbyteNtHeader = (BYTE *) ( (*(DWORD *)((BYTE *)pMapView + 0x3C) + (DWORD)pMapView) ); DWORD dwSectionNum = *(WORD *)(pbyteNtHeader + 0x6); DWORD dwDataDirecNum = *(DWORD *)(pbyteNtHeader + 0x74); IMAGE_SECTION_HEADER *pLastSectionTable = (PIMAGE_SECTION_HEADER) ((pbyteNtHeader + 0x78) + (dwDataDirecNum * 0x8) + ((dwSectionNum - 1) * 0x28) ); // 设置新的区块表 DWORD dwMod = 0; IMAGE_SECTION_HEADER newSectionTable; ZeroMemory(&newSectionTable, sizeof(IMAGE_SECTION_HEADER)); strcpy((char *)newSectionTable.Name, ".xxxx"); newSectionTable.Misc.VirtualSize = INSERT_SIZE; printf("插入区块表虚拟大小: 0x%x/n", newSectionTable.Misc.VirtualSize); newSectionTable.VirtualAddress = pLastSectionTable->VirtualAddress; newSectionTable.VirtualAddress += GetAlignSize(pLastSectionTable->Misc.VirtualSize, dwSectionAlign); printf("插入区块表虚拟地址: 0x%x/n", newSectionTable.VirtualAddress); newSectionTable.SizeOfRawData = GetAlignSize(INSERT_SIZE, dwFileAlign); printf("插入区块表文件大小: 0x%x/n", newSectionTable.SizeOfRawData); newSectionTable.PointerToRawData = pLastSectionTable->PointerToRawData; newSectionTable.PointerToRawData += GetAlignSize(pLastSectionTable->SizeOfRawData, dwFileAlign); printf("插入区块表文件偏移: 0x%x/n", newSectionTable.PointerToRawData); ++pLastSectionTable; *pLastSectionTable = newSectionTable; // 添加区块数目 *(WORD *)(pbyteNtHeader + 0x6) += 1; printf("修正后的区块数目: 0x%x/n", *(WORD *)(pbyteNtHeader + 0x6)); // 修改SizeOfImage *(DWORD *)(pbyteNtHeader + 0x50) = newSectionTable.VirtualAddress + newSectionTable.Misc.VirtualSize; printf("修正的镜像大小: 0x%x/n", *(WORD *)(pbyteNtHeader + 0x50)); // 拷贝数据到目标文件 BYTE *pTargetRem = (BYTE *)(newSectionTable.PointerToRawData + (DWORD)pMapView); for(int i = 0; i < INSERT_SIZE; ++i) { pTargetRem[i] = pszSouFile[i]; } UnmapViewOfFile(pMapView); CloseHandle(hFileMap); CloseHandle(hFile); return 0; }