LegacyHive is an interesting Windows Profile Service vulnerability published by MSNightmare. The public repository describes it as an arbitrary hive-load privilege-escalation vulnerability and makes an unusually direct statement: the released proof of concept was deliberately stripped down, while the original version allegedly needed no additional user credentials and was not limited to UsrClass.dat.
That naturally raises a question: how far can we take the public code using only what was released and, at that moment when I have researched it, it was not patch available?
I spent several days answering that question experimentally. I did not begin by assuming that every privileged registry read was exploitable, nor that every SYSTEM process touching attacker-influenced data meant SYSTEM code execution. I followed each transition with Process Monitor, harmless markers, deliberately missing images, disposable accounts, independent hive backups, and byte-for-byte restoration checks.
The result is both more interesting than simple “works” or “does not work”. The public PoC exposes a real cross-user registry-hive confusion primitive. I was able to extend it far enough for a standard user, using a second standard account, to modify another user's protected UsrClass.dat. I also reached a later administrator-logon path where a High-integrity process consumed an attacker-selected executable command and attempted to open the selected path.
However, the public material still does not provide the missing autonomous trigger that turns this into a complete local privilege-escalation chain.
My deterministic High-integrity test required an administrator account and a later administrator logon in the same machine. That is an important technical result, as it requires waiting for administrator logon is not a practical one-click LPE from an ordinary user.
What the Public LegacyHive PoC Says
The LegacyHive repository says that the public PoC requires credentials for another standard user plus only a name of a third user, which may be an administrator. When successful, it mounts the target user's hive as the helper user's classes root.
It also says something more important: this is a deliberately reduced PoC. According to its author, the original did not need additional credentials, was not limited to UsrClass.dat, and could load any hive.
That distinction matters. The public source demonstrates a powerful primitive, but its final message is essentially “Hive loaded.” It does not show the rest of an unprivileged-to-administrator chain.
The purpose of this research was not to deny that a stronger chain may exist. It was to determine exactly what can be proven from the public code and how much further the primitive can be improved.
The Test Environment and Safety Model
The tests used separate local identities:
labuser: the standard user initiating the experiments.LegacyHiveTest: a disposable helper account belonging only to the localUsersgroup.admin: the protected administrator profile used as the physicalUsrClass.dattarget.
The helper and target profiles were kept unloaded whenever an offline hive operation required it. The probes used harmless text markers, non-operational file associations, signed Windows binaries, or deliberately nonexistent image paths.
Each writer preserved an independent safety copy of the helper's NTUSER.DAT. Cleanup restored the original file and compared it byte-for-byte before deleting the safety copy. Test keys retained for a later consumer were subsequently removed from an offline mount of the target UsrClass.dat and their absence was verified.
This made it possible to distinguish a real security-boundary observation from an artifact of a damaged profile or leftover registry registration.
Understanding the Profile-Loading Confusion
The public PoC modifies the helper profile's registry state offline and uses Windows object-manager objects together with an oplock-controlled profile load. The important outcome is not merely that a file is replaced. It is that a logical classes hive belonging to one identity can become backed by the physical UsrClass.dat of a different identity.
In the standard-helper tests, the system hive list showed:
\REGISTRY\USER\S-1-5-21-3014696492-1777516024-1159550323-1005_Classes
-> \Device\HarddiskVolume3\Users\admin\AppData\Local\Microsoft\Windows\UsrClass.dat
The registry belongs to LegacyHiveTest, a Users-only account. The file UsrClass.dat belongs to the protected admin profile.
This mapping is the center of LegacyHive. Code opening the helper's logical classes hive can operate on data physically stored in another user's protected hive.
Proving the NTUSER.DAT Check/Use Substitution
Before relying on the larger confusion chain, I isolated the underlying Profile Service timing behavior.
A normal profile load showed separate accesses to NTUSER.DAT: an earlier file access, an attribute/reparse-state check, and a later NtLoadKey3 operation. The attribute check and final hive load were separate path resolutions, approximately 0.21 milliseconds apart in the captured run.
An oplock experiment converted that observation into a controlled proof. After ProfSvc reached the earlier access, the original disposable hive was renamed by handle and a structurally valid decoy was placed at the live NTUSER.DAT pathname. The decoy contained only a harmless Desktop value:
C:\LegacyHiveNtuserDecoyMarker
The marker was then read from the live loaded registry, not from the decoy offline. This proved that the object selected by the final path-based hive load could differ from the object present during the earlier check.
A second access-context test gave the decoy an ACL that denied the profile user direct GENERIC_READ access while allowing only SYSTEM and Administrators. The standard user probe received ERROR_ACCESS_DENIED, but ProfSvc still loaded the hive and exposed its marker. This demonstrated an interesting privileged access context, although it did not by itself provide access to another protected profile.
Mounting an Administrator's UsrClass.dat Under a Standard Helper Identity
The next step reproduced and extended the public PoC's cross-user behavior.
While labuser drove the test and LegacyHiveTest supplied the secondary-logon profile, the helper's logical _Classes hive became backed by the administrator's physical UsrClass.dat. A known marker from the administrator hive was read successfully and an existing value was modified through the confused handle.
The first attempt to create a new subkey through RegOpenUserClassesRoot failed. Initially this looked like a permission barrier. It was actually a merged-view routing issue: writes through merged HKEY_CLASSES_ROOT can be redirected according to HKCR merge rules rather than written where the caller expects.
Figure 1. A harmless marker was prepared in the administrator’s UsrClass.dat while the administrator profile was unloaded.
Why the Direct HKU View Matters
Opening the mounted hive directly as:
HKU\<helper-SID>_Classes
changed the result. The standard-user-controlled process successfully created a dedicated subkey, wrote and read a harmless marker, deleted the key, and verified its absence while the confused hive remained loaded.
The live hivelist mapping proved that this operation went through the helper's logical identity but modified the administrator's physical UsrClass.dat.
Figure 2. The marker written through the confused classes-hive handle is visible in the protected target classes hive.
This is a material advance over a simple cross-user read. The demonstrated primitive includes controlled creation, modification, and deletion of registry subkeys in another user's protected classes hive.
Path-Redirection Ideas That Did Not Cross the Boundary
Several obvious ways of turning the profile-loading race into arbitrary protected-file access were tested and rejected by the platform or by the observed consumer behavior:
- A standard helper could not create a replacement profile directory directly under
C:\Users. - Ordinary profile-root junction replacement was blocked by the parent directory ACL.
- NTFS rejected a mount-point final component targeting a file.
- Direct unprivileged file symbolic-link creation failed with
ERROR_PRIVILEGE_NOT_HELD;SeCreateSymbolicLinkPrivilegewas unavailable to the standard token. - Cross-user hard-link creation was denied.
- The helper could query its
ProfileListkey, butKEY_SET_VALUE,KEY_CREATE_SUB_KEY, andWRITE_DACwere denied. - Static analysis of
CreateProcessWithLogonW, Secondary Logon, andLoadUserProfileWfound no caller-controlled hidden profile-path parameter. The path originates in authenticated profile metadata.
I also revisited object-manager system-drive remapping because the technique can be performed differently from a Win32 filesystem symbolic link. A controlled temporary ??\C: remap worked from the low-privileged context and affected some processes, including causing ctfmon.exe to search the fake system tree for MsCtfMonitor.dll. But ProfSvc did not consume the fake-root NTUSER.DAT marker in the combined test. This branch was therefore set aside for LegacyHive rather than treated as evidence for the missing hive-load stage.
Proving Benign Cross-User Configuration Consumption
Being able to write a protected hive is important, but the next question is whether meaningful consumers will use the injected state.
A harmless file association was created in the target UsrClass.dat:
.legacyhive-benign-probe -> LegacyHive.BenignAssociationProbe
with the friendly name:
LegacyHive harmless cross-user association marker
When tested in the relevant target-user classes context, AssocQueryStringW returned the exact marker. This showed that the write was not merely present on disk: a normal Windows API consumed the cross-user-controlled configuration.
It was still not code execution. The value was deliberately non-operational and was removed afterward.
Following Privileged Consumers: RpcSs and DcomLaunch
Process Monitor showed RpcSs reading CLSID data from the confused helper classes hive. That looked promising because the resolver process was svchost.exe running as NETWORK SERVICE at System integrity.
I first installed only harmless CLSID markers. RpcSs successfully opened the controlled CLSID and queried its default value. I then used a deliberately missing LocalServer32 path and confirmed that RpcSs queried both the default value and ServerExecutable.
Finally, I used the existing signed Windows utility C:\Windows\System32\whoami.exe in both fields. RpcSs consumed the registration and DcomLaunch created the selected process with -Embedding.
The decisive detail was the security context:
Impersonating: DESKTOP-DL6K2MP\LegacyHiveTest
Every child ran as LegacyHiveTest at Medium integrity. The SYSTEM broker selected the executable from attacker-influenced cross-user configuration, but it preserved the initiating user's security boundary for access checks and process creation.
This was genuine process selection, not privileged execution.
Following consent.exe During a Cancelled UAC Request
Another strong-looking consumer was consent.exe. A UAC request initiated from the separate standard helper —and cancelled without entering administrator credentials— caused consent.exe, reported as SYSTEM/System, to load the helper's classes hive and read values below its MuiCache tree.
To prove it consumed our data rather than merely neighboring data, I temporarily replaced one known MuiCache value with a unique marker while preserving the original bytes in a recovery value. Process Monitor captured consent.exe reading the exact marker twice.
An all-events capture then resolved the surrounding sequence:
consent.exeobtained a resource reference from protected HKLM OID metadata.- It opened
C:\Windows\System32\wuaueng.dllfor attributes while impersonatingLegacyHiveTest. - It closed the resource file.
- It then queried the matching MuiCache text from the confused classes hive.
No image load occurred. The controlled MuiCache text did not select or redirect the DLL path; it was only cache data consumed after the protected path had already been resolved and checked.
Figure 3. SYSTEM-level consent.exe consumes the controlled MuiCache marker; however, no attacker-selected image load followed.
This established a standard-user-triggerable privileged-process registry-consumption primitive, but not a DLL-load primitive.
The Strongest Result: Standard Helper to High-Integrity Command Resolution
The most important result came from exefile\shell\open\command in the administrator's UsrClass.dat.
From the labuser session, using only the Users-only LegacyHiveTest helper, the writer installed this deliberately nonfunctional command in the protected target hive:
"C:\LegacyHiveMissingHighExefileProbe\LegacyHiveMissing.exe" "%1" %*
Neither the directory nor the executable existed.
For a deterministic laboratory trigger, an administrator created a temporary HKLM RunOnce value pointing to the signed Windows whoami.exe. This setup step explicitly required administrative rights and was kept separate from the standard-user writer.
During the next controlled admin logon, Process Monitor recorded:
Figure 4. High-integrity runonce.exe, running as admin, queries the attacker-controlled exefile\shell\open\command value from the target user’s classes hive.
Process: runonce.exe /Explorer
User: DESKTOP-DL6K2MP\admin
Integrity: High
The same High-integrity process enumerated the laboratory HKLM RunOnce value, queried the controlled per-user exefile\shell\open\command, and attempted four times to open:
C:\LegacyHiveMissingHighExefileProbe\LegacyHiveMissing.exe
Each open returned PATH NOT FOUND, exactly as expected.
Figure 5. The same High-integrity runonce.exe process attempts to open the deliberately absent executable selected by the modified per-user command.
This is the strongest verified result of the investigation. Itproves a standard-helper-to-High execution-redirection path across user profiles:
- A standard user drives the classes-hive confusion using credentials for another Users-only account.
- The write lands in a protected administrator
UsrClass.dat. - A later High-integrity process belonging to that administrator reads the exact controlled command.
- The High process acts on it by opening the selected executable pathname.
It is reasonable to expect that a valid executable at the selected path would be launched by this command-resolution path, not what this safety-controlled run proved. The captured experiment deliberately stopped at the missing-image open. Earlier context-menu-handler tests also did not establish a corresponding High-integrity DLL image load. For that reason, I describe the result as a High-integrity execution-redirection primitive, not as demonstrated arbitrary DLL execution.
Code Used for the Strongest Controlled Test
The code starts with a disposable helper with LOGON_WITH_PROFILE. This is what asks the profile-loading path to load the helper's profile while the separately prepared oplock and object-manager mapping control the relevant resolution window.
if (!CreateProcessWithLogonW(
creds->username,
nullptr,
creds->password,
LOGON_WITH_PROFILE,
L"C:\\Windows\\notepad.exe",
nullptr,
CREATE_SUSPENDED,
nullptr,
nullptr,
&startupInfo,
&processInfo))
{
// Abort and restore the helper hive.
}
The test copies the candidate UsrClass.dat, opens the copy for overlapped access, and requests a batch oplock before starting the helper profile load. A full source would contain the object-manager preparation and cleanup surrounding this abbreviated sequence:
hlock = CreateFileW(
usrClassCopy,
GENERIC_READ | GENERIC_WRITE | DELETE,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
nullptr);
DeviceIoControl(
hlock,
FSCTL_REQUEST_BATCH_OPLOCK,
nullptr, 0,
nullptr, 0,
nullptr,
&overlapped);
CreateThread(nullptr, 0, HiveLoaderThread, &credentials, 0, &threadId);
GetOverlappedResult(hlock, &overlapped, &transferred, TRUE);
After the confused hive is loaded, the important implementation detail is opening the helper's native _Classes hive directly under HKEY_USERS. Using the direct view avoids the merged-HKCR write-routing behavior encountered in the earlier probe:
std::wstring classesPath = helperSid + L"_Classes";
LSTATUS status = RegOpenKeyExW(
HKEY_USERS,
classesPath.c_str(),
0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS | KEY_CREATE_SUB_KEY,
&directClassesRoot);
The writer then creates a new exefile\shell\open\command tree in that direct hive and stores the deliberately missing command. Before doing so, the real probe verifies that the entire exefile subtree, sentinel directory, and sentinel image is absent; it refuses to overwrite or merge with pre-existing state.
const wchar_t commandKey[] = L"exefile\\shell\\open\\command";
const wchar_t missingCommand[] =
L"\"C:\\LegacyHiveMissingHighExefileProbe\\LegacyHiveMissing.exe\" \"%1\" %*";
HKEY command = nullptr;
DWORD disposition = 0;
status = RegCreateKeyExW(
directClassesRoot,
commandKey,
0,
nullptr,
REG_OPTION_NON_VOLATILE,
KEY_QUERY_VALUE | KEY_SET_VALUE,
nullptr,
&command,
&disposition);
if (status == ERROR_SUCCESS && disposition == REG_CREATED_NEW_KEY)
{
status = RegSetValueExW(
command,
nullptr,
0,
REG_SZ,
reinterpret_cast<const BYTE*>(missingCommand),
static_cast<DWORD>((wcslen(missingCommand) + 1) * sizeof(wchar_t)));
}
The executable reads the value back and requires an exact type-and-content match before retaining the probe for consumer testing. It never creates C:\LegacyHiveMissingHighExefileProbe or LegacyHiveMissing.exe.
The writer was invoked from the standard labuser session as follows:
POC_PROBE.exe LegacyHiveTest <helper-password> admin
The later deterministic consumer step was deliberately separated. In our laboratory, an administrator created a temporary HKLM RunOnce value pointing to the signed system whoami.exe, then logged on as admin. Process Monitor was filtered to runonce.exe and captured the High-integrity command lookup and four failed opens of the missing path. Keeping this stage separate is important: it makes the administrative prerequisite visible instead of hiding it inside our test.
What Was Demonstrated
The public LegacyHive technique and the follow-up experiments demonstrated all of the following:
- A real ProfSvc pathname check/use substitution during hive loading.
- Loading of a replacement hive that the standard profile user could not directly read.
- Cross-user mounting of a protected administrator
UsrClass.datbelow a standard helper's logical_Classesidentity. - Controlled creation, modification, reading, and deletion of subkeys in that physical target hive.
- Consumption of injected benign data by normal Windows association APIs.
- Consumption of controlled CLSID/LocalServer configuration by RpcSs and DcomLaunch, with process creation constrained to the helper's Medium token.
- Consumption of an exact controlled MuiCache marker by
consent.exeduring a cancelled UAC flow, without administrator credentials. - Consumption of a controlled
exefilecommand by the target administrator's High-integrityrunonce.exe, followed by attempts to open the selected pathname.
This is substantially more than merely seeing “Hive loaded” allowing the user to elevate to a higher privilege.
What Remains Missing
The experiments did not demonstrate:
- A way to use the public PoC without credentials from a second account.
- A way for an ordinary user to select an arbitrary protected
NTUSER.DATthrough the public Secondary Logon path. - A standard-user-controlled trigger that makes the High-integrity consumer reach the
exefilecommand autonomously. - Execution before or without a later administrator logon.
- A High or SYSTEM image load from an attacker-controlled path in the tested DLL-handler branches.
- An administrator or SYSTEM token returned to the original standard-user session.
- A complete, reliable local privilege-escalation exploit.
The High-integrity RunOnce result is therefore best understood as a conditional post-plant execution-redirection primitive. It shows what can happen when the affected administrator later logs on and a suitable High consumer invokes shell executable resolution. Requiring that logon —and, in our deterministic test, an administrator-created HKLM RunOnce entry— makes it a poor endpoint for a practical exploit.
Final thought
IMHO the original researcher is clearly very talented and has an exceptional understanding of obscure Windows internals. LegacyHive itself is evidence of that. The public README also explicitly says that a stronger original PoC exists: one that needs no additional user credentials and is not restricted to UsrClass.dat.
So my question is straightforward: what is the missing mechanism that connects the published hive-confusion primitive to that complete result?
If the complete LegacyHive chain works as described, I wonder what the missing stages would be like. In particular, it would be valuable to explain:
- How does the original version remove the second user's credential requirement.
- How it escapes the public PoC's effective
UsrClass.datlimitation. - Which code can trigger and provide a reliable and privileged code execution.
- Whether that execution occurs without waiting for an administrator logon, and
- Which security context performs the final file access, image load, or process creation.
Completing that explanation would let everyone verify the claim, understand the real security boundary, and learn from a genuinely unusual Windows technique. That would be more useful than leaving researchers to infer the most important part of the chain from a deliberately incomplete PoC.
TL;DR:
The public LegacyHive PoC is not fake. It exposes a genuine Profile Service hive-confusion primitive.
A standard labuser, using credentials for a disposable helper belonging only to Users, was able to mount the protected administrator UsrClass.dat as the helper's logical classes hive and create controlled registry state inside it.
Several apparent privileged paths preserved the boundary:
- RpcSs/DcomLaunch read the controlled COM registration but launched the selected binary as the Medium-integrity helper.
consent.exeread an exact controlled MuiCache marker as a privileged process, but the related file path came from protected HKLM metadata and was checked while impersonating the helper.- Direct symlink, hard-link, junction, parent-directory, ProfileList, and caller-controlled profile-path ideas did not provide the missing cross-boundary step.
The strongest result in my tests was at administrator logon: High-integrity runonce.exe read an exefile\shell\open\command planted in the administrator's protected UsrClass.dat and attempted four times to open the attacker-selected missing executable. This proves a cross-user standard-helper-to-High execution-redirection primitive.
It still does not prove a complete LPE. The controlled executable was deliberately absent, the deterministic RunOnce trigger required administrative setup, and the path was reached only when the administrator logged on.
LegacyHive uses an unusual technique. The public version nevertheless stops before the stage that would make its strongest claims independently reproducible. If the original unrestricted chain actually exists, publishing that technic would allow the community to validate it and learn from it.