PICing AOP
The 11.10.25 Crystal Palace release added more new commands in one go than I think I've seen thus far. Many of them seemed really similar at first blush, and it took me a while to get an understanding of where each one is applicable (I failed in that regard). The purpose of this post is to serve as a reference point for myself (and others), because I'm bound to forget if I don't write it down.
I also suggest you read Raffi's original post, as he explains the whole Aspect-Oriented Programming angle with Crystal Palace.

exportfunc
A PICO must currently contain a go function, aka an entry point, to be called by a loader using PicoEntryPoint. Here's a simple example:
DECLSPEC_IMPORT int WINAPI USER32$MessageBoxA ( HWND, LPCSTR, LPCSTR, UINT );
void go ( )
{
USER32$MessageBoxA ( NULL, "Hello World", "PICO", MB_OK );
}pico.c
IMPORTFUNCS funcs;
funcs.GetProcAddress = GetProcAddress;
funcs.LoadLibraryA = LoadLibraryA;
char * pico_src = GETRESOURCE ( _PICO_ );
char * pico_data = KERNEL32$VirtualAlloc ( NULL, PicoDataSize ( pico_src ), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
char * pico_code = KERNEL32$VirtualAlloc ( NULL, PicoCodeSize ( pico_src ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
PicoLoad ( &funcs, pico_src, pico_code, pico_data );
PicoEntryPoint ( pico_src, pico_code ) ( NULL );loader.c

Nothing new there. But the new exportfunc command provides a way for a loader to call functions in a PICO other than go (think of it like exporting a function from a DLL). This is paired with a new PicoGetExport function in tcg.h and a 'tag' system.
The following PICO has a function called test_func, which is exported using the tag __tag_testfunc:
void test_func ( )
{
USER32$MessageBoxA ( NULL, "Test Func", "PICO", MB_OK );
}pico.c
x64:
load "bin/loader.x64.o"
make pic +gofirst +optimize
load "bin/pico.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
exportfunc "test_func" "__tag_testfunc" # export test_func
export
link "pico"
export
loader.spec
We then declare a corresponding tag intrinsic in the loader, and pass it to PicoGetExport:
/* linker intrinsic */
int __tag_testfunc ( );
void go ( )
{
IMPORTFUNCS funcs;
funcs.GetProcAddress = GetProcAddress;
funcs.LoadLibraryA = LoadLibraryA;
char * pico_src = GETRESOURCE ( _PICO_ );
char * pico_data = KERNEL32$VirtualAlloc ( NULL, PicoDataSize ( pico_src ), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE );
char * pico_code = KERNEL32$VirtualAlloc ( NULL, PicoCodeSize ( pico_src ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE );
PicoLoad ( &funcs, pico_src, pico_code, pico_data );
/* call test_func */
PicoGetExport ( pico_src, pico_code, __tag_testfunc ( ) ) ( NULL );
}loader.c
Crystal Palace will replace the intrinsic with whatever tag ID it generated.

run command. It will be fixed in a future release.This is useful when a PICO has multiple setup steps, as they can be separated into different functions (and called at different times), rather than shoehorning them all into go. And given that exportfunc now exists, I suspect the mandatory requirement to have a go function in a PICO could be lifted in the future.
addhook
The old way to hook API calls was to manually check functions being resolved in GetProcAddress (by hijacking IMPORTFUNCS), and then returning pointers to internal functions rather than the legitimate ones. For example:
DECLSPEC_IMPORT int WINAPI USER32$MessageBoxA ( HWND, LPCSTR, LPCSTR, UINT );
int WINAPI _MessageBoxA ( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType )
{
return USER32$MessageBoxA ( hWnd, "You've been hooked", "Hooked", uType );
}
char * WINAPI _GetProcAddress ( HMODULE hModule, LPCSTR lpProcName )
{
char * result = ( char * ) GetProcAddress ( hModule, lpProcName );
/*
* Check to see what function is being resolved.
* Note that lpProcName may be an ordinal, not a string.
*/
if ( ( ULONG_PTR ) lpProcName >> 16 == 0 ) {
/* it's an ordinal */
return result;
}
/* Calculte function hash */
DWORD h = hash ( ( char * ) lpProcName );
if ( h == MESSAGEBOXA_HASH ) {
return ( char * ) _MessageBoxA;
} else if ( ... ) {
...
} else {
return result;
}
}
void go ( IMPORTFUNCS * funcs )
{
/* make the loader use our custom GetProcAddress */
funcs->GetProcAddress = ( __typeof__ ( GetProcAddress ) * ) _GetProcAddress;
}As you may imagine, the more hooks you want to add, the more cumbersome this gets. The new addhook command allows us to do this in a more automated fashion. It registers a hook for a DFR function with Crystal Palace, which is implemented via a __resolve_hook ( DWORD func_hash ) intrinsic. That massive _GetProcAddress function can now be boiled down to:
FARPROC WINAPI _GetProcAddress ( HMODULE hModule, LPCSTR lpProcName )
{
FARPROC result = __resolve_hook ( ror13hash ( lpProcName ) );
if ( result != NULL ) {
return result;
}
return GetProcAddress ( hModule, lpProcName );
}pico.c
And the hooks are now defined in the spec file:
load "bin/pico.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
addhook "USER32$MessageBoxA" "_MessageBoxA" # hook MessageBoxA
...loader.spec
Crystal Palace will insert the necessary hash comparisons in the emitted assembly, which look something like this:
call ror13hash
mov %eax,%ecx
cmp $0xBC4D`A2A8,%ecx ; 0xBC4DA2A8 is the ROR13 hash for MessageBoxA
lea _MessageBoxA,%rax
filterhooks
The filterhooks command is provided as a means to exclude any hooks that are not required for the capability being loaded. For instance, if we specify a bunch of hooks like OpenProcess, VirtualAlloc, WriteProcessMemory, etc, but the loaded DLL doesn't have them in its IAT, then it's unlikely that these hooks will be applicable and the final assembly will be larger than needed.
filterhooks walks the imports of the object on the stack (DLL or PICO) and removes any hooks that are not in their respective import tables.
push $DLL
link "dll"
load "bin/hooks.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
addhook "USER32$MessageBoxA" "_MessageBoxA"
addhook "KERNEL32$OpenProcess" "_OpenProcess"
addhook "KERNEL32$VirtualAlloc" "_VirtualAlloc"
filterhooks $DLL # remove any unneeded hooks
export
link "pico"If +optimize is used and a hook function (e.g. _OpenProcess) hasn't any other references, then they will be removed from the final PICO. I initially wondered why filterhooks isn't done implicitly, but then I realised that you may not want to remove hooks in case modules and functions are loaded and resolved at runtime (e.g. BOF loads).
attach
Where addhook is intended to be used with a loaded capability, such as a DLL, the attach command provides a way to hook DFR function calls that our own PICO makes. In the following example, mask_memory calls KERNEL32$VirtualProtect to modify the memory permissions of the DLL before and after masking.
void mask_memory ( BOOL mask )
{
DWORD old_protect;
if ( mask )
{
/* made everything writeable */
KERNEL32$VirtualProtect ( g_dllBase, g_dllLen, PAGE_EXECUTE_READWRITE, &old_protect );
}
/* xor memory */
for ( DWORD i = 0; i < g_dllLen; i++ ) {
g_dllBase [ i ] ^= xorkey [ i % 128 ];
}
if ( ! mask )
{
/* restore old permissions */
KERNEL32$VirtualProtect ( g_dllBase, g_dllLen, old_protect, &old_protect );
}
}
int WINAPI _MessageBoxA ( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType )
{
/* mask DLL's memory */
mask_memory ( TRUE );
/* make the API call */
int result = USER32$MessageBoxA ( hWnd, "You've been hooked", "Hooked", uType );
/* unmask DLL's memory */
mask_memory ( FALSE );
/* return the result */
return result;
}If we want those VirtualProtect calls to go through another function (e.g. one that implements some sort of evasion for the API call), rather than calling the API directly, then we can do that with the attach command. Like addhook, we provide the target DFR function and the name of the hook function.
load "bin/pico.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
attach "KERNEL32$VirtualProtect" "_VirtualProtect"
...Crystal Palace is smart enough not to hook the same API again inside the hook function. So in this example, we could call the original DFR, and CP won't throw us into an endless loop, which is always nice.
BOOL WINAPI _VirtualProtect ( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
dprintf ( "_VirtualProtect\n" );
/* it's just a demo, call the original */
return KERNEL32$VirtualProtect ( lpAddress, dwSize, flNewProtect, lpflOldProtect );
}pico.c
You can stack these hooks though, which means you can hook DFR references inside hook functions and send them to yet another function. Here's a contrived example:
load "bin/pico.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
attach "KERNEL32$VirtualProtect" "_VirtualProtect" # hook VirtualProtect
attach "KERNEL32$VirtualProtect" "_VirtualProtect2" # stack a 2nd hook
...BOOL WINAPI _VirtualProtect ( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
dprintf ( "_VirtualProtect\n" );
/* this will call _VirtualProtect2 */
return KERNEL32$VirtualProtect ( lpAddress, dwSize, flNewProtect, lpflOldProtect );
}
BOOL WINAPI _VirtualProtect2 ( LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect )
{
dprintf ( "_VirtualProtect2\n" );
/* it's just a demo, call the original */
return KERNEL32$VirtualProtect ( lpAddress, dwSize, flNewProtect, lpflOldProtect );
}pico.c
redirect
The redirect command is very similar to the attach command, but it targets local functions, rather than DFR references. Let's say we had two functions that we might want to use for memory masking - mask_memory and mask_memory_alt that we want to choose from at link-time:
void mask_memory ( BOOL mask )
{
DWORD old_protect;
if ( mask )
{
/* made everything writeable */
KERNEL32$VirtualProtect ( g_dllBase, g_dllLen, PAGE_EXECUTE_READWRITE, &old_protect );
}
/* xor memory */
for ( DWORD i = 0; i < g_dllLen; i++ ) {
g_dllBase [ i ] ^= xorkey [ i % 128 ];
}
if ( ! mask )
{
/* restore old permissions */
KERNEL32$VirtualProtect ( g_dllBase, g_dllLen, old_protect, &old_protect );
}
}
void mask_memory_alt ( BOOL mask )
{
/* assume memory is RWX so no need to VP */
for ( DWORD i = 0; i < g_dllLen; i++ ) {
g_dllBase [ i ] ^= xorkey [ i % 128 ];
}
}
int WINAPI _MessageBoxA ( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType )
{
/* mask DLL's memory */
mask_memory ( TRUE );
/* make the API call */
int result = USER32$MessageBoxA ( hWnd, "You've been hooked", "Hooked", uType );
/* unmask DLL's memory */
mask_memory ( FALSE );
/* return the result */
return result;
}pico.c
Instead of manually updating all the code references from mask_memory to mask_memory_alt, we can simply redirect the calls in the spec file.
load "bin/pico.x64.o"
make object +gofirst +optimize
mergelib "libtcg.x64.zip"
redirect "mask_memory" "mask_memory_alt"
...loader.spec
Crystal Palace will rewrite any call to mask_memory with a call to mask_memory_alt. And as before, if no other references to mask_memory remain, it will be optimised out of the final PICO (assuming +optimize is being used).
There may be instances where you don't want functions to be hooked, which is where the new protect, preserve and optout commands come in.
protect
The protect command prevents the listed functions from all attach and redirect hooks from being applied to them. The syntax is simply protect "func1, func2, ...". You would use this if there are functions that cannot tolerate having any hooks (or you just don't want them there).
preserve
The preserve command provides more granular control in that you can exclude specific hooks from specific functions whilst leaving others intact. In the example above, I did attach "KERNEL32$VirtualProtect" "_VirtualProtect" to hook all calls to VirtualProtect and redirect them to _VirtualProtect. However, let's say I wanted to exclude this specific hook from the mask_memory function, in which case I could do preserve "KERNEL32$VirtualProtect" "mask_memory". This will prevent the VirtualProtect references in this function from being hooked, so they will call the original API directly.
optout
The optout command feels a bit niche, but the intention is to prevent tradecraft setup from calling its own hooks. The syntax is optout "function" "hook1, hook2, ...". I couldn't really imagine a concrete scenario where this would be needed, and none of the Tradecraft Garden samples use it either. I guess it would be applicable in more complex loading scenarios - perhaps when tradecraft is merged with a loader that's responsible for loading that tradecraft in the first place. Because in those cases, a loader cannot call a hook for which the corresponding tradecraft isn't yet loaded. I suspect most people won't need to worry about this one, but it's there.
Conclusion
That about covers my woolly explanations of the latest Crystal Palace commands - exportfunc, addhook, attach, redirect, filterhooks, protect, preserve, and optout. When I started looking at the new TCG samples, it took a lot of back-and-forth between the source code and spec files for me to understand how everything was tying together. Between merging tradecraft setup with loaders, adding hooks and redirects, etc, it can definitely be challenging to picture the end result in your head (at least with my limited capacity).
I hope this post serves to demystify the role that these commands have.
