文章目录
一、定义一个函数
Test()
{
DWORD Size = 0; //用来接收数据大小
BOOL isok = FALSE; //用来判断是否写入成功
LPVOID pFileBuffer = NULL; //用来接收缓冲区的首地址
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
}
二、File -> FileBuffer
1、定义一些变量
2、读取文件,并判断是否读取成功
3、读取文件大小
4、分配缓冲区
5、初始化缓冲区
6、将文件数据读取到缓冲区
7、关闭文件,并返回缓冲区首地址
DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer )
{
FILE *pFile = NULL;
DWORD fileSize = 0; //文件大小
LPVOID pTempFileBuffer = NULL; //缓冲区首地址
pFile = fopen(lpszFile,"rb"); //打开文件
if(!pFile)
{
printf("打开文件失败");
return NULL;
}
//读取文件大小
fseek(pFile,0,SEEK_END); //将指针从开始的位置移动到末尾
fileSize = ftell(pFile); //获取数据大小
//分配缓冲区(申请内存)
pTempFileBuffer = malloc(fileSize);
if(!pTempFileBuffer)
{
printf("分配空间失败");
fclose(pFile);
return NULL;
}
//将文件数据读取到缓冲区
fseek(pFile,0,SEEK_SET); //将指针指向开始
size_t n = fread(pTempFileBuffer,fileSize,1,pFile); //将数据读取到缓冲区中
if(!n)
{
printf("读取数据失败");
free(pTempFileBuffer); //释放内存
fclose(pFile); //关闭文件
return NULL;
}
//关闭文件
*pFileBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;
fclose(pFile); //关闭文件
return fileSize;
}
VOID Test()
{
DWORD Size = 0; //用来接收数据大小
BOOL isok = FALSE; //用来接收写入磁盘是否成功
LPVOID pFileBuffer = NULL; //用来接收缓冲区的首地址
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer); //调用函数读取文件数据
if(!pFileBuffer || !Size)
{
printf("File-> FileBuffer失败");
return;
}
}
三、FileBuffer -> ImageBuffer
将缓冲区的文件进行拉伸
1、定义一些变量
2、判断传进来的缓冲区地址是否正确
3、判断是否遵守PE格式
4、获取DOS头、NT头、标准PE头、可选PE头、第一个节表信息
5、分配缓冲区
6、初始化缓冲区
7、根据 SizeOfHeaders,先拷贝PE头
8、根据节表,循环拷贝节
9、将拉伸后的数据首地址传出
DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL; //用来接收DOS头信息
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID pTemImageBuffer = NULL;
//判断传入的值是否有效
if(!pFileBuffer)
{
printf("缓冲区指针无效");
return 0;
}
//判断是否为PE文件
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ头\n");
return 0;
}
//获取头信息
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
return 0;
}
//NT头地址
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//标准PE头地址
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
//可选PE头地址
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个节表地址
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
//申请缓冲区大小
pTemImageBuffer = malloc(pOptionHeader->SizeOfImage);
if(!pTemImageBuffer)
{
printf("分配空间失败");
return 0;
}
//初始化缓冲区
memset(pTemImageBuffer,0,pOptionHeader->SizeOfImage);
//根据 SizeOfHeaders,先拷贝头
memcpy(pTemImageBuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
//根据节表,循环拷贝节
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
{
memcpy((void*)((DWORD)pTemImageBuffer + pTempSectionHeader->VirtualAddress),(void*)((DWORD)pFileBuffer + pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}
//返回数据
*pImageBuffer = pTemImageBuffer;
pTemImageBuffer = NULL;
return 0;
}
VOID Test()
{
DWORD Size = 0;
BOOL isok = FALSE;
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer);
if(!pFileBuffer)
{
printf("File-> FileBuffer失败");
return;
}
//FileBuffer->ImageBuffer
CopyFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!pImageBuffer)
{
printf("FileBuffer->ImageBuffer失败");
free(pFileBuffer);
return;
}
}
四、ImageBuffer -> NewBuffer
1、定义一些变量
2、判断传进来的缓冲区地址是否正确
3、判断是否遵守PE格式
4、获取DOS头、NT头、标准PE头、可选PE头、第一个节表信息
5、申请缓冲区大小
6、初始化缓冲区
7、根据 SizeOfHeaders,先拷贝PE头
8、根据节表,循环拷贝节
9、将新的数据后的数据首地址传出,并返回大小
DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer,OUT LPVOID* pNewBuffer)
{
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;
LPVOID pTempNewBuffer = NULL;
DWORD FileSize = NULL;
if(!pImageBuffer)
{
printf("缓冲区指针无效");
return 0;
}
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ头\n");
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
return 0;
}
//NT头地址
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer + pDosHeader->e_lfanew);
//标准PE头地址
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
//可选PE头地址
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个节表地址
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
FileSize =FileSize = pOptionHeader->SizeOfImage;
pTempNewBuffer = malloc(FileSize);
if(!pTempNewBuffer)
{
printf("分配空间失败");
return 0;
}
//初始化缓冲区
memset(pTempNewBuffer,0,FileSize);
memcpy(pTempNewBuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
//根据节表,循环拷贝节
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
{
memcpy((void*)((DWORD)pTempNewBuffer + pTempSectionHeader->PointerToRawData),
(void*)((DWORD)pImageBuffer + pTempSectionHeader->VirtualAddress),
pTempSectionHeader->Misc.VirtualSize);
}
*pNewBuffer = pTempNewBuffer;
pTempNewBuffer = NULL;
return FileSize;
}
VOID Test()
{
DWORD Size = 0;
BOOL isok = FALSE;
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer);
if(!pFileBuffer)
{
printf("File-> FileBuffer失败");
return;
}
//FileBuffer->ImageBuffer
CopyFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!pImageBuffer)
{
printf("FileBuffer->ImageBuffer失败");
free(pFileBuffer);
return;
}
//ImageBuffer->NewBuffer
Size = CopyImageBufferToNewBuffer(pImageBuffer,&pNewBuffer);
if(!Size || !pNewBuffer)
{
printf("ImageBuffer->NewBuffer失败");
free(pFileBuffer);
free(pImageBuffer);
return;
}
}
五、NewBuffer -> 文件
1、打开文件,并判断是否打开成功
2、将数据写入磁盘
3、关闭文件
4、返回TRUE或FALSE
5、根据返回的数据判断是否存盘成功
6、释放内存
BOOL MemeryTOFile(LPVOID pMemBuffer,size_t size)
{
FILE *fp = NULL;
fp = fopen("C:/fg1.exe","wb");
if(!fp)
{
return FALSE;
}
fwrite(pMemBuffer,size,1,fp); //向磁盘写入数据
fclose(fp); //关闭文件
fp = NULL;
return TRUE;
}
VOID Test()
{
DWORD Size = 0;
BOOL isok = FALSE;
LPVOID pFileBuffer = NULL;
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer);
if(!pFileBuffer)
{
printf("File-> FileBuffer失败");
return;
}
//FileBuffer->ImageBuffer
CopyFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!pImageBuffer)
{
printf("FileBuffer->ImageBuffer失败");
free(pFileBuffer);
return;
}
//ImageBuffer->NewBuffer
Size = CopyImageBufferToNewBuffer(pImageBuffer,&pNewBuffer);
if(!Size || !pNewBuffer)
{
printf("ImageBuffer->NewBuffer失败");
free(pFileBuffer);
free(pImageBuffer);
return;
}
//NewBuffer->文件
isok = MemeryTOFile(pNewBuffer,Size);
if(isok)
{
printf("存盘成功");
return;
}
//释放内存
free(pFileBuffer);
free(pImageBuffer);
free(pNewBuffer);
}
六、调用函数
#include "stdafx.h"
#include <windows.h>
#include "stdlib.h"
#include "stdio.h"
#define FILEPATH_IN "C:/fg.exe"
int main(int argc, char* argv[])
{
Test();
getchar();
return 0;
}
七、完整代码
#include "stdafx.h"
#include <windows.h>
#include "stdlib.h"
#include "stdio.h"
#define FILEPATH_IN "C:/notepad.exe"
DWORD ReadPEFile(IN LPSTR lpszFile,OUT LPVOID* pFileBuffer )
{
FILE *pFile = NULL;
DWORD fileSize = 0; //文件大小
LPVOID pTempFileBuffer = NULL; //缓冲区首地址
pFile = fopen(lpszFile,"rb"); //打开文件
if(!pFile)
{
printf("打开文件失败");
return NULL;
}
//读取文件大小
fseek(pFile,0,SEEK_END); //将指针从开始的位置移动到末尾
fileSize = ftell(pFile); //获取数据大小
//分配缓冲区(申请内存)
pTempFileBuffer = malloc(fileSize);
if(!pTempFileBuffer)
{
printf("分配空间失败");
fclose(pFile);
return NULL;
}
//将文件数据读取到缓冲区
fseek(pFile,0,SEEK_SET); //将指针指向开始
size_t n = fread(pTempFileBuffer,fileSize,1,pFile); //将数据读取到缓冲区中
if(!n)
{
printf("读取数据失败");
free(pTempFileBuffer); //释放内存
fclose(pFile); //关闭文件
return NULL;
}
//关闭文件
*pFileBuffer = pTempFileBuffer;
pTempFileBuffer = NULL;
fclose(pFile); //关闭文件
return fileSize;
}
DWORD CopyFileBufferToImageBuffer(IN LPVOID pFileBuffer,OUT LPVOID* pImageBuffer)
{
PIMAGE_DOS_HEADER pDosHeader = NULL; //用来接收DOS头信息
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID pTemImageBuffer = NULL;
//判断传入的值是否有效
if(!pFileBuffer)
{
printf("缓冲区指针无效");
return 0;
}
//判断是否为PE文件
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ头\n");
return 0;
}
//获取头信息
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
return 0;
}
//NT头地址
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
//标准PE头地址
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
//可选PE头地址
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个节表地址
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
//申请缓冲区大小
pTemImageBuffer = malloc(pOptionHeader->SizeOfImage);
if(!pTemImageBuffer)
{
printf("分配空间失败");
return 0;
}
//初始化缓冲区
memset(pTemImageBuffer,0,pOptionHeader->SizeOfImage);
//根据 SizeOfHeaders,先拷贝头
memcpy(pTemImageBuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
//根据节表,循环拷贝节
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
{
memcpy((void*)((DWORD)pTemImageBuffer + pTempSectionHeader->VirtualAddress),(void*)((DWORD)pFileBuffer + pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}
//返回数据
*pImageBuffer = pTemImageBuffer;
pTemImageBuffer = NULL;
return 0;
}
DWORD CopyImageBufferToNewBuffer(IN LPVOID pImageBuffer,OUT LPVOID* pNewBuffer)
{
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;
LPVOID pTempNewBuffer = NULL;
if(!pImageBuffer)
{
printf("缓冲区指针无效");
return 0;
}
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ头\n");
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志\n");
return 0;
}
//NT头地址
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer + pDosHeader->e_lfanew);
//标准PE头地址
pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 0x4);
//可选PE头地址
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个节表地址
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
//数据大小(最后一个节的文件偏移 + 最后一个节的真实大小 + 文件对齐)
DWORD FileSize = (
(pSectionHeader + pPEHeader->NumberOfSections-1)->PointerToRawData
+ (pSectionHeader + pPEHeader->NumberOfSections-1)->Misc.VirtualSize
+ pOptionHeader->FileAlignment
)&(0 - pOptionHeader->FileAlignment);
pTempNewBuffer = malloc(FileSize);
if(!pTempNewBuffer)
{
printf("分配空间失败");
return 0;
}
//初始化缓冲区
memset(pTempNewBuffer,0,FileSize);
memcpy(pTempNewBuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
//根据节表,循环拷贝节
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(int i=0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
{
memcpy((void*)((DWORD)pTempNewBuffer + pTempSectionHeader->PointerToRawData),
(void*)((DWORD)pImageBuffer + pTempSectionHeader->VirtualAddress),
pTempSectionHeader->Misc.VirtualSize);
}
*pNewBuffer = pTempNewBuffer;
pTempNewBuffer = NULL;
return FileSize;
}
BOOL MemeryTOFile(LPVOID pMemBuffer,size_t size)
{
FILE *fp = NULL;
fp = fopen("C:/copyxx1.exe","wb");
if(!fp)
{
return FALSE;
}
fwrite(pMemBuffer,size,1,fp); //向磁盘写入数据
fclose(fp); //关闭文件
fp = NULL;
return TRUE;
}
VOID Test()
{
DWORD Size = 0; //用来接收数据大小
BOOL isok = FALSE; //用来接收写入磁盘是否成功
LPVOID pFileBuffer = NULL; //用来接收缓冲区的首地址
LPVOID pImageBuffer = NULL;
LPVOID pNewBuffer = NULL;
//File-> FileBuffer
Size = ReadPEFile(FILEPATH_IN,&pFileBuffer); //调用函数读取文件数据
if(!pFileBuffer || !Size)
{
printf("File-> FileBuffer失败");
return;
}
//FileBuffer->ImageBuffer
CopyFileBufferToImageBuffer(pFileBuffer,&pImageBuffer);
if(!pImageBuffer)
{
printf("FileBuffer->ImageBuffer失败");
free(pFileBuffer);
return;
}
//ImageBuffer->NewBuffer
Size = CopyImageBufferToNewBuffer(pImageBuffer,&pNewBuffer);
if(!Size || !pNewBuffer)
{
printf("ImageBuffer->NewBuffer失败");
free(pFileBuffer);
free(pImageBuffer);
return;
}
//NewBuffer->文件
isok = MemeryTOFile(pNewBuffer,Size);
if(isok)
{
printf("存盘成功");
return;
}
//释放内存
free(pFileBuffer);
free(pImageBuffer);
free(pNewBuffer);
}
int main(int argc, char* argv[])
{
Test();
getchar();
return 0;
}