#include <windows.h>
#define my_code ".myCode"
#define my_data ".myData"
#pragma section( my_data, read, write ) // must not have execute access
#pragma section( my_code, read, write, execute ) // must have execute
#pragma const_seg( my_data ) // constant data
#pragma data_seg( my_data ) // initialized data
#pragma bss_seg( my_data ) // uninitialized data
#pragma code_seg(my_code) // executable code
#pragma auto_inline( off ) // tell the compiler to not inline functions
int num1;
int __stdcall DoSomething(int num2)
{
int num3;
num3 = num1 + num2;
return num3;
}
#pragma auto_inline( on ) // restore
#pragma bss_seg() // restore to ".bss"
#pragma const_seg() // restore to ".rdata"
#pragma data_seg() // restore to ".data"
#pragma code_seg() // restore to ".text"
// Combine our two Sections
// section name must be 8 bytes or less (including null terminater if you want one)
// LNK4254 warning expected: merged sections have different attributes
#pragma comment(linker, "/merge:.myData=.myCode"

// append .myDate to .myCode
#pragma comment(linker, "/merge:.myCode=.Inject"

// Rename the merged section
#pragma comment(linker, "/section:.Inject,RWE"

// Read, Write, and Execute Access
iPIMAGE_SECTION_HEADER GetSectionHeader( char * szSectionName, HMODULE hModule )
{
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER) hModule;
if(dos->e_magic != IMAGE_DOS_SIGNATURE)return NULL;
PIMAGE_NT_HEADERS pe = (PIMAGE_NT_HEADERS)( (ULONG)hModule + dos->e_lfanew );
if(pe->Signature != IMAGE_NT_SIGNATURE)return NULL;
if(!pe->FileHeader.SizeOfOptionalHeader)return NULL;
PIMAGE_SECTION_HEADER section_header = IMAGE_FIRST_SECTION( pe );
for(int i = 0; i < pe->FileHeader.NumberOfSections; i++)
{
if(!strcmp((char *)section_header[I].Name,szSectionName))
{
return §ion_header[I];
}
}
return NULL;
}
// use the relocation data in the PE header to patch our code so it will
// work when loaded at any memory address
// *section must have read/write access
// *relocations must not be stripped
bool FixUpSection(PIMAGE_SECTION_HEADER pSectionHeader, DWORD dwNewBase, HMODULE hTarget)
{
bool bRet = false;
PIMAGE_DOS_HEADER dos = (PIMAGE_DOS_HEADER) hTarget;
if(dos->e_magic != IMAGE_DOS_SIGNATURE)return false;
PIMAGE_NT_HEADERS pe = (PIMAGE_NT_HEADERS)( (ULONG)hTarget + dos->e_lfanew );
if(pe->Signature != IMAGE_NT_SIGNATURE)return false;
if(!pe->FileHeader.SizeOfOptionalHeader)return false;
PIMAGE_DATA_DIRECTORY relocdir = (PIMAGE_DATA_DIRECTORY)
( pe->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_BASERELOC );
if(!relocdir->Size)return false; // if module has no relocations
PIMAGE_BASE_RELOCATION reloc = (PIMAGE_BASE_RELOCATION)
((DWORD)hTarget + relocdir->VirtualAddress);
// find the reloc chunk(s) that correspond to our section
while(reloc->VirtualAddress)
{
if(! (reloc->VirtualAddress >
pSectionHeader->VirtualAddress + pSectionHeader->SizeOfRawData))
{
if(! (reloc->VirtualAddress < pSectionHeader->VirtualAddress) )
{
/* preform fixup from relocation data */
DWORD numRelocEntries = ( reloc->SizeOfBlock -
sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
WORD * pRelEntry = (WORD *)((DWORD)reloc + sizeof(IMAGE_BASE_RELOCATION));
DWORD delta = dwNewBase - ((DWORD)pe->OptionalHeader.ImageBase +
(DWORD)pSectionHeader->VirtualAddress);
for(unsigned int i = 0; i < numRelocEntries; i++ )
{
if( ! (( pRelEntry[I] >> 12 ) == IMAGE_REL_BASED_HIGHLOW ) )
continue;
// get location to patch
PULONG CodeLoc = (DWORD *)(pe->OptionalHeader.ImageBase + reloc->VirtualAddress
+ (pRelEntry[I] & 0x0FFF));
// patch location
*CodeLoc += delta;
bRet = true;
}
}
}
reloc = (PIMAGE_BASE_RELOCATION)((DWORD)reloc + reloc->SizeOfBlock);
}
return bRet;
}
int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPI, char * CmdLine, int nCmdShow )
{
DWORD dwNewBase; // location to inject to
HANDLE hProcess; // target process
DWORD dwPID = 0; // target process id
// todo: get pid
dwPID = GetCurrentProcessId();
if( !(hProcess = OpenProcess(PROCESS_VM_WRITE | PROCESS_QUERY_INFORMATION |
PROCESS_VM_OPERATION,FALSE, dwPID)))return 0;
PIMAGE_SECTION_HEADER psh = GetSectionHeader( ".Inject", hInst );
dwNewBase = (DWORD)VirtualAllocEx(hProcess, NULL, psh->SizeOfRawData,
MEM_COMMIT, PAGE_EXECUTE_READWRITE);
FixUpSection(psh, dwNewBase, hInst);
WriteProcessMemory(hProcess,(LPVOID)dwNewBase,
&DoSomething, psh->SizeOfRawData,NULL);
CloseHandle(hProcess);
return 0;
}