From e8cae003cecc043d4149d0236e6bfd7564349e8d Mon Sep 17 00:00:00 2001 From: ek0ms savi0r <4+ek0mssavi0r@noreply.git.churchofmalware.org> Date: Sun, 19 Jul 2026 01:25:40 +0000 Subject: [PATCH] Add CVE-2026-50295_pre-release/readme.md --- CVE-2026-50295_pre-release/readme.md | 141 +++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 CVE-2026-50295_pre-release/readme.md diff --git a/CVE-2026-50295_pre-release/readme.md b/CVE-2026-50295_pre-release/readme.md new file mode 100644 index 0000000..1b9c2a2 --- /dev/null +++ b/CVE-2026-50295_pre-release/readme.md @@ -0,0 +1,141 @@ +In the ZtDeviceStartModule() function of ztdns.sys, it calls IoCreateDevice() to create L"\\Device\\ZTDNS" device, and then calls NtSetSecurityObject() to a SecurityDescriptor to this device object. From this, only the members of Administrators, SYSTEM and Dnscache can open it. + +The code snippet and debugging information is as follows. +int ZtDeviceStartModule(void) +{ + ... + DeviceName.Buffer = L"\\Device\\ZTDNS"; + Status = IoCreateDevice(DriverObject, 0, &DeviceName, 0x12u, 0, 0, &DeviceObject); + Status = ObOpenObjectByPointer(DeviceObject, 0x240u, 0i64, 0x2000000u, 0i64, 0, &DeviceHandle); + Status = NtSetSecurityObject(DeviceHandle, 4u, &gDeviceSecurityDescriptor); + ... +} + +1: kd> !object \device\ztdns +Object: ffff850ad52366b0 Type: (ffff850acc6bfe00) Device + ObjectHeader: ffff850ad5236680 (new version) + HandleCount: 0 PointerCount: 4 + + Directory Object: ffffce0f782288f0 Name: ZTDNS +1: kd> !devobj ffff850ad52366b0 +Device object (ffff850ad52366b0) is for: + ZTDNS \Driver\ZTDNS DriverObject ffff850ad49d9b90 +Current Irp 00000000 RefCount 1 Type 00000012 Flags 00000040 +SecurityDescriptor ffffce0f8d816560 DevExt 00000000 DevObjExt ffff850ad5236800 +ExtensionFlags (0000000000) +Characteristics (0000000000) +Device queue is not busy. +1: kd> !sd ffffce0f8d816560 0x1 +->Revision: 0x1 +->Sbz1 : 0x0 +->Control : 0x9004 + SE_DACL_PRESENT + SE_DACL_PROTECTED + SE_SELF_RELATIVE +->Owner : S-1-5-32-544 (Alias: BUILTIN\Administrators) +->Group : S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM) +->Dacl : +->Dacl : ->AclRevision: 0x2 +->Dacl : ->Sbz1 : 0x0 +->Dacl : ->AclSize : 0x5c +->Dacl : ->AceCount : 0x3 +->Dacl : ->Sbz2 : 0x0 +->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE +->Dacl : ->Ace[0]: ->AceFlags: 0x0 +->Dacl : ->Ace[0]: ->AceSize: 0x14 +->Dacl : ->Ace[0]: ->Mask : 0x001f01ff +->Dacl : ->Ace[0]: ->SID: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM) + +->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE +->Dacl : ->Ace[1]: ->AceFlags: 0x0 +->Dacl : ->Ace[1]: ->AceSize: 0x18 +->Dacl : ->Ace[1]: ->Mask : 0x001f01ff +->Dacl : ->Ace[1]: ->SID: S-1-5-32-544 (Alias: BUILTIN\Administrators) + +->Dacl : ->Ace[2]: ->AceType: ACCESS_ALLOWED_ACE_TYPE +->Dacl : ->Ace[2]: ->AceFlags: 0x0 +->Dacl : ->Ace[2]: ->AceSize: 0x28 +->Dacl : ->Ace[2]: ->Mask : 0x0012019f +->Dacl : ->Ace[2]: ->SID: S-1-5-80-859482183-879914841-863379149-1145462774-2388618682 (Well Known Group: NT SERVICE\Dnscache) + +->Sacl : is NULL + + + +But it does not specify FILE_DEVICE_SECURE_OPEN characteristic for the parameter DeviceCharacteristics of IoCreateDevice(). So unprivileged users can still use L"\\Device\\ZTDNS\\" or L"\\Device\\ZTDNS\\xxx" to open this device. + + + + +Then sending Ioctl code 12800Bh calls ZtSetGlobalPropertiesFastIo() to set global properties: + +struct _ZT_GLOBAL_PROPERTIES +{ + bool fEnableFilters; + bool fPersistFilters; + bool fAuditMode; + bool fAllowMdns; + bool fAllowPlaintextDns; + bool fBlockLocalIps; + bool fAllowIcsDhcpServer; + DWORD dwUnicastLifetime; + DWORD MaxRecordAge; +}; + +BOOLEAN __fastcall ZtSetGlobalPropertiesFastIo( + ... + if ( InputBuffer && InputBufferLength32 == 0x10 && OutputBuffer && OutputBufferLength == 0x10 ) + { + Status = ZtCaptureUserMemory(InputBuffer, 0x10ui64, 4u, PreviousMode, &CapturedProperties); + if ( Status >= 0 ) + { + Status = ZtTryProbeAlignment(OutputBuffer, 0x10ui64, PreviousMode); + if ( Status >= 0 ) + { + if... + g_fEnableFilters = CapturedProperties.fEnableFilters; + g_fPersistFilters = CapturedProperties.fPersistFilters; + g_fAuditMode = CapturedProperties.fAuditMode; + g_fAllowMdns = CapturedProperties.fAllowMdns; + g_fBlockLocalIps = CapturedProperties.fBlockLocalIps; + g_fAllowIcsDhcpServer = CapturedProperties.fAllowIcsDhcpServer; + g_dwUnicastLifetime = CapturedProperties.dwUnicastLifetime; + g_MaxRecordAge = CapturedProperties.MaxRecordAge; + AllowPlaintextDns = 0; + if ( g_fZtdnsSelfhostBranch ) + LOBYTE(AllowPlaintextDns) = CapturedProperties.fAllowPlaintextDns; + *&g_fAllowPlaintextDns = AllowPlaintextDns; + Status = ZtWfpConfigureFilters(CapturedProperties.fEnableFilters, Unused, FilterIds, &FilterIds[1]); + if ( Status >= 0 ) + Status = ZtTryCopyUserMemory(OutputBuffer, FilterIds, PreviousMode); + } + } + } + ... +} + + + + + + + + +For example, setting g_fAuditMode=true can change the mode from Enforcement to Audit, this will permit all outbound connections. + +void __fastcall ZtCalloutConnectClassify( + ... + if ( ZtpAllowConnection(inFixedValues, inMetaValues) || g_fAuditMode ) + { + actionType = 0x1002; // FWP_ACTION_PERMIT + } + else + { + actionType = 0x1001; // FWP_ACTION_BLOCK + Veto = 1; + } + classifyOut->actionType = actionType; + if ( Veto ) + classifyOut->rights &= ~1u; + ... +}