Once gained access to a system there are multiple ways to achieve persistence. Using things like scheduled tasks, placing binaries into the windows startup folder or using the Run directory within the Registry are easy to use, but have the downside of being easily detected. Another method to achieve persistence (and sometimes even privilege escalation) is to use DLL Hijacking which is harder to find by an analyst or AV, since it is dependent on something else that is running on the system and has a lot more variables on where the malicious code could be located on an endpoint.
But how to find processes that are vulnerable to DLL Hijacking?
One common way to identify processes that might be vulnerable to DLL Hijacking is to use Process Monitor by Sysinternals (ProcMon) and to search for processes that are trying to read .dll files which they are not able to find.
To make this easier filters can be applied like:
- Path contains .dll
- Operation equals CreateFile
- Result equals NAME NOT FOUND
Every time a process calls a .dll it tries to locate it by searching in the current working directory. If not found there, depending on the process, it will search for that file inside all entries of the PATH variable (cmd.exe /c echo %PATH%).
In case a process tries to locate a .dll and it is not able to find it, there is a chance to provide a .dll inside the working directory of the process or within a location of the PATH variable so that the process uses the custom .dll.
Sometimes a process will find the intended .dll eventually within a later entry of the PATH variable. If it is possible to write to any directory displayed inside the PATH variable before the entry with the intended file (or the current working directory of the process) the custom .dll can be placed there and would be used by the process due to the decreasing priority of entries within the PATH variable.
But there are also .dll files that can not be hijacked. One example are the so called Known DLLs, since they will always be loaded out of the system32 directory. Some of them can be found within the Registry as shown below.
The downside of using plain DLL Hijacking is that if the process that calls the .dll needs the content to function properly, it can become stuck or error out since it is no longer calling the functions within the correct .dll. This could be enough to give away that there is something malicious going on.
One way to prevent this is to use DLL Proxying – where the custom created .dll would proxy any function calls that are not implemented inside the custom .dll to the original intended dll. This way the process wont lose its needed functions and wont become stuck or error out as easily.
More about this can be found for example here.
After identifying a possible vulnerable process – as shown in figure 1 – it is time to place a custom .dll. For testing purposes the below code can be used to create a .dll file that displays a simple error message box.
#include <windows.h>
BOOL WINAPI
DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved)
{
switch (dwReason)
{
case DLL_PROCESS_ATTACH:
MessageBox(NULL,”DLL executed”,”This could be Malware!”,MB_ICONERROR | MB_OK);
break;
}
return TRUE;
}
Another example could be to use Msfvenom to create a .dll file with a meterpreter payload. After building the .dll file it can then be stored on the target system.
Afterwards the process needs to be triggered to call on the .dll file. In this case a simple startup of the application is all that is needed.
The process starts and tries to read the CRYPTSP.dll as shown in the first image – but this time it actually loads the custom made .dll file. While this .dll is for testing purposes only, the application stops loading until the error message box gets closed. In a real world scenario the malicious process would of course just be executed in the background without notice of the end user.
Tested with Notepad++ version 8.1.9.