public: static int injectDll(HANDLE processHandle, TCHAR* dllToInject, int sizeOfDllPath) {
VOID* pvProcessPath = VirtualAllocEx(processHandle, NULL, sizeOfDllPath, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(processHandle, pvProcessPath, dllToInject, sizeOfDllPath, NULL);
VOID* pvLoadLibraryAddress = GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "LoadLibraryW");
DWORD nThreadIdentifier;
CreateRemoteThread(processHandle, NULL, NULL, (LPTHREAD_START_ROUTINE) pvLoadLibraryAddress, pvProcessPath, 0, &nThreadIdentifier);
return 1;
}
In the DLL, I just call the OutputDebugString() method that should be safe to call from the DllMain (the entry point in the DLL):
#include <iostream>
#include "stdafx.h"
#include "tester.h"
#include <windows.h>
#pragma unmanaged
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
switch (fdwReason) {
case DLL_PROCESS_ATTACH:
OutputDebugString(L"DLL injected");
}
return TRUE;
};
To view the debug messages, I used a tool named DebugView (by Microsoft).
The complete code is the following:
#include "stdafx.h"
#include <windows.h>
#include <tlhelp32.h>
#include <WinDef.h>
class Injector {
public: const static int PROCESS_NOT_FOUND = 1;
public: const static HANDLE getHandle(const LPCWSTR processName) {
PROCESSENTRY32 entry;
entry.dwSize = sizeof(PROCESSENTRY32);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
if (Process32First(snapshot, &entry) == TRUE)
{
while (Process32Next(snapshot, &entry) == TRUE)
{
if (wcscmp(entry.szExeFile, processName) == 0) {
printf("Handle found for process %ls (%i) \n", processName, entry.th32ProcessID);
return OpenProcess(PROCESS_ALL_ACCESS, FALSE, entry.th32ProcessID);
}
}
}
throw PROCESS_NOT_FOUND;
}
public: static void closeHandle(HANDLE handle) {
CloseHandle(handle);
}
public: static int injectDll(HANDLE processHandle, TCHAR* dllToInject, int sizeOfDllPath) {
VOID* pvProcessPath = VirtualAllocEx(processHandle, NULL, sizeOfDllPath, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
WriteProcessMemory(processHandle, pvProcessPath, dllToInject, sizeOfDllPath, NULL);
VOID* pvLoadLibraryAddress = GetProcAddress(GetModuleHandle(_T("kernel32.dll")), "LoadLibraryW");
DWORD nThreadIdentifier;
CreateRemoteThread(processHandle, NULL, NULL, (LPTHREAD_START_ROUTINE) pvLoadLibraryAddress, pvProcessPath, 0, &nThreadIdentifier);
return 1;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
const LPCWSTR processName = L"vlc.exe";
TCHAR dllPath[MAX_PATH] = L"C:\\Users\\oss\\Documents\\Visual\ Studio\ 2010\\Projects\\injector\\Debug\\tester.dll";
try {
HANDLE handle = Injector::getHandle(processName);
Injector::injectDll(handle, dllPath, sizeof dllPath);
Injector::closeHandle(handle);
printf("Dll was injected to %ls \n", processName);
} catch (int e) {
if(e == Injector::PROCESS_NOT_FOUND) {
printf("Process %ls not found \n", processName);
} else {
printf("Some unknown error was thrown: %i \n", e);
}
}
return 0;
}