欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

滴水逆向——PE扩大一个节

程序员文章站 2022-04-26 12:28:39
...

1.问题描述:

滴水逆向——PE扩大一个节

滴水逆向——PE扩大一个节

2.代码实现:

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#define size_shellcode 0x12
#define size_surplus_sizeofheader 0x50
#define messagebox_add 0x76EE2030  

DWORD ToLeaderPE(LPSTR file_path, PVOID* pFileBuffer);
VOID ReadPEFile(IN LPVOID pFileBuffer);
DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer);
DWORD CopyImageBufferToNewBuffer(PVOID pImageBuffer, PVOID* pNewBuffer);
BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile);
DWORD TestAddCodeInDataSec(PVOID pImageBuffer, PVOID* pNewFileBuffer, DWORD FileSize);
DWORD TestAddCodeInXXXSec(PVOID pImageBuffer, PVOID* pNewFileBuffer, DWORD SecNumb, DWORD FileSize);
DWORD RvaToFileOffset(IN LPVOID pImageBuffer, IN LPVOID pFileBuffer, IN DWORD dwRva);
DWORD FoaToImageOffset(IN LPVOID pFileBuffer, IN LPVOID pImageBuffer, IN DWORD dwFoa);
DWORD TestAddSection(IN LPVOID file_path, IN LPVOID* pFileBuffer, IN LPVOID* pAddSectionBuffer);
DWORD TestEnlargeSection(IN LPVOID* pFileBuffer, IN LPVOID* pEnlargerSection);
DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address);

BYTE shellcode[] = {
	0x6A,00,0x6A,00,0x6A,00,0x6A,00,
	0XE8,00,00,00,00,
	0XE9,00,00,00,00
};

char file_path[] = "D:\\IPMSG2007\\IPMSG2007.exe";
char write_file_path[] = "D:\\Lib\\cp_XX.exe";
char write_adddata_file_path[] = "D:\\Lib\\cp_adddata_XX.exe";
char write_addXXXsec_file_path[] = "D:\\Lib\\cp_addXXXsec_XX.exe";
char write_addsec_file_path[] = "D:\\Lib\\cp_addsec_XX.exe";
char write_enlargersec_file_path[] = "D:\\Lib\\cp_enlargersec_XX.exe";

DWORD ToLeaderPE(LPSTR file_path, PVOID* pFileBuffer)
{
	FILE *pFile = NULL;
	DWORD fileSize = 0;
	LPVOID pFileBufferTemp = NULL;

	pFile = fopen(file_path, "rb");

	if (!pFile)
	{
		printf("can't open file1\n");
		return 0;
	}

	fseek(pFile, 0, SEEK_END);
	fileSize = ftell(pFile);
	printf("FileBuffer: %x\n", fileSize);
	fseek(pFile, 0, SEEK_SET);
	pFileBufferTemp = malloc(fileSize);

	if (!pFileBufferTemp)
	{
		printf("apply memory failed\n");
		fclose(pFile);
		return 0;
	}

	size_t n = fread(pFileBufferTemp, fileSize, 1, pFile);

	if (!n)
	{
		printf("read data filed\n");
		free(pFileBufferTemp);
		fclose(pFile);
		return 0;
	}
	*pFileBuffer = pFileBufferTemp;
	pFileBufferTemp = NULL;
	fclose(pFile);
	return fileSize;
}

VOID ReadPEFile(IN LPVOID pFileBuffer)
{
	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("文件读取失败\n");
		return;
	}

	//判断是否是有效的MZ标志	
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		free(pFileBuffer);
		return;
	}
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	//打印DOC头	
	printf("\n********************DOS头********************\n");
	printf("MZ标志:%x\n", pDosHeader->e_magic);
	printf("PE偏移:%x\n", pDosHeader->e_lfanew);
	//判断是否是有效的PE标志	
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pFileBuffer);
		return;
	}
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pFileBuffer + pDosHeader->e_lfanew);
	//打印NT头	
	printf("********************NT头********************\n");
	printf("NT:%x\n", pNTHeader->Signature);
	pPEHeader = (PIMAGE_FILE_HEADER)(((DWORD)pNTHeader) + 4);

	//int NumberOfSections = pPEHeader->NumberOfSections;
	//int SizeOfOptionalHeader = pPEHeader->SizeOfOptionalHeader;

	printf("********************PE头********************\n");
	printf("PE:%x\n", pPEHeader->Machine);
	printf("节的数量:%x\n", pPEHeader->NumberOfSections);
	printf("SizeOfOptionalHeader:%x\n", pPEHeader->SizeOfOptionalHeader);
	//可选PE头	
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	printf("********************OPTIOIN_PE头********************\n");
	printf("OPTION_PE:%x\n", pOptionHeader->Magic);

	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	for (int n = 0; n < pPEHeader->NumberOfSections; n++)
	{
		printf("********************SECTION %d********************\n", n + 1);
		char name[9] = { 0 };
		memcpy(name, pSectionHeader->Name, 8);
		printf("SECTION NAME: %s\n", name);
		printf("VirtualAddress: %x\n", pSectionHeader->VirtualAddress);
		printf("SizeOfRawData: %x\n", pSectionHeader->SizeOfRawData);
		printf("PointerToRawData: %x\n", pSectionHeader->PointerToRawData);
		printf("Characteristics: %x\n", pSectionHeader->Characteristics);
		pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pSectionHeader + IMAGE_SIZEOF_SECTION_HEADER);
	}
}

DWORD CopyFileBufferToImageBuffer(PVOID pFileBuffer, PVOID* pImageBuffer)
{
	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;

	LPVOID pImageTemp = NULL;

	if (!pFileBuffer)
	{
		printf("(CopyFileBufferToImageBuffer)FileBuffer open failed\n");
		return 0;
	}

	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE) 
	{
		printf("(CopyFileBufferToImageBuffer)不含MZ标志,不是exe文件!\n");
		return 0;
	}

	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;

	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{																			 
		printf("(CopyFileBufferToImageBuffer)不是有效的PE标志!\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);

	pImageTemp = malloc(pOptionHeader->SizeOfImage);

	if (!pImageTemp)
	{
		printf("(CopyFileBufferToImageBuffer)allocate dynamic memory failed!\n");
		free(pImageTemp);
		return 0;
	}

	memset(pImageTemp, 0, pOptionHeader->SizeOfImage);
	memcpy(pImageTemp, pDosHeader, pOptionHeader->SizeOfHeaders);

	PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;

	for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionHeaderTemp++)
	{

		memcpy((PVOID)((DWORD)pImageTemp + pSectionHeaderTemp->VirtualAddress), (PVOID)((DWORD)pFileBuffer + pSectionHeaderTemp->PointerToRawData), pSectionHeaderTemp->SizeOfRawData);

		printf("VirtualAddress%d: %10x         PointerToRawData%d: %10x\n", n, (DWORD)pImageTemp + pSectionHeader->VirtualAddress, n, (DWORD)pFileBuffer + pSectionHeader->PointerToRawData);

	}
	*pImageBuffer = pImageTemp;
	pImageTemp = NULL;
	return pOptionHeader->SizeOfImage;

}

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;  // 返回计算得到的分配内存的大小
}

BOOL MemeryTOFile(IN LPVOID pMemBuffer, IN size_t size, OUT LPSTR lpszFile)
{
	FILE *fp;
	fp = fopen(lpszFile, "wb");
	if (fp != NULL)
	{
		fwrite(pMemBuffer, size, 1, fp);
	}
	fclose(fp);
	return 1;
}

DWORD RvaToFileOffset(IN LPVOID pImageBuffer, IN LPVOID pFileBuffer, IN DWORD dwRva)
{
	// 初始化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;

	DWORD ImageOffset = dwRva;
	//DWORD RelSectionOffset = 0;

	// 判断pImageBuffer是否有效
	if (!pImageBuffer)
	{
		printf("(RVA转换成FOA阶段)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(RVA转换成FOA阶段)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
	if (*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(RVA转换成FOA阶段)不是有效的PE标志!\n");
		return 0;
	}

	printf("ImageOffset: %x\n", ImageOffset);
	// 强制结构体类型转换
	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);

	PIMAGE_SECTION_HEADER pSectionTemp = pSectionHeader;

	if (ImageOffset <= pOptionHeader->SizeOfHeaders)
		return (DWORD)pFileBuffer + ImageOffset;
	else
	{
		for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionTemp++)
		{
			if ((ImageOffset >= pSectionTemp[n].VirtualAddress) && (ImageOffset <= pSectionTemp[n].VirtualAddress + pSectionTemp[n].Misc.VirtualSize))
			{
				return ImageOffset - pSectionTemp[n].VirtualAddress + pSectionTemp[n].PointerToRawData;
			}
		}
	}
	printf("地址转换失败!\n");
	return 0;
}

DWORD FoaToImageOffset(IN LPVOID pFileBuffer, IN LPVOID pImageBuffer, IN DWORD dwFoa)
{
	// 初始化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;

	DWORD FileOffset = dwFoa;
	//DWORD RelSectionOffset = 0;

	// 判断pImageBuffer是否有效
	if (!pFileBuffer)
	{
		printf("(FOA转换RVA成阶段)读取到内存的ImageBuffer无效!\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pFileBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(FOA转换RVA成阶段)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	if (*((PDWORD)((DWORD)pFileBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(FOA转换RVA成阶段)不是有效的PE标志!\n");
		return 0;
	}
	printf("FileOffset: %x\n", FileOffset);

	// 强制结构体类型转换
	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);

	PIMAGE_SECTION_HEADER pSectionTemp = pSectionHeader;

	if (FileOffset <= pOptionHeader->SizeOfHeaders)
		return (DWORD)pFileBuffer + FileOffset;
	else
	{
		for (int n = 0; n < pPEHeader->NumberOfSections; n++, pSectionTemp++)
		{	//判断 :   文件对齐+文件偏移>file_panyi>文件偏移  (即是在文件的哪个节中)
			if ((FileOffset >= pSectionTemp->PointerToRawData) && (FileOffset < pSectionTemp->PointerToRawData + pSectionTemp->SizeOfRawData))
			{
				return FileOffset - pSectionTemp->PointerToRawData + pSectionTemp->VirtualAddress;
			}
		}	
	}
	printf("地址转换失败!\n");
	return 0;
}

DWORD TestAddCodeInXXXSec(PVOID pImageBuffer, PVOID* pNewFileBuffer,DWORD SecNumb, DWORD FileSize)
{
	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;

	// 判断pImageBuffer是否有效
	if (!pImageBuffer)
	{
		printf("(TestAddCodeInDataSec)ImageBuffer open failed\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(TestAddCodeInDataSec)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
	if (*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(TestAddCodeInDataSec)不是有效的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);

	PIMAGE_SECTION_HEADER pSectionHeaderTemp = pSectionHeader;

	for (int n = 1; n < SecNumb; n++, pSectionHeaderTemp++)
	{
		//
	}

	//判断XX区空间够不够放shellcode
	if (size_shellcode > (pSectionHeaderTemp->SizeOfRawData - pSectionHeaderTemp->Misc.VirtualSize))
	{
		printf("XX section sapce not enough to store shellcode\n");
		free(pImageBuffer);
		return 0;
	}

	printf("pSectionHeader->PointerToRawData:%x  pSectionHeader->Misc.VirtualSize:%x\n", pSectionHeaderTemp->PointerToRawData, pSectionHeaderTemp->Misc.VirtualSize);
	printf("pImageBuffer:%x\n", pImageBuffer);

	//填充代码
	PBYTE CodeAddLoc = (PBYTE)((DWORD)pImageBuffer + pSectionHeaderTemp->VirtualAddress + pSectionHeaderTemp->Misc.VirtualSize);
	printf("pSectionHeader->VirtualAddress:%X\n", pSectionHeaderTemp->VirtualAddress);
	printf("CodeAddLoc:%x\n", CodeAddLoc);
	memcpy(CodeAddLoc, shellcode, size_shellcode);

	//修改E8跳转地址
	DWORD callAddr = (messagebox_add - (pOptionHeader->ImageBase + ((DWORD)(CodeAddLoc + 0xD) - (DWORD)pImageBuffer)));
	*(PDWORD)(CodeAddLoc + 0x09) = callAddr;
	//修改E9跳转地址
	DWORD jmpAddr = (pOptionHeader->AddressOfEntryPoint - ((DWORD)(CodeAddLoc + size_shellcode) - (DWORD)pImageBuffer));
	*(PDWORD)(CodeAddLoc + 0x0E) = jmpAddr;

	pOptionHeader->AddressOfEntryPoint = (DWORD)CodeAddLoc - (DWORD)pImageBuffer;

	size_t size = CopyImageBufferToNewBuffer(pImageBuffer, pNewFileBuffer);

	if (size = 0 || !pNewFileBuffer)
	{
		printf("imagebuffer->newfilebuffer失败!\n");
		free(pImageBuffer);
		free(pNewFileBuffer);
	}
	// 存盘
	size_t ret_loc1 = MemeryTOFile(*pNewFileBuffer, FileSize, write_addsec_file_path);
	if (!ret_loc1)
	{
		printf("store memory failed!\n");
		return 0;
	}
	return 1;
}

DWORD TestAddCodeInDataSec(PVOID pImageBuffer, PVOID* pNewFileBuffer, DWORD FileSize)
{
	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;

	// 判断pImageBuffer是否有效
	if (!pImageBuffer)
	{
		printf("(TestAddCodeInDataSec)ImageBuffer open failed\n");
		return 0;
	}
	//判断是不是exe文件
	if (*((PWORD)pImageBuffer) != IMAGE_DOS_SIGNATURE)
	{
		printf("(TestAddCodeInDataSec)不含MZ标志,不是exe文件!\n");
		return 0;
	}
	// 强制结构体类型转换
	pDosHeader = (PIMAGE_DOS_HEADER)pImageBuffer;
	if (*((PDWORD)((DWORD)pImageBuffer + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("(TestAddCodeInDataSec)不是有效的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);

	//判断代码区空间够不够放shellcode
	if (size_shellcode > (pSectionHeader->SizeOfRawData - pSectionHeader->Misc.VirtualSize))
	{
		printf("Data section sapce not enough to store shellcode\n");
		free(pImageBuffer);
		return 0;
	}

	printf("pSectionHeader->PointerToRawData:%x  pSectionHeader->Misc.VirtualSize:%x\n", pSectionHeader->PointerToRawData, pSectionHeader->Misc.VirtualSize);
	printf("pImageBuffer:%x\n", pImageBuffer);

	//填充代码
	PBYTE CodeAddLoc = (PBYTE)((DWORD)pImageBuffer + pSectionHeader->VirtualAddress + pSectionHeader->Misc.VirtualSize);
	printf("pSectionHeader->VirtualAddress:%X\n", pSectionHeader->VirtualAddress);
	printf("CodeAddLoc:%x\n", CodeAddLoc);
	memcpy(CodeAddLoc, shellcode, size_shellcode);

	//修改E8跳转地址
	DWORD callAddr = (messagebox_add - (pOptionHeader->ImageBase + ((DWORD)(CodeAddLoc + 0xD) - (DWORD)pImageBuffer)));
	*(PDWORD)(CodeAddLoc + 0x09) = callAddr;
	//修改E9跳转地址
	DWORD jmpAddr = (pOptionHeader->AddressOfEntryPoint - ((DWORD)(CodeAddLoc + size_shellcode) - (DWORD)pImageBuffer));
	*(PDWORD)(CodeAddLoc + 0x0E) = jmpAddr;

	pOptionHeader->AddressOfEntryPoint = (DWORD)CodeAddLoc - (DWORD)pImageBuffer;

	size_t size = CopyImageBufferToNewBuffer(pImageBuffer, pNewFileBuffer);

	if (size = 0 || !pNewFileBuffer)
	{
		printf("imagebuffer->newfilebuffer失败!\n");
		free(pImageBuffer);
		free(pNewFileBuffer);
	}
	// 存盘
	size_t ret_loc1 = MemeryTOFile(*pNewFileBuffer, FileSize, write_adddata_file_path);
	if (!ret_loc1)
	{
		printf("store memory failed!\n");
		return 0;
	}
	return 1;
}

DWORD Alignment(DWORD alignment_value, DWORD addend, DWORD address)
{
	int n = 0;
	if (addend / alignment_value)
	{
		if (addend%alignment_value)
		{
			n = addend / alignment_value + 1;
		}
		else
		{
			n = addend / alignment_value;
		}
	}
	else
	{
		if (addend)
			n = 0;
		else
			n = 1;
	}
	address += n * alignment_value;
	return address;
}

DWORD TestAddSection(IN LPVOID file_path, IN LPVOID* pFileBuffer, IN LPVOID* pAddSectionBuffer)
{
	LPVOID pAddSectionTemp = NULL;
	//加载.exe的PE结构
	size_t ret_loc2 = ToLeaderPE(file_path, pFileBuffer);
	size_t AddSecTotal = ret_loc2 + 0x1000;

	pAddSectionTemp = malloc(AddSecTotal);

	if (!pAddSectionTemp)
	{
		printf("apply memory failed\n");
		return 0;
	}

	memset(pAddSectionTemp, 0, AddSecTotal);
	memcpy(pAddSectionTemp, *pFileBuffer, ret_loc2);

	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 (!pAddSectionTemp)
	{
		printf("文件读取失败\n");
		return;
	}

	//判断是否是有效的MZ标志	
	if (*((PWORD)pAddSectionTemp) != IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		free(pAddSectionTemp);
		return;
	}
	pDosHeader = (PIMAGE_DOS_HEADER)pAddSectionTemp;

	//判断是否是有效的PE标志	
	if (*((PDWORD)((DWORD)pAddSectionTemp + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pAddSectionTemp);
		return;
	}
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pAddSectionTemp + 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 = 0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
	{
		//
	}
	
	//判断SizeOFHeader能否放下多余两个节区(一个新增节区,一个全0节区代表区块结束)
	//分三种情况:1.节表后直接可以放下两个节区 2.节表后放不下,但是dos头后pe前可放下 3.前两种情况都不行,需扩大最后一个节把代码填进去
	//就讨论第一种情况吧...
	if (size_surplus_sizeofheader <= (pOptionHeader->SizeOfHeaders - ((DWORD)(pSectionHeaderTemp - pAddSectionTemp))))
	{
		printf("enough\n");
		//得到最后一个节的信息
		pSectionHeaderTemp--;
		//填充节
		DWORD ret_loc3 = Alignment(0x1000, (DWORD)pSectionHeaderTemp->Misc.VirtualSize, (DWORD)pSectionHeaderTemp->VirtualAddress);
		memset(((PBYTE)(DWORD)pAddSectionTemp + ret_loc3), 0, 0x1000);
		//改节数目
		pPEHeader->NumberOfSections = pPEHeader->NumberOfSections + 1;
		//填充节表
		pSectionHeaderTemp++;
		memcpy(pSectionHeaderTemp, pSectionHeader, IMAGE_SIZEOF_SECTION_HEADER);
		memcpy(pSectionHeaderTemp, ".add", 8);

		pSectionHeaderTemp->VirtualAddress = ret_loc3;
		pSectionHeaderTemp->SizeOfRawData = 0x1000;
		pSectionHeaderTemp->PointerToRawData = ret_loc3;
		pSectionHeaderTemp->Misc.VirtualSize = 0x1000;
		pOptionHeader->SizeOfImage = AddSecTotal;
	}
	else
	{
		free(pAddSectionTemp);
		printf("insufficient");
	}

	size_t ret_loc4 = MemeryTOFile(pAddSectionTemp, AddSecTotal, write_addsec_file_path);
	if (!ret_loc4)
	{
		printf("store memory failed!\n");
		return 0;
	}

	*pAddSectionBuffer = pAddSectionTemp; //暂存的数据传给参数后释放
	free(pAddSectionTemp);
	pAddSectionTemp = NULL;

	return AddSecTotal;
}

DWORD TestEnlargeSection(IN LPVOID* pFileBuffer, IN LPVOID* pEnlargerSection)
{
	LPVOID pEnlargerSectionTemp = NULL;
	//加载.exe的PE结构
	size_t ret_loc2 = ToLeaderPE(file_path, pFileBuffer);
	size_t EnlargerSecTotal = ret_loc2 + 0x1000;

	pEnlargerSectionTemp = malloc(EnlargerSecTotal);

	if (!pEnlargerSectionTemp)
	{
		printf("apply memory failed\n");
		return 0;
	}

	memset(pEnlargerSectionTemp, 0, EnlargerSecTotal);
	memcpy(pEnlargerSectionTemp, *pFileBuffer, ret_loc2);

	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 (!pEnlargerSectionTemp)
	{
		printf("文件读取失败\n");
		return;
	}

	//判断是否是有效的MZ标志	
	if (*((PWORD)pEnlargerSectionTemp) != IMAGE_DOS_SIGNATURE)
	{
		printf("不是有效的MZ标志\n");
		free(pEnlargerSectionTemp);
		return;
	}
	pDosHeader = (PIMAGE_DOS_HEADER)pEnlargerSectionTemp;

	//判断是否是有效的PE标志	
	if (*((PDWORD)((DWORD)pEnlargerSectionTemp + pDosHeader->e_lfanew)) != IMAGE_NT_SIGNATURE)
	{
		printf("不是有效的PE标志\n");
		free(pEnlargerSectionTemp);
		return;
	}
	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)pEnlargerSectionTemp + 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 = 0; i < pPEHeader->NumberOfSections; i++, pSectionHeaderTemp++)
	{
		//
	}

	DWORD max = (pSectionHeaderTemp->SizeOfRawData > pSectionHeaderTemp->Misc.VirtualSize ? pSectionHeaderTemp->SizeOfRawData : pSectionHeaderTemp->Misc.VirtualSize);
	pSectionHeaderTemp->SizeOfRawData = max + 0x1000;
	pSectionHeaderTemp->Misc.VirtualSize = max + 0x1000;

	pOptionHeader->SizeOfImage = Alignment(pOptionHeader->SectionAlignment, pSectionHeaderTemp->Misc.VirtualSize, pOptionHeader->SizeOfImage);

	size_t ret_loc4 = MemeryTOFile(pEnlargerSectionTemp, pOptionHeader->SizeOfImage, write_enlargersec_file_path);
	if (!ret_loc4)
	{
		printf("store memory failed!\n");
		return 0;
	}

	*pEnlargerSection = pEnlargerSectionTemp; //暂存的数据传给参数后释放
	free(pEnlargerSectionTemp);
	pEnlargerSectionTemp = NULL;

	return EnlargerSecTotal;
}


int main()
{

	LPVOID pFileBuffer = NULL;
	LPVOID pNewFileBuffer = NULL;
	LPVOID pImageBuffer = NULL;
	LPVOID pAddSectionBuffer = NULL;
	LPVOID pEnlargerSection = NULL;
	size_t pRVA = 0x00021178;
	size_t pFOA = 0x00020450;

	//size_t ret5 = TestAddSection(file_path, &pFileBuffer, &pAddSectionBuffer);
	//printf("TestAddSection Buffer: %x", ret5);

	size_t ret6 = TestEnlargeSection(&pFileBuffer, &pEnlargerSection);
	printf("TestEnlargeSection Buffer: %x", ret6);

	//size_t ret1 = ToLeaderPE(file_path, &pFileBuffer);  // &pFileBuffer(void**类型) 传递地址对其值可以进行修改
	//printf("exe->filebuffer  返回值为计算所得文件大小:%#x\n", ret1);
	//ReadPEFile(pFileBuffer);
	//size_t ret2 = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
	//printf("filebuffer -> imagebuffer返回值为计算所得文件大小:%#x\n", ret2);
	//size_t ret3 = CopyImageBufferToNewBuffer(pImageBuffer, &pNewFileBuffer);
	//MemeryTOFile(pNewFileBuffer, ret3, write_file_path);
	//int ret_FOA1 = RvaToFileOffset(pImageBuffer, pFileBuffer, pRVA);
	//printf("内存偏移%#x 转换为文件中的偏移:%#x\n", pRVA, ret_FOA1);
	//int ret_RVA1 = FoaToImageOffset(pFileBuffer, pImageBuffer, pFOA);
	//printf("文件偏移%#x 转换为内存中的偏移:%#x\n", pFOA, ret_RVA1);
	//size_t ret4 = TestAddCodeInDataSec(pImageBuffer, &pNewFileBuffer, ret1);
	//size_t ret4 = TestAddCodeInXXXSec(pImageBuffer, &pNewFileBuffer, 3, ret1);
	//printf("%d", ret4);
	free(pFileBuffer);
	free(pNewFileBuffer);
	free(pImageBuffer);
	
	return 0;
}

3.结果展示:

滴水逆向——PE扩大一个节

滴水逆向——PE扩大一个节

滴水逆向——PE扩大一个节

相关标签: 内存管理