Repository: paskalian/WID_LoadLibrary Branch: main Commit: e3f55b6f40ba Files: 18 Total size: 331.5 KB Directory structure: gitextract_m362muyh/ ├── .gitignore ├── LICENSE ├── README.md ├── Src/ │ ├── Functions/ │ │ ├── KERNEL32.cpp │ │ ├── KERNEL32.h │ │ ├── NT.cpp │ │ ├── NT.h │ │ ├── Syscalls.asm │ │ └── Undocumented.h │ ├── Includes.h │ ├── Loader/ │ │ ├── Loader.cpp │ │ └── Loader.h │ ├── Main.cpp │ ├── WID.cpp │ └── WID.h ├── WID_LoadLibrary.sln ├── WID_LoadLibrary.vcxproj └── WID_LoadLibrary.vcxproj.filters ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ ################################################################################ # Bu .gitignore dosyası Microsoft(R) Visual Studio tarafından otomatik olarak oluşturulmuştur. ################################################################################ /.vs /WID_LoadLibrary.vcxproj.user /x64/Debug /Debug/WID_LoadLibrary.tlog /Debug ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2023 Paskalian Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ ![WID LOGO](Images/WID.svg "WID_LOGO")
# LEGAL NOTICE I do not take responsibility for any misuse of these information in any way. The purpose of these series are **only** to understand Windows better, there is a lot to discover. # Information ### Compatibility The project is designed specifically for x64 architecture, not tested in x86 architecture. ### Functions All the function implementations given are my own, they are not guaranteed to represent the exact functionality. # Usage Pretty easy, you first include "WID.h" into your source file. Then you create a LOADLIBRARY instance with a path given, and that's it. Now you can almost see the entire loading process! ```cpp #include "WID.h" using namespace WID::Loader; int main() { LOADLIBRARY LoadDll(TEXT("PATH_TO_DLL.dll")); } ``` The constructor takes in 3 arguments, which the last 2 are set by default. #### PATH Dll path, can be absolute or relative. **Must** be given. #### FLAGS Same flags as in LoadLibraryExW, you can check the possible values in [here](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw). Set to 0 by default. #### LOAD TYPE (NOT USEFUL CURRENTLY) If set to LOADTYPE::HIDDEN, Windows will not be informed about the loading of the dll. Set to LOADTYPE::DEFAULT by default.
# What is LoadLibrary? LoadLibrary is an easy to use Windows API function for loading Dynamic Link Libraries (DLLs) into programs. To be able to use it you must first include into your source file. There are 4 widely used LoadLibrary functions - [LoadLibraryA](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya "MSDN Reference") - [LoadLibraryW](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryw "MSDN Reference") - [LoadLibraryExA](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa "MSDN Reference") - [LoadLibraryExW](https://learn.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexw "MSDN Reference") Even if they look like seperate, they all end up in **LoadLibraryExW** finally, wanna learn how? Keep reading.
Here is a basic diagram to show what functions are called in order to load a module into a process (maybe not exact represantation).

The path was given absolute and no flags were given Diagram

# Basic Explanations ## LoadLibrary ```cpp #ifdef UNICODE #define LoadLibrary LoadLibraryW #else #define LoadLibrary LoadLibraryA #endif // !UNICODE ``` Not a function by itself but a macro instead, resolved into one of the according functions **LoadLibraryA** or **LoadLibraryW** depending on your character set being **Multi-byte** or **Unicode** respectively.
## LoadLibraryA ```cpp HMODULE __fastcall LOADLIBRARY::fLoadLibraryA(LPCSTR lpLibFileName) { // If no path was given. if (!lpLibFileName) //return LoadLibraryExA(lpLibFileName, 0, 0); return NULL; // If path isn't 'twain_32.dll' // This is where our LoadLibrary calls mostly end up. if (_stricmp(lpLibFileName, "twain_32.dll")) return fLoadLibraryExA(lpLibFileName, 0, 0); // If path is 'twain_32.dll' // Windows probably uses this to make itself a shortcut, while we are using it the code won't reach here. PCHAR Heap = (PCHAR)RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, *KernelBaseGlobalData, MAX_PATH); if (!Heap) return fLoadLibraryExA(lpLibFileName, 0, 0); HMODULE Module; // Heap receives the Windows path (def: C:\Windows) // The BufferSize check made against GetWindowsDirectoryA is to see if it actually received. If it's bigger than BufferSize // then GetWindowsDirectoryA returned the size needed (in summary it fails) // If this check doesn't fail '\twain_32.dll' is appended to the Windows path (def: C:\Windows\twain_32.dll) // Then this final module is loaded into the program. // If it can't load, it tries to load it directly and returns from there. if (GetWindowsDirectoryA(Heap, 0xF7) - 1 > 0xF5 || (strncat_s(Heap, MAX_PATH, "\\twain_32.dll", strlen("\\twain_32.dll")), (Module = fLoadLibraryA(Heap)) == 0)) { RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Heap); return fLoadLibraryExA(lpLibFileName, 0, 0); } RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Heap); return Module; } ``` In our use case it's just a small wrapper around LoadLibraryExA. Other way around you can see it provides a shortcut mechanism for loading "**twain_32.dll**".
## LoadLibraryW ```cpp HMODULE __fastcall LOADLIBRARY::fLoadLibraryW(LPCWSTR lpLibFileName) { return fLoadLibraryExW(lpLibFileName, 0, 0); } ``` A wrapper for LoadLibraryExW.
## LoadLibraryExA ```cpp HMODULE __fastcall LOADLIBRARY::fLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { UNICODE_STRING Unicode; if (!Basep8BitStringToDynamicUnicodeString(&Unicode, lpLibFileName)) return NULL; HMODULE Module = fLoadLibraryExW(Unicode.Buffer, hFile, dwFlags); RtlFreeUnicodeString(&Unicode); return Module; } ``` Converts our ANSI given lpLibFileName into Unicode then calls LoadLibraryExW with it. In summary it's a wrapper for LoadLibraryExW, that's what I meant when I said all of the 4 functions end up in LoadLibraryExW.
## LoadLibraryExW ```cpp HMODULE __fastcall LOADLIBRARY::fLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) { NTSTATUS Status; DWORD ConvertedFlags; HMODULE BaseOfLoadedDll; DWORD DatafileFlags = dwFlags & LLEXW_ASDATAFILE; // If no DllName was given OR hFile was given (msdn states that hFile must be 0) OR dwFlags is set to an unknown value OR *both* the Datafile flags are set (they cannot be used together). if (!lpLibFileName || hFile || ((dwFlags & 0xFFFF0000) != 0) || (DatafileFlags == LLEXW_ASDATAFILE)) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } UNICODE_STRING DllName; Status = RtlInitUnicodeStringEx(&DllName, lpLibFileName); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return NULL; } USHORT DllNameLen = DllName.Length; if (!DllName.Length) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } // If the DllName given had empty (space) chars as their last chars, this do-while loop excludes them and sets the excluded length. do { DWORD WchAmount = DllNameLen / 2; if (DllName.Buffer[WchAmount - 1] != ' ' /* 0x20 is space char */) break; DllNameLen -= 2; DllName.Length = DllNameLen; } while (DllNameLen != 2); // In case the above do-while loop misbehaves. if (DllNameLen == 0) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } BaseOfLoadedDll = 0; // If the dll is not getting loaded as a datafile. if ((dwFlags & LLEXW_ISDATAFILE) == 0) { // Converts the actual flags into it's own flag format. Most flags are discarded (only used if loaded as datafile). // Only flags that can go through are DONT_RESOLVE_DLL_REFERENCES, LOAD_PACKAGED_LIBRARY, LOAD_LIBRARY_REQUIRE_SIGNED_TARGET and LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY ConvertedFlags = 0; if ((dwFlags & DONT_RESOLVE_DLL_REFERENCES) != 0) ConvertedFlags |= CNVTD_DONT_RESOLVE_DLL_REFERENCES; if ((dwFlags & LOAD_PACKAGED_LIBRARY) != 0) ConvertedFlags |= LOAD_PACKAGED_LIBRARY; if ((dwFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) != 0) ConvertedFlags |= CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET; if ((dwFlags & LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY) != 0) ConvertedFlags |= CNVTD_LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY; // Evaluates dwFlags to get meaningful flags, includes DONT_RESOLVE_DLL_REFERENCES finally. // But it doesn't matter because the first param LdrLoadDll takes actually a (PWCHAR PathToFile), so I have no idea why that's done. Status = fLdrLoadDll((PWCHAR)((dwFlags & LLEXW_7F08) | 1), &ConvertedFlags, &DllName, (PVOID*)&BaseOfLoadedDll); if (NT_SUCCESS(Status)) return BaseOfLoadedDll; BaseSetLastNTError(Status); return NULL; } PWSTR Path; PWSTR Unknown; // Gets the Dll path. Status = LdrGetDllPath(DllName.Buffer, (dwFlags & LLEXW_7F08), &Path, &Unknown); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return NULL; } // First step into loading a module as datafile. Status = fBasepLoadLibraryAsDataFileInternal(&DllName, Path, Unknown, dwFlags, &BaseOfLoadedDll); // If the Status is only success (excludes warnings) AND if the module is image resource, loads again. I don't know why. if (NT_SUCCESS(Status + 0x80000000) && Status != STATUS_NO_SUCH_FILE && (dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE)) { if (DatafileFlags) Status = fBasepLoadLibraryAsDataFileInternal(&DllName, Path, Unknown, DatafileFlags, &BaseOfLoadedDll); } RtlReleasePath(Path); BaseSetLastNTError(Status); return NULL; } ``` Converts our given flags to it's own converted flags and calls LdrLoadDll, other way around requires the dll to be loaded as a datafile, which we are not interested in right now.
## LdrLoadDll ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrLoadDll(PWSTR DllPath, PULONG pFlags, PUNICODE_STRING DllName, PVOID* BaseAddress) { NTSTATUS Status; // DllPath can also be used as Flags if called from LoadLibraryExW UINT_PTR FlagUsed = 0; if (pFlags) { // Only flags that could go through *LoadLibraryExW* were; // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) // LOAD_PACKAGED_LIBRARY (0x4) // CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x800000) // CNVTD_LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY (0x80000000) // So I am assuming the rest of the flags are 0. UINT_PTR ActualFlags = *pFlags; // If LOAD_PACKAGED_LIBRARY (0x4) flag is set (1) FlagUsed becomes CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2), if not set (0) FlagUsed becomes 0. FlagUsed = CNVTD_DONT_RESOLVE_DLL_REFERENCES * (ActualFlags & LOAD_PACKAGED_LIBRARY); // (MSDN about DONT_RESOLVE_DLL_REFERENCES) Note Do not use this value; it is provided only for backward compatibility. // If you are planning to access only data or resources in the DLL, use LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE // or LOAD_LIBRARY_AS_IMAGE_RESOURCE or both. Otherwise, load the library as a DLL or executable module using the LoadLibrary function. FlagUsed |= ((ActualFlags & CNVTD_DONT_RESOLVE_DLL_REFERENCES) ? LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE : NULL); FlagUsed |= ((ActualFlags & CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) ? LOAD_LIBRARY_REQUIRE_SIGNED_TARGET : NULL); // Ignored because ActualFlags can't have 0x1000 (if called from LoadLibraryExW), this value is used probably in calls from different functions. FlagUsed |= ((ActualFlags & 0x1000) ? 0x100 : 0x0); // Ignored because ActualFlags can't be negative (if called from LoadLibraryExW), this value is used probably in calls from different functions. FlagUsed |= ((ActualFlags < 0) ? 0x400000 : 0x0); // To sum up, in case we are called from LoadLibraryExW, the most flags we can have are; // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x244, "LdrLoadDll", 3u, "DLL name: %wZ\n", DllName); ) if ((*LdrpPolicyBits & 4) == 0 && ((USHORT)DllPath & LLDLL_401) == LLDLL_401) return STATUS_INVALID_PARAMETER; // In here it will go in by the first condition, because 8 couldn't be set by LoadLibraryExW. if ((FlagUsed & LOAD_WITH_ALTERED_SEARCH_PATH) == 0 || (*LdrpPolicyBits & 8) != 0) { // If the current thread is a Worker Thread it fails. if (NtCurrentTeb()->SameTebFlags & LoaderWorker) { Status = STATUS_INVALID_THREAD; } else { LDR_UNKSTRUCT DllPathInited; // There's another LdrpLogInternal inside this function, gonna mess with that later on. LdrpInitializeDllPath(DllName->Buffer, DllPath, &DllPathInited); LDR_DATA_TABLE_ENTRY* DllEntry; Status = fLdrpLoadDll(DllName, &DllPathInited, FlagUsed, &DllEntry); if (DllPathInited.IsInitedMaybe) RtlReleasePath(DllPathInited.pInitNameMaybe); if (NT_SUCCESS(Status)) { // Changes the actual return value and dereferences the module. *BaseAddress = DllEntry->DllBase; LdrpDereferenceModule(DllEntry); } } } else { // LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 601, "LdrLoadDll", 0, &LdrEntry[176]); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x259, "LdrLoadDll", 0, "Nonpackaged process attempted to load a packaged DLL.\n"); ) Status = STATUS_NO_APPLICATION_PACKAGE; } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x279, "LdrLoadDll", 4, "Status: 0x%08lx\n", Status); ) return Status; } ``` Flags are re-converted, a check is made to see if the current thread is a worker thread, our path is initialized then LdrpLoadDll is getting called.
## LdrpLoadDll ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpLoadDll(PUNICODE_STRING DllName, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, LDR_DATA_TABLE_ENTRY** DllEntry) { NTSTATUS Status; WID_HIDDEN( LdrpLogDllState(0, DllName, 0x14A8); ) // Flags is passed by value so no need to create a backup, it's already a backup by itself. // MOST FLAGS = CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) // Creates a new unicode_string and allocates it some buffer. UNICODE_STRING FullDllPath; WCHAR Buffer[128]; FullDllPath.Length = 0; FullDllPath.MaximumLength = MAX_PATH - 4; FullDllPath.Buffer = Buffer; Buffer[0] = 0; // Returns the Absolute path // If a non-relative path was given then the flags will be ORed with LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) // resulting in the MOST FLAGS being: // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) | // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) Status = LdrpPreprocessDllName(DllName, &FullDllPath, 0, &Flags); if (NT_SUCCESS(Status)) // A even deeper function, by far we can see Windows is kinda all *wrapped* around each other. fLdrpLoadDllInternal(&FullDllPath, DllPathInited, Flags, ImageDll, 0, 0, DllEntry, &Status, 0); if (Buffer != FullDllPath.Buffer) NtdllpFreeStringRoutine(FullDllPath.Buffer); // I don't see no point in this but anyways. FullDllPath.Length = 0; FullDllPath.MaximumLength = MAX_PATH - 4; FullDllPath.Buffer = Buffer; Buffer[0] = 0; WID_HIDDEN( LdrpLogDllState(0, DllName, 0x14A9); ) return Status; } ``` A fairly smaller one than the last, the main purpose of it is to divide our path given into meaningful parts by LdrpPreprocessDllName then calling LdrpLoadDllInternal using that.
## LdrpLoadDllInternal ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpLoadDllInternal(PUNICODE_STRING FullPath, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, ULONG LdrFlags, PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY LdrEntry2, PLDR_DATA_TABLE_ENTRY* DllEntry, NTSTATUS* pStatus, ULONG Zero) { NTSTATUS Status; // NOTES: // I assumed that LdrFlags (which was sent as 0x4 (ImageDll) by LdrpLoadDll) is the same flags inside LDR_DATA_TABLE_ENTRY. // LdrEntry & LdrEntry2 were both sent as 0s by LdrpLoadDll. // // Instead of using gotos which causes the local variables to be initialized in the start of the function (making it look not good in my opinion) // I created a do-while loop. The outcome won't be affected. // // MOST FLAGS = CONVERTED_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x379, "LdrpLoadDllInternal", 3, "DLL name: %wZ\n", FullPath); ) bool IsWorkerThread = false; do { *DllEntry = 0; LdrEntry = LdrEntry2; // This will go in. if (LdrFlags != (PackagedBinary | LoadNotificationsSent)) { // This function does some prior setup, incrementing the module load count is done inside here. Status = LdrpFastpthReloadedDll(FullPath, Flags, LdrEntry2, DllEntry); // returns STATUS_DLL_NOT_FOUND in normal circumstances. // If not an actual nt success (excludes warnings) if (!(NT_SUCCESS((int)(Status + 0x80000000))) || Status == STATUS_IMAGE_LOADED_AS_PATCH_IMAGE) { *pStatus = Status; break; } } IsWorkerThread = ((NtCurrentTeb()->SameTebFlags & LoadOwner) == 0); if (IsWorkerThread) LdrpDrainWorkQueue(WaitLoadComplete); // This won't go in so we can ignore it. I still did simplifying though. // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one. if (LdrFlags == (PackagedBinary | LoadNotificationsSent)) { Status = LdrpFindLoadedDllByHandle(Zero, &LdrEntry, 0); if (!NT_SUCCESS(Status)) { if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } if (LdrEntry->HotPatchState == LdrHotPatchFailedToPatch) { Status = STATUS_PATCH_CONFLICT; // goto FREE_DLLNAMEPREPROCANDRETURN; if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } Status = LdrpQueryCurrentPatch(LdrEntry->CheckSum, LdrEntry->TimeDateStamp, FullPath); if (!NT_SUCCESS(Status)) { // goto FREE_DLLNAMEPREPROCANDRETURN; if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } if (!FullPath->Length) { if (LdrEntry->ActivePatchImageBase) Status = LdrpUndoPatchImage(LdrEntry); // goto FREE_DLLNAMEPREPROCANDRETURN; if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } // LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x3FA, "LdrpLoadDllInternal", 2u, &::LdrEntry[232], FullPath); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x3FA, "LdrpLoadDllInternal", 2, "Loading patch image: %wZ\n", FullPath); ) } // Opens a token to the current thread and sets GLOBAL variable LdrpMainThreadToken with that token. LdrpThreadTokenSetMainThreadToken(); // returns STATUS_NO_TOKEN in normal circumstances. LDR_DATA_TABLE_ENTRY* pLdrEntryLoaded = 0; // This will go in by the first check LdrEntry2 because it was sent as 0 in LdrpLoadDll. if (!LdrEntry || !IsWorkerThread || LdrEntry->DdagNode->LoadCount) { // I checked the function, it detects a hook by byte scanning these following functions; // • ntdll!NtOpenFile // • ntdll!NtCreateSection // • ntdll!ZqQueryAttributes // • ntdll!NtOpenSection // • ntdll!ZwMapViewOfSection // Resulting in the global variable LdrpDetourExist to be set if there's a hook, didn't checked what's done with it though. LdrpDetectDetour(); // [IGNORE THIS] Finds the module, increments the loaded module count. [IGNORE THIS] // [IGNORE THIS] It can go to another direction if the Flag LOAD_LIBRARY_SEARCH_APPLICATION_DIR was set, but that couldn't be set coming from LoadLibraryExW. [IGNORE THIS] // If LoadLibrary was given an absolute path, Flags will have LOAD_LIBRARY_SEARCH_APPLICATION_DIR causing this function to call LdrpLoadKnownDll. // In our case LdrpFindOrPrepareLoadingModule actually returns STATUS_DLL_NOT_FOUND, which I thought was a bad thing but after checking up inside // inside LdrpProcessWork it didn't looked that bad. // So our dll loading part is actually inside LdrpProcessWork (for calling LoadLibraryExW with an absolute path and 0 flags at least) //Status = LdrpFindOrPrepareLoadingModule(FullPath, DllPathInited, Flags, LdrFlags, LdrEntry, &pLdrEntryLoaded, pStatus); Status = LdrpFindOrPrepareLoadingModule(FullPath, DllPathInited, Flags, LdrFlags, LdrEntry, &pLdrEntryLoaded, pStatus); if (Status == STATUS_DLL_NOT_FOUND) // Even if the DllMain call succeeds, there's still runtime bugs on the dll side, like the dll not being able to unload itself and such. So I still got // a lot of work to do. fLdrpProcessWork(pLdrEntryLoaded->LoadContext, TRUE); else if (Status != STATUS_RETRY && !NT_SUCCESS(Status)) *pStatus = Status; } else { *pStatus = STATUS_DLL_NOT_FOUND; } LdrpDrainWorkQueue(WaitWorkComplete); if (*LdrpMainThreadToken) // Closes the token handle, and sets GLOBAL variable LdrpMainThreadToken to 0. LdrpThreadTokenUnsetMainThreadToken(); if (pLdrEntryLoaded) { *DllEntry = LdrpHandleReplacedModule(pLdrEntryLoaded); if (pLdrEntryLoaded != *DllEntry) { LdrpFreeReplacedModule(pLdrEntryLoaded); pLdrEntryLoaded = *DllEntry; if (pLdrEntryLoaded->LoadReason == LoadReasonPatchImage && LdrFlags != (PackagedBinary | LoadNotificationsSent)) *pStatus = STATUS_IMAGE_LOADED_AS_PATCH_IMAGE; } if (pLdrEntryLoaded->LoadContext) LdrpCondenseGraph(pLdrEntryLoaded->DdagNode); if (NT_SUCCESS(*pStatus)) { // [IGNORE THIS] In here I realized that the module must have already been loaded to be prepared for execution. // [IGNORE THIS] So I've gone a little back and realized the actual loading was done in the LdrpDrainWorkQueue function. // Doing more research revealed it was inside LdrpProcessWork after LdrpFindOrPrepareLoadingModule returning STATUS_DLL_NOT_FOUND. Status = fLdrpPrepareModuleForExecution(pLdrEntryLoaded, pStatus); *pStatus = Status; if (NT_SUCCESS(Status)) { Status = LdrpBuildForwarderLink(LdrEntry, pLdrEntryLoaded); *pStatus = Status; if (NT_SUCCESS(Status) && !*LdrInitState) LdrpPinModule(pLdrEntryLoaded); } // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one too. if (LdrFlags == (PackagedBinary | LoadNotificationsSent) && LdrEntry->ActivePatchImageBase != pLdrEntryLoaded->DllBase) { if (pLdrEntryLoaded->HotPatchState == LdrHotPatchFailedToPatch) { *pStatus = STATUS_DLL_INIT_FAILED; } else { Status = LdrpApplyPatchImage(pLdrEntryLoaded); *pStatus = Status; if (!NT_SUCCESS(Status)) { //UNICODE_STRING Names[4]; //Names[0] = pLdrEntryLoaded->FullDllName; //WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x4AF, "LdrpLoadDllInternal", 0, "Applying patch \"%wZ\" failed\n", Names); ) WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x4AF, "LdrpLoadDllInternal", 0, "Applying patch \"%wZ\" failed\n", pLdrEntryLoaded->FullDllName); ) } } } } LdrpFreeLoadContextOfNode(pLdrEntryLoaded->DdagNode, pStatus); if (!NT_SUCCESS(*pStatus) && (LdrFlags != (PackagedBinary | LoadNotificationsSent) || pLdrEntryLoaded->HotPatchState != LdrHotPatchAppliedReverse)) { *DllEntry = 0; LdrpDecrementModuleLoadCountEx(pLdrEntryLoaded, 0); LdrpDereferenceModule(pLdrEntryLoaded); } } else { *pStatus = STATUS_NO_MEMORY; } } while (FALSE); // LoadNotificationsSent (0x8) | PackagedBinary (0x1) // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one too. if (LdrFlags == (LoadNotificationsSent | PackagedBinary) && LdrEntry) LdrpDereferenceModule(LdrEntry); // Actually returns what LdrpLogInternal returns. WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x52E, "LdrpLoadDllInternal", 4, "Status: 0x%08lx\n", *pStatus); ) return *pStatus; } ``` The main course of action of this function is to check whether the dll was already loaded and waiting to be executed, or is going to be patched, or a new dll is going to be loaded, if it's a new dll (which is our case) it first goes by LdrpProcessWork to start the mapping process, then after that call succeeds goes on by LdrpPrepareModuleForExecution to execute the mapped dll.
## LdrpProcessWork ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpProcessWork(PLDRP_LOAD_CONTEXT LoadContext, BOOLEAN IsLoadOwner) { NTSTATUS Status; // Converted goto to do-while loop. do { Status = *LoadContext->pStatus; if (!NT_SUCCESS(Status)) break; // Caused most likely because CONTAINING_RECORD macro was used, I have no idea what's going on. // Also the structure used (LDRP_LOAD_CONTEXT) isn't documented, that's what I've got out of it so far. if ((UINT_PTR)LoadContext->WorkQueueListEntry.Flink[9].Blink[3].Blink & UINT_MAX) { Status = fLdrpSnapModule(LoadContext); } else { if (LoadContext->Flags & 0x100000) { Status = fLdrpMapDllRetry(LoadContext); } // We will continue from here since we have the LOAD_LIBRARY_SEARCH_APPLICATION_DIR flag, and also the function name is exactly representing // what we are expecting to happen. else if (LoadContext->Flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) { Status = fLdrpMapDllFullPath(LoadContext); } else { Status = fLdrpMapDllSearchPath(LoadContext); } if (NT_SUCCESS(Status) || Status == STATUS_RETRY) break; WID_HIDDEN( Status = LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x7D2, "LdrpProcessWork", 0, "Unable to load DLL: \"%wZ\", Parent Module: \"%wZ\", Status: 0x%x\n", LoadContext, ((UINT_PTR)&LoadContext->Entry->FullDllName & (UINT_PTR)LoadContext->Entry >> 64), Status); ) // This part is for failed cases so we can ignore it. if (Status == STATUS_DLL_NOT_FOUND) { WID_HIDDEN( LdrpLogError(STATUS_DLL_NOT_FOUND, 0x19, 0, LoadContext); ) WID_HIDDEN( LdrpLogDeprecatedDllEtwEvent(LoadContext); ) WID_HIDDEN( LdrpLogLoadFailureEtwEvent((PVOID)LoadContext, (PVOID)(((UINT_PTR)(LoadContext->Entry->EntryPointActivationContext) & ((UINT_PTR)(LoadContext->Entry) >> 64))), STATUS_DLL_NOT_FOUND, LoadFailure, 0); ) //PLDR_DATA_TABLE_ENTRY DllEntry = (PLDR_DATA_TABLE_ENTRY)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (DllEntry->FlagGroup[0] & ProcessStaticImport) { WID_HIDDEN( Status = LdrpReportError(LoadContext, 0, STATUS_DLL_NOT_FOUND); ) } } } if (!NT_SUCCESS(Status)) { *LoadContext->pStatus = Status; } } while (FALSE); if (!IsLoadOwner) { bool SetWorkCompleteEvent; RtlEnterCriticalSection(LdrpWorkQueueLock); --(*LdrpWorkInProgress); if (*LdrpWorkQueue != (LIST_ENTRY*)LdrpWorkQueue || (SetWorkCompleteEvent = TRUE, *LdrpWorkInProgress != 1)) SetWorkCompleteEvent = FALSE; Status = RtlLeaveCriticalSection(LdrpWorkQueueLock); if (SetWorkCompleteEvent) Status = ZwSetEvent(*LdrpWorkCompleteEvent, 0); } return Status; } ``` Goes in an according direction depending by the path type given, in our case we have an absolute path, so we continue by LdrpMapDllFullPath.
## LdrpMapDllFullPath ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllFullPath(PLDRP_LOAD_CONTEXT LoadContext) { NTSTATUS Status; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); LDRP_FILENAME_BUFFER FileNameBuffer; FileNameBuffer.pFileName.Buffer = FileNameBuffer.FileName; FileNameBuffer.pFileName.Length = 0; FileNameBuffer.pFileName.MaximumLength = MAX_PATH - 4; FileNameBuffer.FileName[0] = 0; // Sets the according members of the DllEntry Status = LdrpResolveDllName(LoadContext, &FileNameBuffer, &DllEntry->BaseDllName, &DllEntry->FullDllName, LoadContext->Flags); do { if (LoadContext->UnknownPtr) { if (!NT_SUCCESS(Status)) break; } else { Status = LdrpAppCompatRedirect(LoadContext, &DllEntry->FullDllName, &DllEntry->BaseDllName, &FileNameBuffer, Status); if (!NT_SUCCESS(Status)) break; // Hashes the dll name ULONG BaseDllNameHash = LdrpHashUnicodeString(&DllEntry->BaseDllName); DllEntry->BaseNameHashValue = BaseDllNameHash; LDR_DATA_TABLE_ENTRY* LoadedDll = nullptr; // Most likely checks if the dll was already mapped/loaded. LdrpFindExistingModule(&DllEntry->BaseDllName, &DllEntry->FullDllName, LoadContext->Flags, BaseDllNameHash, &LoadedDll); if (LoadedDll) { LdrpLoadContextReplaceModule(LoadContext, LoadedDll); break; } } // After this function the dll is mapped. Status = fLdrpMapDllNtFileName(LoadContext, &FileNameBuffer); if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) Status = STATUS_INVALID_IMAGE_FORMAT; } while (FALSE); if (FileNameBuffer.FileName != FileNameBuffer.pFileName.Buffer) NtdllpFreeStringRoutine(FileNameBuffer.pFileName.Buffer); return Status; } ``` Sets up a LDRP_FILENAME_BUFFER structure, basically representing each portion of a path (base part, absolute part, etc.), hashes the **base** dll name and checks if it was already loaded, if it's not (our case) it goes on by calling LdrpMapDllNtFileName.
## LdrpMapDllNtFileName ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllNtFileName(PLDRP_LOAD_CONTEXT LoadContext, LDRP_FILENAME_BUFFER* FileNameBuffer) // CHECKED. { NTSTATUS Status; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); INT64 UnknownPtr = LoadContext->UnknownPtr; LONG Unknown = 0; if (LdrpCheckForRetryLoading(LoadContext, 0)) return STATUS_RETRY; PUNICODE_STRING FullDllName = &DllEntry->FullDllName; WID_HIDDEN( LdrpLogDllState((ULONGLONG)DllEntry->DllBase, &DllEntry->FullDllName, 0x14A5); ) //OBJ_CASE_INSENSITIVE ULONG ObjAttributes = OBJ_CASE_INSENSITIVE; if (!*LdrpUseImpersonatedDeviceMap) ObjAttributes = (OBJ_IGNORE_IMPERSONATED_DEVICEMAP | OBJ_CASE_INSENSITIVE); OBJECT_ATTRIBUTES ObjectAttributes; ObjectAttributes.Length = 0x30; ObjectAttributes.RootDirectory = 0; ObjectAttributes.Attributes = ObjAttributes; ObjectAttributes.ObjectName = &FileNameBuffer->pFileName; ObjectAttributes.SecurityDescriptor = 0; ObjectAttributes.SecurityQualityOfService = 0; PCHAR NtPathStuff = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR Unknown2 = 0; if (RtlGetCurrentServiceSessionId()) Unknown2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; else Unknown2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR NtPathStuff2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; if (*Unknown2 && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled)) { //: (char*)0x7FFE0385; PCHAR NtPathStuff3 = RtlGetCurrentServiceSessionId() ? (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1 : (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; // 0x20 is SPACE char if ((*NtPathStuff3 & ' ')) LdrpLogEtwEvent(0x1485, -1, 0xFFu, 0xFFu); } // SYSTEM_FLAGS_INFORMATION if ((NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD)) { WID_HIDDEN( ZwSystemDebugControl(); ) } HANDLE FileHandle; while (TRUE) { IO_STATUS_BLOCK IoStatusBlock; Status = NtOpenFile(&FileHandle, SYNCHRONIZE | FILE_TRAVERSE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, 5, 0x60); if (NT_SUCCESS(Status)) break; if (Status == STATUS_OBJECT_NAME_NOT_FOUND || Status == STATUS_OBJECT_PATH_NOT_FOUND) return STATUS_DLL_NOT_FOUND; if (Status != STATUS_ACCESS_DENIED || Unknown || !LdrpCheckComponentOnDemandEtwEvent(LoadContext)) return Status; Unknown = TRUE; } ULONG SigningLevel; ULONG AllocationAttributes = 0; if (*LdrpAuditIntegrityContinuity && (Status = LdrpValidateIntegrityContinuity(LoadContext, FileHandle), !NT_SUCCESS(Status)) && *LdrpEnforceIntegrityContinuity || (AllocationAttributes = MEM_IMAGE, (LoadContext->Flags & MEM_IMAGE)) && (NtCurrentPeb()->BitField & IsPackagedProcess) == 0 && // (Status = LdrpSetModuleSigningLevel(FileHandle, (PLDR_DATA_TABLE_ENTRY)LoadContext->WorkQueueListEntry.Flink, &SigningLevel, 8), !NT_SUCCESS(Status))) (Status = LdrpSetModuleSigningLevel(FileHandle, CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), &SigningLevel, 8), !NT_SUCCESS(Status))) { NtClose(FileHandle); return Status; } if (*UseWOW64 && (LoadContext->Flags & 0x800) == 0) AllocationAttributes = MEM_IMAGE | MEM_TOP_DOWN; HANDLE SectionHandle; Status = NtCreateSection(&SectionHandle, SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE, 0, 0, PAGE_EXECUTE, AllocationAttributes, FileHandle); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NEEDS_REMEDIATION || (Status + 0x3FFFFB82) <= 1) { Status = LdrAppxHandleIntegrityFailure(Status); } else if (Status != STATUS_NO_MEMORY && Status != STATUS_INSUFFICIENT_RESOURCES && Status != STATUS_COMMITMENT_LIMIT) { LDR_UNKSTRUCT2 NtHardParameters; NtHardParameters.Name = FullDllName; NtHardParameters.Status = Status; // Semi-documented in http://undocumented.ntinternals.net/ HARDERROR_RESPONSE Response; if (NT_SUCCESS(NtRaiseHardError(STATUS_INVALID_IMAGE_FORMAT, 2, 1, (INT*)&NtHardParameters, OptionOk, &Response)) && *LdrInitState != 3) { ++(*LdrpFatalHardErrorCount); } } WID_HIDDEN( LdrpLogError(Status, 0x1485u, 0, FullDllName); ) NtClose(FileHandle); return Status; } if (RtlGetCurrentServiceSessionId()) NtPathStuff = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; if (*NtPathStuff && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { if (RtlGetCurrentServiceSessionId()) NtPathStuff2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; // 0x20 is SPACE char. if ((*NtPathStuff2 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1486, -1, 0xFFu, 0xFFu); ) } if (!*UseWOW64 && (LoadContext->Flags & 0x100) == 0 && (Status = LdrpCodeAuthzCheckDllAllowed(FileNameBuffer, FileHandle), NT_SUCCESS((LONG)(Status + 0x80000000))) && Status != STATUS_NOT_FOUND || (Status = fLdrpMapDllWithSectionHandle(LoadContext, SectionHandle), !UnknownPtr) || !NT_SUCCESS(Status)) { NtClose(SectionHandle); NtClose(FileHandle); return Status; } LoadContext->FileHandle = FileHandle; LoadContext->SectionHandle = SectionHandle; return Status; } ``` Opens the file with NtOpenFile, creates a section using NtCreateSection to be able to map the dll, continues with calling LdrpMapDllWithSectionHandle.
## LdrpMapDllWithSectionHandle ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllWithSectionHandle(PLDRP_LOAD_CONTEXT LoadContext, HANDLE SectionHandle) // CHECKED. { NTSTATUS Status; NTSTATUS Status2; NTSTATUS Status3; NTSTATUS Status4; int v19[14]; LDR_DATA_TABLE_ENTRY* LdrEntry2; // Mapping mechanism. Status = fLdrpMinimalMapModule(LoadContext, SectionHandle); Status2 = Status; if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) return Status2; if (!NT_SUCCESS(Status)) return Status2; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); SIZE_T Size = LoadContext->Size; LDR_DATA_TABLE_ENTRY* LdrEntry = nullptr; Status3 = Status; PIMAGE_NT_HEADERS OutHeaders; Status2 = RtlImageNtHeaderEx(0, DllEntry->DllBase, Size, &OutHeaders); if (!NT_SUCCESS(Status2)) return Status2; if (LoadContext->Flags & SEC_FILE) { Status3 = STATUS_SUCCESS; DllEntry->TimeDateStamp = OutHeaders->FileHeader.TimeDateStamp; DllEntry->CheckSum = OutHeaders->OptionalHeader.CheckSum; DllEntry->SizeOfImage = OutHeaders->OptionalHeader.SizeOfImage; } else { RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); UINT_PTR Flags = (LoadContext->Flags) & UINT_MAX; PUNICODE_STRING FullDllName_2 = 0; if ((Flags & 0x20) == 0) FullDllName_2 = &DllEntry->FullDllName; // Returns STATUS_DLL_NOT_FOUND is normal situations. Status4 = LdrpFindLoadedDllByNameLockHeld(&DllEntry->BaseDllName, FullDllName_2, Flags, &LdrEntry, DllEntry->BaseNameHashValue); if (Status4 == STATUS_DLL_NOT_FOUND) { PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; v19[0] = OutHeaders->FileHeader.TimeDateStamp; v19[1] = OutHeaders->OptionalHeader.SizeOfImage; LdrpFindLoadedDllByMappingLockHeld(DllBase, OutHeaders, (ULONG*)v19, &LdrEntry); } if (!LdrEntry) { LdrpInsertDataTableEntry(DllEntry); LdrpInsertModuleToIndexLockHeld(DllEntry, OutHeaders); } RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); if (LdrEntry) { if (DllEntry->LoadReason != LoadReasonPatchImage || LdrEntry->LoadReason == LoadReasonPatchImage) { LdrpLoadContextReplaceModule(LoadContext, LdrEntry); } else { Status2 = STATUS_IMAGE_LOADED_AS_PATCH_IMAGE; WID_HIDDEN( LdrpLogEtwHotPatchStatus(&(*LdrpImageEntry)->BaseDllName, LoadContext->Entry, &DllEntry->FullDllName, STATUS_IMAGE_LOADED_AS_PATCH_IMAGE, 3); ) LdrpDereferenceModule(LdrEntry); } return Status2; } } if (*qword_17E238 == NtCurrentTeb()->ClientId.UniqueThread) return STATUS_NOT_FOUND; Status2 = fLdrpCompleteMapModule(LoadContext, OutHeaders, Status3); if (NT_SUCCESS(Status2)) { Status2 = fLdrpProcessMappedModule(DllEntry, LoadContext->Flags & UINT_MAX, 1); if (NT_SUCCESS(Status2)) { WID_HIDDEN( LdrpLogNewDllLoad(LoadContext->Entry, DllEntry); ) LdrEntry2 = LoadContext->Entry; if (LdrEntry2) DllEntry->ParentDllBase = LdrEntry2->DllBase; BOOLEAN DllBasesEqual = FALSE; if (DllEntry->LoadReason == LoadReasonPatchImage && *LdrpImageEntry) DllBasesEqual = DllEntry->ParentDllBase == (*LdrpImageEntry)->DllBase; if ((LoadContext->Flags & SEC_FILE) || (DllEntry->FlagGroup[0] & ImageDll) || DllBasesEqual) { if ((DllEntry->Flags & CorILOnly)) { return fLdrpCorProcessImports(DllEntry); } else { fLdrpMapAndSnapDependency(LoadContext); return *LoadContext->pStatus; } } else { WID_HIDDEN( LdrpLogDllState((ULONG)DllEntry->DllBase, &DllEntry->FullDllName, 0x14AEu); ) Status2 = STATUS_SUCCESS; DllEntry->DdagNode->State = LdrModulesReadyToRun; } } } return Status2; } ``` Maps a view of section inside LdrpMinimalMapModule, validates the image inside LdrpCompleteMapModule, handles relocations inside LdrpProcessMappedModule, updates state inside LdrpCorProcessImports, goes on by calling LdrpMapAndSnapDependency.
## LdrpMapAndSnapDependency ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpMapAndSnapDependency(PLDRP_LOAD_CONTEXT LoadContext) { NTSTATUS Status; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); BOOLEAN IsFile = (LoadContext->Flags & SEC_FILE); BOOLEAN FullPathExists = 0; UNICODE_STRING FullPath; memset(&FullPath, 0, sizeof(FullPath)); do { if (!IsFile) { if (DllEntry->LoadReason != LoadReasonPatchImage) { Status = LdrpFindDllActivationContext(DllEntry); if (!NT_SUCCESS(Status)) break; } } Status = fLdrpPrepareImportAddressTableForSnap(LoadContext); if (!NT_SUCCESS(Status)) break; ULONG CurrentDllDecremented = 0; ULONG OldCurrentDll = 0; if (*LdrpIsHotPatchingEnabled) { DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; if (DllEntry) { Status = LdrpQueryCurrentPatch(DllEntry->CheckSum, DllEntry->TimeDateStamp, &FullPath); if (!NT_SUCCESS(Status)) break; if (FullPath.Length) FullPathExists = TRUE; } } PIMAGE_IMPORT_DESCRIPTOR ImageImportDescriptor = nullptr; if (LoadContext->pImageImportDescriptor || FullPathExists) { if (LdrpShouldModuleImportBeRedirected(DllEntry)) LoadContext->Flags |= 0x2000000u; ImageImportDescriptor = LdrpGetImportDescriptorForSnap(LoadContext); ULONG IATSize = 0; PIMAGE_THUNK_DATA32 FirstThunk = (PIMAGE_THUNK_DATA32)&ImageImportDescriptor->FirstThunk; BOOLEAN JumpIn = FALSE; if (ImageImportDescriptor) { PIMAGE_THUNK_DATA32 FirstThunk2 = (IMAGE_THUNK_DATA32*)&ImageImportDescriptor->FirstThunk; ULONG DllBaseIncremented = 0; do { if (!FirstThunk2[-1].u1.ForwarderString) break; ULONG ForwarderString = FirstThunk2->u1.ForwarderString; if (!FirstThunk2->u1.ForwarderString) break; ULONG DllBaseIncremented_2 = DllBaseIncremented + 1; FirstThunk2 += 5; ++IATSize; if (!*(UINT_PTR*)((char*)&DllEntry->DllBase->e_magic + ForwarderString)) DllBaseIncremented_2 = DllBaseIncremented; DllBaseIncremented = DllBaseIncremented_2; } while (FirstThunk2 != (IMAGE_THUNK_DATA32*)16); OldCurrentDll = DllBaseIncremented; if (DllBaseIncremented) JumpIn = TRUE; } BOOLEAN JumpOut = FALSE; if (JumpIn || FullPathExists) { PVOID* Heap = (PVOID*)RtlAllocateHeap(*LdrpHeap, (*NtdllBaseTag + 0x180000) | 8u, 8 * IATSize); LoadContext->IATCheck = (LDR_DATA_TABLE_ENTRY**)Heap; if (Heap) { LoadContext->SizeOfIAT = IATSize; LoadContext->GuardCFCheckFunctionPointer = ImageImportDescriptor; LoadContext->CurrentDll = OldCurrentDll + 1; if (FullPathExists) LoadContext->CurrentDll = OldCurrentDll + 2; PIMAGE_THUNK_DATA pThunk = nullptr; UINT_PTR IATAmount = 0; if (ImageImportDescriptor) { while (FirstThunk[-1].u1.ForwarderString && FirstThunk->u1.ForwarderString) { PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; if (*(UINT_PTR*)((char*)&DllBase->e_magic + FirstThunk->u1.ForwarderString)) { ULONG ForwarderString_2 = FirstThunk[-1].u1.ForwarderString; IsFile = (PIMAGE_IMPORT_BY_NAME)(ForwarderString_2 + (UINT_PTR)DllBase) != 0; PCHAR ForwarderBuffer = (PCHAR)(ForwarderString_2 + (UINT_PTR)DllBase); STRING SourceString = {}; *(UINT_PTR*)&SourceString.Length = 0; SourceString.Buffer = ForwarderBuffer; if (IsFile) { SIZE_T SourceLen = -1; do { ++SourceLen; } while (ForwarderBuffer[SourceLen]); if (SourceLen > 0xFFFE) { Status = STATUS_NAME_TOO_LONG; break; } SourceString.Length = SourceLen; SourceString.MaximumLength = SourceLen + 1; } Status = LdrpLoadDependentModuleA((PUNICODE_STRING)&SourceString, LoadContext, DllEntry, 0, &LoadContext->IATCheck[IATAmount], (UINT_PTR)&pThunk); if (!NT_SUCCESS(Status)) break; } FirstThunk += 5; IATAmount = (ULONG)(IATAmount + 1); if (FirstThunk == (PIMAGE_THUNK_DATA32)16) break; } } if (FullPathExists) { // Loads Imports dlls. Status = LdrpLoadDependentModuleW(&FullPath, LoadContext, DllEntry); if (!NT_SUCCESS(Status)) WID_HIDDEN(LdrpLogEtwHotPatchStatus(&(*LdrpImageEntry)->BaseDllName, DllEntry, &FullPath, Status, 5u); ) } if (pThunk) RtlFreeHeap(*LdrpHeap, 0, pThunk); if (NT_SUCCESS(Status)) { RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); CurrentDllDecremented = --LoadContext->CurrentDll; RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); JumpOut = TRUE; } } else { Status = STATUS_NO_MEMORY; } } if (!JumpOut) CurrentDllDecremented = OldCurrentDll; } PLDR_DDAG_NODE DdagNode = nullptr; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = LoadContext->pImageImportDescriptor; if (pImageImportDescriptor || !FullPathExists) { if (CurrentDllDecremented) break; DdagNode = DllEntry->DdagNode; if (pImageImportDescriptor) { DdagNode->State = LdrModulesSnapping; if (LoadContext->Entry) LdrpQueueWork(LoadContext); else Status = fLdrpSnapModule(LoadContext); break; } } else { DdagNode = DllEntry->DdagNode; } DdagNode->State = LdrModulesSnapped; } while (FALSE); LdrpFreeUnicodeString(&FullPath); if (!NT_SUCCESS(Status)) { *LoadContext->pStatus = Status; } return *LoadContext->pStatus; } ``` Prepares the Import Address Table (IAT) by calling LdrpPrepareImportAddressTableForSnap, loads the imports of the dll getting loaded, sets the state, continues on by calling LdrpSnapModule which I am quite frank about the actual functionality, but I've seen it handling exports.
## LdrpPrepareImportAddressTableForSnap ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpPrepareImportAddressTableForSnap(LDRP_LOAD_CONTEXT* LoadContext) { NTSTATUS Status; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); PIMAGE_IMPORT_DESCRIPTOR ImageImportDescriptor = nullptr; UINT_PTR* pImageImportDescriptorLen = (UINT_PTR*)&LoadContext->ImageImportDescriptorLen; Status = RtlpImageDirectoryEntryToDataEx(DllEntry->DllBase, 1u, IMAGE_DIRECTORY_ENTRY_IAT, (UINT_PTR*)&LoadContext->ImageImportDescriptorLen, &ImageImportDescriptor); if (!NT_SUCCESS(Status)) ImageImportDescriptor = nullptr; BOOLEAN IsFile = (LoadContext->Flags & SEC_FILE); LoadContext->pImageImportDescriptor = ImageImportDescriptor; if (IsFile) return STATUS_SUCCESS; BOOLEAN JumpOver = FALSE; PIMAGE_NT_HEADERS OutHeaders = nullptr; RtlImageNtHeaderEx(3, DllEntry->DllBase, 0, &OutHeaders); PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigDirectory = LdrImageDirectoryEntryToLoadConfig(DllEntry->DllBase); if (!ImageConfigDirectory || ImageConfigDirectory->Size < 0x94) JumpOver = TRUE; if (!JumpOver) { if ((OutHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF) != 0 && (ImageConfigDirectory->GuardFlags & IMAGE_GUARD_CF_INSTRUMENTED) != 0) { UINT_PTR* GuardCFCheckFunctionPointer = (UINT_PTR*)ImageConfigDirectory->GuardCFCheckFunctionPointer; LoadContext->UnknownFunc = (__int64)GuardCFCheckFunctionPointer; if (GuardCFCheckFunctionPointer) { LoadContext->DllNameLenCompare = *GuardCFCheckFunctionPointer; } } } do { if (!LoadContext->pImageImportDescriptor) { ULONG ImportDirectoryVA = OutHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; PIMAGE_SECTION_HEADER FirstSection = (PIMAGE_SECTION_HEADER)((char*)&OutHeaders->OptionalHeader + OutHeaders->FileHeader.SizeOfOptionalHeader); if (ImportDirectoryVA) { ULONG SectionIdx = 0; if (OutHeaders->FileHeader.NumberOfSections) { ULONG SectionVA = 0; while (TRUE) { SectionVA = FirstSection->VirtualAddress; if (ImportDirectoryVA >= SectionVA && ImportDirectoryVA < SectionVA + FirstSection->SizeOfRawData) break; ++SectionIdx; ++FirstSection; if (SectionIdx >= OutHeaders->FileHeader.NumberOfSections) break; } LoadContext->pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((char*)DllEntry->DllBase + SectionVA); ULONG SectionFA = FirstSection->Misc.PhysicalAddress; *pImageImportDescriptorLen = SectionFA; if (!SectionFA) *pImageImportDescriptorLen = FirstSection->SizeOfRawData; } } } } while (FALSE); PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = LoadContext->pImageImportDescriptor; if (pImageImportDescriptor && *pImageImportDescriptorLen) { UINT_PTR ImageImportDescriptorLen = *pImageImportDescriptorLen; NTSTATUS Status_2 = ZwProtectVirtualMemory((HANDLE)-1, (PVOID*)&pImageImportDescriptor, (PULONG)&ImageImportDescriptorLen, PAGE_READWRITE, (PULONG)&LoadContext->GuardFlags); if (!NT_SUCCESS(Status_2)) return Status_2; PIMAGE_IMPORT_DESCRIPTOR pNextSectionMaybe = pImageImportDescriptor; PIMAGE_IMPORT_DESCRIPTOR pNextImageImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)((char*)pImageImportDescriptor + ImageImportDescriptorLen); do { pNextSectionMaybe = (PIMAGE_IMPORT_DESCRIPTOR)((char*)pNextSectionMaybe + 0x1000); } while (pNextSectionMaybe < pNextImageImportDescriptor); } return STATUS_SUCCESS; } ``` As the function name, prepares the Import Address Table (IAT) for our loaded dll. After this function we go back to LdrpLoadDllInternal because the mapping process is complete. Proceeding with calling LdrpPrepareModuleForExecution.
## LdrpPrepareModuleForExecution ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpPrepareModuleForExecution(PLDR_DATA_TABLE_ENTRY LdrEntry, NTSTATUS* pStatus) { NTSTATUS Status; Status = STATUS_SUCCESS; if (*qword_17E238 == NtCurrentTeb()->ClientId.UniqueThread) return Status; BOOLEAN Skip = FALSE; LDR_DDAG_NODE* DdagNode = LdrEntry->DdagNode; switch (DdagNode->State) { case LdrModulesSnapped: LdrpCondenseGraph(DdagNode); case LdrModulesCondensed: { // This is where we'll start from normally. if ((LdrEntry->FlagGroup[0] & ProcessStaticImport) == 0) { UINT_PTR SubProcessTag = (UINT_PTR)NtCurrentTeb()->SubProcessTag; LdrpAddNodeServiceTag(DdagNode, SubProcessTag); } Status = LdrpNotifyLoadOfGraph(DdagNode); if (NT_SUCCESS(Status)) { Status = LdrpDynamicShimModule(DdagNode); if (!NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x9F3, "LdrpPrepareModuleForExecution", 1u, "Failed to load for appcompat reasons\n"); ) return Status; } Skip = TRUE; } if (!Skip) return Status; } case LdrModulesReadyToInit: LDRP_LOAD_CONTEXT* LoadContext = (LDRP_LOAD_CONTEXT*)LdrEntry->LoadContext; if (LoadContext && (LoadContext->Flags & 1) == 0) { LdrpAcquireLoaderLock(); UINT64 Unknown = 0; Status = fLdrpInitializeGraphRecurse(DdagNode, pStatus, (char*)&Unknown); ULONG64 Unused = 0; LdrpReleaseLoaderLock(Unused, 2, Status); } return Status; } // States end at 9. if (DdagNode->State > LdrModulesReadyToRun) return STATUS_INTERNAL_ERROR; return Status; } ``` Adds a service tag to our module by LdrModulesCondensed, continues by LdrModulesReadyToInit acquiring a Loader lock first then calling LdrpInitializeGraphRecurse.
## LdrpInitializeGraphRecurse ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpInitializeGraphRecurse(LDR_DDAG_NODE* DdagNode, NTSTATUS* pStatus, char* Unknown) { NTSTATUS Status = STATUS_SUCCESS; if (DdagNode->State == LdrModulesInitError) return STATUS_DLL_INIT_FAILED; LDR_DDAG_NODE* DdagNode2 = (LDR_DDAG_NODE*)DdagNode->Dependencies.Tail; CHAR Unknown2_2 = 0; CHAR Unknown2 = 0; BOOLEAN JumpIn = FALSE; do { if (DdagNode2) { LDR_DDAG_NODE* DdagNode2_2 = DdagNode2; do { DdagNode2_2 = (LDR_DDAG_NODE*)DdagNode2_2->Modules.Flink; if ((DdagNode2_2->LoadCount & 1) == 0) { LDR_DDAG_NODE* Blink = (LDR_DDAG_NODE*)DdagNode2_2->Modules.Blink; if (Blink->State == LdrModulesReadyToInit) { Status = fLdrpInitializeGraphRecurse(Blink, pStatus, &Unknown2); if (!NT_SUCCESS(Status)) { JumpIn = TRUE; break; } Unknown2_2 = Unknown2; } else { if (Blink->State == LdrModulesInitError) { Status = STATUS_DLL_INIT_FAILED; { JumpIn = TRUE; break; } } if (Blink->State == LdrModulesInitializing) Unknown2_2 = 1; Unknown2 = Unknown2_2; } } } while (DdagNode2_2 != DdagNode2); if (JumpIn) break; if (Unknown2_2) { LDR_DDAG_NODE* DdagNode3 = (LDR_DDAG_NODE*)DdagNode->Modules.Flink; *Unknown = 1; LDR_SERVICE_TAG_RECORD* ServiceTagList = DdagNode3->ServiceTagList; if (ServiceTagList) { if (pStatus != *(NTSTATUS**)&ServiceTagList[2].ServiceTag) return STATUS_SUCCESS; } } } } while (FALSE); if (!JumpIn) Status = fLdrpInitializeNode(DdagNode); if (JumpIn || !NT_SUCCESS(Status)) DdagNode->State = LdrModulesInitError; return Status; } ``` Does some prior check on the upper area of the function if our DdagNode had dependencies (in our loading case it doesn't so we skip over all the do-while loop), checks for errors and if there are any, sets the state to failed and returns. Otherwise (our case) continues on by calling LdrpInitializeNode.
## LdrpInitializeNode ```cpp NTSTATUS __fastcall LOADLIBRARY::fLdrpInitializeNode(LDR_DDAG_NODE* DdagNode) { NTSTATUS Status; NTSTATUS Status_2; NTSTATUS Status_3; LDR_DDAG_STATE* pState = &DdagNode->State; UNICODE_STRING FullDllName; *(UINT_PTR*)&FullDllName.Length = (UINT_PTR)&DdagNode->State; DdagNode->State = LdrModulesInitializing; LDR_DATA_TABLE_ENTRY* Blink = (LDR_DATA_TABLE_ENTRY*)DdagNode->Modules.Blink; LDR_DATA_TABLE_ENTRY* LdrEntry = *LdrpImageEntry; UINT_PTR** v4 = (UINT_PTR**)*qword_1843B8; while (Blink != (LDR_DATA_TABLE_ENTRY*)DdagNode) { if (&Blink[-1].DdagNode != (LDR_DDAG_NODE**)LdrEntry) { PVOID* p_ParentDllBase = &Blink[-1].ParentDllBase; if (*v4 != qword_1843B0) __fastfail(3u); *p_ParentDllBase = qword_1843B0; Blink[-1].SwitchBackContext = v4; *v4 = (UINT_PTR*)p_ParentDllBase; v4 = (UINT_PTR**)&Blink[-1].ParentDllBase; *qword_1843B8 = (UINT_PTR**)v4; } Blink = (LDR_DATA_TABLE_ENTRY*)Blink->InLoadOrderLinks.Blink; } Status = STATUS_SUCCESS; for (LDR_DATA_TABLE_ENTRY* i = (LDR_DATA_TABLE_ENTRY*)DdagNode->Modules.Blink; i != (LDR_DATA_TABLE_ENTRY*)DdagNode; i = (LDR_DATA_TABLE_ENTRY*)i->InLoadOrderLinks.Blink) { LDR_DATA_TABLE_ENTRY* LdrEntry_2 = (LDR_DATA_TABLE_ENTRY*)((char*)i - 160); if (&i[-1].DdagNode != (LDR_DDAG_NODE**)LdrEntry) { if (LdrEntry_2->LoadReason == LoadReasonPatchImage) { Status_2 = LdrpApplyPatchImage((PLDR_DATA_TABLE_ENTRY)&i[-1].DdagNode); Status = Status_2; if (!NT_SUCCESS(Status_2)) { FullDllName = LdrEntry_2->FullDllName; Status_3 = Status_2; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 1392, "LdrpInitializeNode", 0, "Applying patch \"%wZ\" failed - Status = 0x%x\n", &FullDllName, *(UINT_PTR*)&Status_3); ) break; } } UINT_PTR CurrentDllIniter = *LdrpCurrentDllInitializer; *LdrpCurrentDllInitializer = (UINT_PTR)&i[-1].DdagNode; PVOID EntryPoint = LdrEntry_2->EntryPoint; PUNICODE_STRING pFullDllName = &LdrEntry_2->FullDllName; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 1411, "LdrpInitializeNode", 2u, "Calling init routine %p for DLL \"%wZ\"\n", EntryPoint, &LdrEntry_2->FullDllName); ) RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED StackFrameExtended; StackFrameExtended.Size = 0x48; StackFrameExtended.Format = 1; memset((char*)&StackFrameExtended.Frame.Previous + 4, 0, 48); UINT_PTR v20 = 0; RtlActivateActivationContextUnsafeFast(&StackFrameExtended, LdrEntry_2->EntryPointActivationContext); if (LdrEntry_2->TlsIndex) fLdrpCallTlsInitializers(1i64, (LDR_DATA_TABLE_ENTRY*)&i[-1].DdagNode); BOOLEAN CallSuccess = TRUE; if (EntryPoint) { LPVOID ContextRecord = nullptr; if ((LdrEntry_2->FlagGroup[0] & ProcessStaticImport) != 0) ContextRecord = *LdrpProcessInitContextRecord; CallSuccess = fLdrpCallInitRoutine((BOOL(__stdcall*)(HINSTANCE, DWORD, LPVOID))EntryPoint, LdrEntry_2->DllBase, DLL_PROCESS_ATTACH, ContextRecord); } RtlDeactivateActivationContextUnsafeFast(&StackFrameExtended); *LdrpCurrentDllInitializer = CurrentDllIniter; LdrEntry_2->Flags |= ProcessAttachCalled; if (!CallSuccess) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x5B7, "LdrpInitializeNode", 0, "Init routine %p for DLL \"%wZ\" failed during DLL_PROCESS_ATTACH\n", EntryPoint, pFullDllName); ) Status = STATUS_DLL_INIT_FAILED; LdrEntry_2->Flags |= ProcessAttachFailed; break; } WID_HIDDEN( LdrpLogDllState((UINT_PTR)LdrEntry_2->DllBase, pFullDllName, 0x14AEu); ) LdrEntry = *LdrpImageEntry; } } *pState = Status != 0 ? LdrModulesInitError : LdrModulesReadyToRun; return Status; } ``` Sets the state to initializing, goes on by checking if it's purpose is to patch the image (not in our case), if it is, it patches the image by calling LdrpApplyPatchImage, if it's not it goes on by calling LdrpCallTlsInitializers which is self explanatory and finally it calls LdrpCallInitRoutine.
## LdrpCallInitRoutine ```cpp BOOLEAN __fastcall LOADLIBRARY::fLdrpCallInitRoutine(BOOL(__fastcall* DllMain)(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved), PIMAGE_DOS_HEADER DllBase, unsigned int One, LPVOID ContextRecord) { BOOLEAN ReturnVal = TRUE; PCHAR LoggingVar = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR LoggingVar2 = 0; if (RtlGetCurrentServiceSessionId()) LoggingVar2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; else LoggingVar2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR LoggingVar3 = 0; PCHAR LoggingVar4 = 0; if (*LoggingVar2 && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { LoggingVar3 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; if (RtlGetCurrentServiceSessionId()) LoggingVar4 = (char*)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; else LoggingVar4 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; // 0x20 is SPACE char. if ((*LoggingVar4 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x14A3u, (ULONGLONG)DllBase, 0xFF, 0xFF); ) } else { LoggingVar3 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; } // DLL_PROCESS_ATTACH (1) ReturnVal = DllMain((HINSTANCE)DllBase, One, ContextRecord); if (RtlGetCurrentServiceSessionId()) LoggingVar = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; if (*LoggingVar && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { if (RtlGetCurrentServiceSessionId()) LoggingVar3 = (char*)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; // 0x20 is SPACE char. if ((*LoggingVar3 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1496u, (ULONGLONG)DllBase, 0xFF, 0xFF); ) } ULONG LoggingVar5 = 0; if (!ReturnVal && One == 1) { LoggingVar5 = 1; WID_HIDDEN( LdrpLogError(STATUS_DLL_INIT_FAILED, 0x1496u, LoggingVar5, 0i64); ) } return ReturnVal; } ``` Does prior checks and calls DllMain which finishes the loading process. ================================================ FILE: Src/Functions/KERNEL32.cpp ================================================ #include "KERNEL32.h" ULONG* KernelBaseGlobalData = nullptr; tBasep8BitStringToDynamicUnicodeString Basep8BitStringToDynamicUnicodeString = nullptr; tBaseSetLastNTError BaseSetLastNTError = nullptr; // Signatured tBasepLoadLibraryAsDataFileInternal BasepLoadLibraryAsDataFileInternal = nullptr; ================================================ FILE: Src/Functions/KERNEL32.h ================================================ #pragma once #include "..\Includes.h" #include "Undocumented.h" extern ULONG* KernelBaseGlobalData; typedef BOOLEAN(WINAPI* tBasep8BitStringToDynamicUnicodeString)(PUNICODE_STRING pConvertedStr, LPCSTR pszAnsiStr); extern tBasep8BitStringToDynamicUnicodeString Basep8BitStringToDynamicUnicodeString; typedef DWORD(WINAPI* tBaseSetLastNTError)(IN NTSTATUS Status); extern tBaseSetLastNTError BaseSetLastNTError; // Signatured #define BASEP_LLASDATAFILE_INTERNAL_PATTERN "\x48\x89\x5C\x24\x20\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x10\xFF\xFF\xFF" typedef NTSTATUS(__fastcall* tBasepLoadLibraryAsDataFileInternal)(PUNICODE_STRING DllName, PWSTR Path, PWSTR Unknown, DWORD dwFlags, HMODULE* pBaseOfLoadedModule); extern tBasepLoadLibraryAsDataFileInternal BasepLoadLibraryAsDataFileInternal; ================================================ FILE: Src/Functions/NT.cpp ================================================ #include "NT.h" // Implemented. // Variables DWORD* LdrpPolicyBits = nullptr; HANDLE* LdrpMainThreadToken = nullptr; DWORD* LdrInitState = nullptr; DWORD* LoadFailure = nullptr; PRTL_CRITICAL_SECTION LdrpWorkQueueLock = nullptr; DWORD* LdrpWorkInProgress = nullptr; LIST_ENTRY** LdrpWorkQueue = nullptr; PHANDLE LdrpWorkCompleteEvent = nullptr; KUSER_SHARED_DATA* kUserSharedData = (KUSER_SHARED_DATA*)0x7FFE0000; DWORD* LdrpUseImpersonatedDeviceMap = nullptr; DWORD* LdrpAuditIntegrityContinuity = nullptr; DWORD* LdrpEnforceIntegrityContinuity = nullptr; DWORD* LdrpFatalHardErrorCount = nullptr; DWORD* UseWOW64 = nullptr; PRTL_SRWLOCK LdrpModuleDatatableLock = nullptr; PHANDLE qword_17E238 = nullptr; LDR_DATA_TABLE_ENTRY** LdrpImageEntry = nullptr; PUNICODE_STRING LdrpKernel32DllName = nullptr; UINT_PTR* LdrpAppHeaders = nullptr; PHANDLE LdrpLargePageDllKeyHandle = nullptr; ULONG** LdrpLockMemoryPrivilege = nullptr; ULONG64* LdrpMaximumUserModeAddress = nullptr; UINT_PTR* LdrpMapAndSnapWork = nullptr; LIST_ENTRY* LdrpHashTable = nullptr; PVOID* LdrpHeap = nullptr; BOOLEAN* LdrpIsHotPatchingEnabled = nullptr; LDR_DATA_TABLE_ENTRY** LdrpRedirectionModule = nullptr; ULONG64** qword_1993A8 = nullptr; LONG* NtdllBaseTag = nullptr; FUNCTION_TABLE_DATA* stru_199520 = nullptr; UINT_PTR* qword_199530 = nullptr; LDR_DATA_TABLE_ENTRY** LdrpNtDllDataTableEntry = nullptr; UINT_PTR* qword_1993B8 = nullptr; DWORD* dword_19939C = nullptr; DWORD* LoadFailureOperational = nullptr; DWORD* dword_199398 = nullptr; UINT_PTR*** qword_1843B8 = nullptr; UINT_PTR* qword_1843B0 = nullptr; UINT_PTR* LdrpCurrentDllInitializer = nullptr; LPVOID** LdrpProcessInitContextRecord = nullptr; PRTL_SRWLOCK LdrpTlsLock = nullptr; TLS_ENTRY** LdrpTlsList = nullptr; tLdrpManifestProberRoutine LdrpManifestProberRoutine = nullptr; tLdrpRedirectionCalloutFunc LdrpRedirectionCalloutFunc = nullptr; // Functions PEB* NtCurrentPeb() { return NtCurrentTeb()->ProcessEnvironmentBlock; } VOID __fastcall NtdllpFreeStringRoutine(PWCH Buffer) // CHECKED. { RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Buffer); } NTSTATUS __fastcall LdrpFastpthReloadedDll(PUNICODE_STRING FullPath, ULONG Flags, PLDR_DATA_TABLE_ENTRY LdrEntry, LDR_DATA_TABLE_ENTRY** DllEntry) { NTSTATUS Status; PUNICODE_STRING PathUsed; LDR_DATA_TABLE_ENTRY* pDllEntry; LDR_DDAG_STATE DdagState; DdagState = LdrModulesPlaceHolder; Status = STATUS_NOT_FOUND; if (Flags & LOAD_LIBRARY_AS_IMAGE_RESOURCE) { PathUsed = FullPath; FullPath = 0; } else { // If an absolute path was sent from LoadLibrary it will have 0x200 (LOAD_LIBRARY_SEARCH_APPLICATION_DIR), but the if is checking for not so it can be ignored. if ((Flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) == 0) return Status; PathUsed = nullptr; } Status = LdrpFindLoadedDllByName(PathUsed, FullPath, Flags, DllEntry, &DdagState); if (NT_SUCCESS(Status)) { pDllEntry = *DllEntry; if (pDllEntry->LoadReason == LoadReasonPatchImage) { Status = STATUS_IMAGE_LOADED_AS_PATCH_IMAGE; LdrpLogEtwHotPatchStatus(&(*LdrpImageEntry)->BaseDllName, pDllEntry, 0, STATUS_IMAGE_LOADED_AS_PATCH_IMAGE, 2u); } else { Status = STATUS_NOT_FOUND; if (DdagState == LdrModulesReadyToRun) { Status = LdrpIncrementModuleLoadCount(pDllEntry); if (NT_SUCCESS(Status)) { Status = LdrpBuildForwarderLink(LdrEntry, pDllEntry); // This is where we most likely end up on a normal call from LoadLibraryExW if (NT_SUCCESS(Status)) return Status; BOOLEAN IsWorkerThread = (!(NtCurrentTeb()->SameTebFlags & LoadOwner)); if (IsWorkerThread) LdrpDrainWorkQueue(WaitLoadComplete); LdrpDecrementModuleLoadCountEx(pDllEntry, 0); if (IsWorkerThread) LdrpDropLastInProgressCount(); } } } LdrpDereferenceModule(*DllEntry); *DllEntry = nullptr; } return Status; } NTSTATUS __fastcall LdrpIncrementModuleLoadCount(LDR_DATA_TABLE_ENTRY* LdrEntry) { NTSTATUS Status = STATUS_SUCCESS; RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); LDR_DDAG_NODE* DdagNode = LdrEntry->DdagNode; ULONG LoadCount = DdagNode->LoadCount; if (LoadCount != -1) { if (LoadCount) { DdagNode->LoadCount = LoadCount + 1; } else if (NtCurrentTeb()->SameTebFlags & LoadOwner) { ++DdagNode->LoadWhileUnloadingCount; } else { Status = STATUS_DLL_NOT_FOUND; } } RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); return Status; } VOID __fastcall RtlFreeUnicodeString(PUNICODE_STRING UnicodeString) // CHECKED. { WCHAR* Buffer; Buffer = UnicodeString->Buffer; if (Buffer) { NtdllpFreeStringRoutine(Buffer); //*UnicodeString = 0; memset(UnicodeString, 0, sizeof(UNICODE_STRING)); } } VOID __fastcall LdrpFreeUnicodeString(PUNICODE_STRING String) { WCHAR* Buffer; Buffer = String->Buffer; if (Buffer) { NtdllpFreeStringRoutine(Buffer); String->Buffer = 0; } String->Length = 0; String->MaximumLength = 0; } ULONG __fastcall RtlGetCurrentServiceSessionId(VOID) // CHECKED ? { LPVOID Return = NtCurrentPeb()->SharedData; if (Return) Return = (LPVOID)(*(DWORD*)Return); return (ULONG)Return; } USHORT __fastcall LdrpGetBaseNameFromFullName(PUNICODE_STRING BaseName, PUNICODE_STRING FullName) { USHORT StrLen = BaseName->Length >> 1; if (StrLen) { PWCHAR Buffer = BaseName->Buffer; do { if (Buffer[StrLen - 1] == '\\') break; if (Buffer[StrLen - 1] == '/') break; --StrLen; } while (StrLen); } USHORT ByteLen = 2 * StrLen; USHORT Return = BaseName->MaximumLength - ByteLen; FullName->Length = BaseName->Length - ByteLen; FullName->MaximumLength = Return; FullName->Buffer = &BaseName->Buffer[StrLen]; return Return; } PWCHAR __fastcall RtlGetNtSystemRoot() { if (RtlGetCurrentServiceSessionId()) return (PWCHAR)((char*)NtCurrentPeb()->SharedData + 30); else return kUserSharedData->NtSystemRoot; } BOOLEAN __fastcall LdrpHpatAllocationOptOut(PUNICODE_STRING FullDllName) { UNICODE_STRING NtString; // [rsp+30h] [rbp-18h] BYREF if ((NtCurrentPeb()->ProcessParameters->Flags & 0x2000000) == 0 || *FullDllName->Buffer == '\\') return 0; PWSTR NtSystemRoot = RtlGetNtSystemRoot(); RtlInitUnicodeStringEx(&NtString, NtSystemRoot); return FullDllName->Length < NtString.Length || RtlCompareUnicodeStrings(FullDllName->Buffer, NtString.Length >> 1, NtString.Buffer, NtString.Length >> 1, 1u) != 0; } NTSTATUS __fastcall LdrpCorValidateImage(PIMAGE_DOS_HEADER DosHeader) { NTSTATUS Status; PIMAGE_FILE_HEADER ImageFileHeader; UINT_PTR LastRVASection; Status = RtlpImageDirectoryEntryToDataEx(DosHeader, TRUE, IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_LOCAL_SYMS_STRIPPED, &LastRVASection, (PIMAGE_FILE_HEADER*)&ImageFileHeader); if (!NT_SUCCESS(Status)) ImageFileHeader = 0; return ImageFileHeader != 0 ? STATUS_INVALID_IMAGE_FORMAT : 0; } NTSTATUS __fastcall LdrpCorFixupImage(PIMAGE_DOS_HEADER DosHeader) { NTSTATUS Status; PIMAGE_NT_HEADERS NtHeader = RtlImageNtHeader(DosHeader); ULONG64 LastRVASection; PIMAGE_COR20_HEADER CorHeader = nullptr; Status = RtlpImageDirectoryEntryToDataEx(DosHeader, 1, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &LastRVASection, &CorHeader); if (!NT_SUCCESS(Status) || !CorHeader) return Status; if (NtHeader->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC && NtHeader->FileHeader.Machine == IMAGE_FILE_MACHINE_I386 && (CorHeader->Flags & 2) == 0) { ULONG64* pSizeOfHeapCommit = &NtHeader->OptionalHeader.SizeOfHeapCommit; PBYTE UnknownCalc = (PBYTE)&NtHeader->OptionalHeader + (32 * NtHeader->FileHeader.NumberOfSections) + (8 * NtHeader->FileHeader.NumberOfSections) + NtHeader->FileHeader.SizeOfOptionalHeader; UINT_PTR NumberOfBytesToProtect = 0x1000; if ((unsigned __int64)(UnknownCalc - (PBYTE)DosHeader + 0x10) <= 0x1000) { ULONG OldAccessProtection; Status = ZwProtectVirtualMemory((HANDLE)-1, (PVOID*)&DosHeader, (PULONG)&NumberOfBytesToProtect, PAGE_READWRITE, &OldAccessProtection); if (NT_SUCCESS(Status)) { memmove(NtHeader->OptionalHeader.DataDirectory, &NtHeader->OptionalHeader.SizeOfHeapCommit, UnknownCalc - (PBYTE)pSizeOfHeapCommit); *(ULONG64*)&NtHeader->OptionalHeader.LoaderFlags = NtHeader->OptionalHeader.SizeOfHeapReserve; *pSizeOfHeapCommit = (NtHeader->OptionalHeader.SizeOfStackCommit) & 0xFFFFFFFF00000000; NtHeader->OptionalHeader.SizeOfHeapReserve = (NtHeader->OptionalHeader.SizeOfStackCommit) & UINT_MAX; NtHeader->OptionalHeader.SizeOfStackCommit = (NtHeader->OptionalHeader.SizeOfStackReserve) & 0xFFFFFFFF00000000; NtHeader->OptionalHeader.SizeOfStackReserve = (NtHeader->OptionalHeader.SizeOfStackReserve) & UINT_MAX; NtHeader->OptionalHeader.ImageBase = (NtHeader->OptionalHeader.ImageBase) & 0xFFFFFFFF00000000; NtHeader->FileHeader.SizeOfOptionalHeader += 0x10; NtHeader->OptionalHeader.Magic = IMAGE_NT_OPTIONAL_HDR64_MAGIC; ZwProtectVirtualMemory((HANDLE)-1, (PVOID*)&DosHeader, (PULONG)&NumberOfBytesToProtect, OldAccessProtection, &OldAccessProtection); } } else { return STATUS_INVALID_IMAGE_FORMAT; } } else { WORD Machine = NtHeader->FileHeader.Machine; if (Machine < kUserSharedData->ImageNumberLow) return STATUS_INVALID_IMAGE_FORMAT; Status = STATUS_SUCCESS; if (Machine > kUserSharedData->ImageNumberHigh) return STATUS_INVALID_IMAGE_FORMAT; } return Status; } NTSTATUS __fastcall LdrpFindLoadedDllByNameLockHeld(PUNICODE_STRING BaseDllName, PUNICODE_STRING FullDllName, ULONG64 Flags, LDR_DATA_TABLE_ENTRY** pLdrEntry, ULONG BaseNameHashValue) { LIST_ENTRY* pHashIdx; LDR_DDAG_NODE* DdagNode; // Parse entire hash table. Maybe I use it later on. //for (int idx = 0; idx < 32; idx++) //{ // LIST_ENTRY* IdxHead = &LdrpHashTable[idx]; // LIST_ENTRY* IdxEntry = IdxHead->Flink; // while (IdxEntry != IdxHead) // { // LDR_DATA_TABLE_ENTRY* IdxLdrEntry = CONTAINING_RECORD(IdxEntry, LDR_DATA_TABLE_ENTRY, HashLinks); // // printf("[Name: %ws]\n", IdxLdrEntry->BaseDllName.Buffer); // // LIST_ENTRY* LdrHead = &IdxLdrEntry->InLoadOrderLinks; // LIST_ENTRY* LdrEntry = LdrHead->Flink; // while (LdrEntry != LdrHead) // { // LDR_DATA_TABLE_ENTRY* IdxLdrEntryMod = CONTAINING_RECORD(LdrEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); // // printf(" -> [Name: %ws]\n", IdxLdrEntryMod->BaseDllName.Buffer); // // LdrEntry = LdrEntry->Flink; // } // // IdxEntry = IdxEntry->Flink; // } //} pHashIdx = (LIST_ENTRY*)&(LdrpHashTable)[(BaseNameHashValue & 0x1F)]; BOOLEAN DllFound = FALSE; for (LIST_ENTRY* HashEntry = pHashIdx->Flink; HashEntry != pHashIdx; HashEntry = HashEntry->Flink) { LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)&HashEntry[-7]; //LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(HashEntry, LDR_DATA_TABLE_ENTRY, HashLinks); //LDR_DATA_TABLE_ENTRY* DllEntry = (PLDR_DATA_TABLE_ENTRY)CONTAINING_RECORD(HashEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (BaseNameHashValue == (DllEntry->BaseNameHashValue) && ((Flags & 8) == 0 || (DllEntry->FlagGroup[0] & 1) != 0)) { if (FullDllName) { DllFound = RtlEqualUnicodeString(FullDllName, &DllEntry->FullDllName, TRUE); if (DllFound) goto DLL_FOUND; } else { if ((DllEntry->Flags & Redirected) == 0 && RtlEqualUnicodeString(BaseDllName, &DllEntry->BaseDllName, TRUE)) { DllFound = TRUE; DLL_FOUND: DdagNode = DllEntry->DdagNode; if (DdagNode->LoadCount != -1 && ((__int64)DdagNode->Modules.Flink[-4].Blink & 0x20) == 0) _InterlockedIncrement(&DllEntry->ReferenceCount); *pLdrEntry = DllEntry; return DllFound ? STATUS_SUCCESS : STATUS_DLL_NOT_FOUND; } DllFound = FALSE; } } } return DllFound ? STATUS_SUCCESS : STATUS_DLL_NOT_FOUND; } BOOLEAN __fastcall LdrpIsILOnlyImage(PIMAGE_DOS_HEADER DllBase) { NTSTATUS Status; UINT_PTR LastRVASection; PIMAGE_COR20_HEADER CorHeader; Status = RtlpImageDirectoryEntryToDataEx(DllBase, 1u, 0xEu, &LastRVASection, (PVOID*)&CorHeader); if (Status < 0) return Status; return CorHeader && LastRVASection >= 0x48 && (CorHeader->Flags & 1) != 0; } VOID __fastcall LdrpAddNodeServiceTag(LDR_DDAG_NODE* DdagNode, UINT_PTR ServiceTag) { //LDR_DATA_TABLE_ENTRY* LdrEntry = CONTAINING_RECORD(DdagNode->Modules.Flink, LDR_DATA_TABLE_ENTRY, DdagNode); if (DdagNode->LoadCount != -1 && ((__int64)DdagNode->Modules.Flink[-4].Blink & 0x20) == 0) //if (DdagNode->LoadCount != -1 && (LdrEntry->FlagGroup[0] & 0x20) == 0) { for (LDR_SERVICE_TAG_RECORD* i = DdagNode->ServiceTagList; i; i = i->Next) { if (i->ServiceTag == ServiceTag) return; } LDR_SERVICE_TAG_RECORD* Heap = (LDR_SERVICE_TAG_RECORD*)RtlAllocateHeap(*LdrpHeap, 0, 0x10); if (Heap) { Heap->ServiceTag = ServiceTag; Heap->Next = DdagNode->ServiceTagList; DdagNode->ServiceTagList = Heap; SINGLE_LIST_ENTRY* Tail = DdagNode->Dependencies.Tail; if (Tail) { SINGLE_LIST_ENTRY* Tail_2 = Tail; do { Tail_2 = Tail_2->Next; // LDR_DDAG_NODE* NextNode = CONTAINING_RECORD(Tail_2, LDR_DDAG_NODE, CondenseLink); LdrpAddNodeServiceTag((LDR_DDAG_NODE*)Tail_2[1].Next, ServiceTag); //LdrpAddNodeServiceTag(NextNode, ServiceTag); } while (Tail_2 != Tail); } } } } PIMAGE_LOAD_CONFIG_DIRECTORY LdrImageDirectoryEntryToLoadConfig(PIMAGE_DOS_HEADER DllBase) { NTSTATUS Status = STATUS_SUCCESS; PIMAGE_NT_HEADERS OutHeaders = nullptr; RtlImageNtHeaderEx(1u, DllBase, 0, &OutHeaders); if (!DllBase) return nullptr; UINT_PTR LastRVASection = 0; PIMAGE_LOAD_CONFIG_DIRECTORY LoadConfigDirectory = nullptr; Status = RtlpImageDirectoryEntryToDataEx(DllBase, 1u, 0xAu, &LastRVASection, (PVOID*)&LoadConfigDirectory); if (!NT_SUCCESS(Status)) return nullptr; if (LoadConfigDirectory && (DWORD)LastRVASection && (DWORD)LastRVASection == LoadConfigDirectory->Size && OutHeaders->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64) return LoadConfigDirectory; return nullptr; } BOOLEAN __fastcall LdrpShouldModuleImportBeRedirected(LDR_DATA_TABLE_ENTRY* DllEntry) { if (!DllEntry || !*LdrpRedirectionModule || *LdrpRedirectionModule == DllEntry) return FALSE; if ((NtCurrentPeb()->BitField & IsPackagedProcess) != 0) return DllEntry->FlagGroup[0] & PackagedBinary; // LdrpRedirectionCalloutFunc is a function pointer. if (*LdrpRedirectionCalloutFunc) return (*LdrpRedirectionCalloutFunc)(DllEntry->FullDllName.Buffer); else return TRUE; } PIMAGE_IMPORT_DESCRIPTOR __fastcall LdrpGetImportDescriptorForSnap(LDRP_LOAD_CONTEXT* LoadContext) { NTSTATUS Status; // [CORRECT] //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); UINT_PTR LastRVASection; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor; Status = RtlpImageDirectoryEntryToDataEx(DllEntry->DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_IMPORT, &LastRVASection, (PVOID*)&pImageImportDescriptor); if (!NT_SUCCESS(Status)) return nullptr; if (DllEntry == *LdrpImageEntry && (((ULONG64)(*qword_1993A8) >> 44) & 3) == 1) { PIMAGE_NT_HEADERS pImageNtHeaders = nullptr; RtlImageNtHeaderEx(3, DllEntry->DllBase, 0, (PIMAGE_NT_HEADERS*)&pImageNtHeaders); if (!((LdrpCheckPagesForTampering(&pImageNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT], 8) || LdrpCheckPagesForTampering((PIMAGE_DATA_DIRECTORY)pImageImportDescriptor, (ULONG)LastRVASection)) && NT_SUCCESS(LdrpMapCleanModuleView(LoadContext)))) { return nullptr; } } return pImageImportDescriptor; } NTSTATUS __fastcall LdrpMapCleanModuleView(LDRP_LOAD_CONTEXT* LoadContext) { NTSTATUS Status; HANDLE ProcessInformation = 0; PIMAGE_DOS_HEADER ImageDosHeader = nullptr; ULONG64 ViewSize = 0; if (CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks) != *LdrpImageEntry) return STATUS_NOT_SUPPORTED; Status = NtQueryInformationProcess((HANDLE)-1, ProcessImageSection, &ProcessInformation, 8, 0); if (NT_SUCCESS(Status)) { Status = ZwMapViewOfSection(ProcessInformation, (HANDLE)-1u, &ImageDosHeader, 0, 0, 0, (PULONG)&ViewSize, ViewShare, 0x40000u, 2u); if (NT_SUCCESS(Status)) LoadContext->ImageBase = ImageDosHeader; NtClose(ProcessInformation); } return Status; } LDR_DATA_TABLE_ENTRY* __fastcall LdrpHandleReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry) { LDR_DATA_TABLE_ENTRY* DllEntry = LdrEntry; if (LdrEntry) { LDRP_LOAD_CONTEXT* LoadContext = (LDRP_LOAD_CONTEXT*)LdrEntry->LoadContext; if (LoadContext) { if ((LoadContext->Flags & 0x80000) == 0 && (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink != LdrEntry) { DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LoadContext->WorkQueueListEntry.Flink = &LdrEntry->InLoadOrderLinks; } } } return DllEntry; } NTSTATUS __fastcall LdrpFreeReplacedModule(LDR_DATA_TABLE_ENTRY* LdrDataTableEntry) { LdrpFreeLoadContext(LdrDataTableEntry->LoadContext); // Revokes ProcessStaticImport (0x20) flag. LdrDataTableEntry->Flags &= ~ProcessStaticImport; LdrDataTableEntry->ReferenceCount = 1; return LdrpDereferenceModule(LdrDataTableEntry); } VOID __fastcall LdrpHandlePendingModuleReplaced(LDRP_LOAD_CONTEXT* LoadContext) { LDR_DATA_TABLE_ENTRY* Entry = (LDR_DATA_TABLE_ENTRY*)LoadContext->pvImports; if (Entry) { LDR_DATA_TABLE_ENTRY* ReturnEntry = LdrpHandleReplacedModule(Entry); LDR_DATA_TABLE_ENTRY** CompareEntry = LoadContext->pvImports; if (ReturnEntry != (LDR_DATA_TABLE_ENTRY*)CompareEntry) LdrpFreeReplacedModule((LDR_DATA_TABLE_ENTRY*)CompareEntry); LoadContext->pvImports = nullptr; } } PIMAGE_SECTION_HEADER __fastcall RtlSectionTableFromVirtualAddress(PIMAGE_NT_HEADERS NtHeader, PVOID Base, UINT_PTR Address) { PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((char*)&NtHeader->OptionalHeader + NtHeader->FileHeader.SizeOfOptionalHeader); if (!NtHeader->FileHeader.NumberOfSections) return nullptr; ULONG NumberOfSections = NtHeader->FileHeader.NumberOfSections; ULONG SectionIdx = 0; while (TRUE) { ULONG VirtualAddress = SectionHeader->VirtualAddress; if ((unsigned int)Address >= VirtualAddress && (unsigned int)Address < SectionHeader->SizeOfRawData + VirtualAddress) break; ++SectionHeader; if (++SectionIdx >= NumberOfSections) return nullptr; } return SectionHeader; } PIMAGE_SECTION_HEADER __fastcall RtlAddressInSectionTable(PIMAGE_NT_HEADERS NtHeader, PVOID Base, UINT_PTR Address) { PIMAGE_SECTION_HEADER SectionHeader; SectionHeader = RtlSectionTableFromVirtualAddress(NtHeader, Base, Address); if (SectionHeader) return (PIMAGE_SECTION_HEADER)(SectionHeader->PointerToRawData - SectionHeader->VirtualAddress); return SectionHeader; } BOOLEAN __fastcall LdrpValidateEntrySection(LDR_DATA_TABLE_ENTRY* DllEntry) { PIMAGE_NT_HEADERS OutHeaders; RtlImageNtHeaderEx(3u, DllEntry->DllBase, 0, &OutHeaders); ULONG AddressOfEntryPoint = OutHeaders->OptionalHeader.AddressOfEntryPoint; return !AddressOfEntryPoint || !DllEntry->EntryPoint || AddressOfEntryPoint >= OutHeaders->OptionalHeader.SizeOfHeaders; } BOOL __fastcall LdrpIsExecutableRelocatedImage(PIMAGE_DOS_HEADER DllBase) { MEMORY_IMAGE_INFORMATION MemoryInformation; // [rsp+30h] [rbp-28h] BYREF PIMAGE_NT_HEADERS OutHeaders; // [rsp+68h] [rbp+10h] BYREF return NT_SUCCESS(RtlImageNtHeaderEx(3u, DllBase, 0i64, &OutHeaders)) && (PIMAGE_DOS_HEADER)OutHeaders->OptionalHeader.ImageBase == DllBase && NT_SUCCESS(ZwQueryVirtualMemory((HANDLE)-1, DllBase, MemoryImageInformation, &MemoryInformation, 0x18, 0)) && MemoryInformation.ImageBase == DllBase && (MemoryInformation.ImageFlags & 2) == 0 && (MemoryInformation.ImageFlags & 1) == 0; } TLS_ENTRY* __fastcall LdrpFindTlsEntry(LDR_DATA_TABLE_ENTRY* LdrEntry) { TLS_ENTRY* TlsEntry; for (TlsEntry = *LdrpTlsList; TlsEntry != (TLS_ENTRY*)LdrpTlsList; TlsEntry = (TLS_ENTRY*)TlsEntry->TlsEntry.Flink) { if ((LDR_DATA_TABLE_ENTRY*)TlsEntry->ModuleEntry == LdrEntry) return TlsEntry; } return nullptr; } BOOL __fastcall ImageTlsCallbackCaller(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved) { ((void(__fastcall*)(HINSTANCE, DWORD, LPVOID))lpvReserved)(hInstDll, fdwReason, 0); return 1; } // Implemented inside LOADLIBRARY class to use WID_HIDDEN NTSTATUS __fastcall WID::Loader::LOADLIBRARY::LdrpThreadTokenSetMainThreadToken() // CHECKED. { NTSTATUS Status; HANDLE ReturnToken = NULL; Status = NtOpenThreadToken((HANDLE)-2, 0x2001C, 0, &ReturnToken); *LdrpMainThreadToken = ReturnToken; if (Status != STATUS_NO_TOKEN) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0xDC8, "LdrpThreadTokenSetMainThreadToken", 2, "Status: 0x%x\n", Status); ) } return Status; } NTSTATUS __fastcall WID::Loader::LOADLIBRARY::LdrpThreadTokenUnsetMainThreadToken() // CHECKED. { NTSTATUS Status; Status = NtClose(*LdrpMainThreadToken); *LdrpMainThreadToken = NULL; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0xDEE, "LdrpThreadTokenUnsetMainThreadToken", 2u, "Status: 0x%x\n", Status); ) return Status; } LDR_DATA_TABLE_ENTRY* __fastcall WID::Loader::LOADLIBRARY::LdrpHandleReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry) // CHECKED. { LDR_DATA_TABLE_ENTRY* DllEntry = LdrEntry; if (LdrEntry) { LDRP_LOAD_CONTEXT* LoadContext = LdrEntry->LoadContext; if (LoadContext) { DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); //if ((LoadContext->Flags & SEC_64K_PAGES) == 0 && (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink != LdrEntry) if ((LoadContext->Flags & SEC_64K_PAGES) == 0 && DllEntry != LdrEntry) { //DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LoadContext->WorkQueueListEntry.Flink = &LdrEntry->InLoadOrderLinks; } } } return DllEntry; } NTSTATUS __fastcall WID::Loader::LOADLIBRARY::LdrpFreeReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry) // CHECKED. { LdrpFreeLoadContext(LdrEntry->LoadContext); // Resets (sets to 0) flag ProcessStaticImport (0x20) LdrEntry->Flags &= ~0x20u; // Might change if hidden, not touching for now. LdrEntry->ReferenceCount = 1; return LdrpDereferenceModule(LdrEntry); } NTSTATUS __fastcall WID::Loader::LOADLIBRARY::LdrpResolveDllName(LDRP_LOAD_CONTEXT* LoadContext, LDRP_FILENAME_BUFFER* FileNameBuffer, PUNICODE_STRING BaseDllName, PUNICODE_STRING FullDllName, DWORD Flags) // CHECKED. { NTSTATUS Status; PWCHAR FileName; UNICODE_STRING DllName; BOOLEAN FileNamesNotEqual = FALSE; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x6B9, "LdrpResolveDllName", 3u, "DLL name: %wZ\n", LoadContext); ) // Converted goto to do-while loop. do { // This if will go in if call stack starts back from LoadLibraryExW with an absolute path. if (Flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) { DllName = LoadContext->BaseDllName; } else { Status = LdrpGetFullPath(LoadContext, &FileNameBuffer->pFileName); if (!NT_SUCCESS(Status)) { if (FileNamesNotEqual) LdrpFreeUnicodeString(&DllName); WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x742, "LdrpResolveDllName", 4, "Status: 0x%08lx\n", Status); ) return Status; } FileName = FileNameBuffer->FileName; DllName = FileNameBuffer->pFileName; FileNamesNotEqual = (FileNameBuffer->FileName != FileNameBuffer->pFileName.Buffer); if (FileNamesNotEqual) { FileNameBuffer->pFileName.Buffer = FileName; FileNameBuffer->pFileName.MaximumLength = MAX_PATH - 4; *FileName = 0; break; } } USHORT Length = DllName.Length; PWCHAR Buffer = DllName.Buffer; Status = LdrpAllocateUnicodeString(&DllName, DllName.Length); if (!NT_SUCCESS(Status)) { if (FileNamesNotEqual) LdrpFreeUnicodeString(&DllName); WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x742, "LdrpResolveDllName", 4, "Status: 0x%08lx\n", Status); ) return Status; } FileNamesNotEqual = TRUE; memmove(DllName.Buffer, Buffer, Length + 2); DllName.Length = Length; } while (FALSE); FileNameBuffer->pFileName.Length = 0; if (Flags & 0x10000000) Status = LdrpAppendUnicodeStringToFilenameBuffer(&FileNameBuffer->pFileName, LoadContext); else Status = LdrpGetNtPathFromDosPath(&DllName, FileNameBuffer); if (NT_SUCCESS(Status)) { *FullDllName = DllName; LdrpGetBaseNameFromFullName(&DllName, BaseDllName); WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x742, "LdrpResolveDllName", 4, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS StatusAdded = (Status + 0x3FFFFFF1); //LONGLONG BitTestVar = 0x1C3000000011; LONGLONG BitTestVar = 0b0001'1100'0011'0000'0000'0000'0000'0000'0000'0000'0001'0001; if (StatusAdded <= 0x2C && (_bittest64(&BitTestVar, StatusAdded)) || Status == STATUS_DEVICE_OFF_LINE || Status == STATUS_DEVICE_NOT_READY) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x72D, "LdrpResolveDllName", 2, "Original status: 0x%08lx\n", Status); ) Status = STATUS_DLL_NOT_FOUND; } if (FileNamesNotEqual) LdrpFreeUnicodeString(&DllName); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x742, "LdrpResolveDllName", 4, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall WID::Loader::LOADLIBRARY::LdrpFindDllActivationContext(LDR_DATA_TABLE_ENTRY* LdrEntry) // CHECKED. { NTSTATUS Status = STATUS_SUCCESS; if (*(UINT_PTR*)(*LdrpManifestProberRoutine)) { PEB* PEB = NtCurrentPeb(); if (LdrEntry != *LdrpImageEntry || !PEB->ActivationContextData) { PWCHAR Buffer = LdrEntry->FullDllName.Buffer; if (LdrEntry == *LdrpImageEntry && *Buffer == '\\' && Buffer[1] == '?' && Buffer[2] == '?' && Buffer[3] == '\\' && Buffer[4] && Buffer[5] == ':' && Buffer[6] == '\\') { Buffer += 4; } // LdrpManifestProberRoutine is a function pointer. ACTIVATION_CONTEXT* pActivationCtx = nullptr; Status = (*LdrpManifestProberRoutine)(LdrEntry->DllBase, Buffer, &pActivationCtx); if ((unsigned int)(Status + 0x3FFFFF77) <= 2 || Status == STATUS_NOT_SUPPORTED || Status == STATUS_NO_SUCH_FILE || Status == STATUS_NOT_IMPLEMENTED || Status == STATUS_RESOURCE_LANG_NOT_FOUND) { WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 733, "LdrpFindDllActivationContext", 2u, "Probing for the manifest of DLL \"%wZ\" failed with status 0x%08lx\n", &LdrEntry->FullDllName, Status); ) Status = STATUS_SUCCESS; } if (pActivationCtx) { if (LdrEntry->EntryPointActivationContext) { RtlReleaseActivationContext(LdrEntry->EntryPointActivationContext); } LdrEntry->EntryPointActivationContext = pActivationCtx; } if (!NT_SUCCESS(Status)) { WID_HIDDEN(LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x2FA, "LdrpFindDllActivationContext", 0, "Querying the active activation context failed with status 0x%08lx\n", Status); ) } } } return Status; } // Planning to implement them all in the future. tNtOpenThreadToken NtOpenThreadToken = nullptr; tNtClose NtClose = nullptr; tRtlAllocateHeap RtlAllocateHeap = nullptr; tRtlFreeHeap RtlFreeHeap = nullptr; tLdrGetDllPath LdrGetDllPath = nullptr; tRtlReleasePath RtlReleasePath = nullptr; tRtlInitUnicodeStringEx RtlInitUnicodeStringEx = nullptr; tRtlEnterCriticalSection RtlEnterCriticalSection = nullptr; tRtlLeaveCriticalSection RtlLeaveCriticalSection = nullptr; tZwSetEvent ZwSetEvent = nullptr; tNtOpenFile NtOpenFile = nullptr; tLdrAppxHandleIntegrityFailure LdrAppxHandleIntegrityFailure = nullptr; tNtRaiseHardError NtRaiseHardError = nullptr; tRtlImageNtHeaderEx RtlImageNtHeaderEx = nullptr; tRtlAcquireSRWLockExclusive RtlAcquireSRWLockExclusive = nullptr; tRtlReleaseSRWLockExclusive RtlReleaseSRWLockExclusive = nullptr; tRtlEqualUnicodeString RtlEqualUnicodeString = nullptr; tRtlAcquirePrivilege RtlAcquirePrivilege = nullptr; tRtlReleasePrivilege RtlReleasePrivilege = nullptr; tRtlCompareUnicodeStrings RtlCompareUnicodeStrings = nullptr; tRtlImageNtHeader RtlImageNtHeader = nullptr; tRtlReleaseActivationContext RtlReleaseActivationContext = nullptr; tRtlCharToInteger RtlCharToInteger = nullptr; tRtlActivateActivationContextUnsafeFast RtlActivateActivationContextUnsafeFast = nullptr; tRtlDeactivateActivationContextUnsafeFast RtlDeactivateActivationContextUnsafeFast = nullptr; tRtlAcquireSRWLockShared RtlAcquireSRWLockShared = nullptr; tRtlReleaseSRWLockShared RtlReleaseSRWLockShared = nullptr; // Signatured tLdrpLogInternal LdrpLogInternal = nullptr; tLdrpInitializeDllPath LdrpInitializeDllPath = nullptr; tLdrpDereferenceModule LdrpDereferenceModule = nullptr; tLdrpLogDllState LdrpLogDllState = nullptr; tLdrpPreprocessDllName LdrpPreprocessDllName = nullptr; tLdrpFindLoadedDllByName LdrpFindLoadedDllByName = nullptr; tLdrpDrainWorkQueue LdrpDrainWorkQueue = nullptr; tLdrpFindLoadedDllByHandle LdrpFindLoadedDllByHandle = nullptr; tLdrpDropLastInProgressCount LdrpDropLastInProgressCount = nullptr; tLdrpQueryCurrentPatch LdrpQueryCurrentPatch = nullptr; tLdrpUndoPatchImage LdrpUndoPatchImage = nullptr; tLdrpDetectDetour LdrpDetectDetour = nullptr; tLdrpFindOrPrepareLoadingModule LdrpFindOrPrepareLoadingModule = nullptr; tLdrpFreeLoadContext LdrpFreeLoadContext = nullptr; tLdrpCondenseGraph LdrpCondenseGraph = nullptr; tLdrpBuildForwarderLink LdrpBuildForwarderLink = nullptr; tLdrpPinModule LdrpPinModule = nullptr; tLdrpApplyPatchImage LdrpApplyPatchImage = nullptr; tLdrpFreeLoadContextOfNode LdrpFreeLoadContextOfNode = nullptr; tLdrpDecrementModuleLoadCountEx LdrpDecrementModuleLoadCountEx = nullptr; tLdrpLogError LdrpLogError = nullptr; tLdrpLogDeprecatedDllEtwEvent LdrpLogDeprecatedDllEtwEvent = nullptr; tLdrpLogLoadFailureEtwEvent LdrpLogLoadFailureEtwEvent = nullptr; tLdrpReportError LdrpReportError = nullptr; tLdrpResolveDllName LdrpResolveDllName = nullptr; tLdrpAppCompatRedirect LdrpAppCompatRedirect = nullptr; tLdrpHashUnicodeString LdrpHashUnicodeString = nullptr; tLdrpFindExistingModule LdrpFindExistingModule = nullptr; tLdrpLoadContextReplaceModule LdrpLoadContextReplaceModule = nullptr; tLdrpSearchPath LdrpSearchPath = nullptr; tLdrpIsSecurityEtwLoggingEnabled LdrpIsSecurityEtwLoggingEnabled = nullptr; tLdrpLogEtwDllSearchResults LdrpLogEtwDllSearchResults = nullptr; tLdrpCheckForRetryLoading LdrpCheckForRetryLoading = nullptr; tLdrpLogEtwEvent LdrpLogEtwEvent = nullptr; tLdrpCheckComponentOnDemandEtwEvent LdrpCheckComponentOnDemandEtwEvent = nullptr; tLdrpValidateIntegrityContinuity LdrpValidateIntegrityContinuity = nullptr; tLdrpSetModuleSigningLevel LdrpSetModuleSigningLevel = nullptr; tLdrpCodeAuthzCheckDllAllowed LdrpCodeAuthzCheckDllAllowed = nullptr; tLdrpGetFullPath LdrpGetFullPath = nullptr; tLdrpAllocateUnicodeString LdrpAllocateUnicodeString = nullptr; tLdrpAppendUnicodeStringToFilenameBuffer LdrpAppendUnicodeStringToFilenameBuffer = nullptr; tLdrpGetNtPathFromDosPath LdrpGetNtPathFromDosPath = nullptr; tLdrpFindLoadedDllByMappingLockHeld LdrpFindLoadedDllByMappingLockHeld = nullptr; tLdrpInsertDataTableEntry LdrpInsertDataTableEntry = nullptr; tLdrpInsertModuleToIndexLockHeld LdrpInsertModuleToIndexLockHeld = nullptr; tLdrpLogEtwHotPatchStatus LdrpLogEtwHotPatchStatus = nullptr; tLdrpLogNewDllLoad LdrpLogNewDllLoad = nullptr; tLdrpProcessMachineMismatch LdrpProcessMachineMismatch = nullptr; tRtlQueryImageFileKeyOption RtlQueryImageFileKeyOption = nullptr; tRtlpImageDirectoryEntryToDataEx RtlpImageDirectoryEntryToDataEx = nullptr; tLdrpLogDllRelocationEtwEvent LdrpLogDllRelocationEtwEvent = nullptr; tLdrpNotifyLoadOfGraph LdrpNotifyLoadOfGraph = nullptr; tLdrpDynamicShimModule LdrpDynamicShimModule = nullptr; tLdrpAcquireLoaderLock LdrpAcquireLoaderLock = nullptr; tLdrpReleaseLoaderLock LdrpReleaseLoaderLock = nullptr; tLdrpCheckPagesForTampering LdrpCheckPagesForTampering = nullptr; tLdrpLoadDependentModuleA LdrpLoadDependentModuleA = nullptr; tLdrpLoadDependentModuleW LdrpLoadDependentModuleW = nullptr; tLdrpQueueWork LdrpQueueWork = nullptr; tLdrpHandleTlsData LdrpHandleTlsData = nullptr; tLdrControlFlowGuardEnforcedWithExportSuppression LdrControlFlowGuardEnforcedWithExportSuppression = nullptr; tLdrpUnsuppressAddressTakenIat LdrpUnsuppressAddressTakenIat = nullptr; tLdrControlFlowGuardEnforced LdrControlFlowGuardEnforced = nullptr; tRtlpxLookupFunctionTable RtlpxLookupFunctionTable = nullptr; tLdrpCheckRedirection LdrpCheckRedirection = nullptr; tCompatCachepLookupCdb CompatCachepLookupCdb = nullptr; tLdrpGenRandom LdrpGenRandom = nullptr; tLdrInitSecurityCookie LdrInitSecurityCookie = nullptr; tLdrpCfgProcessLoadConfig LdrpCfgProcessLoadConfig = nullptr; tRtlInsertInvertedFunctionTable RtlInsertInvertedFunctionTable = nullptr; tLdrpSignalModuleMapped LdrpSignalModuleMapped = nullptr; tAVrfDllLoadNotification AVrfDllLoadNotification = nullptr; tLdrpSendDllNotifications LdrpSendDllNotifications = nullptr; tLdrpCallTlsInitializers LdrpCallTlsInitializers = nullptr; ================================================ FILE: Src/Functions/NT.h ================================================ #pragma once #include "..\Includes.h" #include "..\WID.h" #include "Undocumented.h" #define NT_SUCCESS(x) ((x)>=0) #define STATUS_SUCCESS 0x0 #define STATUS_IMAGE_NOT_AT_BASE 0x40000003 #define STATUS_IMAGE_AT_DIFFERENT_BASE 0x40000036 #define STATUS_IMAGE_MACHINE_TYPE_MISMATCH 0x4000000E #define STATUS_DEVICE_OFF_LINE 0x80000010 #define STATUS_UNSUCCESSFUL 0xC0000001 #define STATUS_NOT_IMPLEMENTED 0xC0000002 #define STATUS_NO_SUCH_FILE 0xC000000F #define STATUS_CONFLICTING_ADDRESSES 0xC0000018 #define STATUS_ACCESS_DENIED 0xC0000022 #define STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034 #define STATUS_OBJECT_PATH_NOT_FOUND 0xC000003A #define STATUS_PROCEDURE_NOT_FOUND 0xC000007A #define STATUS_DEVICE_NOT_READY 0xC00000A3 #define STATUS_INVALID_IMAGE_FORMAT 0xC000007B #define STATUS_NO_TOKEN 0xC000007C #define STATUS_INSUFFICIENT_RESOURCES 0xC000009A #define STATUS_NOT_SUPPORTED 0xC00000BB #define STATUS_INTERNAL_ERROR 0xC00000E5 #define STATUS_NAME_TOO_LONG 0xC0000106 #define STATUS_COMMITMENT_LIMIT 0xC000012D #define STATUS_NO_APPLICATION_PACKAGE 0xC00001AA #define STATUS_RESOURCE_LANG_NOT_FOUND 0xC0000204 #define STATUS_NOT_FOUND 0xC0000225 #define STATUS_RETRY 0xC000022D #define STATUS_INVALID_IMAGE_HASH 0xC0000428 #define STATUS_NEEDS_REMEDIATION 0xC0000462 #define STATUS_PATCH_CONFLICT 0xC00004AC #define STATUS_IMAGE_LOADED_AS_PATCH_IMAGE 0xC00004C0 #define STATUS_INVALID_THREAD 0xC000071C // Implemented. extern DWORD* LdrpPolicyBits; extern HANDLE* LdrpMainThreadToken; extern DWORD* LdrInitState; extern DWORD* LoadFailure; extern PRTL_CRITICAL_SECTION LdrpWorkQueueLock; extern DWORD* LdrpWorkInProgress; extern LIST_ENTRY** LdrpWorkQueue; extern PHANDLE LdrpWorkCompleteEvent; extern KUSER_SHARED_DATA* kUserSharedData; extern DWORD* LdrpUseImpersonatedDeviceMap; extern DWORD* LdrpAuditIntegrityContinuity; extern DWORD* LdrpEnforceIntegrityContinuity; extern DWORD* LdrpFatalHardErrorCount; extern DWORD* UseWOW64; extern PRTL_SRWLOCK LdrpModuleDatatableLock; extern PHANDLE qword_17E238; extern LDR_DATA_TABLE_ENTRY** LdrpImageEntry; extern PUNICODE_STRING LdrpKernel32DllName; extern UINT_PTR* LdrpAppHeaders; extern PHANDLE LdrpLargePageDllKeyHandle; extern ULONG** LdrpLockMemoryPrivilege; extern ULONG64* LdrpMaximumUserModeAddress; extern UINT_PTR* LdrpMapAndSnapWork; extern LIST_ENTRY* LdrpHashTable; extern PVOID* LdrpHeap; extern BOOLEAN* LdrpIsHotPatchingEnabled; extern LDR_DATA_TABLE_ENTRY** LdrpRedirectionModule; extern ULONG64** qword_1993A8; extern LONG* NtdllBaseTag; extern FUNCTION_TABLE_DATA* stru_199520; extern UINT_PTR* qword_199530; extern LDR_DATA_TABLE_ENTRY** LdrpNtDllDataTableEntry; extern UINT_PTR* qword_1993B8; extern DWORD* dword_19939C; extern DWORD* LoadFailureOperational; extern DWORD* dword_199398; extern UINT_PTR*** qword_1843B8; extern UINT_PTR* qword_1843B0; extern UINT_PTR* LdrpCurrentDllInitializer; extern LPVOID** LdrpProcessInitContextRecord; extern PRTL_SRWLOCK LdrpTlsLock; extern TLS_ENTRY** LdrpTlsList; typedef NTSTATUS(__fastcall** tLdrpManifestProberRoutine)(PIMAGE_DOS_HEADER Base, PWCHAR, PVOID); extern tLdrpManifestProberRoutine LdrpManifestProberRoutine; typedef BOOLEAN(__fastcall** tLdrpRedirectionCalloutFunc)(PWCHAR Buffer); extern tLdrpRedirectionCalloutFunc LdrpRedirectionCalloutFunc; PEB* NtCurrentPeb(); VOID __fastcall NtdllpFreeStringRoutine(PWCH Buffer); // CHECKED. NTSTATUS __fastcall LdrpFastpthReloadedDll(PUNICODE_STRING FullPath, ULONG Flags, PLDR_DATA_TABLE_ENTRY LdrEntry, LDR_DATA_TABLE_ENTRY** DllEntry); NTSTATUS __fastcall LdrpIncrementModuleLoadCount(LDR_DATA_TABLE_ENTRY* LdrEntry); VOID __fastcall RtlFreeUnicodeString(PUNICODE_STRING UnicodeString); // CHECKED. VOID __fastcall LdrpFreeUnicodeString(PUNICODE_STRING String); ULONG __fastcall RtlGetCurrentServiceSessionId(VOID); // CHECKED ? USHORT __fastcall LdrpGetBaseNameFromFullName(PUNICODE_STRING BaseName, PUNICODE_STRING FullName); PWCHAR __fastcall RtlGetNtSystemRoot(); BOOLEAN __fastcall LdrpHpatAllocationOptOut(PUNICODE_STRING FullDllName); NTSTATUS __fastcall LdrpCorValidateImage(PIMAGE_DOS_HEADER DosHeader); NTSTATUS __fastcall LdrpCorFixupImage(PIMAGE_DOS_HEADER DosHeader); NTSTATUS __fastcall LdrpFindLoadedDllByNameLockHeld(PUNICODE_STRING BaseDllName, PUNICODE_STRING FullDllName, ULONG64 Flags, LDR_DATA_TABLE_ENTRY** pLdrEntry, ULONG BaseNameHashValue); BOOLEAN __fastcall LdrpIsILOnlyImage(PIMAGE_DOS_HEADER DllBase); VOID __fastcall LdrpAddNodeServiceTag(LDR_DDAG_NODE* DdagNode, UINT_PTR ServiceTag); PIMAGE_LOAD_CONFIG_DIRECTORY LdrImageDirectoryEntryToLoadConfig(PIMAGE_DOS_HEADER DllBase); BOOLEAN __fastcall LdrpShouldModuleImportBeRedirected(LDR_DATA_TABLE_ENTRY* DllEntry); PIMAGE_IMPORT_DESCRIPTOR __fastcall LdrpGetImportDescriptorForSnap(LDRP_LOAD_CONTEXT* LoadContext); NTSTATUS __fastcall LdrpMapCleanModuleView(LDRP_LOAD_CONTEXT* LoadContext); LDR_DATA_TABLE_ENTRY* __fastcall LdrpHandleReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry); NTSTATUS __fastcall LdrpFreeReplacedModule(LDR_DATA_TABLE_ENTRY* LdrDataTableEntry); VOID __fastcall LdrpHandlePendingModuleReplaced(LDRP_LOAD_CONTEXT* LoadContext); PIMAGE_SECTION_HEADER __fastcall RtlSectionTableFromVirtualAddress(PIMAGE_NT_HEADERS NtHeader, PVOID Base, UINT_PTR Address); PIMAGE_SECTION_HEADER __fastcall RtlAddressInSectionTable(PIMAGE_NT_HEADERS NtHeader, PVOID Base, UINT_PTR Address); BOOLEAN __fastcall LdrpValidateEntrySection(LDR_DATA_TABLE_ENTRY* DllEntry); BOOL __fastcall LdrpIsExecutableRelocatedImage(PIMAGE_DOS_HEADER DllBase); TLS_ENTRY* __fastcall LdrpFindTlsEntry(LDR_DATA_TABLE_ENTRY* LdrEntry); BOOL __fastcall ImageTlsCallbackCaller(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved); extern "C" NTSTATUS __fastcall ZwSystemDebugControl(); extern "C" NTSTATUS __fastcall NtCreateSection(PHANDLE SectionHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES * ObjectAttributes, PLARGE_INTEGER MaximumSize, ULONG SectionPageProtection, ULONG AllocationAttributes, HANDLE FileHandle); extern "C" NTSTATUS __fastcall ZwMapViewOfSection(HANDLE SectionHandle, HANDLE ProcessHandle, PIMAGE_DOS_HEADER * BaseAddress, ULONG64 ZeroBits, ULONG64 CommitSize, PLARGE_INTEGER SectionOffset, PULONG ViewSize, SECTION_INHERIT InheritDisposition, ULONG64 AllocationType, ULONG64 Protect); extern "C" NTSTATUS __fastcall ZwMapViewOfSectionEx(HANDLE SectionHandle, HANDLE ProcessHandle, PIMAGE_DOS_HEADER * DllBase, PLARGE_INTEGER a4, PULONG ViewSize, ULONG a6, ULONG a7, MEM_EXTENDED_PARAMETER * MemExtendedParam, ULONG a9); extern "C" NTSTATUS __fastcall NtUnmapViewOfSection(HANDLE ProcessHandle, PVOID BaseAddress); extern "C" NTSTATUS __fastcall ZwProtectVirtualMemory(HANDLE ProcessHandle, PVOID * BaseAddress, PULONG ProtectSize, ULONG NewProtect, PULONG OldProtect); extern "C" NTSTATUS __fastcall ZwQueryVirtualMemory(HANDLE ProcessHandle, PVOID BaseAddress, MEMORY_INFORMATION_CLASS MemoryInformationClass, PVOID MemoryInformation, SIZE_T MemoryInformationLength, PSIZE_T ReturnLength); extern "C" NTSTATUS __fastcall NtQueryInformationProcess(HANDLE ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, PVOID ProcessInformation, ULONG ProcessInformationLength, PULONG ReturnLength); // Planning to implement them all in the future. typedef NTSTATUS(__fastcall* tNtOpenThreadToken)(IN HANDLE ThreadHandle, IN ACCESS_MASK DesiredAccess, IN BOOLEAN OpenAsSelf, OUT PHANDLE TokenHandle); extern tNtOpenThreadToken NtOpenThreadToken; typedef NTSTATUS(__fastcall* tNtClose)(HANDLE Handle); extern tNtClose NtClose; typedef PVOID(__fastcall* tRtlAllocateHeap)(IN PVOID HeapHandle, IN OPTIONAL ULONG Flags, IN SIZE_T Size); extern tRtlAllocateHeap RtlAllocateHeap; typedef BOOLEAN(__fastcall* tRtlFreeHeap)(IN PVOID HeapHandle, IN OPTIONAL ULONG Flags, _Frees_ptr_opt_ PVOID BaseAddress); extern tRtlFreeHeap RtlFreeHeap; typedef NTSTATUS(__fastcall* tLdrGetDllPath)(PWCH DllName, DWORD dwFlags, PWSTR* Path, PWSTR* Unknown); extern tLdrGetDllPath LdrGetDllPath; typedef VOID(__fastcall* tRtlReleasePath)(IN PWSTR); extern tRtlReleasePath RtlReleasePath; typedef NTSTATUS(__fastcall* tRtlInitUnicodeStringEx)(PUNICODE_STRING target, PCWSTR source); extern tRtlInitUnicodeStringEx RtlInitUnicodeStringEx; typedef NTSTATUS(__fastcall* tRtlEnterCriticalSection)(PRTL_CRITICAL_SECTION CriticalSection); extern tRtlEnterCriticalSection RtlEnterCriticalSection; typedef NTSTATUS(__fastcall* tRtlLeaveCriticalSection)(PRTL_CRITICAL_SECTION CriticalSection); extern tRtlLeaveCriticalSection RtlLeaveCriticalSection; typedef NTSTATUS(__fastcall* tZwSetEvent)(HANDLE EventHandle, PLONG PreviousState); extern tZwSetEvent ZwSetEvent; typedef NTSTATUS(__fastcall* tNtOpenFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, OBJECT_ATTRIBUTES* ObjectAttributes, PIO_STATUS_BLOCK IoStatusBlock, ULONG ShareAccess, ULONG OpenOptions); extern tNtOpenFile NtOpenFile; typedef NTSTATUS(__fastcall* tLdrAppxHandleIntegrityFailure)(NTSTATUS Status); extern tLdrAppxHandleIntegrityFailure LdrAppxHandleIntegrityFailure; typedef NTSTATUS(__fastcall* tNtRaiseHardError)(NTSTATUS Status, ULONG NumberOfParameters, ULONG UnicodeStringParameterMask, INT* Parameters, HARDERROR_RESPONSE_OPTION ValidResponseOption, HARDERROR_RESPONSE* Response); extern tNtRaiseHardError NtRaiseHardError; typedef NTSTATUS(__fastcall* tRtlImageNtHeaderEx)(ULONG Flags, PVOID Base, ULONG64 Size, PIMAGE_NT_HEADERS* OutHeaders); extern tRtlImageNtHeaderEx RtlImageNtHeaderEx; typedef VOID(__fastcall* tRtlAcquireSRWLockExclusive)(PRTL_SRWLOCK SRWLock); extern tRtlAcquireSRWLockExclusive RtlAcquireSRWLockExclusive; typedef NTSTATUS(__fastcall* tRtlReleaseSRWLockExclusive)(PRTL_SRWLOCK SRWLock); extern tRtlReleaseSRWLockExclusive RtlReleaseSRWLockExclusive; typedef NTSTATUS(__fastcall* tRtlEqualUnicodeString)(PUNICODE_STRING String1, PUNICODE_STRING String2, BOOLEAN CaseInSensitive); extern tRtlEqualUnicodeString RtlEqualUnicodeString; typedef NTSTATUS(__fastcall* tRtlAcquirePrivilege)(ULONG* Privilege,ULONG NumPriv,ULONG Flags,PVOID * ReturnedState); extern tRtlAcquirePrivilege RtlAcquirePrivilege; typedef VOID(__fastcall* tRtlReleasePrivilege)(PVOID ReturnedState); extern tRtlReleasePrivilege RtlReleasePrivilege; typedef NTSTATUS(__fastcall* tRtlCompareUnicodeStrings)(PWCH String1, UINT_PTR String1Length, PWCH String2, UINT_PTR String2Length, BOOLEAN CaseInSensitive); extern tRtlCompareUnicodeStrings RtlCompareUnicodeStrings; typedef PIMAGE_NT_HEADERS(__fastcall* tRtlImageNtHeader)(PIMAGE_DOS_HEADER DosHeader); extern tRtlImageNtHeader RtlImageNtHeader; typedef UINT_PTR(__fastcall* tRtlReleaseActivationContext)(ACTIVATION_CONTEXT* ActivationContext); extern tRtlReleaseActivationContext RtlReleaseActivationContext; typedef NTSTATUS(__fastcall* tRtlCharToInteger)(const PCHAR String, ULONG Base, PULONG Value); extern tRtlCharToInteger RtlCharToInteger; typedef NTSTATUS(__fastcall* tRtlActivateActivationContextUnsafeFast)(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED* StackFrameExtended, ACTIVATION_CONTEXT* ActivationContext); extern tRtlActivateActivationContextUnsafeFast RtlActivateActivationContextUnsafeFast; typedef VOID(__fastcall* tRtlDeactivateActivationContextUnsafeFast)(RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED* StackFrameExtended); extern tRtlDeactivateActivationContextUnsafeFast RtlDeactivateActivationContextUnsafeFast; typedef NTSTATUS(__fastcall* tRtlAcquireSRWLockShared)(PRTL_SRWLOCK SrwLock); extern tRtlAcquireSRWLockShared RtlAcquireSRWLockShared; typedef NTSTATUS(__fastcall* tRtlReleaseSRWLockShared)(PRTL_SRWLOCK SrwLock); extern tRtlReleaseSRWLockShared RtlReleaseSRWLockShared; // Signatured #define LDRP_LOG_INTERNAL_PATTERN "\x89\x54\x24\x10\x4C\x8B\xDC\x49\x89\x4B\x08" typedef NTSTATUS(__fastcall* tLdrpLogInternal)(PCHAR, ULONG, PCHAR, ULONG, PCHAR, ...); extern tLdrpLogInternal LdrpLogInternal; #define LDRP_INITIALIZE_DLLPATH_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x30\x49\x8B\xF8\x48\x8B\xDA\x48\x8B\xF1" typedef NTSTATUS(__fastcall* tLdrpInitializeDllPath)(PWSTR DllName, PWSTR DllPath, LDR_UNKSTRUCT* ReturnPath); extern tLdrpInitializeDllPath LdrpInitializeDllPath; #define LDRP_DEREFERENCE_MODULE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x20\x48\x8B\x81\x98\x00\x00\x00" typedef NTSTATUS(__fastcall* tLdrpDereferenceModule)(LDR_DATA_TABLE_ENTRY* DllEntry); extern tLdrpDereferenceModule LdrpDereferenceModule; #define LDRP_LOG_DLLSTATE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x30\x65\x48\x8B\x04\x25\x60\x00\x00\x00\x41" typedef NTSTATUS(__fastcall* tLdrpLogDllState)(UINT_PTR, PUNICODE_STRING, ULONG); extern tLdrpLogDllState LdrpLogDllState; #define LDRP_PREPROCESS_DLLNAME_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x08\x49\x89\x6B\x10\x49\x89\x73\x18\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x40" typedef NTSTATUS(__fastcall* tLdrpPreprocessDllName)(PUNICODE_STRING DllName, PUNICODE_STRING ResName, PULONG pZero, PULONG pFlags); extern tLdrpPreprocessDllName LdrpPreprocessDllName; #define LDRP_FIND_LOADEDDLLBYNAME_PATTERN "\x48\x8B\xC4\x53\x55\x41\x57\x48\x83\xEC\x50" typedef NTSTATUS(__fastcall* tLdrpFindLoadedDllByName)(PUNICODE_STRING FullPath, PUNICODE_STRING DllName, USHORT Flags, LDR_DATA_TABLE_ENTRY** DllEntry, LDR_DDAG_STATE* ReturnStatus); extern tLdrpFindLoadedDllByName LdrpFindLoadedDllByName; #define LDRP_DRAIN_WORKQUEUE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x54\x41\x56\x48\x83\xEC\x20\x4C\x8B\x35\x35\xA3\x15\x00" typedef TEB* (__fastcall* tLdrpDrainWorkQueue)(DRAIN_TASK DrainTask); extern tLdrpDrainWorkQueue LdrpDrainWorkQueue; #define LDRP_FIND_LOADEDDLL_BYHANDLE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x18\x41\x56\x48\x83\xEC\x20\x33\xDB\x49\x8B\xF8\x4C\x8B\xF2" typedef NTSTATUS(__fastcall* tLdrpFindLoadedDllByHandle)(unsigned __int64 a1, PLDR_DATA_TABLE_ENTRY* ppLdrEntry, DWORD* a3); extern tLdrpFindLoadedDllByHandle LdrpFindLoadedDllByHandle; #define LDRP_DROP_LASTINPROGRESS_COUNT_PATTERN "\x48\x83\xEC\x28\x65\x48\x8B\x04\x25\x30\x00\x00\x00\xB9\xFF\xEF\x00\x00" typedef NTSTATUS(__fastcall* tLdrpDropLastInProgressCount)(); extern tLdrpDropLastInProgressCount LdrpDropLastInProgressCount; #define LDRP_QUERY_CURRENT_PATCH_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x70\x10\x48\x89\x78\x20\x55\x41\x56" typedef NTSTATUS(__fastcall* tLdrpQueryCurrentPatch)(ULONG Checksum, ULONG TimeDateStamp, PUNICODE_STRING FullPath); extern tLdrpQueryCurrentPatch LdrpQueryCurrentPatch; #define LDRP_UNDO_PATCH_IMAGE_PATTERN "\x4C\x8B\xDC\x53\x48\x83\xEC\x40\x48\x8B\x41\x30\x4D\x8D\x4B\x08" typedef NTSTATUS(__fastcall* tLdrpUndoPatchImage)(PLDR_DATA_TABLE_ENTRY LdrEntry); extern tLdrpUndoPatchImage LdrpUndoPatchImage; #define LDRP_DETECT_DETOUR_PATTERN "\x40\x57\x48\x83\xEC\x30\x80\x3D\x87\x32\x11\x00\x00\x75\x7B" typedef VOID(__fastcall* tLdrpDetectDetour)(); extern tLdrpDetectDetour LdrpDetectDetour; #define LDRP_FINDORPREPARE_LOADINGMODULE_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x20\x57\x41\x56\x41\x57\x48\x83\xEC\x50" typedef NTSTATUS(__fastcall* tLdrpFindOrPrepareLoadingModule)(PUNICODE_STRING FullPath, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, ULONG LdrFlags, PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY* pLdrEntryLoaded, NTSTATUS* pStatus); extern tLdrpFindOrPrepareLoadingModule LdrpFindOrPrepareLoadingModule; #define LDRP_FREE_LOAD_CONTEXT_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x48\x8B\x41\x38\x48\x8B\xD9\x48\x83\xA0\xB0\x00\x00\x00" typedef VOID(__fastcall* tLdrpFreeLoadContext)(PLDRP_LOAD_CONTEXT LoadContext); extern tLdrpFreeLoadContext LdrpFreeLoadContext; #define LDRP_CONDENSE_GRAPH_PATTERN "\x48\x8B\xC4\x48\x83\xEC\x28\x83\x79\x38\x06\x7D\x19" typedef PVOID* (__fastcall* tLdrpCondenseGraph)(LDR_DDAG_NODE* DdagNode); extern tLdrpCondenseGraph LdrpCondenseGraph; #define LDRP_BUILD_FORWARDER_LINK_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x20\x33\xDB\x48\x8B\xF2" typedef NTSTATUS(__fastcall* tLdrpBuildForwarderLink)(PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY LdrEntry2); extern tLdrpBuildForwarderLink LdrpBuildForwarderLink; #define LDRP_PIN_MODULE_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x48\x8B\xD9\x33\xFF\x48\x8D\x0D\x02\xBB\x10\x00" typedef NTSTATUS(__fastcall* tLdrpPinModule)(PLDR_DATA_TABLE_ENTRY LdrEntry); extern tLdrpPinModule LdrpPinModule; #define LDRP_APPLY_PATCH_IMAGE_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x7C\x24\x18\x55\x41\x56\x41\x57\x48\x8B\xEC" typedef NTSTATUS(__fastcall* tLdrpApplyPatchImage)(PLDR_DATA_TABLE_ENTRY LdrEntry); extern tLdrpApplyPatchImage LdrpApplyPatchImage; #define LDRP_FREE_LOADCONTEXT_NODE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\x48\x8B\x19\x48\x8B\xF2" typedef NTSTATUS(__fastcall* tLdrpFreeLoadContextOfNode)(PLDR_DDAG_NODE DdagNode, NTSTATUS* pStatus); extern tLdrpFreeLoadContextOfNode LdrpFreeLoadContextOfNode; #define LDRP_DECREMENT_MODULELOADCOUNTEX_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x8B\xFA\x48\x8B\xD9\x85\xD2" typedef NTSTATUS(__fastcall* tLdrpDecrementModuleLoadCountEx)(PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY LdrEntry2); extern tLdrpDecrementModuleLoadCountEx LdrpDecrementModuleLoadCountEx; #define LDRP_LOG_ERROR_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x30\x49\x8B\xD9" typedef PEB*(__fastcall* tLdrpLogError)(NTSTATUS Status, ULONG, ULONG, PVOID); extern tLdrpLogError LdrpLogError; #define LDRP_LOG_DEPRECATED_DLL_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x48\x83\xEC\x40" typedef WCHAR*(__fastcall* tLdrpLogDeprecatedDllEtwEvent)(PLDRP_LOAD_CONTEXT LoadContext); extern tLdrpLogDeprecatedDllEtwEvent LdrpLogDeprecatedDllEtwEvent; #define LDRP_LOG_LOAD_FAILURE_PATTERN "\x48\x89\x5C\x24\x08\x44\x89\x44\x24\x18\x55\x56\x57\x48\x8B\xEC\x48\x83\xEC\x70" typedef VOID(__fastcall* tLdrpLogLoadFailureEtwEvent)(PVOID Unknown, PVOID Unknown2, NTSTATUS Status, PVOID LoadFailure, ULONG Unknown3); extern tLdrpLogLoadFailureEtwEvent LdrpLogLoadFailureEtwEvent; #define LDRP_REPORT_ERROR_PATTERN "\x48\x89\x5C\x24\x20\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\x50\xFF\xFF\xFF\x48\x81\xEC\xB0\x01\x00\x00\x48\x8B\x05\xEE\x08\x19\x00" typedef NTSTATUS(__fastcall* tLdrpReportError)(PVOID Report, ULONG Unknown, NTSTATUS Status); extern tLdrpReportError LdrpReportError; #define LDRP_RESOLVE_DLLNAME_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x08\x49\x89\x6B\x10\x49\x89\x73\x20\x4D\x89\x43\x18\x57\x41\x54\x41\x55\x41\x56" typedef NTSTATUS(__fastcall* tLdrpResolveDllName)(PLDRP_LOAD_CONTEXT FileName, LDRP_FILENAME_BUFFER* FileNameBuffer, PUNICODE_STRING FullName, PUNICODE_STRING ResolvedName, DWORD Flags); extern tLdrpResolveDllName LdrpResolveDllName; #define LDRP_APP_COMPAT_REDIRECT_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x56\x41\x57\x48\x83\xEC\x50\x45\x33\xFF\x49\x8B\xF1\x44\x38\x3D\xC3\x3A\x17\x00" typedef NTSTATUS(__fastcall* tLdrpAppCompatRedirect)(PLDRP_LOAD_CONTEXT LoadContext, PUNICODE_STRING FullDllName, PUNICODE_STRING BaseDllName, LDRP_FILENAME_BUFFER* FileNameBuffer, NTSTATUS Status); extern tLdrpAppCompatRedirect LdrpAppCompatRedirect; #define LDRP_HASH_UNICODE_STRING_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x45\x33\xDB" typedef ULONG(__fastcall* tLdrpHashUnicodeString)(PUNICODE_STRING BaseDllName); extern tLdrpHashUnicodeString LdrpHashUnicodeString; #define LDRP_FIND_EXISTING_MODULE_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x30\x48\x8B\x7C\x24\x60\x48\x8B\xD9" typedef NTSTATUS(__fastcall* tLdrpFindExistingModule)(PUNICODE_STRING BaseDllName, PUNICODE_STRING FullDllName, UINT64 Flags, ULONG BaseDllNameHash, PLDR_DATA_TABLE_ENTRY* LoadedDll); extern tLdrpFindExistingModule LdrpFindExistingModule; #define LDRP_LOADCONTEXT_REPLACE_MODULE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x20\x48\x8B\xD9\x48\x8B\xF2" typedef NTSTATUS(__fastcall* tLdrpLoadContextReplaceModule)(PLDRP_LOAD_CONTEXT LoadContext, PLDR_DATA_TABLE_ENTRY LoadedDll); extern tLdrpLoadContextReplaceModule LdrpLoadContextReplaceModule; #define LDRP_SEARCHPATH_PATTERN "\x48\x89\x5C\x24\x18\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\xF9\x48\x81\xEC\xD0\x00\x00\x00" typedef NTSTATUS(__fastcall* tLdrpSearchPath)(LDRP_LOAD_CONTEXT* LoadContext, LDR_UNKSTRUCT* UnkStruct, ULONG Flags, PUNICODE_STRING ReturnPath, LDRP_FILENAME_BUFFER* FileName, PUNICODE_STRING BaseDllName, PUNICODE_STRING UnkStruct3_String, BOOL* a8, LDR_UNKSTRUCT3* UnkStruct3); extern tLdrpSearchPath LdrpSearchPath; #define LDRP_ISSECURITYETW_LOGG_ENABLED_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\xE8\x04\xA2\x02\x00" typedef BOOLEAN(__fastcall* tLdrpIsSecurityEtwLoggingEnabled)(); extern tLdrpIsSecurityEtwLoggingEnabled LdrpIsSecurityEtwLoggingEnabled; #define LDRP_LOGETW_DLL_SEARCHRESULTS_PATTERN "\x48\x89\x5C\x24\x08\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8B\xEC\x48\x83\xEC\x60\x44\x8B\xF9" typedef VOID(__fastcall* tLdrpLogEtwDllSearchResults)(ULONG Flags, LDRP_LOAD_CONTEXT* LoadContext); extern tLdrpLogEtwDllSearchResults LdrpLogEtwDllSearchResults; #define LDRP_CHECKFORRETRY_LOADING_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x20\x33\xDB\x44\x8A\xFA" typedef BOOLEAN(__fastcall* tLdrpCheckForRetryLoading)(PLDRP_LOAD_CONTEXT LoadContext, BOOLEAN Unknown); extern tLdrpCheckForRetryLoading LdrpCheckForRetryLoading; #define LDRP_LOG_ETWEVENT_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x80\x02\x00\x00" typedef NTSTATUS(__fastcall* tLdrpLogEtwEvent)(ULONG a1, ULONGLONG a2, ULONG a3, ULONG a4); extern tLdrpLogEtwEvent LdrpLogEtwEvent; #define LDRP_CHECK_COMPONENTONDEMAND_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x55\x57\x41\x56\x48\x8B\xEC\x48\x81\xEC\x80\x00\x00\x00" typedef BOOLEAN(__fastcall* tLdrpCheckComponentOnDemandEtwEvent)(LDRP_LOAD_CONTEXT* LoadContext); extern tLdrpCheckComponentOnDemandEtwEvent LdrpCheckComponentOnDemandEtwEvent; #define LDRP_VALIDATE_INTEGRITY_PATTERN "\x44\x88\x44\x24\x18\x53\x56\x57\x48\x83\xEC\x30" typedef NTSTATUS(__fastcall* tLdrpValidateIntegrityContinuity)(PLDRP_LOAD_CONTEXT LoadContext, HANDLE FileHandle); extern tLdrpValidateIntegrityContinuity LdrpValidateIntegrityContinuity; #define LDRP_SET_MODULE_SIGNINGLEVEL_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x10\x49\x89\x73\x18\x49\x89\x7B\x20\x49\x89\x4B\x08\x41\x56" typedef NTSTATUS(__fastcall* tLdrpSetModuleSigningLevel)(HANDLE FileHandle, PLDR_DATA_TABLE_ENTRY LoadContext, PULONG pSigningLevel, ULONG NewSigningLevelMaybe); extern tLdrpSetModuleSigningLevel LdrpSetModuleSigningLevel; #define LDRP_CODE_AUTHZCHECKDLL_ALLOWED_PATTERN "\x48\x83\x3D\xC8\x44\x17\x00\x00\x4C\x8B\xCA" typedef NTSTATUS(__fastcall* tLdrpCodeAuthzCheckDllAllowed)(LDRP_FILENAME_BUFFER* pFileNameBuffer, HANDLE FileHandle); extern tLdrpCodeAuthzCheckDllAllowed LdrpCodeAuthzCheckDllAllowed; #define LDRP_GET_FULLPATH_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x08\x55\x56\x57\x41\x56\x41\x57\x48\x83\xEC\x30" typedef NTSTATUS(__fastcall* tLdrpGetFullPath)(PLDRP_LOAD_CONTEXT LoadContext, PUNICODE_STRING FullPath); extern tLdrpGetFullPath LdrpGetFullPath; #define LDRP_ALLOCATE_UNICODESTRING_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x20\x33\xDB\x8D\x7A\x02" typedef NTSTATUS(__fastcall* tLdrpAllocateUnicodeString)(PUNICODE_STRING Allocated, USHORT Length); extern tLdrpAllocateUnicodeString LdrpAllocateUnicodeString; #define LDRP_APPEND_UNICODETOFILENAME_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x20\x45\x33\xF6\x48\x8B\xEA" typedef NTSTATUS(__fastcall* tLdrpAppendUnicodeStringToFilenameBuffer)(PUNICODE_STRING FileName, PLDRP_LOAD_CONTEXT LoadContext); extern tLdrpAppendUnicodeStringToFilenameBuffer LdrpAppendUnicodeStringToFilenameBuffer; #define LDRP_GET_NTPATH_FROM_DOSPATH_PATTERN "\x48\x89\x5C\x24\x18\x55\x56\x57\x48\x8D\x6C\x24\xB9\x48\x81\xEC\xC0\x00\x00\x00" typedef NTSTATUS(__fastcall* tLdrpGetNtPathFromDosPath)(PUNICODE_STRING DosPath, LDRP_FILENAME_BUFFER* NtPath); extern tLdrpGetNtPathFromDosPath LdrpGetNtPathFromDosPath; #define LDRP_FIND_LOADEDDLL_MAPLOCK_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x56\x41\x57\x48\x83\xEC\x30\x4C\x8B\x15\xFD\x89\x15\x00" typedef NTSTATUS(__fastcall* tLdrpFindLoadedDllByMappingLockHeld)(PIMAGE_DOS_HEADER DllBase, PIMAGE_NT_HEADERS OutHeaders, PVOID Unknown, PLDR_DATA_TABLE_ENTRY* pLdrEntry); extern tLdrpFindLoadedDllByMappingLockHeld LdrpFindLoadedDllByMappingLockHeld; #define LDRP_INSERT_DATATABLEENTRY_PATTERN "\x40\x53\x48\x83\xEC\x20\xF6\x41\x68\x40" typedef VOID(__fastcall* tLdrpInsertDataTableEntry)(PLDR_DATA_TABLE_ENTRY LdrEntry); extern tLdrpInsertDataTableEntry LdrpInsertDataTableEntry; #define LDRP_INSERT_MODTOIDX_LOCKHELD_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x44\x8B\x4A\x08" typedef NTSTATUS(__fastcall* tLdrpInsertModuleToIndexLockHeld)(PLDR_DATA_TABLE_ENTRY LdrEntry, PIMAGE_NT_HEADERS OutHeaders); extern tLdrpInsertModuleToIndexLockHeld LdrpInsertModuleToIndexLockHeld; #define LDRP_LOGETW_HOTPATCHSTATUS_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x70\x10\x48\x89\x78\x18\x4C\x89\x60\x20\x55\x41\x56\x41\x57\x48\x8D\x68\x98" typedef NTSTATUS(__fastcall* tLdrpLogEtwHotPatchStatus)(PUNICODE_STRING BaseDllName, LDR_DATA_TABLE_ENTRY* LdrEntry, PUNICODE_STRING FullDllName, NTSTATUS Status, ULONG Unknown); extern tLdrpLogEtwHotPatchStatus LdrpLogEtwHotPatchStatus; #define LDRP_LOG_NEWDLL_LOAD_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x30\x48\x8B\xEA\x4C\x8B\xF1" typedef PEB*(__fastcall* tLdrpLogNewDllLoad)(LDR_DATA_TABLE_ENTRY* LdrEntry, LDR_DATA_TABLE_ENTRY* LdrEntry2); extern tLdrpLogNewDllLoad LdrpLogNewDllLoad; #define LDRP_PROCESS_MACHINE_MISMATCH_PATTERN "\x40\x53\x55\x57\x48\x83\xEC\x40\x48\x8B\x59\x38" typedef NTSTATUS(__fastcall* tLdrpProcessMachineMismatch)(PLDRP_LOAD_CONTEXT LoadContext); extern tLdrpProcessMachineMismatch LdrpProcessMachineMismatch; #define RTL_QUERY_IMAGEFILE_KEYOPT_PATTERN "\x48\x89\x5C\x24\x10\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\xAC\x24\xA0\xFC\xFF\xFF" typedef NTSTATUS(__fastcall* tRtlQueryImageFileKeyOption)(HANDLE hKey, PCWSTR lpszOption, ULONG dwType, PVOID lpData, ULONG cbData, ULONG* lpcbData); extern tRtlQueryImageFileKeyOption RtlQueryImageFileKeyOption; #define RTLP_IMAGEDIR_ENTRYTODATA_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x10\x49\x89\x6B\x18\x49\x89\x73\x20\x57\x41\x56\x41\x57\x48\x83\xEC\x20\x4C\x8B\x74\x24\x60" typedef NTSTATUS(__fastcall* tRtlpImageDirectoryEntryToDataEx)(PIMAGE_DOS_HEADER DllBase, BOOLEAN Unknown, WORD Characteristics, ULONG64* LastRVASection, PVOID OutHeader); extern tRtlpImageDirectoryEntryToDataEx RtlpImageDirectoryEntryToDataEx; #define LDRP_LOG_DLLRELOCATION_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x83\xEC\x20\x4D\x8B\xF1" typedef PVOID(__fastcall* tLdrpLogDllRelocationEtwEvent)(PUNICODE_STRING FullDllName, ULONGLONG ImageBase, PIMAGE_DOS_HEADER DllBase, SIZE_T Size); extern tLdrpLogDllRelocationEtwEvent LdrpLogDllRelocationEtwEvent; #define LDRP_NOTIFY_LOADOFGRAPH_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x20\x48\x8B\x71\x28\x48\x8B\xF9" typedef NTSTATUS(__fastcall* tLdrpNotifyLoadOfGraph)(LDR_DDAG_NODE* DdagNode); extern tLdrpNotifyLoadOfGraph LdrpNotifyLoadOfGraph; #define LDRP_DYNAMIC_SHIMMODULE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x18\x48\x89\x74\x24\x20\x57\x41\x56\x41\x57\x48\x83\xEC\x40" typedef NTSTATUS(__fastcall* tLdrpDynamicShimModule)(LDR_DDAG_NODE* DdagNode); extern tLdrpDynamicShimModule LdrpDynamicShimModule; #define LDRP_ACQUIRE_LOADERLOCK_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x30\xE8\xE4\x9E\xFE\xFF" typedef NTSTATUS(__fastcall* tLdrpAcquireLoaderLock)(); extern tLdrpAcquireLoaderLock LdrpAcquireLoaderLock; #define LDRP_RELEASE_LOADER_LOCK_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x83\xEC\x30\x48\x8D\x0D\x2E\xD8\x12\x00" typedef NTSTATUS(__fastcall* tLdrpReleaseLoaderLock)(ULONG64 Unused, ULONG Two, ULONG64 LdrFlags); extern tLdrpReleaseLoaderLock LdrpReleaseLoaderLock; #define LDRP_CHECKPAGES_FOR_TAMPERING_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x68\x10\x48\x89\x70\x18\x48\x89\x78\x20\x41\x56\x48\x83\xEC\x30\x48\x8D\xBA\xFF\x0F\x00\x00" typedef BOOLEAN(__fastcall* tLdrpCheckPagesForTampering)(PIMAGE_DATA_DIRECTORY pDataDir, ULONG64 Offset); extern tLdrpCheckPagesForTampering LdrpCheckPagesForTampering; #define LDRP_LOAD_DEPENDENTMODULEA_PATTERN "\x4C\x8B\xDC\x55\x53\x49\x8D\xAB\x48\xFF\xFF\xFF" typedef NTSTATUS(__fastcall* tLdrpLoadDependentModuleA)(PUNICODE_STRING SourceString, LDRP_LOAD_CONTEXT* LoadContext, LDR_DATA_TABLE_ENTRY* LdrEntry, UINT_PTR Unknown, LDR_DATA_TABLE_ENTRY** pLdrEntry, UINT_PTR Unknown2); extern tLdrpLoadDependentModuleA LdrpLoadDependentModuleA; #define LDRP_LOAD_DEPENDENTMODULEW_PATTERN "\x48\x89\x5C\x24\x20\x55\x56\x57\x41\x56\x41\x57\x48\x81\xEC\x50\x01\x00\x00" typedef NTSTATUS(__fastcall* tLdrpLoadDependentModuleW)(PUNICODE_STRING SourceString, LDRP_LOAD_CONTEXT* LoadContext, LDR_DATA_TABLE_ENTRY* DllEntry); extern tLdrpLoadDependentModuleW LdrpLoadDependentModuleW; #define LDRP_QUEUE_WORK_PATTERN "\x40\x53\x48\x83\xEC\x20\x48\x8B\x41\x28\x48\x8B\xD9" typedef NTSTATUS(__fastcall* tLdrpQueueWork)(PLDRP_LOAD_CONTEXT LoadContext); extern tLdrpQueueWork LdrpQueueWork; #define LDRP_HANDLE_TLSDATA_PATTERN "\x48\x89\x5C\x24\x10\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x41\x55\x41\x56\x41\x57\x48\x81\xEC\x00\x01\x00\x00" typedef NTSTATUS(__fastcall* tLdrpHandleTlsData)(LDR_DATA_TABLE_ENTRY* LdrDataTableEntry); extern tLdrpHandleTlsData LdrpHandleTlsData; #define LDR_CONTROLFLOWGUARD_ENFEXP_PATTERN "\x33\xC0\x48\x39\x05\x8F\x7D\x17\x00" typedef BOOLEAN(__fastcall* tLdrControlFlowGuardEnforcedWithExportSuppression)(); extern tLdrControlFlowGuardEnforcedWithExportSuppression LdrControlFlowGuardEnforcedWithExportSuppression; #define LDRP_UNSUPPRESS_ADDRESSIAT_PATTERN "\x48\x89\x5C\x24\x18\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8B\xEC\x48\x83\xEC\x70\x48\x8B\x05\x6E\xC6\x0B\x00" typedef __int64(__fastcall* tLdrpUnsuppressAddressTakenIat)(PIMAGE_DOS_HEADER DllBase, ULONG Unknown, ULONG Unknown2); extern tLdrpUnsuppressAddressTakenIat LdrpUnsuppressAddressTakenIat; #define LDR_CONTROLFLOWGUARD_ENF_PATTERN "\x48\x83\x3D\x90\xD5\x16\x00\x00" typedef BOOL(__fastcall* tLdrControlFlowGuardEnforced)(); extern tLdrControlFlowGuardEnforced LdrControlFlowGuardEnforced; #define RTLP_LOOKUP_FUNCTIONTABLE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x18\x48\x89\x7C\x24\x20\x41\x56\x48\x83\xEC\x20\x33\xDB" typedef PIMAGE_RUNTIME_FUNCTION_ENTRY(__fastcall* tRtlpxLookupFunctionTable)(PIMAGE_DOS_HEADER DllBase, PIMAGE_RUNTIME_FUNCTION_ENTRY* ppImageFunctionEntry); extern tRtlpxLookupFunctionTable RtlpxLookupFunctionTable; #define LDRP_CHECK_REDIRECTION_PATTERN "\x48\x8B\xC4\x48\x89\x58\x08\x48\x89\x70\x10\x48\x89\x78\x18\x4C\x89\x68\x20\x55\x41\x56\x41\x57\x48\x8D\x68\xA1" typedef PCHAR(__fastcall* tLdrpCheckRedirection)(LDR_DATA_TABLE_ENTRY* DllEntry, LDR_DATA_TABLE_ENTRY* NtLdrEntry, PCHAR StringToBeHashed); extern tLdrpCheckRedirection LdrpCheckRedirection; #define COMPAT_CACHE_LOOKUPCDB_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x57\x48\x81\xEC\xB0\x01\x00\x00" typedef BOOL(__fastcall* tCompatCachepLookupCdb)(PWCHAR Buffer, LONG Unknown); extern tCompatCachepLookupCdb CompatCachepLookupCdb; #define LDRP_GEN_RANDOM_PATTERN "\x48\x83\xEC\x28\xB9\x1C\x00\x00\x00\xE8\x0E\x0B\x00\x00" typedef UINT_PTR(__fastcall* tLdrpGenRandom)(); extern tLdrpGenRandom LdrpGenRandom; #define LDR_INIT_SECURITY_COOKIE_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x20\x55\x41\x54\x41\x56" typedef BOOL(__fastcall* tLdrInitSecurityCookie)(PIMAGE_DOS_HEADER DllBase, INT_PTR ImageSize, UINT_PTR* Zero, UINT_PTR RandomNumberStuff, UINT_PTR* Zero_2); extern tLdrInitSecurityCookie LdrInitSecurityCookie; #define LDRP_CFG_PROCESS_LOADCFG_PATTERN "\x48\x89\x5C\x24\x20\x55\x56\x57\x41\x54\x41\x55\x41\x56\x41\x57\x48\x8D\x6C\x24\xD9\x48\x81\xEC\xF0\x00\x00\x00\x48\x8B\x05\x99\x11\x17\x00" typedef NTSTATUS(__fastcall* tLdrpCfgProcessLoadConfig)(LDR_DATA_TABLE_ENTRY* DllEntry, PIMAGE_NT_HEADERS NtHeader, __int64 Zero); extern tLdrpCfgProcessLoadConfig LdrpCfgProcessLoadConfig; #define RTL_INSERT_INV_FUNCTIONTABLE_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x30\x8B\xDA\x4C\x8D\x44\x24\x50" typedef NTSTATUS(__fastcall* tRtlInsertInvertedFunctionTable)(PIMAGE_DOS_HEADER DllBase, ULONG ImageSize); extern tRtlInsertInvertedFunctionTable RtlInsertInvertedFunctionTable; #define LDRP_SIGNAL_MODULEMAPPED_PATTERN "\x48\x89\x5C\x24\x08\x57\x48\x83\xEC\x20\x48\x8B\x81\x98\x00\x00\x00\x48\x8B\x78\x30" typedef LDR_DDAG_NODE*(__fastcall* tLdrpSignalModuleMapped)(LDR_DATA_TABLE_ENTRY* DllEntry); extern tLdrpSignalModuleMapped LdrpSignalModuleMapped; #define AVRF_DLL_LOADNOTIFICATION_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x6C\x24\x10\x48\x89\x74\x24\x18\x57\x48\x83\xEC\x30\x65\x48\x8B\x04\x25\x60\x00\x00\x00" typedef NTSTATUS(__fastcall* tAVrfDllLoadNotification)(LDR_DATA_TABLE_ENTRY* DllEntry); extern tAVrfDllLoadNotification AVrfDllLoadNotification; #define LDRP_SEND_DLLNOTIFICATIONS_PATTERN "\x4C\x8B\xDC\x49\x89\x5B\x08\x49\x89\x73\x10\x57\x48\x83\xEC\x50\x83\x64\x24\x20\x00" typedef NTSTATUS(__fastcall* tLdrpSendDllNotifications)(LDR_DATA_TABLE_ENTRY* DllEntry, UINT_PTR Unknown); extern tLdrpSendDllNotifications LdrpSendDllNotifications; #define LDRP_CALL_TLSINIT_PATTERN "\x48\x89\x5C\x24\x08\x48\x89\x74\x24\x10\x48\x89\x7C\x24\x20\x41\x56\x48\x83\xEC\x60" typedef NTSTATUS(__fastcall* tLdrpCallTlsInitializers)(ULONG One, LDR_DATA_TABLE_ENTRY* LdrEntry); extern tLdrpCallTlsInitializers LdrpCallTlsInitializers; ================================================ FILE: Src/Functions/Syscalls.asm ================================================ .code ZwSystemDebugControl proc mov r10, rcx mov eax, 1CDh test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh ZwSystemDebugControl endp NtCreateSection proc mov r10, rcx mov eax, 4Ah test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh NtCreateSection endp ZwMapViewOfSection proc mov r10, rcx mov eax, 28h test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh ZwMapViewOfSection endp ZwMapViewOfSectionEx proc mov r10, rcx mov eax, 11Ch test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh ZwMapViewOfSectionEx endp NtUnmapViewOfSection proc mov r10, rcx mov eax, 2Ah test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh NtUnmapViewOfSection endp ZwProtectVirtualMemory proc mov r10, rcx mov eax, 50h test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh ZwProtectVirtualMemory endp ZwQueryVirtualMemory proc mov r10, rcx mov eax, 23h test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh ZwQueryVirtualMemory endp NtQueryInformationProcess proc mov r10, rcx mov eax, 19h test byte ptr [7FFE0308h], 1 ; KUSER_SHARED_DATA.SystemCall jnz short SYSCALL_DEFINED syscall ret SYSCALL_DEFINED: int 2Eh NtQueryInformationProcess endp end ================================================ FILE: Src/Functions/Undocumented.h ================================================ #pragma once #include "..\Includes.h" typedef void* PPS_POST_PROCESS_INIT_ROUTINE; typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer; } LSA_UNICODE_STRING, * PLSA_UNICODE_STRING, UNICODE_STRING, * PUNICODE_STRING; typedef struct _STRING { USHORT Length; USHORT MaximumLength; PCHAR Buffer; } STRING, * PSTRING, ANSI_STRING, * PANSI_STRING; #define DOS_MAX_COMPONENT_LENGTH 255 #define DOS_MAX_PATH_LENGTH (DOS_MAX_COMPONENT_LENGTH + 5) typedef struct _CURDIR { UNICODE_STRING DosPath; HANDLE Handle; } CURDIR, * PCURDIR; #define RTL_USER_PROC_CURDIR_CLOSE 0x00000002 #define RTL_USER_PROC_CURDIR_INHERIT 0x00000003 typedef struct _RTL_DRIVE_LETTER_CURDIR { USHORT Flags; USHORT Length; ULONG TimeStamp; STRING DosPath; } RTL_DRIVE_LETTER_CURDIR, * PRTL_DRIVE_LETTER_CURDIR; #define RTL_MAX_DRIVE_LETTERS 32 #define RTL_DRIVE_LETTER_VALID (USHORT)0x0001 typedef struct _RTL_USER_PROCESS_PARAMETERS { ULONG MaximumLength; ULONG Length; ULONG Flags; ULONG DebugFlags; HANDLE ConsoleHandle; ULONG ConsoleFlags; HANDLE StandardInput; HANDLE StandardOutput; HANDLE StandardError; CURDIR CurrentDirectory; UNICODE_STRING DllPath; UNICODE_STRING ImagePathName; UNICODE_STRING CommandLine; PVOID Environment; ULONG StartingX; ULONG StartingY; ULONG CountX; ULONG CountY; ULONG CountCharsX; ULONG CountCharsY; ULONG FillAttribute; ULONG WindowFlags; ULONG ShowWindowFlags; UNICODE_STRING WindowTitle; UNICODE_STRING DesktopInfo; UNICODE_STRING ShellInfo; UNICODE_STRING RuntimeData; RTL_DRIVE_LETTER_CURDIR CurrentDirectories[RTL_MAX_DRIVE_LETTERS]; ULONG EnvironmentSize; ULONG EnvironmentVersion; PVOID PackageDependencyData; ULONG ProcessGroupId; ULONG LoaderThreads; } RTL_USER_PROCESS_PARAMETERS, * PRTL_USER_PROCESS_PARAMETERS; typedef struct _PEB_LDR_DATA { ULONG Length; BOOL Initialized; LPVOID SsHandle; LIST_ENTRY InLoadOrderModuleList; LIST_ENTRY InMemoryOrderModuleList; LIST_ENTRY InInitializationOrderModuleList; } PEB_LDR_DATA, * PPEB_LDR_DATA; typedef BOOLEAN(NTAPI* PLDR_INIT_ROUTINE)( _In_ PVOID DllHandle, _In_ ULONG Reason, _In_opt_ PVOID Context ); typedef struct _RTL_BALANCED_NODE { union { struct _RTL_BALANCED_NODE* Children[2]; //0x0 struct { struct _RTL_BALANCED_NODE* Left; //0x0 struct _RTL_BALANCED_NODE* Right; //0x4 }; }; union { struct { UCHAR Red : 1; //0x8 UCHAR Balance : 2; //0x8 }; ULONG ParentValue; //0x8 }; } RTL_BALANCED_NODE, *PRTL_BALANCED_NODE; // symbols typedef struct _LDR_SERVICE_TAG_RECORD { struct _LDR_SERVICE_TAG_RECORD* Next; ULONG ServiceTag; } LDR_SERVICE_TAG_RECORD, * PLDR_SERVICE_TAG_RECORD; // symbols typedef struct _LDRP_CSLIST { PSINGLE_LIST_ENTRY Tail; } LDRP_CSLIST, * PLDRP_CSLIST; // symbols typedef enum _LDR_DDAG_STATE { LdrModulesMerged = -5, LdrModulesInitError = -4, LdrModulesSnapError = -3, LdrModulesUnloaded = -2, LdrModulesUnloading = -1, LdrModulesPlaceHolder = 0, LdrModulesMapping = 1, LdrModulesMapped = 2, LdrModulesWaitingForDependencies = 3, LdrModulesSnapping = 4, LdrModulesSnapped = 5, LdrModulesCondensed = 6, LdrModulesReadyToInit = 7, LdrModulesInitializing = 8, LdrModulesReadyToRun = 9 } LDR_DDAG_STATE; // symbols typedef struct _LDR_DDAG_NODE { LIST_ENTRY Modules; PLDR_SERVICE_TAG_RECORD ServiceTagList; ULONG LoadCount; ULONG LoadWhileUnloadingCount; ULONG LowestLink; union { LDRP_CSLIST Dependencies; SINGLE_LIST_ENTRY* RemovalLink; }; LDRP_CSLIST IncomingDependencies; LDR_DDAG_STATE State; SINGLE_LIST_ENTRY* CondenseLink; ULONG PreorderNumber; ULONG Pad; } LDR_DDAG_NODE, * PLDR_DDAG_NODE; // rev typedef struct _LDR_DEPENDENCY_RECORD { SINGLE_LIST_ENTRY DependencyLink; PLDR_DDAG_NODE DependencyNode; SINGLE_LIST_ENTRY IncomingDependencyLink; PLDR_DDAG_NODE IncomingDependencyNode; } LDR_DEPENDENCY_RECORD, * PLDR_DEPENDENCY_RECORD; // symbols typedef enum _LDR_DLL_LOAD_REASON { LoadReasonStaticDependency, LoadReasonStaticForwarderDependency, LoadReasonDynamicForwarderDependency, LoadReasonDelayloadDependency, LoadReasonDynamicLoad, LoadReasonAsImageLoad, LoadReasonAsDataLoad, LoadReasonEnclavePrimary, // since REDSTONE3 LoadReasonEnclaveDependency, LoadReasonPatchImage, // since WIN11 LoadReasonUnknown = -1 } LDR_DLL_LOAD_REASON, * PLDR_DLL_LOAD_REASON; typedef enum _LDR_HOT_PATCH_STATE { LdrHotPatchBaseImage, LdrHotPatchNotApplied, LdrHotPatchAppliedReverse, LdrHotPatchAppliedForward, LdrHotPatchFailedToPatch, LdrHotPatchStateMax, } LDR_HOT_PATCH_STATE, * PLDR_HOT_PATCH_STATE; // LDR_DATA_TABLE_ENTRY->Flags #define LDRP_PACKAGED_BINARY 0x00000001 #define LDRP_MARKED_FOR_REMOVAL 0x00000002 #define LDRP_IMAGE_DLL 0x00000004 #define LDRP_LOAD_NOTIFICATIONS_SENT 0x00000008 #define LDRP_TELEMETRY_ENTRY_PROCESSED 0x00000010 #define LDRP_PROCESS_STATIC_IMPORT 0x00000020 #define LDRP_IN_LEGACY_LISTS 0x00000040 #define LDRP_IN_INDEXES 0x00000080 #define LDRP_SHIM_DLL 0x00000100 #define LDRP_IN_EXCEPTION_TABLE 0x00000200 #define LDRP_LOAD_IN_PROGRESS 0x00001000 #define LDRP_LOAD_CONFIG_PROCESSED 0x00002000 #define LDRP_ENTRY_PROCESSED 0x00004000 #define LDRP_PROTECT_DELAY_LOAD 0x00008000 #define LDRP_DONT_CALL_FOR_THREADS 0x00040000 #define LDRP_PROCESS_ATTACH_CALLED 0x00080000 #define LDRP_PROCESS_ATTACH_FAILED 0x00100000 #define LDRP_COR_DEFERRED_VALIDATE 0x00200000 #define LDRP_COR_IMAGE 0x00400000 #define LDRP_DONT_RELOCATE 0x00800000 #define LDRP_COR_IL_ONLY 0x01000000 #define LDRP_CHPE_IMAGE 0x02000000 #define LDRP_CHPE_EMULATOR_IMAGE 0x04000000 #define LDRP_REDIRECTED 0x10000000 #define LDRP_COMPAT_DATABASE_PROCESSED 0x80000000 #define LDR_DATA_TABLE_ENTRY_SIZE_WINXP FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, DdagNode) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN7 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, BaseNameHashValue) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN8 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, ImplicitPathOptions) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN10 FIELD_OFFSET(LDR_DATA_TABLE_ENTRY, SigningLevel) #define LDR_DATA_TABLE_ENTRY_SIZE_WIN11 sizeof(LDR_DATA_TABLE_ENTRY) // symbols typedef struct _LDR_DATA_TABLE_ENTRY { LIST_ENTRY InLoadOrderLinks; LIST_ENTRY InMemoryOrderLinks; union { LIST_ENTRY InInitializationOrderLinks; LIST_ENTRY InProgressLinks; }; PIMAGE_DOS_HEADER DllBase; PLDR_INIT_ROUTINE EntryPoint; ULONG SizeOfImage; UNICODE_STRING FullDllName; UNICODE_STRING BaseDllName; union { UCHAR FlagGroup[4]; ULONG Flags; struct { ULONG PackagedBinary : 1; ULONG MarkedForRemoval : 1; ULONG ImageDll : 1; ULONG LoadNotificationsSent : 1; ULONG TelemetryEntryProcessed : 1; ULONG ProcessStaticImport : 1; ULONG InLegacyLists : 1; ULONG InIndexes : 1; ULONG ShimDll : 1; ULONG InExceptionTable : 1; ULONG ReservedFlags1 : 2; ULONG LoadInProgress : 1; ULONG LoadConfigProcessed : 1; ULONG EntryProcessed : 1; ULONG ProtectDelayLoad : 1; ULONG ReservedFlags3 : 2; ULONG DontCallForThreads : 1; ULONG ProcessAttachCalled : 1; ULONG ProcessAttachFailed : 1; ULONG CorDeferredValidate : 1; ULONG CorImage : 1; ULONG DontRelocate : 1; ULONG CorILOnly : 1; ULONG ChpeImage : 1; ULONG ChpeEmulatorImage : 1; ULONG ReservedFlags5 : 1; ULONG Redirected : 1; ULONG ReservedFlags6 : 2; ULONG CompatDatabaseProcessed : 1; }; }; USHORT ObsoleteLoadCount; USHORT TlsIndex; LIST_ENTRY HashLinks; ULONG TimeDateStamp; struct _ACTIVATION_CONTEXT* EntryPointActivationContext; PVOID Lock; // RtlAcquireSRWLockExclusive PLDR_DDAG_NODE DdagNode; LIST_ENTRY NodeModuleLink; struct _LDRP_LOAD_CONTEXT* LoadContext; PVOID ParentDllBase; PVOID SwitchBackContext; RTL_BALANCED_NODE BaseAddressIndexNode; RTL_BALANCED_NODE MappingInfoIndexNode; ULONG_PTR OriginalBase; LARGE_INTEGER LoadTime; ULONG BaseNameHashValue; LDR_DLL_LOAD_REASON LoadReason; // since WIN8 ULONG ImplicitPathOptions; ULONG ReferenceCount; // since WIN10 ULONG DependentLoadFlags; UCHAR SigningLevel; // since REDSTONE2 ULONG CheckSum; // since 22H1 PVOID ActivePatchImageBase; LDR_HOT_PATCH_STATE HotPatchState; } LDR_DATA_TABLE_ENTRY, * PLDR_DATA_TABLE_ENTRY; #define PROCESSOR_FEATURE_MAX 64 typedef struct _KSYSTEM_TIME { ULONG LowPart; LONG High1Time; LONG High2Time; } KSYSTEM_TIME, * PKSYSTEM_TIME; typedef enum _NT_PRODUCT_TYPE { NtProductWinNt = 1, NtProductLanManNt = 2, NtProductServer = 3 } NT_PRODUCT_TYPE; typedef enum _ALTERNATIVE_ARCHITECTURE_TYPE { StandardDesign = 0, NEC98x86 = 1, EndAlternatives = 2 } ALTERNATIVE_ARCHITECTURE_TYPE; typedef struct _KUSER_SHARED_DATA { ULONG TickCountLowDeprecated; ULONG TickCountMultiplier; KSYSTEM_TIME InterruptTime; KSYSTEM_TIME SystemTime; KSYSTEM_TIME TimeZoneBias; USHORT ImageNumberLow; USHORT ImageNumberHigh; WCHAR NtSystemRoot[260]; ULONG MaxStackTraceDepth; ULONG CryptoExponent; ULONG TimeZoneId; ULONG LargePageMinimum; ULONG AitSamplingValue; ULONG AppCompatFlag; ULONGLONG RNGSeedVersion; ULONG GlobalValidationRunlevel; LONG TimeZoneBiasStamp; ULONG NtBuildNumber; NT_PRODUCT_TYPE NtProductType; BOOLEAN ProductTypeIsValid; BOOLEAN Reserved0[1]; USHORT NativeProcessorArchitecture; ULONG NtMajorVersion; ULONG NtMinorVersion; BOOLEAN ProcessorFeatures[PROCESSOR_FEATURE_MAX]; ULONG Reserved1; ULONG Reserved3; ULONG TimeSlip; ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; ULONG BootId; LARGE_INTEGER SystemExpirationDate; ULONG SuiteMask; BOOLEAN KdDebuggerEnabled; union { UCHAR MitigationPolicies; struct { UCHAR NXSupportPolicy : 2; UCHAR SEHValidationPolicy : 2; UCHAR CurDirDevicesSkippedForDlls : 2; UCHAR Reserved : 2; }; }; USHORT CyclesPerYield; ULONG ActiveConsoleId; ULONG DismountCount; ULONG ComPlusPackage; ULONG LastSystemRITEventTickCount; ULONG NumberOfPhysicalPages; BOOLEAN SafeBootMode; union { UCHAR VirtualizationFlags; struct { UCHAR ArchStartedInEl2 : 1; UCHAR QcSlIsSupported : 1; }; }; UCHAR Reserved12[2]; union { ULONG SharedDataFlags; struct { ULONG DbgErrorPortPresent : 1; ULONG DbgElevationEnabled : 1; ULONG DbgVirtEnabled : 1; ULONG DbgInstallerDetectEnabled : 1; ULONG DbgLkgEnabled : 1; ULONG DbgDynProcessorEnabled : 1; ULONG DbgConsoleBrokerEnabled : 1; ULONG DbgSecureBootEnabled : 1; ULONG DbgMultiSessionSku : 1; ULONG DbgMultiUsersInSessionSku : 1; ULONG DbgStateSeparationEnabled : 1; ULONG SpareBits : 21; } DUMMYSTRUCTNAME2; } DUMMYUNIONNAME2; ULONG DataFlagsPad[1]; ULONGLONG TestRetInstruction; LONGLONG QpcFrequency; ULONG SystemCall; ULONG Reserved2; ULONGLONG SystemCallPad[2]; union { KSYSTEM_TIME TickCount; ULONG64 TickCountQuad; struct { ULONG ReservedTickCountOverlay[3]; ULONG TickCountPad[1]; } DUMMYSTRUCTNAME; } DUMMYUNIONNAME3; ULONG Cookie; ULONG CookiePad[1]; LONGLONG ConsoleSessionForegroundProcessId; ULONGLONG TimeUpdateLock; ULONGLONG BaselineSystemTimeQpc; ULONGLONG BaselineInterruptTimeQpc; ULONGLONG QpcSystemTimeIncrement; ULONGLONG QpcInterruptTimeIncrement; UCHAR QpcSystemTimeIncrementShift; UCHAR QpcInterruptTimeIncrementShift; USHORT UnparkedProcessorCount; ULONG EnclaveFeatureMask[4]; ULONG TelemetryCoverageRound; USHORT UserModeGlobalLogger[16]; ULONG ImageFileExecutionOptions; ULONG LangGenerationCount; ULONGLONG Reserved4; ULONGLONG InterruptTimeBias; ULONGLONG QpcBias; ULONG ActiveProcessorCount; UCHAR ActiveGroupCount; UCHAR Reserved9; union { USHORT QpcData; struct { UCHAR QpcBypassEnabled; UCHAR QpcShift; }; }; LARGE_INTEGER TimeZoneBiasEffectiveStart; LARGE_INTEGER TimeZoneBiasEffectiveEnd; XSTATE_CONFIGURATION XState; KSYSTEM_TIME FeatureConfigurationChangeStamp; ULONG Spare; ULONG64 UserPointerAuthMask; } KUSER_SHARED_DATA, * PKUSER_SHARED_DATA; enum DRAIN_TASK { WaitLoadComplete = 0, WaitWorkComplete }; typedef struct _PEB { BYTE InheritedAddressSpace; BYTE ReadImageFileExecOptions; BYTE BeingDebugged; union { UCHAR BitField; struct { /* bit fields, follow link */ }; }; LPVOID Mutant; LPVOID ImageBaseAddress; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; LPVOID SubSystemData; LPVOID ProcessHeap; LPVOID FastPebLock; LPVOID _SYSTEM_DEPENDENT_02; LPVOID _SYSTEM_DEPENDENT_03; LPVOID _SYSTEM_DEPENDENT_04; union { LPVOID KernelCallbackTable; LPVOID UserSharedInfoPtr; }; DWORD SystemReserved; DWORD _SYSTEM_DEPENDENT_05; LPVOID _SYSTEM_DEPENDENT_06; LPVOID TlsExpansionCounter; LPVOID TlsBitmap; DWORD TlsBitmapBits[2]; LPVOID ReadOnlySharedMemoryBase; KUSER_SHARED_DATA* SharedData; LPVOID ReadOnlyStaticServerData; LPVOID AnsiCodePageData; LPVOID OemCodePageData; LPVOID UnicodeCaseTableData; DWORD NumberOfProcessors; union { DWORD NtGlobalFlag; LPVOID dummy02; }; LARGE_INTEGER CriticalSectionTimeout; LPVOID HeapSegmentReserve; LPVOID HeapSegmentCommit; LPVOID HeapDeCommitTotalFreeThreshold; LPVOID HeapDeCommitFreeBlockThreshold; DWORD NumberOfHeaps; DWORD MaximumNumberOfHeaps; LPVOID ProcessHeaps; LPVOID GdiSharedHandleTable; LPVOID ProcessStarterHelper; LPVOID GdiDCAttributeList; LPVOID LoaderLock; DWORD OSMajorVersion; DWORD OSMinorVersion; WORD OSBuildNumber; WORD OSCSDVersion; DWORD OSPlatformId; DWORD ImageSubsystem; DWORD ImageSubsystemMajorVersion; LPVOID ImageSubsystemMinorVersion; union { LPVOID ImageProcessAffinityMask; LPVOID ActiveProcessAffinityMask; }; #ifdef _WIN64 LPVOID GdiHandleBuffer[64]; #else LPVOID GdiHandleBuffer[32]; #endif LPVOID PostProcessInitRoutine; LPVOID TlsExpansionBitmap; DWORD TlsExpansionBitmapBits[32]; LPVOID SessionId; ULARGE_INTEGER AppCompatFlags; ULARGE_INTEGER AppCompatFlagsUser; LPVOID pShimData; LPVOID AppCompatInfo; PUNICODE_STRING CSDVersion; LPVOID ActivationContextData; LPVOID ProcessAssemblyStorageMap; LPVOID SystemDefaultActivationContextData; LPVOID SystemAssemblyStorageMap; LPVOID MinimumStackCommit; //Appended for Windows Server 2003 PVOID SparePointers[4]; LIST_ENTRY FlsListHead; PVOID FlsBitmap; ULONG SpareUlongs[5]; ULONG FlsHighIndex; //Appended for Windows Vista PVOID WerRegistrationData; PVOID WerShipAssertPtr; //Appended for Windows 7 PVOID pUnused; PVOID pImageHeaderHash; union { ULONG TracingFlags; struct { /* bit fields, follow link */ }; }; } PEB, * PPEB; struct FUNCTION_TABLE_DATA { UINT_PTR TableAddress; PIMAGE_DOS_HEADER ImageBase; DWORD ImageSize; DWORD Size; }; typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; PVOID SecurityQualityOfService; } OBJECT_ATTRIBUTES; enum HARDERROR_RESPONSE_OPTION { OptionAbortRetryIgnore = 0x0, OptionOk = 0x1, OptionOkCancel = 0x2, OptionRetryCancel = 0x3, OptionYesNo = 0x4, OptionYesNoCancel = 0x5, OptionShutdownSystem = 0x6, }; enum HARDERROR_RESPONSE { ResponseReturnToCaller = 0x0, ResponseNotHandled = 0x1, ResponseAbort = 0x2, ResponseCancel = 0x3, ResponseIgnore = 0x4, ResponseNo = 0x5, ResponseOk = 0x6, ResponseRetry = 0x7, ResponseYes = 0x8, }; typedef struct _IO_STATUS_BLOCK { union { NTSTATUS Status; PVOID Pointer; }; ULONG_PTR Information; } IO_STATUS_BLOCK, * PIO_STATUS_BLOCK; typedef struct _CLIENT_ID { HANDLE UniqueProcess; HANDLE UniqueThread; } CLIENT_ID, * PCLIENT_ID; typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME* PRTL_ACTIVATION_CONTEXT_STACK_FRAME; typedef struct _ACTIVATION_CONTEXT* PACTIVATION_CONTEXT; typedef struct _TEB_ACTIVE_FRAME* PTEB_ACTIVE_FRAME; typedef struct _TEB_ACTIVE_FRAME_CONTEXT* PTEB_ACTIVE_FRAME_CONTEXT; typedef struct _RTL_ACTIVATION_CONTEXT_STACK_FRAME { PRTL_ACTIVATION_CONTEXT_STACK_FRAME Previous; PACTIVATION_CONTEXT* ActivationContext; ULONG Flags; } RTL_ACTIVATION_CONTEXT_STACK_FRAME, * PRTL_ACTIVATION_CONTEXT_STACK_FRAME; typedef struct _ACTIVATION_CONTEXT_STACK { PRTL_ACTIVATION_CONTEXT_STACK_FRAME ActiveFrame; LIST_ENTRY FrameListCache; ULONG Flags; ULONG NextCookieSequenceNumber; ULONG StackId; } ACTIVATION_CONTEXT_STACK, * PACTIVATION_CONTEXT_STACK; typedef struct _RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC { SIZE_T Size; ULONG Format; RTL_ACTIVATION_CONTEXT_STACK_FRAME Frame; } RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC, * PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_BASIC; typedef struct _RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED { SIZE_T Size; ULONG Format; RTL_ACTIVATION_CONTEXT_STACK_FRAME Frame; PVOID Extra1; PVOID Extra2; PVOID Extra3; PVOID Extra4; } RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED, * PRTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED; #define GDI_BATCH_BUFFER_SIZE 310 typedef struct _GDI_TEB_BATCH { ULONG Offset; ULONG_PTR HDC; ULONG Buffer[GDI_BATCH_BUFFER_SIZE]; } GDI_TEB_BATCH, * PGDI_TEB_BATCH; typedef struct _TEB_ACTIVE_FRAME_CONTEXT { ULONG Flags; PSTR FrameName; } TEB_ACTIVE_FRAME_CONTEXT, * PTEB_ACTIVE_FRAME_CONTEXT; typedef struct _TEB_ACTIVE_FRAME { ULONG Flags; struct _TEB_ACTIVE_FRAME* Previous; PTEB_ACTIVE_FRAME_CONTEXT Context; } TEB_ACTIVE_FRAME, * PTEB_ACTIVE_FRAME; #if !defined(_MSC_VER) typedef struct _PROCESSOR_NUMBER { USHORT Group; UCHAR Number; UCHAR Reserved; } PROCESSOR_NUMBER, * PPROCESSOR_NUMBER; #endif typedef struct _TEB { NT_TIB NtTib; PVOID EnvironmentPointer; CLIENT_ID ClientId; PVOID ActiveRpcHandle; PVOID ThreadLocalStoragePointer; PPEB ProcessEnvironmentBlock; ULONG LastErrorValue; ULONG CountOfOwnedCriticalSections; PVOID CsrClientThread; PVOID Win32ThreadInfo; ULONG User32Reserved[26]; ULONG UserReserved[5]; PVOID WOW32Reserved; LCID CurrentLocale; ULONG FpSoftwareStatusRegister; PVOID SystemReserved1[54]; NTSTATUS ExceptionCode; PVOID ActivationContextStackPointer; #ifdef _M_X64 UCHAR SpareBytes[24]; #else UCHAR SpareBytes[36]; #endif ULONG TxFsContext; GDI_TEB_BATCH GdiTebBatch; CLIENT_ID RealClientId; HANDLE GdiCachedProcessHandle; ULONG GdiClientPID; ULONG GdiClientTID; PVOID GdiThreadLocalInfo; ULONG_PTR Win32ClientInfo[62]; PVOID glDispatchTable[233]; ULONG_PTR glReserved1[29]; PVOID glReserved2; PVOID glSectionInfo; PVOID glSection; PVOID glTable; PVOID glCurrentRC; PVOID glContext; NTSTATUS LastStatusValue; UNICODE_STRING StaticUnicodeString; WCHAR StaticUnicodeBuffer[261]; PVOID DeallocationStack; PVOID TlsSlots[64]; LIST_ENTRY TlsLinks; PVOID Vdm; PVOID ReservedForNtRpc; PVOID DbgSsReserved[2]; ULONG HardErrorMode; #ifdef _M_X64 PVOID Instrumentation[11]; #else PVOID Instrumentation[9]; #endif GUID ActivityId; PVOID SubProcessTag; PVOID EtwLocalData; PVOID EtwTraceData; PVOID WinSockData; ULONG GdiBatchCount; union { PROCESSOR_NUMBER CurrentIdealProcessor; ULONG IdealProcessorValue; struct { UCHAR ReservedPad0; UCHAR ReservedPad1; UCHAR ReservedPad2; UCHAR IdealProcessor; }; }; ULONG GuaranteedStackBytes; PVOID ReservedForPerf; PVOID ReservedForOle; ULONG WaitingOnLoaderLock; PVOID SavedPriorityState; ULONG_PTR SoftPatchPtr1; PVOID ThreadPoolData; PVOID* TlsExpansionSlots; #ifdef _M_X64 PVOID DeallocationBStore; PVOID BStoreLimit; #endif ULONG MuiGeneration; ULONG IsImpersonating; PVOID NlsCache; PVOID pShimData; ULONG HeapVirtualAffinity; HANDLE CurrentTransactionHandle; PTEB_ACTIVE_FRAME ActiveFrame; PVOID FlsData; PVOID PreferredLanguages; PVOID UserPrefLanguages; PVOID MergedPrefLanguages; ULONG MuiImpersonation; union { USHORT CrossTebFlags; USHORT SpareCrossTebBits : 16; }; union { USHORT SameTebFlags; struct { USHORT SafeThunkCall : 1; USHORT InDebugPrint : 1; USHORT HasFiberData : 1; USHORT SkipThreadAttach : 1; USHORT WerInShipAssertCode : 1; USHORT RanProcessInit : 1; USHORT ClonedThread : 1; USHORT SuppressDebugMsg : 1; USHORT DisableUserStackWalk : 1; USHORT RtlExceptionAttached : 1; USHORT InitialThread : 1; USHORT SessionAware : 1; USHORT SpareSameTebBits : 4; }; }; PVOID TxnScopeEnterCallback; PVOID TxnScopeExitCallback; PVOID TxnScopeContext; ULONG LockCount; ULONG SpareUlong0; PVOID ResourceRetValue; PVOID ReservedForWdf; } TEB, * PTEB; struct LDR_UNKSTRUCT { PWSTR pInitNameMaybe; __declspec(align(16)) PWSTR Buffer; int Flags; PWSTR pDllName; char Pad1[84]; BOOLEAN IsInitedMaybe; char Pad2[3]; }; struct LDR_UNKSTRUCT2 { PUNICODE_STRING Name; UINT64 Status; }; struct LDR_UNKSTRUCT3 { ULONG Flags; UNICODE_STRING String; }; typedef struct _LDRP_LOAD_CONTEXT { UNICODE_STRING BaseDllName; LDR_UNKSTRUCT* UnkStruct; HANDLE SectionHandle; DWORD Flags; NTSTATUS* pStatus; LDR_DATA_TABLE_ENTRY* Entry; _LIST_ENTRY WorkQueueListEntry; LDR_DATA_TABLE_ENTRY* ReplacedEntry; LDR_DATA_TABLE_ENTRY** pvImports; LDR_DATA_TABLE_ENTRY** IATCheck; PVOID pvIAT; ULONG SizeOfIAT; ULONG CurrentDll; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor; ULONG ImageImportDescriptorLen; __declspec(align(8)) ULONG OriginalIATProtect; PVOID GuardCFCheckFunctionPointer; __int64 GuardFlags; __int64 DllNameLenCompare; __int64 UnknownFunc; SIZE_T Size; __int64 UnknownPtr; HANDLE FileHandle; PIMAGE_DOS_HEADER ImageBase; wchar_t BaseDllNameBuffer[260]; } LDRP_LOAD_CONTEXT, *PLDRP_LOAD_CONTEXT; struct LDRP_FILENAME_BUFFER { UNICODE_STRING pFileName{}; wchar_t FileName[128]{}; }; typedef struct _MEMORY_IMAGE_INFORMATION { PVOID ImageBase; SIZE_T SizeOfImage; union { ULONG ImageFlags; struct { ULONG ImagePartialMap : 1; ULONG ImageNotExecutable : 1; ULONG ImageSigningLevel : 4; // REDSTONE3 ULONG Reserved : 26; }; }; } MEMORY_IMAGE_INFORMATION, * PMEMORY_IMAGE_INFORMATION; typedef struct _TLS_ENTRY { LIST_ENTRY TlsEntry; IMAGE_TLS_DIRECTORY TlsDirectory; PLDR_DATA_TABLE_ENTRY ModuleEntry; SIZE_T Index; } TLS_ENTRY, *PTLS_ENTRY; enum SECTION_INHERIT { ViewShare = 1, ViewUnmap = 2 }; /* struct MEM_EXTENDED_PARAMETER { PVOID Type; PHANDLE pHandle; HANDLE Handle; }; */ typedef struct _MEMORY_WORKING_SET_EX_BLOCK { union { struct { ULONG_PTR Valid : 1; ULONG_PTR ShareCount : 3; ULONG_PTR Win32Protection : 11; ULONG_PTR Shared : 1; ULONG_PTR Node : 6; ULONG_PTR Locked : 1; ULONG_PTR LargePage : 1; ULONG_PTR Priority : 3; ULONG_PTR Reserved : 3; ULONG_PTR SharedOriginal : 1; ULONG_PTR Bad : 1; ULONG_PTR Win32GraphicsProtection : 4; // 19H1 #ifdef _WIN64 ULONG_PTR ReservedUlong : 28; #endif }; struct { ULONG_PTR Valid : 1; ULONG_PTR Reserved0 : 14; ULONG_PTR Shared : 1; ULONG_PTR Reserved1 : 5; ULONG_PTR PageTable : 1; ULONG_PTR Location : 2; ULONG_PTR Priority : 3; ULONG_PTR ModifiedList : 1; ULONG_PTR Reserved2 : 2; ULONG_PTR SharedOriginal : 1; ULONG_PTR Bad : 1; #ifdef _WIN64 ULONG_PTR ReservedUlong : 32; #endif } Invalid; }; } MEMORY_WORKING_SET_EX_BLOCK, * PMEMORY_WORKING_SET_EX_BLOCK; // private typedef struct _MEMORY_WORKING_SET_EX_INFORMATION { PVOID VirtualAddress; union { MEMORY_WORKING_SET_EX_BLOCK VirtualAttributes; ULONG_PTR Long; } u1; } MEMORY_WORKING_SET_EX_INFORMATION, * PMEMORY_WORKING_SET_EX_INFORMATION; typedef enum _MEMORY_INFORMATION_CLASS { MemoryBasicInformation, // q: MEMORY_BASIC_INFORMATION MemoryWorkingSetInformation, // q: MEMORY_WORKING_SET_INFORMATION MemoryMappedFilenameInformation, // q: UNICODE_STRING MemoryRegionInformation, // q: MEMORY_REGION_INFORMATION MemoryWorkingSetExInformation, // q: MEMORY_WORKING_SET_EX_INFORMATION // since VISTA MemorySharedCommitInformation, // q: MEMORY_SHARED_COMMIT_INFORMATION // since WIN8 MemoryImageInformation, // q: MEMORY_IMAGE_INFORMATION MemoryRegionInformationEx, // MEMORY_REGION_INFORMATION MemoryPrivilegedBasicInformation, // MEMORY_BASIC_INFORMATION MemoryEnclaveImageInformation, // MEMORY_ENCLAVE_IMAGE_INFORMATION // since REDSTONE3 MemoryBasicInformationCapped, // 10 MemoryPhysicalContiguityInformation, // MEMORY_PHYSICAL_CONTIGUITY_INFORMATION // since 20H1 MemoryBadInformation, // since WIN11 MemoryBadInformationAllProcesses, // since 22H1 MaxMemoryInfoClass } MEMORY_INFORMATION_CLASS; typedef enum _PROCESSINFOCLASS { ProcessBasicInformation, // q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX ProcessIoCounters, // q: IO_COUNTERS ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX, VM_COUNTERS_EX2 ProcessTimes, // q: KERNEL_USER_TIMES ProcessBasePriority, // s: KPRIORITY ProcessRaisePriority, // s: ULONG ProcessDebugPort, // q: HANDLE ProcessExceptionPort, // s: PROCESS_EXCEPTION_PORT (requires SeTcbPrivilege) ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN ProcessLdtInformation, // qs: PROCESS_LDT_INFORMATION // 10 ProcessLdtSize, // s: PROCESS_LDT_SIZE ProcessDefaultHardErrorMode, // qs: ULONG ProcessIoPortHandlers, // (kernel-mode only) // PROCESS_IO_PORT_HANDLER_INFORMATION ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void ProcessUserModeIOPL, // qs: ULONG (requires SeTcbPrivilege) ProcessEnableAlignmentFaultFixup, // s: BOOLEAN ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS ProcessWx86Information, // qs: ULONG (requires SeTcbPrivilege) (VdmAllowed) ProcessHandleCount, // q: ULONG, PROCESS_HANDLE_INFORMATION // 20 ProcessAffinityMask, // (q >WIN7)s: KAFFINITY, qs: GROUP_AFFINITY ProcessPriorityBoost, // qs: ULONG ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND ProcessWow64Information, // q: ULONG_PTR ProcessImageFileName, // q: UNICODE_STRING ProcessLUIDDeviceMapsEnabled, // q: ULONG ProcessBreakOnTermination, // qs: ULONG ProcessDebugObjectHandle, // q: HANDLE // 30 ProcessDebugFlags, // qs: ULONG ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables ProcessIoPriority, // qs: IO_PRIORITY_HINT ProcessExecuteFlags, // qs: ULONG ProcessTlsInformation, // PROCESS_TLS_INFORMATION // ProcessResourceManagement ProcessCookie, // q: ULONG ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION // since VISTA ProcessPagePriority, // qs: PAGE_PRIORITY_INFORMATION ProcessInstrumentationCallback, // s: PVOID or PROCESS_INSTRUMENTATION_CALLBACK_INFORMATION // 40 ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[] ProcessImageFileNameWin32, // q: UNICODE_STRING ProcessImageFileMapping, // q: HANDLE (input) ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE ProcessGroupInformation, // q: USHORT[] ProcessTokenVirtualizationEnabled, // s: ULONG ProcessConsoleHostProcess, // qs: ULONG_PTR // ProcessOwnerInformation ProcessWindowInformation, // q: PROCESS_WINDOW_INFORMATION // 50 ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8 ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION ProcessDynamicFunctionTableInformation, ProcessHandleCheckingMode, // qs: ULONG; s: 0 disables, otherwise enables ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION ProcessWorkingSetControl, // s: PROCESS_WORKING_SET_CONTROL (requires SeDebugPrivilege) ProcessHandleTable, // q: ULONG[] // since WINBLUE ProcessCheckStackExtentsMode, // qs: ULONG // KPROCESS->CheckStackExtents (CFG) ProcessCommandLineInformation, // q: UNICODE_STRING // 60 ProcessProtectionInformation, // q: PS_PROTECTION ProcessMemoryExhaustion, // PROCESS_MEMORY_EXHAUSTION_INFO // since THRESHOLD ProcessFaultInformation, // PROCESS_FAULT_INFORMATION ProcessTelemetryIdInformation, // q: PROCESS_TELEMETRY_ID_INFORMATION ProcessCommitReleaseInformation, // PROCESS_COMMIT_RELEASE_INFORMATION ProcessDefaultCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5] ProcessAllowedCpuSetsInformation, // SYSTEM_CPU_SET_INFORMATION[5] ProcessSubsystemProcess, ProcessJobMemoryInformation, // q: PROCESS_JOB_MEMORY_INFO ProcessInPrivate, // s: void // ETW // since THRESHOLD2 // 70 ProcessRaiseUMExceptionOnInvalidHandleClose, // qs: ULONG; s: 0 disables, otherwise enables ProcessIumChallengeResponse, ProcessChildProcessInformation, // q: PROCESS_CHILD_PROCESS_INFORMATION ProcessHighGraphicsPriorityInformation, // qs: BOOLEAN (requires SeTcbPrivilege) ProcessSubsystemInformation, // q: SUBSYSTEM_INFORMATION_TYPE // since REDSTONE2 ProcessEnergyValues, // q: PROCESS_ENERGY_VALUES, PROCESS_EXTENDED_ENERGY_VALUES ProcessPowerThrottlingState, // qs: POWER_THROTTLING_PROCESS_STATE ProcessReserved3Information, // ProcessActivityThrottlePolicy // PROCESS_ACTIVITY_THROTTLE_POLICY ProcessWin32kSyscallFilterInformation, // q: WIN32K_SYSCALL_FILTER ProcessDisableSystemAllowedCpuSets, // 80 ProcessWakeInformation, // PROCESS_WAKE_INFORMATION ProcessEnergyTrackingState, // qs: PROCESS_ENERGY_TRACKING_STATE ProcessManageWritesToExecutableMemory, // MANAGE_WRITES_TO_EXECUTABLE_MEMORY // since REDSTONE3 ProcessCaptureTrustletLiveDump, ProcessTelemetryCoverage, ProcessEnclaveInformation, ProcessEnableReadWriteVmLogging, // PROCESS_READWRITEVM_LOGGING_INFORMATION ProcessUptimeInformation, // q: PROCESS_UPTIME_INFORMATION ProcessImageSection, // q: HANDLE ProcessDebugAuthInformation, // since REDSTONE4 // 90 ProcessSystemResourceManagement, // PROCESS_SYSTEM_RESOURCE_MANAGEMENT ProcessSequenceNumber, // q: ULONGLONG ProcessLoaderDetour, // since REDSTONE5 ProcessSecurityDomainInformation, // PROCESS_SECURITY_DOMAIN_INFORMATION ProcessCombineSecurityDomainsInformation, // PROCESS_COMBINE_SECURITY_DOMAINS_INFORMATION ProcessEnableLogging, // PROCESS_LOGGING_INFORMATION ProcessLeapSecondInformation, // PROCESS_LEAP_SECOND_INFORMATION ProcessFiberShadowStackAllocation, // PROCESS_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION // since 19H1 ProcessFreeFiberShadowStackAllocation, // PROCESS_FREE_FIBER_SHADOW_STACK_ALLOCATION_INFORMATION ProcessAltSystemCallInformation, // since 20H1 // 100 ProcessDynamicEHContinuationTargets, // PROCESS_DYNAMIC_EH_CONTINUATION_TARGETS_INFORMATION ProcessDynamicEnforcedCetCompatibleRanges, // PROCESS_DYNAMIC_ENFORCED_ADDRESS_RANGE_INFORMATION // since 20H2 ProcessCreateStateChange, // since WIN11 ProcessApplyStateChange, ProcessEnableOptionalXStateFeatures, ProcessAltPrefetchParam, // since 22H1 ProcessAssignCpuPartitions, ProcessPriorityClassEx, // s: PROCESS_PRIORITY_CLASS_EX ProcessMembershipInformation, // PROCESS_MEMBERSHIP_INFORMATION ProcessEffectiveIoPriority, // q: IO_PRIORITY_HINT ProcessEffectivePagePriority, // q: ULONG MaxProcessInfoClass } PROCESSINFOCLASS; typedef struct _file_info { ULONG type; char info; } file_info; typedef struct _ASSEMBLY_STORAGE_MAP { ULONG Flags; ULONG AssemblyCount; PVOID AssemblyArray; } ASSEMBLY_STORAGE_MAP; typedef struct _ASSEMBLY_STORAGE_MAP_ENTRY { ULONG Flags; UNICODE_STRING DosPath; HANDLE Handle; } ASSEMBLY_STORAGE_MAP_ENTRY; typedef struct _ACTIVATION_CONTEXT { LONG RefCount; ULONG Flags; LIST_ENTRY Links; PVOID ActivationContextData; PVOID NotificationRoutine; PVOID NotificationContext; ULONG SentNotifications[8]; ULONG DisabledNotifications[8]; ASSEMBLY_STORAGE_MAP* StorageMap; ASSEMBLY_STORAGE_MAP_ENTRY* InlineStorageMapEntires; ULONG StackTraceIndex; PVOID StackTraces[4][4]; file_info config; file_info appdir; char pad[256]; } ACTIVATION_CONTEXT; #define SEC_NO_FLAGS 0x000 /* Tells the OS to allocate space for this section when loading. This is clear for a section containing debug information only. */ #define SEC_ALLOC 0x001 /* Tells the OS to load the section from the file when loading. This is clear for a .bss section. */ #define SEC_LOAD 0x002 /* The section contains data still to be relocated, so there is some relocation information too. */ #define SEC_RELOC 0x004 #if 0 /* Obsolete ? */ #define SEC_BALIGN 0x008 #endif /* A signal to the OS that the section contains read only data. */ #define SEC_READONLY 0x010 /* The section contains code only. */ #define SEC_CODE 0x020 /* The section contains data only. */ #define SEC_DATA 0x040 /* The section will reside in ROM. */ #define SEC_ROM 0x080 /* The section contains constructor information. This section type is used by the linker to create lists of constructors and destructors used by g++. When a back end sees a symbol which should be used in a constructor list, it creates a new section for the type of name (e.g., __CTOR_LIST__), attaches the symbol to it, and builds a relocation. To build the lists of constructors, all the linker has to do is catenate all the sections called __CTOR_LIST__ and relocate the data contained within - exactly the operations it would peform on standard data. */ #define SEC_CONSTRUCTOR 0x100 /* The section is a constuctor, and should be placed at the end of the text, data, or bss section(?). */ #define SEC_CONSTRUCTOR_TEXT 0x1100 #define SEC_CONSTRUCTOR_DATA 0x2100 #define SEC_CONSTRUCTOR_BSS 0x3100 /* The section has contents - a data section could be SEC_ALLOC | SEC_HAS_CONTENTS; a debug section could be SEC_HAS_CONTENTS */ #define SEC_HAS_CONTENTS 0x200 /* An instruction to the linker to not output the section even if it has information which would normally be written. */ #define SEC_NEVER_LOAD 0x400 /* The section is a COFF shared library section. This flag is only for the linker. If this type of section appears in the input file, the linker must copy it to the output file without changing the vma or size. FIXME: Although this was originally intended to be general, it really is COFF specific (and the flag was renamed to indicate this). It might be cleaner to have some more general mechanism to allow the back end to control what the linker does with sections. */ #define SEC_COFF_SHARED_LIBRARY 0x800 /* The section contains common symbols (symbols may be defined multiple times, the value of a symbol is the amount of space it requires, and the largest symbol value is the one used). Most targets have exactly one of these (which we translate to bfd_com_section_ptr), but ECOFF has two. */ #define SEC_IS_COMMON 0x8000 /* The section contains only debugging information. For example, this is set for ELF .debug and .stab sections. strip tests this flag to see if a section can be discarded. */ #define SEC_DEBUGGING 0x10000 /* The contents of this section are held in memory pointed to by the contents field. This is checked by bfd_get_section_contents, and the data is retrieved from memory if appropriate. */ #define SEC_IN_MEMORY 0x20000 /* The contents of this section are to be excluded by the linker for executable and shared objects unless those objects are to be further relocated. */ #define SEC_EXCLUDE 0x40000 /* The contents of this section are to be sorted by the based on the address specified in the associated symbol table. */ #define SEC_SORT_ENTRIES 0x80000 /* When linking, duplicate sections of the same name should be discarded, rather than being combined into a single section as is usually done. This is similar to how common symbols are handled. See SEC_LINK_DUPLICATES below. */ #define SEC_LINK_ONCE 0x100000 /* If SEC_LINK_ONCE is set, this bitfield describes how the linker should handle duplicate sections. */ #define SEC_LINK_DUPLICATES 0x600000 /* This value for SEC_LINK_DUPLICATES means that duplicate sections with the same name should simply be discarded. */ #define SEC_LINK_DUPLICATES_DISCARD 0x0 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if there are any duplicate sections, although it should still only link one copy. */ #define SEC_LINK_DUPLICATES_ONE_ONLY 0x200000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections are a different size. */ #define SEC_LINK_DUPLICATES_SAME_SIZE 0x400000 /* This value for SEC_LINK_DUPLICATES means that the linker should warn if any duplicate sections contain different contents. */ #define SEC_LINK_DUPLICATES_SAME_CONTENTS 0x600000 /* This section was created by the linker as part of dynamic relocation or other arcane processing. It is skipped when going through the first-pass output, trusting that someone else up the line will take care of it later. */ #define SEC_LINKER_CREATED 0x800000 ================================================ FILE: Src/Includes.h ================================================ #pragma once #include #include #include #include ================================================ FILE: Src/Loader/Loader.cpp ================================================ #include "Loader.h" using namespace WID::Loader; LOADLIBRARY::LOADLIBRARY(TCHAR* DllPath, DWORD Flags, LOADTYPE LoadType) { assert(DllPath); assert(GetFileAttributes(DllPath) != INVALID_FILE_ATTRIBUTES); if (!bInitialized) Init(); memcpy(CreationInfo.DllPath, DllPath, MAX_PATH * sizeof(TCHAR)); CreationInfo.Flags = Flags; CreationInfo.LoadType = LoadType; DllHandle = NULL; NTSTATUS Status = STATUS_SUCCESS; if (Status = Load(), NT_SUCCESS(Status)) { WID_DBG(TEXT("[WID] >> (Path: %s), (Flags: %lu) load successful.\n"), DllPath, Flags); WID_DBG(TEXT("[WID] >> Base address: %p.\n"), DllHandle); } else { WID_DBG(TEXT("[WID] >> (Path: %s), (Flags: %lu) load failed, err: 0x%X.\n"), DllPath, Flags, Status); } } LOADLIBRARY::~LOADLIBRARY() { NTSTATUS Status = STATUS_SUCCESS; if (Status = Unload(), NT_SUCCESS(Status)) { WID_DBG(TEXT("[WID] >> (Path: %s), (Flags: %lu) unload successful.\n"), CreationInfo.DllPath, CreationInfo.Flags); } else { WID_DBG(TEXT("[WID] >> (Path: %s), (Flags: %lu) unload failed, err: 0x%X.\n"), CreationInfo.DllPath, CreationInfo.Flags, Status); } } NTSTATUS LOADLIBRARY::Load() { if (!CreationInfo.DllPath) return STATUS_INVALID_PARAMETER; switch (CreationInfo.LoadType) { case LOADTYPE::DEFAULT: //case LOADTYPE::HIDDEN: DllHandle = fLoadLibrary(CreationInfo.DllPath); if (!DllHandle || DllHandle == INVALID_HANDLE_VALUE) break; return STATUS_SUCCESS; case LOADTYPE::HIDDEN: WID_DBG(TEXT("[WID] >> Hidden loading isn't available currently.\n")); default: return STATUS_INVALID_PARAMETER; } return STATUS_UNSUCCESSFUL; } HMODULE __fastcall LOADLIBRARY::fLoadLibrary(PTCHAR lpLibFileName) // CHECKED. { #ifndef _UNICODE return fLoadLibraryA(lpLibFileName); #else return fLoadLibraryW(lpLibFileName); #endif } HMODULE __fastcall LOADLIBRARY::fLoadLibraryA(LPCSTR lpLibFileName) // CHECKED. { // If no path was given. if (!lpLibFileName) //return LoadLibraryExA(lpLibFileName, 0, 0); return NULL; // If path isn't 'twain_32.dll' // This is where our LoadLibrary calls mostly end up. if (_stricmp(lpLibFileName, "twain_32.dll")) return fLoadLibraryExA(lpLibFileName, 0, 0); // If path is 'twain_32.dll' // Windows probably uses this to make itself a shortcut, while we are using it the code won't reach here. PCHAR Heap = (PCHAR)RtlAllocateHeap(NtCurrentPeb()->ProcessHeap, *KernelBaseGlobalData, MAX_PATH); if (!Heap) return fLoadLibraryExA(lpLibFileName, 0, 0); HMODULE Module; // Heap receives the Windows path (def: C:\Windows) // The BufferSize check made against GetWindowsDirectoryA is to see if it actually received. If it's bigger than BufferSize // then GetWindowsDirectoryA returned the size needed (in summary it fails) // If this check doesn't fail '\twain_32.dll' is appended to the Windows path (def: C:\Windows\twain_32.dll) // Then this final module is loaded into the program. // If it can't load, it tries to load it directly and returns from there. if (GetWindowsDirectoryA(Heap, 0xF7) - 1 > 0xF5 || (strncat_s(Heap, MAX_PATH, "\\twain_32.dll", strlen("\\twain_32.dll")), (Module = fLoadLibraryA(Heap)) == 0)) { RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Heap); return fLoadLibraryExA(lpLibFileName, 0, 0); } RtlFreeHeap(NtCurrentPeb()->ProcessHeap, 0, Heap); return Module; } HMODULE __fastcall LOADLIBRARY::fLoadLibraryW(LPCWSTR lpLibFileName) // CHECKED. { return fLoadLibraryExW(lpLibFileName, 0, 0); } HMODULE __fastcall LOADLIBRARY::fLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) // CHECKED. { UNICODE_STRING Unicode; if (!Basep8BitStringToDynamicUnicodeString(&Unicode, lpLibFileName)) return NULL; HMODULE Module = fLoadLibraryExW(Unicode.Buffer, hFile, dwFlags); RtlFreeUnicodeString(&Unicode); return Module; } HMODULE __fastcall LOADLIBRARY::fLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags) // CHECKED. { NTSTATUS Status; DWORD ConvertedFlags; HMODULE BaseOfLoadedDll; DWORD DatafileFlags = dwFlags & LLEXW_ASDATAFILE; // If no DllName was given OR hFile was given (msdn states that hFile must be 0) OR dwFlags is set to an unknown value OR *both* the Datafile flags are set (they cannot be used together). if (!lpLibFileName || hFile || ((dwFlags & 0xFFFF0000) != 0) || (DatafileFlags == LLEXW_ASDATAFILE)) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } UNICODE_STRING DllName; Status = RtlInitUnicodeStringEx(&DllName, lpLibFileName); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return NULL; } USHORT DllNameLen = DllName.Length; if (!DllName.Length) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } // If the DllName given had empty (space) chars as their last chars, this do-while loop excludes them and sets the excluded length. do { DWORD WchAmount = DllNameLen / 2; if (DllName.Buffer[WchAmount - 1] != ' ' /* 0x20 is space char */) break; DllNameLen -= 2; DllName.Length = DllNameLen; } while (DllNameLen != 2); // In case the above do-while loop misbehaves. if (DllNameLen == 0) { BaseSetLastNTError(STATUS_INVALID_PARAMETER); return NULL; } BaseOfLoadedDll = 0; // If the dll is not getting loaded as a datafile. if ((dwFlags & LLEXW_ISDATAFILE) == 0) { // Converts the actual flags into it's own flag format. Most flags are discarded (only used if loaded as datafile). // Only flags that can go through are DONT_RESOLVE_DLL_REFERENCES, LOAD_PACKAGED_LIBRARY, LOAD_LIBRARY_REQUIRE_SIGNED_TARGET and LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY ConvertedFlags = 0; if ((dwFlags & DONT_RESOLVE_DLL_REFERENCES) != 0) ConvertedFlags |= CNVTD_DONT_RESOLVE_DLL_REFERENCES; if ((dwFlags & LOAD_PACKAGED_LIBRARY) != 0) ConvertedFlags |= LOAD_PACKAGED_LIBRARY; if ((dwFlags & LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) != 0) ConvertedFlags |= CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET; if ((dwFlags & LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY) != 0) ConvertedFlags |= CNVTD_LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY; // Evaluates dwFlags to get meaningful flags, includes DONT_RESOLVE_DLL_REFERENCES finally. // But it doesn't matter because the first param LdrLoadDll takes actually a (PWCHAR PathToFile), so I have no idea why that's done. Status = fLdrLoadDll((PWCHAR)((dwFlags & LLEXW_7F08) | 1), &ConvertedFlags, &DllName, (PVOID*)&BaseOfLoadedDll); if (NT_SUCCESS(Status)) return BaseOfLoadedDll; BaseSetLastNTError(Status); return NULL; } PWSTR Path; PWSTR Unknown; // Gets the Dll path. Status = LdrGetDllPath(DllName.Buffer, (dwFlags & LLEXW_7F08), &Path, &Unknown); if (!NT_SUCCESS(Status)) { BaseSetLastNTError(Status); return NULL; } // First step into loading a module as datafile. Status = fBasepLoadLibraryAsDataFileInternal(&DllName, Path, Unknown, dwFlags, &BaseOfLoadedDll); // If the Status is only success (excludes warnings) AND if the module is image resource, loads again. I don't know why. if (NT_SUCCESS(Status + 0x80000000) && Status != STATUS_NO_SUCH_FILE && (dwFlags & LOAD_LIBRARY_AS_IMAGE_RESOURCE)) { if (DatafileFlags) Status = fBasepLoadLibraryAsDataFileInternal(&DllName, Path, Unknown, DatafileFlags, &BaseOfLoadedDll); } RtlReleasePath(Path); BaseSetLastNTError(Status); return NULL; } NTSTATUS __fastcall LOADLIBRARY::fLdrLoadDll(PWSTR DllPath, PULONG pFlags, PUNICODE_STRING DllName, PVOID* BaseAddress) // CHECKED. { NTSTATUS Status; // DllPath can also be used as Flags if called from LoadLibraryExW UINT_PTR FlagUsed = 0; if (pFlags) { // Only flags that could go through *LoadLibraryExW* were; // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) // LOAD_PACKAGED_LIBRARY (0x4) // CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x800000) // CNVTD_LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY (0x80000000) // So I am assuming the rest of the flags are 0. UINT_PTR ActualFlags = *pFlags; // If LOAD_PACKAGED_LIBRARY (0x4) flag is set (1) FlagUsed becomes CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2), if not set (0) FlagUsed becomes 0. FlagUsed = CNVTD_DONT_RESOLVE_DLL_REFERENCES * (ActualFlags & LOAD_PACKAGED_LIBRARY); // (MSDN about DONT_RESOLVE_DLL_REFERENCES) Note Do not use this value; it is provided only for backward compatibility. // If you are planning to access only data or resources in the DLL, use LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE // or LOAD_LIBRARY_AS_IMAGE_RESOURCE or both. Otherwise, load the library as a DLL or executable module using the LoadLibrary function. FlagUsed |= ((ActualFlags & CNVTD_DONT_RESOLVE_DLL_REFERENCES) ? LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE : NULL); FlagUsed |= ((ActualFlags & CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET) ? LOAD_LIBRARY_REQUIRE_SIGNED_TARGET : NULL); // Ignored because ActualFlags can't have 0x1000 (if called from LoadLibraryExW), this value is used probably in calls from different functions. FlagUsed |= ((ActualFlags & 0x1000) ? 0x100 : 0x0); // Ignored because ActualFlags can't be negative (if called from LoadLibraryExW), this value is used probably in calls from different functions. FlagUsed |= ((ActualFlags < 0) ? 0x400000 : 0x0); // To sum up, in case we are called from LoadLibraryExW, the most flags we can have are; // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x244, "LdrLoadDll", 3u, "DLL name: %wZ\n", DllName); ) if ((*LdrpPolicyBits & 4) == 0 && ((USHORT)DllPath & LLDLL_401) == LLDLL_401) return STATUS_INVALID_PARAMETER; // In here it will go in by the first condition, because 8 couldn't be set by LoadLibraryExW. if ((FlagUsed & LOAD_WITH_ALTERED_SEARCH_PATH) == 0 || (*LdrpPolicyBits & 8) != 0) { // If the current thread is a Worker Thread it fails. if (NtCurrentTeb()->SameTebFlags & LoaderWorker) { Status = STATUS_INVALID_THREAD; } else { LDR_UNKSTRUCT DllPathInited; // There's another LdrpLogInternal inside this function, gonna mess with that later on. LdrpInitializeDllPath(DllName->Buffer, DllPath, &DllPathInited); LDR_DATA_TABLE_ENTRY* DllEntry; Status = fLdrpLoadDll(DllName, &DllPathInited, FlagUsed, &DllEntry); if (DllPathInited.IsInitedMaybe) RtlReleasePath(DllPathInited.pInitNameMaybe); if (NT_SUCCESS(Status)) { // Changes the actual return value and dereferences the module. *BaseAddress = DllEntry->DllBase; LdrpDereferenceModule(DllEntry); } } } else { // LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 601, "LdrLoadDll", 0, &LdrEntry[176]); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x259, "LdrLoadDll", 0, "Nonpackaged process attempted to load a packaged DLL.\n"); ) Status = STATUS_NO_APPLICATION_PACKAGE; } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x279, "LdrLoadDll", 4, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpLoadDll(PUNICODE_STRING DllName, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, LDR_DATA_TABLE_ENTRY** DllEntry) // CHECKED. { NTSTATUS Status; WID_HIDDEN( LdrpLogDllState(0, DllName, 0x14A8); ) // Flags is passed by value so no need to create a backup, it's already a backup by itself. // MOST FLAGS = CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) // Creates a new unicode_string and allocates it some buffer. UNICODE_STRING FullDllPath; WCHAR Buffer[128]; FullDllPath.Length = 0; FullDllPath.MaximumLength = MAX_PATH - 4; FullDllPath.Buffer = Buffer; Buffer[0] = 0; // Returns the Absolute path // If a non-relative path was given then the flags will be ORed with LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) // resulting in the MOST FLAGS being: // CNVTD_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) | // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) Status = LdrpPreprocessDllName(DllName, &FullDllPath, 0, &Flags); if (NT_SUCCESS(Status)) // A even deeper function, by far we can see Windows is kinda all *wrapped* around each other. // This function is responsible for the linking issue. fLdrpLoadDllInternal(&FullDllPath, DllPathInited, Flags, ImageDll, 0, 0, DllEntry, &Status, 0); if (Buffer != FullDllPath.Buffer) NtdllpFreeStringRoutine(FullDllPath.Buffer); // I don't see no point in this but anyways. FullDllPath.Length = 0; FullDllPath.MaximumLength = MAX_PATH - 4; FullDllPath.Buffer = Buffer; Buffer[0] = 0; WID_HIDDEN( LdrpLogDllState(0, DllName, 0x14A9); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpLoadDllInternal(PUNICODE_STRING FullPath, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, ULONG LdrFlags, PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY LdrEntry2, PLDR_DATA_TABLE_ENTRY* DllEntry, NTSTATUS* pStatus, ULONG Zero) // CHECKED. // This function is responsible for the linking issue. { NTSTATUS Status; // NOTES: // I assumed that LdrFlags (which was sent as 0x4 (ImageDll) by LdrpLoadDll) is the same flags inside LDR_DATA_TABLE_ENTRY. // LdrEntry & LdrEntry2 were both sent as 0s by LdrpLoadDll. // // Instead of using gotos which causes the local variables to be initialized in the start of the function (making it look not good in my opinion) // I created a do-while loop. The outcome won't be affected. // // MOST FLAGS = CONVERTED_DONT_RESOLVE_DLL_REFERENCES (0x2) | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE (0x40) | LOAD_LIBRARY_REQUIRE_SIGNED_TARGET (0x80) // LOAD_LIBRARY_SEARCH_APPLICATION_DIR (0x200) | LOAD_LIBRARY_SEARCH_USER_DIRS (0x400) WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x379, "LdrpLoadDllInternal", 3, "DLL name: %wZ\n", FullPath); ) bool IsWorkerThread = false; do { *DllEntry = 0; LdrEntry = LdrEntry2; // This will go in. if (LdrFlags != (PackagedBinary | LoadNotificationsSent)) { // This function does some prior setup, incrementing the module load count is done inside here. Status = LdrpFastpthReloadedDll(FullPath, Flags, LdrEntry2, DllEntry); // returns STATUS_DLL_NOT_FOUND in normal circumstances. // If not an actual nt success (excludes warnings) if (!NT_SUCCESS((LONG)(Status + 0x80000000)) || Status == STATUS_IMAGE_LOADED_AS_PATCH_IMAGE) { *pStatus = Status; break; } } IsWorkerThread = ((NtCurrentTeb()->SameTebFlags & LoadOwner) == 0); if (IsWorkerThread) LdrpDrainWorkQueue(WaitLoadComplete); // This won't go in so we can ignore it. I still did simplifying though. // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one. if (LdrFlags == (PackagedBinary | LoadNotificationsSent)) { Status = LdrpFindLoadedDllByHandle(Zero, &LdrEntry, 0); if (!NT_SUCCESS(Status)) { if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } if (LdrEntry->HotPatchState == LdrHotPatchFailedToPatch) { Status = STATUS_PATCH_CONFLICT; if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } Status = LdrpQueryCurrentPatch(LdrEntry->CheckSum, LdrEntry->TimeDateStamp, FullPath); if (!NT_SUCCESS(Status)) { if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } if (!FullPath->Length) { if (LdrEntry->ActivePatchImageBase) Status = LdrpUndoPatchImage(LdrEntry); if (FullPath->Buffer) LdrpFreeUnicodeString(FullPath); *pStatus = Status; if (IsWorkerThread) LdrpDropLastInProgressCount(); break; } // LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x3FA, "LdrpLoadDllInternal", 2u, &::LdrEntry[232], FullPath); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x3FA, "LdrpLoadDllInternal", 2, "Loading patch image: %wZ\n", FullPath); ) } // Opens a token to the current thread and sets GLOBAL variable LdrpMainThreadToken with that token. LdrpThreadTokenSetMainThreadToken(); // returns STATUS_NO_TOKEN in normal circumstances. LDR_DATA_TABLE_ENTRY* pLdrEntryLoaded = 0; // This will go in by the first check LdrEntry2 because it was sent as 0 in LdrpLoadDll. if (!LdrEntry || !IsWorkerThread || LdrEntry->DdagNode->LoadCount) { // I checked the function, it detects a hook by byte scanning these following functions; // ntdll!NtOpenFile // ntdll!NtCreateSection // ntdll!ZqQueryAttributes // ntdll!NtOpenSection // ntdll!ZwMapViewOfSection // Resulting in the global variable LdrpDetourExist to be set if there's a hook, didn't checked what's done with it though. LdrpDetectDetour(); // [IGNORE THIS] Finds the module, increments the loaded module count. [IGNORE THIS] // [IGNORE THIS] It can go to another direction if the Flag LOAD_LIBRARY_SEARCH_APPLICATION_DIR was set, but that couldn't be set coming from LoadLibraryExW. [IGNORE THIS] // If LoadLibrary was given an absolute path, Flags will have LOAD_LIBRARY_SEARCH_APPLICATION_DIR causing this function to call LdrpLoadKnownDll. // In our case LdrpFindOrPrepareLoadingModule actually returns STATUS_DLL_NOT_FOUND, which I thought was a bad thing but after checking up inside // inside LdrpProcessWork it didn't looked that bad. // So our dll loading part is actually inside LdrpProcessWork (for calling LoadLibraryExW with an absolute path and 0 flags at least) //Status = LdrpFindOrPrepareLoadingModule(FullPath, DllPathInited, Flags, LdrFlags, LdrEntry, &pLdrEntryLoaded, pStatus); Status = LdrpFindOrPrepareLoadingModule(FullPath, DllPathInited, Flags, LdrFlags, LdrEntry, &pLdrEntryLoaded, pStatus); if (Status == STATUS_DLL_NOT_FOUND) // Even if the DllMain call succeeds, there's still runtime bugs on the dll side, like the dll not being able to unload itself and such. So I still got // a lot of work to do. fLdrpProcessWork(pLdrEntryLoaded->LoadContext, TRUE); else if (Status != STATUS_RETRY && !NT_SUCCESS(Status)) *pStatus = Status; } else { *pStatus = STATUS_DLL_NOT_FOUND; } LdrpDrainWorkQueue(WaitWorkComplete); if (*LdrpMainThreadToken) // Closes the token handle, and sets GLOBAL variable LdrpMainThreadToken to 0. LdrpThreadTokenUnsetMainThreadToken(); if (pLdrEntryLoaded) { *DllEntry = LdrpHandleReplacedModule(pLdrEntryLoaded); if (pLdrEntryLoaded != *DllEntry) { LdrpFreeReplacedModule(pLdrEntryLoaded); pLdrEntryLoaded = *DllEntry; if (pLdrEntryLoaded->LoadReason == LoadReasonPatchImage && LdrFlags != (PackagedBinary | LoadNotificationsSent)) *pStatus = STATUS_IMAGE_LOADED_AS_PATCH_IMAGE; } if (pLdrEntryLoaded->LoadContext) LdrpCondenseGraph(pLdrEntryLoaded->DdagNode); if (NT_SUCCESS(*pStatus)) { // [IGNORE THIS] In here I realized that the module must have already been loaded to be prepared for execution. // [IGNORE THIS] So I've gone a little back and realized the actual loading was done in the LdrpDrainWorkQueue function. // Doing more research revealed it was inside LdrpProcessWork after LdrpFindOrPrepareLoadingModule returning STATUS_DLL_NOT_FOUND. Status = fLdrpPrepareModuleForExecution(pLdrEntryLoaded, pStatus); *pStatus = Status; if (NT_SUCCESS(Status)) { Status = LdrpBuildForwarderLink(LdrEntry, pLdrEntryLoaded); *pStatus = Status; if (NT_SUCCESS(Status) && !*LdrInitState) LdrpPinModule(pLdrEntryLoaded); } // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one too. if (LdrFlags == (PackagedBinary | LoadNotificationsSent) && LdrEntry->ActivePatchImageBase != pLdrEntryLoaded->DllBase) { if (pLdrEntryLoaded->HotPatchState == LdrHotPatchFailedToPatch) { *pStatus = STATUS_DLL_INIT_FAILED; } else { Status = LdrpApplyPatchImage(pLdrEntryLoaded); *pStatus = Status; if (!NT_SUCCESS(Status)) { //UNICODE_STRING Names[4]; //Names[0] = pLdrEntryLoaded->FullDllName; //WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x4AF, "LdrpLoadDllInternal", 0, "Applying patch \"%wZ\" failed\n", Names); ) WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x4AF, "LdrpLoadDllInternal", 0, "Applying patch \"%wZ\" failed\n", pLdrEntryLoaded->FullDllName); ) } } } } LdrpFreeLoadContextOfNode(pLdrEntryLoaded->DdagNode, pStatus); if (!NT_SUCCESS(*pStatus) && (LdrFlags != (PackagedBinary | LoadNotificationsSent) || pLdrEntryLoaded->HotPatchState != LdrHotPatchAppliedReverse)) { *DllEntry = 0; LdrpDecrementModuleLoadCountEx(pLdrEntryLoaded, 0); LdrpDereferenceModule(pLdrEntryLoaded); } } else { *pStatus = STATUS_NO_MEMORY; } } while (FALSE); if (IsWorkerThread) LdrpDropLastInProgressCount(); // LoadNotificationsSent (0x8) | PackagedBinary (0x1) // Because the LdrFlags was sent 0x4 (ImageDll), we can ignore this one too. if (LdrFlags == (LoadNotificationsSent | PackagedBinary) && LdrEntry) LdrpDereferenceModule(LdrEntry); Status = *pStatus; WID_HIDDEN( Status = LdrpLogInternal("minkernel\\ntdll\\ldrapi.c", 0x52E, "LdrpLoadDllInternal", 4, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpProcessWork(PLDRP_LOAD_CONTEXT LoadContext, BOOLEAN IsLoadOwner) // CHECKED. { NTSTATUS Status; // Converted goto to do-while loop. do { Status = *LoadContext->pStatus; if (!NT_SUCCESS(Status)) break; // Caused most likely because CONTAINING_RECORD macro was used, I have no idea what's going on. // Also the structure used (LDRP_LOAD_CONTEXT) isn't documented, that's what I've got out of it so far. if ((UINT_PTR)LoadContext->WorkQueueListEntry.Flink[9].Blink[3].Blink & UINT_MAX) { Status = fLdrpSnapModule(LoadContext); } else { if (LoadContext->Flags & 0x100000) { Status = fLdrpMapDllRetry(LoadContext); } // We will continue from here since we have the LOAD_LIBRARY_SEARCH_APPLICATION_DIR flag, and also the function name is exactly representing // what we are expecting to happen. else if (LoadContext->Flags & LOAD_LIBRARY_SEARCH_APPLICATION_DIR) { Status = fLdrpMapDllFullPath(LoadContext); } else { Status = fLdrpMapDllSearchPath(LoadContext); } if (NT_SUCCESS(Status) || Status == STATUS_RETRY) break; //Status = LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x7D2, "LdrpProcessWork", 0, "Unable to load DLL: \"%wZ\", Parent Module: \"%wZ\", Status: 0x%x\n", LoadContext, &LoadContext->Entry->FullDllName & (unsigned __int64)((unsigned __int128)-(__int128)(unsigned __int64)LoadContext->Entry >> 64), Status); WID_HIDDEN( Status = LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x7D2, "LdrpProcessWork", 0, "Unable to load DLL: \"%wZ\", Parent Module: \"%wZ\", Status: 0x%x\n", LoadContext, ((UINT_PTR)&LoadContext->Entry->FullDllName & (UINT_PTR)LoadContext->Entry >> 64), Status); ) // This part is for failed cases so we can ignore it. if (Status == STATUS_DLL_NOT_FOUND) { WID_HIDDEN( LdrpLogError(STATUS_DLL_NOT_FOUND, 0x19, 0, LoadContext); ) WID_HIDDEN( LdrpLogDeprecatedDllEtwEvent(LoadContext); ) //LdrpLogLoadFailureEtwEvent((DWORD)LoadContext,(DWORD(LoadContext->Entry) + 0x48) & ((unsigned __int128)-(__int128)(unsigned __int64)LoadContext->Entry >> 64),STATUS_DLL_NOT_FOUND,(unsigned int)&LoadFailure,0); WID_HIDDEN( LdrpLogLoadFailureEtwEvent((PVOID)LoadContext, (PVOID)(((UINT_PTR)(LoadContext->Entry->EntryPointActivationContext) & ((UINT_PTR)(LoadContext->Entry) >> 64))), STATUS_DLL_NOT_FOUND, LoadFailure, 0); ) //PLDR_DATA_TABLE_ENTRY DllEntry = (PLDR_DATA_TABLE_ENTRY)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (DllEntry->FlagGroup[0] & ProcessStaticImport) { WID_HIDDEN( Status = LdrpReportError(LoadContext, 0, STATUS_DLL_NOT_FOUND); ) } } } if (!NT_SUCCESS(Status)) { *LoadContext->pStatus = Status; } } while (FALSE); if (!IsLoadOwner) { bool SetWorkCompleteEvent; //RtlEnterCriticalSection(&LdrpWorkQueueLock); RtlEnterCriticalSection(LdrpWorkQueueLock); --(*LdrpWorkInProgress); if (*LdrpWorkQueue != (LIST_ENTRY*)LdrpWorkQueue || (SetWorkCompleteEvent = TRUE, *LdrpWorkInProgress != 1)) SetWorkCompleteEvent = FALSE; //Status = RtlLeaveCriticalSection(&LdrpWorkQueueLock); Status = RtlLeaveCriticalSection(LdrpWorkQueueLock); if (SetWorkCompleteEvent) Status = ZwSetEvent(*LdrpWorkCompleteEvent, 0); } return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpSnapModule(PLDRP_LOAD_CONTEXT LoadContext) { NTSTATUS Status = STATUS_SUCCESS; NTSTATUS Status_2 = STATUS_SUCCESS; NTSTATUS Status_3 = STATUS_SUCCESS; NTSTATUS NtStatus = STATUS_SUCCESS; FUNCTION_TABLE_DATA FunctionTableData{}; FUNCTION_TABLE_DATA FunctionTableData2{}; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; PUNICODE_STRING FullDllName = &DllEntry->FullDllName; WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllBase, &DllEntry->FullDllName, 0x14A6u); ) LdrpHandlePendingModuleReplaced(LoadContext); PIMAGE_DOS_HEADER DosHeaders[8]; memset(DosHeaders, 0, sizeof(DosHeaders)); PIMAGE_SECTION_HEADER SectionHeader = nullptr; LONG DosHeaderIdx = 0; ULONG v93 = 0; BOOL SomeStatus = FALSE; LDR_DATA_TABLE_ENTRY* DllEntry_2 = nullptr; LDR_DATA_TABLE_ENTRY* DllEntry_3 = nullptr; PCHAR GuardCFArray = nullptr; PCHAR GuardCFArray2VA = nullptr; PIMAGE_SECTION_HEADER SectionHeader_2; while (TRUE) { SomeStatus = TRUE; ULONG OriginalIATProtect = LoadContext->OriginalIATProtect; if (OriginalIATProtect >= LoadContext->SizeOfIAT) { Status = fLdrpDoPostSnapWork(LoadContext); if (NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllEntry->DllBase, &DllEntry->FullDllName, 0x14A7u); ) DllEntry->DdagNode->State = LdrModulesSnapped; } goto SET_LOAD_CONTEXT; } UINT_PTR OriginalIATProtect_2 = OriginalIATProtect; LDR_DATA_TABLE_ENTRY* IdxLdrEntry = LoadContext->IATCheck[OriginalIATProtect]; DllEntry_2 = IdxLdrEntry; DllEntry_3 = IdxLdrEntry; if (IdxLdrEntry) { LDRP_LOAD_CONTEXT* LoadContext_2 = IdxLdrEntry->LoadContext; if (LoadContext_2) { if ((LoadContext_2->Flags & 0x80000) == 0 && CONTAINING_RECORD(LoadContext_2->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks) != IdxLdrEntry) { DllEntry_2 = CONTAINING_RECORD(LoadContext_2->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); DllEntry_3 = DllEntry_2; LoadContext_2->WorkQueueListEntry.Flink = &IdxLdrEntry->InLoadOrderLinks; } } } LDR_DATA_TABLE_ENTRY* IdxLdrEntry_2 = LoadContext->IATCheck[OriginalIATProtect_2]; if (IdxLdrEntry_2 != DllEntry_2) { LdrpFreeReplacedModule(IdxLdrEntry_2); LoadContext->IATCheck[OriginalIATProtect_2] = DllEntry_2; } ULONG* GuardCFCheckFunctionPointer = (ULONG*)LoadContext->GuardCFCheckFunctionPointer; UINT_PTR GuardCFArrayVA = GuardCFCheckFunctionPointer[5 * OriginalIATProtect_2]; GuardCFArray = (char*)DllBase + GuardCFArrayVA; GuardCFArray2VA = (char*)DllBase + GuardCFCheckFunctionPointer[5 * OriginalIATProtect_2 + 4]; if (!(DWORD)GuardCFArrayVA || (unsigned int)GuardCFArrayVA > DllEntry->SizeOfImage) GuardCFArray = (char*)DllBase + GuardCFCheckFunctionPointer[5 * OriginalIATProtect_2 + 4]; if (DllEntry_2) break; INCREMENT_IAT_PROTECT: ++LoadContext->OriginalIATProtect; } PIMAGE_DOS_HEADER DllBase_3 = DllEntry_2->DllBase; PIMAGE_DOS_HEADER DllBase_4 = DllBase_3; BOOLEAN DllBaseUnknownFlagCheck = TRUE; PIMAGE_DOS_HEADER DllBase_5 = DllBase_3; PIMAGE_NT_HEADERS32 pNtHeader = nullptr; PIMAGE_EXPORT_DIRECTORY pImageExportDir_2 = nullptr; if (((BYTE)DllBase_3 & 3) != 0) { DllBase_5 = (PIMAGE_DOS_HEADER)((UINT_PTR)DllBase_3 & 0xFFFFFFFFFFFFFFFC); DllBaseUnknownFlagCheck = ((BYTE)DllBase_3 & 1) == 0; } NtStatus = RtlImageNtHeaderEx(1u, DllBase_5, 0i64, (PIMAGE_NT_HEADERS*)&pNtHeader); if (!pNtHeader) goto ZERO_IMAGE_EXPORT_DIR_2; WORD Magic = pNtHeader->OptionalHeader.Magic; ULONG DirectorySize = 0; UINT_PTR DirectoryVA = 0; // For 32-bit apps // Checks if it's not a 32-bit app if (Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // For 64-bit apps if (Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC && pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size) { DirectoryVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; if ((DWORD)DirectoryVA) { DirectorySize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size; if (!DllBaseUnknownFlagCheck && (ULONG)DirectoryVA >= pNtHeader->OptionalHeader.SizeOfHeaders) { SectionHeader_2 = RtlAddressInSectionTable((PIMAGE_NT_HEADERS)pNtHeader, DllBase_5, (ULONG)DirectoryVA); pImageExportDir_2 = (PIMAGE_EXPORT_DIRECTORY)SectionHeader_2; NtStatus = STATUS_SUCCESS; if (!SectionHeader_2) NtStatus = STATUS_INVALID_PARAMETER; goto NT_STUFF; } GET_IMAGE_EXPORT_DIR: SectionHeader_2 = (PIMAGE_SECTION_HEADER)((char*)DllBase_5 + DirectoryVA); pImageExportDir_2 = (PIMAGE_EXPORT_DIRECTORY)((char*)DllBase_5 + DirectoryVA); NtStatus = STATUS_SUCCESS; goto NT_STUFF; } NtStatus = STATUS_NOT_IMPLEMENTED; ZERO_IMAGE_EXPORT_DIR_2: SectionHeader_2 = nullptr; goto NT_STUFF; } ZERO_IMAGE_EXPORT_DIR: NtStatus = STATUS_INVALID_PARAMETER; goto ZERO_IMAGE_EXPORT_DIR_2; } if (!pNtHeader->OptionalHeader.NumberOfRvaAndSizes) goto ZERO_IMAGE_EXPORT_DIR; DirectoryVA = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (!(DWORD)DirectoryVA) { NtStatus = STATUS_NOT_IMPLEMENTED; goto ZERO_IMAGE_EXPORT_DIR_2; } DirectorySize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (DllBaseUnknownFlagCheck || (ULONG)DirectoryVA < pNtHeader->OptionalHeader.SizeOfHeaders) goto GET_IMAGE_EXPORT_DIR; SectionHeader_2 = RtlAddressInSectionTable((PIMAGE_NT_HEADERS)pNtHeader, DllBase_5, (ULONG)DirectoryVA); pImageExportDir_2 = (PIMAGE_EXPORT_DIRECTORY)SectionHeader_2; NtStatus = STATUS_SUCCESS; if (!SectionHeader_2) NtStatus = STATUS_INVALID_PARAMETER; NT_STUFF: if (!NT_SUCCESS(NtStatus)) { SectionHeader_2 = nullptr; pImageExportDir_2 = nullptr; } if (!SectionHeader_2) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 3278, "LdrpSnapModule", 0, "DLL \"%wZ\" does not contain an export table\n", &DllEntry_3->FullDllName); ) Status = STATUS_INVALID_IMAGE_FORMAT; SomeStatus = TRUE; goto SET_LOAD_CONTEXT; } ULONG i = 0; BOOLEAN IsFinalIdx = FALSE; for (i = 0; ; ++i) { IsFinalIdx = i == 8; if (i >= 8) break; PIMAGE_DOS_HEADER IdxDosHeader = DosHeaders[i]; if (!IdxDosHeader || DllBase_3 == IdxDosHeader) { IsFinalIdx = i == 8; break; } } if (IsFinalIdx || !DosHeaders[i]) { if (LdrControlFlowGuardEnforced()) { if (DllBase_3 < (*stru_199520).ImageBase || DllBase_3 >= (PIMAGE_DOS_HEADER)((char*)(*stru_199520).ImageBase + (*stru_199520).ImageSize)) { RtlpxLookupFunctionTable(DllBase_3, (PIMAGE_RUNTIME_FUNCTION_ENTRY*)&FunctionTableData); } else { FunctionTableData = (*stru_199520); } if (FunctionTableData.ImageBase != DllBase_3) goto LABEL_188; } DosHeaders[DosHeaderIdx] = DllBase_3; DosHeaderIdx = ((BYTE)DosHeaderIdx + 1) & 7; } PCHAR v27 = (CHAR*)&SectionHeader_2->Name[DirectorySize]; PCHAR v108 = v27; UINT_PTR* pFuncAddresses = (UINT_PTR*)((char*)&DllBase_3->e_magic + SectionHeader_2->PointerToLinenumbers); UINT_PTR* pFuncAddresses_2 = pFuncAddresses; DWORD NumberNames = SectionHeader_2->PointerToRelocations; DWORD NumberNames_2 = NumberNames; PCHAR pAddressNames = (char*)DllBase_3 + *(unsigned int*)&SectionHeader_2->NumberOfRelocations; PCHAR pAddressNames_2 = pAddressNames; PSHORT pNameOrdinals = (SHORT*)((char*)DllBase_3 + SectionHeader_2->Characteristics); UINT_PTR IATIdx = 8 * (*(&LoadContext->OriginalIATProtect + 1)); UINT_PTR* v32 = (UINT_PTR*)&GuardCFArray[IATIdx]; UINT_PTR* v33 = (UINT_PTR*)&GuardCFArray2VA[IATIdx]; UINT_PTR v36 = 0; PCHAR v104 = 0; while (TRUE) { UINT_PTR* v106 = v33; UINT_PTR* v105 = v32; UINT_PTR v34 = *v32; if (!*v32) { *(&LoadContext->OriginalIATProtect + 1) = 0; goto INCREMENT_IAT_PROTECT; } Status = STATUS_PROCEDURE_NOT_FOUND; v36 = v34 >> 63; UINT_PTR v103 = v34 >> 63; PCHAR FunctionIdxAddress = (PCHAR)0xFFFFFFFFFFBADD11; ULONG FunctionIdx = 0; v104 = 0; if ((v34 & 0x8000000000000000) != 0) { v93 = (USHORT)v34; FunctionIdx = (USHORT)v34 - SectionHeader_2->SizeOfRawData; } else { PCHAR v38 = (char*)DllEntry->DllBase + (ULONG)v34; v104 = v38 + 2; if ((LoadContext->Flags & 0x2000000) != 0) { PCHAR v79 = LdrpCheckRedirection(DllEntry, DllEntry_3, v38 + 2); FunctionIdxAddress = v79; if (v79 != (PCHAR)0xFFFFFFFFFFBADD11) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 3375, "LdrpSnapModule", 2u, "Import '%s' of DLL '%wZ' is redirected to 0x%p", v38 + 2, FullDllName, v79); ) SectionHeader_2 = (PIMAGE_SECTION_HEADER)pImageExportDir_2; goto LABEL_54; } pAddressNames = pAddressNames_2; NumberNames = NumberNames_2; } LONG NameOrdinalIdx = *(USHORT*)v38; LONG v40 = 0; LONG NumberNamesM1 = NumberNames - 1; if (NameOrdinalIdx >= NumberNames) NameOrdinalIdx = NumberNamesM1 / 2; if (NumberNamesM1 < 0) { SET_SOMESTATUS_LOG_RETURN: SomeStatus = TRUE; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 2190, "LdrpNameToOrdinal", 1u, "Procedure \"%s\" could not be located in DLL at base 0x%p.\n", v38 + 2, DllBase_3); ) SectionHeader_2 = (PIMAGE_SECTION_HEADER)pImageExportDir_2; goto CHECK_STATUS_GOON; } LONG v45 = 0; while (TRUE) { PBOOLEAN v42 = (BOOLEAN*)(v38 + 2); BOOLEAN v44 = FALSE; PCHAR Names = (PCHAR)((char*)DllBase_3 + *(unsigned int*)&pAddressNames[4 * NameOrdinalIdx] - (v38 + 2)); while (TRUE) { v44 = *v42; if (*v42 != Names[(UINT_PTR)v42]) break; ++v42; if (!v44) { v45 = 0; goto LABEL_41; } } v45 = v44 < (unsigned int)Names[(UINT_PTR)v42] ? -1 : 1; LABEL_41: if (!v45) break; LONG NameOrdinalIdxM1 = NameOrdinalIdx - 1; if (v45 >= 0) NameOrdinalIdxM1 = NumberNamesM1; NumberNamesM1 = NameOrdinalIdxM1; if (v45 >= 0) v40 = NameOrdinalIdx + 1; NameOrdinalIdx = (v40 + NameOrdinalIdxM1) / 2; pAddressNames = pAddressNames_2; if (NameOrdinalIdxM1 < v40) goto SET_SOMESTATUS_LOG_RETURN; } FunctionIdx = (USHORT)pNameOrdinals[NameOrdinalIdx]; SectionHeader_2 = (PIMAGE_SECTION_HEADER)pImageExportDir_2; pFuncAddresses = pFuncAddresses_2; v27 = v108; } if (FunctionIdx >= SectionHeader_2->PointerToRawData) { LABEL_52: SomeStatus = TRUE; goto CHECK_STATUS_GOON; } _mm_lfence(); UINT_PTR FunctionIdxAddressVA = *((ULONG*)pFuncAddresses + FunctionIdx); if (!(DWORD)FunctionIdxAddressVA) { Status = STATUS_PROCEDURE_NOT_FOUND; goto LABEL_52; } FunctionIdxAddress = (char*)DllBase_3 + FunctionIdxAddressVA; PCHAR FunctionIdxAddress_2 = (char*)DllBase_3 + FunctionIdxAddressVA; Status = STATUS_SUCCESS; if ((char*)DllBase_3 + FunctionIdxAddressVA <= (char*)SectionHeader_2 || FunctionIdxAddress >= v27) goto LABEL_52; LDR_DATA_TABLE_ENTRY* NtLdrEntry = DllEntry_3; PCHAR FunctionIdxAddress_3 = (char*)DllBase_3 + FunctionIdxAddressVA; pNtHeader = nullptr; LDR_DATA_TABLE_ENTRY* NtLdrEntry_2 = nullptr; LDRP_LOAD_CONTEXT* LoadContext_3 = DllEntry->LoadContext; LDRP_LOAD_CONTEXT* v111 = LoadContext_3; PVOID v101 = nullptr; STRING SourceString = {}; PCHAR SourceBuffer = SourceString.Buffer; USHORT SourceLength = SourceString.Length; while (TRUE) { PCHAR StringToBeHashed = 0; PCHAR DotOccurence = strrchr(FunctionIdxAddress_3, '.'); if (!DotOccurence || (unsigned __int64)(DotOccurence - FunctionIdxAddress_3) > 0xFFFF) goto LABEL_169; SourceBuffer = FunctionIdxAddress_3; SourceString.Buffer = FunctionIdxAddress_3; SourceLength = (WORD)DotOccurence - (WORD)FunctionIdxAddress_3; SourceString.Length = (WORD)DotOccurence - (WORD)FunctionIdxAddress_3; SourceString.MaximumLength = (WORD)DotOccurence - (WORD)FunctionIdxAddress_3; if (DotOccurence[1] != '#') { StringToBeHashed = DotOccurence + 1; goto LABEL_64; } PCHAR StringToBeHashed_2 = nullptr; ULONG IntValue = 0; BOOL SomeStatus_2 = FALSE; if (RtlCharToInteger(DotOccurence + 2, 0, &IntValue) >= 0) { StringToBeHashed = nullptr; LABEL_64: StringToBeHashed_2 = StringToBeHashed; Status = STATUS_SUCCESS; SomeStatus_2 = TRUE; } else { LABEL_169: Status = STATUS_INVALID_IMAGE_FORMAT; SomeStatus_2 = FALSE; StringToBeHashed = StringToBeHashed_2; } if (!SomeStatus_2) goto LABEL_105; // 4 spaces, ldtn, 1 space, l if (SourceLength == 5 && (*(DWORD*)SourceBuffer | ' ') == 'ldtn' && ((BYTE)SourceBuffer[4] | ' ') == 'l') { NtLdrEntry = (LDR_DATA_TABLE_ENTRY*)(*LdrpNtDllDataTableEntry); NtLdrEntry_2 = (LDR_DATA_TABLE_ENTRY*)(*LdrpNtDllDataTableEntry); } else { Status = LdrpLoadDependentModuleA((PUNICODE_STRING)&SourceString, LoadContext_3, NtLdrEntry, 1, &NtLdrEntry_2, (UINT_PTR)&v101); SomeStatus = TRUE; if (!NT_SUCCESS(Status) || Status == STATUS_PENDING) goto LOAD_DEPENDENTA_FAILED; NtLdrEntry = NtLdrEntry_2; SourceBuffer = SourceString.Buffer; SourceLength = SourceString.Length; } PCHAR v85 = 0; if ((DllEntry->LoadContext->Flags & 0x2000000) != 0) { if (StringToBeHashed) { FunctionIdxAddress_3 = LdrpCheckRedirection(DllEntry, NtLdrEntry, StringToBeHashed); v85 = FunctionIdxAddress_3; if (FunctionIdxAddress_3 != (PCHAR)0xFFFFFFFFFFBADD11) { Status = STATUS_SUCCESS; SomeStatus = TRUE; goto LABEL_109; } } } PIMAGE_DOS_HEADER NtBase = NtLdrEntry->DllBase; BOOLEAN SomeNtCheck = TRUE; PIMAGE_DOS_HEADER NtBase_2 = NtBase; PIMAGE_NT_HEADERS OutHeaders = nullptr; if (((BYTE)NtBase & 3) != 0) { NtBase_2 = (PIMAGE_DOS_HEADER)((UINT_PTR)NtBase & 0xFFFFFFFFFFFFFFFC); SomeNtCheck = ((BYTE)NtBase & 1) == 0; } Status_2 = RtlImageNtHeaderEx(1u, NtBase_2, 0, &OutHeaders); ULONG Size = 0; if (OutHeaders) { WORD Magic_2 = OutHeaders->OptionalHeader.Magic; UINT_PTR NtExportDirVA = 0; if (Magic_2 != IMAGE_NT_OPTIONAL_HDR32_MAGIC) { if (Magic_2 == IMAGE_NT_OPTIONAL_HDR64_MAGIC && OutHeaders->OptionalHeader.NumberOfRvaAndSizes) { NtExportDirVA = OutHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; if (!(DWORD)NtExportDirVA) { Status_2 = STATUS_NOT_IMPLEMENTED; goto CHECK_NT_EXPORTDIR; } Size = OutHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size; if (!SomeNtCheck && (unsigned int)NtExportDirVA >= OutHeaders->OptionalHeader.SizeOfHeaders) { SectionHeader = RtlAddressInSectionTable(OutHeaders, NtBase_2, (unsigned int)NtExportDirVA); Status_2 = 0; if (!SectionHeader) Status_2 = STATUS_INVALID_PARAMETER; goto CHECK_NT_EXPORTDIR; } GET_NT_EXPORTDIR: SectionHeader = (PIMAGE_SECTION_HEADER)((char*)NtBase_2 + NtExportDirVA); Status_2 = 0; goto CHECK_NT_EXPORTDIR; } FAIL_NTSTATUS: Status_2 = STATUS_INVALID_PARAMETER; goto CHECK_NT_EXPORTDIR; } if (!(OutHeaders->OptionalHeader.SizeOfHeapReserve & 0xFFFFFFFF00000000)) goto FAIL_NTSTATUS; NtExportDirVA = (OutHeaders->OptionalHeader.SizeOfHeapCommit & UINT_MAX); if (!(DWORD)NtExportDirVA) { Status_2 = STATUS_NOT_IMPLEMENTED; goto CHECK_NT_EXPORTDIR; } Size = (OutHeaders->OptionalHeader.SizeOfHeapCommit & 0xFFFFFFFF00000000); if (SomeNtCheck || (unsigned int)NtExportDirVA < OutHeaders->OptionalHeader.SizeOfHeaders) goto GET_NT_EXPORTDIR; SectionHeader = RtlAddressInSectionTable(OutHeaders, NtBase_2, (unsigned int)NtExportDirVA); Status_2 = 0; if (!SectionHeader) Status_2 = STATUS_INVALID_PARAMETER; } CHECK_NT_EXPORTDIR: if (!NT_SUCCESS(Status_2)) SectionHeader = nullptr; if (!SectionHeader) { Status = STATUS_PROCEDURE_NOT_FOUND; LABEL_192: SectionHeader = nullptr; LABEL_105: SomeStatus = TRUE; goto LOAD_DEPENDENTA_FAILED; } PCHAR v64 = StringToBeHashed_2; ULONG v73 = 0; if (StringToBeHashed_2) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 827, "LdrpGetProcedureAddress", 2u, "Locating procedure \"%s\" by name\n", StringToBeHashed_2); ) LONG NameIdxP1 = 0; LONG NumberOfNames = SectionHeader->PointerToRelocations - 1; LONG NameIdx = NumberOfNames / 2; if (NumberOfNames >= 0) { LONG v71 = 0; BOOLEAN v70 = 0; while (TRUE) { PCHAR v68 = StringToBeHashed_2; INT_PTR v69 = (char*)NtBase + *(unsigned int*)((char*)&NtBase->e_magic + 4 * NameIdx + *(unsigned int*)&SectionHeader->NumberOfRelocations) - StringToBeHashed_2; while (TRUE) { v70 = *v68; if (*v68 != v68[v69]) break; ++v68; if (!v70) { v71 = 0; goto LABEL_89; } } v71 = v70 < (BOOLEAN)v68[v69] ? -1 : 1; LABEL_89: if (!v71) break; LONG v72 = NameIdx - 1; if (v71 >= 0) v72 = NumberOfNames; NumberOfNames = v72; if (v71 >= 0) NameIdxP1 = NameIdx + 1; NameIdx = (NameIdxP1 + v72) / 2; if (v72 < NameIdxP1) goto LABEL_187; } v73 = *(unsigned __int16*)((char*)&NtBase->e_magic + 2 * NameIdx + SectionHeader->Characteristics); v64 = StringToBeHashed_2; goto LABEL_97; } LABEL_187: SomeStatus = TRUE; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 2190, "LdrpNameToOrdinal", 1u, "Procedure \"%s\" could not be located in DLL at base 0x%p.\n", StringToBeHashed_2, NtBase); ) Status = STATUS_PROCEDURE_NOT_FOUND; SectionHeader = nullptr; LOAD_DEPENDENTA_FAILED: FunctionIdxAddress_3 = v85; goto LABEL_107; } ULONG v78 = IntValue; PVOID v83 = (PVOID)IntValue; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x34D, "LdrpGetProcedureAddress", 2u, "Loading procedure 0x%lx by ordinal\n", v83); ) if (!v78) { Status = STATUS_INVALID_PARAMETER; goto LABEL_192; } v73 = v78 - SectionHeader->SizeOfRawData; LABEL_97: if (v73 >= SectionHeader->PointerToRawData) { SectionHeader = nullptr; Status = (v64 != nullptr) - 0x3FFFFEC8; goto LABEL_105; } FunctionIdxAddress_3 = (char*)NtBase + *(unsigned int*)((char*)&NtBase->e_magic + 4 * v73 + SectionHeader->PointerToLinenumbers); v85 = FunctionIdxAddress_3; if (FunctionIdxAddress_3 < (PCHAR)SectionHeader || FunctionIdxAddress_3 >= (PCHAR)&SectionHeader->Name[Size]) { SectionHeader = nullptr; Status = STATUS_SUCCESS; PIMAGE_RUNTIME_FUNCTION_ENTRY v74 = (PIMAGE_RUNTIME_FUNCTION_ENTRY)NtLdrEntry->DllBase; if (!*qword_1993B8 || (*dword_19939C & 1)) goto LABEL_105; if ((PIMAGE_DOS_HEADER)v74 < (*stru_199520).ImageBase || v74 >= (PIMAGE_RUNTIME_FUNCTION_ENTRY)((char*)(*stru_199520).ImageBase + (*stru_199520).ImageSize)) { RtlpxLookupFunctionTable(NtLdrEntry->DllBase, (PIMAGE_RUNTIME_FUNCTION_ENTRY*)&FunctionTableData2); } else { FunctionTableData2 = *stru_199520; } if ((PIMAGE_RUNTIME_FUNCTION_ENTRY)FunctionTableData2.ImageBase == v74) goto LABEL_105; LABEL_188: __fastfail(0x18u); } pNtHeader = (PIMAGE_NT_HEADERS32)((DWORD)pNtHeader + 1); SectionHeader = 0; if ((DWORD)pNtHeader != 32) { LoadContext_3 = v111; continue; } break; } Status = STATUS_INVALID_IMAGE_FORMAT; SomeStatus = TRUE; LABEL_107: if (v101) RtlFreeHeap(*LdrpHeap, 0, v101); LABEL_109: if (Status == STATUS_PENDING) return STATUS_SUCCESS; DllBase_3 = DllBase_4; v36 = (BYTE)v103; if (!NT_SUCCESS(Status)) FunctionIdxAddress = FunctionIdxAddress_2; else FunctionIdxAddress = FunctionIdxAddress_3; SectionHeader_2 = (PIMAGE_SECTION_HEADER)pImageExportDir_2; CHECK_STATUS_GOON: if (NT_SUCCESS(Status)) { LABEL_54: UINT_PTR* v49 = v106; *v106 = (UINT_PTR)FunctionIdxAddress; v32 = v105 + 1; v33 = v49 + 1; ++(*(&LoadContext->OriginalIATProtect + 1)); pAddressNames = pAddressNames_2; NumberNames = NumberNames_2; pFuncAddresses = pFuncAddresses_2; v27 = v108; continue; } break; } LDRP_LOAD_CONTEXT* LoadContext_4 = nullptr; if (Status != STATUS_PROCEDURE_NOT_FOUND && Status != STATUS_DLL_NOT_FOUND) { SET_LOAD_CONTEXT: LoadContext_4 = LoadContext; goto GET_IMAGEBASE_RETURN; } PUNICODE_STRING pFullDllName_2 = {}; if (CompatCachepLookupCdb(DllEntry->FullDllName.Buffer, 128) || CompatCachepLookupCdb(DllEntry_3->FullDllName.Buffer, 128)) { pFullDllName_2 = FullDllName; WID_HIDDEN( LdrpLogLoadFailureEtwEvent(FullDllName, (PCHAR)DllEntry_3 + 72, 1, LoadFailure, 0); ) WID_HIDDEN( LdrpLogLoadFailureEtwEvent(pFullDllName_2, (PCHAR)DllEntry_3 + 72, 1, LoadFailureOperational, 1); ) } else { pFullDllName_2 = FullDllName; } UINT_PTR v82 = 0; if ((BYTE)v36) { Status_3 = STATUS_ORDINAL_NOT_FOUND; Status = STATUS_ORDINAL_NOT_FOUND; v82 = v93; } else { Status = STATUS_ENTRYPOINT_NOT_FOUND; Status_3 = STATUS_ENTRYPOINT_NOT_FOUND; v82 = (UINT_PTR)v104; } LdrpReportError(pFullDllName_2, v82, (unsigned int)Status_3); LoadContext_4 = LoadContext; GET_IMAGEBASE_RETURN: PIMAGE_DOS_HEADER ImageBase = LoadContext_4->ImageBase; if (ImageBase) { NtUnmapViewOfSection((HANDLE)-1ui64, ImageBase); LoadContext_4 = LoadContext; LoadContext->ImageBase = 0i64; } if (!NT_SUCCESS(Status)) SomeStatus = FALSE; if (!SomeStatus) WID_HIDDEN( LdrpLogError(Status, 0x19u, 0, &LoadContext_4->BaseDllName); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpDoPostSnapWork(LDRP_LOAD_CONTEXT* LoadContext) { NTSTATUS Status = STATUS_SUCCESS; LDR_DATA_TABLE_ENTRY* DllEntry; NTSTATUS Status_2; UINT_PTR* DllNameLen; NTSTATUS Status_3; NTSTATUS Status_4; ULONG OldAccessProtect; DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; if (!LoadContext->pImageImportDescriptor || (Status_2 = ZwProtectVirtualMemory((HANDLE)-1, (PVOID*)&LoadContext->pImageImportDescriptor, &LoadContext->ImageImportDescriptorLen, LoadContext->GuardFlags, &OldAccessProtect), Status = Status_2, Status_2 >= 0)) { DllNameLen = (UINT_PTR*)LoadContext->UnknownFunc; if (DllNameLen && *DllNameLen != LoadContext->DllNameLenCompare) __fastfail(0x13u); if (DllEntry->TlsIndex || (Status_2 = LdrpHandleTlsData(DllEntry), Status = Status_2, Status_2 >= 0)) { if (LdrControlFlowGuardEnforcedWithExportSuppression()) { Status_3 = LdrpUnsuppressAddressTakenIat(DllEntry->DllBase, 0i64, 0i64); Status = Status_3; if (Status_3 < 0) { Status_4 = Status_3; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 583, "LdrpDoPostSnapWork", 0, "LdrpDoPostSnapWork:Unable to unsuppress the export suppressed functions that are imported in the DLL based a""t 0x%p.Status = 0x%x\n", DllEntry->DllBase, Status_4); ) } } return Status; } } return Status_2; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllRetry(PLDRP_LOAD_CONTEXT LoadContext) { // TO DO. return STATUS_SUCCESS; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllFullPath(PLDRP_LOAD_CONTEXT LoadContext) // CHECKED. { NTSTATUS Status; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); LDRP_FILENAME_BUFFER FileNameBuffer; FileNameBuffer.pFileName.Buffer = FileNameBuffer.FileName; FileNameBuffer.pFileName.Length = 0; FileNameBuffer.pFileName.MaximumLength = MAX_PATH - 4; FileNameBuffer.FileName[0] = 0; // Sets the according members of the DllEntry Status = LdrpResolveDllName(LoadContext, &FileNameBuffer, &DllEntry->BaseDllName, &DllEntry->FullDllName, LoadContext->Flags); do { if (LoadContext->UnknownPtr) { if (!NT_SUCCESS(Status)) break; } else { Status = LdrpAppCompatRedirect(LoadContext, &DllEntry->FullDllName, &DllEntry->BaseDllName, &FileNameBuffer, Status); if (!NT_SUCCESS(Status)) break; // Hashes the dll name ULONG BaseDllNameHash = LdrpHashUnicodeString(&DllEntry->BaseDllName); DllEntry->BaseNameHashValue = BaseDllNameHash; LDR_DATA_TABLE_ENTRY* LoadedDll = nullptr; // Most likely checks if the dll was already mapped/loaded. LdrpFindExistingModule(&DllEntry->BaseDllName, &DllEntry->FullDllName, LoadContext->Flags, BaseDllNameHash, &LoadedDll); if (LoadedDll) { LdrpLoadContextReplaceModule(LoadContext, LoadedDll); break; } } // After this function the dll is mapped. Status = fLdrpMapDllNtFileName(LoadContext, &FileNameBuffer); if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) Status = STATUS_INVALID_IMAGE_FORMAT; } while (FALSE); if (FileNameBuffer.FileName != FileNameBuffer.pFileName.Buffer) NtdllpFreeStringRoutine(FileNameBuffer.pFileName.Buffer); return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllSearchPath(PLDRP_LOAD_CONTEXT LoadContext) { NTSTATUS Status; UINT_PTR DependentLoadFlags; LDR_UNKSTRUCT* UnkStruct; ULONG Flags; LDR_UNKSTRUCT DllPath; LDRP_FILENAME_BUFFER DllNameResolved; DllNameResolved.pFileName.Buffer = DllNameResolved.FileName; DllNameResolved.pFileName.Length = 0; DllNameResolved.pFileName.MaximumLength = MAX_PATH - 4; DllNameResolved.FileName[0] = 0; LDR_UNKSTRUCT3 UnkStruct3; memset(&UnkStruct3, 0, sizeof(UnkStruct3)); UNICODE_STRING ReturnPath = {}; LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* LdrEntry = LoadContext->Entry; LDR_DATA_TABLE_ENTRY* LdrEntry2 = nullptr; do { if (LdrEntry && (DependentLoadFlags = LdrEntry->DependentLoadFlags, (((*LdrpPolicyBits & 4) != 0 ? 0x7F00 : 0x7B00) & (ULONG)DependentLoadFlags) != 0)) { LdrpInitializeDllPath(LdrEntry->FullDllName.Buffer, (PWSTR)(DependentLoadFlags & ((-(__int64)((*LdrpPolicyBits & 4) != 0) & 0x400) + 0x7B00) | 1), &DllPath); UnkStruct = &DllPath; } else { LdrpInitializeDllPath(nullptr, nullptr, &DllPath); UnkStruct = LoadContext->UnkStruct; } BOOL SomeCheck; BOOLEAN JumpOut = FALSE; while (TRUE) { UNICODE_STRING BaseDllName; BOOL a8 = FALSE; Flags = LoadContext->Flags >> 3; Flags = (LoadContext->Flags & 8) != 0; Status = LdrpSearchPath(LoadContext, UnkStruct, Flags, &ReturnPath, &DllNameResolved, &BaseDllName, &UnkStruct3.String, &a8, &UnkStruct3); if (a8) DllEntry->Flags |= PackagedBinary; if (Status == STATUS_DLL_NOT_FOUND) break; if (!NT_SUCCESS(Status)) { JumpOut = TRUE; break; } CHECK_LOADCONTEXT: SomeCheck = TRUE; if (!LoadContext->UnknownPtr) { Status = LdrpAppCompatRedirect(LoadContext, &UnkStruct3.String, &BaseDllName, &DllNameResolved, Status); if (!NT_SUCCESS(Status)) { JumpOut = TRUE; break; } if ((LoadContext->Flags & 0x10000) != 0) UnkStruct3.Flags |= PackagedBinary; ULONG DllNameHash = LdrpHashUnicodeString(&BaseDllName); DllEntry->BaseNameHashValue = DllNameHash; Status = LdrpFindExistingModule(&BaseDllName, &UnkStruct3.String, LoadContext->Flags, DllNameHash, &LdrEntry2); if (Status != STATUS_DLL_NOT_FOUND) { JumpOut = TRUE; break; } } LdrpFreeUnicodeString(&DllEntry->FullDllName); DllEntry->FullDllName = UnkStruct3.String; DllEntry->BaseDllName = BaseDllName; UnkStruct3.String = {}; Status = fLdrpMapDllNtFileName(LoadContext, &DllNameResolved); if (Status != STATUS_IMAGE_MACHINE_TYPE_MISMATCH) { JumpOut = TRUE; break; } if (DllNameResolved.FileName != DllNameResolved.pFileName.Buffer) NtdllpFreeStringRoutine(DllNameResolved.pFileName.Buffer); DllNameResolved.pFileName.Length = 0; DllNameResolved.pFileName.MaximumLength = MAX_PATH - 4; DllNameResolved.pFileName.Buffer = DllNameResolved.FileName; DllNameResolved.FileName[0] = 0; } if (JumpOut) break; if (!SomeCheck) goto CHECK_LOADCONTEXT; Status = STATUS_INVALID_IMAGE_FORMAT; } while (FALSE); if (LdrEntry2) { LdrpLoadContextReplaceModule(LoadContext, LdrEntry2); } else if (LdrpIsSecurityEtwLoggingEnabled()) { LdrpLogEtwDllSearchResults(UnkStruct3.Flags, LoadContext); } if (DllNameResolved.FileName != DllNameResolved.pFileName.Buffer) NtdllpFreeStringRoutine(DllNameResolved.pFileName.Buffer); DllNameResolved.pFileName.Length = 0; DllNameResolved.pFileName.MaximumLength = MAX_PATH - 4; DllNameResolved.pFileName.Buffer = DllNameResolved.FileName; DllNameResolved.FileName[0] = 0; LdrpFreeUnicodeString(&UnkStruct3.String); if (DllPath.IsInitedMaybe) RtlReleasePath(DllPath.pInitNameMaybe); return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllNtFileName(PLDRP_LOAD_CONTEXT LoadContext, LDRP_FILENAME_BUFFER* FileNameBuffer) // CHECKED. { NTSTATUS Status; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); INT64 UnknownPtr = LoadContext->UnknownPtr; LONG Unknown = 0; if (LdrpCheckForRetryLoading(LoadContext, 0)) return STATUS_RETRY; PUNICODE_STRING FullDllName = &DllEntry->FullDllName; WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllEntry->DllBase, &DllEntry->FullDllName, 0x14A5); ) //OBJ_CASE_INSENSITIVE ULONG ObjAttributes = OBJ_CASE_INSENSITIVE; if (!*LdrpUseImpersonatedDeviceMap) ObjAttributes = (OBJ_IGNORE_IMPERSONATED_DEVICEMAP | OBJ_CASE_INSENSITIVE); OBJECT_ATTRIBUTES ObjectAttributes; ObjectAttributes.Length = 0x30; ObjectAttributes.RootDirectory = 0; ObjectAttributes.Attributes = ObjAttributes; ObjectAttributes.ObjectName = &FileNameBuffer->pFileName; ObjectAttributes.SecurityDescriptor = 0; ObjectAttributes.SecurityQualityOfService = 0; PCHAR NtPathStuff = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR Unknown2 = 0; if (RtlGetCurrentServiceSessionId()) Unknown2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; else Unknown2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR NtPathStuff2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; if (*Unknown2 && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled)) { //: (char*)0x7FFE0385; PCHAR NtPathStuff3 = RtlGetCurrentServiceSessionId() ? (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1 : (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; // 0x20 is SPACE char if ((*NtPathStuff3 & ' ')) LdrpLogEtwEvent(0x1485, -1, 0xFFu, 0xFFu); } // SYSTEM_FLAGS_INFORMATION if ((NtCurrentPeb()->NtGlobalFlag & FLG_ENABLE_KDEBUG_SYMBOL_LOAD)) { WID_HIDDEN( ZwSystemDebugControl(); ) } HANDLE FileHandle; while (TRUE) { IO_STATUS_BLOCK IoStatusBlock; Status = NtOpenFile(&FileHandle, SYNCHRONIZE | FILE_TRAVERSE | FILE_LIST_DIRECTORY, &ObjectAttributes, &IoStatusBlock, 5, 0x60); if (NT_SUCCESS(Status)) break; if (Status == STATUS_OBJECT_NAME_NOT_FOUND || Status == STATUS_OBJECT_PATH_NOT_FOUND) return STATUS_DLL_NOT_FOUND; if (Status != STATUS_ACCESS_DENIED || Unknown || !LdrpCheckComponentOnDemandEtwEvent(LoadContext)) return Status; Unknown = TRUE; } ULONG SigningLevel; ULONG AllocationAttributes = 0; if (*LdrpAuditIntegrityContinuity && (Status = LdrpValidateIntegrityContinuity(LoadContext, FileHandle), !NT_SUCCESS(Status)) && *LdrpEnforceIntegrityContinuity || (AllocationAttributes = MEM_IMAGE, (LoadContext->Flags & MEM_IMAGE)) && (NtCurrentPeb()->BitField & IsPackagedProcess) == 0 && // (Status = LdrpSetModuleSigningLevel(FileHandle, (PLDR_DATA_TABLE_ENTRY)LoadContext->WorkQueueListEntry.Flink, &SigningLevel, 8), !NT_SUCCESS(Status))) (Status = LdrpSetModuleSigningLevel(FileHandle, CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks), &SigningLevel, 8), !NT_SUCCESS(Status))) { NtClose(FileHandle); return Status; } if (*UseWOW64 && (LoadContext->Flags & 0x800) == 0) AllocationAttributes = MEM_IMAGE | MEM_TOP_DOWN; HANDLE SectionHandle; Status = NtCreateSection(&SectionHandle, SECTION_QUERY | SECTION_MAP_READ | SECTION_MAP_EXECUTE, 0, 0, PAGE_EXECUTE, AllocationAttributes, FileHandle); if (!NT_SUCCESS(Status)) { if (Status == STATUS_NEEDS_REMEDIATION || (Status + 0x3FFFFB82) <= 1) { Status = LdrAppxHandleIntegrityFailure(Status); } else if (Status != STATUS_NO_MEMORY && Status != STATUS_INSUFFICIENT_RESOURCES && Status != STATUS_COMMITMENT_LIMIT) { LDR_UNKSTRUCT2 NtHardParameters; NtHardParameters.Name = FullDllName; NtHardParameters.Status = Status; // Semi-documented in http://undocumented.ntinternals.net/ HARDERROR_RESPONSE Response; if (NT_SUCCESS(NtRaiseHardError(STATUS_INVALID_IMAGE_FORMAT, 2, 1, (INT*)&NtHardParameters, OptionOk, &Response)) && *LdrInitState != 3) { ++(*LdrpFatalHardErrorCount); } } WID_HIDDEN( LdrpLogError(Status, 0x1485u, 0, FullDllName); ) NtClose(FileHandle); return Status; } if (RtlGetCurrentServiceSessionId()) NtPathStuff = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; if (*NtPathStuff && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { if (RtlGetCurrentServiceSessionId()) NtPathStuff2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; // 0x20 is SPACE char. if ((*NtPathStuff2 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1486, -1, 0xFFu, 0xFFu); ) } if (!*UseWOW64 && (LoadContext->Flags & 0x100) == 0 && (Status = LdrpCodeAuthzCheckDllAllowed(FileNameBuffer, FileHandle), NT_SUCCESS((LONG)(Status + 0x80000000))) && Status != STATUS_NOT_FOUND || (Status = fLdrpMapDllWithSectionHandle(LoadContext, SectionHandle), !UnknownPtr) || !NT_SUCCESS(Status)) { NtClose(SectionHandle); NtClose(FileHandle); return Status; } LoadContext->FileHandle = FileHandle; LoadContext->SectionHandle = SectionHandle; return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapDllWithSectionHandle(PLDRP_LOAD_CONTEXT LoadContext, HANDLE SectionHandle) // CHECKED. { NTSTATUS Status; NTSTATUS Status2; NTSTATUS Status3; NTSTATUS Status4; int v19[14]; LDR_DATA_TABLE_ENTRY* LdrEntry2; // Mapping mechanism. Status = fLdrpMinimalMapModule(LoadContext, SectionHandle); Status2 = Status; if (Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH) return Status2; if (!NT_SUCCESS(Status)) return Status2; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); SIZE_T Size = LoadContext->Size; LDR_DATA_TABLE_ENTRY* LdrEntry = nullptr; Status3 = Status; PIMAGE_NT_HEADERS OutHeaders; Status2 = RtlImageNtHeaderEx(0, DllEntry->DllBase, Size, &OutHeaders); if (!NT_SUCCESS(Status2)) return Status2; if (LoadContext->Flags & SEC_FILE) { Status3 = STATUS_SUCCESS; DllEntry->TimeDateStamp = OutHeaders->FileHeader.TimeDateStamp; DllEntry->CheckSum = OutHeaders->OptionalHeader.CheckSum; DllEntry->SizeOfImage = OutHeaders->OptionalHeader.SizeOfImage; } else { RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); UINT_PTR Flags = (LoadContext->Flags) & UINT_MAX; PUNICODE_STRING FullDllName_2 = 0; if ((Flags & 0x20) == 0) FullDllName_2 = &DllEntry->FullDllName; // Returns STATUS_DLL_NOT_FOUND is normal situations. Status4 = LdrpFindLoadedDllByNameLockHeld(&DllEntry->BaseDllName, FullDllName_2, Flags, &LdrEntry, DllEntry->BaseNameHashValue); if (Status4 == STATUS_DLL_NOT_FOUND) { PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; v19[0] = OutHeaders->FileHeader.TimeDateStamp; v19[1] = OutHeaders->OptionalHeader.SizeOfImage; LdrpFindLoadedDllByMappingLockHeld(DllBase, OutHeaders, (ULONG*)v19, &LdrEntry); } if (!LdrEntry) { LdrpInsertDataTableEntry(DllEntry); LdrpInsertModuleToIndexLockHeld(DllEntry, OutHeaders); } RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); if (LdrEntry) { if (DllEntry->LoadReason != LoadReasonPatchImage || LdrEntry->LoadReason == LoadReasonPatchImage) { LdrpLoadContextReplaceModule(LoadContext, LdrEntry); } else { Status2 = STATUS_IMAGE_LOADED_AS_PATCH_IMAGE; WID_HIDDEN( LdrpLogEtwHotPatchStatus(&(*LdrpImageEntry)->BaseDllName, LoadContext->Entry, &DllEntry->FullDllName, STATUS_IMAGE_LOADED_AS_PATCH_IMAGE, 3); ) LdrpDereferenceModule(LdrEntry); } return Status2; } } if (*qword_17E238 == NtCurrentTeb()->ClientId.UniqueThread) return STATUS_NOT_FOUND; Status2 = fLdrpCompleteMapModule(LoadContext, OutHeaders, Status3); if (NT_SUCCESS(Status2)) { Status2 = fLdrpProcessMappedModule(DllEntry, LoadContext->Flags & UINT_MAX, 1); if (NT_SUCCESS(Status2)) { WID_HIDDEN( LdrpLogNewDllLoad(LoadContext->Entry, DllEntry); ) LdrEntry2 = LoadContext->Entry; if (LdrEntry2) DllEntry->ParentDllBase = LdrEntry2->DllBase; BOOLEAN DllBasesEqual = FALSE; if (DllEntry->LoadReason == LoadReasonPatchImage && *LdrpImageEntry) DllBasesEqual = DllEntry->ParentDllBase == (*LdrpImageEntry)->DllBase; if ((LoadContext->Flags & SEC_FILE) || (DllEntry->FlagGroup[0] & ImageDll) || DllBasesEqual) { if ((DllEntry->Flags & CorILOnly)) { return fLdrpCorProcessImports(DllEntry); } else { fLdrpMapAndSnapDependency(LoadContext); return *LoadContext->pStatus; } } else { WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllEntry->DllBase, &DllEntry->FullDllName, 0x14AEu); ) Status2 = STATUS_SUCCESS; DllEntry->DdagNode->State = LdrModulesReadyToRun; } } } return Status2; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMinimalMapModule(PLDRP_LOAD_CONTEXT LoadContext, HANDLE SectionHandle) { NTSTATUS Status; BOOLEAN UnknownBool; int Flags; int Flags2; ULONG ProtectFlags; wchar_t* Buffer; MEM_EXTENDED_PARAMETER MemExtendedParam; void* Data; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x2BC, "LdrpMinimalMapModule", 3u, "DLL name: %wZ\n", &DllEntry->FullDllName); ) if (!RtlEqualUnicodeString(&DllEntry->BaseDllName, LdrpKernel32DllName, TRUE) || (UnknownBool = 1, (*((BYTE*)*LdrpAppHeaders + 0x16) & 0x20) == 0)) { UnknownBool = 0; } PVOID ReturnedState = nullptr; Flags = DontRelocate; if (!UnknownBool) { if (*LdrpLargePageDllKeyHandle) { Buffer = DllEntry->BaseDllName.Buffer; Data = 0; RtlQueryImageFileKeyOption(*LdrpLargePageDllKeyHandle, Buffer, 4, &Data, 4, 0); if ((DWORD)Data) { if (NT_SUCCESS(RtlAcquirePrivilege(*LdrpLockMemoryPrivilege, 1, 0, &ReturnedState))) Flags = 0x20000000; } } } TEB* TEB = NtCurrentTeb(); LoadContext->Size = 0; Data = TEB->NtTib.ArbitraryUserPointer; TEB->NtTib.ArbitraryUserPointer = DllEntry->FullDllName.Buffer; ULONG64 MaxUsermodeAddress; ProtectFlags = (LoadContext->Flags & SEC_LINKER_CREATED) != 0 ? PAGE_READONLY : PAGE_EXECUTE_WRITECOPY; Flags2 = Flags | DontCallForThreads; if ((LoadContext->Flags & SEC_LINKER_CREATED) == 0) Flags2 = Flags; if ((LoadContext->Flags & SEC_COFF_SHARED_LIBRARY) != 0) { MaxUsermodeAddress = *LdrpMaximumUserModeAddress; MemExtendedParam.Handle = 0; MemExtendedParam.Pointer = &MemExtendedParam.Handle; MemExtendedParam.Type = 1; Status = ZwMapViewOfSectionEx(SectionHandle, (HANDLE)-1, &DllEntry->DllBase, 0, (PULONG)&LoadContext->Size, Flags2, ProtectFlags, &MemExtendedParam, 1); } else { // R9 register isn't used by the function (or I couldn't see) but it must be passed anyways so I did. // After this function our dll is mapped, DllEntry->DllBase receives the base address. Status = fLdrpMapViewOfSection(SectionHandle, ProtectFlags, &DllEntry->DllBase, 0x4B, (PULONG)&LoadContext->Size, Flags2, ProtectFlags, &DllEntry->FullDllName); } TEB->NtTib.ArbitraryUserPointer = Data; if (Flags2 == 0x20000000) RtlReleasePrivilege(ReturnedState); switch (Status) { case STATUS_IMAGE_MACHINE_TYPE_MISMATCH: Status = LdrpProcessMachineMismatch(LoadContext); break; case STATUS_IMAGE_NOT_AT_BASE: case STATUS_IMAGE_AT_DIFFERENT_BASE: if (!LoadContext->UnknownPtr && *LdrpMapAndSnapWork) { if (LdrpCheckForRetryLoading(LoadContext, TRUE)) { Status = STATUS_RETRY; } else if (UnknownBool) { Status = STATUS_CONFLICTING_ADDRESSES; } } break; } if (DllEntry->DllBase && (!NT_SUCCESS(Status) || Status == STATUS_IMAGE_MACHINE_TYPE_MISMATCH)) { NtUnmapViewOfSection((HANDLE)-1, DllEntry->DllBase); DllEntry->DllBase = 0; } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x38D, "LdrpMinimalMapModule", 4, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapViewOfSection(HANDLE SectionHandle, ULONG ProtectFlags, PIMAGE_DOS_HEADER* BaseAddress, DWORD Unknown, PULONG ViewSize, ULONG AllocationType, ULONG Win32Protect, PUNICODE_STRING FullDllName) { MEM_EXTENDED_PARAMETER MemExtendedParam; // [rsp+50h] [rbp-18h] BYREF // I believe this check is to seperate between Windows dlls and user-made dlls. Goes in if User-made dll. if (!LdrpHpatAllocationOptOut(FullDllName)) return ZwMapViewOfSection(SectionHandle, (HANDLE)-1, BaseAddress, 0, 0, 0, ViewSize, ViewShare, AllocationType, Win32Protect); // Windows dlls. MemExtendedParam.Type = 5; MemExtendedParam.Pointer = (PHANDLE)128; return ZwMapViewOfSectionEx(SectionHandle, (HANDLE)-1, BaseAddress, 0, ViewSize, AllocationType, Win32Protect, &MemExtendedParam, 1); } NTSTATUS __fastcall LOADLIBRARY::fLdrpCompleteMapModule(PLDRP_LOAD_CONTEXT LoadContext, PIMAGE_NT_HEADERS OutHeaders, NTSTATUS Status) { NTSTATUS ReturnStatus = STATUS_SUCCESS; NTSTATUS ReturnStatus2; //LDR_DATA_TABLE_ENTRY* DllEntry = (LDR_DATA_TABLE_ENTRY*)LoadContext->WorkQueueListEntry.Flink; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; PIMAGE_COR20_HEADER CorHeader = nullptr; ULONG64 LastRVASection = 0; ReturnStatus2 = RtlpImageDirectoryEntryToDataEx(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR, &LastRVASection, &CorHeader); if (!NT_SUCCESS(ReturnStatus2)) CorHeader = 0; BOOLEAN JumpIn = FALSE; if (!CorHeader) JumpIn = TRUE; DWORD NewDllFlags = 0; if (!JumpIn) { if ((LoadContext->Flags & SEC_LINKER_CREATED) != 0) return STATUS_INVALID_IMAGE_FORMAT; NewDllFlags = DllEntry->Flags | CorImage; DllEntry->Flags = NewDllFlags; } if (JumpIn || ((CorHeader->Flags & 1) == 0 || (DllEntry->Flags = NewDllFlags | CorILOnly, ReturnStatus = LdrpCorValidateImage(DllBase), (NT_SUCCESS(ReturnStatus)) && ((LoadContext->Flags & SEC_LINK_DUPLICATES_ONE_ONLY) == 0 || (ReturnStatus = LdrpCorFixupImage(DllBase), NT_SUCCESS(ReturnStatus)))))) { if ((OutHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0) { if (NT_SUCCESS(*(BYTE*)&(LoadContext->Flags)) || !NT_SUCCESS(*(BYTE*)&(OutHeaders->OptionalHeader.DllCharacteristics))) { if ((DllEntry->Flags & CorILOnly) == 0 && (Status == STATUS_IMAGE_NOT_AT_BASE || Status == STATUS_IMAGE_AT_DIFFERENT_BASE)) { char* UMGlobalLogger = (char*)&kUserSharedData->UserModeGlobalLogger[2]; char* UMGlobalLogger_2 = nullptr; char* UMGlobalLoggerP1 = nullptr; char* UMGlobalLoggerP1_2 = nullptr; if (RtlGetCurrentServiceSessionId()) UMGlobalLogger_2 = (char*)NtCurrentPeb()->SharedData + 0x22A; else UMGlobalLogger_2 = (char*)&kUserSharedData->UserModeGlobalLogger[2]; UMGlobalLoggerP1 = (char*)&kUserSharedData->UserModeGlobalLogger[2] + 1; if (*(BYTE*)UMGlobalLogger_2 && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { UMGlobalLoggerP1_2 = RtlGetCurrentServiceSessionId() ? (char*)NtCurrentPeb()->SharedData + 0x22B : (char*)UMGlobalLoggerP1; // 0x20 is space char. if ((*UMGlobalLoggerP1_2 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1490u, (ULONGLONG)DllBase, 0xFFu, 0xFFu); ) } if (Status == STATUS_IMAGE_NOT_AT_BASE && (ReturnStatus = fLdrpRelocateImage(DllEntry->DllBase, LoadContext->Size, OutHeaders, &DllEntry->FullDllName), !NT_SUCCESS(ReturnStatus))) { WID_HIDDEN( LdrpLogError(ReturnStatus, 0x1490u, 0, &DllEntry->FullDllName); ) } else { if (RtlGetCurrentServiceSessionId()) UMGlobalLogger = (char*)NtCurrentPeb()->SharedData + 0x22A; if (*(BYTE*)UMGlobalLogger && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { if (RtlGetCurrentServiceSessionId()) UMGlobalLoggerP1 = (char*)NtCurrentPeb()->SharedData + 0x22B; // 0x20 is space char. if ((*(BYTE*)UMGlobalLoggerP1 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1491u, (ULONGLONG)DllBase, 0xFFu, 0xFFu); ) } } } } else { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 1009, "LdrpCompleteMapModule", 0, "Could not validate the crypto signature for DLL %wZ\n", &DllEntry->FullDllName); ) return STATUS_INVALID_IMAGE_HASH; } } else { DllEntry->Flags &= ~ImageDll; } } return ReturnStatus; } NTSTATUS __fastcall LOADLIBRARY::fLdrpRelocateImage(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeaders, PUNICODE_STRING FullDllName) { NTSTATUS Status; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 0x164, "LdrpRelocateImage", 3, "DLL name: %wZ\n", FullDllName); ) Status = STATUS_SUCCESS; // To delete goto. BOOLEAN PassOver = FALSE; if ((OutHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0) PassOver = TRUE; UINT_PTR LastRVASection; PIMAGE_BASE_RELOCATION BaseReloc; if (!PassOver) { Status = RtlpImageDirectoryEntryToDataEx(DllBase, TRUE, IMAGE_DIRECTORY_ENTRY_BASERELOC, &LastRVASection, (PVOID*)&BaseReloc); if (!NT_SUCCESS(Status)) BaseReloc = 0; } if (PassOver || (BaseReloc && (DWORD)LastRVASection)) { if (!LdrpIsILOnlyImage(DllBase)) { WID_HIDDEN( LdrpLogDllRelocationEtwEvent(FullDllName, OutHeaders->OptionalHeader.ImageBase, DllBase, Size); ) Status = fLdrpProtectAndRelocateImage(DllBase, Size, OutHeaders); } } WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrmap.c", 396, "LdrpRelocateImage", 4u, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpProtectAndRelocateImage(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeader) { NTSTATUS Status; do { BOOLEAN DoNotRelocate = FALSE; // The DOS header receives memory information. MEMORY_WORKING_SET_EX_INFORMATION MemoryWorkingSetExInfo; MemoryWorkingSetExInfo.VirtualAddress = DllBase; Status = ZwQueryVirtualMemory((HANDLE)-1, 0, MemoryWorkingSetExInformation, &MemoryWorkingSetExInfo, 0x10, 0); if (!NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x7BC, "LdrpProtectAndRelocateImage", 0, "Querying large page info failed with status 0x%08lx\n", Status); ) } else if ((MemoryWorkingSetExInfo.u1.Long & PackagedBinary) != 0) { DoNotRelocate = (MemoryWorkingSetExInfo.u1.Long & DontRelocate) != 0; } if (!DontRelocate) { Status = fLdrpSetProtection(DllBase, FALSE); if (!NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x7C6, "LdrpProtectAndRelocateImage", 0, "Changing the protection of the executable at %p failed with status 0x%08lx\n", DllBase, Status); ) break; } } Status = fLdrRelocateImageWithBias(DllBase, Size, OutHeader); if (NT_SUCCESS(Status) && !DontRelocate) { Status = fLdrpSetProtection(DllBase, TRUE); if (!NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x7DE, "LdrpProtectAndRelocateImage", 0, "Changing the protection of the executable at %p failed with status 0x%08lx\n", DllBase, Status); ) break; } } } while (FALSE); WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrfind.c", 0x806, "LdrpProtectAndRelocateImage", 4u, "Status: 0x%08lx\n", Status); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpSetProtection(PIMAGE_DOS_HEADER DllBase, BOOLEAN Unknown) { NTSTATUS Status; PIMAGE_NT_HEADERS NtHeader; RtlImageNtHeaderEx(3, DllBase, 0, &NtHeader); PIMAGE_NT_HEADERS NtHeader_2 = NtHeader; if (!NtHeader->FileHeader.NumberOfSections) return STATUS_SUCCESS; LONG SectionIdx = 0; for (PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((char*)&NtHeader->OptionalHeader.AddressOfEntryPoint + NtHeader->FileHeader.SizeOfOptionalHeader); ; ++SectionHeader) { LONG pRawData = SectionHeader->PointerToRawData; if (pRawData >= 0 && *(DWORD*)SectionHeader->Name) { ULONG Flags; ULONG Flags2; if (Unknown) { // Reserved (0x2), Reserved (0x10) Flags = (pRawData & IMAGE_SCN_MEM_EXECUTE) != 0 ? ((pRawData & IMAGE_SCN_MEM_READ) != 0 ? IMAGE_SCN_CNT_CODE : 0x10) : 2; Flags2 = Flags | IMAGE_SCN_LNK_INFO; if ((pRawData & IMAGE_SCN_MEM_NOT_CACHED) == 0) Flags2 = Flags; } else { // Reserved (0x4) Flags2 = 4; } PVOID BaseAddress[6]; BaseAddress[0] = (char*)DllBase + SectionHeader[-1].Characteristics; ULONG64 NumberOfBytesToProtect = *(unsigned int*)SectionHeader->Name; if (NumberOfBytesToProtect) { ULONG OldAccessProtection; Status = ZwProtectVirtualMemory((HANDLE)-1, BaseAddress, (PULONG)&NumberOfBytesToProtect, Flags2, &OldAccessProtection); if (!NT_SUCCESS(Status)) break; } } if (++SectionIdx >= (unsigned int)NtHeader_2->FileHeader.NumberOfSections) return STATUS_SUCCESS; } return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrRelocateImageWithBias(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeader) { NTSTATUS Status = STATUS_SUCCESS; PIMAGE_NT_HEADERS NtHeader_4; ULONG64 ImageBaseHigh; NTSTATUS Status_2; PIMAGE_NT_HEADERS NtHeader_3; ULONG LastRVASection_2; ULONG Machine; PIMAGE_NT_HEADERS NtHeader_2; NtHeader_2 = OutHeader; ULONG64 LastRVASection = 0; if (!NT_SUCCESS(RtlImageNtHeaderEx(1, DllBase, 0, &NtHeader_2))) return STATUS_INVALID_IMAGE_FORMAT; NtHeader_4 = NtHeader_2; if (NtHeader_2->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { ImageBaseHigh = (NtHeader_2->OptionalHeader.ImageBase) & 0xFFFFFFFF00000000; } else { if (NtHeader_2->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) return STATUS_INVALID_IMAGE_FORMAT; ImageBaseHigh = NtHeader_2->OptionalHeader.ImageBase; } Status_2 = RtlpImageDirectoryEntryToDataEx(DllBase, 1u, IMAGE_DIRECTORY_ENTRY_BASERELOC, &LastRVASection, (PVOID*)&NtHeader_2); NtHeader_3 = NtHeader_2; if (!NT_SUCCESS(Status_2)) NtHeader_3 = 0; if (!NtHeader_3) return (NtHeader_4->FileHeader.Characteristics & 1) != 0 ? STATUS_CONFLICTING_ADDRESSES : 0; LastRVASection_2 = LastRVASection; if (!(DWORD)LastRVASection) return (NtHeader_4->FileHeader.Characteristics & 1) != 0 ? STATUS_CONFLICTING_ADDRESSES : 0; while (TRUE) { Machine = *(DWORD*)&NtHeader_3->FileHeader.Machine; LastRVASection_2 -= Machine; NtHeader_3 = fLdrProcessRelocationBlockLongLong(NtHeader_4->FileHeader.Machine, (LONG)DllBase + NtHeader_3->Signature, (ULONG)(Machine - 8) >> 1, (PIMAGE_NT_HEADERS64)((LONG)NtHeader_3 + 8), (UINT_PTR)DllBase - ImageBaseHigh); if (!NtHeader_3) break; if (!LastRVASection_2) return Status; } return STATUS_INVALID_IMAGE_FORMAT; } PIMAGE_NT_HEADERS __fastcall LOADLIBRARY::fLdrProcessRelocationBlockLongLong(USHORT Machine, ULONG64 Signature, ULONG64 Unknown, PIMAGE_NT_HEADERS64 NtHeader, ULONG64 Unknown2) { // TO DO. return STATUS_SUCCESS; } NTSTATUS __fastcall LOADLIBRARY::fLdrpProcessMappedModule(PLDR_DATA_TABLE_ENTRY DllEntry, UINT_PTR Flags, ULONG One) { NTSTATUS Status; PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; PIMAGE_NT_HEADERS OutHeaders; Status = RtlImageNtHeaderEx(3, DllBase, 0, &OutHeaders); if (!NT_SUCCESS(Status)) return Status; PIMAGE_NT_HEADERS OutHeaders_2 = OutHeaders; if ((DllEntry->Flags & (ImageDll | CorILOnly)) == ImageDll && DllEntry->LoadReason != LoadReasonPatchImage) { PLDR_INIT_ROUTINE EntryPoint = nullptr; if (OutHeaders->OptionalHeader.AddressOfEntryPoint) EntryPoint = (PLDR_INIT_ROUTINE)((char*)DllBase + OutHeaders->OptionalHeader.AddressOfEntryPoint); else EntryPoint = nullptr; DllEntry->EntryPoint = EntryPoint; } if (!LdrpValidateEntrySection(DllEntry)) return STATUS_INVALID_IMAGE_FORMAT; DllEntry->OriginalBase = OutHeaders_2->OptionalHeader.ImageBase; DllEntry->LoadTime.QuadPart = *(LONGLONG*)(0x7FFE0014); do { if ((Flags & 0x800000) == 0 && ((DllEntry->FlagGroup[0] & 4) != 0 || One && LdrpIsExecutableRelocatedImage(DllBase)) && (DllEntry->Flags & LoadConfigProcessed) == 0 && One) { UINT_PTR Zero = 0; UINT_PTR RandomNumber = LdrpGenRandom(); BOOL IsInited = LdrInitSecurityCookie(DllBase, DllEntry->SizeOfImage, 0, RandomNumber ^ *dword_199398, &Zero); if (!DllBase || !DllEntry->EntryPoint || (OutHeaders->OptionalHeader.MajorSubsystemVersion != 6 || OutHeaders->OptionalHeader.MinorSubsystemVersion < IMAGE_SUBSYSTEM_WINDOWS_CUI) && OutHeaders->OptionalHeader.MajorSubsystemVersion < IMAGE_SUBSYSTEM_POSIX_CUI || IsInited) { Status = LdrpCfgProcessLoadConfig(DllEntry, OutHeaders, Zero); if (!NT_SUCCESS(Status)) return Status; break; } return STATUS_INVALID_IMAGE_FORMAT; } } while (FALSE); if ((Flags & 0x800000) == 0 && (DllEntry->Flags & InExceptionTable) == 0) RtlInsertInvertedFunctionTable(DllBase, DllEntry->SizeOfImage); DllEntry->Flags |= InExceptionTable | LoadConfigProcessed; RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); DllEntry->DdagNode->State = LdrModulesMapped; if ((Flags & 0x800000) == 0 && DllEntry->LoadContext) LdrpSignalModuleMapped(DllEntry); RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllEntry->DllBase, &DllEntry->FullDllName, 0x14A1u); ) return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpCorProcessImports(PLDR_DATA_TABLE_ENTRY DllEntry) { NTSTATUS Status = STATUS_SUCCESS; DllEntry->DdagNode->State = LdrModulesCondensed; Status = AVrfDllLoadNotification(DllEntry); if (NT_SUCCESS(Status)) { LdrpSendDllNotifications(DllEntry, 1); WID_HIDDEN( LdrpLogDllState((UINT_PTR)DllEntry->DllBase, &DllEntry->FullDllName, 0x14ADu); ) DllEntry->DdagNode->State = LdrModulesReadyToInit; } return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpMapAndSnapDependency(PLDRP_LOAD_CONTEXT LoadContext) { NTSTATUS Status; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); BOOLEAN IsFile = (LoadContext->Flags & SEC_FILE); BOOLEAN FullPathExists = 0; UNICODE_STRING FullPath; memset(&FullPath, 0, sizeof(FullPath)); do { if (!IsFile) { if (DllEntry->LoadReason != LoadReasonPatchImage) { Status = LdrpFindDllActivationContext(DllEntry); if (!NT_SUCCESS(Status)) break; } } Status = fLdrpPrepareImportAddressTableForSnap(LoadContext); if (!NT_SUCCESS(Status)) break; ULONG CurrentDllDecremented = 0; ULONG OldCurrentDll = 0; if (*LdrpIsHotPatchingEnabled) { DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); if (DllEntry) { Status = LdrpQueryCurrentPatch(DllEntry->CheckSum, DllEntry->TimeDateStamp, &FullPath); if (!NT_SUCCESS(Status)) break; if (FullPath.Length) FullPathExists = TRUE; } } PIMAGE_IMPORT_DESCRIPTOR ImageImportDescriptor = nullptr; if (LoadContext->pImageImportDescriptor || FullPathExists) { if (LdrpShouldModuleImportBeRedirected(DllEntry)) LoadContext->Flags |= 0x2000000u; ImageImportDescriptor = LdrpGetImportDescriptorForSnap(LoadContext); ULONG IATSize = 0; PIMAGE_THUNK_DATA32 FirstThunk = (PIMAGE_THUNK_DATA32)&ImageImportDescriptor->FirstThunk; BOOLEAN JumpIn = FALSE; if (ImageImportDescriptor) { PIMAGE_THUNK_DATA32 FirstThunk2 = (IMAGE_THUNK_DATA32*)&ImageImportDescriptor->FirstThunk; ULONG DllBaseIncremented = 0; do { if (!FirstThunk2[-1].u1.ForwarderString) break; ULONG ForwarderString = FirstThunk2->u1.ForwarderString; if (!FirstThunk2->u1.ForwarderString) break; ULONG DllBaseIncremented_2 = DllBaseIncremented + 1; FirstThunk2 += 5; ++IATSize; if (!*(UINT_PTR*)((char*)&DllEntry->DllBase->e_magic + ForwarderString)) DllBaseIncremented_2 = DllBaseIncremented; DllBaseIncremented = DllBaseIncremented_2; } while (FirstThunk2 != (IMAGE_THUNK_DATA32*)16); OldCurrentDll = DllBaseIncremented; if (DllBaseIncremented) JumpIn = TRUE; } BOOLEAN JumpOut = FALSE; if (JumpIn || FullPathExists) { PVOID* Heap = (PVOID*)RtlAllocateHeap(*LdrpHeap, (*NtdllBaseTag + 0x180000) | 8u, 8 * IATSize); LoadContext->IATCheck = (LDR_DATA_TABLE_ENTRY**)Heap; if (Heap) { LoadContext->SizeOfIAT = IATSize; LoadContext->GuardCFCheckFunctionPointer = ImageImportDescriptor; LoadContext->CurrentDll = OldCurrentDll + 1; if (FullPathExists) LoadContext->CurrentDll = OldCurrentDll + 2; PIMAGE_THUNK_DATA pThunk = nullptr; UINT_PTR IATAmount = 0; if (ImageImportDescriptor) { while (FirstThunk[-1].u1.ForwarderString && FirstThunk->u1.ForwarderString) { PIMAGE_DOS_HEADER DllBase = DllEntry->DllBase; if (*(UINT_PTR*)((char*)&DllBase->e_magic + FirstThunk->u1.ForwarderString)) { ULONG ForwarderString_2 = FirstThunk[-1].u1.ForwarderString; IsFile = (PIMAGE_IMPORT_BY_NAME)(ForwarderString_2 + (UINT_PTR)DllBase) != 0; PCHAR ForwarderBuffer = (PCHAR)(ForwarderString_2 + (UINT_PTR)DllBase); STRING SourceString = {}; *(UINT_PTR*)&SourceString.Length = 0; SourceString.Buffer = ForwarderBuffer; if (IsFile) { SIZE_T SourceLen = -1; do { ++SourceLen; } while (ForwarderBuffer[SourceLen]); if (SourceLen > 0xFFFE) { Status = STATUS_NAME_TOO_LONG; break; } SourceString.Length = SourceLen; SourceString.MaximumLength = SourceLen + 1; } Status = LdrpLoadDependentModuleA((PUNICODE_STRING)&SourceString, LoadContext, DllEntry, 0, &LoadContext->IATCheck[IATAmount], (UINT_PTR)&pThunk); if (!NT_SUCCESS(Status)) break; } FirstThunk += 5; IATAmount = (ULONG)(IATAmount + 1); if (FirstThunk == (PIMAGE_THUNK_DATA32)16) break; } } if (FullPathExists) { // Loads Imports dlls. Status = LdrpLoadDependentModuleW(&FullPath, LoadContext, DllEntry); if (!NT_SUCCESS(Status)) WID_HIDDEN(LdrpLogEtwHotPatchStatus(&(*LdrpImageEntry)->BaseDllName, DllEntry, &FullPath, Status, 5u); ) } if (pThunk) RtlFreeHeap(*LdrpHeap, 0, pThunk); if (NT_SUCCESS(Status)) { RtlAcquireSRWLockExclusive(LdrpModuleDatatableLock); CurrentDllDecremented = --LoadContext->CurrentDll; RtlReleaseSRWLockExclusive(LdrpModuleDatatableLock); JumpOut = TRUE; } } else { Status = STATUS_NO_MEMORY; } } if (!JumpOut) CurrentDllDecremented = OldCurrentDll; } PLDR_DDAG_NODE DdagNode = nullptr; PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = LoadContext->pImageImportDescriptor; if (pImageImportDescriptor || !FullPathExists) { if (CurrentDllDecremented) break; DdagNode = DllEntry->DdagNode; if (pImageImportDescriptor) { DdagNode->State = LdrModulesSnapping; if (LoadContext->Entry) LdrpQueueWork(LoadContext); else Status = fLdrpSnapModule(LoadContext); break; } } else { DdagNode = DllEntry->DdagNode; } DdagNode->State = LdrModulesSnapped; } while (FALSE); LdrpFreeUnicodeString(&FullPath); if (!NT_SUCCESS(Status)) { *LoadContext->pStatus = Status; } return *LoadContext->pStatus; } NTSTATUS __fastcall LOADLIBRARY::fLdrpPrepareImportAddressTableForSnap(LDRP_LOAD_CONTEXT* LoadContext) { NTSTATUS Status; LDR_DATA_TABLE_ENTRY* DllEntry = CONTAINING_RECORD(LoadContext->WorkQueueListEntry.Flink, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); PIMAGE_IMPORT_DESCRIPTOR ImageImportDescriptor = nullptr; UINT_PTR* pImageImportDescriptorLen = (UINT_PTR*)&LoadContext->ImageImportDescriptorLen; Status = RtlpImageDirectoryEntryToDataEx(DllEntry->DllBase, 1u, IMAGE_DIRECTORY_ENTRY_IAT, (UINT_PTR*)&LoadContext->ImageImportDescriptorLen, &ImageImportDescriptor); if (!NT_SUCCESS(Status)) ImageImportDescriptor = nullptr; BOOLEAN IsFile = (LoadContext->Flags & SEC_FILE); LoadContext->pImageImportDescriptor = ImageImportDescriptor; if (IsFile) return STATUS_SUCCESS; BOOLEAN JumpOver = FALSE; PIMAGE_NT_HEADERS OutHeaders = nullptr; RtlImageNtHeaderEx(3, DllEntry->DllBase, 0, &OutHeaders); PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigDirectory = LdrImageDirectoryEntryToLoadConfig(DllEntry->DllBase); if (!ImageConfigDirectory || ImageConfigDirectory->Size < 0x94) JumpOver = TRUE; if (!JumpOver) { if ((OutHeaders->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF) != 0 && (ImageConfigDirectory->GuardFlags & IMAGE_GUARD_CF_INSTRUMENTED) != 0) { UINT_PTR* GuardCFCheckFunctionPointer = (UINT_PTR*)ImageConfigDirectory->GuardCFCheckFunctionPointer; LoadContext->UnknownFunc = (__int64)GuardCFCheckFunctionPointer; if (GuardCFCheckFunctionPointer) { LoadContext->DllNameLenCompare = *GuardCFCheckFunctionPointer; } } } do { if (!LoadContext->pImageImportDescriptor) { ULONG ImportDirectoryVA = OutHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; PIMAGE_SECTION_HEADER FirstSection = (PIMAGE_SECTION_HEADER)((char*)&OutHeaders->OptionalHeader + OutHeaders->FileHeader.SizeOfOptionalHeader); if (ImportDirectoryVA) { ULONG SectionIdx = 0; if (OutHeaders->FileHeader.NumberOfSections) { ULONG SectionVA = 0; while (TRUE) { SectionVA = FirstSection->VirtualAddress; if (ImportDirectoryVA >= SectionVA && ImportDirectoryVA < SectionVA + FirstSection->SizeOfRawData) break; ++SectionIdx; ++FirstSection; if (SectionIdx >= OutHeaders->FileHeader.NumberOfSections) break; } LoadContext->pImageImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((char*)DllEntry->DllBase + SectionVA); ULONG SectionFA = FirstSection->Misc.PhysicalAddress; *pImageImportDescriptorLen = SectionFA; if (!SectionFA) *pImageImportDescriptorLen = FirstSection->SizeOfRawData; } } } } while (FALSE); PIMAGE_IMPORT_DESCRIPTOR pImageImportDescriptor = LoadContext->pImageImportDescriptor; if (pImageImportDescriptor && *pImageImportDescriptorLen) { UINT_PTR ImageImportDescriptorLen = *pImageImportDescriptorLen; NTSTATUS Status_2 = ZwProtectVirtualMemory((HANDLE)-1, (PVOID*)&pImageImportDescriptor, (PULONG)&ImageImportDescriptorLen, PAGE_READWRITE, (PULONG)&LoadContext->GuardFlags); if (!NT_SUCCESS(Status_2)) return Status_2; PIMAGE_IMPORT_DESCRIPTOR pNextSectionMaybe = pImageImportDescriptor; PIMAGE_IMPORT_DESCRIPTOR pNextImageImportDescriptor = (IMAGE_IMPORT_DESCRIPTOR*)((char*)pImageImportDescriptor + ImageImportDescriptorLen); do { pNextSectionMaybe = (PIMAGE_IMPORT_DESCRIPTOR)((char*)pNextSectionMaybe + 0x1000); } while (pNextSectionMaybe < pNextImageImportDescriptor); } return STATUS_SUCCESS; } NTSTATUS __fastcall LOADLIBRARY::fLdrpPrepareModuleForExecution(PLDR_DATA_TABLE_ENTRY LdrEntry, NTSTATUS* pStatus) { NTSTATUS Status; Status = STATUS_SUCCESS; if (*qword_17E238 == NtCurrentTeb()->ClientId.UniqueThread) return Status; BOOLEAN Skip = FALSE; LDR_DDAG_NODE* DdagNode = LdrEntry->DdagNode; switch (DdagNode->State) { case LdrModulesSnapped: LdrpCondenseGraph(DdagNode); case LdrModulesCondensed: { // This is where we'll start from normally. if ((LdrEntry->FlagGroup[0] & ProcessStaticImport) == 0) { UINT_PTR SubProcessTag = (UINT_PTR)NtCurrentTeb()->SubProcessTag; LdrpAddNodeServiceTag(DdagNode, SubProcessTag); } Status = LdrpNotifyLoadOfGraph(DdagNode); if (NT_SUCCESS(Status)) { Status = LdrpDynamicShimModule(DdagNode); if (!NT_SUCCESS(Status)) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x9F3, "LdrpPrepareModuleForExecution", 1u, "Failed to load for appcompat reasons\n"); ) return Status; } Skip = TRUE; } if (!Skip) return Status; } case LdrModulesReadyToInit: LDRP_LOAD_CONTEXT* LoadContext = (LDRP_LOAD_CONTEXT*)LdrEntry->LoadContext; if (LoadContext && (LoadContext->Flags & 1) == 0) { LdrpAcquireLoaderLock(); UINT64 Unknown = 0; Status = fLdrpInitializeGraphRecurse(DdagNode, pStatus, (char*)&Unknown); ULONG64 Unused = 0; LdrpReleaseLoaderLock(Unused, 2, Status); } return Status; } // States end at 9. if (DdagNode->State > LdrModulesReadyToRun) return STATUS_INTERNAL_ERROR; return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpInitializeGraphRecurse(LDR_DDAG_NODE* DdagNode, NTSTATUS* pStatus, char* Unknown) { NTSTATUS Status = STATUS_SUCCESS; if (DdagNode->State == LdrModulesInitError) return STATUS_DLL_INIT_FAILED; LDR_DDAG_NODE* DdagNode2 = (LDR_DDAG_NODE*)DdagNode->Dependencies.Tail; CHAR Unknown2_2 = 0; CHAR Unknown2 = 0; BOOLEAN JumpIn = FALSE; do { if (DdagNode2) { LDR_DDAG_NODE* DdagNode2_2 = DdagNode2; do { DdagNode2_2 = (LDR_DDAG_NODE*)DdagNode2_2->Modules.Flink; if ((DdagNode2_2->LoadCount & 1) == 0) { LDR_DDAG_NODE* Blink = (LDR_DDAG_NODE*)DdagNode2_2->Modules.Blink; if (Blink->State == LdrModulesReadyToInit) { Status = fLdrpInitializeGraphRecurse(Blink, pStatus, &Unknown2); if (!NT_SUCCESS(Status)) { JumpIn = TRUE; break; } Unknown2_2 = Unknown2; } else { if (Blink->State == LdrModulesInitError) { Status = STATUS_DLL_INIT_FAILED; { JumpIn = TRUE; break; } } if (Blink->State == LdrModulesInitializing) Unknown2_2 = 1; Unknown2 = Unknown2_2; } } } while (DdagNode2_2 != DdagNode2); if (JumpIn) break; if (Unknown2_2) { LDR_DDAG_NODE* DdagNode3 = (LDR_DDAG_NODE*)DdagNode->Modules.Flink; *Unknown = 1; LDR_SERVICE_TAG_RECORD* ServiceTagList = DdagNode3->ServiceTagList; if (ServiceTagList) { if (pStatus != *(NTSTATUS**)&ServiceTagList[2].ServiceTag) return STATUS_SUCCESS; } } } } while (FALSE); if (!JumpIn) Status = fLdrpInitializeNode(DdagNode); if (JumpIn || !NT_SUCCESS(Status)) DdagNode->State = LdrModulesInitError; return Status; } NTSTATUS __fastcall LOADLIBRARY::fLdrpInitializeNode(LDR_DDAG_NODE* DdagNode) { NTSTATUS Status; NTSTATUS Status_2; NTSTATUS Status_3; LDR_DDAG_STATE* pState = &DdagNode->State; UNICODE_STRING FullDllName; *(UINT_PTR*)&FullDllName.Length = (UINT_PTR)&DdagNode->State; DdagNode->State = LdrModulesInitializing; LDR_DATA_TABLE_ENTRY* Blink = (LDR_DATA_TABLE_ENTRY*)DdagNode->Modules.Blink; LDR_DATA_TABLE_ENTRY* LdrEntry = *LdrpImageEntry; UINT_PTR** v4 = (UINT_PTR**)*qword_1843B8; while (Blink != (LDR_DATA_TABLE_ENTRY*)DdagNode) { if (&Blink[-1].DdagNode != (LDR_DDAG_NODE**)LdrEntry) { PVOID* p_ParentDllBase = &Blink[-1].ParentDllBase; if (*v4 != qword_1843B0) __fastfail(3u); *p_ParentDllBase = qword_1843B0; Blink[-1].SwitchBackContext = v4; *v4 = (UINT_PTR*)p_ParentDllBase; v4 = (UINT_PTR**)&Blink[-1].ParentDllBase; *qword_1843B8 = (UINT_PTR**)v4; } Blink = (LDR_DATA_TABLE_ENTRY*)Blink->InLoadOrderLinks.Blink; } Status = STATUS_SUCCESS; for (LDR_DATA_TABLE_ENTRY* i = (LDR_DATA_TABLE_ENTRY*)DdagNode->Modules.Blink; i != (LDR_DATA_TABLE_ENTRY*)DdagNode; i = (LDR_DATA_TABLE_ENTRY*)i->InLoadOrderLinks.Blink) { LDR_DATA_TABLE_ENTRY* LdrEntry_2 = (LDR_DATA_TABLE_ENTRY*)((char*)i - 160); if (&i[-1].DdagNode != (LDR_DDAG_NODE**)LdrEntry) { if (LdrEntry_2->LoadReason == LoadReasonPatchImage) { Status_2 = LdrpApplyPatchImage((PLDR_DATA_TABLE_ENTRY)&i[-1].DdagNode); Status = Status_2; if (!NT_SUCCESS(Status_2)) { FullDllName = LdrEntry_2->FullDllName; Status_3 = Status_2; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 1392, "LdrpInitializeNode", 0, "Applying patch \"%wZ\" failed - Status = 0x%x\n", &FullDllName, *(UINT_PTR*)&Status_3); ) break; } } UINT_PTR CurrentDllIniter = *LdrpCurrentDllInitializer; *LdrpCurrentDllInitializer = (UINT_PTR)&i[-1].DdagNode; PVOID EntryPoint = LdrEntry_2->EntryPoint; PUNICODE_STRING pFullDllName = &LdrEntry_2->FullDllName; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 1411, "LdrpInitializeNode", 2u, "Calling init routine %p for DLL \"%wZ\"\n", EntryPoint, &LdrEntry_2->FullDllName); ) RTL_CALLER_ALLOCATED_ACTIVATION_CONTEXT_STACK_FRAME_EXTENDED StackFrameExtended; StackFrameExtended.Size = 0x48; StackFrameExtended.Format = 1; memset((char*)&StackFrameExtended.Frame.Previous + 4, 0, 48); UINT_PTR v20 = 0; RtlActivateActivationContextUnsafeFast(&StackFrameExtended, LdrEntry_2->EntryPointActivationContext); if (LdrEntry_2->TlsIndex) fLdrpCallTlsInitializers(1i64, (LDR_DATA_TABLE_ENTRY*)&i[-1].DdagNode); BOOLEAN CallSuccess = TRUE; if (EntryPoint) { LPVOID ContextRecord = nullptr; if ((LdrEntry_2->FlagGroup[0] & ProcessStaticImport) != 0) ContextRecord = *LdrpProcessInitContextRecord; CallSuccess = fLdrpCallInitRoutine((BOOL(__stdcall*)(HINSTANCE, DWORD, LPVOID))EntryPoint, LdrEntry_2->DllBase, DLL_PROCESS_ATTACH, ContextRecord); } RtlDeactivateActivationContextUnsafeFast(&StackFrameExtended); *LdrpCurrentDllInitializer = CurrentDllIniter; LdrEntry_2->Flags |= ProcessAttachCalled; if (!CallSuccess) { WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrsnap.c", 0x5B7, "LdrpInitializeNode", 0, "Init routine %p for DLL \"%wZ\" failed during DLL_PROCESS_ATTACH\n", EntryPoint, pFullDllName); ) Status = STATUS_DLL_INIT_FAILED; LdrEntry_2->Flags |= ProcessAttachFailed; break; } WID_HIDDEN( LdrpLogDllState((UINT_PTR)LdrEntry_2->DllBase, pFullDllName, 0x14AEu); ) LdrEntry = *LdrpImageEntry; } } *pState = Status != 0 ? LdrModulesInitError : LdrModulesReadyToRun; return Status; } BOOL __fastcall LOADLIBRARY::fLdrpCallTlsInitializers(DWORD fdwReason, LDR_DATA_TABLE_ENTRY* LdrEntry) { BOOL Result = FALSE; RtlAcquireSRWLockShared(LdrpTlsLock); TLS_ENTRY* TlsEntry = LdrpFindTlsEntry(LdrEntry); RtlReleaseSRWLockShared(LdrpTlsLock); if (TlsEntry) { LPVOID* AddressOfCallBacks = (LPVOID*)TlsEntry->TlsDirectory.AddressOfCallBacks; if (AddressOfCallBacks) { while (TRUE) { LPVOID ContextRecord = *AddressOfCallBacks; if (!ContextRecord) break; ++AddressOfCallBacks; WID_HIDDEN( LdrpLogInternal("minkernel\\ntdll\\ldrtls.c", 1180, "LdrpCallTlsInitializers", 2u, "Calling TLS callback %p for DLL \"%wZ\" at %p\n", ContextRecord, &LdrEntry->FullDllName, LdrEntry->DllBase); ) Result = fLdrpCallInitRoutine(ImageTlsCallbackCaller, LdrEntry->DllBase, fdwReason, ContextRecord); } } } return Result; } BOOLEAN __fastcall LOADLIBRARY::fLdrpCallInitRoutine(BOOL(__fastcall* DllMain)(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved), PIMAGE_DOS_HEADER DllBase, unsigned int One, LPVOID ContextRecord) { BOOLEAN ReturnVal = TRUE; PCHAR LoggingVar = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR LoggingVar2 = 0; if (RtlGetCurrentServiceSessionId()) LoggingVar2 = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; else LoggingVar2 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2]; PCHAR LoggingVar3 = 0; PCHAR LoggingVar4 = 0; if (*LoggingVar2 && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { LoggingVar3 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; if (RtlGetCurrentServiceSessionId()) LoggingVar4 = (char*)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; else LoggingVar4 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; // 0x20 is SPACE char. if ((*LoggingVar4 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x14A3u, (ULONGLONG)DllBase, 0xFF, 0xFF); ) } else { LoggingVar3 = (PCHAR)&kUserSharedData->UserModeGlobalLogger[2] + 1; } // DLL_PROCESS_ATTACH (1) ReturnVal = DllMain((HINSTANCE)DllBase, One, ContextRecord); if (RtlGetCurrentServiceSessionId()) LoggingVar = (PCHAR)&NtCurrentPeb()->SharedData->NtSystemRoot[253]; if (*LoggingVar && (NtCurrentPeb()->TracingFlags & LibLoaderTracingEnabled) != 0) { if (RtlGetCurrentServiceSessionId()) LoggingVar3 = (char*)&NtCurrentPeb()->SharedData->NtSystemRoot[253] + 1; // 0x20 is SPACE char. if ((*LoggingVar3 & ' ') != 0) WID_HIDDEN( LdrpLogEtwEvent(0x1496u, (ULONGLONG)DllBase, 0xFF, 0xFF); ) } ULONG LoggingVar5 = 0; if (!ReturnVal && One == 1) { LoggingVar5 = 1; WID_HIDDEN( LdrpLogError(STATUS_DLL_INIT_FAILED, 0x1496u, LoggingVar5, 0i64); ) } return ReturnVal; } NTSTATUS __fastcall LOADLIBRARY::fBasepLoadLibraryAsDataFileInternal(PUNICODE_STRING DllName, PWSTR Path, PWSTR Unknown, DWORD dwFlags, HMODULE* pBaseOfLoadedModule) { // I have no control over datafile loads. It's only included to not break-up functionality. return BasepLoadLibraryAsDataFileInternal(DllName, Path, Unknown, dwFlags, pBaseOfLoadedModule); } NTSTATUS LOADLIBRARY::Unload() { if (DllHandle) { // Yes. if (!FreeLibrary(DllHandle)) return STATUS_UNSUCCESSFUL; } return STATUS_SUCCESS; } ================================================ FILE: Src/Loader/Loader.h ================================================ #pragma once #include "..\WID.h" #define LLEXW_ISDATAFILE (LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE | LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE) #define LLEXW_7F08 (LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER | LOAD_LIBRARY_SAFE_CURRENT_DIRS | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS | LOAD_LIBRARY_SEARCH_SYSTEM32 | LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR | LOAD_WITH_ALTERED_SEARCH_PATH) #define LLEXW_ASDATAFILE (LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE | LOAD_LIBRARY_AS_DATAFILE) #define LLDLL_401 (LOAD_LIBRARY_SEARCH_USER_DIRS | DONT_RESOLVE_DLL_REFERENCES) #define CNVTD_DONT_RESOLVE_DLL_REFERENCES 0x2 #define LOAD_PACKAGED_LIBRARY 0x4 #define CNVTD_LOAD_LIBRARY_REQUIRE_SIGNED_TARGET 0x800000 #define CNVTD_LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY 0x80000000 #define LoadOwner 0x1000 #define LoaderWorker 0x2000 #define FLG_ENABLE_KDEBUG_SYMBOL_LOAD 0x40000 // OBJECT_ATTRIBUTES.Attributes #define OBJ_INHERIT 0x00000002 #define OBJ_PERMANENT 0x00000010 #define OBJ_EXCLUSIVE 0x00000020 #define OBJ_CASE_INSENSITIVE 0x00000040 #define OBJ_OPENIF 0x00000080 #define OBJ_OPENLINK 0x00000100 #define OBJ_KERNEL_HANDLE 0x00000200 #define OBJ_FORCE_ACCESS_CHECK 0x00000400 #define OBJ_VALID_ATTRIBUTES 0x000007f2 #define OBJ_IGNORE_IMPERSONATED_DEVICEMAP 0x800 // PEB.Bitfield #define IsPackagedProcess 0x10 // PEB.TracingFlags #define HeapTracingEnabled 0x1 #define CritSecTracingEnabled 0x2 #define LibLoaderTracingEnabled 0x4 // LDR_DATA_TABLE_ENTRY.Flags #define PackagedBinary 0x00000001 #define MarkedForRemoval 0x00000002 #define ImageDll 0x00000004 #define LoadNotificationsSent 0x00000008 #define TelemetryEntryProcessed 0x00000010 #define ProcessStaticImport 0x00000020 #define InLegacyLists 0x00000040 #define InIndexes 0x00000080 #define ShimDll 0x00000100 #define InExceptionTable 0x00000200 #define ReservedFlags1 0x00000C00 #define LoadInProgress 0x00001000 #define LoadConfigProcessed 0x00002000 #define EntryProcessed 0x00004000 #define ProtectDelayLoad 0x00008000 #define ReservedFlags3 0x00030000 #define DontCallForThreads 0x00040000 #define ProcessAttachCalled 0x00080000 #define ProcessAttachFailed 0x00100000 #define CorDeferredValidate 0x00200000 #define CorImage 0x00400000 #define DontRelocate 0x00800000 #define CorILOnly 0x01000000 #define ReservedFlags5 0x0E000000 #define Redirected 0x10000000 #define ReservedFlags6 0x60000000 #define CompatDatabaseProcessed 0x80000000 namespace WID { namespace Loader { enum class LOADTYPE { DEFAULT = 0, HIDDEN }; class LOADLIBRARY { private: NTSTATUS Load(); // NT Functions NTSTATUS __fastcall LdrpThreadTokenSetMainThreadToken(); // CHECKED. NTSTATUS __fastcall LdrpThreadTokenUnsetMainThreadToken(); // CHECKED. LDR_DATA_TABLE_ENTRY* __fastcall LdrpHandleReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry); // CHECKED. NTSTATUS __fastcall LdrpFreeReplacedModule(LDR_DATA_TABLE_ENTRY* LdrEntry); // CHECKED. NTSTATUS __fastcall LdrpResolveDllName(LDRP_LOAD_CONTEXT* LoadContext, LDRP_FILENAME_BUFFER* FileNameBuffer, PUNICODE_STRING BaseDllName, PUNICODE_STRING FullDllName, DWORD Flags); // CHECKED. NTSTATUS __fastcall LdrpFindDllActivationContext(LDR_DATA_TABLE_ENTRY* LdrEntry); // CHECKED. // Using directly is not recommended. HMODULE __fastcall fLoadLibrary(PTCHAR lpLibFileName); // CHECKED. HMODULE __fastcall fLoadLibraryA(LPCSTR lpLibFileName); // CHECKED. HMODULE __fastcall fLoadLibraryW(LPCWSTR lpLibFileName); // CHECKED. HMODULE __fastcall fLoadLibraryExA(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); // CHECKED. HMODULE __fastcall fLoadLibraryExW(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags); // CHECKED. NTSTATUS __fastcall fLdrLoadDll(PWSTR DllPath, PULONG pFlags, PUNICODE_STRING DllName, PVOID* BaseAddress); // CHECKED. NTSTATUS __fastcall fLdrpLoadDll(PUNICODE_STRING DllName, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, LDR_DATA_TABLE_ENTRY** DllEntry); // CHECKED. NTSTATUS __fastcall fLdrpLoadDllInternal(PUNICODE_STRING FullPath, LDR_UNKSTRUCT* DllPathInited, ULONG Flags, ULONG LdrFlags, PLDR_DATA_TABLE_ENTRY LdrEntry, PLDR_DATA_TABLE_ENTRY LdrEntry2, PLDR_DATA_TABLE_ENTRY* DllEntry, NTSTATUS* pStatus, ULONG Zero); // CHECKED. // This function is responsible for the linking issue. NTSTATUS __fastcall fLdrpProcessWork(PLDRP_LOAD_CONTEXT LoadContext, BOOLEAN IsLoadOwner); // CHECKED. NTSTATUS __fastcall fLdrpSnapModule(PLDRP_LOAD_CONTEXT LoadContext); NTSTATUS __fastcall fLdrpDoPostSnapWork(LDRP_LOAD_CONTEXT* LoadContext); NTSTATUS __fastcall fLdrpMapDllRetry(PLDRP_LOAD_CONTEXT LoadContext); NTSTATUS __fastcall fLdrpMapDllFullPath(PLDRP_LOAD_CONTEXT LoadContext); // CHECKED. NTSTATUS __fastcall fLdrpMapDllSearchPath(PLDRP_LOAD_CONTEXT LoadContext); NTSTATUS __fastcall fLdrpMapDllNtFileName(PLDRP_LOAD_CONTEXT LoadContext, LDRP_FILENAME_BUFFER* FileNameBuffer); // CHECKED. NTSTATUS __fastcall fLdrpMapDllWithSectionHandle(PLDRP_LOAD_CONTEXT LoadContext, HANDLE SectionHandle); // CHECKED. NTSTATUS __fastcall fLdrpMinimalMapModule(PLDRP_LOAD_CONTEXT LoadContext, HANDLE SectionHandle); NTSTATUS __fastcall fLdrpMapViewOfSection(HANDLE SectionHandle, ULONG ProtectFlags, PIMAGE_DOS_HEADER* BaseAddress, DWORD Unknown, PULONG ViewSize, ULONG AllocationType, ULONG Win32Protect, PUNICODE_STRING FullDllName); NTSTATUS __fastcall fLdrpCompleteMapModule(PLDRP_LOAD_CONTEXT LoadContext, PIMAGE_NT_HEADERS OutHeaders, NTSTATUS Status); NTSTATUS __fastcall fLdrpRelocateImage(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeaders, PUNICODE_STRING FullDllName); NTSTATUS __fastcall fLdrpProtectAndRelocateImage(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeader); NTSTATUS __fastcall fLdrpSetProtection(PIMAGE_DOS_HEADER DllBase, BOOLEAN Unknown); NTSTATUS __fastcall fLdrRelocateImageWithBias(PIMAGE_DOS_HEADER DllBase, SIZE_T Size, PIMAGE_NT_HEADERS OutHeader); PIMAGE_NT_HEADERS __fastcall fLdrProcessRelocationBlockLongLong(USHORT Machine, ULONG64 Signature, ULONG64 Unknown, PIMAGE_NT_HEADERS64 NtHeader, ULONG64 Unknown2); NTSTATUS __fastcall fLdrpProcessMappedModule(PLDR_DATA_TABLE_ENTRY DllEntry, UINT_PTR Flags, ULONG One); NTSTATUS __fastcall fLdrpCorProcessImports(PLDR_DATA_TABLE_ENTRY DllEntry); NTSTATUS __fastcall fLdrpMapAndSnapDependency(PLDRP_LOAD_CONTEXT LoadContext); NTSTATUS __fastcall fLdrpPrepareImportAddressTableForSnap(LDRP_LOAD_CONTEXT* LoadContext); NTSTATUS __fastcall fLdrpPrepareModuleForExecution(PLDR_DATA_TABLE_ENTRY LdrEntry, NTSTATUS* pStatus); NTSTATUS __fastcall fLdrpInitializeGraphRecurse(LDR_DDAG_NODE* DdagNode, NTSTATUS* pStatus, char* Unknown); NTSTATUS __fastcall fLdrpInitializeNode(_LDR_DDAG_NODE* DdagNode); BOOL __fastcall fLdrpCallTlsInitializers(DWORD fdwReason, LDR_DATA_TABLE_ENTRY* LdrEntry); BOOLEAN __fastcall fLdrpCallInitRoutine(BOOL(__fastcall* DllMain)(HINSTANCE hInstDll, DWORD fdwReason, LPVOID lpvReserved), PIMAGE_DOS_HEADER DllBase, unsigned int One, LPVOID ContextRecord); NTSTATUS __fastcall fBasepLoadLibraryAsDataFileInternal(PUNICODE_STRING DllName, PWSTR Path, PWSTR Unknown, DWORD dwFlags, HMODULE* pBaseOfLoadedModule); public: LOADLIBRARY(TCHAR* DllPath, DWORD Flags = 0, LOADTYPE LoadType = LOADTYPE::DEFAULT); ~LOADLIBRARY(); NTSTATUS Unload(); struct CREATIONINFO { TCHAR DllPath[MAX_PATH]; DWORD Flags; LOADTYPE LoadType; } CreationInfo; HMODULE DllHandle; }; } } ================================================ FILE: Src/Main.cpp ================================================ #include "WID.h" #pragma warning(disable : 6031) int main() { { WID::Loader::LOADLIBRARY Test(TEXT("PATH_TO_DLL.dll")); getchar(); } getchar(); } ================================================ FILE: Src/WID.cpp ================================================ #include "WID.h" BOOLEAN WID::bInitialized = FALSE; MODULEINFO WID::Kernel32ModuleInfo = {}; MODULEINFO WID::KernelBaseModuleInfo = {}; MODULEINFO WID::NtdllModuleInfo = {}; NTSTATUS WID::Init() { if (!bInitialized) { // MODULE INITIALIZATION HMODULE Kernel32Module = GetModuleHandle(TEXT("KERNEL32.DLL")); assert(Kernel32Module); HMODULE KernelBaseModule = GetModuleHandle(TEXT("KERNELBASE.DLL")); assert(KernelBaseModule); HMODULE NtdllModule = GetModuleHandle(TEXT("NTDLL.DLL")); assert(NtdllModule); (GetModuleInformation(GetCurrentProcess(), Kernel32Module, &Kernel32ModuleInfo, sizeof(MODULEINFO)), assert(Kernel32ModuleInfo.lpBaseOfDll)); (GetModuleInformation(GetCurrentProcess(), KernelBaseModule, &KernelBaseModuleInfo, sizeof(MODULEINFO)), assert(KernelBaseModuleInfo.lpBaseOfDll)); (GetModuleInformation(GetCurrentProcess(), NtdllModule, &NtdllModuleInfo, sizeof(MODULEINFO)), assert(NtdllModuleInfo.lpBaseOfDll)); // KERNEL32 // Variables (KernelBaseGlobalData = (ULONG*) ((PCHAR)Kernel32Module + 0x34DE80) ,assert(KernelBaseGlobalData)); // Exported functions (Basep8BitStringToDynamicUnicodeString = (tBasep8BitStringToDynamicUnicodeString)GetProcAddress(Kernel32Module, "Basep8BitStringToDynamicUnicodeString") ,assert(Basep8BitStringToDynamicUnicodeString)); (BaseSetLastNTError = (tBaseSetLastNTError)GetProcAddress(Kernel32Module, "BaseSetLastNTError") ,assert(BaseSetLastNTError)); // KERNELBASE // Signatured (BasepLoadLibraryAsDataFileInternal = (tBasepLoadLibraryAsDataFileInternal) Helper::SigScan((PCHAR)KernelBaseModule, KernelBaseModuleInfo.SizeOfImage, BASEP_LLASDATAFILE_INTERNAL_PATTERN, ARRAYSIZE(BASEP_LLASDATAFILE_INTERNAL_PATTERN) - 1), assert(BasepLoadLibraryAsDataFileInternal)); // NTDLL // Variables (LdrpPolicyBits = (DWORD*) ((PCHAR)NtdllModule + 0x181694) ,assert(LdrpPolicyBits)); (LdrpMainThreadToken = (HANDLE*) ((PCHAR)NtdllModule + 0x1842C8) ,assert(LdrpMainThreadToken)); (LdrInitState = (DWORD*) ((PCHAR)NtdllModule + 0x185220) ,assert(LdrInitState)); (LoadFailure = (DWORD*) ((PCHAR)NtdllModule + 0x135CA0) ,assert(LoadFailure)); (LdrpWorkQueueLock = (PRTL_CRITICAL_SECTION) ((PCHAR)NtdllModule + 0x184280) ,assert(LdrpWorkQueueLock)); (LdrpWorkInProgress = (DWORD*) ((PCHAR)NtdllModule + 0x1842A8) ,assert(LdrpWorkInProgress)); (LdrpWorkQueue = (LIST_ENTRY**) ((PCHAR)NtdllModule + 0x1842B0) ,assert(LdrpWorkQueue)); (LdrpWorkCompleteEvent = (PHANDLE) ((PCHAR)NtdllModule + 0x184260) ,assert(LdrpWorkCompleteEvent)); (LdrpUseImpersonatedDeviceMap = (DWORD*) ((PCHAR)NtdllModule + 0x184350) ,assert(LdrpUseImpersonatedDeviceMap)); (LdrpAuditIntegrityContinuity = (DWORD*) ((PCHAR)NtdllModule + 0x184328) ,assert(LdrpAuditIntegrityContinuity)); (LdrpEnforceIntegrityContinuity = (DWORD*) ((PCHAR)NtdllModule + 0x1842D8) ,assert(LdrpEnforceIntegrityContinuity)); (LdrpFatalHardErrorCount = (DWORD*) ((PCHAR)NtdllModule + 0x183EE8) ,assert(LdrpFatalHardErrorCount)); (UseWOW64 = (DWORD*) ((PCHAR)NtdllModule + 0x1843E8) ,assert(UseWOW64)); (LdrpModuleDatatableLock = (PRTL_SRWLOCK) ((PCHAR)NtdllModule + 0x184D40) ,assert(LdrpModuleDatatableLock)); (qword_17E238 = (PHANDLE) ((PCHAR)NtdllModule + 0x17E238) ,assert(qword_17E238)); (LdrpImageEntry = (LDR_DATA_TABLE_ENTRY**) ((PCHAR)NtdllModule + 0x183F88) ,assert(LdrpImageEntry)); (LdrpKernel32DllName = (PUNICODE_STRING) ((PCHAR)NtdllModule + 0x1311C0) ,assert(LdrpKernel32DllName)); (LdrpAppHeaders = (UINT_PTR*) ((PCHAR)NtdllModule + 0x1842D0) ,assert(LdrpAppHeaders)); (LdrpLargePageDllKeyHandle = (PHANDLE) ((PCHAR)NtdllModule + 0x183EE0) ,assert(LdrpLargePageDllKeyHandle)); (LdrpLockMemoryPrivilege = (ULONG**) ((PCHAR)NtdllModule + 0x14DAC0) ,assert(LdrpLockMemoryPrivilege)); (LdrpMaximumUserModeAddress = (ULONG64*) ((PCHAR)NtdllModule + 0x199280) ,assert(LdrpMaximumUserModeAddress)); (LdrpMapAndSnapWork = (UINT_PTR*) ((PCHAR)NtdllModule + 0x184238) ,assert(LdrpMapAndSnapWork)); (LdrpHashTable = (LIST_ENTRY*) ((PCHAR)NtdllModule + 0x183FE0) ,assert(LdrpHashTable)); (LdrpHeap = (PVOID*) ((PCHAR)NtdllModule + 0x1843E0) ,assert(LdrpHeap)); (LdrpIsHotPatchingEnabled = (BOOLEAN*) ((PCHAR)NtdllModule + 0x185258) ,assert(LdrpIsHotPatchingEnabled)); (LdrpRedirectionModule = (LDR_DATA_TABLE_ENTRY**) ((PCHAR)NtdllModule + 0x184218) ,assert(LdrpRedirectionModule)); (LdrpManifestProberRoutine = (tLdrpManifestProberRoutine) ((PCHAR)NtdllModule + 0x184C20) ,assert(LdrpManifestProberRoutine)); (LdrpRedirectionCalloutFunc = (tLdrpRedirectionCalloutFunc) ((PCHAR)NtdllModule + 0x184228) ,assert(LdrpRedirectionCalloutFunc)); (qword_1993A8 = (ULONG64**) ((PCHAR)NtdllModule + 0x1993A8) ,assert(qword_1993A8)); (NtdllBaseTag = (LONG*) ((PCHAR)NtdllModule + 0x1843F0) ,assert(NtdllBaseTag)); (stru_199520 = (FUNCTION_TABLE_DATA*) ((PCHAR)NtdllModule + 0x199520) ,assert(stru_199520)); (qword_199530 = (UINT_PTR*) ((PCHAR)NtdllModule + 0x199530) ,assert(qword_199530)); (LdrpNtDllDataTableEntry = (LDR_DATA_TABLE_ENTRY**) ((PCHAR)NtdllModule + 0x184370) ,assert(LdrpNtDllDataTableEntry)); (qword_1993B8 = (UINT_PTR*) ((PCHAR)NtdllModule + 0x1993B8) ,assert(qword_1993B8)); (dword_19939C = (DWORD*) ((PCHAR)NtdllModule + 0x19939C) ,assert(dword_19939C)); (LoadFailureOperational = (DWORD*) ((PCHAR)NtdllModule + 0x14BA98) ,assert(LoadFailureOperational)); (dword_199398 = (DWORD*) ((PCHAR)NtdllModule + 0x199398) ,assert(dword_199398)); (qword_1843B8 = (UINT_PTR***) ((PCHAR)NtdllModule + 0x1843B8) ,assert(qword_1843B8)); (qword_1843B0 = (UINT_PTR*) ((PCHAR)NtdllModule + 0x1843B0) ,assert(qword_1843B0)); (LdrpCurrentDllInitializer = (UINT_PTR*) ((PCHAR)NtdllModule + 0x184A88) ,assert(LdrpCurrentDllInitializer)); (LdrpProcessInitContextRecord = (LPVOID**) ((PCHAR)NtdllModule + 0x184358) ,assert(LdrpProcessInitContextRecord)); (LdrpTlsLock = (PRTL_SRWLOCK) ((PCHAR)NtdllModule + 0x184EF8) ,assert(LdrpTlsLock)); (LdrpTlsList = (TLS_ENTRY**) ((PCHAR)NtdllModule + 0x17E2B0) ,assert(LdrpTlsList)); // Exported functions (NtOpenThreadToken = (tNtOpenThreadToken) GetProcAddress(NtdllModule, "NtOpenThreadToken") ,assert(NtOpenThreadToken)); (NtClose = (tNtClose) GetProcAddress(NtdllModule, "NtClose") ,assert(NtClose)); (RtlAllocateHeap = (tRtlAllocateHeap) GetProcAddress(NtdllModule, "RtlAllocateHeap") ,assert(RtlAllocateHeap)); (RtlFreeHeap = (tRtlFreeHeap) GetProcAddress(NtdllModule, "RtlFreeHeap") ,assert(RtlFreeHeap)); (LdrGetDllPath = (tLdrGetDllPath) GetProcAddress(NtdllModule, "LdrGetDllPath") ,assert(LdrGetDllPath)); (RtlReleasePath = (tRtlReleasePath) GetProcAddress(NtdllModule, "RtlReleasePath") ,assert(RtlReleasePath)); (RtlInitUnicodeStringEx = (tRtlInitUnicodeStringEx) GetProcAddress(NtdllModule, "RtlInitUnicodeStringEx") ,assert(RtlInitUnicodeStringEx)); (RtlEnterCriticalSection = (tRtlEnterCriticalSection) GetProcAddress(NtdllModule, "RtlEnterCriticalSection") ,assert(RtlEnterCriticalSection)); (RtlLeaveCriticalSection = (tRtlLeaveCriticalSection) GetProcAddress(NtdllModule, "RtlLeaveCriticalSection") ,assert(RtlLeaveCriticalSection)); (ZwSetEvent = (tZwSetEvent) GetProcAddress(NtdllModule, "ZwSetEvent") ,assert(ZwSetEvent)); (NtOpenFile = (tNtOpenFile) GetProcAddress(NtdllModule, "NtOpenFile") ,assert(NtOpenFile)); (LdrAppxHandleIntegrityFailure = (tLdrAppxHandleIntegrityFailure) GetProcAddress(NtdllModule, "LdrAppxHandleIntegrityFailure") ,assert(LdrAppxHandleIntegrityFailure)); (NtRaiseHardError = (tNtRaiseHardError) GetProcAddress(NtdllModule, "NtRaiseHardError") ,assert(NtRaiseHardError)); (RtlImageNtHeaderEx = (tRtlImageNtHeaderEx) GetProcAddress(NtdllModule, "RtlImageNtHeaderEx") ,assert(RtlImageNtHeaderEx)); (RtlAcquireSRWLockExclusive = (tRtlAcquireSRWLockExclusive) GetProcAddress(NtdllModule, "RtlAcquireSRWLockExclusive") ,assert(RtlAcquireSRWLockExclusive)); (RtlReleaseSRWLockExclusive = (tRtlReleaseSRWLockExclusive) GetProcAddress(NtdllModule, "RtlReleaseSRWLockExclusive") ,assert(RtlReleaseSRWLockExclusive)); (RtlEqualUnicodeString = (tRtlEqualUnicodeString) GetProcAddress(NtdllModule, "RtlEqualUnicodeString") ,assert(RtlEqualUnicodeString)); (RtlAcquirePrivilege = (tRtlAcquirePrivilege) GetProcAddress(NtdllModule, "RtlAcquirePrivilege") ,assert(RtlAcquirePrivilege)); (RtlReleasePrivilege = (tRtlReleasePrivilege) GetProcAddress(NtdllModule, "RtlReleasePrivilege") ,assert(RtlReleasePrivilege)); (RtlCompareUnicodeStrings = (tRtlCompareUnicodeStrings) GetProcAddress(NtdllModule, "RtlCompareUnicodeStrings") ,assert(RtlCompareUnicodeStrings)); (RtlImageNtHeader = (tRtlImageNtHeader) GetProcAddress(NtdllModule, "RtlImageNtHeader") ,assert(RtlImageNtHeader)); (RtlReleaseActivationContext = (tRtlReleaseActivationContext) GetProcAddress(NtdllModule, "RtlReleaseActivationContext") ,assert(RtlReleaseActivationContext)); (RtlCharToInteger = (tRtlCharToInteger) GetProcAddress(NtdllModule, "RtlCharToInteger") ,assert(RtlCharToInteger)); (RtlActivateActivationContextUnsafeFast = (tRtlActivateActivationContextUnsafeFast) GetProcAddress(NtdllModule, "RtlActivateActivationContextUnsafeFast") ,assert(RtlActivateActivationContextUnsafeFast)); (RtlDeactivateActivationContextUnsafeFast = (tRtlDeactivateActivationContextUnsafeFast) GetProcAddress(NtdllModule, "RtlDeactivateActivationContextUnsafeFast") ,assert(RtlDeactivateActivationContextUnsafeFast)); (RtlAcquireSRWLockShared = (tRtlAcquireSRWLockShared) GetProcAddress(NtdllModule, "RtlAcquireSRWLockShared") ,assert(RtlAcquireSRWLockShared)); (RtlReleaseSRWLockShared = (tRtlReleaseSRWLockShared) GetProcAddress(NtdllModule, "RtlReleaseSRWLockShared") ,assert(RtlReleaseSRWLockShared)); // Signatured. // I don't think the signatures will ever change, you can go with the offsets though. (LdrpLogInternal = (tLdrpLogInternal) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_INTERNAL_PATTERN, ARRAYSIZE(LDRP_LOG_INTERNAL_PATTERN) - 1) ,assert(LdrpLogInternal)); (LdrpInitializeDllPath = (tLdrpInitializeDllPath) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_INITIALIZE_DLLPATH_PATTERN, ARRAYSIZE(LDRP_INITIALIZE_DLLPATH_PATTERN) - 1) ,assert(LdrpInitializeDllPath)); (LdrpDereferenceModule = (tLdrpDereferenceModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DEREFERENCE_MODULE_PATTERN, ARRAYSIZE(LDRP_DEREFERENCE_MODULE_PATTERN) - 1) ,assert(LdrpDereferenceModule)); (LdrpLogDllState = (tLdrpLogDllState) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_DLLSTATE_PATTERN, ARRAYSIZE(LDRP_LOG_DLLSTATE_PATTERN) - 1) ,assert(LdrpLogDllState)); (LdrpPreprocessDllName = (tLdrpPreprocessDllName) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_PREPROCESS_DLLNAME_PATTERN, ARRAYSIZE(LDRP_PREPROCESS_DLLNAME_PATTERN) - 1) ,assert(LdrpPreprocessDllName)); (LdrpFindLoadedDllByName = (tLdrpFindLoadedDllByName) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FIND_LOADEDDLLBYNAME_PATTERN, ARRAYSIZE(LDRP_FIND_LOADEDDLLBYNAME_PATTERN) - 1) ,assert(LdrpFindLoadedDllByName)); (LdrpDrainWorkQueue = (tLdrpDrainWorkQueue) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DRAIN_WORKQUEUE_PATTERN, ARRAYSIZE(LDRP_DRAIN_WORKQUEUE_PATTERN) - 1) ,assert(LdrpDrainWorkQueue)); (LdrpFindLoadedDllByHandle = (tLdrpFindLoadedDllByHandle) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FIND_LOADEDDLL_BYHANDLE_PATTERN, ARRAYSIZE(LDRP_FIND_LOADEDDLL_BYHANDLE_PATTERN) - 1) ,assert(LdrpFindLoadedDllByHandle)); (LdrpDropLastInProgressCount = (tLdrpDropLastInProgressCount) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DROP_LASTINPROGRESS_COUNT_PATTERN, ARRAYSIZE(LDRP_DROP_LASTINPROGRESS_COUNT_PATTERN) - 1) ,assert(LdrpDropLastInProgressCount)); (LdrpQueryCurrentPatch = (tLdrpQueryCurrentPatch) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_QUERY_CURRENT_PATCH_PATTERN, ARRAYSIZE(LDRP_QUERY_CURRENT_PATCH_PATTERN) - 1) ,assert(LdrpQueryCurrentPatch)); (LdrpUndoPatchImage = (tLdrpUndoPatchImage) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_UNDO_PATCH_IMAGE_PATTERN, ARRAYSIZE(LDRP_UNDO_PATCH_IMAGE_PATTERN) - 1) ,assert(LdrpUndoPatchImage)); (LdrpDetectDetour = (tLdrpDetectDetour) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DETECT_DETOUR_PATTERN, ARRAYSIZE(LDRP_DETECT_DETOUR_PATTERN) - 1) ,assert(LdrpDetectDetour)); (LdrpFindOrPrepareLoadingModule = (tLdrpFindOrPrepareLoadingModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FINDORPREPARE_LOADINGMODULE_PATTERN, ARRAYSIZE(LDRP_FINDORPREPARE_LOADINGMODULE_PATTERN) - 1) ,assert(LdrpFindOrPrepareLoadingModule)); (LdrpFreeLoadContext = (tLdrpFreeLoadContext) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FREE_LOAD_CONTEXT_PATTERN, ARRAYSIZE(LDRP_FREE_LOAD_CONTEXT_PATTERN) - 1) ,assert(LdrpFreeLoadContext)); (LdrpCondenseGraph = (tLdrpCondenseGraph) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CONDENSE_GRAPH_PATTERN, ARRAYSIZE(LDRP_CONDENSE_GRAPH_PATTERN) - 1) ,assert(LdrpCondenseGraph)); (LdrpBuildForwarderLink = (tLdrpBuildForwarderLink) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_BUILD_FORWARDER_LINK_PATTERN, ARRAYSIZE(LDRP_BUILD_FORWARDER_LINK_PATTERN) - 1) ,assert(LdrpBuildForwarderLink)); (LdrpPinModule = (tLdrpPinModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_PIN_MODULE_PATTERN, ARRAYSIZE(LDRP_PIN_MODULE_PATTERN) - 1) ,assert(LdrpPinModule)); (LdrpApplyPatchImage = (tLdrpApplyPatchImage) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_APPLY_PATCH_IMAGE_PATTERN, ARRAYSIZE(LDRP_APPLY_PATCH_IMAGE_PATTERN) - 1) ,assert(LdrpApplyPatchImage)); (LdrpFreeLoadContextOfNode = (tLdrpFreeLoadContextOfNode) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FREE_LOADCONTEXT_NODE_PATTERN, ARRAYSIZE(LDRP_FREE_LOADCONTEXT_NODE_PATTERN) - 1) ,assert(LdrpFreeLoadContextOfNode)); (LdrpDecrementModuleLoadCountEx = (tLdrpDecrementModuleLoadCountEx) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DECREMENT_MODULELOADCOUNTEX_PATTERN, ARRAYSIZE(LDRP_DECREMENT_MODULELOADCOUNTEX_PATTERN) - 1) ,assert(LdrpDecrementModuleLoadCountEx)); (LdrpLogError = (tLdrpLogError) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_ERROR_PATTERN, ARRAYSIZE(LDRP_LOG_ERROR_PATTERN) - 1) ,assert(LdrpLogError)); (LdrpLogDeprecatedDllEtwEvent = (tLdrpLogDeprecatedDllEtwEvent) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_DEPRECATED_DLL_PATTERN, ARRAYSIZE(LDRP_LOG_DEPRECATED_DLL_PATTERN) - 1) ,assert(LdrpLogDeprecatedDllEtwEvent)); (LdrpLogLoadFailureEtwEvent = (tLdrpLogLoadFailureEtwEvent) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_LOAD_FAILURE_PATTERN, ARRAYSIZE(LDRP_LOG_LOAD_FAILURE_PATTERN) - 1) ,assert(LdrpLogLoadFailureEtwEvent)); (LdrpReportError = (tLdrpReportError) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_REPORT_ERROR_PATTERN, ARRAYSIZE(LDRP_REPORT_ERROR_PATTERN) - 1) ,assert(LdrpReportError)); (LdrpResolveDllName = (tLdrpResolveDllName) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_RESOLVE_DLLNAME_PATTERN, ARRAYSIZE(LDRP_RESOLVE_DLLNAME_PATTERN) - 1) ,assert(LdrpResolveDllName)); (LdrpAppCompatRedirect = (tLdrpAppCompatRedirect) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_APP_COMPAT_REDIRECT_PATTERN, ARRAYSIZE(LDRP_APP_COMPAT_REDIRECT_PATTERN) - 1) ,assert(LdrpAppCompatRedirect)); (LdrpHashUnicodeString = (tLdrpHashUnicodeString) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_HASH_UNICODE_STRING_PATTERN, ARRAYSIZE(LDRP_HASH_UNICODE_STRING_PATTERN) - 1) ,assert(LdrpHashUnicodeString)); (LdrpFindExistingModule = (tLdrpFindExistingModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FIND_EXISTING_MODULE_PATTERN, ARRAYSIZE(LDRP_FIND_EXISTING_MODULE_PATTERN) - 1) ,assert(LdrpFindExistingModule)); (LdrpLoadContextReplaceModule = (tLdrpLoadContextReplaceModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOADCONTEXT_REPLACE_MODULE_PATTERN, ARRAYSIZE(LDRP_LOADCONTEXT_REPLACE_MODULE_PATTERN) - 1) ,assert(LdrpLoadContextReplaceModule)); (LdrpSearchPath = (tLdrpSearchPath) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_SEARCHPATH_PATTERN, ARRAYSIZE(LDRP_SEARCHPATH_PATTERN) - 1) ,assert(LdrpSearchPath)); (LdrpIsSecurityEtwLoggingEnabled = (tLdrpIsSecurityEtwLoggingEnabled) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_ISSECURITYETW_LOGG_ENABLED_PATTERN, ARRAYSIZE(LDRP_ISSECURITYETW_LOGG_ENABLED_PATTERN) - 1) ,assert(LdrpIsSecurityEtwLoggingEnabled)); (LdrpLogEtwDllSearchResults = (tLdrpLogEtwDllSearchResults) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOGETW_DLL_SEARCHRESULTS_PATTERN, ARRAYSIZE(LDRP_LOGETW_DLL_SEARCHRESULTS_PATTERN) - 1) ,assert(LdrpLogEtwDllSearchResults)); (LdrpCheckForRetryLoading = (tLdrpCheckForRetryLoading) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CHECKFORRETRY_LOADING_PATTERN, ARRAYSIZE(LDRP_CHECKFORRETRY_LOADING_PATTERN) - 1) ,assert(LdrpCheckForRetryLoading)); (LdrpLogEtwEvent = (tLdrpLogEtwEvent) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_ETWEVENT_PATTERN, ARRAYSIZE(LDRP_LOG_ETWEVENT_PATTERN) - 1) ,assert(LdrpLogEtwEvent)); (LdrpCheckComponentOnDemandEtwEvent = (tLdrpCheckComponentOnDemandEtwEvent) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CHECK_COMPONENTONDEMAND_PATTERN, ARRAYSIZE(LDRP_CHECK_COMPONENTONDEMAND_PATTERN) - 1) ,assert(LdrpCheckComponentOnDemandEtwEvent)); (LdrpValidateIntegrityContinuity = (tLdrpValidateIntegrityContinuity) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_VALIDATE_INTEGRITY_PATTERN, ARRAYSIZE(LDRP_VALIDATE_INTEGRITY_PATTERN) - 1) ,assert(LdrpValidateIntegrityContinuity)); (LdrpSetModuleSigningLevel = (tLdrpSetModuleSigningLevel) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_SET_MODULE_SIGNINGLEVEL_PATTERN, ARRAYSIZE(LDRP_SET_MODULE_SIGNINGLEVEL_PATTERN) - 1) ,assert(LdrpSetModuleSigningLevel)); (LdrpCodeAuthzCheckDllAllowed = (tLdrpCodeAuthzCheckDllAllowed) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CODE_AUTHZCHECKDLL_ALLOWED_PATTERN, ARRAYSIZE(LDRP_CODE_AUTHZCHECKDLL_ALLOWED_PATTERN) - 1) ,assert(LdrpCodeAuthzCheckDllAllowed)); (LdrpGetFullPath = (tLdrpGetFullPath) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_GET_FULLPATH_PATTERN, ARRAYSIZE(LDRP_GET_FULLPATH_PATTERN) - 1) ,assert(LdrpGetFullPath)); (LdrpAllocateUnicodeString = (tLdrpAllocateUnicodeString) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_ALLOCATE_UNICODESTRING_PATTERN, ARRAYSIZE(LDRP_ALLOCATE_UNICODESTRING_PATTERN) - 1) ,assert(LdrpAllocateUnicodeString)); (LdrpAppendUnicodeStringToFilenameBuffer = (tLdrpAppendUnicodeStringToFilenameBuffer)Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_APPEND_UNICODETOFILENAME_PATTERN, ARRAYSIZE(LDRP_APPEND_UNICODETOFILENAME_PATTERN) - 1) ,assert(LdrpAppendUnicodeStringToFilenameBuffer)); (LdrpGetNtPathFromDosPath = (tLdrpGetNtPathFromDosPath) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_GET_NTPATH_FROM_DOSPATH_PATTERN, ARRAYSIZE(LDRP_GET_NTPATH_FROM_DOSPATH_PATTERN) - 1) ,assert(LdrpGetNtPathFromDosPath)); (LdrpFindLoadedDllByMappingLockHeld = (tLdrpFindLoadedDllByMappingLockHeld) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_FIND_LOADEDDLL_MAPLOCK_PATTERN, ARRAYSIZE(LDRP_FIND_LOADEDDLL_MAPLOCK_PATTERN) - 1) ,assert(LdrpFindLoadedDllByMappingLockHeld)); (LdrpInsertDataTableEntry = (tLdrpInsertDataTableEntry) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_INSERT_DATATABLEENTRY_PATTERN, ARRAYSIZE(LDRP_INSERT_DATATABLEENTRY_PATTERN) - 1) ,assert(LdrpInsertDataTableEntry)); (LdrpInsertModuleToIndexLockHeld = (tLdrpInsertModuleToIndexLockHeld) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_INSERT_MODTOIDX_LOCKHELD_PATTERN, ARRAYSIZE(LDRP_INSERT_MODTOIDX_LOCKHELD_PATTERN) - 1) ,assert(LdrpInsertModuleToIndexLockHeld)); (LdrpLogEtwHotPatchStatus = (tLdrpLogEtwHotPatchStatus) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOGETW_HOTPATCHSTATUS_PATTERN, ARRAYSIZE(LDRP_LOGETW_HOTPATCHSTATUS_PATTERN) - 1) ,assert(LdrpLogEtwHotPatchStatus)); (LdrpLogNewDllLoad = (tLdrpLogNewDllLoad) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_NEWDLL_LOAD_PATTERN, ARRAYSIZE(LDRP_LOG_NEWDLL_LOAD_PATTERN) - 1) ,assert(LdrpLogNewDllLoad)); (LdrpProcessMachineMismatch = (tLdrpProcessMachineMismatch) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_PROCESS_MACHINE_MISMATCH_PATTERN, ARRAYSIZE(LDRP_PROCESS_MACHINE_MISMATCH_PATTERN) - 1) ,assert(LdrpProcessMachineMismatch)); (RtlQueryImageFileKeyOption = (tRtlQueryImageFileKeyOption) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, RTL_QUERY_IMAGEFILE_KEYOPT_PATTERN, ARRAYSIZE(RTL_QUERY_IMAGEFILE_KEYOPT_PATTERN) - 1) ,assert(RtlQueryImageFileKeyOption)); (RtlpImageDirectoryEntryToDataEx = (tRtlpImageDirectoryEntryToDataEx) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, RTLP_IMAGEDIR_ENTRYTODATA_PATTERN, ARRAYSIZE(RTLP_IMAGEDIR_ENTRYTODATA_PATTERN) - 1) ,assert(RtlpImageDirectoryEntryToDataEx)); (LdrpLogDllRelocationEtwEvent = (tLdrpLogDllRelocationEtwEvent) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOG_DLLRELOCATION_PATTERN, ARRAYSIZE(LDRP_LOG_DLLRELOCATION_PATTERN) - 1) ,assert(LdrpLogDllRelocationEtwEvent)); (LdrpNotifyLoadOfGraph = (tLdrpNotifyLoadOfGraph) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_NOTIFY_LOADOFGRAPH_PATTERN, ARRAYSIZE(LDRP_NOTIFY_LOADOFGRAPH_PATTERN) - 1) ,assert(LdrpNotifyLoadOfGraph)); (LdrpDynamicShimModule = (tLdrpDynamicShimModule) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_DYNAMIC_SHIMMODULE_PATTERN, ARRAYSIZE(LDRP_DYNAMIC_SHIMMODULE_PATTERN) - 1) ,assert(LdrpDynamicShimModule)); (LdrpAcquireLoaderLock = (tLdrpAcquireLoaderLock) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_ACQUIRE_LOADERLOCK_PATTERN, ARRAYSIZE(LDRP_ACQUIRE_LOADERLOCK_PATTERN) - 1) ,assert(LdrpAcquireLoaderLock)); (LdrpReleaseLoaderLock = (tLdrpReleaseLoaderLock) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_RELEASE_LOADER_LOCK_PATTERN, ARRAYSIZE(LDRP_RELEASE_LOADER_LOCK_PATTERN) - 1) ,assert(LdrpReleaseLoaderLock)); (LdrpCheckPagesForTampering = (tLdrpCheckPagesForTampering) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CHECKPAGES_FOR_TAMPERING_PATTERN, ARRAYSIZE(LDRP_CHECKPAGES_FOR_TAMPERING_PATTERN) - 1) ,assert(LdrpCheckPagesForTampering)); (LdrpLoadDependentModuleA = (tLdrpLoadDependentModuleA) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOAD_DEPENDENTMODULEA_PATTERN, ARRAYSIZE(LDRP_LOAD_DEPENDENTMODULEA_PATTERN) - 1) ,assert(LdrpLoadDependentModuleA)); (LdrpLoadDependentModuleW = (tLdrpLoadDependentModuleW) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_LOAD_DEPENDENTMODULEW_PATTERN, ARRAYSIZE(LDRP_LOAD_DEPENDENTMODULEW_PATTERN) - 1) ,assert(LdrpLoadDependentModuleW)); (LdrpQueueWork = (tLdrpQueueWork) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_QUEUE_WORK_PATTERN, ARRAYSIZE(LDRP_QUEUE_WORK_PATTERN) - 1) ,assert(LdrpQueueWork)); (LdrpHandleTlsData = (tLdrpHandleTlsData) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_HANDLE_TLSDATA_PATTERN, ARRAYSIZE(LDRP_HANDLE_TLSDATA_PATTERN) - 1) ,assert(LdrpHandleTlsData)); (LdrControlFlowGuardEnforcedWithExportSuppression = (tLdrControlFlowGuardEnforcedWithExportSuppression)Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDR_CONTROLFLOWGUARD_ENFEXP_PATTERN,ARRAYSIZE(LDR_CONTROLFLOWGUARD_ENFEXP_PATTERN) - 1) ,assert(LdrControlFlowGuardEnforcedWithExportSuppression)); (LdrpUnsuppressAddressTakenIat = (tLdrpUnsuppressAddressTakenIat) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_UNSUPPRESS_ADDRESSIAT_PATTERN, ARRAYSIZE(LDRP_UNSUPPRESS_ADDRESSIAT_PATTERN) - 1) ,assert(LdrpUnsuppressAddressTakenIat)); (LdrControlFlowGuardEnforced = (tLdrControlFlowGuardEnforced) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDR_CONTROLFLOWGUARD_ENF_PATTERN, ARRAYSIZE(LDR_CONTROLFLOWGUARD_ENF_PATTERN) - 1) ,assert(LdrControlFlowGuardEnforced)); (RtlpxLookupFunctionTable = (tRtlpxLookupFunctionTable) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, RTLP_LOOKUP_FUNCTIONTABLE_PATTERN, ARRAYSIZE(RTLP_LOOKUP_FUNCTIONTABLE_PATTERN) - 1) ,assert(RtlpxLookupFunctionTable)); (LdrpCheckRedirection = (tLdrpCheckRedirection) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CHECK_REDIRECTION_PATTERN, ARRAYSIZE(LDRP_CHECK_REDIRECTION_PATTERN) - 1) ,assert(LdrpCheckRedirection)); (CompatCachepLookupCdb = (tCompatCachepLookupCdb) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, COMPAT_CACHE_LOOKUPCDB_PATTERN, ARRAYSIZE(COMPAT_CACHE_LOOKUPCDB_PATTERN) - 1) ,assert(CompatCachepLookupCdb)); (LdrpGenRandom = (tLdrpGenRandom) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_GEN_RANDOM_PATTERN, ARRAYSIZE(LDRP_GEN_RANDOM_PATTERN) - 1) ,assert(LdrpGenRandom)); (LdrInitSecurityCookie = (tLdrInitSecurityCookie) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDR_INIT_SECURITY_COOKIE_PATTERN, ARRAYSIZE(LDR_INIT_SECURITY_COOKIE_PATTERN) - 1) ,assert(LdrInitSecurityCookie)); (LdrpCfgProcessLoadConfig = (tLdrpCfgProcessLoadConfig) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CFG_PROCESS_LOADCFG_PATTERN, ARRAYSIZE(LDRP_CFG_PROCESS_LOADCFG_PATTERN) - 1) ,assert(LdrpCfgProcessLoadConfig)); (RtlInsertInvertedFunctionTable = (tRtlInsertInvertedFunctionTable) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, RTL_INSERT_INV_FUNCTIONTABLE_PATTERN, ARRAYSIZE(RTL_INSERT_INV_FUNCTIONTABLE_PATTERN) - 1) ,assert(RtlInsertInvertedFunctionTable)); (LdrpSignalModuleMapped = (tLdrpSignalModuleMapped) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_SIGNAL_MODULEMAPPED_PATTERN, ARRAYSIZE(LDRP_SIGNAL_MODULEMAPPED_PATTERN) - 1) ,assert(LdrpSignalModuleMapped)); (AVrfDllLoadNotification = (tAVrfDllLoadNotification) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, AVRF_DLL_LOADNOTIFICATION_PATTERN, ARRAYSIZE(AVRF_DLL_LOADNOTIFICATION_PATTERN) - 1) ,assert(AVrfDllLoadNotification)); (LdrpSendDllNotifications = (tLdrpSendDllNotifications) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_SEND_DLLNOTIFICATIONS_PATTERN, ARRAYSIZE(LDRP_SEND_DLLNOTIFICATIONS_PATTERN) - 1) ,assert(LdrpSendDllNotifications)); (LdrpCallTlsInitializers = (tLdrpCallTlsInitializers) Helper::SigScan((PCHAR)NtdllModule, NtdllModuleInfo.SizeOfImage, LDRP_CALL_TLSINIT_PATTERN, ARRAYSIZE(LDRP_CALL_TLSINIT_PATTERN) - 1) ,assert(LdrpCallTlsInitializers)); WID_DBG(TEXT("[WID] >> Initialized.\n")); bInitialized = TRUE; return STATUS_SUCCESS; } WID_DBG(TEXT("[WID] >> Already initialized.\n")); return STATUS_SUCCESS; } PVOID WID::Helper::SigScan(PCHAR StartAddress, SIZE_T Len, PCHAR Pattern, SIZE_T PatternLen) { bool Found = TRUE; for (int i1 = 0; i1 < Len; i1++) { Found = TRUE; for (int i2 = 0; i2 < PatternLen; i2++) { if (Pattern[i2] != 0x90 && StartAddress[i1 + i2] != Pattern[i2]) { Found = FALSE; break; } } if (Found) return StartAddress + i1; } return nullptr; } ================================================ FILE: Src/WID.h ================================================ #pragma once #include "Includes.h" #include "Functions/KERNEL32.h" #include "Functions/NT.h" #include "Functions/Undocumented.h" #include "Loader/Loader.h" #ifdef _DEBUG #ifdef UNICODE #define WID_DBG wprintf #else #define WID_DBG printf #endif #else #define WID_DBG ; #endif #define WID_HIDDEN(x) { if(CreationInfo.LoadType == LOADTYPE::DEFAULT){x} } namespace WID { extern BOOLEAN bInitialized; extern MODULEINFO Kernel32ModuleInfo; extern MODULEINFO KernelBaseModuleInfo; extern MODULEINFO NtdllModuleInfo; NTSTATUS Init(); namespace Helper { PVOID SigScan(PCHAR StartAddress, SIZE_T Len, PCHAR Pattern, SIZE_T PatternLen); } } ================================================ FILE: WID_LoadLibrary.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.4.33213.308 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WID_LoadLibrary", "WID_LoadLibrary.vcxproj", "{096D6383-D4DE-494B-B324-A925C690CD93}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {096D6383-D4DE-494B-B324-A925C690CD93}.Debug|x64.ActiveCfg = Debug|x64 {096D6383-D4DE-494B-B324-A925C690CD93}.Debug|x64.Build.0 = Debug|x64 {096D6383-D4DE-494B-B324-A925C690CD93}.Debug|x86.ActiveCfg = Debug|Win32 {096D6383-D4DE-494B-B324-A925C690CD93}.Debug|x86.Build.0 = Debug|Win32 {096D6383-D4DE-494B-B324-A925C690CD93}.Release|x64.ActiveCfg = Release|x64 {096D6383-D4DE-494B-B324-A925C690CD93}.Release|x64.Build.0 = Release|x64 {096D6383-D4DE-494B-B324-A925C690CD93}.Release|x86.ActiveCfg = Release|Win32 {096D6383-D4DE-494B-B324-A925C690CD93}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C5486FDA-3A69-4FF4-9FD5-4DCF94799F68} EndGlobalSection EndGlobal ================================================ FILE: WID_LoadLibrary.vcxproj ================================================ Debug Win32 Release Win32 Debug x64 Release x64 17.0 {096D6383-D4DE-494B-B324-A925C690CD93} Win32Proj Application true v143 Application false v143 Application true v143 Unicode Application false v143 true true WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level3 ProgramDatabase Disabled MachineX86 true Console WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase MachineX86 true Console true true Document ================================================ FILE: WID_LoadLibrary.vcxproj.filters ================================================  {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hh;hpp;hxx;hm;inl;inc;xsd {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav Source Files Source Files Source Files Source Files Source Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files