Windows Security Internals

From Wiki Aghanim
Jump to navigationJump to search

Windows Security Internals – Reference Notes

I'm reading the book Windows Security Internals by James Forshaw. Beside the reading I've also taken phyiscal notes, and then used AI to organize my notes before posting them here. The intended use-case is for qucikly reading up on a subject or a topic. It is not intended to replace the book for in-depth information about a topic/subject.

Chapter 1: The Windows Kernel Executive

Overview

The Windows Kernel Executive (NTOS Kernel) is the core of the Windows operating system. It:

  • Provides all of the operating system's privileged functionality.
  • Provides an interface for user-mode applications to communicate with hardware.
  • Exposes APIs for other subsystems to call.

The kernel is divided into subsystems, each identified by an API prefix. The most important subsystem is the Security Reference Monitor, which handles all access control decisions in the OS.

Conceptual model of Windows ring levels:

  1. Ring 0 – The hardware layer.
  2. The Kernel – Security guards and elevator (permissions and scheduling only).
  3. The first layer – Where actual work happens (user applications, services).

API Prefix to Subsystem Mapping

When you see a Windows API function name, its prefix tells you which kernel subsystem it belongs to.

Prefix Subsystem Example
Nt or Zw System Call Interface NtOpenFile
Se Security Reference Monitor SeImpersonate
Ob Object Manager ObReferenceObject
Ps Process and Thread Manager PsGetCurrentProcess
Cm Configuration Manager CmRegisterCallbackEx
Mm Memory Manager MmMapIoSpace
Io Input/Output Manager IoCreateFile
Ci Code Integrity CiValidateFileObject

Security Reference Monitor (SRM)

The Security Reference Monitor is the most important kernel subsystem. It is responsible for deciding who can access what in the operating system.

How the SRM Works

When a user process tries to access a resource, the SRM performs an access check:

  1. The process presents its access token to the SRM.
  2. The SRM queries the resource's security descriptor.
  3. If the token grants the requested rights, access is granted.

Key facts:

  • Every process on the system is assigned an access token when it is created.
  • The token is managed by the SRM.
  • The token defines the identity of the user associated with the process.
  • The SRM can perform access checks and queries the resource's security descriptor to do so.
  • Users and groups are represented to the SRM by a SID (Security Identifier).

Access Token

An access token is a kernel object assigned to every process at creation time. It defines the user identity and the rights held by that process. The SRM uses this token when performing access checks against a resource's security descriptor.

Security Identifiers (SIDs)

A SID is a binary structure that uniquely represents a user or group. The Local Security Authority Subsystem (LSASS) creates SIDs and provides them to the SRM.

SID String Format (SDDL)

Microsoft defines the Security Descriptor Definition Language (SDDL) format to represent a SID as a human-readable string.

Example: The built-in Users group has the SID S-1-5-32-545.

Part Meaning
S Fixed prefix – identifies this as a SID
1 Version of the SID (always 1)
5 Security Authority (5 = NT Authority)
32 Sub-authority value (part of the RID chain)
545 RID – Relative Identifier (identifies the specific group)

Well-known SIDs (like built-in groups) are always the same across Windows systems.

Take-home: SIDs represent users and groups, and can be represented as strings.

Key Kernel Executive Subsystems

The I/O Manager

The I/O Manager is a kernel subsystem that coordinates how applications and drivers communicate to perform input and output operations (files, devices, networks).

Job: Provide access to I/O devices through device drivers. The purpose of these drivers is to implement a filesystem or device interface.

How to load a driver:

  • Manually: via the NtLoadDriver system call.
  • Automatically: by the Plug and Play (PnP) Manager.

Driver directory in the OMNS: For every driver loaded, the I/O Manager creates an entry in a driver directory inside the Object Manager Namespace. Only administrators can list this directory.

How does a normal user access a driver? They don't interact with the driver directory directly. Instead, they interact through a device object, which is normally created in the \Device OMNS directory.

Example: When a user-mode app opens a file, the request goes through the I/O Manager, which creates an Input/Output Request Packet (IRP) and routes it to the correct driver.

Networking: Windows uses the AFD (Ancillary Function Driver) to provide networking services (TCP/IP, etc.) to applications. There are no built-in system calls for core network protocols – everything goes through AFD. WinSock is the user-mode handle to AFD.

The Process and Thread Manager

The Process and Thread Manager is the kernel component that creates and manages processes and threads.

  • A process is the container – it holds the address space, handle table, and resources.
  • A thread is the actual unit of execution running inside a process.

It handles scheduling, creation, termination, and keeps track of what the CPU should run and when, so the CPU knows what to run at any given moment.

The Memory Manager

The Memory Manager controls the allocation of both physical and virtual memory. It handles paging, swapping, and keeps memory protected between processes so one process cannot read another's memory.

Memory Protection Levels
Protection Level Description
ReadOnly Memory can only be read
ReadWrite Memory can be read and written
ExecuteRead Memory can be executed and read
ExecuteReadWrite Memory can be executed, read, and written
Memory States
State Meaning Safe to use?
Commit Virtual memory is allocated and has backing physical memory Yes
Reserve Address range is reserved but has no backing physical memory. Using it causes a crash. No
Free Virtual memory is unused and unmapped. Using it causes a crash. No
Allocating Virtual Memory

Two ways to allocate virtual memory:

  1. NtAllocateVirtualMemory – direct virtual memory allocation syscall.
  2. Through a Section Object – a kernel object type that implements memory-mapped files.

What is a Section Object? A Section Object is a kernel type that implements memory-mapped files. It allows a file or pagefile-backed region to be mapped into a process's address space.

How to map a section into another process: Specify a process handle to NtMapViewOfSection. This lets you share memory between processes.

Code Integrity

Code Integrity is a kernel subsystem that verifies and restricts what files can execute in the kernel and in user mode, by checking code signatures.

  • Authenticode is the mechanism used to digitally sign executables and drivers.
  • If a file or driver has an invalid signature, the kernel can block the loading of that driver to preserve system integrity.

Advanced Local Procedure Call (ALPC)

ALPC allows transmission of discrete messages between a server and a client on the same machine. It is a kernel-level inter-process communication (IPC) mechanism.

System Call Purpose
NtCreateAlpcPort Creates a server-side ALPC port
NtConnectAlpcPort Connects a client to an existing ALPC port

The Configuration Manager

The Configuration Manager is what most people know as the Windows Registry. It stores persistent configuration information for the OS, device drivers, and applications – similar to how a text editor stores your last cursor position.

Chapter 2: The Object Manager

Overview

In Unix-like systems, everything is a file. In Windows, everything is an object. The Object Manager treats all kernel resources uniformly – files, registry keys, processes, threads, mutexes, and so on.

Every object has three things:

  • A name – its path in the OMNS.
  • A type – what kind of object it is.
  • A security descriptor – who can access it and how.

The Object Manager is the central authority that organises the entire OS into a searchable tree structure.

What does the Object Manager actually do? It translates a handle into a memory address in kernel space.

Object Manager Namespace (OMNS)

Underneath the user interface, Windows has a hidden filesystem for kernel objects. Access to this internal filesystem is through the Object Manager Namespace (OMNS). It is not well-documented.

Think of it like a hidden File Explorer that shows kernel objects instead of regular files.

The OMNS is built out of Directory objects. These act like folders in a filesystem – each directory can contain other objects (which you can think of as files).

A security descriptor on each directory controls:

  • Which users can list its contents.
  • Who can create new objects or subdirectories inside it.

To enumerate the OMNS: Use a PowerShell module such as NtObjectManager.

A Symbolic Link in the OMNS redirects one OMNS path to another. It contains a SymbolicLinkTarget property that holds the target path that the link should resolve to.

Example: Drive letters like C: are symbolic links stored under \GLOBAL?? pointing to the actual device path (e.g., \Device\HarddiskVolume3).

Pre-configured OMNS Directories

Windows pre-configures several important object directories at boot:

Path Description
\BaseNamedObjects Global directory for named user-mode objects (mutexes, events, semaphores, etc.)
\Device Contains device objects such as mounted filesystems and hardware devices
\GLOBAL?? Global directory for symbolic links, including drive letter mappings (e.g., C:)
\KnownDlls Directory containing special, pre-loaded DLL mappings
\ObjectTypes Directory containing all named kernel object types
\Sessions Directory for separate console sessions
\Windows Directory for objects related to the Windows Manager
\RpcControl Directory for Remote Procedure Call (RPC) endpoints

System Calls

A system call lets user-mode code invoke kernel-mode code using the system call interface.

Nt vs Zw Prefix

All system calls start with either the Nt or Zw prefix. When the same code is executed inside the kernel:

  • Zw prefix – changes the security checking process. It signals to the kernel that the caller is trusted (typically another kernel component), and bypasses certain user-mode security checks.
  • Nt prefix – performs the full security check as if the call came from user mode.

After the prefix comes an operation verb that describes what the call does.

Example: In NtCreateMutant, the verb is Create.

Common System Call Operations

Operation Verb Description
Create Creates a new kernel object
Open Opens an existing kernel object
QueryInformation Queries object information and properties
SetInformation Sets object information and properties

Example: NtCreateMutant

From Listing 2-6 in the book. This is a real system call that creates a Mutant (mutex) object.

NTSTATUS NtCreateMutant(
    HANDLE*             MutantHandle,     // (1) Out-pointer: receives the new handle
    ACCESS_MASK         DesiredAccess,    // (2) What operations we want to perform via this handle
    OBJECT_ATTRIBUTES*  ObjectAttributes, // (3) Struct defining the object's attributes (name, etc.)
    BOOLEAN             InitialOwner      // (4) Is the Mutant owned by the caller on creation?
);

Parameter explanations:

  1. MutantHandle – An outbound pointer to a HANDLE. The kernel writes the newly created handle value here.
  2. DesiredAccess – An access mask specifying what operations we want to be able to perform on the Mutant using this handle.
  3. ObjectAttributes – A struct that defines attributes for the object (name, root directory, security descriptor, etc.). See Listing 2-7 in the book.
  4. InitialOwner – Determines whether the newly created Mutant is immediately owned by the calling thread (TRUE) or not (FALSE).

What is a Mutant?

A Mutant is Windows's kernel-internal name for a mutex (mutual exclusion object). It ensures that only one thread can access a shared resource at a time.

NTSTATUS Codes

All system calls return a 32-bit NTSTATUS code. This tells the caller whether the operation succeeded and, if not, why it failed.

NTSTATUS Structure

Field Bits Description
Severity 31–30 Indicates the severity of the status (Success, Info, Warning, Error)
Customer Code (C) 29 Is this code defined by Microsoft (0) or a third party (1)?
Reserved (R) 28 Must always be set to 0
Facility 27–16 The component or subsystem this code belongs to
Status Code 15–0 A 16-bit number unique within the facility

Severity Values

Severity Name Value Meaning
STATUS_SEVERITY_SUCCESS 0 Operation succeeded
STATUS_SEVERITY_INFORMATIONAL 1 Informational, not an error
STATUS_SEVERITY_WARNING 2 Warning – something unexpected but not fatal
STATUS_SEVERITY_ERROR 3 Error – operation failed

Facility Values (selected)

There are approximately 50 defined facilities. The facility identifies which component or subsystem produced the status code.

Facility Name Value Description
FACILITY_DEFAULT 0 Used for common/generic status codes
FACILITY_DEBUGGER 1 Codes associated with the debugger
FACILITY_NTWIN32 7 Codes that originated from the Win32 API layer

The Status Code field (bits 15–0) is a 16-bit number chosen to be unique within its facility.

Object Handles

What is a Handle?

A handle is a number (an ID tag) that a process holds to reference a kernel object it does not have direct memory access to – like a file or a kernel mutex.

  • It is like an ID tag the process holds instead of a real memory address.
  • User-mode applications cannot directly read or write kernel memory, so handles are the abstraction layer.
  • The Object Manager translates a handle into a kernel memory address when the syscall is executed.

Handle Table

Each running process has an associated handle table maintained by the kernel. Every entry in the table contains three pieces of information:

  1. The handle's numeric identifier – the number used in user-mode code.
  2. The granted access mask – what rights (e.g., Read, Write) were granted when this handle was opened.
  3. A pointer to the object structure in kernel memory.

Handle Lookup Process

When a user-mode process passes a handle to a system call, the kernel:

  1. Receives the handle value from the system call.
  2. Calls an internal API (e.g., ObReferenceObjectByHandle) to convert the handle to a kernel pointer by looking up the numeric value in the process's handle table.
  3. Determines whether the access the user requested is permitted.

Why step 3 is crucial: It ensures that a user cannot perform an operation on a handle they don't have rights for.

Example: If a process has a file handle opened with read-only access, attempting to write to it via that handle will be denied – even if the underlying file is writable.

If the lookup and access check succeed, the syscall gets a pointer to the object and performs the requested operation.

Conversion operation = turning a handle value into an actual kernel pointer.

Access Masks

What is an Access Mask?

An access mask is a 32-bit bitfield that specifies which specific operations a user or program is allowed to perform on a file, folder, or kernel object.

  • The granted access stored in each handle table entry is an access mask.
  • When opening or creating a handle, the caller passes a DesiredAccess parameter in the same format.

Access Mask Structure

Region Bits Name Notes
1 (most important) 15–0 Type-Specific Access Operations specific to a particular kernel object type
2 20–16 Standard Access Operations that apply to any kernel object type
3 27–24 Special Access Special flags (system security, maximum allowed)
4 31–28 Generic Access Only used when requesting access; SRM converts to type-specific access

Type-Specific Access (Bits 15–0)

Defines the operations allowed on a particular object type. Each type defines its own bits independently.

Example: A file object has separate bits to specify whether the file can be read or written.

Standard Access Rights (Bits 20–16)

These operations apply to any kernel object type:

Right Description
Delete Removes the object (e.g., deletes the file from disk or key from registry)
ReadControl Reads the security descriptor information for the object
WriteDac Writes the object's Discretionary Access Control (DAC) – modifies who can access it
WriteOwner Writes the owner information to the object
Synchronize Waits on the object; allows a process to block until the object signals (e.g., wait for a process to exit)

Additionally, from the special access region:

Right Description
AccessSystemSecurity Reads or writes audit (SACL) information on the object
MaximumAllowed Requests the maximum access the caller is permitted when performing an access check

Generic Access Rights (Bits 31–28)

Used only when requesting access via a system call's DesiredAccess parameter. The SRM converts these into the corresponding type-specific access rights for the object type being opened.

Generic Right Converts to
GenericRead Type-specific read rights for that object type
GenericWrite Type-specific write rights for that object type
GenericExecute Type-specific execute rights for that object type
GenericAll All type-specific rights for that object type

Permanent Objects

What is a Permanent Object?

A permanent object is an object that the kernel marks to prevent it from being destroyed when all handles to it are closed. The object's name remains in the OMNS even after all handles close.

Contrast with normal objects: A normal object is destroyed automatically once all handles to it are closed.

Note: Files and registry keys cannot be permanent objects in the OMNS – they are not stored in the OMNS and need a system call (like a delete call) to be removed.

API Calls

API Description
NtMakePermanentObject Makes an object permanent. Requires the SeCreatePermanentPrivilege privilege.
NtMakeTemporaryObject Reverse operation – allows the object to be destroyed. All handles must be closed first.

Handle Duplication

What is Handle Duplication?

Handle duplication allows a process to take an additional reference to a kernel object by creating a new handle (in the same or another process) pointing to the same underlying object.

Example: Pass a file handle to a new process. You can grant the duplicated handle only read-only access, even if the original handle had full read-write access.

PowerShell command for handle duplication: Copy-NtObject

Query and Set Information System Calls

The kernel implements a generic Query and Set Information pattern that applies consistently to all kernel objects.

Use case: Query a kernel object about its state. Example: get the creation timestamp for a process.

Purpose System Call Example PowerShell Equivalent
Query object information NtQueryInformationProcess Get-NtObjectInformation
Set object information Set-NtObjectInformation

Usage notes:

  • Specify the open object handle and an information class (the type of info you want).
  • Some information classes require special privileges or admin access to query.
  • A buffer must be provided to receive the queried data. The exact required buffer size is rarely documented – discover it by inspection or brute-force.

Glossary

Access Mask
A 32-bit bitfield specifying which operations are allowed on a kernel object. Used both in the handle table (granted access) and when requesting access (DesiredAccess parameter).
Access Token
A kernel object assigned to every process at creation. Defines the user identity and the rights held by that process. Managed and checked by the SRM during access checks.
AFD (Ancillary Function Driver)
The kernel driver that provides networking services (TCP/IP, etc.) to user-mode applications. WinSock is the user-mode interface to AFD. There are no direct system calls for core network protocols – everything routes through AFD.
ALPC (Advanced Local Procedure Call)
A kernel mechanism for passing discrete messages between a server process and a client process on the same machine. Uses NtCreateAlpcPort and NtConnectAlpcPort.
Authenticode
Microsoft's mechanism for digitally signing executables and drivers. Used by the Code Integrity subsystem to verify signatures before loading.
Code Integrity
A kernel subsystem that verifies file and driver code signatures and can block the loading of unsigned or improperly signed drivers to preserve system integrity.
Configuration Manager
The kernel subsystem that manages the Windows Registry. Stores persistent configuration for the OS, drivers, and applications.
Handle
A numeric ID tag a process holds to reference a kernel object it cannot directly access in memory. The Object Manager translates it to a kernel memory address via the handle table.
Handle Duplication
The process of creating a new handle (in the same or a different process) that references the same kernel object as an existing handle, optionally with reduced access rights. PowerShell: Copy-NtObject.
Handle Table
A per-process table maintained by the kernel. Each entry holds: (1) the handle number, (2) the granted access mask, and (3) a pointer to the kernel object in memory.
I/O Manager
The kernel subsystem that coordinates how applications and device drivers communicate for I/O operations such as file access, device interaction, and networking. Creates an IRP (I/O Request Packet) for each operation.
LSASS (Local Security Authority Subsystem)
The user-mode Windows service responsible for creating SIDs and providing them to the SRM. Manages authentication and local security policy.
Memory Manager
The kernel subsystem that controls the allocation and protection of physical and virtual memory. Manages paging, swapping, and memory isolation between processes.
Mutant
The Windows kernel's internal name for a mutex (mutual exclusion object). Ensures that only one thread can access a shared resource at a time.
NTSTATUS
A 32-bit status code returned by all system calls. Encodes: severity (bits 31–30), customer code (bit 29), reserved (bit 28), facility (bits 27–16), and a status code (bits 15–0).
Object
In Windows, everything is an object: files, registry keys, processes, threads, mutexes, etc. Every kernel object has a name, a type, and a security descriptor. Managed uniformly by the Object Manager.
Object Manager
The kernel component responsible for managing all kernel objects. Translates handles to kernel memory addresses, maintains the OMNS, and enforces naming and object lifetime rules.
OMNS (Object Manager Namespace)
A hidden, filesystem-like namespace for kernel objects. Built from Directory objects organised in a tree. Not well-documented. Can be explored with the NtObjectManager PowerShell module.
Permanent Object
A kernel object marked to persist in the OMNS even after all handles to it are closed. Requires SeCreatePermanentPrivilege to create via NtMakePermanentObject.
Process
A container that holds an address space, handle table, and threads. Created and managed by the Process and Thread Manager.
Process and Thread Manager
The kernel subsystem responsible for creating, managing, scheduling, and terminating processes and threads.
RID (Relative Identifier)
The rightmost sub-authority value(s) in a SID that uniquely identify a user or group within a domain or local machine.
SDDL (Security Descriptor Definition Language)
A Microsoft-defined string format for representing SIDs and security descriptors in human-readable form. Example: S-1-5-32-545.
Section Object
A kernel object type that implements memory-mapped files. Allows file or pagefile-backed memory regions to be shared across processes.
Security Descriptor
An object attached to every kernel resource that defines who can access it and in what way. Queried by the SRM during access checks.
Security Reference Monitor (SRM)
The most important kernel subsystem. Performs all access checks – deciding whether a user process can access a resource based on its access token and the resource's security descriptor.
SID (Security Identifier)
A binary structure that uniquely identifies a user or group. Represented as a string in the format S-1-5-... using SDDL notation. Created by LSASS and used by the SRM.
Symbolic Link (OMNS)
An OMNS object that redirects one namespace path to another. Contains a SymbolicLinkTarget property pointing to the destination path. Used for drive letter mappings under \GLOBAL??.
System Call
A mechanism that allows user-mode code to invoke kernel-mode functionality through the system call interface. Always prefixed with Nt or Zw.
Thread
The actual unit of execution running inside a process. A single process can have many threads running concurrently.
Windows Kernel Executive
The core of the Windows OS (NTOS Kernel). Provides all privileged OS functionality and exposes APIs to subsystems and user-mode applications via kernel executive components.