上节课说到遍历节表,这节课让我们把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<stdio.h>
#include<windows.h>
#include<malloc.h>
//
//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("%x\n",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%x\n",pOptionalHeader->SizeOfImage);
//malloc清零
memset(*ppImageBuffer,0,pOptionalHeader->SizeOfImage);
//复制Headers
printf("SizeOfHeader%x\n",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("%d\n",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<pFileHeader->NumberOfSections;i++,pSectionHeader++)
{
printf("%d\n",i);
}
//循环到最后一个节表
DWORD SizeOfBuffer=pSectionHeader->PointerToRawData+pSectionHeader->SizeOfRawData;
//开辟空间
*ppBuffer=malloc(SizeOfBuffer);
if(!*ppBuffer)
{
printf("开辟Buffer空间失败\n");
return 0;
}
printf("SizeOfBuffer%x\n",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("%d\n",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("success\n");
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;
}
}
代码效果: