DLL or Dynamic Link Library is a file format that contains multiple codes and procedures for windows application so that multiple programs can use the information at the same time. The advantage of such an arrangement is that it can save memory. Also, a user can change the code of multiple applications at once without changing each and every application.
DLL injection is a process of running a custom code within the memory of another DLL. Since it involves running custom codes, it is usually exploited by external programs to make the targeted application behave in an abnormal way. For instance, DLL injection can be used to inject malicious code which can hook on to the system function calls or read passwords.
Approaches on various OS
There are many ways to inject a malicious DLL in Windows:
- DLLs in the registry entry HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs are loaded into every process that loads User32.dll during the initial call of that DLL. In Windows Vista, AppInit_DLLs are disabled by default. In Windows 7, the AppInit_DLL infrastructure supports signing code. In Windows 8, the entire AppInit_DLL functionality is disabled when Secure Boot is enabled
- DLLs listed under the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\AppCertDLLs are loaded into every process that calls the Win32 API functions CreateProcess, CreateProcessAsUser etc
- Process manipulation functions like CreateRemoteThread or code injection methods such as AtomBombing can be used to inject a DLL into a program after it has started.
- Open a handle to the target process. This can be achieved by spawning the process or by keying off something created by that process that is known to exist
- Allocate some memory in the target process, and the name of the DLL to be injected is written to it.
- Create a new thread in the target process with the thread's start address set to be the address of LoadLibrary and the argument set to the address of the string just uploaded into the target.
- The operating system then calls the initialization routine of the injected DLL.
Note that without precautions, this approach can be detected by the target process due to the DLL_THREAD_ATTACH notifications sent to every loaded module as a thread starts.
- Use of the SuspendThread or NtSuspendThread function to suspend all threads, and then SetThreadContext or NtSetContextThread function can be used to modify an existing thread's context in the application to execute injected code, which in turn could load a DLL.
- Exploitation of the design limitations in Windows and applications that call the LoadLibrary or LoadLibraryEx function without specifying a full qualified path to the DLL being loaded.
- Substituting an application-specific DLL with a rogue replacement that implements the same function exports as the original.
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.
For example, in bash, this command launches the command "prog" with the shared library from file "test.so" linked into it at the launch time:
Such libraries can be created with GCC by 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 OS X, the following command launches the command "prog" with the shared library from file "test.dylib" linked into it at the launch time:
DYLD_INSERT_LIBRARIES=”/test.dylib” DYLD_FORCE_FLAT_NAMESPACE=1 prog
It is also possible to use debugger-based techniques on Unix-like systems.
POC on Windows System
To carry out this attack, a dll injector is required. The below method is used to hook the malicious injector into the process of the target application and increase its memory allocation to execute the malicious DLL
Steps to Reproduce:
- Access the Windows application and check its PID from “Task Manager”
- Open command prompt and navigate to the path to the DLL injector
- Run the command dllInjector-x86.exe -c -p <PID of the application> -l <dll to be injected>
- The injected DLL is executed in the form of a popup
Fig 1: Malicious DLL is injected into PID of target
Fig 2: Reflective DLL is injected
To prevent DLL injection need to ensure no untrusted process gets Administrator access or runs as the same user account as your application. Without this access, code injection into the application is not possible; and once such a process gets that access, it can cause all kinds of unauthorized activities without needing to inject itself into another process – the injection just makes it easier to hide.
Authored By - Pramita Das
TCS Cyber Security Practice