コード例 #1
0
ファイル: barrier.c プロジェクト: marchon/pokerbridge
BOOL TlsAddCurrentThread(THREAD_LOCAL_STORAGE* InTls)
{
/*
Description:

    Tries to reserve a THREAD_RUNTIME_INFO entry for the calling thread.
    On success it may call TlsGetCurrentValue() to query a pointer to
    its private entry.

    This is a replacement for the Windows Thread Local Storage which seems
    to cause trouble when using it in Explorer.EXE for example.

    No parameter validation (for performance reasons).

    This method will raise an assertion if the thread was already added
    to the storage!

Parameters:
    - InTls

        The thread local storage to allocate from.

Returns:

    TRUE on success, FALSE otherwise.
*/
#ifndef DRIVER
	ULONG		CurrentId = (ULONG)GetCurrentThreadId();
#else
	ULONG		CurrentId = (ULONG)PsGetCurrentThreadId();
#endif
	LONG		Index = -1;
    LONG		i;

    RtlAcquireLock(&InTls->ThreadSafe);

    // select Index AND check whether thread is already registered.
	for(i = 0; i < MAX_THREAD_COUNT; i++)
	{
		if((InTls->IdList[i] == 0) && (Index == -1))
			Index = i;
		
		ASSERT(InTls->IdList[i] != CurrentId);
	}

	if(Index == -1)
	{
		RtlReleaseLock(&InTls->ThreadSafe);

		return FALSE;
	}

	InTls->IdList[Index] = CurrentId;
	RtlZeroMemory(&InTls->Entries[Index], sizeof(THREAD_RUNTIME_INFO));
	
	RtlReleaseLock(&InTls->ThreadSafe);

	return TRUE;
}
コード例 #2
0
ファイル: barrier.c プロジェクト: marchon/pokerbridge
void TlsRemoveCurrentThread(THREAD_LOCAL_STORAGE* InTls)
{
/*
Description:

    Removes the caller from the local storage. If the caller
    is already removed, the method will do nothing.

Parameters:

    - InTls

        The storage from which the caller should be removed.
*/
#ifndef DRIVER
	ULONG		    CurrentId = (ULONG)GetCurrentThreadId();
#else
	ULONG		    CurrentId = (ULONG)PsGetCurrentThreadId();
#endif
    ULONG           Index;

    RtlAcquireLock(&InTls->ThreadSafe);

	for(Index = 0; Index < MAX_THREAD_COUNT; Index++)
	{
		if(InTls->IdList[Index] == CurrentId)
		{
			InTls->IdList[Index] = 0;

			RtlZeroMemory(&InTls->Entries[Index], sizeof(THREAD_RUNTIME_INFO));
		}
	}

	RtlReleaseLock(&InTls->ThreadSafe);
}
コード例 #3
0
ファイル: uninstall.c プロジェクト: EasyHook/EasyHook
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;
}
コード例 #4
0
ファイル: caller.c プロジェクト: Garfield-Chen/hf-2011
EASYHOOK_NT_INTERNAL LhUpdateModuleInformation()
{
	NTSTATUS						NtStatus;
	PSYSTEM_MODULE_INFORMATION		NativeList = NULL;
	ULONG							RequiredSize = 0;
	ULONG							i;
	PSYSTEM_MODULE					Mod;
	MODULE_INFORMATION*				List = NULL;

	if(!LhModuleListChanged)
		return STATUS_SUCCESS;

	LhModuleListChanged = FALSE;

	if(ZwQuerySystemInformation(11, NULL, 0, &RequiredSize) != STATUS_INFO_LENGTH_MISMATCH)
		THROW(STATUS_INTERNAL_ERROR, L"Unable to enumerate system modules.");

	if((NativeList = RtlAllocateMemory(TRUE, RequiredSize)) == NULL)
		THROW(STATUS_NO_MEMORY, L"Unable to allocate memory.");

	if(!RTL_SUCCESS(ZwQuerySystemInformation(11, NativeList, RequiredSize, &RequiredSize)))
		THROW(STATUS_INTERNAL_ERROR, L"Unable to enumerate system modules.");

	if((List = RtlAllocateMemory(FALSE, sizeof(MODULE_INFORMATION) * NativeList->Count)) == NULL)
		THROW(STATUS_NO_MEMORY, L"Unable to allocate memory.");

	for(i = 0; i < NativeList->Count; i++)
	{
		Mod = &NativeList->Modules[i];

		List[i].BaseAddress = Mod->ImageBaseAddress;
		List[i].ImageSize = Mod->ImageSize;
		List[i].ModuleName = Mod->Name + Mod->NameOffset;
		
		memcpy(List[i].Path, Mod->Name, 256);

		if(i + 1 < NativeList->Count)
			List[i].Next = &List[i + 1];
		else
			List[i].Next = NULL;
	}

	RtlAcquireLock(&GlobalHookLock);
	{
		if(LhNativeModuleArray != NULL)
			RtlFreeMemory(LhNativeModuleArray);

		if(LhModuleArray != NULL)
			RtlFreeMemory(LhModuleArray);

		LhNativeModuleArray = NativeList;
		LhModuleArray = List;
		LhModuleCount = NativeList->Count;
	}
	RtlReleaseLock(&GlobalHookLock);

    RETURN;

THROW_OUTRO:
	{
		if(NativeList != NULL)
			RtlFreeMemory(NativeList);

		if(List != NULL)
			RtlFreeMemory(List);
	}
FINALLY_OUTRO:
    return NtStatus;
}
コード例 #5
0
ファイル: caller.c プロジェクト: Garfield-Chen/hf-2011
EASYHOOK_NT_EXPORT LhBarrierPointerToModule(
              PVOID InPointer,
              MODULE_INFORMATION* OutModule)
{
/*
Description:

    Translates the given pointer (likely a method) to its
    owning module if possible.

Parameters:

    - InPointer

        A method pointer to be translated.

    - OutModule

        Receives the owner of a given method.
        
Returns:

    STATUS_NOT_FOUND
            
        No matching module could be found.
*/
    UCHAR*					Pointer = (UCHAR*)InPointer;
    NTSTATUS				NtStatus;
    BOOL					CanTryAgain = TRUE;
	MODULE_INFORMATION*		List;

	if(!IsValidPointer(OutModule, sizeof(MODULE_INFORMATION)))
		THROW(STATUS_INVALID_PARAMETER_2, L"The given module storage is invalid.");

LABEL_TRY_AGAIN:

	RtlAcquireLock(&GlobalHookLock);
	{
		List = LhModuleArray;

		// walk through process modules
		while(List != NULL)
		{
			if((Pointer >= List->BaseAddress) && (Pointer <= List->BaseAddress + List->ImageSize))
			{
				*OutModule = *List;

				RtlReleaseLock(&GlobalHookLock);

				RETURN;
			}

			List = List->Next;
		}
	}
	RtlReleaseLock(&GlobalHookLock);

    if((InPointer == NULL) || (InPointer == (PVOID)~0))
    {
        // this pointer does not belong to any module...
    }
    else
    {
        // unable to find calling module...
        FORCE(LhUpdateModuleInformation());

        if(CanTryAgain)
        {
            CanTryAgain = FALSE;

            goto LABEL_TRY_AGAIN;
        }
    }

    THROW(STATUS_NOT_FOUND, L"Unable to determine module.");

THROW_OUTRO:
FINALLY_OUTRO:
    return NtStatus;
}
コード例 #6
0
ファイル: caller.c プロジェクト: Garfield-Chen/hf-2011
EASYHOOK_NT_EXPORT LhEnumModules(
			HMODULE* OutModuleArray, 
            ULONG InMaxModuleCount,
            ULONG* OutModuleCount)
{
/*
Description:

	For performance reasons, only the module base addresses are returned.
	You may then loop through the array and use LhBarrierPointerToModule()
	to query each module information.

Parameters:
	
	- OutModuleArray

		An array receiveing module pointers. Set to NULL to only query "OutModuleCount".

	- InMaxModuleCount

		The maximum count of modules that the given buffer can hold.

	- OutModuleCount

		The actual count of modules loaded into the current process or into the kernel,
		depending on the caller's context. This pointer must be specified if no
		module buffer is passed; if one is passed, this parameter is optional.
*/
	ULONG					ModIndex = 0;
	NTSTATUS				NtStatus;
	MODULE_INFORMATION*		List;

	if(IsValidPointer(OutModuleArray, InMaxModuleCount * sizeof(PVOID)))
	{
		// loop through the module list...
		RtlAcquireLock(&GlobalHookLock);
		{
			if(IsValidPointer(OutModuleCount, sizeof(ULONG)))
				*OutModuleCount = LhModuleCount;

			List = LhModuleArray;

			// walk through process modules
			while(List != NULL)
			{
				if(ModIndex > InMaxModuleCount)
				{
					RtlReleaseLock(&GlobalHookLock);

					THROW(STATUS_BUFFER_TOO_SMALL, L"The given buffer was filled but could not hold all modules.");
				}

				OutModuleArray[ModIndex++] = (HMODULE)List->BaseAddress;

				List = List->Next;
			}	
		}	
		RtlReleaseLock(&GlobalHookLock);
	}
	else
	{
		// return module count...
		if(!IsValidPointer(OutModuleCount, sizeof(ULONG)))
			THROW(STATUS_INVALID_PARAMETER_3, L"If no buffer is specified you need to pass a module count storage.");

		*OutModuleCount = LhModuleCount;
	}

	RETURN;

THROW_OUTRO:
FINALLY_OUTRO:
    return NtStatus;
}
コード例 #7
0
ファイル: caller.c プロジェクト: Garfield-Chen/hf-2011
EASYHOOK_NT_INTERNAL LhUpdateModuleInformation()
{
	
/*
Description:

    Is supposed to be called interlocked... "ProcessModules" is 
    outsourced to prevent "__chkstk".
    Will just enumerate current process modules and extract
    required information for each of them.
*/
    LONG					NtStatus = STATUS_UNHANDLED_EXCEPTION;
    ULONG					Index;
    ULONG					ModIndex;
    MODULEINFO*				NativeList = NULL;
    ULONG					ModuleCount;
	MODULEINFO*				Mod = NULL;
	MODULE_INFORMATION*		List = NULL;
	CHAR*					PathList = NULL;
	CHAR*					ModPath = NULL;
	ULONG					ModPathSize = 0;
	LONG					iChar = 0;

    // enumerate modules...
	RtlAcquireLock(&GlobalHookLock);
	{
		if(!EnumProcessModules(
				GetCurrentProcess(),
				ProcessModules,
				sizeof(ProcessModules),
				&ModuleCount))
		{
			RtlReleaseLock(&GlobalHookLock);

			THROW(STATUS_INTERNAL_ERROR, L"Unable to enumerate current process modules.");
		}
	}
	RtlReleaseLock(&GlobalHookLock);

    ModuleCount /= sizeof(HMODULE);

    // retrieve module information
    if((NativeList = (MODULEINFO*)RtlAllocateMemory(FALSE, ModuleCount * sizeof(NativeList[0]))) == NULL)
        THROW(STATUS_NO_MEMORY, L"Unable to allocate memory for module information.");

	if((List = (MODULE_INFORMATION*)RtlAllocateMemory(TRUE, sizeof(MODULE_INFORMATION) * ModuleCount)) == NULL)
		THROW(STATUS_NO_MEMORY, L"Unable to allocate memory.");

	if((PathList = (CHAR*)RtlAllocateMemory(TRUE, MAX_PATH * ModuleCount)) == NULL)
		THROW(STATUS_NO_MEMORY, L"Unable to allocate memory.");

    for(Index = 0, ModIndex = 0; Index < ModuleCount; Index++)
    {
		// collect information
        if(!GetModuleInformation(
                GetCurrentProcess(),
                ProcessModules[Index],
                &NativeList[ModIndex],
                sizeof(NativeList[ModIndex])))
            continue;

		GetModuleFileNameA(
				ProcessModules[Index],
				&PathList[ModIndex * MAX_PATH],
				MAX_PATH);

		if(GetLastError() != ERROR_SUCCESS)
			continue;

        Mod = &NativeList[ModIndex];

		// normalize module information
		List[ModIndex].BaseAddress = (UCHAR*)Mod->lpBaseOfDll;
		List[ModIndex].ImageSize = Mod->SizeOfImage;

		memcpy(List[ModIndex].Path, &PathList[ModIndex * MAX_PATH], MAX_PATH + 1);

		ModPath = List[ModIndex].Path;
		ModPathSize = RtlAnsiLength(ModPath);

		for(iChar = ModPathSize; iChar >= 0; iChar--)
		{
			if(ModPath[iChar] == '\\')
			{
				List[ModIndex].ModuleName = &ModPath[iChar + 1];

				break;
			}
		}

		if(ModIndex + 1 < ModuleCount)
			List[ModIndex].Next = &List[ModIndex + 1];
		else
			List[ModIndex].Next = NULL;

        ModIndex++;
    }

    // save changes...
	RtlAcquireLock(&GlobalHookLock);
	{
		if(LhNativeModuleArray != NULL)
			RtlFreeMemory(LhNativeModuleArray);

		if(LhModuleArray != NULL)
			RtlFreeMemory(LhModuleArray);

		if(LhNativePathArray != NULL)
			RtlFreeMemory(LhNativePathArray);

		LhNativePathArray = PathList;
		LhNativeModuleArray = NativeList;
		LhModuleArray = List;
		LhModuleCount = ModIndex;
	}
	RtlReleaseLock(&GlobalHookLock);

    RETURN;

THROW_OUTRO:
	{
		if(NativeList != NULL)
			RtlFreeMemory(NativeList);

		if(List != NULL)
			RtlFreeMemory(List);
	}
FINALLY_OUTRO:
    return NtStatus;
}
コード例 #8
0
ファイル: uninstall.c プロジェクト: EasyHook/EasyHook
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;
}
コード例 #9
0
ファイル: uninstall.c プロジェクト: EasyHook/EasyHook
EASYHOOK_NT_EXPORT LhWaitForPendingRemovals()
{
/*
Descriptions:

    For stability reasons, all resources associated with a hook
    have to be released if no thread is currently executing the
    handler. Separating this wait loop from the uninstallation
    method is a great performance gain, because you can release
    all hooks first, and then wait for all removals simultaneously.

*/
    PLOCAL_HOOK_INFO        Hook;
    NTSTATUS                NtStatus = STATUS_SUCCESS;
    INT32                  Timeout = 1000;
#ifdef X64_DRIVER
    KIRQL                  CurrentIRQL = PASSIVE_LEVEL;
#endif

#pragma warning(disable: 4127)
    while(TRUE)
#pragma warning(default: 4127)
    {
        // pop from removal list
        RtlAcquireLock(&GlobalHookLock);
        {
            Hook = GlobalRemovalListHead.Next;
            
            if(Hook == NULL)
            {
                RtlReleaseLock(&GlobalHookLock);

                break;
            }

            GlobalRemovalListHead.Next = Hook->Next;
        }
        RtlReleaseLock(&GlobalHookLock);

        // restore entry point...
        if(Hook->HookCopy == *((ULONGLONG*)Hook->TargetProc))
        {
#ifdef X64_DRIVER
            CurrentIRQL = KeGetCurrentIrql();
            RtlWPOff();
#endif
            *((ULONGLONG*)Hook->TargetProc) = Hook->TargetBackup;
#ifdef X64_DRIVER
            // we support a trampoline jump of up to 16 bytes in X64_DRIVER
            *((ULONGLONG*)(Hook->TargetProc + 8)) = Hook->TargetBackup_x64;
            RtlWPOn(CurrentIRQL);
#endif

#pragma warning(disable: 4127)
            while (TRUE)
#pragma warning(default: 4127)
            {
                if (*Hook->IsExecutedPtr <= 0)
                {
                    // release slot
                    if (GlobalSlotList[Hook->HLSIndex] == Hook->HLSIdent)
                    {
                        GlobalSlotList[Hook->HLSIndex] = 0;
                    }

                    // release memory...
                    LhFreeMemory(&Hook);
                    break;
                }

                if (Timeout <= 0)
                {
                    // this hook was not released within timeout or cannot be released.
                    // We will leak the memory, but not hang forever.
                    NtStatus = STATUS_TIMEOUT;
                    break;
                }

                RtlSleep(25);
                Timeout -= 25;
            }
        }
        else
        {
            // hook was changed... no chance to release resources
        }
    }

    return NtStatus;
}