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
AipSmartHashImageFileCTuneupMgr::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_addedioctl_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\AppIdand sends IOCTL0x22A018with crafted input buffers containing kernel-mode pointer values, exploiting the missing access control on the smart-hash handler - The IOCTL input buffer for
0x22A018contains 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
0x22A018is an internal-only IOCTL