Pipe Attribute Primitives
Named pipe extended attributes used as arbitrary read/write primitives through controlled kernel pool allocations with attacker-specified size and content.
Description
Named pipe extended attributes are key-value pairs managed by the Named Pipe File System driver (npfs.sys) through the NtFsControlFile API. When an attribute is set with FSCTL_PIPE_SET_ATTRIBUTE, the kernel allocates a pool buffer to store the attribute name and value data. When an attribute is read with FSCTL_PIPE_GET_ATTRIBUTE, the kernel copies the stored data back to user mode. By corrupting an attribute entry's value pointer or length field, an attacker gains controlled read-back from arbitrary kernel addresses.
Pipe attributes are allocated in PagedPool with a total size of approximately sizeof(header) + name_length + value_length, giving fine-grained control over which pool bucket the allocation lands in. The attribute value content is fully attacker-controlled, making pipe attributes an effective spray primitive. Multiple attributes can be set on a single pipe handle, each producing a separate pool allocation, and individual attributes can be deleted to create precise holes in the pool layout.
The pipe attribute technique is widely used in modern Windows kernel exploits as both a spray primitive for pool grooming and as a read-back primitive for information leaks. It complements the named pipe data queue entry technique, which operates in NonPagedPoolNx, by providing similar capabilities for PagedPool targets. Together, pipe data queue entries and pipe attributes give an attacker spray coverage across both major pool types.
Key Structures
NP_ATTRIBUTE_ENTRY (approximate layout from npfs.sys)
+0x000 Flink / Blink // LIST_ENTRY linking to next/previous attribute
+0x010 AttributeNameLength // length of attribute name in bytes
+0x018 AttributeName // inline UNICODE_STRING or pointer to name
+0x020 AttributeValue // pointer to value data (or inline)
+0x028 ValueLength // length of attribute value in bytes
... (inline name and value data follow the header)
The exact internal layout varies between Windows versions. The important fields for exploitation are:
ValueLength-- controls how many bytes the kernel copies onFSCTL_PIPE_GET_ATTRIBUTE. Corrupting this field to a larger value produces an out-of-bounds read.AttributeValue-- if this is a pointer (rather than inline data), corrupting it to a kernel address makesFSCTL_PIPE_GET_ATTRIBUTEread from that arbitrary address.LIST_ENTRY-- the linked list pointers connecting attributes. Corrupting these causes a BSOD during pipe cleanup, so exploits must avoid modifying them.
Mechanism
Setting and Reading Attributes
- Create named pipe pair -- call
CreateNamedPipefor the server end andCreateFilefor the client end - Set attribute -- call
NtFsControlFilewithFSCTL_PIPE_SET_ATTRIBUTE(control code0x110038), providing an attribute name string and a value buffer of the desired size - Kernel allocates attribute entry --
npfs.sysallocates a PagedPool buffer containing the header, name, and value data - Get attribute -- call
NtFsControlFilewithFSCTL_PIPE_GET_ATTRIBUTE(control code0x11003C), providing the attribute name; the kernel locates the matching entry and copiesValueLengthbytes to the user-mode output buffer - Delete attribute -- call
NtFsControlFilewithFSCTL_PIPE_DELETE_ATTRIBUTEto free the pool allocation (useful for hole-poking)
As an Arbitrary Read Primitive
- Spray pipe attributes of target size to fill the target pool bucket, creating a dense layout adjacent to the vulnerable allocation
- Trigger vulnerability -- a pool overflow or UAF corrupts an adjacent attribute entry
- Corrupt
ValueLength-- the overflow extends theValueLengthfield to a value larger than the actual allocation (e.g., change 0x100 to 0x1000) - Call
FSCTL_PIPE_GET_ATTRIBUTE-- the kernel readsValueLengthbytes starting from the attribute value data, extending past the allocation boundary - Receive leaked data -- the excess bytes come from adjacent pool memory and may contain kernel pointers, pool metadata, or object headers useful for KASLR bypass
Alternatively, if the corruption can overwrite the AttributeValue pointer directly:
- Set
AttributeValueto an arbitrary kernel address - Call
FSCTL_PIPE_GET_ATTRIBUTE-- the kernel readsValueLengthbytes from the specified kernel address - Receive data from the target kernel address in the user-mode output buffer
As an Arbitrary Write Primitive
- Corrupt attribute entry -- extend the
ValueLengthor modify theAttributeValuepointer - Call
FSCTL_PIPE_SET_ATTRIBUTEwith updated value data -- the kernel writes the attacker-controlled data to the (corrupted) buffer region - Targeted overwrite -- the written data extends past the original allocation or targets an arbitrary kernel address, overwriting adjacent object fields
As a Spray Primitive
- Create a large number of named pipes (e.g., 10,000)
- Set attributes on each pipe with value buffers sized to target a specific pool bucket
- Attribute data is fully controlled -- plant marker bytes, fake pointers, or fake structure fields
- Selectively delete attributes on specific pipes to create holes at known positions
- Trigger the vulnerable allocation to land in a prepared hole
Practical Considerations
- Pool type: Pipe attribute allocations are made from PagedPool. This makes them suitable for grooming vulnerabilities in PagedPool but not for NonPagedPoolNx targets (use named pipe data queue entries for NonPagedPoolNx).
- Attribute name contributes to allocation size: The name string is stored inline in the allocation. Exploits typically use short, fixed-length names (e.g.,
"A") and vary the value size for precise bucket targeting. - Multiple attributes per pipe: A single pipe can hold multiple attributes, each in a separate pool allocation. This allows creating allocations of different sizes from a single pipe handle.
- LIST_ENTRY corruption is fatal: The attribute linked list pointers are walked during pipe cleanup. If
FlinkorBlinkis corrupted, the kernel follows an invalid pointer and causes a BSOD. Robust exploits either avoid corrupting the list entry fields or restore them before closing the pipe. - Segment heap considerations: On Windows 11 with segment heap, pipe attribute allocations may be isolated by pool tag from other allocation types, limiting cross-object spray effectiveness. Tag-matched spray (finding objects with the same pool tag as the target) can bypass this.
- Combined with DATA_QUEUE_ENTRY: Many exploits use pipe attributes for PagedPool spray and
DATA_QUEUE_ENTRYfor NonPagedPoolNx spray in the same exploit chain, covering both pool types. - Cleanup order matters: Close pipe handles in a controlled order to avoid triggering linked list traversal on corrupted entries. Some exploits intentionally leak handles rather than closing them.
Mitigations and Limitations
- Pool header cookies: Overflows that damage pool chunk headers are detected and cause BSOD. The corruption must target the attribute entry's data fields, not the pool header.
- Segment Heap pool tag isolation (Windows 11): Pipe attribute allocations may be isolated from other pool tag types, reducing cross-object spray effectiveness.
- No integrity check on attribute fields: The kernel does not validate that
ValueLengthorAttributeValuehave not been tampered with before performing the read-back. This is the fundamental weakness that enables the read primitive. - PagedPool only: Pipe attributes cannot be used to groom NonPagedPoolNx targets. Exploits targeting NonPagedPoolNx drivers must use alternative spray objects.
- KASLR: Leaked pointers must be interpreted relative to the randomized kernel base. The pipe attribute read primitive is often used specifically to defeat KASLR by disclosing kernel pointers from adjacent allocations.
Related CVEs
| CVE | Driver | Role |
|---|---|---|
| CVE-2024-30085 | cldflt.sys |
Pipe attribute spray and read primitive for pool overflow exploitation |
| CVE-2023-28252 | clfs.sys |
Pipe attribute spray for CLFS pool grooming |
| CVE-2024-26229 | csc.sys |
Pipe attribute R/W primitive in exploit chain |
| CVE-2023-36036 | cldflt.sys |
Pipe attribute spray for pool overflow |
| CVE-2024-38193 | afd.sys |
Combined pipe attribute and data queue spray |
See Also
- Named Pipe Objects --
DATA_QUEUE_ENTRYspray for NonPagedPoolNx targets - Pool Spray / Heap Feng Shui -- general pool spray theory and object selection criteria
- Pool Overflow -- the vulnerability class that pipe attribute spray most commonly grooms
- I/O Ring -- commonly chained after pipe attribute info leak for full kernel R/W
- Token Manipulation -- downstream privilege escalation after achieving R/W via pipe attributes