winternl

cybersecurity & programming

Loader Lock Ownership Semantics

If your career as a programmer has led you here, fear not, there is still time to turn back.

I will not tell you to rethink whatever disreputable sequence of instructions you intend to force feed your processor. Nor do I think it would be beneficial to re-evaluate any alternative solutions.

No dear reader, I trust that you have first read the litany of terrible things you are never to do if you should find yourself in your current predicament. With that said…

Method 1: Windows Auxiliary API

You may use the AuxUlibIsDLLSynchronizationHeld function to check whether your code (read thread) owns the loader lock.

#include <aux_ulib.h>

//
// Does not distinguish between failure and lack of ownership
bool is_loader_lock_owned()
{
	static auto init = []() -> bool {
		return AuxUlibInitialize();
	}();

	if (init)
	{
		BOOL owned{ false };
		
		if (AuxUlibIsDLLSynchronizationHeld(&owned))
		{
			return owned;
		}
	}

	return false;
}

Thanks to @therealdreg of rootkit.es for providing a complete reverse engineered source code for this API.

It’s worth pointing out that the Auxiliary API functions (all three of them!) are always statically linked into your executable.

Method 2: Loader Lock Critical Section

If we check out David’s reversed source, we can see the the function will in essence do one of two things.

  1. AuxUlibIsDLLSynchronizationHeld tries to call kernelbase!RtPrivIsDllSynchronizationHeld — if it exists. This function does not seem to exist on many Windows versions.
  2. In the more likely control flow, the function will check the OwningThread field of the loader lock critical section and compare that to the current thread id.
BOOL WINAPI AuxUlibIsDLLSynchronizationHeld( PBOOL SynchronizationHeld )
{
	if ( DLLSynchAPISafe != 1 )
	{
		if ( AuxpInitState != 1 )
		{
			SetLastError( ERROR_INVALID_FUNCTION ); 

			return FALSE;
		}

		if ( AuxpUlibData.RtPrivIsDllSynchronizationHeld )
			return AuxpUlibData.RtPrivIsDllSynchronizationHeld( SynchronizationHeld );

		if ( DLLSynchAPISafe )
		{
			if ( DLLSynchAPISafe != 1 )
				goto NOT_SUPPORTED;
		}
		else
		{
			if ( AuxpUlibData.dwMajorVersion < 5 )
			{
				DLLSynchAPISafe = 2;
				goto NOT_SUPPORTED;
			}

			DllSynchronizationOwnerPtr = & NtCurrentTeb()->Peb->LoaderLock->OwningThread;
			
			InterlockedExchange( & DLLSynchAPISafe, 1 );
		}
	}

	if ( * DllSynchronizationOwnerPtr )
		* SynchronizationHeld = ( * DllSynchronizationOwnerPtr == GetCurrentThreadId() );
	else
		* SynchronizationHeld = 0;

	return TRUE;

	NOT_SUPPORTED:
		SetLastError( ERROR_NOT_SUPPORTED );

		return FALSE;
}

Which can be summarized more succinctly as:

bool AuxUlibIsDLLSynchronizationHeld_implemenation()
{
	return NtCurrentTeb()->ClientId.UniqueThread != 0
		&& NtCurrentTeb()->ClientId.UniqueThread == NtCurrentPeb()->LoaderLock->OwningThread;
}

Additional Ownership Semantics

AuxUlibIsDLLSynchronizationHeld sets the SynchronizationHeld output to false if there are no threads holding the lock. Consider the scenario where the calling code would like to check if the current thread owns the loader lock or there are no other threads owning the lock.

I’ve provided the following helper methods detailing additional ownership semantics.

//
// Returns true IIF the current thread owns the loader lock.
bool is_loader_lock_owned_this_thread()
{
	return NtCurrentPeb()->LoaderLock->OwningThread ==
		NtCurrentTeb()->ClientId.UniqueThread;
}

//
// Returns true IIF the loader lock is owned by any thread.
bool is_loader_lock_owned_any_thread()
{
	return NtCurrentPeb()->LoaderLock->OwningThread != 0;
}

//
// Returns true IIF the loader lock is not owned by any thread.
bool is_loader_lock_not_owned_any_thread()
{
	return NtCurrentPeb()->LoaderLock->OwningThread == 0;
}

//
// Returns true IIF the loader lock is not owned by this thread, but is owned by another thread.
bool is_loader_lock_not_owned_this_thread()
{
	return is_loader_lock_owned_any_thread() 
		&& !is_loader_lock_owned_this_thread();
}

Where one could express the AuxUlibIsDLLSynchronizationHeld function as:

bool AuxUlibIsDLLSynchronizationHeld_implemenation()
{
	return is_loader_lock_owned_any_thread() && is_loader_lock_owned_this_thread();
}

That’s all — I hope you will find this information useful in your no doubt questionable endeavors.