[C] 纯文本查看 复制代码
#include <iostream>
#include <windows.h>
// 读取PE,返回PE大小
DWORD ToLoaderPE(LPSTR file_path, PVOID *pFileBuffer){
FILE *pFile = NULL;
DWORD FileSize = 0;
PVOID pFileBufferTemp = NULL;
pFile = fopen(file_path, "rb");
if(!pFile){
printf("Can not open file\n");
return 0;
}
fseek(pFile, 0, SEEK_END);
FileSize = ftell(pFile);
printf("FileBuffer Size: %x\n",FileSize);
fseek(pFile, 0, SEEK_SET);
pFileBufferTemp = malloc(FileSize);
if(!pFileBufferTemp){
printf("malloc fail!\n");
fclose(pFile);
}
DWORD n = fread(pFileBufferTemp, FileSize, 1, pFile);
if(!n){
printf("read file failed!\n");
free(pFileBufferTemp);
fclose(pFile);
return 0;
}
*pFileBuffer = pFileBufferTemp;
pFileBufferTemp = NULL;
fclose(pFile);
return FileSize;
}
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer){
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;
if(!pFileBuffer){
printf("file loader failed!\n");
return 0;
}
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE){
printf("Don not hava MZ!\n");
return 0;
}
// 找出各个结构的起始地址
pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
if(*((LPDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("没有PE符号");
return 0;
}
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
// 头部,节表等内容拉伸放入内存
PVOID pImageTemp = malloc(pOptionHeader -> SizeOfImage);
if(!pImageTemp){
printf("申请内存映像失败!");
free(pImageTemp);
return 0;
}
memset(pImageTemp, 0, pOptionHeader->SizeOfImage);
memcpy(pImageTemp, pFileBuffer, pOptionHeader->SizeOfHeaders);
int n;
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
printf("节表数量:%d\n", pPEHeader->NumberOfSections);
for(n=0; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++){
memcpy((PVOID)((DWORD)pImageTemp + pSectionHeaderTemp->VirtualAddress), (PVOID)((DWORD)pFileBuffer + pSectionHeaderTemp ->PointerToRawData), pSectionHeaderTemp->SizeOfRawData);
printf("第%d节表:内存偏移%x,磁盘偏移%x\n", n, pSectionHeaderTemp->VirtualAddress, pSectionHeaderTemp->PointerToRawData);
}
*pImageBuffer = pImageTemp;
pImageTemp = NULL;
return pOptionHeader->SizeOfImage;
}
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer, PVOID* pNewFileBuffer){
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;
if(!pImageBuffer){
printf("内存加载失败!\n");
return 0;
}
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE){
printf("Don not hava MZ!\n");
return 0;
}
// 找出头部各个结构的起始地址
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE){
printf("没有PE符号");
return 0;
}
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pImageBuffer + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
// 计算要申请空间
int new_file_size = pOptionHeader->SizeOfHeaders;
for(int i=0; i < pPEHeader->NumberOfSections; i++){
new_file_size += pSectionHeader[i].SizeOfRawData;
}
// 申请文件存盘空间
LPVOID pNewFileBufferTemp = malloc(new_file_size);
if(!pNewFileBufferTemp){
printf("存盘空间申请失败!");
return 0;
}
// 头部放进去
memset(pNewFileBufferTemp, 0, new_file_size);
memcpy(pNewFileBufferTemp, pDosHeader, pOptionHeader->SizeOfHeaders);
// 各个节表放进去
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
for(i=0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
memcpy((PVOID)((DWORD)pNewFileBufferTemp + pSectionHeaderTemp->PointerToRawData), (PVOID)((DWORD)pImageBuffer + pSectionHeaderTemp->VirtualAddress), pSectionHeaderTemp->SizeOfRawData);
*pNewFileBuffer = pNewFileBufferTemp;
pNewFileBufferTemp = NULL;
return new_file_size;
}
int newbuffer_write2_exe(PVOID NewFileBuffer,DWORD FileSize, LPSTR FilePath){
FILE* fp1 = fopen(FilePath,"wb");
if(fp1 != NULL)
fwrite(NewFileBuffer,FileSize,1,fp1);
fclose(fp1);
return 1;
}
int main()
{
LPSTR file_path = "C:\\WINDOWS\\system32\\notepad.exe";
LPSTR write_file_path = "c:\\2.exe";
LPVOID pFileBuffer = NULL; // 从磁盘读取到缓存
LPVOID pImageBuffer = NULL;// 缓存拉伸存放到内存
LPVOID pNewFileBuffer = NULL; // 存盘
// 读取PE到缓存
DWORD FileSize = ToLoaderPE(file_path, &pFileBuffer);
printf("exe to buffer : %x\n", FileSize);
// 缓存拉伸到内存
DWORD ImageSize = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
printf("拉伸到内存的大小 : %x\n", ImageSize);
DWORD NewFileSize = CopyImageBufferToNewBuffer(pImageBuffer, &pNewFileBuffer);
printf("要存盘的大小:%x\n", NewFileSize);
int ret4 = newbuffer_write2_exe(pNewFileBuffer, NewFileSize, write_file_path);
printf("newbuffer->存盘返回值为:%d\n",ret4);
return 0;
}