~/posts/binary/k7-named-pipe-registry-client-trust.md

K7 named pipes: registry writes and client trust

Trace a 28-byte settings header through registry writes and process creation, then examine the mismatch between accepted clients and protected processes, with the vendor's final fixed versions.

date[31:24]
read[23:16]
7 min
cat[15:8]
Binary
Contents
  1. 0x00Follow the settings action to the service
  2. 0x01Separate length checks from value restrictions
  3. 0x02Verify replay through backend state
  4. 0x03Connect registry writes to process creation
  5. 0x04Patches expose different trust sets
  6. 0x05Align accepted and protected identities
  7. 0x06Later advisory and remediation
  8. 0x07References

K7 Ultimate Security 17.0.2045 restricted standard users in its settings UI, yet its SYSTEM service accepted registry content submitted by a low-privilege client. Subsequent patches exposed a second boundary problem: the service's trusted-client set did not match the driver's protected-process set.

Three questions matter here: who can reach the pipe, which objects a request may modify, and whether client identity implies runtime integrity. The analysis distinguishes historical behavior from static findings and uses an offline model to check framing. It does not claim a reproduction against current releases.

Follow the settings action to the service

Object Role in the historical evidence
K7 Ultimate Security 17.0.2045 Initial product version
K7TSMain.exe UI process running as a standard user
K7TSMngr.exe SYSTEM service process
K7TSMngrService1 Named pipe associated with the settings operation
K7MailProxyV1 Null-DACL enumeration lead, not the confirmed settings channel

A standard user encountered a restriction dialog, while an administrator could enable settings changes by non-administrators. The useful step was correlating that UI action with pipe traffic, rather than assuming that the most permissive ACL identified the relevant feature. Windows pipe access checks govern connection access; application operations still need their own authorization.

Interface illustration: standard-user restriction and K7 access-control options.

Interface illustration. It explains the two entry points, not the appearance or state of a particular experiment.

The captured settings request contained 213 bytes: a 28-byte header and a 185-byte body. The reply contained 36 bytes. The body included HKLM\Software\K7 Computing\K7TotalSecurity\CommonInfo and three value names:

  • AdminNonAdminIsValid: whether non-administrators may change settings.
  • AdminChangesNeedPassword: whether changes require a password.
  • AdminChangesPasswordHash: a password-related state field.

That resembles a general registry-text transport rather than a dedicated Boolean-setting API. A path in a request does not establish arbitrary registry access, however. The service's resulting writes must be checked.

Separate length checks from value restrictions

This header comes from the variant whose body was shortened by one byte. It consists of seven little-endian DWORDs.

Settings request header, 28 bytes
000000005354374B101000001C00000000000000
0000001044000100B800000000000000
  1. magic0x00–0x03
  2. version0x04–0x07
  3. header_size0x08–0x0B
  4. reserved0x0C–0x0F
  5. command0x10–0x13
  6. body_length0x14–0x17
  7. auxiliary_length0x18–0x1B
Offset Value Interpretation
0x00 0x4b375453 Raw bytes spell ASCII ST7K
0x04 0x1010 Protocol identifier
0x08 0x1c Header length, 28
0x0c 0 Reserved field in this sample
0x10 0x10044 Registry request command in the capture
0x14 0xb8 Body length, 184
0x18 0 Auxiliary length field in this sample

The differential tests separated a possible value-name allowlist from a framing check. Success here means that the new value was observed, not merely that the client received a reply.

Change Value-name bytes Declared body length Historical result
AdminNonAdminIsValid 20 185 Original settings request
Change to aaaaa, retain old length 5 185 Unsuccessful
Same-length AdminNonAdminIsValie 20 185 New value written
Shorten to AdminNonAdminIsVali, update length 19 184 New value written

A successful same-length substitution shows that the service was not limited to the original value name. Success after correcting the shorter body's length explains why an earlier modification failed. This establishes control over the value name; path scope remains a separate question.

A general encoder must update all four bytes at offset 0x14. Editing one byte works only for particular lengths below 256. Count encoded bytes, including the line endings and terminator actually transmitted, rather than characters.

header_check.pypython
import struct

header = bytes.fromhex(
    "53 54 37 4b 10 10 00 00 1c 00 00 00 00 00 00 00 "
    "44 00 01 00 b8 00 00 00 00 00 00 00"
)
fields = struct.unpack("<7I", header)
assert fields == (0x4b375453, 0x1010, 28, 0, 0x10044, 184, 0)

body = b"x" * 300  # Illustrative bytes, not registry syntax.
updated = bytearray(header)
struct.pack_into("<I", updated, 20, len(body))
assert updated[20:24] == b"\x2c\x01\x00\x00"

The offline check passed: the captured header declares 28 header bytes and 184 body bytes; an illustrative length of 300 encodes as 2c 01 00 00. The sample body is filler. This code neither connects to a pipe nor modifies the registry.

Verify replay through backend state

The settings recording first shows the standard-user restriction. After the request receives a 36-byte reply, reopening the page shows that non-administrator settings access is enabled. The reply alone establishes only that data came back. The UI state and backend writes support the authorization consequence.

Process Monitor attributes the writes to SYSTEM and shows HKLM\SOFTWARE\WOW6432Node\K7 Computing\K7TotalSecurity\CommonInfo. That is not the exact spelling in the request: WOW64 registry redirection distinguishes the 32-bit and 64-bit views. Record process bitness and registry view instead of treating these paths as contradictory evidence.

Evidence What it supports What it does not establish
Low-privilege initiating process No administrator UI action is required for this request Every product version accepts it
36-byte reply The service returned data on the connection The registry write succeeded
Registry writes by SYSTEM A privileged service applied the request Every path is writable
New value names and changed settings Client influence over object contents Every subsequent operation escalates privileges

Connect registry writes to process creation

The early-version record extends path control to Image File Execution Options (IFEO), specifically the Debugger configuration for K7TSHlpr.exe. IFEO debugger configuration affects new instances of the target program. When a SYSTEM service starts that helper, registry-controlled data can therefore redirect a privileged launch.

flowchart TD
  A["Low-privilege client"] --> B["Service accepts registry content"]
  B --> C["SYSTEM writes IFEO configuration"]
  C --> D["Service starts helper"]
  D --> E["Debugger setting redirects the launch"]
  E --> F["Privileged child and account-state changes"]

The order of the recorded controls matters. The test account initially does not exist, and direct account creation is denied. Following the pipe operations, the process tree shows a SYSTEM command interpreter beneath K7TSMngr.exe. The final account query lists the new account in the local Administrators group. This is stronger evidence than a success message printed by the script.

The chain depends on three independent conditions: the write primitive reaches the relevant registry location, the target image is actually launched, and that launch has sufficient privilege. Changing a settings toggle and achieving SYSTEM execution are distinct findings.

Patches expose different trust sets

Historical stage Observation Boundary
Initial 17.0.2045 Low-privilege script replay works Incomplete service-side authorization
Client identification added Ordinary PowerShell requests fail; requests from a product process still have a successful recorded path File identity is not runtime integrity
K7Sentry.sys 22.0.0.70 The previous carrier path is blocked, but the K7QuervarCleaningTool.exe path still changes the setting Accepted clients and protected processes differ

The intermediate tests also report different outcomes for ordinary module loading and manual mapping. That makes the client's hosting process relevant; it does not establish that every signed file or mapping technique works. Driver 22.0.0.70 is an intermediate tested version, not the final fixed version named by the vendor.

The service-side static analysis describes ProcessPipeConnection reading a 28-byte header, checking the magic, protocol identifier and header size, and limiting both lengths to 1 MiB. Its client-validation gate has this semantic form:

dispatch_condition.cc
command == 0x1004C || old_windows_condition || ValidatePipeClient(this)

The exception uses 0x1004C, whereas the settings request uses 0x10044. Without command-dispatch analysis and a runtime trace, the settings operation should not be assigned to that exception. This expression is a semantic excerpt from static analysis, not a complete compilable function.

Align accepted and protected identities

ValidatePipeClient obtains the client PID through GetNamedPipeClientProcessId, then uses OpenProcess and QueryFullProcessImageNameA to obtain its image path. The recorded acceptance routes include installation-path matching, a file-digest cache hit, and vendor-signature verification.

The driver's ShouldProtectProcess uses different rules: a name listed in VDefProtectedProcs, or a K7 filename prefix together with the normalized installation-path condition. A path substring is not a strict directory-membership test. A signature on a disk file does not establish the integrity of its process memory.

Let A mean that the service accepts a client, and P that the driver applies the expected protection:

A P Meaning
false false Neither accepted nor protected by this rule
false true Protected, but not accepted by this service
true false Trusted carrier without the corresponding protection
true true The two rules agree for this process

The offline model enumerates all four combinations; only A and not P identifies the gap. This checks design consistency, not a vulnerability in a new release. A candidate process still needs runtime conditions such as controllable request logic and service acceptance of the operation.

Later advisory and remediation

The vendor's 2025-12-22 advisory identifies CVE-2025-67826, confirms the local named-pipe issue in 17.0.2045, and sets the minimum update to K7 Ultimate Security 17.0.2057 with K7Sentry.sys 22.0.0.74 or later. This advisory postdates the original publication; it is a later update, not a fix state validated by the earlier experiments.

The service should separate connection access, product-file identity, and permission to modify a particular setting. Configuration APIs should constrain keys, values, types and permitted state transitions. If client trust depends on process protection, maintain the accepted and protected sets together and stop sensitive operations when identity or integrity checks fail.

The lesson is the verification order, not the pipe's particular name: establish valid framing, establish the object mutation, then establish the privileged effect. Evidence at one layer does not prove the next.

References

NORMAL~/posts/binary/k7-named-pipe-registry-client-trust.md§--
0%en