扩大一个节:
流程如下:
注意:修改完ImageBuffer后需要将其再压缩(拉伸的逆过程)后再存盘。
代码:
// ExtendLastSection.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "windows.h"
#include "malloc.h"
// exe->filebuffer
DWORD ReadFile2Buffer(char* file_path,PVOID* FileBuffer);
// filebuffer->imagebuffer
DWORD Read2ImageBuffer(PVOID FileBuffer,PVOID* ImageBuffer);
// 求对齐后的大小
DWORD Align(DWORD actuall_size,DWORD Align_size);
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer,PVOID* pNewBuffer);
// 存盘
void StoreNewBuffer(PVOID pNewBuffer,DWORD new_file_size,char* save_path);
void ExtendLastSection()
{
PVOID FileBuffer = NULL;
PVOID ImageBuffer = NULL;
PVOID SaveBuffer = NULL;
DWORD FileBuffersize = 0;
DWORD ImageBuffersize = 0;
DWORD Save_size = 0;
char file_path[] = "D:\\2020学习\\逆向\\IPMSG2007.exe";
char save_path[] = "D:\\Lib\\IPMSG2007_extend_last_section.exe";
// 1.将exe文件转化为filebuffer
FileBuffersize = ReadFile2Buffer(file_path,&FileBuffer);
// 2.filebuffer -> imagebuffer(并修改)
ImageBuffersize = Read2ImageBuffer(FileBuffer,&ImageBuffer);
Save_size = CopyImageBufferToNewBuffer(ImageBuffer,&SaveBuffer);
// 3.存盘
StoreNewBuffer(SaveBuffer,Save_size,save_path);
}
// exe->filebuffer 返回filebuffer的大小
DWORD ReadFile2Buffer(char* file_path,PVOID* FileBuffer)
{
PVOID FileTempBuffer = NULL;
DWORD file_size = 0;
FILE* pFile = NULL;
// 打开文件
pFile = fopen(file_path,"rb");
if(!pFile)
{
printf("打开文件失败!\n");
return 0;
}
// 获取大小
fseek(pFile,0,SEEK_END);
file_size = ftell(pFile);
fseek(pFile,0,SEEK_SET);
// 分配内存
FileTempBuffer = (PVOID)malloc(file_size);
if(!FileTempBuffer)
{
printf("分配内存失败!\n");
fclose(pFile);
return 0;
}
// 数据存入内存
size_t n = fread(FileTempBuffer,file_size,1,pFile);
if(!n)
{
printf("文件中数据读取到内存中失败!\n");
fclose(pFile);
free(FileTempBuffer);
return 0;
}
// 关闭文件返回filebuffer的长度
*FileBuffer = FileTempBuffer;
FileTempBuffer = NULL;
fclose(pFile);
return file_size;
}
// filebuffer->imagebuffer 返回imagebuffer的大小
DWORD Read2ImageBuffer(PVOID FileBuffer,PVOID* ImageBuffer)
{
// 初始化
PVOID ImageTempBuffer = NULL;
DWORD imagebuffer_size = 0;
// 初始化PE结构体
PIMAGE_DOS_HEADER pDosHeader = NULL;
PIMAGE_NT_HEADERS pNTHeader = NULL;
PIMAGE_FILE_HEADER pPEHeader = NULL;
PIMAGE_OPTIONAL_HEADER32 pOptionalHeader = NULL;
PIMAGE_SECTION_HEADER pSectionHeader = NULL;
// 判断filebuffer是否合法
if(!FileBuffer)
{
printf("打开filebuffer失败!\n");
return 0;
}
// 判断是否为合法exe文件
if(*((PWORD)FileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不含有MZ标志,不是合法exe文件!\n");
return 0;
}
pDosHeader = PIMAGE_DOS_HEADER(FileBuffer);
if(*((PDWORD)((DWORD)FileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志!\n");
return 0;
}
// 强制结构体类型转换
pDosHeader = (PIMAGE_DOS_HEADER)(FileBuffer);
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)FileBuffer+pDosHeader->e_lfanew);
pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader+4);
pOptionalHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader+IMAGE_SIZEOF_FILE_HEADER);
pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionalHeader+pPEHeader->SizeOfOptionalHeader);
// 需要修改的部分
PDWORD pVirtualSize = &pSectionHeader[pPEHeader->NumberOfSections-1].Misc.VirtualSize;
PDWORD pSizeOfRawData = &pSectionHeader[pPEHeader->NumberOfSections-1].SizeOfRawData;
PDWORD pSizeOfImage = &pOptionalHeader->SizeOfImage;
// printf("pPEHeader->NumberOfSections:%#X\n",pPEHeader->NumberOfSections);
// 需要修改的部分
printf("*pVirtualSize:%#X\n",*pVirtualSize);
printf("pOptionalHeader->SectionAlignment:%#X\n",pOptionalHeader->SectionAlignment);
*pVirtualSize = Align(*pVirtualSize,pOptionalHeader->SectionAlignment)+0x1000;
printf("*pVirtualSize:%#X\n",*pVirtualSize);
printf("*pSizeOfRawData:%#X\n",*pSizeOfRawData);
*pSizeOfRawData = Align(*pSizeOfRawData,pOptionalHeader->SectionAlignment)+0x1000;
printf("*pSizeOfRawData:%#X\n",*pSizeOfRawData);
printf("*pSizeOfImage:%#X\n",*pSizeOfImage);
*pSizeOfImage += 0x1000;
printf("*pSizeOfImage:%#X\n",*pSizeOfImage);
printf("================================\n");
// 分配内存
DWORD ImageBuffer_size = pOptionalHeader->SizeOfImage;
ImageTempBuffer = (PVOID)malloc(ImageBuffer_size);
if(!ImageTempBuffer)
{
printf("分配内存ImageTempBuffer失败!\n");
return 0;
}
memset(ImageTempBuffer,0,ImageBuffer_size);
memcpy(ImageTempBuffer,pDosHeader,pOptionalHeader->SizeOfHeaders);
// 创建一个临时的节结构体指针,遍历存储
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
// printf("pTempSectionHeader:%#X\n",pTempSectionHeader);
// printf("(void*)((DWORD)pFileBuffer+pTempSectionHeader->PointerToRawData):%#X\n",(void*)((DWORD)FileBuffer+pTempSectionHeader->PointerToRawData));
for(int i = 0;i<pPEHeader->NumberOfSections;i++,pTempSectionHeader++)
{
// 第二个参数是 imagebuffer开始的位置,FileBuffer+PointerToRawData(image中的偏移)
memcpy((PVOID)((DWORD)ImageTempBuffer+pTempSectionHeader->VirtualAddress),(void*)((DWORD)FileBuffer+pTempSectionHeader->PointerToRawData),pTempSectionHeader->SizeOfRawData);
}
*ImageBuffer = ImageTempBuffer;
ImageTempBuffer = NULL;
return *pSizeOfImage;
}
DWORD Align(DWORD actuall_size,DWORD Align_size)
{
if(actuall_size%Align_size == 0)
{
return actuall_size;
}
else
{
int n = actuall_size / Align_size;
return Align_size*(n+1);
}
}
//imagebuffer->newbuffer
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer,PVOID* pNewBuffer)
{
// ???PE?????
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;
// ???NEW_BUFFER??(temparay)
LPVOID pTempNewbuffer = NULL;
// ??pImageBuffer????
if(!pImageBuffer)
{
printf("(2pnewbuffer??)??????pimagebuffer??!\n");
return 0;
}
//?????exe??
if(*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("(2pnewbuffer??)??MZ??,??exe??!\n");
return 0;
}
// ?????????
pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
if(*((PDWORD)((DWORD)pImageBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("(2pnewbuffer??)?????PE??!\n");
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);
//??new_buffer???
int new_buffer_size = pOptionHeader->SizeOfHeaders;
for(DWORD i = 0;i<pPEHeader->NumberOfSections;i++)
{
new_buffer_size += pSectionHeader[i].SizeOfRawData; // pSectionHeader[i]?????
}
// ????(newbuffer)
pTempNewbuffer = malloc(new_buffer_size);
if(!pTempNewbuffer)
{
printf("(2pnewbuffer??)??Newbuffer??!\n");
return 0;
}
memset(pTempNewbuffer,0,new_buffer_size);
// ????
memcpy(pTempNewbuffer,pDosHeader,pOptionHeader->SizeOfHeaders);
// ??????
PIMAGE_SECTION_HEADER pTempSectionHeader = pSectionHeader;
for(DWORD j = 0;j<pPEHeader->NumberOfSections;j++,pTempSectionHeader++)
{ //PointerToRawData?????????,VirtualAddress???????????,SizeOfRawData???????????
memcpy((PDWORD)((DWORD)pTempNewbuffer+pTempSectionHeader->PointerToRawData),(PDWORD)((DWORD)pImageBuffer+pTempSectionHeader->VirtualAddress),pTempSectionHeader->SizeOfRawData);
}
//????
*pNewBuffer = pTempNewbuffer; //????????????
pTempNewbuffer = NULL;
return new_buffer_size; // ??????????????
}
//存盘
void StoreNewBuffer(PVOID pNewBuffer,DWORD new_file_size,char* save_path)
{
FILE* fp2;
fp2 = fopen(save_path,"wb");
if(!fp2)
{
printf("写入文件失败!\n");
fclose(fp2);
return;
}
fwrite(pNewBuffer,new_file_size,1,fp2);
fclose(fp2);
}
int main(int argc, char* argv[])
{
ExtendLastSection();
getchar();
return 0;
}
结果如下:
原本exe:
最后一个节:
扩大最后一个节后: