A proof of concept demonstrating the DLL-load proxying using undocumented Syscalls. This repo is not about teaching you what DLL Load proxying is and how it works, it is greatly explained on this blogpost. Instead, the main focus is on finding undocumented callback functions by reversing the DLLs and creating your own version.
Before getting in directly to reversing the DLLs, we need to first know what to look for. We can start by looking at the Microsoft documentation (MSDN), which provides an excellent example of a custom thread pool, which creates a work item and a thread pool timer. The code alone is also suitable for archiving the execution of LoadLibrary
via callback functions, but as already known, the userland functions are prone to hooking. So using their respective syscalls would be a better approach. Looking at the MSDN documentation, the example code uses the following Win32API functions:
CreateThreadpool
SetThreadpoolThreadMaximum
SetThreadpoolThreadMinimum
CreateThreadpoolCleanupGroup
CreateThreadpoolTimer
SetThreadpoolTimer
CloseThreadpoolCleanupGroupMembers
If you use IDA, open kernel32.dll, go to "Exports" and search for the mentioned Win32 APIs, in this case CreateThreadpool
. Double-clicking the function redirect us to its dissassembled code:
Through the assembly instructions, we see the TpAllocPool
syscall being executed: call cs:__imp_TpAllocPool
If you repeat the process with the other functions, you will end up with the following syscalls:
Ntdll!TpAllocPool
Ntdll!TpSetPoolMaxThreads
Ntdll!TpSetPoolMinThreads
Ntdll!TpAllocCleanupGroup
Ntdll!TpAllocTimer
Ntdll!TpSetTimer
Ntdll!TpReleaseCleanupGroupMembers
Now you have everything you need to start creating your own version of proxying the DLL Loads. You can look at this documentation from Process Hacker to help you implement the undocumented syscalls in your code.
Set a breakpoint before the assembly code in Callbackstub get's executed. Look at right tab of x64dbg as the registers are being populated.
demo_dbg.mp4
RAX -> pointer to LoadLibraryA
RCX -> library name string
https://0xdarkvortex.dev/proxying-dll-loads-for-hiding-etwti-stack-tracing/
https://github.com/hlldz/misc/tree/main/proxy_calls
https://processhacker.sourceforge.io/doc/nttp_8h.html#adad18de6710381f08cf36a0fa72e7529