DLL injection

1

In computer programming, DLL injection is a technique used for running code within the address space of another process by forcing it to load a dynamic-link library. DLL injection is often used by external programs to influence the behavior of another program in a way its authors did not anticipate or intend. For example, the injected code could hook system function calls, or read the contents of password textboxes, which cannot be done the usual way. A program used to inject arbitrary code into arbitrary processes is called a DLL injector.

Approaches on Microsoft Windows

There are multiple ways on Microsoft Windows to force a process to load and execute code in a DLL that the authors did not intend:

Approaches on Unix-like systems

On Unix-like operating systems with the dynamic linker based on ld.so (on BSD) and ld-linux.so (on Linux), arbitrary libraries can be linked to a new process by giving the library's pathname in the LD PRELOAD environment variable, that can be set globally or individually for a single process. For example, on a Linux system, this command launches the command "prog" with the shared library from file "test.so" linked into it at the launchtime: Such a library can be created in the same way as other shared objects. With GCC, this involves compiling the source file containing the new globals to be linked, with the -fpic or -fPIC option, and linking with the -shared option. The library has access to external symbols declared in the program like any other library. On macOS, the following command launches the command "prog" with the shared library from file "test.dylib" linked into it at the launchtime: It is also possible to use debugger-based techniques on Unix-like systems.

Sample code

Copying a LoadLibrary-loaded DLL to a remote process

As there is no call to load a DLL into a foreign process you have to copy a locally loaded DLL into remotely allocated memory. The following commented code shows how to do that. The main issue solved here is that a locally loaded DLL copied to a remote process must occupy the same addresses as in the injecting process. The above code does this by allocating memory for the same address range as occupied before in the injecting process. If this fails the DLL is locally freed, the former address range is marked as reserved, and the call is tried again. By reserving the former address range the code prevents that the next attempt will assign the same address range as used before. The main drawback with that approach is that the DLL copied into the foreign process is that there aren't any other DLL library dependencies of that DLL loaded into the foreign address space or pointers, f.e. function calls, to DLLs loaded by the foreign process are adjusted according to the dependencies of the copied DLL. Luckily DLLs usually have preferred loading addresses which are honored by the kernel's loader. Some DLLs like are reliably loaded in the early beginning when the process address space is occupied by the executable image and its depending DLLs. These normally have reliable and non-conflicting addresses. So the copied DLL can use any calls, f.e. to load another DLL with full advantages of a locally loaded DLL, i.e. having all relative library-dependencies. The path to that DLL is copied to the foreign address space and given as a void-parameter to the thread-function. The above implementation also allows to have additional parameters, which are passed to the remotely copied DLL after the string with the DLL to remotely loaded to passed to that DLL. The following code is the source of the remotely copied loader DLL which only does calls: The last code shows an example of a DLL loaded by the loader DLL which prints the parameters to a file. One important fact is that there are no exports called from the loader DLL, but instead all initialization is done from. The only export is that of, which receives the parameters given by the injecting process through the loader DLL. And one must be aware that the thread created from a DllMain-function isn't scheduled until after its -function has succeeded. So there may not be any synchronization from inside with the created thread.

This article is derived from Wikipedia and licensed under CC BY-SA 4.0. View the original article.

Wikipedia® is a registered trademark of the Wikimedia Foundation, Inc.
Bliptext is not affiliated with or endorsed by Wikipedia or the Wikimedia Foundation.

Edit article