Skip to content

AD2029: EnableIntegrityCheck

Summary

Property Value
ID AD2029
Name EnableIntegrityCheck
Category Security
Severity Error
Applies to PE (Windows)

Description

Binaries that are loaded by certain Windows features must (and device drivers should) opt into Windows validation of their digital signatures by setting the /INTEGRITYCHECK linker flag.

This option sets the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY attribute in the PE header which tells the memory manager to validate a binary's digital signature when loaded.

How It Works

The rule checks for the IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY flag (0x0080) in the PE optional header's DLL characteristics field.

Why This Matters

Integrity Check (/INTEGRITYCHECK) enforces cryptographic verification of code before it runs, ensuring that even system-level attacks cannot inject unverified code into protected scenarios. For security-critical components, this flag is not optionalβ€”it's required.

The Chain of Trust

Modern Windows security relies on authenticated boot and runtime verification:

Secure Boot β†’ Boot Loader β†’ Kernel β†’ ELAM β†’ Protected Processes
     ↓              ↓           ↓        ↓           ↓
   Signed       Signed      Signed   Signed    Signed + IntegrityCheck

Without /INTEGRITYCHECK, a binary can be tampered with and still load (if signature checking isn't mandatory for that code path).

Critical Use Cases

Scenario Requirement Consequence if Missing
ELAM drivers Required Won't load as ELAM
PPL binaries Required Signature bypass possible
Device drivers Strongly recommended Weak tamper resistance
UEFI code Required Secure boot compromise
Antimalware Required Rootkit evasion possible

Early Launch Antimalware (ELAM)

ELAM drivers load before other drivers to detect rootkits:

  1. Boot starts - Minimal kernel loaded
  2. ELAM loads - Must have INTEGRITYCHECK
  3. ELAM scans - Checks all subsequent driver loads
  4. Other drivers - Loaded if ELAM approves

Without INTEGRITYCHECK, an attacker could: - Modify the ELAM driver binary - Disable malware detection at the earliest stage - Hide subsequent rootkit activity

Protected Process Light (PPL)

PPL provides enhanced process protection:

PPL Protection Levels:
  PPL-WinTcb: Windows kernel components
  PPL-Antimalware: AV/EDR software
  PPL-App: Protected applications

All PPL binaries MUST have INTEGRITYCHECK.

How Verification Works

Without INTEGRITYCHECK:
  Binary loaded β†’ Signature optional β†’ May run modified

With INTEGRITYCHECK:
  Binary loaded β†’ Signature REQUIRED β†’ Modified = load fails
  ↓
  Memory manager checks Authenticode signature
  ↓
  Invalid/missing signature = binary won't load

Defense Against Tampering

Common tampering attacks and INTEGRITYCHECK's effect:

Attack Without INTEGRITYCHECK With INTEGRITYCHECK
Binary patching May succeed Load fails
DLL replacement May succeed Load fails
Driver substitution May succeed Load fails
Man-in-the-middle May succeed Load fails

Signing Requirements

Binaries with INTEGRITYCHECK must be properly signed:

  • EV code signing certificate for drivers
  • Standard code signing for user-mode PPL
  • Timestamp to survive certificate expiration
  • SHA-256 or better hash algorithm

Compliance Implications

Standard Relevance
Windows Hardware Compatibility Required for drivers
Common Criteria Tamper resistance evidence
FIPS 140 Cryptographic module integrity
Antimalware certification Required for ELAM

Required for: - ELAM drivers: Early Launch Antimalware drivers - Device firmware: UEFI-related code - Protected processes: Code loading into PPL space - Secure boot: Authenticated boot chain

Benefits: - Tamper detection: Modified binaries won't load - Trust chain: Ensures authentic code execution - Compliance: Required for certain Windows features

Resolution

Enable Integrity Check

Linker flag:

link.exe /INTEGRITYCHECK ...

Project Properties

  1. Open Project Properties
  2. Navigate to Linker β†’ Advanced
  3. Set "Force File Output Integrity Check" to "Yes (/INTEGRITYCHECK)"

CMake

if(MSVC)
    add_link_options(/INTEGRITYCHECK)
endif()

Sign the Binary

Binaries with /INTEGRITYCHECK must be signed:

signtool sign /a /fd SHA256 /t http://timestamp.digicert.com binary.exe

When to Suppress

This rule can be suppressed for:

  • Regular applications: Most apps don't need forced integrity
  • Unsigned binaries: If you can't sign the binary
  • Development builds: During development without code signing
  • Internal tools: Non-production utilities

Caveats

  • Binary MUST be signed if this flag is set, or it won't load
  • Requires a valid code signing certificate
  • Self-signed certs may not work in all scenarios
  • Loading fails silently if signature validation fails

Who Needs /INTEGRITYCHECK

Component Required
ELAM drivers βœ… Yes
Kernel drivers ⚠️ Recommended
UEFI applications βœ… Yes
Protected process code βœ… Yes
Normal applications ❌ Optional
DLLs loaded by above βœ… Yes

Verification

Check if integrity check is enabled:

dumpbin /HEADERS binary.exe | findstr "Force integrity"

Error When Unsigned

If the binary is marked with /INTEGRITYCHECK but not signed:

ERROR_INVALID_IMAGE_HASH (0x80070241)
Windows cannot verify the digital signature for this file.

References