#define _CRT_SECURE_NO_WARNINGS
#include "windows.h"
#include <stdio.h>
long readFile(IN const char* szFilePath, OUT void ** BaseAddr)
{
FILE * fd = fopen(szFilePath, "rb");
long fileSize = 0;
void * tmpBuffer = NULL;
if (fd == NULL)
{
printf("不是有效的EXE文件");
return 0;
}
fseek(fd, 0, SEEK_END);
fileSize = ftell(fd);
fseek(fd, 0, SEEK_SET);
tmpBuffer = (void*)malloc(fileSize);
memset(tmpBuffer, 0, fileSize);
fread(tmpBuffer, sizeof(char), fileSize, fd);
*BaseAddr = tmpBuffer;
tmpBuffer = NULL;
fclose(fd);
return 1;
}
BOOL MentoFile(LPVOID MenAddr, OUT PSTR szOutfilePath,size_t fielSize)
{
FILE *fd = fopen(szOutfilePath, "wb+");
if (fd == NULL)
{
printf("打开EXE文件失败");
return 0;
}
fwrite(MenAddr, fielSize, 1, fd);
fclose(fd);
//释放没有用处的内存
free(MenAddr);
MenAddr = NULL;
return 1;
}
DWORD FileToBuffer(IN LPVOID FBufferAddr, OUT LPVOID* MBufferAddr)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
LPVOID tmpBuffer = NULL;
if (FBufferAddr == NULL)
{
printf("缓冲区指针无效");
return 0;
}
if (*(PWORD)FBufferAddr != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志");
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)FBufferAddr;
if (*(PWORD)((DWORD)FBufferAddr + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志");
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}
//NT头
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)FBufferAddr + pDosHeader->e_lfanew);
//pe头
pEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
//可选pe头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个目录节指针
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pEHeader->SizeOfOptionalHeader);
//根据sizeOfImage分配内存空间
tmpBuffer = (LPVOID)malloc(pOptionHeader->SizeOfImage);
if (tmpBuffer == NULL)
{
printf("内存分配失败"); //如果分配内存失败就没有必要进行下去了,释放原来分配的内存
free(FBufferAddr);
FBufferAddr = NULL;
return 0;
}
//初始化缓冲区
memset(tmpBuffer, 0, pOptionHeader->SizeOfImage);
//根据sizeOfHeader拷贝头
memcpy(tmpBuffer, FBufferAddr, pOptionHeader->SizeOfHeaders);
//根据节表进行拷贝
PIMAGE_SECTION_HEADER ptmpSection = pSectionHeader;
for (int i = 0; i < pEHeader->NumberOfSections; i++, ptmpSection++)
{
memcpy((LPVOID)((DWORD)tmpBuffer + ptmpSection->VirtualAddress), (LPVOID)((DWORD)FBufferAddr + ptmpSection->PointerToRawData), ptmpSection->SizeOfRawData);
}
free(FBufferAddr); //拷贝完数据之后 将旧的内存释放
FBufferAddr = NULL;
*MBufferAddr = tmpBuffer;
return pOptionHeader->SizeOfImage;
}
DWORD BufferTofileBuffer(IN LPVOID oldBufferAddr, OUT LPVOID *NewBufferAddr)
{
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
PIMAGE_SECTION_HEADER ptmpSection = NULL;
DWORD fileSize = 0;
DWORD numberSection = 0;
LPVOID tmpBuffer = NULL;
if (oldBufferAddr == NULL)
{
printf("缓冲区指针无效");
return 0;
}
if (*(PWORD)oldBufferAddr != IMAGE_DOS_SIGNATURE)
{
printf("不是有效的MZ标志");
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)oldBufferAddr;
if (*(PWORD)((DWORD)oldBufferAddr + pDosHeader->e_lfanew) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志");
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}
//NT头
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)oldBufferAddr + pDosHeader->e_lfanew);
//pe头
pEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
//可选pe头
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pEHeader + IMAGE_SIZEOF_FILE_HEADER);
//第一个目录节指针
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pEHeader->SizeOfOptionalHeader);
//j计算文件大小
numberSection = pEHeader->NumberOfSections;
//在节表中找到最后一个节的位置
ptmpSection =pSectionHeader + (numberSection-1);
//从最后一个节中文件偏移开始
fileSize = (DWORD)ptmpSection->PointerToRawData + ptmpSection->SizeOfRawData;
tmpBuffer = (LPVOID)malloc(pOptionHeader->SizeOfImage);
if (tmpBuffer == NULL)
{
printf("内存分配失败"); //如果分配内存失败就没有必要进行下去了,释放原来分配的内存
free(oldBufferAddr);
oldBufferAddr = NULL;
return 0;
}
//初始化缓冲区
memset(tmpBuffer, 0, fileSize);
//根据sizeOfHeader拷贝头
memcpy(tmpBuffer, oldBufferAddr, pOptionHeader->SizeOfHeaders);
//根据节表进行拷贝
ptmpSection = pSectionHeader;
for (int i = 0; i < pEHeader->NumberOfSections; i++, ptmpSection++)
{
memcpy((LPVOID)((DWORD)tmpBuffer + ptmpSection->PointerToRawData), (LPVOID)((DWORD)oldBufferAddr + ptmpSection->VirtualAddress), ptmpSection->SizeOfRawData);
}
free(oldBufferAddr);
oldBufferAddr = NULL;
*NewBufferAddr = tmpBuffer;
return fileSize;
}
#include "pe.h"
#include <stdio.h>
#define FILE_IN "D:\\java\\飞鸽传书.exe"
#define FILE_OUT "D:\\java\\飞鸽传书_1.exe"
int main(void)
{
LPVOID fileBuffer = NULL;
LPVOID MemBuffer = NULL;
LPVOID NewBufferAddr = NULL;
DWORD len = 0;
readFile(FILE_IN, &fileBuffer);
FileToBuffer(fileBuffer, &MemBuffer);
len = BufferTofileBuffer(MemBuffer, &NewBufferAddr);
MentoFile(NewBufferAddr, FILE_OUT, len);
printf("hello ....");
return 0;
}