Join our Newsletter — 33% off our NHI Course
Home› Guides› D3-PSEP Process Segment Execution Prevention: Enforcing Non-Executable Memory…
Guide Application Security

D3-PSEP Process Segment Execution Prevention: Enforcing Non-Executable Memory and Proving It Works

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 12 November 2026 12 min read
On this page

Most memory corruption exploits end with the processor running bytes the attacker placed in a stack or heap buffer, and Process Segment Execution Prevention stops that last step by refusing to execute anything outside the code segment. MITRE D3FEND names this countermeasure Process Segment Execution Prevention (D3-PSEP) and defines it as "Preventing execution of any address in a memory region other than the code segment." Its synonyms are No Execute and Execute Disable, and in Windows it is known as Data Execution Prevention (DEP). It sits under the Harden tactic as a child of Application Hardening. This card covers what D3-PSEP enforces, which ATT&CK techniques D3FEND relates it to, where it is implemented on Windows, Linux and macOS, how to verify it is on for every process, and why it is a baseline rather than a complete exploit defence. It is written for platform engineers, application security teams and endpoint owners.

Key takeaways

  • It is a baseline, not a full exploit defence. Microsoft's own documentation says DEP "is not intended to be a comprehensive defense against all exploits", and D3FEND notes that return-oriented programming and return-to-libc reuse code that is already executable.
  • Hardware enforcement is the norm. The NX (AMD) or XD (Intel) bit in each page table entry marks memory as non-executable; D3FEND notes that software-only implementations are easier to turn off for a page.
  • 64-bit processes are covered by default. Microsoft states that DEP is enabled for x64, ARM and Arm64 executables and cannot be disabled; legacy 32-bit processes are where gaps remain.
  • Exceptions are the real attack surface. JIT compilers, executable stacks set by the linker, and runtime entitlements that permit writable and executable memory are where the control is weakened, so inventory them.
  • Verification is cheap. Boot messages, CPU flags, the boot configuration value and ELF program headers show whether the control is active, and a build pipeline can fail on executable stacks.

D3-PSEP at a glance

AttributeValue
D3FEND IDD3-PSEP (d3f:ProcessSegmentExecutionPrevention)
TacticHarden
Parent techniqueApplication Hardening
Digital artefactProcess Segment, synonym Process Memory (D3FEND relation: neutralizes Process Segment)
SynonymsNo Execute, Execute Disable
Common namesNX bit, XD bit, DEP, W^X (write xor execute), non-executable stack
What it changesStack, heap and data pages are mapped without execute permission, so a jump into them faults
EffortLow: on by default on current 64-bit platforms; effort goes into legacy binaries and exceptions
Main limitationCode-reuse attacks (ROP, return-to-libc) and abuse of legitimately executable memory

How it works

D3FEND describes the principle simply: during execution the instruction pointer should only point at addresses in the code segment (the .text segment), because that is the only segment that should hold program code. D3-PSEP enforces that by giving memory regions an execute permission and refusing to fetch instructions from regions that lack it.

  • Hardware enforcement: the processor's NX or XD bit marks memory as non-executable. D3FEND notes that early implementations set this per segment, while modern flat-memory systems store it in each page table entry, so execution is controlled page by page.
  • Software enforcement: D3FEND's example is Windows XP SP2 software-enforced DEP, which did not check every change of the instruction pointer but did check, before calling an exception handler, that the handler sat in executable memory. Combined with SafeSEH it also checked that the handler was registered in the program file.
  • What happens on violation: on Windows, code executed from a protected page raises STATUS_ACCESS_VIOLATION, and an unhandled exception terminates the process. D3FEND points out that a detected violation can feed eviction countermeasures such as Process Termination or blocking the faulting executable.

The same idea is often expressed as W^X: a page may be writable or executable, never both at once. Code that genuinely needs to generate instructions at runtime, such as a JIT compiler, has to ask for executable memory explicitly. Microsoft's guidance is to allocate with VirtualAlloc using a PAGE_EXECUTE protection value and then call VirtualProtect to remove write access once the code is generated. Heap memory from malloc and HeapAlloc is non-executable.

ATT&CK techniques D3FEND relates to D3-PSEP

Relationship type: inferred only. D3FEND does not hand-map D3-PSEP to ATT&CK. It infers the rows below because D3-PSEP neutralizes Process Segment and these techniques access or modify a Process Segment or one of its sub-artefacts. D3FEND labels these relations "inferred and experimental" (knowledge graph 1.6.0, checked November 2026). Every ID was checked against ATT&CK v20.

Tactic (ATT&CK v20)ATT&CK IDTechniqueWhere non-executable memory helps
Initial AccessT1189Drive-by CompromiseBrowser exploits that place shellcode in heap memory fault instead of running
Initial AccessT1190Exploit Public-Facing ApplicationClassic stack or heap overflow payloads in a server process cannot execute in place
ExecutionT1203Exploitation for Client ExecutionDocument and client exploits must fall back to code reuse
Privilege EscalationT1068Exploitation for Privilege EscalationInjected code in data pages of a privileged process cannot run directly
Privilege Escalation, StealthT1055.012Process HollowingPartial: hollowing maps code as executable, so the gain is in forcing explicit, observable permission changes
StealthT1211Exploitation for StealthSame as other exploitation techniques
StealthT1620Reflective Code LoadingPartial: the loader must request executable memory, which ACG-style policies can block
StealthT1218.013MavinjectPartial: injection into another process writes to its memory segments
StealthT1564.010Process Argument SpoofingLittle direct effect: the technique rewrites data, not code, in process memory
Lateral MovementT1210Exploitation of Remote ServicesRemote service exploits that rely on executing a buffer fail
Credential AccessT1212Exploitation for Credential AccessSame as other exploitation techniques
Credential Access, CollectionT1056.004Credential API HookingPartial: hooks must be placed in executable memory with explicit permission changes
DiscoveryT1033System Owner/User DiscoveryLittle direct effect: D3FEND relates it because the technique may read process memory

The fourth column is NHI Mgmt Group's reading, not D3FEND's. Read the table as "where the artefact overlaps", not as a coverage claim: non-executable memory blocks injected shellcode, not discovery or argument spoofing. Defensive detail for the techniques is in T1190 Exploit Public-Facing Application Defensive Guide, MITRE ATT&CK T1189 Drive-by Compromise, MITRE ATT&CK T1210 Exploitation of Remote Services and MITRE ATT&CK T1620 Reflective Code Loading. The mitigation view is in M1050 Exploit Protection.

Where it is implemented

Platforms are listed alphabetically.

Platform or layerMechanism and settingExceptions to watch
CPUNX (No eXecute) or XD (eXecute Disable) bit in page table entries. Red Hat notes that some firmware setup menus offer an option to turn it offFirmware setting disabled on older or misconfigured hardware
Linux kernelNX enabled by default when the CPU supports it; kernel parameter noexec=on is the default and noexec=off disables it, which Red Hat does not recommend. On 32-bit x86 the option needs a PAE kernelnoexec=off on the kernel command line
Linux toolchain (GNU ld)-z noexecstack marks the stack non-executable; -z separate-code puts instructions on pages separate from data; --warn-rwx-segments (on by default) warns on segments that are readable, writable and executable; --error-rwx-segments and --error-execstack turn warnings into build failures-z execstack, hand-written assembler objects with no .note.GNU-stack section, which on some targets implies an executable stack
macOSHardened Runtime, required for notarisation, disallows capabilities such as JIT compilation unless an exception entitlement is addedEntitlements com.apple.security.cs.allow-jit, com.apple.security.cs.allow-unsigned-executable-memory and com.apple.security.cs.disable-executable-page-protection (all default false)
Windows boot policyBCDEdit nx value: OptIn (operating system components only), OptOut (all processes, with per-program opt-out), AlwaysOn (all processes, attempts to disable ignored), AlwaysOff (DEP disabled)OptIn or AlwaysOff on servers; per-program opt-outs under OptOut
Windows exploit protectionDEP mitigation: enabled for x64, ARM and Arm64 executables and cannot be disabled; enabled for x86 binaries but can be disabled per process. Arbitrary code guard (ACG) goes further and blocks making memory executable at all (STATUS_DYNAMIC_CODE_BLOCKED), with an audit-only optionEnable ATL Thunk emulation for old ATL components; legacy x86 applications that generate code at runtime
Windows applicationsImages built DEP-compatible (the MSVC /NXCOMPAT linker option); code in data sections moved to a code section or marked IMAGE_SCN_MEM_EXECUTEJIT engines and plug-in hosts that need executable heaps

Implementation steps

  1. Confirm hardware support and firmware state. On Linux, check for the nx flag in /proc/cpuinfo and the boot message "NX (Execute Disable) protection: active". On Windows, read the system policy (GetSystemDEPPolicy, or the nx entry in the boot configuration). Fix any firmware setting that has turned NX or XD off.
  2. Set the strongest workable system policy. On Windows servers aim for OptOut or AlwaysOn rather than OptIn. On Linux, make sure no host has noexec=off on the kernel command line.
  3. Inventory the exceptions. List 32-bit Windows processes with DEP disabled, programs on the OptOut exception list, ELF binaries with an executable stack (a GNU_STACK program header with execute permission) or RWX segments, and macOS apps carrying the three executable memory entitlements. Each needs an owner and a reason.
  4. Harden the build pipeline. Add --error-execstack and --error-rwx-segments (with the matching warning switches) to release builds, keep -z separate-code, and treat any new executable memory entitlement as a security review item.
  5. Tighten beyond DEP where it fits. For processes that never generate code, such as many server daemons and document renderers, test ACG in audit mode first, then enforce. Do not enforce it on JIT hosts.
  6. Pilot and roll back. Move legacy 32-bit applications to DEP enabled in a test ring; a crash on start usually means runtime code generation or old ATL thunks. Roll back with a per-application setting, not by weakening the system policy.

How to verify it works

  • Platform check: record the boot NX message or CPU flag on Linux and the nx boot value on Windows in configuration compliance scans, so drift is reported.
  • Binary check: scan release artefacts for executable stacks and RWX segments as part of the build; treat a hit as a failed build.
  • Process check: for Windows, query each process's DEP state through endpoint tooling and alert on 32-bit processes running with DEP disabled.
  • Functional test: in a lab, run a harmless test program that copies a few bytes into a heap buffer and jumps to them. It must crash with an access violation or segmentation fault. Keep it out of production estates.
  • Audit evidence: where ACG is in audit mode, review blocked-in-audit events before enforcing.
MetricExample target (NHI Mgmt Group suggestion, not a standard)
Hosts with NX active and DEP policy OptOut or AlwaysOn100% of supported hardware
Release binaries with executable stack or RWX segmentsZero, or each with a documented exception
32-bit processes running with DEP disabledFalling quarter on quarter
Apps holding executable memory entitlements or ACG exemptions without an ownerZero

Limits, bypasses and failure patterns

  • Code reuse: D3FEND states that ROP and return-to-libc can bypass D3-PSEP because they call code that legitimately sits in the .text segment. Pair it with D3-CFI Control Flow Integrity, D3-SFCV Stack Frame Canary Validation, D3-PAN Pointer Authentication and D3-SAOR Segment Address Offset Randomization, which make the reuse step harder.
  • Attacker-requested executable memory: an exploit that has gained some control can call the operating system to mark its buffer executable. ACG on Windows and the absence of executable memory entitlements on macOS are the controls that close this path.
  • JIT surfaces: browsers, script engines and runtimes that compile code keep writable or executable regions by design. Isolate them in separate processes where the platform allows.
  • Legacy exceptions that become permanent: an OptOut entry added for one old application years ago stays forever unless it has an owner and a review date.
  • Silent toolchain regressions: one hand-written assembler file without a .note.GNU-stack section can mark a whole binary as needing an executable stack on some targets. Build-time errors catch it; reviews rarely do.
  • Software-only enforcement: D3FEND notes that non-hardware enforcement is easier to switch off for a page of memory; rely on hardware NX or XD.

Framework mapping

FrameworkReferenceRelevance
NIST SP 800-53 Rev 5SI-16 Memory ProtectionControls to protect system memory from unauthorised code execution, the direct home of D3-PSEP
NIST SP 800-53 Rev 5CM-7 Least Functionality; SA-15 Development Process, Standards, and ToolsRemoving executable memory exceptions; toolchain flags as development standards
NIST CSF 2.0PR.PS-01, PR.PS-06Configuration management practices; secure software development practices
MITRE ATT&CKM1050 Exploit ProtectionThe ATT&CK mitigation that covers DEP and related exploit mitigations
MITRE D3FENDApplication Hardening, D3-PSEPParent and technique

Practitioner checklist

  • Confirm NX or XD is enabled in firmware and active at boot on every host class.
  • Set Windows DEP policy to OptOut or AlwaysOn on servers and record any per-program exceptions.
  • Check no Linux host boots with noexec=off.
  • Fail release builds on executable stacks and RWX segments.
  • Register every JIT host, ATL thunk exception and macOS executable memory entitlement with an owner.
  • Test ACG in audit mode for processes that never generate code, then enforce.
  • Pair D3-PSEP with control flow integrity, stack canaries and address randomisation.
  • Include DEP and NX state in configuration compliance reporting.

Standards and references

Related NHI Mgmt Group resources: MITRE D3FEND Guide · M1050 Exploit Protection · D3-CFI Control Flow Integrity · Memory Safety Roadmap Guide

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 12 November 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org