#include "stdafx.h"
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
LPVOID ReadPEFile (LPSTR FilePath)
{
//设置文件空指针,打开文件,指向文件,确认是否打开
FILE* pFile = NULL;
pFile = fopen(FilePath, "rb+");
if(pFile == NULL)
{
printf("打开失败\n");
return NULL;
}
//返回文件大小,为随后申请堆空间做准备
fseek(pFile,0,SEEK_END);
long size = ftell(pFile);
rewind(pFile);
//设置堆指针(初始化为NULL),开始申请堆空间
LPVOID pFileBuffer;
pFileBuffer = malloc(size);
//判断是否申请成功
if(pFileBuffer == NULL)
{
printf("申请失败\n");
fclose(pFile);
return NULL;
}
//初始化malloc空间
memset(pFileBuffer,0,size);
//读取到内存中
fread(pFileBuffer,1,size,pFile);
//读取完毕,做清理工作
fclose(pFile);
return pFileBuffer;
}
//拷贝为内存中运行状态的大小
LPVOID CopytoImageBuffer (LPVOID pFileBuffer)
{
//准备指针,初始化为NULL
PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头指针
PIMAGE_NT_HEADERS pNTHeader = NULL;//NT头指针
PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头指针
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;//可选PE头指针
PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表指针
//接收缓冲区指针,设置各指针位置
//pFileBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");
pDosHeader = (PIMAGE_DOS_HEADER) pFileBuffer;
pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)pFileBuffer+pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER) ( (DWORD) pNTHeader+4);
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)( (DWORD) pFileHeader+IMAGE_SIZEOF_FILE_HEADER );
pSectionHeader =(PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
//判断是否读取成功
if(!pFileBuffer)
{
printf("读取失败\n");
free(pFileBuffer);
return NULL;
}
if(*(PWORD)pFileBuffer != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志\n");
free(pFileBuffer);
return NULL;
}
//打印DOS头
printf("*************DOS头如下*************\n");
printf("%x\n",pDosHeader->e_magic);
printf("%x\n",pDosHeader->e_lfanew);
//判断PE签名
if(*( (PDWORD) ((DWORD)pFileBuffer+pDosHeader->e_lfanew) ) != IMAGE_NT_SIGNATURE)
{
printf("%x:不是有效的PE签名\n",(pNTHeader->Signature));
free(pFileBuffer);
return NULL;
}
//打印PE签名
printf("%x:是有效的PE签名\n",pNTHeader->Signature);
//打印标准PE头
printf("*************标准PE头大小如下*************\n");
printf("%x\n",(pFileHeader->Machine));
printf("%x\n",(pFileHeader->NumberOfSections));
//打印可选PE头大小
printf("*************可选PE头大小如下*************\n");
printf("%x\n",pOptionalHeader->Magic);
//打印节表头-
for(int i =0;i<pFileHeader->NumberOfSections;i++)
{
printf("*************各节表头如下*************\n");
printf("%s\n",pSectionHeader->Name);
//pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader+IMAGE_SIZEOF_SECTION_HEADER);
pSectionHeader++;
}
pSectionHeader = (PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
//申请Image指针
LPVOID pImageBuffer = NULL;
//读取Imagesize大小,申请malloc空间
pImageBuffer = malloc(pOptionalHeader->SizeOfImage);//printf("%x",pOptionalHeader->SizeOfImage);
//检查是否申请成功
if(!pImageBuffer)
{
printf("申请Image缓冲区失败");
free(pFileBuffer);
return NULL;
}
//初始化malloc空间
memset(pImageBuffer,0,pOptionalHeader->SizeOfImage);
//开始拷贝各头+节表大小——依据:optional头中的SizeOfHeaders;
memcpy(pImageBuffer,pFileBuffer,pOptionalHeader->SizeOfHeaders);
//开始循环拷贝节
for(int k=0;k<pFileHeader->NumberOfSections;k++)
{
//memcpy( ( (PDWORD)pImageBuffer+pSectionHeader->VirtualAddress),( (PDWORD)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
//printf("%x\n",( (PDWORD)pImageBuffer+pSectionHeader->VirtualAddress));
memcpy( ( (char*)pImageBuffer+pSectionHeader->VirtualAddress),( (char*)pFileBuffer+pSectionHeader->PointerToRawData),pSectionHeader->SizeOfRawData);
printf("%x\n",( (char*)pImageBuffer+pSectionHeader->VirtualAddress));
pSectionHeader++;
}
//free(pFileBuffer);
return pImageBuffer;
}
void CopytoNewBuffer_Save(LPVOID pImageBuffer)
{
//准备指针,初始化为NULL
PIMAGE_DOS_HEADER pDosHeader = NULL;//DOS头指针
PIMAGE_NT_HEADERS pNTHeader = NULL;//NT头指针
PIMAGE_FILE_HEADER pFileHeader = NULL;//标准PE头指针
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;//可选PE头指针
PIMAGE_SECTION_HEADER pSectionHeader = NULL;//节表指针
//接收缓冲区指针,设置各指针位置
//pImageBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");
pDosHeader = (PIMAGE_DOS_HEADER) pImageBuffer;
pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)pImageBuffer+pDosHeader->e_lfanew);
pFileHeader = (PIMAGE_FILE_HEADER) ( (DWORD) pNTHeader+4);
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)( (DWORD) pFileHeader+IMAGE_SIZEOF_FILE_HEADER );
pSectionHeader =(PIMAGE_SECTION_HEADER) ((DWORD)pOptionalHeader+pFileHeader->SizeOfOptionalHeader);
//再次申请NewBuffer内存空间,确认并初始化
//设置文件空指针,打开文件,指向文件,确认是否打开
FILE* pFile = NULL;
pFile = fopen("C:\\WINDOWS\\system32\\notepad.exe", "rb+");
if(pFile == NULL)
{
printf("打开失败\n");
return;
}
//返回文件大小,为随后申请堆空间做准备
fseek(pFile,0,SEEK_END);
long size = ftell(pFile);
rewind(pFile);
//设置堆指针(初始化为NULL),开始申请堆空间
LPVOID pNewBuffer;
pNewBuffer = malloc(size);
//判断是否申请成功
if(pNewBuffer == NULL)
{
printf("申请失败\n");
fclose(pFile);
return;
}
//初始化malloc空间
memset(pNewBuffer,0,size);
//开始拷贝头们+节表
memcpy(pNewBuffer,pImageBuffer,pOptionalHeader->SizeOfHeaders);
//循环拷贝三个节
for(int i=0;i<pFileHeader->NumberOfSections;i++)
{
memcpy((char*)pNewBuffer+pSectionHeader->PointerToRawData,(char*)pImageBuffer+pSectionHeader->VirtualAddress,pSectionHeader->SizeOfRawData);
char* tempNewBuffer = (char*)pNewBuffer + pSectionHeader->PointerToRawData + pSectionHeader->SizeOfRawData;
char* tempImageBuffer = (char*)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize;
}
//准备一个新文件用于接收NewBuffer缓冲区的内存数据
FILE* pNewFile = NULL;
pNewFile = fopen("C:\\Documents and Settings\\Administrator\\桌面\\Stack.exe","wb+");
if(!pNewFile)
{
printf("接收的文件打开失败");
free(pNewBuffer);
return;
}
//写入新硬盘
fwrite(pNewBuffer,size,1,pNewFile);
free(pNewBuffer);
free(pImageBuffer);
return;
}
int main(int argc, char* argv[])
{
LPVOID pFileBuffer = ReadPEFile ("C:\\WINDOWS\\system32\\notepad.exe");
LPVOID pImageBuffer = CopytoImageBuffer(pFileBuffer);
CopytoNewBuffer_Save(pImageBuffer);
return 0;
}