EASYHOOK_NT_EXPORT LhSetExclusiveACL( ULONG* InThreadIdList, ULONG InThreadCount, TRACED_HOOK_HANDLE InHandle) { /* Description: Sets an inclusive hook local ACL based on the given thread ID list. Parameters: - InThreadIdList An array of thread IDs. If you specific zero for an entry in this array, it will be automatically replaced with the calling thread ID. - InThreadCount The count of entries listed in the thread ID list. This value must not exceed MAX_ACE_COUNT! - InHandle The hook handle whose local ACL is going to be set. */ PLOCAL_HOOK_INFO Handle; if(!LhIsValidHandle(InHandle, &Handle)) return STATUS_INVALID_PARAMETER_3; return LhSetACL(&Handle->LocalACL, TRUE, InThreadIdList, InThreadCount); }
EASYHOOK_NT_EXPORT LhGetHookBypassAddress(TRACED_HOOK_HANDLE InHook, PVOID** OutAddress) { /* Description: Retrieves the address to bypass the hook. Using the returned value to call the original function bypasses all thread safety measures and must be used with care. This function should be called each time the address is required to ensure the hook and associated memory is still valid at the time of use. CAUTION: This must be used with extreme caution. If the hook is uninstalled and pending hooks removed, the address returned by this function will no longer point to valid memory and attempting to use the address will result in unexpected behaviour, most likely crashing the process. Parameters: - InHook The hook to retrieve the relocated entry point for. - OutAddress Upon successfully retrieving the hook details this will contain the address of the relocated function entry point. This address can be used to call the original function from outside of a hook while still bypassing the hook. Returns: STATUS_SUCCESS - OutAddress will contain the result STATUS_INVALID_PARAMETER_1 - the hook is invalid STATUS_INVALID_PARAMETER_3 - the target pointer is invalid */ NTSTATUS NtStatus; PLOCAL_HOOK_INFO Handle; if (!LhIsValidHandle(InHook, &Handle)) THROW(STATUS_INVALID_PARAMETER_1, L"The given hook handle is invalid or already disposed."); if (!IsValidPointer(OutAddress, sizeof(PVOID*))) THROW(STATUS_INVALID_PARAMETER_3, L"Invalid pointer for result storage."); *OutAddress = (PVOID*)Handle->OldProc; RETURN; THROW_OUTRO: FINALLY_OUTRO: return NtStatus; }
EASYHOOK_NT_EXPORT LhUninstallAllHooks() { /* Description: Will remove ALL hooks. To also release associated resources, you will have to call LhWaitForPendingRemovals(). */ LOCAL_HOOK_INFO* Hook; LOCAL_HOOK_INFO* List; NTSTATUS NtStatus; RtlAcquireLock(&GlobalHookLock); { // remove from global list List = GlobalHookListHead.Next; while(List != NULL) { Hook = List; List = List->Next; // remove tracking if(LhIsValidHandle(Hook->Tracking, NULL)) { Hook->Tracking->Link = NULL; } // add to removal list Hook->HookProc = NULL; Hook->Next = GlobalRemovalListHead.Next; GlobalRemovalListHead.Next = Hook; } GlobalHookListHead.Next = NULL; } RtlReleaseLock(&GlobalHookLock); RETURN(STATUS_SUCCESS); FINALLY_OUTRO: return NtStatus; }
EASYHOOK_NT_EXPORT LhIsProcessIntercepted( TRACED_HOOK_HANDLE InHook, ULONG InProcessID, BOOL* OutResult) #endif { /* Description: This method will negotiate whether a given thread passes the ACLs and would invoke the related hook handler. Refer to the source code of Is[Thread/Process]Intercepted() for more information about the implementation. */ NTSTATUS NtStatus; PLOCAL_HOOK_INFO Handle; if(!LhIsValidHandle(InHook, &Handle)) THROW(STATUS_INVALID_PARAMETER_1, L"The given hook handle is invalid or already disposed."); if(!IsValidPointer(OutResult, sizeof(BOOL))) THROW(STATUS_INVALID_PARAMETER_3, L"Invalid pointer for result storage."); #ifndef DRIVER *OutResult = IsThreadIntercepted(&Handle->LocalACL, InThreadID); #else *OutResult = IsProcessIntercepted(&Handle->LocalACL, InProcessID); #endif RETURN; THROW_OUTRO: FINALLY_OUTRO: return NtStatus; }
EASYHOOK_NT_EXPORT LhUninstallHook(TRACED_HOOK_HANDLE InHandle) { /* Description: Removes the given hook. To also release associated resources, you will have to call LhWaitForPendingRemovals(). In any case your hook handler will never be executed again, after calling this method. Parameters: - InHandle A traced hook handle. If the hook is already removed, this method will still return STATUS_SUCCESS. */ LOCAL_HOOK_INFO* Hook = NULL; LOCAL_HOOK_INFO* List; LOCAL_HOOK_INFO* Prev; NTSTATUS NtStatus; BOOLEAN IsAllocated = FALSE; if(!IsValidPointer(InHandle, sizeof(HOOK_TRACE_INFO))) return FALSE; RtlAcquireLock(&GlobalHookLock); { if((InHandle->Link != NULL) && LhIsValidHandle(InHandle, &Hook)) { InHandle->Link = NULL; if(Hook->HookProc != NULL) { Hook->HookProc = NULL; IsAllocated = TRUE; } } if(!IsAllocated) { RtlReleaseLock(&GlobalHookLock); RETURN; } // remove from global list List = GlobalHookListHead.Next; Prev = &GlobalHookListHead; while(List != NULL) { if(List == Hook) { Prev->Next = Hook->Next; break; } List = List->Next; } // add to removal list Hook->Next = GlobalRemovalListHead.Next; GlobalRemovalListHead.Next = Hook; } RtlReleaseLock(&GlobalHookLock); RETURN(STATUS_SUCCESS); //THROW_OUTRO: FINALLY_OUTRO: return NtStatus; }