新增一个节
// testt.cpp : Defines the entry point for the console application.
//
#define _CRT_SECURE_NO_WARNINGS
#include "stdafx.h"
#include <malloc.h>
#include <windows.h>
#include <string.h>
int Read2file(char* file_path,PVOID* FileBuffer);
DWORD CopyImageBufferToNewBuffer(PVOID pFileBuffer,PVOID* pNeweBuffer,DWORD file_size);
void StoreNewBuffer(PVOID pNewBuffer,DWORD new_file_size,char* save_path);
void add_new_section()
{ // 0.初始化
PVOID pFileBuffer = NULL;
PVOID pNewBuffer = NULL;
DWORD file_size = 0;
DWORD new_buffer_size = 0;
// 1.从文件中读取/计算文件大小/开辟一段内存/写入内存中
char file_path[] = "D:\\2020学习\\逆向\\IPMSG2007.exe";
char save_path[] = "D:\\Lib\\IPMSG2007附件.exe";
file_size = Read2file(file_path,&pFileBuffer);
// printf("file_size:%d",file_size);
// 2.将filebuffer修改后转存到newbuffer
new_buffer_size = CopyImageBufferToNewBuffer(pFileBuffer,&pNewBuffer,file_size);
// 3.将修改后的newbuffer存盘
StoreNewBuffer(pNewBuffer,new_buffer_size,save_path);
}
// exe->filebuffer
int Read2file(char* file_path,PVOID* FileBuffer)
{
FILE* pfile = NULL;
DWORD file_size = 0;
PVOID pTempFileBuffer = NULL;
// 打开文件需要判断
pfile = fopen(file_path,"rb");
if(!pfile)
{
printf("打开.exe文件失败!\n");
return 0;
}
// 计算文件大小
fseek(pfile,0,SEEK_END);
file_size = ftell(pfile);
fseek(pfile,0,SEEK_SET);
// 分配动态内存
pTempFileBuffer = (char*)malloc(file_size);
if(!pTempFileBuffer)
{
printf("分配动态内存失败!\n");
fclose(pfile);
return 0;
}
// 将文件中的数据读取到动态内存中
size_t n = fread(pTempFileBuffer,file_size,1,pfile);
if(!n)
{
printf("读取文件数据到内存中失败!\n");
fclose(pfile);
free(pTempFileBuffer);
return 0;
}
// 关闭文件
*FileBuffer = pTempFileBuffer;
pTempFileBuffer = NULL; // 注意这里不能free
fclose(pfile);
return file_size;
}
// filebuffer->NEWbuffer
DWORD CopyImageBufferToNewBuffer(PVOID pFileBuffer,PVOID* pNewBuffer,DWORD file_size)
{
PVOID pNewTempBuffer = NULL;
DWORD New_file_size = 0;
DWORD Remained_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;
PIMAGE_SECTION_HEADER pLastSection = NULL;
// ====================判断是否为有效exe文件======================================
// 判断filebuffer是否有效
if(!pFileBuffer)
{
printf("读取filebuffer失败!\n");
return 0;
}
// 判断是否可执行文件
if(*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
{
printf("不含MZ标志,不是合法的exe文件!\n");
return 0;
}
// 强制类型转换
pDosHeader = PIMAGE_DOS_HEADER(pFileBuffer);
// 判断是否含有PE标志
if(*((PDWORD)((DWORD)pFileBuffer+pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
{
printf("不是有效的PE标志!\n");
return 0;
}
// ====================开辟新的内存空间,并拷贝到新的内存中======================
// 开辟新的内存空间+0x1000
New_file_size = file_size+0x1000;
pNewTempBuffer = (PVOID)malloc(New_file_size);
// 判断开辟空间是否成功
if(!pNewTempBuffer)
{
printf("pNewTempBuffer开辟空间失败!\n");
return 0;
}
// 初始化内存
memset(pNewTempBuffer,0,New_file_size);
// 将旧空间的内容copy到新的空间
memcpy(pNewTempBuffer,pFileBuffer,file_size);
// ============================判断剩余的空间是否足够============================
// 初始化PE头部结构体
pDosHeader = (PIMAGE_DOS_HEADER)(pNewTempBuffer);
pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pNewTempBuffer+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);
//最后一个节表的地址
pLastSection = &pSectionHeader[pPEHeader->NumberOfSections-1];
// 判断剩余的空间是否足够
Remained_size = (DWORD)(pOptionalHeader->SizeOfHeaders-
pDosHeader->e_lfanew-4-
sizeof(PIMAGE_FILE_HEADER)-
pPEHeader->SizeOfOptionalHeader-
sizeof(PIMAGE_SECTION_HEADER)*pPEHeader->NumberOfSections);
if(Remained_size < 2*sizeof(PIMAGE_SECTION_HEADER))
{
printf("exe文件头部剩余空间不足!\n");
free(pNewTempBuffer);
return 0;
}
// ============================修改信息============================
// 其他头部需要修改的内容
PWORD pNumberOfSection = &pPEHeader->NumberOfSections;
PDWORD pSizeOfImage = &pOptionalHeader->SizeOfImage;
// 初始化新节表的信息
PVOID pSecName = &pSectionHeader[pPEHeader->NumberOfSections].Name;
PDWORD pSecMisc = &pSectionHeader[pPEHeader->NumberOfSections].Misc.VirtualSize;
PDWORD pSecVirtualAddress = &pSectionHeader[pPEHeader->NumberOfSections].VirtualAddress;
PDWORD pSecSizeofRawData = &pSectionHeader[pPEHeader->NumberOfSections].SizeOfRawData;
PDWORD pSecPointerToRawData = &pSectionHeader[pPEHeader->NumberOfSections].PointerToRawData;
PDWORD pSecCharacteristic = &pSectionHeader[pPEHeader->NumberOfSections].Characteristics;
*pNumberOfSection = pPEHeader->NumberOfSections+1;
printf("*pNumberOfSection:%#X\n",pPEHeader->NumberOfSections);
*pSizeOfImage = pOptionalHeader->SizeOfImage+0x1000;
// printf("pSizeOfImage:%#X\n",*pSizeOfImage);
// 向节表中填入数据
memcpy(pSecName,".newSec",8);
*pSecMisc = 0x1000;
//最后一个节表中VirtualAddress+max(VirtualSize,SizeOfRawData)
DWORD add_size = pLastSection->Misc.VirtualSize > pLastSection->SizeOfRawData?
pLastSection->Misc.VirtualSize:pLastSection->SizeOfRawData;
/*
printf("NumberOfSections:%d\n",pPEHeader->NumberOfSections);
printf("virtualAddress:%X\n",pSectionHeader[pPEHeader->NumberOfSections-2].VirtualAddress);
printf("add_size:%#X\n",add_size);
return 0;*/
*pSecVirtualAddress = pLastSection->VirtualAddress+add_size;
//SectionAlignment对齐
if(*pSecVirtualAddress % pOptionalHeader->SectionAlignment)
{
*pSecVirtualAddress = *pSecVirtualAddress / pOptionalHeader->SectionAlignment * pOptionalHeader->SectionAlignment+pOptionalHeader->SectionAlignment;
}
*pSecSizeofRawData = 0x1000;
*pSecPointerToRawData = pLastSection->PointerToRawData+pLastSection->SizeOfRawData;
// FILEAlignment对齐
if(*pSecPointerToRawData % pOptionalHeader->FileAlignment)
{
*pSecPointerToRawData = (*pSecPointerToRawData) / pOptionalHeader->FileAlignment * pOptionalHeader->FileAlignment + pOptionalHeader->FileAlignment;
}
*pSecCharacteristic = 0xFFFFFFFF;
*pNewBuffer = pNewTempBuffer;
pNewTempBuffer = NULL;
return New_file_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[])
{
add_new_section();
getchar();
return 0;
}