mirror of
				https://github.com/HackTricks-wiki/hacktricks.git
				synced 2025-10-10 18:36:50 +00:00 
			
		
		
		
	Merge pull request #1335 from HackTricks-wiki/update_CreateProcessAsPPL__launch_a_Windows_Protected_Pro_20250825_124827
CreateProcessAsPPL launch a Windows Protected Process Light
This commit is contained in:
		
						commit
						f28318eeaa
					
				| @ -38,6 +38,64 @@ This structure is packed into a single byte and determines **who can access whom | ||||
| - LSASS being PPL does **not prevent credential dumping if you can execute kernel shellcode** or **leverage a high-privileged process with proper access**. | ||||
| - **Setting or removing PPL** requires reboot or **Secure Boot/UEFI settings**, which can persist the PPL setting even after registry changes are reversed. | ||||
|    | ||||
| ### Create a PPL process at launch (documented API) | ||||
| 
 | ||||
| Windows exposes a documented way to request a Protected Process Light level for a child process during creation using the extended startup attribute list. This does not bypass signing requirements — the target image must be signed for the requested signer class. | ||||
| 
 | ||||
| Minimal flow in C/C++: | ||||
| 
 | ||||
| ```c | ||||
| // Request a PPL protection level for the child process at creation time | ||||
| // Requires Windows 8.1+ and a properly signed image for the selected level | ||||
| #include <windows.h> | ||||
| 
 | ||||
| int wmain(int argc, wchar_t **argv) { | ||||
|     STARTUPINFOEXW si = {0}; | ||||
|     PROCESS_INFORMATION pi = {0}; | ||||
|     si.StartupInfo.cb = sizeof(si); | ||||
| 
 | ||||
|     SIZE_T attrSize = 0; | ||||
|     InitializeProcThreadAttributeList(NULL, 1, 0, &attrSize); | ||||
|     si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attrSize); | ||||
|     if (!si.lpAttributeList) return 1; | ||||
| 
 | ||||
|     if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attrSize)) return 1; | ||||
| 
 | ||||
|     DWORD level = PROTECTION_LEVEL_ANTIMALWARE_LIGHT; // or WINDOWS_LIGHT/LSA_LIGHT/WINTCB_LIGHT | ||||
|     if (!UpdateProcThreadAttribute( | ||||
|             si.lpAttributeList, 0, | ||||
|             PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL, | ||||
|             &level, sizeof(level), NULL, NULL)) { | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     DWORD flags = EXTENDED_STARTUPINFO_PRESENT; | ||||
|     if (!CreateProcessW(L"C\\Windows\\System32\\notepad.exe", NULL, NULL, NULL, FALSE, | ||||
|                         flags, NULL, NULL, &si.StartupInfo, &pi)) { | ||||
|         // If the image isn't signed appropriately for the requested level, | ||||
|         // CreateProcess will fail with ERROR_INVALID_IMAGE_HASH (577). | ||||
|         return 1; | ||||
|     } | ||||
| 
 | ||||
|     // cleanup | ||||
|     DeleteProcThreadAttributeList(si.lpAttributeList); | ||||
|     HeapFree(GetProcessHeap(), 0, si.lpAttributeList); | ||||
|     CloseHandle(pi.hThread); | ||||
|     CloseHandle(pi.hProcess); | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Notes and constraints: | ||||
| - Use `STARTUPINFOEX` with `InitializeProcThreadAttributeList` and `UpdateProcThreadAttribute(PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL, ...)`, then pass `EXTENDED_STARTUPINFO_PRESENT` to `CreateProcess*`. | ||||
| - The protection `DWORD` can be set to constants such as `PROTECTION_LEVEL_WINTCB_LIGHT`, `PROTECTION_LEVEL_WINDOWS`, `PROTECTION_LEVEL_WINDOWS_LIGHT`, `PROTECTION_LEVEL_ANTIMALWARE_LIGHT`, or `PROTECTION_LEVEL_LSA_LIGHT`. | ||||
| - The child only starts as PPL if its image is signed for that signer class; otherwise process creation fails, commonly with `ERROR_INVALID_IMAGE_HASH (577)` / `STATUS_INVALID_IMAGE_HASH (0xC0000428)`. | ||||
| - This is not a bypass — it’s a supported API meant for appropriately signed images. Useful to harden tools or validate PPL-protected configurations. | ||||
| 
 | ||||
| Example CLI using a minimal loader: | ||||
| - Antimalware signer: `CreateProcessAsPPL.exe 3 C:\Tools\agent.exe --svc` | ||||
| - LSA-light signer: `CreateProcessAsPPL.exe 4 C:\Windows\System32\notepad.exe` | ||||
| 
 | ||||
| **Bypass PPL protections options:** | ||||
| 
 | ||||
| If you want to dump LSASS despite PPL, you have 3 main options: | ||||
| @ -143,7 +201,12 @@ For more detailed information, consult the official [documentation](https://docs | ||||
| | Schema Admins           | Schema Admins            | Schema Admins                                                                 | Schema Admins                | | ||||
| | Server Operators        | Server Operators         | Server Operators                                                              | Server Operators             | | ||||
| 
 | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
| 
 | ||||
| ## References | ||||
| 
 | ||||
| - [CreateProcessAsPPL – minimal PPL process launcher](https://github.com/2x7EQ13/CreateProcessAsPPL) | ||||
| - [STARTUPINFOEX structure (Win32 API)](https://learn.microsoft.com/en-us/windows/win32/api/winbase/ns-winbase-startupinfoexw) | ||||
| - [InitializeProcThreadAttributeList (Win32 API)](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-initializeprocthreadattributelist) | ||||
| - [UpdateProcThreadAttribute (Win32 API)](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-updateprocthreadattribute) | ||||
| - [LSASS RunAsPPL – background and internals](https://itm4n.github.io/lsass-runasppl/) | ||||
| 
 | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
| @ -106,7 +106,7 @@ int wmain(void) { | ||||
|         STARTUPINFOW si = { .cb = sizeof(si) }; | ||||
|         PROCESS_INFORMATION pi = { 0 }; | ||||
|         if (CreateProcessWithTokenW(dupToken, LOGON_WITH_PROFILE, | ||||
|                 L"C\\\Windows\\\System32\\\cmd.exe", NULL, CREATE_NEW_CONSOLE, | ||||
|                 L"C\\\\Windows\\\\System32\\\\cmd.exe", NULL, CREATE_NEW_CONSOLE, | ||||
|                 NULL, NULL, &si, &pi)) { | ||||
|             CloseHandle(pi.hProcess); | ||||
|             CloseHandle(pi.hThread); | ||||
| @ -159,8 +159,54 @@ int main(void) { | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## Create child as Protected Process Light (PPL) | ||||
| Request a PPL protection level for a child at creation time using `STARTUPINFOEX` + `PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL`. This is a documented API and will only succeed if the target image is signed for the requested signer class (Windows/WindowsLight/Antimalware/LSA/WinTcb). | ||||
| 
 | ||||
| ```c | ||||
| // x86_64-w64-mingw32-gcc -O2 -o spawn_ppl.exe spawn_ppl.c | ||||
| #include <windows.h> | ||||
| 
 | ||||
| int wmain(void) { | ||||
|     STARTUPINFOEXW si = {0}; | ||||
|     PROCESS_INFORMATION pi = {0}; | ||||
|     si.StartupInfo.cb = sizeof(si); | ||||
| 
 | ||||
|     SIZE_T attrSize = 0; | ||||
|     InitializeProcThreadAttributeList(NULL, 1, 0, &attrSize); | ||||
|     si.lpAttributeList = (PPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(GetProcessHeap(), 0, attrSize); | ||||
|     InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &attrSize); | ||||
| 
 | ||||
|     DWORD lvl = PROTECTION_LEVEL_ANTIMALWARE_LIGHT; // choose the desired level | ||||
|     UpdateProcThreadAttribute(si.lpAttributeList, 0, | ||||
|         PROC_THREAD_ATTRIBUTE_PROTECTION_LEVEL, | ||||
|         &lvl, sizeof(lvl), NULL, NULL); | ||||
| 
 | ||||
|     if (!CreateProcessW(L"C\\\Windows\\\System32\\\notepad.exe", NULL, NULL, NULL, FALSE, | ||||
|                         EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, &si.StartupInfo, &pi)) { | ||||
|         // likely ERROR_INVALID_IMAGE_HASH (577) if the image is not properly signed for that level | ||||
|         return 1; | ||||
|     } | ||||
|     DeleteProcThreadAttributeList(si.lpAttributeList); | ||||
|     HeapFree(GetProcessHeap(), 0, si.lpAttributeList); | ||||
|     CloseHandle(pi.hThread); | ||||
|     CloseHandle(pi.hProcess); | ||||
|     return 0; | ||||
| } | ||||
| ``` | ||||
| 
 | ||||
| Levels used most commonly: | ||||
| - `PROTECTION_LEVEL_WINDOWS_LIGHT` (2) | ||||
| - `PROTECTION_LEVEL_ANTIMALWARE_LIGHT` (3) | ||||
| - `PROTECTION_LEVEL_LSA_LIGHT` (4) | ||||
| 
 | ||||
| Validate the result with Process Explorer/Process Hacker by checking the Protection column. | ||||
| 
 | ||||
| --- | ||||
| 
 | ||||
| ## References | ||||
| * Ron Bowes – “Fodhelper UAC Bypass Deep Dive” (2024) | ||||
| * SplinterCode – “AMSI Bypass 2023: The Smallest Patch Is Still Enough” (BlackHat Asia 2023) | ||||
| * CreateProcessAsPPL – minimal PPL process launcher: https://github.com/2x7EQ13/CreateProcessAsPPL | ||||
| * Microsoft Docs – STARTUPINFOEX / InitializeProcThreadAttributeList / UpdateProcThreadAttribute | ||||
| 
 | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
| {{#include ../../banners/hacktricks-training.md}} | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user