Добавление новой секции в EXE
Код на C++, добавление новой секции в PE файл
/////////////////////////////////////////////////////////////////
//
// Coded by NEOx <NEOx@Pisem.net>
//
/////////////////////////////////////////////////////////////////
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#include <windows.h>
#include "MMFiles.h"
#ifdef NDEBUG
#pragma optimize ("gsy",on)
#pragma comment (linker,"/IGNORE:4078 /IGNORE:4089")
#pragma comment (linker,"/RELEASE")
#pragma comment (linker,"/merge:.rdata=.data")
#pragma comment (linker,"/merge:.text=.data")
#pragma comment (linker,"/merge:.reloc=.data")
#if _MSC_VER >= 1000
#pragma comment (linker,"/FILEALIGN:0×200")
#endif
#endif
#pragma comment (linker,"/ENTRY:main")
#define DEFAULT_NEW_SECTION_CHARACTERISTICS IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE
#define MIN (a,b) ((a)<(b)?(a):(b))
#define RALIGN (dwToAlign, dwAlignOn) ((dwToAlign % dwAlignOn == 0) ? dwToAlign : dwToAlign — (dwToAlign % dwAlignOn) + dwAlignOn)
#if !defined (MakePtr)
#define MakePtr (cast, ptr, addValue) (cast)( (DWORD)(ptr) + (DWORD)(addValue))
#endif
BOOL AddSectionHeader (PIMAGE_SECTION_HEADER pSH);
BOOL IsRoom (LPVOID lpMem);
PIMAGE_SECTION_HEADER GetLastSection (LPVOID lpMap);
DWORD CalcRealSizeOfImage (LPVOID m_Map);
DWORD CalcRealHeaderSize (PIMAGE_NT_HEADERS pNT);
BOOL LoadSectionFromFile (CHAR *szFilePath, LPVOID lpData, DWORD dwDataSize);
int main ()
{
BYTE sb[20023] = {'N', 'E', 'O', 'x'};
LoadSectionFromFile ("c.exe", sb, sizeof (sb));
return 0;
}
BOOL AddSectionHeader (LPVOID lpMem, PIMAGE_SECTION_HEADER pSH)
{
PIMAGE_DOS_HEADER pDosH;
PIMAGE_NT_HEADERS pNTH;
PIMAGE_SECTION_HEADER pLastH;
if (!IsRoom (lpMem))
{
MessageBox (GetActiveWindow (), "Not enough room for a new section available !", "Error", MB_ICONERROR);
return FALSE;
}
pDosH = (PIMAGE_DOS_HEADER) lpMem;
pNTH = (PIMAGE_NT_HEADERS)((DWORD) pDosH + pDosH->e_lfanew);
__try
{
pLastH = GetLastSection (lpMem);
pLastH++;
CopyMemory (pLastH, pSH, sizeof (IMAGE_SECTION_HEADER));
pNTH->FileHeader.NumberOfSections++;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
MessageBox (GetActiveWindow (), "Access violation !", "Error", MB_OK | MB_ICONERROR);
return FALSE;
}
return TRUE;
}
BOOL IsRoom (LPVOID lpMem)
{
PIMAGE_DOS_HEADER pDosH;
PIMAGE_NT_HEADERS pNTH;
PIMAGE_SECTION_HEADER pSH;
DWORD dwNumOfSect, dwHeadersSize;
pDosH = (PIMAGE_DOS_HEADER) lpMem;
pNTH = (PIMAGE_NT_HEADERS)((DWORD) pDosH + pDosH->e_lfanew);
pSH = IMAGE_FIRST_SECTION (pNTH);
dwNumOfSect = pNTH->FileHeader.NumberOfSections;
dwHeadersSize = sizeof (IMAGE_NT_HEADERS) + (dwNumOfSect * sizeof (IMAGE_SECTION_HEADER)) + sizeof (IMAGE_SECTION_HEADER);
if (dwHeadersSize > pNTH->OptionalHeader.SizeOfHeaders)
return FALSE;
return TRUE;
}
PIMAGE_SECTION_HEADER GetLastSection (LPVOID lpMap)
{
WORD u;
PIMAGE_DOS_HEADER pDosh;
PIMAGE_NT_HEADERS pPeh;
IMAGE_SECTION_HEADER *pSH;
__try
{
pDosh = (PIMAGE_DOS_HEADER) lpMap;
pPeh = (PIMAGE_NT_HEADERS)((DWORD) pDosh + pDosh->e_lfanew);
pSH = IMAGE_FIRST_SECTION32 (pPeh);
for (u = 0; u < pPeh->FileHeader.NumberOfSections — 1; u++) ++pSH;
return pSH;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
MessageBox (GetActiveWindow (), "Access violation !", "Error", MB_OK | MB_ICONERROR);
return NULL;
}
}
DWORD CalcRealSizeOfImage (LPVOID m_Map)
{
DWORD dwCorrSoI = 0;
DWORD dwNumOfSect = 0;
PIMAGE_DOS_HEADER pDosh = {0};
PIMAGE_NT_HEADERS pPeh = {0};
IMAGE_SECTION_HEADER *pSH;
pDosh = (PIMAGE_DOS_HEADER) m_Map;
pPeh = (PIMAGE_NT_HEADERS)((DWORD) pDosh + pDosh->e_lfanew);
pSH = IMAGE_FIRST_SECTION32 (pPeh);
dwNumOfSect = pPeh->FileHeader.NumberOfSections;
for (WORD i = 0; i < dwNumOfSect; i++)
{
if ((pSH->VirtualAddress + pSH->Misc.VirtualSize) > dwCorrSoI)
dwCorrSoI = pSH->VirtualAddress + pSH->Misc.VirtualSize;
++pSH;
}
return dwCorrSoI;
}
DWORD CalcRealHeaderSize (PIMAGE_NT_HEADERS pNT)
{
DWORD dwHSize;
UINT i;
IMAGE_SECTION_HEADER *pS;
if (!pNT->FileHeader.NumberOfSections)
return ((PIMAGE_NT_HEADERS32) pNT) ->OptionalHeader.SizeOfHeaders;
dwHSize = 0xFFFFFFFF;
pS = IMAGE_FIRST_SECTION (pNT);
for (i = 0; i < pNT->FileHeader.NumberOfSections; i++)
{
if (pS->PointerToRawData)
dwHSize = MIN (dwHSize, pS->PointerToRawData);
++pS;
}
// Fix
return (dwHSize > 0×00001000) ? 0×00001000 : dwHSize;
}
BOOL LoadSectionFromFile (CHAR *szFilePath, LPVOID lpData, DWORD dwDataSize)
{
CMMFiles m_File;
PIMAGE_DOS_HEADER pDosH;
PIMAGE_NT_HEADERS pNTH;
PIMAGE_SECTION_HEADER pSH;
IMAGE_SECTION_HEADER pNewSH[1];
if (!m_File.MMMakeMappedFile (szFilePath))
{
// File I/O error
return FALSE;
}
//
// Если юзаешь мою Dll'ку (rebpe32.dll), тогда расскомментируй вызов
// этой функции. Потому что лучше выровнять все секции.
//
// DumpFixer32 (m_File.m_pMap);
if (!m_File.MMSetFileSize (m_File.MMGetFileSize () + dwDataSize))
{
// Clean up
m_File.MMEndMappedFile ();
return FALSE;
}
try
{
// Copy new section data
pSH = GetLastSection (m_File.m_pMap);
// !!! BUG !!!
CopyMemory (MakePtr (LPVOID, m_File.m_pMap, (pSH->PointerToRawData + pSH->SizeOfRawData)), lpData, dwDataSize);
}
catch (...)
{
MessageBox (GetActiveWindow (), "Access violation !", "Error", MB_OK | MB_ICONERROR);
return FALSE;
}
pDosH = (PIMAGE_DOS_HEADER) m_File.m_pMap;
pNTH = (PIMAGE_NT_HEADERS)((DWORD) pDosH + pDosH->e_lfanew);
ZeroMemory (&pNewSH, sizeof (IMAGE_SECTION_HEADER));
lstrcpy ((CHAR *) pNewSH[0].Name, ".NewSect");
pNewSH[0].Characteristics = DEFAULT_NEW_SECTION_CHARACTERISTICS;
pNewSH[0].Misc.VirtualSize = dwDataSize/*RALIGN (dwDataSize, pNTH->OptionalHeader.SectionAlignment)*/;
pNewSH[0].VirtualAddress = pSH->VirtualAddress + pSH->Misc.VirtualSize;
pNewSH[0].SizeOfRawData = dwDataSize;
pNewSH[0].PointerToRawData = pSH->PointerToRawData + pSH->SizeOfRawData;
if (!AddSectionHeader (m_File.m_pMap, pNewSH))
{
// Clean up
m_File.MMEndMappedFile ();
return FALSE;
}
pNTH->OptionalHeader.SizeOfImage = CalcRealSizeOfImage (m_File.m_pMap);
pNTH->OptionalHeader.SizeOfHeaders = CalcRealHeaderSize (pNTH);
// Clean up
m_File.MMEndMappedFile ();
return TRUE;
}
Автор: NEOx