向PE文件中空白处添加代码

// mem.cpp : 定义控制台应用程序的入口点。
//PE文件从文件加载到内存,再从内存读取,然后存盘到文件

#include "stdafx.h"
#include <windows.h>
#include <winnt.h>

//#define  PATH "C:\Windows\System32\notepad.exe"
#define  PATH "C:\Users\Administrator\Desktop\ipmsg.exe"
#define  MsgADD 0x74e3fd1e
char Shellcode[] =
{
	0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00, 0x6A, 0x00,
	0xE8, 0x00, 0x00, 0x00, 0x00,
	0xE9, 0x00, 0x00, 0x00, 0x00
};

int Filelength(FILE *fp);
int _tmain(int argc, _TCHAR* argv[])
{
	FILE *Fp;
	fopen_s(&Fp, PATH, "rb");
	int FileSize = Filelength(Fp);//获取文件大小
	char * FileBuffer = (char *)malloc(FileSize);//申请存放文件的内存空间
	if (FileBuffer == NULL)
	{
		printf("申请iImageBuffer失败");
	}
	fread_s(FileBuffer, FileSize, 1, FileSize, Fp); //将文件复制到内存中
	//定位一下内存中的数据 各个头表
	//定位标准PE头 
	PIMAGE_FILE_HEADER MyFileHeader;
	MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(FileBuffer + *(int *)(FileBuffer + 0x3c) + 0x4);
	//定位可选PE头 
	PIMAGE_OPTIONAL_HEADER  MyOptionalHeader;
	MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
	//定位节表
	PIMAGE_SECTION_HEADER MySectionHeader;
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);


	//拉伸,也就是读到内存中的状态
	char * ImageBuffer = (char *)malloc(MyOptionalHeader->SizeOfImage);//给拉伸申请内存空间
	//ZeroMemory(ImageBuffer, MyOptionalHeader->SizeOfImage);

	if (ImageBuffer == NULL)
	{
		printf("申请iImageBuffer失败");
	}
	memcpy(ImageBuffer, FileBuffer, MyOptionalHeader->SizeOfHeaders);


	for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
	{
		memcpy(ImageBuffer + MySectionHeader->VirtualAddress, FileBuffer + MySectionHeader->PointerToRawData, MySectionHeader->SizeOfRawData);//
		MySectionHeader++;
	}
	//添加代码到PE中 
	MyFileHeader = (PIMAGE_FILE_HEADER)(char *)(ImageBuffer + *(int *)(ImageBuffer + 0x3c) + 0x4);
	MyOptionalHeader = (PIMAGE_OPTIONAL_HEADER)((char *)MyFileHeader + 0x14);
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面动过了

	//E8后面的硬编码地址 =真正要到的地址 - E8的下一行或E8本行 +0x5
	char *CodeAdd =ImageBuffer + MySectionHeader->VirtualAddress + MySectionHeader->Misc.VirtualSize;//为要增加的代码确定位置
	memcpy(CodeAdd, Shellcode, sizeof(Shellcode));//把硬编码复制到指定位置
	int CallAdd = MsgADD - (MyOptionalHeader->ImageBase + ((int)(CodeAdd + 0xd) - (int)ImageBuffer));
	*(int *)(CodeAdd + 0x9) = CallAdd;//定位CALL函数位置
	int JmpAdd = MyOptionalHeader->ImageBase + MyOptionalHeader->AddressOfEntryPoint - (MyOptionalHeader->ImageBase + (CodeAdd + 0xd - ImageBuffer));//前面是真正要跳的地址  后面括号是下一条指令的地址
	*(int *)(CodeAdd + 0xe) = JmpAdd;//定位JMP 跳回位置,也就是修改程序入口
	MyOptionalHeader->AddressOfEntryPoint = CodeAdd - ImageBuffer;//重新定位程序入口处
	
	//添加代码到PE结束

	//压缩,为存盘做准备
	char *NewBuffer = (char *)malloc(FileSize);//给压缩申请内存空间
	if (NewBuffer == NULL)
	{
		printf("申请iImageBuffer失败");
	}
	memcpy(NewBuffer, ImageBuffer, MyOptionalHeader->SizeOfHeaders);
	MySectionHeader = (PIMAGE_SECTION_HEADER)((char *)MyOptionalHeader + MyFileHeader->SizeOfOptionalHeader);//重新指一下,前面动过了

	for (int i = 0; i < MyFileHeader->NumberOfSections; i++)
	{
		memcpy(NewBuffer + MySectionHeader->PointerToRawData, ImageBuffer + MySectionHeader->VirtualAddress, MySectionHeader->SizeOfRawData);
		MySectionHeader++;
	}
	FILE *nFp;
	fopen_s(&nFp, "C:\Users\Administrator\Desktop\CYP.exe", "wb");
	fwrite(NewBuffer, FileSize, 1, nFp);

	//getchar();
	fclose(nFp);
	free(FileBuffer);
	free(ImageBuffer);
	free(NewBuffer);
	return 0;
}

//获取文件大小



int Filelength(FILE *fp)
{
	int num;
	fseek(fp, 0, SEEK_END);
	num = ftell(fp);
	fseek(fp, 0, SEEK_SET);
	return num;
}
原文地址:https://www.cnblogs.com/wumac/p/5272846.html