PE合併節

把所有節合併成一個節,好處是可以騰出節表空間,保證能成功新增節。
方法是先拉伸成imagebuffer,修改第一個節的VirtualSize = SizeOfRawData = SizeOfImage - VirtualAddress,因爲PE文件本身就對齊好了,所以不用關心對齊問題。由於修改了SizeOfRawData ,處理後PE文件會變大。除此之外還要修改節的數量,和第一個節必須具有其他節的屬性。

代碼

// 合併所有節
BOOL MergeSection(LPVOID pImageBuffer, LPVOID *pNewImageBuffer, DWORD imageSize)
{
	*pNewImageBuffer = malloc(imageSize);
	memcpy(*pNewImageBuffer, pImageBuffer, imageSize);

	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;

	pDosHeader = (PIMAGE_DOS_HEADER)*pNewImageBuffer;
	pNTHeader = (PIMAGE_NT_HEADERS)(pDosHeader->e_lfanew + (DWORD)*pNewImageBuffer);	
	pPEHeader = (PIMAGE_FILE_HEADER)((DWORD)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pNTHeader + 0x18);
	pSectionHeader = (PIMAGE_SECTION_HEADER)((DWORD)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	// 第一個節的VirtualSize = SizeOfRawData = SizeOfImage - VirtualAddress
	pSectionHeader->Misc.VirtualSize = pSectionHeader->SizeOfRawData = \
		pOptionHeader->SizeOfImage - pSectionHeader->VirtualAddress;
	//對齊
	//pSectionHeader->Misc.VirtualSize = Align(pSectionHeader->Misc.VirtualSize, pOptionHeader->SectionAlignment);
	//pSectionHeader->SizeOfRawData = Align(pSectionHeader->SizeOfRawData, pOptionHeader->FileAlignment);

	// 屬性包含所有節的屬性
	for (int i = 1; i < pPEHeader->NumberOfSections; i++)
	{
		pSectionHeader[0].Characteristics |= pSectionHeader[i].Characteristics;
	}

	// 節的數量 = 1
	pPEHeader->NumberOfSections = 1;

	
	return TRUE;
}

結果

測試了幾個32位GUI程序,擴大後均能正常運行。
下圖是notepad合併節後的結果對比:

在這裏插入圖片描述
在這裏插入圖片描述可以看到,文件大小改變了,節的數量也由原來的3變成了1。

附上驅動程序

// 測試合併節
DWORD TestMergeSection(LPSTR lpszFile, LPSTR lpszOut)
{
	LPVOID pFileBuffer = NULL;
	LPVOID pNewFileBuffer = NULL;
	LPVOID pImageBuffer = NULL;
	LPVOID pNewImageBuffer = NULL;
	DWORD fileBufferSize = 0;
	DWORD newFileBufferSize = 0;
	DWORD imageBufferSize = 0;
	DWORD newImageBufferSize = 0;

	fileBufferSize = ReadPEFile(lpszFile, &pFileBuffer);
	if (fileBufferSize == 0)
	{
		printf("打開文件失敗\n");
		return -1;
	}
	imageBufferSize = CopyFileBufferToImageBuffer(pFileBuffer, &pImageBuffer);
	if (imageBufferSize == 0)
	{
		printf("拉伸失敗\n");
		return -1;
	}
	if (!MergeSection(pImageBuffer, &pNewImageBuffer, imageBufferSize))
	{
		printf("合併節失敗\n");
		return -1;
	}
	newFileBufferSize = CopyImageBufferToNewBuffer(pNewImageBuffer, &pNewFileBuffer);
	if (newFileBufferSize == 0)
	{
		printf("CopyImageBufferToNewBuffer 失敗\n");
		return -1;
	}
	if (!MemeryTOFile(pNewFileBuffer,newFileBufferSize,lpszOut))
	{
		printf("存盤失敗\n");
		return -1;
	}

	free(pFileBuffer);
	free(pNewFileBuffer);
	free(pImageBuffer);
	free(pNewImageBuffer);


	return 0;

}

int main(int argc, char *argv[])
{
	TestMergeSection("c:\\winmine.exe", "c:\\out.exe");
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章