A
DLL proxy stands in for, or interfaces to, a
normal DLL. In security, these tend to be custom-made DLLs which
reimplement key functionality of application or system DLLs. They might
do so to enhance games (
DirectX overlay), cheat at games (
Direct3D proxy), subvert the browser (
IE
proxy), or just gain execution (
Fax Malware).
As the interaction between callee and caller, in practice, relies on
assembly-level calls; building a DLL proxy tends to be a highly
specialized task.
Some folks have generously made publicly available ones though, such as
Michael Chourdakis. These make it a lot easier to
make a DLL proxy! They don't make it much easier to actually
Man-in-the-Middle (MITM) individual calls though.
The latter requirement tends to be much more challenging. This DLL
proxy generator provides a mirror copy of exports with scaffolding to
mitm calls in, and results from, the original DLL.
Usage:
$ python dllproxy.py
usage: dllproxy.py <TargetDLL> <ProxyFileBase> [<TargetFunctions>]
$ python dllproxy.py inetcfg.dll InetProxy InetSetProxy ConfigureSystemForInternet
Source Code
dllproxy.py
DLL Wrappers
What most folks mean by DLL Proxy is actually a DLL Wrapper (as here by
floodberry).
A DLL wrapper forward all non-implemented function back to the original
DLL, while fully intercepting functions the developer cares about. By
contrast, a DLL Proxy intentionally inserts itself in all calls between
the callee and caller. For example, A DLL Proxy is capable of recording
all arguments to, and results from, the original DLL (including
modification of those results). A DLL Forwarder may call the original
DLL in some instances, but its primary purpose is to hook or interrupt
specific calls to fundamentally change the callee's flow of execution.
DLL Exports
DLL exports come in a
bewildering array of types, but essentially come down to two characterics:
1) Each export has a name and/or an ordinal (index number).
2) Each export addresses a local function or forwards to a local or remote export
Our goal is to identify each type of export, rebuild the export table,
and avoid exposing any changed numbers or names. This is easy for
non-forwarding functions; they directly reference functions our
scaffolding code generates (
trampoline-style
or Pre/Post call). Forwarded functions can be trickier though, as the
DLL exporting a forward doesn't actually receive execution from such a
call. Mimicking it correctly means ensuring the forward continues to
the original destination, but that often includes forwarding to a local
function (ie, one we're not exporting).
DLL MITM Scaffolding
The MITM scaffolding focuses on three specific instances to MITM:
1) Intercept the call before it happens to record/modify arguments
2) Intercept the call after it occurs to record/modify return values
3) Intercept both before and after to identify interesting queries and modify them
dllproxy.py exposes three functions for the end user:
DllProxyPre( FuncProxyName, .../*Function Arguments*/) // Intercept execution before Original DLL called
DllProxyPost(FuncProxyName, .../*Function Arguments*/) // Intercept execution after Original DLL called
DllProxyBoth(FuncProxyName, .../*Function Arguments*/) // Intercept execution before AND after Original DLL called
...which actually use the following #defines:
#define DllProxyGeneric(A) extern "C" __declspec(naked) void A()
#define DllProxyFunction(A,...) extern "C" cdecl void A(__VA_ARGS__)
#define DllProxyPreFunction(A,...) DllProxyFunction(intercept_pre_##A, void *ReturnPointer,__VA_ARGS__)
#define DllProxyPostFunction(A,...) DllProxyFunction(intercept_post_##A,void *ReturnValue, __VA_ARGS__)
Example
$ python dllproxy.py inetcfg.dll InetProxy InetSetProxy ConfigureSystemForInternet
$ cat InetProxy.cpp
#include "InetProxy.h"
FARPROC proxyFunctionPointers[58];
HANDLE hThis = NULL; HMODULE hThat = NULL;
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
hThis = hModule;
lpReserved = NULL;
switch(dwReason)
{
case DLL_PROCESS_ATTACH: return ProxyAttach();
case DLL_PROCESS_DETACH: return ProxyRelease();
default: break;
}
return TRUE;
}
DllProxyPre(ConfigureSystemForInternet /*, add function parameters here */)
{
printf("intercepting ConfigureSystemForInternet\n");
}
DllProxyPre(InetSetProxy /*, add function parameters here */)
{
printf("intercepting InetSetProxy\n");
}
- Kelson (kelson
@shysecurity.com)