上节课说到遍历节表,这节课让我们把FileBuffer-->ImageBuffer
海哥让我们用notepad.exe因为他的文件对齐和内存对齐是不一样的,如果一样的化,FileBuffer和ImageBuffer是一样的,为什么ImageBuffer还是不能执行呢?因为ImageBuffer的地址是我们malloc出来的,首地址不是Imagebase。
写代码之前我们需要掌握几个知识点
1.ImageBuffer的大小是多少?
我们不能直接把FileBuffer复制过来,因为notepad.exe的FileBuffer没有拉伸,我们回想PE结构,OptionalHeader有一个属性记载着ImageBuffer的大小,那就是SizeOfImage。
2.FileBuffer和ImageBuffer的Headers是没有区别的,头部没有拉伸,直接复制过来即可
3.如何复制节表?
因为FileBuffer和ImageBuffer的区别就是节表在内存中的位置不同,我们要一个一个节表的循环复制,那么我们要复制几次?FilePE头的NumberOfSection参数记录这节表的数量。我们要从哪里开始复制复制多少?节表里给出了答案。我们要从FileBuffer的PointerToRawData开始复制到ImgaeBuffer的VirtualAddress,复制SizeOfRawData的大小。
4.这里用到了二级指针,为什么要用到二级指针?因为当一个函数要返回两个参数的时候,就要用到二级指针。
5.当我们ImageBuffer——>NewBuffer的时候,我们怎么知道NewBuffer开辟malloc的大小?
因为Headers是一样的,我们只需要看节表就行,我们首先要循环到最后一个节表,找到PointerToRawData也就是在文件中的偏移,然后再找到SizeOfRawData也就是文件对齐后的大小,这两个相加就是NewBuffer的大小(记得把SectionHeader的指针还原,因为后面还需要遍历)
代码:
#include "stdafx.h" #include#include #include // //FileBuffer函数 DWORD ReadPEFile(LPVOID* ppFileBuffer) { FILE* pFile=NULL; DWORD SizeFileBuffer=0; pFile=fopen("C://WINDOWS//system32//notepad.exe","rb"); if(!pFile) { printf("打开notepad失败n"); return 0; } //获取文件大小 fseek(pFile,0,SEEK_END); SizeFileBuffer=ftell(pFile); fseek(pFile,0,SEEK_SET); if(!SizeFileBuffer) { printf("读取文件大小失败n"); return 0; } //开辟空间 *ppFileBuffer=malloc(SizeFileBuffer); if(!*ppFileBuffer) { printf("开辟空间失败n"); fclose(pFile); return 0; } //复制数据 size_t n=fread(*ppFileBuffer,SizeFileBuffer,1,pFile); if(!n) { printf("复制数据失败n"); free(*ppFileBuffer); fclose(pFile); return 0; } fclose(pFile); return SizeFileBuffer; } /// //FileBuffer--->ImgaeBuffer DWORD FileBufferToImageBuffer(LPVOID pFileBuffer,LPVOID* ppImageBuffer) { PIMAGE_DOS_HEADER pDosHeader=NULL; PIMAGE_NT_HEADERS pNTHeader=NULL; PIMAGE_FILE_HEADER pFileHeader=NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL; PIMAGE_SECTION_HEADER pSectionHeader=NULL; if(!pFileBuffer) { printf("FileBuffer函数调用失败n"); return 0; } printf("%xn",pFileBuffer); //判断是否是PE文件 pDosHeader=(PIMAGE_DOS_HEADER)pFileBuffer; if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE) { printf("不是有效的MZ标志n"); return 0; } pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pFileBuffer+pDosHeader->e_lfanew); if(pNTHeader->Signature!=IMAGE_NT_SIGNATURE) { printf("不是有效的PE标志n"); return 0; } pFileHeader=(PIMAGE_FILE_HEADER)(((DWORD)pNTHeader)+4); pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader+20); //开辟ImageBuffer空间 *ppImageBuffer=malloc(pOptionalHeader->SizeOfImage); if(!*ppImageBuffer) { printf("开辟ImageBuffer空间失败"); return 0; } printf("SizeOfImage%xn",pOptionalHeader->SizeOfImage); //malloc清零 memset(*ppImageBuffer,0,pOptionalHeader->SizeOfImage); //复制Headers printf("SizeOfHeader%xn",pOptionalHeader->SizeOfHeaders); memcpy(*ppImageBuffer,pDosHeader,pOptionalHeader->SizeOfHeaders); //循环复制节表 pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); for(int i=1;i<=pFileHeader->NumberOfSections;i++,pSectionHeader++) { memcpy((LPVOID)((DWORD)*ppImageBuffer+pSectionHeader->VirtualAddress),(LPVOID)((DWORD)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData); printf("%dn",i); } printf("拷贝完成n"); return pOptionalHeader->SizeOfImage; } / //ImageBufferToFileBuffer DWORD ImageBufferToFileBuffer(LPVOID pImageBuffer,LPVOID* ppBuffer) { PIMAGE_DOS_HEADER pDosHeader=NULL; PIMAGE_NT_HEADERS pNTHeader=NULL; PIMAGE_FILE_HEADER pFileHeader=NULL; PIMAGE_OPTIONAL_HEADER pOptionalHeader=NULL; PIMAGE_SECTION_HEADER pSectionHeader=NULL; if(!pImageBuffer) { printf("error"); return 0; } pDosHeader=(PIMAGE_DOS_HEADER)pImageBuffer; pNTHeader=(PIMAGE_NT_HEADERS)((DWORD)pImageBuffer+pDosHeader->e_lfanew); pFileHeader=(PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4); pOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pFileHeader + 20); pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); //得到FileBuffer的大小 for(int i=1;i NumberOfSections;i++,pSectionHeader++) { printf("%dn",i); } //循环到最后一个节表 DWORD SizeOfBuffer=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData; //开辟空间 *ppBuffer=malloc(SizeOfBuffer); if(!*ppBuffer) { printf("开辟Buffer空间失败n"); return 0; } printf("SizeOfBuffer%xn",SizeOfBuffer); memset(*ppBuffer,0,SizeOfBuffer); //复制头 memcpy(*ppBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders); //复制节表 pSectionHeader=(PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader); for(int j=1;j<=pFileHeader->NumberOfSections;j++,pSectionHeader++) { printf("%dn",j); memcpy((LPVOID)((DWORD)*ppBuffer+pSectionHeader->PointerToRawData),(LPVOID)((DWORD)pImageBuffer+pSectionHeader->VirtualAddress),pSectionHeader->SizeOfRawData); } printf("拷贝完成n"); return SizeOfBuffer; } / //存贮到新的exe BOOL MemeryToFile(LPVOID pBuffer,DWORD SizeOfBuffer) { FILE* fpw=fopen("C://WINDOWS//system32//creakme.exe","wb"); if(!fpw) { printf("fpw error"); return false; } if (fwrite(pBuffer, 1, SizeOfBuffer, fpw) == 0) { printf("fpw fwrite fail"); return false; } fclose(fpw); fpw = NULL; printf("successn"); return true; } int main() { LPVOID pFileBuffer=NULL; LPVOID* ppFileBuffer=&pFileBuffer; //定义二级指针 LPVOID pImageBuffer=NULL; LPVOID* ppImageBuffer=&pImageBuffer; //定义二级指针 DWORD SizeOfFileBuffer=0; DWORD SizeOfImageBuffer=0; DWORD SizeOfBuffer=0; LPVOID pBuffer=NULL; LPVOID* ppBuffer=&pBuffer; //调用filebuffer函数 SizeOfFileBuffer=ReadPEFile(ppFileBuffer); if(!SizeOfFileBuffer) { printf("FileBuffer函数调用失败 n"); return 0; } pFileBuffer=*ppFileBuffer; //调用FileBufferToImageBuffer函数 SizeOfBuffer=FileBufferToImageBuffer(pFileBuffer,ppImageBuffer); if(!SizeOfBuffer) { printf("调用FileBufferToImageBuffer函数失败"); return 0; } //调用ImageBufferToBuffer SizeOfBuffer=ImageBufferToFileBuffer(pImageBuffer,ppBuffer); pBuffer=*ppBuffer; if(!SizeOfBuffer) { printf("SizeOfBuffer error"); return 0; } //调用MemeryToFile if(MemeryToFile(pBuffer,SizeOfBuffer)==false) { printf("end"); return 0; } }
代码效果:



