Using Library Broker
A Practical ExampleLet's assume that you wanted to proxy (intercept,
monitor, scan) calls to the Kernels LoadLibraryA method - perhaps you want
to prevent certain libraries from being loaded or maybe you're keen to send
LoadLibraryA debug information to the event log.
There are 3 things that you are required to do to accomplish this task:
- Create a method that will act as the proxy for the original method.
This method must have, excepting the first parameter of type pDetourHeader,
the same parameter list and calling convention as the original method. In
this instance, that method is
stubLoadLibraryA.
- Register your proxy method, along with the
procedure and the library that owns that procedure with the Library
Server, a global library manager instantiated by IridiumX Assist. In this
instance, LoadLibraryA is the method and is defined in the library
Kernel32.DLL.
- When finished, even if that's when your application or library is
closing, deregister your handler. This ensures
that once your code is unloaded from the process space of the current
application, any outstanding calls to the original method will succeed.
The following unit provides a working example of proxying calls to the
LoadLibraryA function.
unit MyLoadLibraryUnit;
interface
uses
SysUtils, Windows;
// These methods would be called by your
application
// as the LoadLibrary handler is required.
procedure InstallLoadLibraryHandler;
procedure UninstallLoadLibraryHandler;
implementation
uses
AssistLibraryDetours,
AssistLibraryServer;
type
// Define the structure of the function
passed
// to our handler in the previous method field
// of the LIBBROKERHEADER
record.
TLoadLibraryA = function(
lpLibFileName: PAnsiChar): HMODULE; stdcall;
// stubLoadLibraryA
// ----------------
// stubLoadLibraryA is our proxy method handler. This is
// the function that will get called whenever another
// library uses the LoadLibraryA method.
//
// Note that the FIRST parameter declared is the detour
// header - a parameter put there on purpose by IridiumX
// Assist to help you identify more information regarding
// the method currently being called.
//
// All other parameters and the methods original calling
// convention (i.e., stdcall) MUST remain the SAME and
// be presented in the SAME order.
function stubLoadLibraryA(const
pHeader: pDetourHeader;
lpLibFileName: PAnsiChar): HMODULE; stdcall;
begin
// The detour header contains a pointer to
the
// library broker header identifying the original
// method handler. In this example we're only out
// to prove that we can intercept calls to LoadLibraryA,
// so we'll do nothing except call the original handler.
//
// pHeader^.LibBrokerHeader.lpPreviousInstance identifies
// the address of the original method. Because we know the
// calling structure of the original method we can typecast
// the function call and use it without problem.
// Call the original handler.
Result := TLoadLibraryA(
pHeader^.LibBrokerHeader.lpPreviousInstance)(lpLibFileName);
end;
procedure InstallLoadLibraryHandler;
begin
// Inform the Library Broker engine that we
have a method
// that we would like to proxy. We're proxying the Kernel32
// method "LoadLibraryA" so that instead of the original
// method being called, our proxy method "stubLoadLibraryA"
// is called instead.
LibraryBrokerRegisterProxy(kernel32,
'LoadLibraryA', @stubLoadLibraryA);
end;
procedure UninstallLoadLibraryHandler;
begin
// Once we've finished with our method
handlers, we'll
// shut them down (even though any outstanding handlers
// are shut down when IridiumX Assist shuts down the
// library server, it makes good programming sense).
LibraryBrokerUnregisterProxy(kernel32,
'LoadLibraryA', @stubLoadLibraryA);
end;
end.
|