afd.sys — Out-of-bounds read/write via feature-gated length clamp in AfdRestartSuperAcceptGetAddress (CWE-787) fixed
KB5073722
1. Overview
| Field | Value |
|---|---|
| Unpatched binary | afd_unpatched.sys |
| Patched binary | afd_patched.sys |
| Overall similarity | 0.992 |
| Matched functions | 1073 |
| Changed functions | 6 |
| Identical functions | 1067 |
| Unmatched (either direction) | 0 / 0 |
Verdict: The patch makes an existing length clamp in AfdRestartSuperAcceptGetAddress unconditional. In the unpatched build that clamp is only executed when a servicing feature flag is enabled, so on the flag-off path a kernel-mode memmove runs with a length taken from a 16-bit AddressLength field with no bound (HIGH — out-of-bounds read/write, CWE-787 / CWE-125). The patch also removes a conditional that passed AccessMode = KernelMode to ObOpenObjectByPointer in AfdQueryHandles and AfdTdiCreateAO, so the ACCESS_SYSTEM_SECURITY open of the caller's own transport file objects now honours the caller's processor mode (MEDIUM — missing privilege check, CWE-862). Finally it adds a device-stack match check in AfdCreateConnection before issuing a device control on a caller-supplied handle (MEDIUM — improper validation, CWE-20).
The remaining two changed functions are servicing feature-flag teardown with no security-relevant logic delta.
Addresses in this report are the real virtual addresses shown in the disassembly (image base 0x1C0000000). AfdRestartSuperAcceptGetAddress relocated from 0x1C00641C0 (unpatched) to 0x1C00641D0 (patched); other cited functions are matched by content.
2. Vulnerability Summary
2.1 HIGH — OOB Read/Write in AfdRestartSuperAcceptGetAddress
- Severity: High
- Class: Out-of-bounds write / out-of-bounds read via unclamped
memmovelength (CWE-787 / CWE-125) - Affected function:
AfdRestartSuperAcceptGetAddress(unpatched0x1C00641C0, patched0x1C00641D0)
Root cause. On completion of a SuperAccept (accept-with-address) operation, AfdRestartSuperAcceptGetAddress maps the buffer that the transport filled with a TRANSPORT_ADDRESS/TA_ADDRESS and compacts it in place. It computes a copy length as size = *(word)(buffer + 8) + 2 — the 16-bit AddressLength field plus 2 — and then calls memmove(buffer, buffer + 0xa, size).
In the unpatched build the clamp that would constrain size to MDL->ByteCount - offset is executed only when EvaluateCurrentState(&g_Feature_4201696571_57655968) returns non-zero. When that feature flag is off, the jz at 0x1C00642DE jumps straight to the memmove at 0x1C0064304, so the copy runs with size bounded only by the 16-bit field (up to 0x10001). Because destination buffer and source buffer + 0xa both point inside the mapped completion buffer, a size larger than the mapped region reads past the source and writes past the destination in kernel context.
The patch makes a bound unconditional. A new flag g_Feature_499346745_59190809 selects between two clamps, and both branches clamp:
- flag on (the default-carrying path): size is clamped to IoStatus.Information - 0xa, i.e. the number of bytes the transport actually reported returning;
- flag off: size is clamped to the legacy MDL->ByteCount - offset formula.
No path now reaches the memmove without a clamp.
Scope note. The AddressLength value originates from the buffer the transport writes on accept completion, read back through MDL->MappedSystemVa. The tightened patched clamp (to IoStatus.Information - 0xa) indicates the concern is an AddressLength field that claims more than the transport actually wrote. A concrete attacker-controlled oversized value could not be demonstrated from the two binaries alone; the demonstrable fact is that the kernel-mode memmove length was unbounded on the flag-off path and is bounded in every path after the patch.
Entry point and data flow (as reachable in the binary):
- User-mode
NtDeviceIoControlFileon the AFD endpoint with the SuperAccept IOCTL. AfdDispatch→AfdDispatchDeviceControl(IRP_MJ_DEVICE_CONTROL) →AfdSuperAccept; the IRP is pended on the transport.- The transport completes the accept asynchronously; AFD's restart path runs
AfdContinueSuperAccept, which reachesAfdRestartSuperAcceptGetAddress. - Inside that function the
memmoveat0x1C0064304(unpatched) runs with the computedsize.
2.2 MEDIUM — KernelMode ObOpenObjectByPointer in AfdQueryHandles
- Severity: Medium
- Class: Missing privilege/authorization check (CWE-862), via
ObOpenObjectByPointerwithAccessMode = KernelMode - Affected function:
AfdQueryHandles(0x1C0031B70in both builds)
Root cause. AfdQueryHandles opens handles to the endpoint's address-object file object (endpoint + 0x18) and, when connected, the connection object's file object, each with DesiredAccess = 0x02000000 (ACCESS_SYSTEM_SECURITY). In the unpatched build the AccessMode argument is chosen conditionally: when EvaluateCurrentState(&g_Feature_3932725563_57984164) returns FALSE and the endpoint flag 0x10000 is clear (*(endpoint + 0x10) & 0x10000 == 0), AccessMode is set to 0 (KernelMode). A KernelMode open skips the ACCESS_SYSTEM_SECURITY privilege check (SeSecurityPrivilege) and the security-descriptor check. Both ObOpenObjectByPointer sites in the routine follow the same pattern.
The effect is that a caller without SeSecurityPrivilege can obtain a handle carrying ACCESS_SYSTEM_SECURITY to the transport file objects underlying its own socket. The patch removes the conditional and always passes the caller's processor mode (the value in sil, the routine's arg3) to ObOpenObjectByPointer.
2.3 MEDIUM — KernelMode ObOpenObjectByPointer in AfdTdiCreateAO
- Severity: Medium
- Class: Missing privilege/authorization check (CWE-862)
- Affected function:
AfdTdiCreateAO(unpatched0x1C0039D88, patched0x1C0039CF8)
Same pattern as §2.2, in the address-object creation (bind) path. When EvaluateCurrentState(&g_Feature_3932725563_57984164) is FALSE and endpoint flag 0x10000 is clear, AccessMode is forced to 0 (KernelMode) for the ObOpenObjectByPointer open of the transport file object, again with DesiredAccess = 0x02000000. The patch removes the conditional and always passes the caller's processor mode.
2.4 MEDIUM — Missing handle/device validation in AfdCreateConnection
- Severity: Medium (hardening)
- Class: Improper input validation of a caller-supplied handle's device stack (CWE-20)
- Affected function:
AfdCreateConnection(0x1C0047F50in both builds)
Root cause. The unpatched AfdCreateConnection issues AfdIssueDeviceControl on a caller-supplied handle's file object without confirming that the file object sits on the same device stack as the connection's transport device. The patch adds an IoGetDeviceAttachmentBaseRef comparison: it takes the base attachment device of the connection's device object (connection + 0x18) and of the file object's related device object, and returns STATUS_INVALID_PARAMETER (0xC000000D) if they differ, before calling AfdIssueDeviceControl.
3. Pseudocode Diff
3.1 AfdRestartSuperAcceptGetAddress — OOB length clamp
// ===== UNPATCHED (0x1C00641C0) =====
// buffer = MappedSystemVa(MDL) + offset
size = *(uint16_t*)(buffer + 8) + 2; // 0x642CF / 0x642D3
if (EvaluateCurrentState(&g_Feature_4201696571_57655968)) { // 0x642D7 — flag-gated
if (Mdl->ByteCount - offset < size)
size = Mdl->ByteCount - offset; // clamp (only on flag-on path)
}
// flag off (0x642DE jz): reach memmove with size unclamped
memmove(buffer, buffer + 0xa, size); // 0x64304
*(uint16_t*)(buffer + size - 2) = size; // 0x64309
// ===== PATCHED (0x1C00641D0) =====
size = *(uint16_t*)(buffer + 8) + 2;
if (EvaluateCurrentState(&g_Feature_499346745_59190809)) { // 0x642DF — new flag
uint16_t max = (IoStatus.Information >= 0xa)
? (IoStatus.Information - 0xa) : 0;
if (max < size) size = max; // clamp to actual returned length
} else {
if (Mdl->ByteCount - offset < size)
size = Mdl->ByteCount - offset; // legacy clamp
}
memmove(buffer, buffer + 0xa, size); // 0x6432C — clamped in every path
*(uint16_t*)(buffer + size - 2) = size; // 0x64331
3.2 AfdQueryHandles / AfdTdiCreateAO — AccessMode
// ===== UNPATCHED =====
accessMode = callerMode; // arg3 (sil) / stack AccessMode
if (!EvaluateCurrentState(&g_Feature_3932725563_57984164) // default path
&& !(endpoint->Flags & 0x10000)) {
accessMode = 0; // KernelMode — skips ACCESS_SYSTEM_SECURITY check
}
ObOpenObjectByPointer(fileObject, 0x40, NULL, 0x2000000,
*IoFileObjectType, accessMode, &handle);
// ===== PATCHED =====
ObOpenObjectByPointer(fileObject, 0x40, NULL, 0x2000000,
*IoFileObjectType, callerMode, &handle);
3.3 AfdCreateConnection — device-stack match
// ===== UNPATCHED =====
AfdIssueDeviceControl(connection, fileObject, ...); // no device check
// ===== PATCHED =====
base = IoGetDeviceAttachmentBaseRef(connection->DeviceObject); // 0x48267
hbase = IoGetDeviceAttachmentBaseRef(IoGetRelatedDeviceObject(fileObject)); // 0x4827C
if (base != hbase) { // 0x48285
ObDereferenceObject(hbase); ObDereferenceObject(base); ObDereferenceObject(fileObject);
return STATUS_INVALID_PARAMETER; // 0xC000000D @ 0x482B7
}
ObDereferenceObject(hbase); ObDereferenceObject(base); ObDereferenceObject(fileObject);
AfdIssueDeviceControl(connection, fileObject, ...); // 0x482F5
4. Assembly Analysis
4.1 AfdRestartSuperAcceptGetAddress — Unpatched flag-gated clamp (0x1C00641C0)
00000001C00642BE mov ebp, [rsi+8] ; buffer offset
00000001C00642C1 lea rcx, g_Feature_4201696571_57655968_FeatureDescriptorDetails
00000001C00642C8 mov r15d, [rsi+18h] ; IoStatus.Information
00000001C00642CC add rbp, rax ; rbp = MappedSystemVa + offset
00000001C00642CF movzx edi, word ptr [rbp+8] ; AddressLength
00000001C00642D3 add di, 2 ; size = AddressLength + 2
00000001C00642D7 call EvaluateCurrentState
00000001C00642DC test eax, eax
00000001C00642DE jz short loc_1C00642F9 ; flag off -> skip clamp
00000001C00642E0 mov rdx, [rbx+8] ; MDL
00000001C00642E4 movzx eax, di
00000001C00642E7 mov ecx, [rdx+28h] ; MDL->ByteCount
00000001C00642EA sub ecx, [rsi+8] ; ByteCount - offset
00000001C00642ED cmp ecx, eax
00000001C00642EF jnb short loc_1C00642F9
00000001C00642F1 movzx edi, word ptr [rdx+28h] ; clamp
00000001C00642F5 sub di, [rsi+8]
00000001C00642F9 movzx r8d, di ; Size
00000001C00642FD lea rdx, [rbp+0Ah] ; Src
00000001C0064301 mov rcx, rbp ; Dst
00000001C0064304 call memmove ; unbounded size on flag-off path
00000001C0064309 mov [r15+rbp-2], di
0x1C00642DE— thejzthat skips the clamp entirely whenEvaluateCurrentStatereturns 0.0x1C0064304— the copy that runs withsize = AddressLength + 2, unconstrained on the flag-off path (out-of-bounds write torbp, out-of-bounds read fromrbp + 0xa).
4.2 AfdRestartSuperAcceptGetAddress — Patched, clamp in both branches (0x1C00641D0)
00000001C00642C6 mov ebp, [rsi+8]
00000001C00642C9 lea rcx, g_Feature_499346745_59190809_FeatureDescriptorDetails
00000001C00642D0 mov r15d, [rsi+18h] ; IoStatus.Information
00000001C00642D4 add rbp, rax
00000001C00642D7 movzx ebx, word ptr [rbp+8] ; AddressLength
00000001C00642DB add bx, 2 ; size = AddressLength + 2
00000001C00642DF call EvaluateCurrentState
00000001C00642E4 test eax, eax
00000001C00642E6 jz short loc_1C0064308 ; new flag off -> legacy MDL clamp
00000001C00642E8 movzx eax, word ptr [rsi+18h] ; IoStatus.Information
00000001C00642EC cmp ax, 0Ah
00000001C00642F0 jb short loc_1C00642FC ; if < 0xa, max = 0
00000001C00642F2 mov ecx, 0FFF6h ; -0xa
00000001C00642F7 add ax, cx ; ax = Information - 0xa
00000001C00642FA jmp short loc_1C00642FE
00000001C00642FC xor eax, eax
00000001C00642FE cmp ax, bx
00000001C0064301 jnb short loc_1C0064321 ; if max >= size keep size
00000001C0064303 movzx ebx, ax ; clamp size = Information - 0xa
00000001C0064306 jmp short loc_1C0064321
00000001C0064308 mov rdx, [rdi+8] ; MDL (legacy path)
00000001C006430C movzx eax, bx
00000001C006430F mov ecx, [rdx+28h]
00000001C0064312 sub ecx, [rsi+8]
00000001C0064315 cmp ecx, eax
00000001C0064317 jnb short loc_1C0064321
00000001C0064319 movzx ebx, word ptr [rdx+28h]
00000001C006431D sub bx, [rsi+8]
00000001C0064321 movzx r8d, bx ; Size
00000001C0064325 lea rdx, [rbp+0Ah] ; Src
00000001C0064329 mov rcx, rbp ; Dst
00000001C006432C call memmove ; clamped in every path
00000001C0064331 mov [r15+rbp-2], bx
Every path to the memmove at 0x1C006432C passes through one of the two clamps.
4.3 AfdQueryHandles — Unpatched AccessMode selection (first ObOpenObjectByPointer)
r15d is zeroed in the prologue (0x1C0031B96 xor r15d, r15d) and sil = movzx(arg3) is the caller's processor mode.
00000001C0031CBF lea rcx, g_Feature_3932725563_57984164_FeatureDescriptorDetails
00000001C0031CC6 call EvaluateCurrentState
00000001C0031CCB test eax, eax
00000001C0031CCD jz short loc_1C0031CE0 ; feature off -> below
00000001C0031CD9 mov [rsp+88h+AccessMode], sil ; feature on: caller mode
00000001C0031CDE jmp short loc_1C0031CFE
00000001C0031CE0 test dword ptr [rbx+10h], 10000h
00000001C0031CE7 movsx eax, sil
00000001C0031CEB jnz short loc_1C0031CF0 ; flag set -> caller mode
00000001C0031CED mov eax, r15d ; else AccessMode = 0 (KernelMode)
00000001C0031CFA mov [rsp+88h+AccessMode], al
...
00000001C0031D0D mov r9d, 2000000h ; DesiredAccess = ACCESS_SYSTEM_SECURITY
00000001C0031D1A mov rcx, [rbx+18h] ; Object (address-object file object)
00000001C0031D1E call cs:__imp_ObOpenObjectByPointer
Patched equivalent (0x1C0031B70): the feature-state call and the 0x10000 test are gone, and both open sites use the caller's mode directly:
00000001C0031CBE mov [rsp+88h+AccessMode], sil ; always caller mode
00000001C0031CD2 mov r9d, 2000000h
00000001C0031CDF call cs:__imp_ObOpenObjectByPointer
(AccessMode is the sixth ObOpenObjectByPointer argument, passed on the stack; r9d here is DesiredAccess.)
4.4 AfdTdiCreateAO — Unpatched AccessMode selection
edi is 0 on this path and r12d = 0x2000000 (0x1C003A4C5 mov r12d, 2000000h).
00000001C003A5A7 lea rcx, g_Feature_3932725563_57984164_FeatureDescriptorDetails
00000001C003A5AE call EvaluateCurrentState
00000001C003A5B3 test eax, eax
00000001C003A5B5 jz short loc_1C003A5C0
00000001C003A5B7 mov al, [rsp+4B8h+AccessMode] ; feature on: caller mode
00000001C003A5BE jmp short loc_1C003A5D3
00000001C003A5C0 test dword ptr [rsi+10h], 10000h
00000001C003A5C7 movsx eax, [rsp+4B8h+AccessMode]
00000001C003A5CF jnz short loc_1C003A5D3 ; flag set -> caller mode
00000001C003A5D1 mov eax, edi ; else AccessMode = 0 (KernelMode)
00000001C003A5D8 mov byte ptr [rsp+4B8h+EcpContext], al ; AccessMode
...
00000001C003A5EB mov r9d, r12d ; DesiredAccess = 0x2000000
00000001C003A5F8 call cs:__imp_ObOpenObjectByPointer
Patched (0x1C0039CF8): the feature-state call and 0x10000 test are removed; AccessMode comes straight from the stacked caller mode.
4.5 AfdCreateConnection — Patched device-stack check
00000001C0048263 mov rcx, [rbx+18h] ; connection DeviceObject
00000001C0048267 call cs:__imp_IoGetDeviceAttachmentBaseRef
00000001C004826D mov rcx, rdi ; caller-supplied FileObject
00000001C0048270 mov rsi, rax
00000001C0048273 call cs:__imp_IoGetRelatedDeviceObject
00000001C004827C call cs:__imp_IoGetDeviceAttachmentBaseRef
00000001C0048285 cmp rsi, rax ; base(connection) vs base(handle)
00000001C0048288 jz short loc_1C00482C1 ; match -> proceed
...
00000001C00482B7 mov eax, 0C000000Dh ; STATUS_INVALID_PARAMETER
...
00000001C00482F5 call AfdIssueDeviceControl ; only reached on match
The unpatched AfdCreateConnection contains no IoGetDeviceAttachmentBaseRef call and reaches AfdIssueDeviceControl without this comparison.
5. Trigger Conditions (SuperAccept OOB)
The reachable path to AfdRestartSuperAcceptGetAddress, as present in the binary:
- From user mode, create a listening TCP socket (
socket/bind/listen) over the AFD endpoint. - Issue the SuperAccept operation via
NtDeviceIoControlFileon the AFD endpoint, supplying the accept output buffer that receives the peer address. - A peer connects; the transport completes the accept IRP.
- AFD's restart path runs
AfdContinueSuperAccept→AfdRestartSuperAcceptGetAddress, which maps the completion buffer, computessize = AddressLength + 2, and (on the unpatched flag-off path) callsmemmove(buffer, buffer + 0xa, size)without clampingsize.
The out-of-bounds condition requires the AddressLength field in the mapped completion buffer to exceed MDL->ByteCount - offset. The AddressLength value is read from the transport-filled buffer via the MDL mapping. A demonstrable attacker-controlled route to an oversized value could not be established from the two binaries alone; the verified fact is the absence of any length bound on the flag-off path in the unpatched build.
6. Impact Assessment
The change in AfdRestartSuperAcceptGetAddress is a length-bounding fix on a kernel-mode memmove. On the unpatched flag-off path the copy length is bounded only by the 16-bit AddressLength field (maximum 0x10001), so a value larger than the mapped buffer produces an out-of-bounds write to the destination and an out-of-bounds read from the source, both in kernel context. That is the primitive established by the binaries: an unbounded intra-kernel copy length.
No exploit primitive beyond that (pool grooming, adjacent-object corruption, arbitrary read/write, token replacement, or mitigation bypass) is demonstrable from the two binaries, and none is claimed here. Severity is assessed as HIGH on the basis of a kernel-mode out-of-bounds read/write whose bound was skippable in the unpatched default path and is unconditional after the patch.
The AfdQueryHandles / AfdTdiCreateAO changes remove a KernelMode open of the caller's own transport file objects with ACCESS_SYSTEM_SECURITY; the impact is that the SeSecurityPrivilege and security-descriptor checks were skipped for those opens. The AfdCreateConnection change adds validation that a caller-supplied handle belongs to the connection's device stack before a device control is issued through it.
7. Verification Aids
7.1 AfdRestartSuperAcceptGetAddress
Real addresses to observe (unpatched image base 0x1C0000000):
| Address | Instruction | Purpose |
|---|---|---|
0x1C00641C0 |
function entry | inspect the IRP (rdx) and completion context (rsi = [rdx+0xB8]) |
0x1C00642CF |
movzx edi, word [rbp+8] |
the AddressLength read; rbp = MappedSystemVa + offset |
0x1C00642DE |
jz 0x1C00642F9 |
branch that skips the clamp when the feature flag is off |
0x1C0064304 |
call memmove |
the copy; r8d = size, rcx = dst = rbp, rdx = src = rbp+0xa |
Relevant MDL field: MDL+0x28 = ByteCount (the value the disabled clamp would have used). Compare size at 0x1C0064304 against ByteCount - offset to observe whether the copy exceeds the mapped buffer.
7.2 AfdQueryHandles / AfdTdiCreateAO
AfdQueryHandles0x1C0031B70; feature-state call at0x1C0031CC6;KernelModeassignment at0x1C0031CED(mov eax, r15d,r15d = 0);ObOpenObjectByPointerat0x1C0031D1Eand0x1C0031DEA. Inspect the stackedAccessModeargument (sixth parameter) at the call:0on the vulnerable path, caller mode after the patch.AfdTdiCreateAO0x1C0039D88(unpatched); feature-state call at0x1C003A5AE;KernelModeassignment at0x1C003A5D1(mov eax, edi,edi = 0);ObOpenObjectByPointerat0x1C003A5F8.DesiredAccessis0x02000000(ACCESS_SYSTEM_SECURITY) at both sites.
7.3 AfdCreateConnection
- Patched device check at
0x1C0048263–0x1C0048288; mismatch returnsSTATUS_INVALID_PARAMETERat0x1C00482B7;AfdIssueDeviceControlat0x1C00482F5. Set a breakpoint onnt!IoGetDeviceAttachmentBaseRefto observe the two base-device queries in the patched build; they are absent in the unpatched routine.
8. Changed Functions — Full Triage
Security-relevant
AfdRestartSuperAcceptGetAddress— similarity0.9295. HIGH. Flag-gated length clamp made unconditional (and tightened toIoStatus.Information - 0xa); see §2.1.AfdQueryHandles— similarity0.9012. MEDIUM. Removes conditionalAccessMode = KernelModefor twoObOpenObjectByPointeropens; see §2.2.AfdTdiCreateAO— similarity0.9723. MEDIUM. Same AccessMode pattern in the address-object creation path; see §2.3.AfdCreateConnection— similarity0.8395. MEDIUM (hardening). AddsIoGetDeviceAttachmentBaseRefdevice-stack match beforeAfdIssueDeviceControl; see §2.4.
Servicing feature-flag teardown (no security-relevant logic delta)
AfdExtractAfdSendMsgInfo— similarity0.966. The unpatched build gates a size/source validation behindg_Feature_Servicing_AudioVideoStutteringIssue_58996271(when the flag is on, the check is skipped). The patched build removes the flag and instead validates unconditionally: it acquires the queued spinlock and requiresSize == *(endpoint + 0x94), returningSTATUS_INVALID_PARAMETER(0xC000000D) on mismatch before thememmoveat0x1C000B3CF. The subsequentmemmovesites and theirAfdUserProbeAddressprobes are unchanged. This is an always-on validation, not a removed one; no security regression.r15is reallocated tor14.AfdSuperAccept— similarity0.9796. Removes theEvaluateCurrentState(&g_Feature_1487976763_57832072)gate; theSTATUS_BUFFER_TOO_SMALL(0xC0000023) reject path itself remains in the patched build. Register and stack layout changes only. No security impact.
9. Unmatched Functions
None. Both removed and added are empty — every change is inside an existing function; no helper or sanitiser was introduced or removed at function granularity.
10. Confidence & Caveats
- The
AfdRestartSuperAcceptGetAddresschange is verified directly against both builds: the unpatched clamp is behindjz 0x1C00642F9at0x1C00642DE, gated onEvaluateCurrentState(&g_Feature_4201696571_57655968); the patched build clamps in both branches ofg_Feature_499346745_59190809and reaches thememmoveat0x1C006432Conly after a clamp. Whether an attacker can driveAddressLengthpast the buffer bound is not established from the binaries; the severity reflects a kernel-mode out-of-bounds copy whose bound was skippable by default. - The
AfdQueryHandles/AfdTdiCreateAOfindings are verified: theKernelMode(0) assignment is present on the feature-off, flag-clear path in the unpatched build (0x1C0031CED,0x1C003A5D1) and removed in the patched build.DesiredAccessis0x02000000(ACCESS_SYSTEM_SECURITY) at all sites; the affected objects are the caller's own socket's transport file objects. - The
AfdCreateConnectionfinding is a hardening fix: the patched build adds theIoGetDeviceAttachmentBaseRefdevice-stack comparison (0x1C0048263–0x1C0048288); the unpatched routine has no such check. - Default state of the named servicing feature flags is configuration-dependent and cannot be read from the binaries. The findings are stated in terms of the code path that runs when each flag is off.