Simple Loader (Hooking)
This is a Simple Loader (w/ free COFF) that demonstrates an extensible architecture for runtime tradecraft.
Project Files
NOTES
This loader demonstrates a modular user-defined architecture with tradecraft layered on top of it.
Base Layer
Our base hooking loader is defined in loader.c. This loader runs our hooking PICO, allows hook modules to run their setup, loads a DLL into memory, and calls free.c's freeAndRun() to free the memory of our loader and pass execution to the DLL capability.
hook.c is our hooking PICO. It's designed to stay memory resident with the DLL after our loader is freed. hook.c's go() updates the GetProcAddress field of our IMPORTFUNCS struct to insert itself into the API resolution process for our DLL. _GetProcAddress is a generic hook resolver. It uses the __resolve_hook() linker intrinsic to map a Function name to a hook function. __resolve_hook()'s code is dynamically generated at link-time using hooks registered in our specification files via addhook. If there is no hook function mapped, _GetProcAddress calls GetProcAddress and returns the result. hook.c doesn't define any hooks.
run "freeandrun.spec in loader.spec merges free.c into our hooking PICO. freeAndRun is exported with exportfunc "freeAndRun" "__tag_freeandrun" in freeandrun.spec. This saves us a memory allocation as our freeAndRun function now co-exists with our hooking PICO. loader.c uses PicoGetExport to find the freeAndRun function pointer and call it. The __tag_freeandrun is a linker intrinsic function (e.g., code expanded at link time) to safely get a unique integer tag for use with PicoGetExport. The exportfunc command created this linker intrinsic. This is a cool example of how to combine separate tools into one PICO and use each of them.
These components define our modular base hooking loader. There is no tradecraft here. It is just an empty shell that we can compose other tradecraft on top of.
PIC Services Module
This loader does not define dfr, fixptrs, or fixbss functions. These are Crystal Palace's base tools to make PIC ergonomic. This loader doesn't define them, because it gets these functions from somewhere else.
loader.spec runs services.spec from the Simple PIC project. The services.spec file defines dfr, fixptrs, and fixbss for us. And, it merges in the necessary code to fulfill these contracts.
In this way--the PIC services tradecraft is agnostic to our loader capability. And, because we delegate these services out, we can seamlessly swap implementations as needed.
Hooking Module Contract
This loader accepts one or more modules, specified in the %HOOKS variable, to add hooks to a capability. This architecture supports chaining hooks too (e.g., specifying multiple hooks for one Win32 function that execute in sequence).
loader.spec uses foreach to loop through the modules in %HOOKS and call labels specific to different parts of the loader's architecture:
Each module's setup label is run in the context of the PIC loader itself. This is where the module:
- merges its setup code into the PIC loader
- uses
redirect "setupHooks" "setupHooksXXX"to layer its setup logic over loader.c's setupHooks function.
Each module's hooks label is run in the context of the hooking PICO. This is where the module:
- merges its hooks implementations with the hooking PICO
- uses
attachandaddhook(together) to define hooks for the DLL.
The attach command registers a function as a hook for a Win32 API within the current PIC program. By itself, this as no effect on __resolve_hook. But, addhook "MODULE$Function" without a specified hook function will use the attach chain for MODULE$Function. By using attach to setup the specific hook and registering the attach chain with addhook, our hooking modules get the ability to layer on top of eachother.
loader.spec calls filterhooks $DLL after setting up hooks via our modules. This command walks the imports of $DLL and filters any registered hooks that aren't needed by the current capability. The filterhooks command accepts COFF object and DLLs as arguments.
The XOR Hooks module is a simple example of a hooking module. To use it with this base architecture:
./link loader.spec demo/test.x64.dll out.bin %HOOKS="modules/xorhooks/xorhooks.spec"
Stack Cutting is also a module for this base too. You can use it stand-alone or combine it with xorhooks:
./link loader.spec demo/test.x64.dll out.bin %HOOKS="modules/xorhooks/xorhooks.spec, modules/stackcutting/stackcutting.spec"
As a next step, I recommend reading the XOR Hooks notes and code.
License
This project is licensed under the BSD License.