这个过程还是单纯的只是PE文件的读取,详情见上一章,这里只截取部分代码 这是个文件拉伸的过程,如果PE文件的SectionAlignment(内存对齐)和FileAlignment(硬盘对齐)不一样,而我们要读取到的ImageBuffer空间是要将PE文件进行拉伸的,那么申请的ImageBuffer空间大小就是可选PE头里面的SizeOfImage,这个函数在以后解析也会经常用到,所以单独写出来这个函数,如下 函数功能: 注意前面申请ImageBuffer空间的时候因为有个属性SizeOfImage告诉你了在加载的时候PE文件拉伸的大小,但是压缩的时候没法这样直接得到,需要自己计算(当然也可以设计这个函数的时候传入FileSize,FileSize就是第一个函数的返回值)。 函数功能: 之前说过代码规范的问题,现在另写一个函数用来测试一下PE加载过程 就拿notepad.exe来做测试FileBuffer->ImageBuffer->NewBuffer->存盘
一.主要函数实现
1.PE文件到FileBuffer
2.FileBuffer到ImageBuffer
函数名称:
DWORD Copy_FileBufferToImageBuffer(IN void* FileBuffer, OUT void** ImageBuffer) { //先将用到的结构体指针定义出来 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; //判断传进来的FileBuffer指针是否存在 if (!FileBuffer) { printf("为空指针!!,无效!!"); return 0; } //上面如果有效,那么就给那些结构体指针赋值 pDosHeader = (PIMAGE_DOS_HEADER)FileBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)FileBuffer + pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader); //判断是否是MZ标志 if (*(WORD*)pDosHeader != IMAGE_DOS_SIGNATURE) { printf("这不是有效的MZ标志!!"); return 0; } //判断是否是有效的PE标志 if (*(DWORD*)pNTHeader != IMAGE_NT_SIGNATURE) { printf("这不是有效的PE标志!!"); return 0; } //申请Temp_ImageBuffer堆空间 void* Temp_ImageBuffer = malloc(pOptionHeader->SizeOfImage); if (!Temp_ImageBuffer) { printf("分配Temp_ImageBuffer堆空间失败!!"); return 0; } //初始化Temp_ImageBuffer堆空间 memset(Temp_ImageBuffer, 0, pOptionHeader->SizeOfImage); //根据SizeOfHeaders,先复制头儿,头部永远都是这个大小 memcpy(Temp_ImageBuffer, pDosHeader, pOptionHeader->SizeOfHeaders); //*******************************最重要的一个环节循环复制节的数据**************************** for (WORD i = 0; i < pPEHeader->NumberOfSections; i++, pSectionHeader++) { memcpy( (void*)((DWORD)Temp_ImageBuffer + pSectionHeader->VirtualAddress), (void*)((DWORD)FileBuffer + pSectionHeader->PointerToRawData), pSectionHeader->SizeOfRawData ); } //将传进来的ImageBuffer指针重新赋值 *ImageBuffer = Temp_ImageBuffer; //返回文件大小 return pOptionHeader->SizeOfImage; }
3.ImageBuffer->NewBuffer
这个过程是一个压缩的过程,自己计算的话要先计算出头部的大小,然后加上每个节的大小就是总共要申请的NewBuffer空间的大小,一起malloc即可
函数名称:
DWORD Copy_ImageBufferToNewBuffer(IN void* ImageBuffer, OUT void** NewBuffer) { //先将用到的结构体指针定义出来 PIMAGE_DOS_HEADER pDosHeader = NULL; PIMAGE_NT_HEADERS pNTHeader = NULL; PIMAGE_FILE_HEADER pPEHeader = NULL; PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL; PIMAGE_SECTION_HEADER pSectionHeader = NULL; //判断传进来的指针能不能用 if (!ImageBuffer) { printf("为空指针!!,无效!!"); return 0; } //如果传入成功给这些结构体指针赋值 pDosHeader = (PIMAGE_DOS_HEADER)ImageBuffer; pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)ImageBuffer + pDosHeader->e_lfanew); pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4); pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + 20); pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader); //判断是否是MZ标志 if (*(WORD*)pDosHeader != IMAGE_DOS_SIGNATURE) { printf("这不是有效的MZ标志!!"); return 0; } //判断是否是有效的PE标志 if (*(DWORD*)pNTHeader != IMAGE_NT_SIGNATURE) { printf("这不是有效的PE标志!!"); return 0; } //*********************最重要的环节获取NewBuffer空间的大小****************************** DWORD Temp_NewBuffer_Size = pOptionHeader->SizeOfHeaders; PIMAGE_SECTION_HEADER Temp_pSectionHeader = pSectionHeader;//保留pSectionHeader for (size_t i = 0; i < pPEHeader->NumberOfSections; i++, Temp_pSectionHeader++) { Temp_NewBuffer_Size += Temp_pSectionHeader->SizeOfRawData; } //********************************************************************************** //分配Temp_NewBuffer空间 void* Temp_NewBuffer = malloc(Temp_NewBuffer_Size); if (!Temp_NewBuffer) { printf("分配内存失败!!!!!"); return 0; } //初始化Temp_ImageBuffer堆空间 memset(Temp_NewBuffer, 0, Temp_NewBuffer_Size); //先copy头 memcpy(Temp_NewBuffer, ImageBuffer, pOptionHeader->SizeOfHeaders); //循环复制节到Temp_NewBuffer空间 Temp_pSectionHeader = pSectionHeader; for (size_t i = 0; i < pPEHeader->NumberOfSections; i++, Temp_pSectionHeader++) { memcpy( (void*)((DWORD)Temp_NewBuffer + Temp_pSectionHeader->PointerToRawData), (void*)((DWORD)ImageBuffer + Temp_pSectionHeader->VirtualAddress), Temp_pSectionHeader->SizeOfRawData ); } //返回数据 *NewBuffer = Temp_NewBuffer; //返回NewBuffer空间大小 return Temp_NewBuffer_Size; }
4.NewBuffer->存盘
DWORD Memory_TO_File(IN void* pMemoryBuffer, IN DWORD MemorySize, OUT char* filepath) { FILE* fileAdress = fopen(filepath, "wb"); if (!fileAdress) { printf("打开文件失败(写入)!!"); return 0; } fwrite(pMemoryBuffer, MemorySize, 1, fileAdress); fclose(fileAdress); return 1; }
二:测试函数
1.测试上述函数,完成PE加载
函数名称:
void Test_PEloader()
函数功能:
模拟PE加载到内存中的过程,然后还原存盘void Test_PEloader() { //声明三个空间的指针 void* FileBuffer = NULL; void* ImageBuffer = NULL; void* NewBuffer = NULL; //文件->FileBuffer DWORD FileSize = ReadPEfile_TO_FileBuffer(FILEPATH_IN, &FileBuffer); printf("FileBuffer空间大小为%xn", FileSize); //FileBuffer->ImageBuffer DWORD ImageBufferSize = Copy_FileBufferToImageBuffer(FileBuffer, &ImageBuffer); printf("ImageBuffer空间大小为%xn", ImageBufferSize); //ImageBuffer->NewBuffer DWORD NewBufferSize = Copy_ImageBufferToNewBuffer(ImageBuffer, &NewBuffer); printf("NewBuffer空间大小为%xn", NewBufferSize); //NewBuffer->存盘,FILEPATH_OUT就是你要存盘的路径,自己定义个宏 DWORD Judge = Memory_TO_File(NewBuffer, NewBufferSize, FILEPATH_OUT); if (Judge == 1) { printf("存盘成功!!"); } else { printf("存盘失败!!"); } //释放堆空间 free(FileBuffer); free(ImageBuffer); free(NewBuffer); }
三.执行结果
1.在主函数里面执行测试函数
int main(int argc,char* argv[]) { Test_PEloader(); return 0; }
2.执行结果
我们先打开notepad.exe看看
ok成功打开
下面再打开我们存盘的exe
双击打开
ok,成功打开!!!
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算