📄 c-apiworks-unhooking.txt
字号:
Even though unhooking is not part of ApiWorks, it is described here.
Unhooking process can have 3 phases:
a) Deactivation
b) Unhooking
c) Unloading Hooks_DLL
Deactivation
------------
This is the 1st required step in unhooking process.
It is safe and sufficient - unhooking and unloading
aren't needed.
NewAPI routine should look like:
RESULTTYPE NewAPI(PAR1TYPE Par1, PAR2TYPE Par2, ...) {
if(IsActive()) {
// arbitrary code
}
else {
// original function is called only
return(OldApi(Par1, Par2, ...));
}
}
// Two IsActive() ways are possible:
static BOOL Active = TRUE;
// a) signal (event) checking (see WSLog example)////////////////
BOOL IsActive(VOID) {
if(Active) {
Active = CheckActive();
}
return(Active);
}
BOOL CheckActive(VOID) {
return(WaitForSingleObject(hActiveEvent, 0) != WAIT_OBJECT_0);
}
/////////////////////////////////////////////////////////////////
// b) uses ResetActive invoked via LoadAndCall(..,"ResetActive", NULL)
// (see GlobalC example)
BOOL IsActive(VOID) {
return(Active);
}
__EXPORT BOOL ResetActive(VOID) {
Active = FALSE;
}
////////////////////////////////////////////////////////////////
Unhooking
---------
means: replace new values (instructions or pointers) with the old
ones according to API_HOOK[x].UnhookAddresses. UnhookApis function
does the job. The only meaning of unhooking is preparing for dynamic
unloading Hooks_DLL (due to FreeLibrary, ..; not due to process
termination, except 9xGlobal hooks).
ApiHooks (not ApiWorks) offers you UnhookApis function:
BOOL __stdcall UnhookApis(PAPI_HOOK lpAHChain, LONG nAHooks);
This function tries to perform optimal unhooking. It can be called more times with
the same ApiHookChain. It modifies ApiHookChain's API_UNHOOK and ADDR_CONTENTS
structures (they must lie in writable memory).
Parameters:
lpAHChain - pointer to API_HOOK structure (typicaly ApiHookChain).
nAHooks - how many hooks to unhook (number of API_HOOK structures)
including HOOKS_DYNAMIC hook (it is ignored, of course)
or WHOLE_AH_CHAIN = unhook all hooks.
Returns:
TRUE if specified API_HOOKs were unhooked (~old values were returned).
FALSE if it detects overhooks.
ApiHookChain's API_UNHOOKs are modified. UnhookApis can be called later with
the same ApiHookChain to try next unhooking.
API_HOOK ApiHookChain1[4] = { {HOOKS_DYNAMIC}, {.1st.}, {.2nd.}, {.3rd.}};
API_HOOK ApiHookChain2[3] = { {.1st.}, {.2nd.}, {.3rd.}};
To unhook {.1st.} and {.2nd.} API_HOOK structures:
UnhookApis(ApiHookChain1, 3); //2+HOOKS_DYNAMIC-API_HOOK
UnhookApis(ApiHookChain2, 2);
Notes:
If HookApi was used for hooking instead of ApiHookChain, build dynamic hook chain
from HookApi parameters:
HookApi(TEXT("GDI32.DLL"), TEXT("Pie"), HOOK_BY_NAME, ALL_MODULES, &ApiUnhook, NewPie, ExcludeThem);
->
API_HOOK TempAHC[3] = {
{HOOKS_DYNAMIC},
{"GDI32.DLL", "Pie", HOOK_BY_NAME, ALL_MODULES, &ApiUnhook, NewPie},
{HOOKS_END}
};
and call UnhookApis(TempAHC, WHOLE_AH_CHAIN);
HOOK_OVERWRITE/RAW: Space for routine-to-jump-to-original-API is not freed.
Use Local/GlobalFree.
Important:
If UnhookApis returns TRUE and there are no threads in Hooks_DLL (except DllMain):
*) If all hooks are HOOK_OVERWRITE/RAW it is possible to unload Hooks_DLL.
*) If AHChain contains HOOK_BY_* it is risky to unload Hooks_DLL. Unmapping a module
with GetProcAddress hook, when hooked GPA returned some NewAPIs, is very risky.
*) If UnhookApis returns FALSE, overhooks were detected - unloading
is impossible.
Unloading
---------
It is safe to unload Hooks_DLL only if there are no threads inside
NewAPI functions (see GlobalC example). The only advantage of unhooking
and unloading is memory saving.
Summary
-------
Use Deactivation only.
9x global hooks and hooks in shared sections
--------------------------------------------
must be unhooked even if Hooks_DLL is unmapped due to process termination,
not only due to FreeLibrary.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -