C# Inject a Dll into a Process (w/ CreateRemoteThread)

Since I’ve been asked if this is possible - well…you can do Dll Injection using C# but the injected Dll must be written in a language that doesn’t depend on a CLR (C/C++ would be a good option here, but it’s ok to write the injector in C#).

I’m writing this tutorial as a prologue - some day… I’ll try to publish one about hotpatching executables and…it requires stuff from here.

Disclaimer: almost all AV programs detect this as a possible malware simply because this behaviour is specific to some viruses/keygens/etc. - and they prefer to be rather paranoid than ineffective. Even if this technique has a bad reputation it has legit uses like hotpatching & logging - and this is what I’m going to write about.

Some theory

Dll Injection is a technique used to make a running process (executable) load a Dll without requiring a restart (name makes it kinda obvious :p).

It is usually done using 2 programs:

an Injector (written in any language)

a Dll (compiled to a native language)

The purpose of the injector is to…inject the Dll into the target process.
In order to do so:

get the handle of the process (OpenProcess())

obtain the address of this method: LoadLibraryA() (from kernel32.dll) by using GetProcAddress(); we’re trying to make the target process call it in order to load our library; DON’T hardcode this address - since Windows Vista came out, it will be different everytime.

use VirtualAllocEx to allocate a few bytes of memory on the target process

write there the name/path of our library (WriteProcessMemory())

with CreateRemoteThread() spawn the thread which will run LoadLibraryA() with the pointer to the allocated address as an argument (that pointer actually indicates the name of the dll).

One more thing: when the Dll is loaded, its DllMain() method (entry point) will be called with DLL_PROCESS_ATTACH as reason (fdwReason).

Writing the Dll

For this tutorial I used a dummy-dll which displays a MessageBox once it’s successfully loaded.

Note: always return true at the end - otherwise some processes will crash when injecting.

Writing the Injector

Ok, the fancy part. I kinda explained how all this works in the first part of the tutorial so just remember: get the handle, allocate some memory on the process, write there the name of the dll and finally, create a thread that will call LoadLibraryA and load your dll.

Also, check the comments in code and refer to the “theory” part of this article whenever you feel the need to.

usingSystem;usingSystem.Diagnostics;usingSystem.Runtime.InteropServices;usingSystem.Text;publicclassBasicInject{[DllImport("kernel32.dll")]publicstaticexternIntPtrOpenProcess(intdwDesiredAccess,boolbInheritHandle,intdwProcessId);[DllImport("kernel32.dll",CharSet=CharSet.Auto)]publicstaticexternIntPtrGetModuleHandle(stringlpModuleName);[DllImport("kernel32",CharSet=CharSet.Ansi,ExactSpelling=true,SetLastError=true)]staticexternIntPtrGetProcAddress(IntPtrhModule,stringprocName);[DllImport("kernel32.dll",SetLastError=true,ExactSpelling=true)]staticexternIntPtrVirtualAllocEx(IntPtrhProcess,IntPtrlpAddress,uintdwSize,uintflAllocationType,uintflProtect);[DllImport("kernel32.dll",SetLastError=true)]staticexternboolWriteProcessMemory(IntPtrhProcess,IntPtrlpBaseAddress,byte[]lpBuffer,uintnSize,outUIntPtrlpNumberOfBytesWritten);[DllImport("kernel32.dll")]staticexternIntPtrCreateRemoteThread(IntPtrhProcess,IntPtrlpThreadAttributes,uintdwStackSize,IntPtrlpStartAddress,IntPtrlpParameter,uintdwCreationFlags,IntPtrlpThreadId);// privileges
constintPROCESS_CREATE_THREAD=0x0002;constintPROCESS_QUERY_INFORMATION=0x0400;constintPROCESS_VM_OPERATION=0x0008;constintPROCESS_VM_WRITE=0x0020;constintPROCESS_VM_READ=0x0010;// used for memory allocation
constuintMEM_COMMIT=0x00001000;constuintMEM_RESERVE=0x00002000;constuintPAGE_READWRITE=4;publicstaticintMain(){// the target process - I'm using a dummy process for this
// if you don't have one, open Task Manager and choose wisely
ProcesstargetProcess=Process.GetProcessesByName("testApp")[0];// geting the handle of the process - with required privileges
IntPtrprocHandle=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ,false,targetProcess.Id);// searching for the address of LoadLibraryA and storing it in a pointer
IntPtrloadLibraryAddr=GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");// name of the dll we want to inject
stringdllName="test.dll";// alocating some memory on the target process - enough to store the name of the dll
// and storing its address in a pointer
IntPtrallocMemAddress=VirtualAllocEx(procHandle,IntPtr.Zero,(uint)((dllName.Length+1)*Marshal.SizeOf(typeof(char))),MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);// writing the name of the dll there
UIntPtrbytesWritten;WriteProcessMemory(procHandle,allocMemAddress,Encoding.Default.GetBytes(dllName),(uint)((dllName.Length+1)*Marshal.SizeOf(typeof(char))),outbytesWritten);// creating a thread that will call LoadLibraryA with allocMemAddress as argument
CreateRemoteThread(procHandle,IntPtr.Zero,0,loadLibraryAddr,allocMemAddress,0,IntPtr.Zero);return0;}}