What is DLL injection
DLL injection is a way of inserting a dynamic link library into some software whose source code you have no access to, so you can run custom code.
Writing an injector
Let’s begin with with importing some necessary libraries:
|
|
I will be introducing a few Windows API functions, along with an explanation and the MSDN documentation.
Obtaining the PID of the process
We first need to find what the PID of the process we want is, we can do that by enumerating through every process.
Microsoft provides an helpful example
We can modify it slightly to find the process we want:
|
|
We begin by enumerating each process, we obtain an handle to each one, and check if the base module’s name matches what we want.
An handle is an unique reference to a resource, in this case a process.
After we have the PID, we want to request an handle to the process with enough permissions to read and write its memory and create a thread in it.
Requesting an handle to the process
The signature of the function we need:
HANDLE OpenProcess(DWORD dwDesiredAccess, BOOL bInheritHandle, DWORD dwProcessId);
Its documentation is available here
The documentation for the available flags for dwDesiredAccess is available here
|
|
Creating a DLL
For the next step we will need an actual DLL we can inject. You can create a Dynamic Link Library project with Visual Studio. Make sure its built for the same architecture as the target process and the DLL Injector. Replace the generated code with this:
|
|
When the DLL is injected, it will display a message box. After you build the DLL, place it anywhere you’d like.
Allocating memory on the process
The next function we will use is VirtualAllocEx.
This function lets you allocate memory in another process, and will return the address where it was allocated. We need this because later on we will create a thread in the target process, and we will need a place to store the argument to the function we will start the thread with.
The function we will be starting in the target process is LoadLibrary. This function loads a DLL into the current process and since we will be starting it from a thread we create on the target process, it really means it will load a DLL into the target process. Its signature is as follows:
HMODULE LoadLibraryW(LPCWSTR lpLibFileName);
This means we will need to allocate enough space on the target process for a string with the path of the DLL we want to inject, and then copy the path string to that memory. I placed my DLL in “C:/Dll.dll”, you will want to adjust the path to where you put yours.
|
|
The documentation for flProtect argument is available here
Writing into the process
Now, we need to write the path string into the memory we just allocated, we can use WriteProcessMemory for that.
|
|
Running the DLL
We are almost at the end.
The only thing left to do is create a thread on the target process, with the LoadLibrary function, and with the DLL path as an argument.
First we need the address of the LoadLibrary function. Even though Windows has ASLR, this doesn’t appear to affect where addresses of functions in the kernel32.dll library are located, so we can obtain the function’s address from our own process.
We will use GetProcAddress to obtain the function’s address. The function signature is as follows:
FARPROC GetProcAddress(HMODULE hModule,LPCSTR lpProcName);
To obtain the value for the first argument, we will need an handle to the kernel32.dll module.
We can use GetModuleHandle for that, its signature:
HMODULE GetModuleHandleW(LPCSTR lpModuleName);
We will also need to start a thread on the remote process, we can use CreateRemoteThread for that. Its signature:
HANDLE CreateRemoteThread( HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId );
There’s a lot of arguments, but we can safely ignore most of them by using 0 or NULL and the default values for thread creation will be used. The most important one is dwCreationFlags, which we want to set to 0 so the thread runs immediately once created.
|
|
If all worked correctly, you should see a message box pop up saying “Hello, World”.
Conclusion
This is only one of several methods on DLL Injection, the Wikipedia article contains a few more.
https://en.wikipedia.org/wiki/DLL_injection#Approaches_on_Microsoft_Windows
While writing this article, Windows Defender kept preventing me from running the injector, so you might need to briefly disable it.