参考:Revival_S
1、拉伸到内存 (这里是真的拉伸到一块内存空间)
2、将第一个节的内存大小、文件大小改成一样
VirtualSize = SizeOfRawData = 整个文件拉伸后的大小 - 第一节VirtualAddress
即相当于在拉伸后的文件中 从第一个节表开始到 最后 都作为第一个节的内存长度与文件长度
3、将第一个节的属性改为包含所有节的属性 (所有节的Characteristics 全部按位或在一起)
4、修改节的数量为1
5、其他节表的空间全部置0
6、最后将这个拉伸的空间直接拷贝到文件
#include<stdio.h>
#include<windows.h>
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 Align(DWORD ad, DWORD alignment){
if(ad % alignment == 0){
return ad;
}else{
return ((ad / alignment) + 1) * alignment;
}
}
int write2file(PVOID ImageBuffer,DWORD Size, PSTR FilePath)
{
if(!ImageBuffer){
printf("没有东西可以写入\n");
}
FILE* fp1 = fopen(FilePath,"wb");
if(!fp1)
{
printf("不能打开要写入的文件\n");
}else{
fwrite(ImageBuffer,Size,1,fp1);
}
fclose(fp1);
return 1;
}
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("(CopyFileBufferToImageBuffer)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("(CopyImageBufferToNewBuffer)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;
printf("每个节:%x\n",pSectionHeader[i].SizeOfRawData);
}
printf("头加节:%x\n",new_file_size);
// 申请文件存盘空间
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;
}
DWORD HBSection(PVOID* pImageBuffer){
PVOID ppImageBuffer = NULL;
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
pDosHeader = (PIMAGE_DOS_HEADER)(*pImageBuffer);
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pDosHeader + pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);
pSectionHeader->SizeOfRawData = Align(pOptionHeader->SizeOfImage - pSectionHeader->VirtualAddress, pOptionHeader->FileAlignment);
printf("duiqi:%x\n",pSectionHeader->SizeOfRawData);
pSectionHeader->Misc.VirtualSize = pSectionHeader->SizeOfRawData;
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
DWORD Characteristics = pSectionHeader->Characteristics;
pSectionHeaderTemp++;
for(DWORD n=1; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++){
Characteristics = pSectionHeaderTemp->Characteristics | Characteristics;
memset(pSectionHeaderTemp, 0, IMAGE_SIZEOF_SECTION_HEADER);
}
// 修改第一个节表属性
pSectionHeader->Characteristics = Characteristics;
printf("Name:%s\n",pSectionHeader->Name);
pPEHeader->NumberOfSections = 1;
return 0;
}
int main(){
PSTR file_path = "C:\\Users\\lolol\\Desktop\\3.exe";
PSTR write_path = "C:\\Users\\lolol\\Desktop\\6.exe";
PVOID pFileBuffer = NULL;
PVOID pImageBuffer = NULL;
PVOID ppImageBuffer = NULL;
DWORD FileSize = ToLoaderPE(file_path, &pFileBuffer);
printf("文件磁盘上大小:%x\n", FileSize);
DWORD sizeOfImage = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
printf("文件在内存中的大小:%x\n", sizeOfImage);
HBSection(&pImageBuffer);
DWORD sizeOfFile = CopyImageBufferToNewBuffer(pImageBuffer, &ppImageBuffer);
BOOL isSuccess = write2file(ppImageBuffer, sizeOfFile, write_path);
if(isSuccess){
printf("yes\n");
}else{
printf("no\n");
}
return 0;
}