![]() As the master thread loads imports, the work queue is filled up with secondary library dependencies for worker threads to process. Once the thread pool has been initialized, the master thread continues on with ntdll!LdrpMapAndSnapDependency which will map the first level of explicit imports with a call to ntdll!LdrpLoadDependentModule. Work is added and removed from the queue in a last-in first-out (LIFO) manner. If the worker finds a new dependency, it will queue up more work. įigure 5: Partially documented LDRP_LOAD_CONTEXT structureĪt this point, worker threads in the thread pool will pull work off the queue and perform the appropriate action (mapping or snapping). ![]() This structure is allocated by ntdll!LdrpAllocatePlaceHolder and contains a variety of information such as the DLL name, a _LDR_DATA_TABLE_ENTRY structure, a pointer to the import address table (IAT), the activation context, and the control flow guard (CFG) function pointer. The work queue is defined by ntdll!LdrpWorkQueue which is a doubly linked list (LIST_ENTRY) of an opaque structure, LDRP_LOAD_CONTEXT. Snapping is the process of resolving the library’s import address table.Īt the end of every mapping procedure, ntdll!LdrpSignalModuleMapped is called which will queue the snap action by calling ntdll!LdrpQueueWork. Mapping is the process of loading a file from disk into memory. The thread will either map ( ntdll!LdrpMapDllSearchPath or ntdll!LdrpMapDllFullPath) a DLL or snap ( ntdll!LdrpSnapModule) a DLL based on the value _LDR_DDAG_NODE.State. When work is available, the worker thread will call ntdll!LdrpWorkCallback which calls ntdll!LdrpProcessWork. Ntdll!LdrpWorkCallback is registered as the thread pool work callback function. Programs which execute in less than 30 seconds will appear to hang due to ntdll!TppWorkerThreadwaiting for the idle timeout before the process terminates. The worker thread idle timeout is set to 30 seconds. If LoaderThreads is 0, it will be set to the default value of 4 if the LoaderThreads is larger than 16, it is set to the max value of 16. Ntdll!LdrpEnableParallelLoading validates the number of worker threads to be between and creates a thread pool with one less than LoaderThreadsworkers threads since the master thread will also perform the work of loading DLLs. This data is an array of the first 16 bytes of each function copied by ntdll!LdrpCaptureCriticalThunks which is called near the start of ntdll!LdrpInitializeProcess. The first 16 bytes of these functions are compared to ntdll!LdrpThunkSignature. Hooks are detected by examining the first 16 bytes of the functions defined in ntdll!LdrpCriticalLoaderFunctions: If a hook is detected, ntdll!LdrpDetourExist is set to true and the thread pool is drained and released. Ntdll!LdrpEnableParallelLoading calls ntdll!LdrpDetectDetour to determine if the process being hooked. In order to mitigate against corrupting memory or compatibility issues, Windows detects if a process is hooked before enabling parallel loading. There are a lot of hazards when it comes to parallel loading and code hooking. How Windows 10 Mitigates Parallel Loading Hazards One interesting thing to note is that kernel32.dll and kernelbase.dll are loaded even if the process does not require it. ntdll!LdrpWorkQueueLock (CRITICAL_SECTION)įigure 2: Initializing the work queue structuresįigure 3: Creating the synchronization eventsĪfter ntdll loads kernel32.dll and kernelbase.dll are loaded, ntdll!LdrpEnableParallelLoading is called to set up the necessary events and worker pool.Ntdll!LdrpInitParallelLoadingSupport and ntdll!LdrpCreateLoaderEvents are called to initialize the following structures: Threads created by the master thread in the thread pool will be referred to as worker threads. The initial thread in the process executing ntdll!LdrInitializeThunk will be referred to as the master thread. Interestingly, Windows 10 contains a default entry for chrome.exe with MaxLoaderThreads set to 1 to disable parallel loading.įigure 1: Querying the IFEO registry key for MaxLoaderThreads ntdll!LdrpInitializeExecutionOptions can further override the LoaderThreads field by querying the Image File Execution Options (IFEO) registry key HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\\MaxLoaderThreads. The parent process defines the number of worker threads by defining in the PEB->ProcessParameters->LoaderThreads (ULONG) field. Windows 10 implements parallel loading by creating a thread pool of worker threads when the process initializes. How Windows 10 Implements Parallel Loading This feature decreases process startup times by using multiple threads to load libraries from disk into memory. One of the unnoticed improvements of Window 10 is the parallel library loading support in ntdll.dll.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. ArchivesCategories |