1、拉伸到内存(只是逻辑上,实际代码操作并不需要这一步)
2、分配一块新的空间:SizeOfImage + sizeof ( 新增的大小)
3、扩大节,修改最后一个节的 SizeOfRawData 和 VirtualSize
4、修改SizeOfImage大小(内存对齐)
#include<stdio.h>
#include<windows.h>
DWORD toLordPE(PSTR file_path, PVOID* pFileBuffer){
FILE *pFile;
DWORD FileSize = 0;
PVOID pFileBufferTemp = NULL;
pFile = fopen(file_path, "rb");
if(!pFile){
printf("不能打开文件!\n");
return 0;
}
fseek(pFile, 0, SEEK_END);
FileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
pFileBufferTemp = malloc(FileSize);
if(!pFileBufferTemp){
printf("不能分配内存空间!\n");
return 0;
}
fread(pFileBufferTemp, FileSize, 1, pFile);
*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;
}
}
DWORD EnlargeSection(PVOID* pFileBuffer, PVOID* pNewFileBuffer, DWORD FileSize, DWORD exSize){
DWORD FileTotal = 0;
PVOID pNewFileBufferTemp = NULL;
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("(TestEnlargeSection)Can't open file!\n");
return 0;
}
//判断是否是有效的MZ标志
if (*((PWORD)(*pFileBuffer)) != IMAGE_DOS_SIGNATURE)
{
printf("(TestEnlargeSection)No MZ flag, not exe file!\n");
return 0;
}
pDosHeader = (PIMAGE_DOS_HEADER)(*pFileBuffer);
//判断是否是有效的PE标志
if (*((PDWORD)((DWORD)(*pFileBuffer) + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(EnlargeSection)Not a valid PE flag!\n");
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);
FileTotal = FileSize + Align(exSize, pOptionHeader->FileAlignment);
*pNewFileBuffer = malloc(FileTotal);
if(!pNewFileBuffer){
printf("(enlargeSection)内存分配失败\n");
return 0;
}
memset(*pNewFileBuffer, 0, FileTotal);
memcpy(*pNewFileBuffer, *pFileBuffer, FileSize);
pDosHeader = (PIMAGE_DOS_HEADER)(*pNewFileBuffer);
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)(*pNewFileBuffer) + 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);
//遍历到最后一个节表
PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;
for (DWORD i = 1; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
{
// i=0,for结束后,pSectionHeaderTemp指向之后一个节表的后面,不是最后一个节表
// i=1,pSectionHeaderTemp指向的是最后一个
}
DWORD max = pSectionHeaderTemp->Misc.VirtualSize > pSectionHeaderTemp->SizeOfRawData ? pSectionHeaderTemp->Misc.VirtualSize : pSectionHeaderTemp->SizeOfRawData;
pSectionHeaderTemp->Misc.VirtualSize = Align(max + exSize, pOptionHeader->FileAlignment);
pSectionHeaderTemp->SizeOfRawData = Align(max + exSize, pOptionHeader->FileAlignment);
pOptionHeader->SizeOfImage = Align(pSectionHeaderTemp->VirtualAddress + pSectionHeaderTemp->Misc.VirtualSize, pOptionHeader->SectionAlignment);
return FileTotal;
}
BOOL Memory2File(PVOID pNewFileBuffer, DWORD size, PSTR write_path){
FILE *fp;
fp = fopen(write_path, "wb");
if(!fp){
printf("(MemoryToFile)写入失败!\n");
return 0;
}
printf("mtf :%x\n", pNewFileBuffer);
fwrite(pNewFileBuffer, size, 1, fp);
fclose(fp);
return 1;
}
int main(){
PSTR file_path = "C:\\Users\\lolol\\Desktop\\3.exe";
PSTR write_path = "C:\\Users\\lolol\\Desktop\\5.exe";
PVOID pFileBuffer = NULL;
PVOID pNewFileBuffer = NULL;
DWORD FileSize = toLordPE(file_path, &pFileBuffer);
printf("文件大小:%x\n", FileSize);
DWORD FileTotal = EnlargeSection(&pFileBuffer, &pNewFileBuffer, FileSize, 0x1500);
printf("%x\n",FileTotal);
if(FileTotal){
BOOL IsSuccess = Memory2File(pNewFileBuffer, FileTotal, write_path);
if(IsSuccess){
printf("扩大成功!\n");
}
}else{
printf("扩大失败!\n");
}
return 0;
}