SECTION

The SECTION structure (formally _SECTION) is the kernel’s representation of a section object. Both kernel-mode and user-mode software may obtain a handle to a section object. Kernel-mode software may reference the handle to obtain the address of the object. If the ObReferenceObjectByHandle function successfully resolves a handle though directed to do so only if the object type is MmSectionObjectType, then the pointer that the function produces for the object is a pointer to a SECTION.

Documentation Status

The SECTION structure is not documented. Microsoft is not known to have disclosed even its name for—let alone any internal details of—whatever kernel-mode structure supports a handle to a section object. For the handful of exported functions, e.g., MmMapViewInSystemSpace and MmMapViewInSessionSpace, that take a pointer to a section object as an argument and for which Microsoft has published C-language declarations in headers from a Windows Driver Kit (WDK), the argument’s type is simply PVOID. Even the referencing of the object from a handle is obscure: though the MmSectionObjectType variable is a kernel export as far back as version 3.51, it never has been declared in any WDK header except an NTOSP.H that Microsoft disclosed in early editions of the WDK for Windows 10 (apparently only by oversight).

The structure of a section object is obscure even in the public symbol files. Before the original Windows 10, these show type information for a SECTION_OBJECT but not for the SECTION.

Layout

The SECTION is 0x28 and 0x40 bytes in 32-bit and 64-bit Windows, respectively, in all known versions. Sizes, types and Microsoft’s names of members are from public symbol files for the Windows 10 kernel. What is shown below for earlier versions is, of course, something of a guess.

Offset (x86) Offset (x64) Definition Versions Remarks
0x00 (3.10 to 5.1)  
PVOID StartingVa;
3.10 to 5.1 next at 0x0C
0x04 (3.10 to 5.1)  
PVOID EndingVa;
3.10 to 5.1 next at 0x10
0x08 (3.10 to 5.1);
0x00 (5.2 to 6.1)
0x00 (late 5.2 to 6.1)
PVOID Parent;
3.10 to 6.1 next in SectionNode at 0x00
0x0C (3.10 to 5.1);
0x04 (5.2 to 6.1)
0x08 (late 5.2 to 6.1)
PVOID LeftChild;
3.10 to 6.1 next in SectionNode at 0x00
0x10 (3.10 to 5.1);
0x08 (5.2 to 6.1)
0x10 (late 5.2 to 6.1)
PVOID RightChild;
3.10 to 6.1 next in SectionNode at 0x00
0x00 0x00
MM_AVL_NODE SectionNode;
6.2 only  
RTL_BALANCED_NODE SectionNode;
6.3 and higher  
0x0C 0x18
PVOID StartingVa;
5.2 to 6.1 previously at 0x00
ULONG_PTR StartingVpn;
6.2 and higher  
0x10 0x20
PVOID EndingVa;
5.2 to 6.1 previously at 0x04
ULONG_PTR EndingVpn;
6.2 and higher  
0x14 0x28
SEGMENT *Segment;
3.10 to 6.3  
union {
    CONTROL_AREA *ControlArea;
    FILE_OBJECT *FileObject;
    struct {
        RemoteImageFileObject : 1;
        RemoteDataFileObject : 1;
    };
} u1;
10.0 and higher  

The original behaviour is consistent with the section object beginning as a SECTION_OBJECT, which is well known from symbol files, but continuing with members that symbol files for Windows 10 confirm are those of the SECTION (see below). The SECTION_OBJECT can usefully be seen as having its members in three sets: two for the virtual addresses of the section’s first and last bytes; three as links for the section object in a tree; a pointer to a SEGMENT. The kernel for Windows Server 2003 swaps the first two but the symbol files for the SECTION_OBJECT show no such reordering. This means that for whatever reason the SECTION_OBJECT survives in symbol files in version 5.2—indeed, all the way to the original Windows 10—it cannot be that the SECTION_OBJECT any longer had anything to do with section objects as actually implemented by the kernel.

In Windows 10, the section object ordinarily keeps a pointer to the control area, which has in its turn a FilePointer for access to the file. However, if the file’s device object has the FILE_REMOTE_DEVICE characteristic, then the section object instead keeps a pointer to the file object. In this case, one or other of the low two bits in the address is set according to whether the section is for an image or for data. The control area is then found through the file object’s SectionObjectPointer.

Offset (x86) Offset (x64) Definition Versions
0x18 0x30
ULONGLONG SizeOfSection;
all
0x20 0x38
union {
    ULONG LongFlags;
    MMSECTION_FLAGS Flags;
} u;
all
0x24 0x3C
ULONG InitialPageProtection;
3.10 to 5.2
struct {
    /*  changing bit fields, see below  */
};
6.0 and higher

The InitialPageProtection comes from the macros (defined in WDM.H and WINNT.H) that start with PAGE_NOACCESS. It will typically be just what was provided as the SectionPageProtection argument when creating the section, but PAGE_NOCACHE and PAGE_WRITECOMBINE bits can have been picked up by implication. The point to retaining it in this form is for validating that the Win32Protect argument that is presented when later mapping a view of the section is compatible with the page protection that was specified for the section.

Windows Vista recognised that with only 12 bits allowed for the InitialPageProtection, a truly new member could be added to the SECTION without changing the size:

Mask Definition Versions
0x00000FFF
ULONG InitialPageProtection : 12;
6.0 and higher
0xFFFFF000 (6.0 to 6.1);
0x7FFFF000
ULONG SessionId : 20;
6.0 to 6.1
ULONG SessionId : 19;
6.2 and higher
0x80000000
ULONG NoValidationNeeded : 1;
6.2 and higher