<原创>在PE最后一节中插入补丁程序(附代码)
完整文件 https://files.cnblogs.com/Files/Gotogoo/在PE最后一节中插入补丁程序.zip
在PE文件最后一节中插入补丁程序,是最简单也是最有效的一种,因为PE最后一节的数据在文件的末尾,将代码加到最后一节时,不需要修改太多的内容。
最近在学习python,没时间详细写这个了,有问题看代码,或者在评论区提问,或者看书《Windows PE权威指南》,讲的很详细。
1 #include "stdafx.h" 2 #include<Windows.h> 3 4 char szTargetPath[MAX_PATH] = "D:\\Target.exe"; //目标文件的路径 5 char szPatchPath[MAX_PATH] = "D:\\helloworld_1.exe"; //补丁文件的路径 6 char szModifyPEPath[MAX_PATH]= "D:\\Modified_PE.exe"; //修改后生成新文件的路径 7 enum PATCH_FILE_INFO 8 { 9 FileAlignSectionSize, 10 RealSectionSize, 11 SectionRVA, 12 AddressOfEntryPoint, 13 FileAlignment 14 }; 15 16 PVOID GetFileBaseAddressAndSize(char* szFilePath,PULONG ulFileSize ); 17 BOOL InsertPatchFileToTargetFile(PVOID lpTargetMemory,PVOID lpPatchMemory,ULONG ulTargetSize); 18 DWORD GetFileInfo(PVOID FileBaseAddress,PATCH_FILE_INFO Type); 19 VOID ModifyParameter(PVOID FileBaseAddress,ULONG ulTargetSize,ULONG ulFlieAlignPatchCodeSize,ULONG ulRealPatchCodeSize,ULONG ulNewOEP); 20 ULONG GetPathCodeSectionRVA(PVOID lpPatchMemory); 21 ULONG Align(ULONG FileSize,ULONG ulAlignment); 22 ULONG FileAlign(ULONG FileSize,ULONG ulFileAlignment); 23 ULONG GetNewFileOEP(PVOID lpTargetMemory); 24 VOID ModifyPatchCodeJumpAddress(PVOID lpNewFileBaseAddress,ULONG NewFileSize,ULONG ULNewFileOEP,ULONG ulOldOEP,ULONG ulRealPatchCodeSize); 25 26 int _tmain(int argc, _TCHAR* argv[]) 27 { 28 PVOID lpPatchMemory = NULL; 29 PVOID lpTargetMemory = NULL; 30 ULONG ulPatchSize = 0; 31 ULONG ulTargetSize = 0; 32 33 lpTargetMemory = GetFileBaseAddressAndSize(szTargetPath,&ulTargetSize); 34 lpPatchMemory = GetFileBaseAddressAndSize(szPatchPath,&ulPatchSize); 35 36 InsertPatchFileToTargetFile(lpTargetMemory,lpPatchMemory,ulTargetSize); 37 38 return 0; 39 } 40 41 BOOL InsertPatchFileToTargetFile(PVOID lpTargetMemory,PVOID lpPatchMemory,ULONG ulTargetSize) 42 { 43 DWORD dwFileAlignPatchCodeSize = 0; 44 DWORD dwRealPatchCodeSize = 0; 45 ULONG ulPathCodeSectionRVA = 0; 46 ULONG ULNewFileOEP = 0; 47 ULONG ulOldOEP = 0; 48 ULONG ulFileAlignment = 0; 49 50 51 dwRealPatchCodeSize = GetFileInfo(lpPatchMemory,RealSectionSize); //获得Patch文件未对齐时的大小 52 ulPathCodeSectionRVA = GetFileInfo(lpPatchMemory,SectionRVA); //获得Patch文件所要加载节的RVA 53 ulOldOEP = GetFileInfo(lpTargetMemory,AddressOfEntryPoint); 54 ulFileAlignment = GetFileInfo(lpTargetMemory,FileAlignment); 55 ULNewFileOEP = GetNewFileOEP(lpTargetMemory); 56 dwFileAlignPatchCodeSize = Align(dwRealPatchCodeSize,ulFileAlignment); 57 58 PVOID NewFileBaseAddress = malloc(ulTargetSize+dwFileAlignPatchCodeSize); 59 memset(NewFileBaseAddress,0,ulTargetSize+dwFileAlignPatchCodeSize); 60 61 memcpy(NewFileBaseAddress,lpTargetMemory,ulTargetSize); 62 memcpy((PVOID)((ULONG_PTR)NewFileBaseAddress+ulTargetSize),(PVOID)((ULONG_PTR)lpPatchMemory+ulPathCodeSectionRVA),dwRealPatchCodeSize); 63 64 65 ModifyPatchCodeJumpAddress(NewFileBaseAddress,ulTargetSize+dwRealPatchCodeSize,ULNewFileOEP,ulOldOEP,dwRealPatchCodeSize); //修改PatchCode结尾E9跳转地址 66 67 ModifyParameter(NewFileBaseAddress,ulTargetSize,dwFileAlignPatchCodeSize,dwRealPatchCodeSize,ULNewFileOEP); //修改最后一节和PE头的参数 68 69 70 HANDLE hNewFile = CreateFileA(szModifyPEPath,GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_ARCHIVE,NULL); 71 if(hNewFile == INVALID_HANDLE_VALUE) 72 { 73 printf("CreateFileA Failed!\r\n"); 74 return FALSE; 75 } 76 DWORD dwRet = 0; 77 if(WriteFile(hNewFile,NewFileBaseAddress,ulTargetSize+dwFileAlignPatchCodeSize,&dwRet,NULL) == 0) 78 { 79 printf("WriteFile Failed!\r\n"); 80 return FALSE; 81 } 82 else 83 { 84 printf("Succeed!\r\n"); 85 } 86 87 return TRUE; 88 89 90 } 91 ULONG GetNewFileOEP(PVOID lpTargetMemory) 92 { 93 PIMAGE_DOS_HEADER DosHead = (PIMAGE_DOS_HEADER)lpTargetMemory; 94 PIMAGE_NT_HEADERS NTHead = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHead+DosHead->e_lfanew); 95 PIMAGE_SECTION_HEADER SectionHead = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NTHead+sizeof(IMAGE_NT_HEADERS)); 96 97 ULONG ulNumberOfSection = NTHead->FileHeader.NumberOfSections; 98 ULONG ulNewFileOEP = SectionHead[ulNumberOfSection-1].VirtualAddress+SectionHead[ulNumberOfSection-1].SizeOfRawData; 99 return ulNewFileOEP; 100 } 101 VOID ModifyPatchCodeJumpAddress(PVOID lpNewFileBaseAddress,ULONG NewFileSize,ULONG ULNewFileOEP,ULONG ulOldOEP,ULONG ulRealPatchCodeSize) 102 { 103 UCHAR JmpCode[] = "\x00\x00\x00\x00"; 104 *(int*)JmpCode = ( ulOldOEP + 1) - ( ULNewFileOEP + ulRealPatchCodeSize ); //+1越过E9 105 memcpy((PVOID)((UCHAR*)lpNewFileBaseAddress + NewFileSize - 5),JmpCode,strlen((char*)JmpCode)); //看内存 E9后有5个非0字节,所以不是-4 106 107 } 108 109 VOID ModifyParameter(PVOID FileBaseAddress,ULONG ulTargetSize,ULONG ulFlieAlignPatchCodeSize,ULONG ulRealPatchCodeSize,ULONG ulNewOEP) 110 { 111 PIMAGE_DOS_HEADER DosHead = (PIMAGE_DOS_HEADER)FileBaseAddress; 112 PIMAGE_NT_HEADERS NTHead = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHead+DosHead->e_lfanew); 113 PIMAGE_SECTION_HEADER SectionHead = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NTHead+sizeof(IMAGE_NT_HEADERS)); 114 115 ULONG MemoryAlignment = NTHead->OptionalHeader.SectionAlignment; 116 ULONG ulNumberOfSection = NTHead->FileHeader.NumberOfSections; 117 118 SectionHead[ulNumberOfSection-1].Characteristics = 0x60000020; 119 SectionHead[ulNumberOfSection-1].Misc.VirtualSize = SectionHead[ulNumberOfSection-1].SizeOfRawData + ulRealPatchCodeSize; 120 SectionHead[ulNumberOfSection-1].SizeOfRawData += ulFlieAlignPatchCodeSize; 121 122 123 NTHead->OptionalHeader.SizeOfImage = Align(SectionHead[ulNumberOfSection-1].VirtualAddress+SectionHead[ulNumberOfSection-1].SizeOfRawData,MemoryAlignment); 124 NTHead->OptionalHeader.AddressOfEntryPoint = ulNewOEP; 125 } 126 127 128 129 ULONG Align(ULONG FileSize,ULONG ulAlignment) 130 { 131 if(FileSize%ulAlignment != 0) 132 { 133 int Temp = FileSize/ulAlignment; 134 return ulAlignment*(Temp+1); 135 } 136 else 137 { 138 return FileSize; 139 } 140 } 141 DWORD GetFileInfo(PVOID FileBaseAddress,PATCH_FILE_INFO Type) 142 { 143 PIMAGE_DOS_HEADER DosHead = (PIMAGE_DOS_HEADER)FileBaseAddress; 144 PIMAGE_NT_HEADERS NTHead = (PIMAGE_NT_HEADERS)((ULONG_PTR)DosHead+DosHead->e_lfanew); 145 PIMAGE_SECTION_HEADER SectionHead = (PIMAGE_SECTION_HEADER)((ULONG_PTR)NTHead+sizeof(IMAGE_NT_HEADERS)); 146 147 DWORD dwEntryPoint = NTHead->OptionalHeader.AddressOfEntryPoint; 148 DWORD dwRet = 0; 149 if(Type == AddressOfEntryPoint) 150 { 151 dwRet = dwEntryPoint; 152 } 153 if(Type == FileAlignment) 154 { 155 dwRet = NTHead->OptionalHeader.FileAlignment; 156 } 157 158 for(int i=0;i<NTHead->FileHeader.NumberOfSections;i++) 159 { 160 if(dwEntryPoint>=SectionHead[i].VirtualAddress && dwEntryPoint<SectionHead[i].VirtualAddress+SectionHead[i].SizeOfRawData) 161 { 162 163 if(Type == RealSectionSize) 164 { 165 dwRet = SectionHead[i].Misc.VirtualSize; 166 } 167 if(Type == SectionRVA) 168 { 169 dwRet = SectionHead[i].PointerToRawData; 170 } 171 172 } 173 174 } 175 176 if(dwRet == NULL) 177 { 178 printf("GetFileInfo Failed!\r\n"); 179 } 180 181 return dwRet; 182 183 } 184 185 PVOID GetFileBaseAddressAndSize(char* szFilePath,PULONG ulFileSize ) 186 { 187 HANDLE hFile = CreateFileA(szFilePath, 188 GENERIC_READ|GENERIC_WRITE,FILE_SHARE_WRITE|FILE_SHARE_WRITE,NULL, 189 OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 190 191 if (hFile==INVALID_HANDLE_VALUE) 192 { 193 printf("CreateFile Failed!\r\n"); 194 return NULL; 195 } 196 *ulFileSize = GetFileSize(hFile,NULL); 197 198 if (!(*ulFileSize)) 199 { 200 printf("GetFileSize Failed!\r\n"); 201 CloseHandle(hFile); 202 return NULL; 203 } 204 HANDLE hMapFile = CreateFileMapping( 205 hFile, 206 NULL, 207 PAGE_READWRITE, 208 0, 209 0, 210 NULL); 211 212 if (hMapFile == INVALID_HANDLE_VALUE) 213 { 214 printf("CreateFileMapping Failed!\r\n"); 215 CloseHandle(hFile); 216 return NULL; 217 } 218 219 PVOID FileBaseAddress = MapViewOfFile(hMapFile,FILE_MAP_ALL_ACCESS,NULL,NULL,NULL); 220 if (FileBaseAddress == NULL) 221 { 222 CloseHandle(hFile); 223 CloseHandle(hMapFile); 224 printf("MapViewOfFile Failed!\r\n"); 225 return NULL; 226 } 227 228 return FileBaseAddress; 229 }