mirror of
https://github.com/ElliotKillick/LdrLockLiberator
synced 2026-06-06 15:34:33 +00:00
Update
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (C) 2023 Elliot Killick <contact@elliotkillick.com>
|
||||
Copyright (C) 2023-2024 Elliot Killick <contact@elliotkillick.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+11
-3
@@ -1,3 +1,6 @@
|
||||
// Copyright (C) 2023 Elliot Killick <contact@elliotkillick.com>
|
||||
// Licensed under the MIT License. See LICENSE file for details.
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <Windows.h>
|
||||
#include <winternl.h> // For NTSTATUS
|
||||
@@ -91,7 +94,7 @@ PCRITICAL_SECTION getLdrpLoaderLockAddress(VOID) {
|
||||
INT32 rel32EncodedAddress = *(PINT32)(ldrUnlockLoaderLockSearchCounter + sizeof(callAddressOpcode));
|
||||
|
||||
// Reverse engineering Native API function: LdrpReleaseLoaderLock
|
||||
// First argument: For output only, it returns a pointer (pointing to USER_SHARED_DATA, a read-only section used by the kernel) to a byte
|
||||
// First argument: For output only, it returns a pointer (pointing to KUSER_SHARED_DATA, a read-only section used by the kernel) to a byte
|
||||
// - The value of this byte should be zero under normal circumstances, otherwise the code jumps to some error-handling (the program may recover and jump back to the LdrpReleaseLoaderLock code or terminate)
|
||||
// Second argument: Unused (Exists in API for compatibility with previous/different Windows version? Reserved for future use?)
|
||||
// Third argument: Jump to error-handling code if it's a negative value
|
||||
@@ -262,7 +265,9 @@ VOID LdrFullUnlock(VOID) {
|
||||
// ntdll!LdrpWorkInProgress must be ZERO while libraries are loading in the newly spawned thread (requires further research)
|
||||
// For this reason, we must preload the libraries loaded by ShellExecute
|
||||
// Perform this operation atomically with InterlockedDecrement to maintain thread safety (I'm not sure this is necessary given that the NTDLL code isn't doing it but we will be even safer than Microsoft here)
|
||||
InterlockedDecrement64(LdrpWorkInProgress);
|
||||
// NOTE: SAFELY MODIFYING the LdrpWorkInProgress state mandates acquring the LdrpWorkQueueLock. I will leave this as an exercise to the reader.
|
||||
// Technically, loading a library at process startup means you can get away safely without acquiring the LdrpWorkQueueLock lock here
|
||||
LdrpWorkInProgress = 0;
|
||||
|
||||
//
|
||||
// Run our payload!
|
||||
@@ -285,7 +290,9 @@ VOID LdrFullUnlock(VOID) {
|
||||
// Must set ntdll!LdrpWorkInProgress back to NON-ZERO otherwise we crash/deadlock in NTDLL library loader code sometime after returning from DllMain
|
||||
// The crash/deadlock occurs to due to concurrent operations happening in other threads
|
||||
// The problem arises due to ntdll!TppWorkerThread threads by default (https://devblogs.microsoft.com/oldnewthing/20191115-00/?p=103102)
|
||||
InterlockedAdd64(LdrpWorkInProgress, 1);
|
||||
// NOTE: SAFELY MODIFYING the LdrpWorkInProgress state mandates acquring the LdrpWorkQueueLock. I will leave this as an exercise to the reader. Alternatively, exit the process.
|
||||
// There is a real chance of crashing here without acquiring the LdrpWorkQueueLock here now that other, potentialy load owner threads, are operating inside the process. Continue without acquiring the LdrpWorkQueueLock at your own risk.
|
||||
LdrpWorkInProgress = 1;
|
||||
// Reset these events to how they were to be safe (although it doesn't appear to be necessary at least in our case)
|
||||
modifyLdrEvents(FALSE, events, eventsCount);
|
||||
// Reacquire loader lock to be safe (although it doesn't appear to be necessary at least in our case)
|
||||
@@ -563,6 +570,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved)
|
||||
//LdrLockWinRace(lpvReserved);
|
||||
//LdrLockEscapeVehCatchException();
|
||||
//LdrLockDetonateNuclearOption();
|
||||
break;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
// Copyright (C) 2023 Elliot Killick <contact@elliotkillick.com>
|
||||
// Licensed under the MIT License. See LICENSE file for details.
|
||||
|
||||
// WIN32_LEAN_AND_MEAN has already been defined (don't redefine to avoid warning)
|
||||
#include <Windows.h>
|
||||
#include <shellapi.h>
|
||||
@@ -52,15 +55,19 @@ EXTERN_C __declspec(dllimport) int __cdecl atexit(void (__cdecl*)(void));
|
||||
//EXTERN_C __declspec(dllimport) int __cdecl _onexit(void (__cdecl*)(void));
|
||||
|
||||
VOID payload(VOID) {
|
||||
ShellExecute(NULL, L"open", L"calc", NULL, NULL, SW_SHOW);
|
||||
|
||||
// Ensure program doesn't terminate before ShellExecute completes (see main project C file for further explanation and the correct way way of doing this)
|
||||
Sleep(3000);
|
||||
}
|
||||
|
||||
VOID atexitHandler(VOID) {
|
||||
// Unlock CRT critical section: msvcrt!CrtLock_Exit
|
||||
// This is necessary because ShellExecute calls atexit on a NEW THREAD
|
||||
// Doing this is 100% safe (see main project C file for details)
|
||||
_unlock(8);
|
||||
|
||||
ShellExecute(NULL, L"open", L"calc.exe", NULL, NULL, SW_SHOW);
|
||||
|
||||
// Ensure program doesn't terminate before ShellExecute completes (see main project C file for further explanation and the correct way way of doing this)
|
||||
Sleep(3000);
|
||||
payload();
|
||||
|
||||
// This is necessary to be 100% safe (see main project C file for details)
|
||||
_lock(8);
|
||||
|
||||
@@ -46,7 +46,7 @@ As a proof of concept, we run `ShellExecute` as the default payload. However, yo
|
||||
|
||||
The `LdrLockLiberator.c` at the root of this project has been tested to compile on Visual Studio 2022.
|
||||
|
||||
Link to NTDLL by navigating from `Project > Properties`, go to `Linker > Input` then append to `Additional Dependencies`: `ntdll.lib`. Configure this for `All Configurations` and `All Platforms`.
|
||||
Link to NTDLL by selecting the current Visual Studio project in the Solution Explorer window, then navigating to `Project > Properties` in the menu bar. From the drop-down `Configuration` menus at the top, select `All Configurations` and `All Platforms`. Now, go to `Linker > Input` then append to `Additional Dependencies`: `ntdll.lib`.
|
||||
|
||||
### WDK
|
||||
|
||||
@@ -54,7 +54,7 @@ Link to NTDLL by navigating from `Project > Properties`, go to `Linker > Input`
|
||||
|
||||
1. Go to the [WDK download page](https://learn.microsoft.com/en-us/windows-hardware/drivers/other-wdk-downloads#step-2-install-the-wdk)
|
||||
2. Click on the Windows 7 [WDK 7.1.0](https://www.microsoft.com/en-us/download/confirmation.aspx?id=11800) link to start download the correct WDK version
|
||||
- This is the last WDK that **officially** supports linking to the original MSVCRT (`C:\Windows\System32\msvcrt.dll`)
|
||||
- This is the last public WDK that **officially** supports linking to the original MSVCRT (`C:\Windows\System32\msvcrt.dll`)
|
||||
- SHA-256 checksum: `5edc723b50ea28a070cad361dd0927df402b7a861a036bbcf11d27ebba77657d`
|
||||
3. Mount the downloaded ISO then run `KitSetup.exe`
|
||||
4. Click through the installation process using the default options
|
||||
@@ -71,4 +71,4 @@ As an alternative to WDK, compiling with MinGW would also probably work.
|
||||
|
||||
## License
|
||||
|
||||
MIT License - Copyright (C) 2023 Elliot Killick <contact@elliotkillick.com>
|
||||
MIT License - Copyright (C) 2023-2024 Elliot Killick <contact@elliotkillick.com>
|
||||
|
||||
Reference in New Issue
Block a user