Inline Hooking Library for Arm64 devices across multiple platforms.
Platform Support:
- iOS (arm64/arm64e).
- Android (arm64).
- Linux (arm64).
- OSX (arm64/arm64e).
BWSR is a versatile inline hooking library implemented entirely in C
, designed to facilitate dynamic code modification and interception on Linux
, OSX
, iOS
, and Android
.
Building iOS
and MacOSX
requires a Mac machine with X-Code
and Command-Line-Tools
installed.
Building Android
requires a recent AndroidNDK downloaded and have the ANDROID_NDK
environmental set to the path of the NDK.
Building Linux
requires that build-essential
and clang
are installed.
To make the hooking library and all the example programs simply run:
make
To make only the hooking library
make hooklibs
To make the example program
make examples
This will return the address of the first occurence encountered of only the mach header matching the specific image name and the specific function name.
uintptr_t function_address = 0;
// iOS
retVal = BWSR_ResolveSymbol( "AudioUnitProcess", "AudioToolbox", &function_address );
// Android
retVal = BWSR_ResolveSymbol( "open", "/apex/com.android.runtime/lib64/bionic/libc.so", &function_address );
This will return the address of the first occurence encounted in any mach header for the matching function name. This is usually fine but if the function name is common enough you may get the address of the wrong function.
uintptr_t function_address = 0;
// iOS/Mac
retVal = BWSR_ResolveSymbol( "AudioUnitProcess", NULL, &function_address );
// Android/Linux
retVal = BWSR_ResolveSymbol( "open", NULL, &function_address );
Hooks and code page backups are handled internally, so there is no need to worry about reverting hooks or memory leaks.
The easiest and most user friendly way to hook
// Function receiving the printf calls
int hook_printf( const char* text, ... ) {
return -1;
}
// A simple hook of printf
BWSR_InlineHook( printf, hook_printf, NULL, NULL, NULL );
// Cleanup the hook
BWSR_DestroyHook( printf );
It may be benefitial to have a pointer to where the original function to use inside of the hooked function for recording or altering parameters.
// Pointer to the original creat()
void* original_creat = NULL;
// The version replacing creat()
int hcreat( const char * files, mode_t modes ) {
BWSR_DEBUG( LOG_CRITICAL, "SUCCESS! Caught creat()\n" );
if( NULL != original_creat )
return ((__typeof(creat)*)original_creat)("/some/new/location", modes);
return 0;
}
BWSR_InlineHook( creat, hcreat, &original_creat, NULL, NULL );
On iOS it may be benefitial to know the address of the page where the hook is employed before or after the hook is written out. In the snippet below, is an example of a callback triggered before and after the modification of the code page is done.
void BeforePageWriteCallbackFn( uintptr_t PageAddress ) {
BWSR_DEBUG( LOG_CRITICAL, "PageAddress: %" PRIuPTR "\n", PageAddress );
/// Do something before the write occurs.
}
void AfterPageWriteCallbackFn( uintptr_t PageAddress ) {
BWSR_DEBUG( LOG_ALERT, "PageAddress: %" PRIuPTR "\n", PageAddress );
// Do something after the write occurs...
// Update CDHashes, etc.
}
BWSR_InlineHook( printf, hook_printf, NULL, BeforePageWriteCallbackFn, AfterPageWriteCallbackFn );
It may be benefitial to undo all hooks and release all memory associated with hooks at once. This can be done at any time through one simple call.
BWSR_DestroyAllHooks();
Important
The memory tracker is only used when DEBUG_MODE
is defined. It is not used for release builds.
The memory tracker was built to ensure all memory leaks are resolved. In order for the memory tracker to successfully track allocations the calls BWSR allocation and free calls be used. The current allocations/leaked memory at any time with a simple call.
size_t leaks = 0;
leaks = MemoryTracker_CheckForMemoryLeaks();
if( leaks > 0 )
{
// Uh-oh!
}
The list of items that needs to be done is far longer than this list, but these are these are the next important goals:
- Dynamic entitlements for iOS.