Last updated on January 13, 2024 pm
                  
                
              
            
            
              
                
                模拟PE加载过程 将文件从磁盘load到内存,再从内存中解析PE信息,然后开辟新内存进行“拉伸”操作。
定义PE结构体 由于PE中的内容全部是按1字节进行结构体对齐,因此在定义结构体时应当注意对齐方式,以及保存编译环境对齐字节。
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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 #ifndef  PE #define  PE typedef  unsigned  char  BYTE, * lpBYTE;typedef  unsigned  short  int  WORD, * lpWORD;typedef  unsigned  int  DWORD, * lpDWORD;#pragma  pack(push) #pragma  pack(1) typedef  struct  _PE_HEADER_DOS { 	WORD e_magic; 	WORD e_cblp; 	WORD e_cp; 	WORD e_crlc; 	WORD e_cparhdr; 	WORD e_minalloc; 	WORD e_maxalloc; 	WORD e_ss; 	WORD e_sp; 	WORD e_csum; 	WORD e_ip; 	WORD e_cs; 	WORD e_lfarlc; 	WORD e_ovno; 	WORD e_res[4 ]; 	WORD e_oemid; 	WORD e_oeminfo; 	WORD e_res2[10 ]; 	DWORD e_lfanew; }PEHDOS, *lpPEHDOS;typedef  struct  _PE_HEADERS_PE  { 	DWORD Signature; 	WORD Machine; 	WORD NumberOfSections; 	DWORD TimeDateStamp; 	DWORD PointerToSymbolTable; 	DWORD NumberOfSymbols; 	WORD SizeOfOptionalHeader; 	WORD Characteristics; }PEHPE, *lpPEHPE;typedef  struct  _PE_HEADERS_OPTIONAL  { 	WORD Magic; 	BYTE MajorLinkerVersion; 	BYTE MinorLinkerVersion; 	DWORD SizeOfCode; 	DWORD SizeOfInitializedData; 	DWORD SizeOfUninitializedData; 	DWORD AddressOfEntryPoint; 	DWORD BaseOfCode; 	DWORD BaseOfData; 	DWORD ImageBase; 	DWORD SectionAlignment; 	DWORD FileAlignment; 	WORD MajorOperatingSystemVersion; 	WORD MinorOperatingSystemVersion; 	WORD MajorImageVersion; 	WORD MinorImageVersion; 	WORD MajorSubsystemVersion; 	WORD MinorSubsystemVersion; 	DWORD Win32VersionValue; 	DWORD SizeOfImage; 	DWORD SizeOfHeader; 	DWORD CheckSum; 	WORD Subsystem; 	WORD DllCharacteristics; 	DWORD SizeOfStackReserve; 	DWORD SizeOfStackCommit; 	DWORD SizeOfHeapReserve; 	DWORD SizeOfHeapCommit; 	DWORD LoaderFlags; 	DWORD NmberOfRvaAndSizes; }PEHOPTIONAL, *lpPEHOPTIONAL;typedef  struct  _PE_HEADERS_TABLE_ITEM  { 	BYTE name[8 ]; 	DWORD VirtualSize; 	DWORD VirtualAddress; 	DWORD SizeOfRawData; 	DWORD PointerToRawData; 	DWORD PointerToRelocations; 	DWORD PointerToLinenumbers; 	WORD NumberOfRelocations; 	WORD NumberOfLinenumbers; 	DWORD Characteristics; } PETable, *lpPETable;#pragma  pack(pop) typedef  struct  _PE  { 	lpPEHDOS h_dos; 	lpPEHPE h_pe; 	lpPEHOPTIONAL h_op; 	lpPETable pet; }PEFILE, *lpPEFILE;int  LoadFileToMemory (FILE* pFile, lpPEFILE lpPEFile) ;void * CreateImageBuffer (lpPEFILE lpPEFile) ;void  DumpImageToFile (FILE* pFile, void * imageBase, lpPEFILE lpPEFile) ;#endif   
 
文件从磁盘到内存 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 int  LoadFileToMemory (FILE* pFile, lpPEFILE lpPEFile)  { 	int  fileLength = 0 ; 	fseek(pFile, 0 , SEEK_END); 	fileLength = ftell(pFile); 	fseek(pFile, 0 , SEEK_SET); 	BYTE* start = new BYTE[fileLength]{ 0  }; 	for  (int  i = 0 ; i < fileLength; i++) { 		start[i] = fgetc(pFile); 	} 	 	lpPEFile->h_dos = (lpPEHDOS)start; 	 	int  peOffset = lpPEFile->h_dos->e_lfanew; 	lpPEFile->h_pe = (lpPEHPE)((DWORD)start + peOffset); 	 	DWORD peAddress = (DWORD)lpPEFile->h_pe; 	lpPEFile->h_op = (lpPEHOPTIONAL)(peAddress + 24 ); 	 	WORD sizeOfOptionalHeader = lpPEFile->h_pe->SizeOfOptionalHeader; 	lpPEFile->pet = (lpPETable)(peAddress + 24  + sizeOfOptionalHeader); 	return  fileLength; }
 
解析内存PE信息 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 void * CreateImageBuffer (lpPEFILE peFile)  { 	 	lpPEHDOS lpHdos = peFile->h_dos; 	if  (lpHdos == nullptr) { 		return  nullptr; 	} 	DWORD imageBaseSrc = (DWORD)lpHdos; 	lpPEHPE lpHpe = peFile->h_pe; 	if  (lpHpe == nullptr) { 		return  nullptr; 	} 	lpPEHOPTIONAL lpHop = peFile->h_op; 	if  (lpHop == nullptr) { 		return  nullptr; 	} 	lpPETable lpTable = peFile->pet; 	if  (lpTable == nullptr) { 		return  nullptr; 	} 	 	DWORD sizeOfImage = lpHop->SizeOfImage; 	void  *pMemoryBuffer = new BYTE[sizeOfImage]; 	DWORD imageBaseDst = (DWORD)pMemoryBuffer; 	 	DWORD sizeOfHeader = lpHop->SizeOfHeader; 	memcpy (pMemoryBuffer, (void *)imageBaseSrc, sizeOfHeader); 	 	WORD numberOfSections = lpHpe->NumberOfSections; 	for  (int  i = 0 ; i < numberOfSections; i++) { 		lpPETable t = (lpTable + i); 		DWORD pointerToRawData = t->PointerToRawData; 		DWORD sizeOfRawData = t->SizeOfRawData; 		DWORD virtualAddress = t->VirtualAddress; 		memcpy ((void *)(imageBaseDst + virtualAddress), (void *)(imageBaseSrc + pointerToRawData), sizeOfRawData); 	} 	return  pMemoryBuffer; }
 
从内存中还原到磁盘 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 void  DumpImageToFile (FILE* pFile, void * imageBase, lpPEFILE peFile)  { 	fseek(pFile, 0 , SEEK_SET); 	 	lpPEHDOS lpHdos = peFile->h_dos; 	if  (lpHdos == nullptr) { 		return ; 	} 	lpPEHPE lpHpe = peFile->h_pe; 	if  (lpHpe == nullptr) { 		return ; 	} 	lpPEHOPTIONAL lpHop = peFile->h_op; 	if  (lpHop == nullptr) { 		return ; 	} 	lpPETable lpTable = peFile->pet; 	if  (lpTable == nullptr) { 		return ; 	} 	 	 	DWORD sizeOfHeader = lpHop->SizeOfHeader; 	for  (int  i = 0 ; i < sizeOfHeader; i++) { 		BYTE byte = *((lpBYTE)imageBase + i); 		fputc(byte, pFile); 	} 	 	WORD numberOfSections = lpHpe->NumberOfSections; 	for  (int  num = 0 ; num < numberOfSections; num++) { 		lpPETable t = (lpTable + num); 		DWORD pointerToRawData = t->PointerToRawData; 		DWORD sizeOfRawData = t->SizeOfRawData; 		DWORD virtualAddress = t->VirtualAddress; 		 		fseek(pFile, pointerToRawData, SEEK_SET); 		for  (int  i = 0 ; i < sizeOfRawData; i++) { 			BYTE byte = *((lpBYTE)imageBase + virtualAddress + i); 			fputc(byte, pFile); 		} 	} }
 
测试程序 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include  <stdio.h>  #include  <memory.h>  #include  "PE.h"  int  main ()  { 	 	PEFILE peFile{ 0  }; 	FILE *pFile = fopen("D:\\src.exe" , "rb" ); 	int  fileLength = LoadFileToMemory(pFile, &peFile); 	void  *pMemoryBuffer = nullptr; 	fclose(pFile); 	 	pMemoryBuffer = CreateImageBuffer(&peFile); 	 	pFile = fopen("D:\\dst.exe" , "wb" ); 	DumpImageToFile(pFile, pMemoryBuffer, &peFile); 	delete[] pMemoryBuffer; 	delete peFile.h_dos; }
 
                
               
            
             
            
              
              
  
  
    
      PE结构(3)从磁盘到内存的加载过程
      http://dubhehub.github.io/blogs/2024011317470017231.html