Skip to content

CVE-2024-21338

AppLocker — IOCTL 0x22A018 missing access control allows kernel code execution

Exploited in the Wild

This vulnerability was exploited in the wild before or shortly after patching.

Summary

Field Value
Driver appid.sys
Vulnerability Class IOCTL Hardening
Vulnerable Build 10.0.22621.2506 (KB5031455)
Fixed Build 10.0.22621.3155 (KB5034765)
Exploited ITW Yes

Affected Functions

  • AipSmartHashImageFile
  • CTuneupMgr::NotifyRefresh

Root Cause

The vulnerable driver, appid.sys, is the kernel-mode component of Windows AppLocker, the application whitelisting technology built into Windows. AppLocker creates a device object (\Device\AppId) that user-mode services interact with via DeviceIoControl. Among the IOCTL codes handled by the driver's dispatch routine is 0x22A018, which dispatches to a handler responsible for computing a "smart hash" of a file. This handler calls the internal function AipSmartHashImageFile, which maps the target file into kernel memory and produces a hash used by AppLocker's policy evaluation logic. The IOCTL uses METHOD_NEITHER for buffer passing, meaning the I/O manager does not perform any buffering or probing of the user-supplied input and output pointers -- the driver receives raw user-mode addresses directly.

The core vulnerability is the absence of proper access control checks on IOCTL 0x22A018. Any process running at any privilege level could open a handle to the AppLocker device and send this control code. The handler dereferences a user-supplied pointer from the input buffer without adequate validation, trusting that the caller has provided a legitimate file path structure. Because the IOCTL uses METHOD_NEITHER, an attacker can pass a carefully crafted pointer that the kernel follows during the hash computation, effectively turning the handler into an arbitrary kernel read/write primitive. This IOCTL was designed strictly for AppLocker's internal policy evaluation pipeline and was never intended to be accessible to unprivileged processes, but no check enforced that restriction.

AutoPiff categorizes this as ioctl_hardening with detection rules:

  • ioctl_input_size_validation_added
  • ioctl_code_default_case_added

Exploitation

CVE-2024-21338 was exploited in the wild by the Lazarus Group (a North Korean APT) as an admin-to-kernel zero-day to deploy the FudModule rootkit. The attack was discovered and documented by researchers at Gen Digital (Avast). Notably, this was characterized as a "beyond BYOVD" attack: rather than bringing a vulnerable third-party driver onto the system (the typical Bring Your Own Vulnerable Driver technique), Lazarus exploited a zero-day vulnerability in appid.sys, a driver that ships with every modern Windows installation and is loaded by default.

The vulnerability provides a direct kernel read/write primitive. The attacker calls DeviceIoControl with IOCTL code 0x22A018, supplying a crafted input buffer whose pointer fields are set to attacker-chosen kernel addresses. When the handler dereferences these controlled pointers during the smart-hash computation, the kernel reads from or writes to arbitrary kernel memory on behalf of the attacker. The exploitation chain proceeds as follows: the attacker sends the IOCTL with crafted buffers, the kernel dereferences the controlled pointers granting arbitrary read/write, the attacker uses this primitive to locate and overwrite kernel callback structures or token fields, and finally gains full kernel code execution. With kernel-level control established, Lazarus deployed the FudModule rootkit, which disables security callbacks, hides processes, and tampers with kernel telemetry to evade endpoint detection products.

Patch Analysis

The patch shipped in KB5034765 (build 10.0.22621.3155) and addressed the vulnerability through multiple hardening changes to the IOCTL dispatch logic in appid.sys. The primary fix added access control validation to IOCTL 0x22A018, verifying that the caller holds sufficient privileges before the handler processes the request. Additionally, input buffer size validation was introduced so that the handler rejects requests whose input buffer is smaller than the expected structure size, preventing the crafted-pointer attack. The IOCTL dispatch switch statement was also updated with a default case that explicitly rejects unrecognized control codes, closing off any other undocumented IOCTLs from being reached.

AutoPiff detects these changes through the ioctl_input_size_validation_added and ioctl_code_default_case_added rules, which fire when binary diffing reveals that the patched build introduced size checks on IOCTL input buffers and added a default rejection path to the IOCTL dispatch, respectively.

Detection

YARA Rule

rule CVE_2024_21338_appid_sys {
    meta:
        description = "Detects vulnerable version of appid.sys (pre-patch)"
        cve = "CVE-2024-21338"
        author = "KernelSight"
        severity = "high"
    strings:
        $mz = { 4D 5A }
        $driver_name = "appid.sys" wide ascii nocase
        $version = "10.0.22621.2506" wide ascii
        $smart_hash = "AipSmartHashImageFile" ascii
        $ioctl_code = { 18 A0 22 00 }  // IOCTL 0x22A018 little-endian
    condition:
        $mz at 0 and $driver_name and $version and ($smart_hash or $ioctl_code)
}

ETW Indicators

Provider Event / Signal Relevance
Microsoft-Windows-AppLocker AppLocker policy evaluation events Monitors AppLocker device interactions; anomalous IOCTL traffic to \Device\AppId from non-AppLocker service processes indicates exploitation
Microsoft-Windows-Security-Auditing Event 4688 — Process creation Detects the initial attacker process and any post-exploitation child processes spawned with SYSTEM or kernel-level privileges
Microsoft-Windows-Security-Auditing Event 4672 — Special privileges assigned Fires when the attacker process acquires elevated privileges after corrupting kernel callback structures or token fields
Microsoft-Windows-Kernel-Audit Kernel callback registration changes Detects tampering with security callback arrays (PsSetCreateProcessNotifyRoutine, ObRegisterCallbacks) used by the FudModule rootkit to blind EDR products
Microsoft-Windows-Kernel-Process Process and thread creation/termination Identifies hidden processes or processes with tampered tokens resulting from FudModule rootkit deployment

Behavioral Indicators

  • A user-mode process (potentially running with admin privileges) opens a handle to \Device\AppId and sends IOCTL 0x22A018 with crafted input buffers containing kernel-mode pointer values, exploiting the missing access control on the smart-hash handler
  • The IOCTL input buffer for 0x22A018 contains pointer fields pointing to kernel virtual addresses rather than valid file paths, repurposing the hash computation logic as an arbitrary kernel R/W primitive
  • Following exploitation, kernel security callback arrays (process creation notify routines, object callbacks, minifilter callbacks) are zeroed or corrupted, indicating FudModule rootkit deployment to disable EDR kernel telemetry
  • The attacker process modifies its own token or the token of a target process by writing directly to kernel memory, transitioning from admin to full kernel-level access without using documented APIs
  • AppLocker service (AppIDSvc) is not running or the attacker process has no relationship to AppLocker policy evaluation, yet it is actively communicating with the AppId device -- a strong anomaly indicator since 0x22A018 is an internal-only IOCTL

References