PE文件绑定,或者说多个exe文件的合并

思路:

    是我自己想的,也许不会,也许别人已经做过了,但是不是重点,哈,我现在想将两个exe文件合并成为一个exe文件,那么就需要四个exe,现在说下这四个exe文件的作用

分别是A.exe   D.exe  tmpA.exe  tmpB.exe

A.exe的作用是将tmpA.exe和tmpB.exe文件写入到D.exe当中去,这里tmpA.exe和tmpB.exe我们是不知道源码的,但是D.exe和A.exe是知道的,

D.exe的源码是这样的:

// PE文件捆绑.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include<Windows.h>
#include<iostream>
#include<ImageHlp.h>
using namespace std;
#pragma comment(lib,"ImageHlp.lib")


char* strFileTarget="D:\\D.exe";
int gSectionNum=0;
int gSectionAlign=0;
int gFileAlign=0;
char* gFileA="D:\\tmpA.exe";
char* gFileB="D:\\tmpB.exe";
char* gExeBufferA=NULL;
char* gExeBufferB=NULL;
int gdwFileSizeA=0;
int gdwFileSizeB=0;


//函数名称:getAlign
//函数描述:根据固有对其值和将要对其的大小,返回应有大小

int getAlign(int Align,int target)
{
	if(target<Align)
	{
		return Align;
	}
	else if(target%Align)
	{
		return (target/Align+1)*Align;
	}
	else
	{
		return target;
	}
}

//函数结束



//函数名称:fileToStream
//函数描述:根据固有对其值和将要对其的大小,返回应有大小

char* fileTostream(char* srcExePathA,char* srcExePathB)
{
	//开始读取第一个文件
	HANDLE hFileA=CreateFile(srcExePathA,GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);
	DWORD dwTmp=0;
	if(hFileA==INVALID_HANDLE_VALUE)
	{
		int errNum=GetLastError();
		MessageBox(NULL,"对不起,文件打开失败",0,0);
		return 0;
	}
	gdwFileSizeA=GetFileSize(hFileA,0);
	gExeBufferA=new char[gdwFileSizeA+1];
	memset(gExeBufferA,0,gdwFileSizeA+1);
	ReadFile(hFileA,gExeBufferA,gdwFileSizeA,&dwTmp,NULL);
	CloseHandle(hFileA);
	//开始读取第二个文件
	HANDLE hFileB=CreateFile(srcExePathB,GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,0);
	if(hFileB==INVALID_HANDLE_VALUE)
	{
		MessageBox(NULL,"对不起,文件打开失败",0,0);
		return 0;
	}
	gdwFileSizeB=GetFileSize(hFileB,0);
	gExeBufferB=new char[gdwFileSizeB+1];
	memset(gExeBufferB,0,gdwFileSizeB+1);
	ReadFile(hFileB,gExeBufferB,gdwFileSizeB,&dwTmp,NULL);
	CloseHandle(hFileB);
}

//函数结束






//函数名称:editTarget
//函数描述:编辑目标exe文件,将待捆绑文件作为数据放在新
//          区块中

void editTarget()
{
	//尝试打开文件
	HANDLE hFile=CreateFile(strFileTarget,GENERIC_ALL,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
	if(INVALID_HANDLE_VALUE==hFile)
	{
		int srrNum=GetLastError();
		MessageBox(NULL,"文件打开失败",0,0);
		return ;
	}
	//获得文件大小
	DWORD dwFileSize=GetFileSize(hFile,0);
	//尝试映射到内存
	HANDLE hMap=CreateFileMapping(hFile,NULL,PAGE_EXECUTE_READWRITE,0,dwFileSize+getAlign(512,gdwFileSizeA)+getAlign(512,gdwFileSizeB),0);
	if(INVALID_HANDLE_VALUE==hMap)
	{
		MessageBox(NULL,"文件映射失败",0,0);
		return ;
	}
    LPVOID lpBase=MapViewOfFile(hMap,FILE_MAP_READ|FILE_MAP_WRITE,0,0,0);
	//获得文件的DOS头部
	PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)lpBase;
	//检测DOS头部,是否是PE文件
	if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
	{
		MessageBox(NULL,"非PE文件",0,0);
		return ;
	}
	//获得文件的NT头部,需要注意的是pDosHeader需要进行强制类型转换,pDosHeader转成DWORD
	PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
	if(pNtHeader->Signature!=IMAGE_NT_SIGNATURE)
	{
		MessageBox(NULL,"非PE文件",0,0);
		return ;
	}
	//记录区块的数目
	gSectionNum=pNtHeader->FileHeader.NumberOfSections;
	//记录内存对其值
	gSectionAlign=pNtHeader->OptionalHeader.SectionAlignment;
	//记录文件对其值
	gFileAlign=pNtHeader->OptionalHeader.FileAlignment;	
	//移动文件指针,方便我们进行读取区块信息
	 SetFilePointer(hFile,pDosHeader->e_lfanew  +sizeof(IMAGE_NT_HEADERS),0,0);
	IMAGE_SECTION_HEADER LastSection={0};
	DWORD dwTmp;
	//开始读取区块信息,当然只记录最后一个区块的信息
	for(int i=0;i<gSectionNum;i++)
	{
		ReadFile(hFile,&LastSection,sizeof(IMAGE_SECTION_HEADER),&dwTmp,NULL);
	}	 
	//将exeA的文件内容写入到newA区块当中去,新建一个区块,A
	IMAGE_SECTION_HEADER SectionA={0};
	memcpy(SectionA.Name,".NewA",5);
	SectionA.Characteristics=IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_EXECUTE;
	SectionA.PointerToRawData=LastSection.PointerToRawData+LastSection.SizeOfRawData;
	SectionA.SizeOfRawData=getAlign(gFileAlign,gdwFileSizeA);
	SectionA.Misc.VirtualSize=gdwFileSizeA;
	SectionA.VirtualAddress=LastSection.VirtualAddress+getAlign(gSectionAlign,LastSection.Misc.VirtualSize);
	//写入新的区块,移动文件指针
	SetFilePointer(hFile,pDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS)+(pNtHeader->FileHeader.NumberOfSections)*sizeof(IMAGE_SECTION_HEADER),0,0);
	WriteFile(hFile,&SectionA,sizeof(IMAGE_SECTION_HEADER),&dwTmp,NULL);
	pNtHeader->FileHeader.NumberOfSections++;
	//向区块中写入数据,移动文件指针
	SetFilePointer(hFile,SectionA.PointerToRawData,0,0);
	//首先写入大小	
	WriteFile(hFile,gExeBufferA,gdwFileSizeA,&dwTmp,NULL);
	//修改镜像大小
	pNtHeader->OptionalHeader.SizeOfCode+=gdwFileSizeA;
	pNtHeader->OptionalHeader.SizeOfImage+=gdwFileSizeA;
	//开始进行第二个文件的内容写入
	IMAGE_SECTION_HEADER SectionB={0};
	SectionB.Misc.VirtualSize=gdwFileSizeB;
	memcpy(SectionB.Name,".NewB",5);
	SectionB.Characteristics=IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE|IMAGE_SCN_MEM_EXECUTE;
	SectionB.PointerToRawData=SectionA.PointerToRawData+SectionA.SizeOfRawData;
	SectionB.SizeOfRawData=getAlign(gFileAlign,gdwFileSizeB);
	SectionB.Misc.VirtualSize=gdwFileSizeB;
	SectionB.VirtualAddress=SectionA.VirtualAddress+getAlign(gSectionAlign,gdwFileSizeB);
	//写入新的区块信息,移动文件指针
	SetFilePointer(hFile,pDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS)+(pNtHeader->FileHeader.NumberOfSections)*sizeof(IMAGE_SECTION_HEADER),0,0);
	WriteFile(hFile,&SectionB,sizeof(IMAGE_SECTION_HEADER),&dwTmp,0);
	pNtHeader->FileHeader.NumberOfSections++;
	//向区块中写入数据
	SetFilePointer(hFile,SectionB.PointerToRawData,0,0);	
	WriteFile(hFile,gExeBufferB,gdwFileSizeB,&dwTmp,0);
	//修改镜像大小
	pNtHeader->OptionalHeader.SizeOfCode+=gdwFileSizeA;
	pNtHeader->OptionalHeader.SizeOfImage+=gdwFileSizeA;
	CloseHandle(hFile);
	MessageBox(NULL,"写入成功",0,0);	
}

//函数结束

int _tmain(int argc, _TCHAR* argv[])
{
	fileTostream(gFileA,gFileB);
	editTarget();
	return 0;
}

而A.exe的源码是这样的:

// tmpB.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include<Windows.h>


//函数名称:getAlign
//函数描述:根据固有对其值和将要对其的大小,返回应有大小

int getAlign(int Align,int target)
{
	if(target<Align)
	{
		return Align;
	}
	else if(target%Align)
	{
		return (target/Align+1)*Align;
	}
	else
	{
		return target;
	}
}

//函数结束

int _tmain(int argc, _TCHAR* argv[])
{
	
	HANDLE hFile=:: GetModuleHandle (NULL);
	if(hFile==INVALID_HANDLE_VALUE)
	{
		int a=GetLastError();
		return 0;
	}
	LPVOID lpBase=(LPVOID)hFile;
	PIMAGE_DOS_HEADER pDosHeader=(PIMAGE_DOS_HEADER)lpBase;
	if(pDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
	{
		MessageBox(NULL,"对不起不是有效的额PE文件",0,0);		
		return 0;
	}
	//读取区块的名字
	PIMAGE_NT_HEADERS pNtHeader=(PIMAGE_NT_HEADERS)((DWORD)pDosHeader+pDosHeader->e_lfanew);
	if(pNtHeader->Signature!=IMAGE_NT_SIGNATURE)
	{
		MessageBoxA(NULL,"对不起,不是有效的PE文件",0,0);
		return 0;
	}
	//移动文件指针,读取特定的区块内容,
	int a=pNtHeader->FileHeader.NumberOfSections;
	LPVOID lpSectionsHeader=(LPVOID)((DWORD)pDosHeader+pDosHeader->e_lfanew+sizeof(IMAGE_NT_HEADERS));
	PIMAGE_SECTION_HEADER pSectionA=(PIMAGE_SECTION_HEADER)((DWORD)lpSectionsHeader+7*(sizeof(IMAGE_SECTION_HEADER)));
	if(strcmp((char*)pSectionA->Name,".NewA")!=0)
	{
		return 0;
	}
	//移动指针,获得该区块中文件大小	
	char* tmpA=new char[pSectionA->Misc.VirtualSize];
	memset(tmpA,0,pSectionA->Misc.VirtualSize);
	memcpy(tmpA,(char*)((DWORD)pDosHeader+pSectionA->VirtualAddress),pSectionA->Misc.VirtualSize);
	DWORD dwTmp=0;
	HANDLE hFileA=CreateFileA("heheA.exe",GENERIC_ALL,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0);
	WriteFile(hFileA,tmpA,pSectionA->Misc.VirtualSize,&dwTmp,NULL);
	CloseHandle(hFileA);	
	STARTUPINFO si;
    PROCESS_INFORMATION pi;
    LPTSTR szCmdline=NULL;
    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    ZeroMemory( &pi, sizeof(pi) );
	CreateProcessA("heheA.exe",NULL,NULL,NULL,false,0,NULL,NULL,&si,&pi);	
	//开始获取第二个文件的内容
	PIMAGE_SECTION_HEADER pSectionB=(PIMAGE_SECTION_HEADER)((DWORD)lpSectionsHeader+8*sizeof(IMAGE_SECTION_HEADER));
	//开始获取文件大小
	DWORD dwFileSizeB=pSectionB->Misc.VirtualSize;
	char* FileBBuffer=new char[dwFileSizeB+1];
	memset(FileBBuffer,0,dwFileSizeB+1);
	memcpy(FileBBuffer,(void*)((DWORD)pDosHeader+pSectionB->VirtualAddress),dwFileSizeB);
	HANDLE hFileB=CreateFile("heheB.exe",GENERIC_ALL,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
	if(hFileB==INVALID_HANDLE_VALUE)
	{
		return 0;
	}
	WriteFile(hFileB,FileBBuffer,dwFileSizeB,&dwTmp,NULL);
	CloseHandle(hFileB);
	if(CreateProcess("heheB.exe",NULL,NULL,NULL,false,0,NULL,NULL,&si,&pi))
	{
		return 0;
	}	
	DeleteFile("heheA.exe");
    DeleteFile("heheB.exe");	
}

即,将tmpA.exe的数据写入到D.exe的NewA的区块当中去,tmpB.exe的数据内容写入到newB的区块当中去,然后呢,在D.exe执行时查找自己的IMAGE_SECTION_HEADER

中是否有newA和NewB区块,如果有则将其写入到一个新的文件当中去,CreateFile,创建成功之后CreateProcess即可,最后最好再DeleteFile,就更完美了

哈哈,自己瞎写的,大神飘过即可

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值