Skip to content

AD2010: DoNotMarkImportsSectionAsExecutable

Summary

Property Value
ID AD2010
Name DoNotMarkImportsSectionAsExecutable
Category Security
Severity Error
Applies to PE (Windows)

Description

PE sections should not be marked as both writable and executable. This condition makes it easier for an attacker to exploit memory corruption vulnerabilities, as it may provide an attacker executable location(s) to inject shellcode.

Because the loader will always mark the imports section as writable, it is therefore important to mark this section as non-executable.

How It Works

The rule examines the section headers in the PE file and specifically checks the .idata (imports) section. It verifies that:

  1. The section does not have the IMAGE_SCN_MEM_EXECUTE flag set
  2. The imports are not placed in an executable section

Why This Matters

The imports section (.idata) contains function pointers to external libraries. If this section is executable, an attacker who can write to it gains the ability to execute arbitrary code—the holy grail of exploitation.

The W^X Security Principle

W^X ("Write XOR Execute") is a fundamental security principle: memory should be either writable OR executable, never both.

Memory Type Should Be Why
Code (.text) R-X Execute, but never modify
Data (.data) RW- Modify, but never execute
Imports (.idata) RW- Loader writes, but never execute
Stack RW- Local variables, never code

Why Imports Are Writable

The imports section must be writable because:

  1. At load time: The loader resolves import addresses and writes them to the Import Address Table (IAT)
  2. After loading: The IAT contains pointers to external functions

Because the loader writes to this section, it cannot be read-only. This makes the executable flag particularly dangerous—if imports are W+X, any write to the IAT becomes potential code execution.

Attack Scenario

1. Attacker finds write-what-where primitive
2. Overwrites IAT entry for common function (e.g., printf)
3. Writes shellcode to adjacent IAT padding (W+X section)
4. Application calls printf() → executes attacker's shellcode

With proper permissions (W, not WX), step 3 fails because shellcode can't execute.

How This Vulnerability Occurs

This misconfiguration typically happens through:

  1. Custom linker scripts: Merging .idata with .text
  2. Section attribute flags: Explicitly adding execute permission
  3. Packers/Protectors: Some modify section attributes
  4. Legacy configurations: Old project settings

Defense in Depth

Mitigation Protection
Non-executable imports Prevents code execution in IAT
ASLR IAT address unpredictable
CFG Validates indirect calls through IAT
DEP General W^X enforcement

Performance Impact

There is zero performance impact from proper import section permissions. This is purely a configuration issue with no runtime cost to fix.

Resolution

Linker Settings

Ensure you're not using custom section flags that make imports executable:

# Bad
link.exe /SECTION:.idata,ERW ...

# Good - let the linker use default settings
link.exe ...

Check for Merge Options

Don't merge imports into code sections:

# Bad - merges .idata into .text (executable)
link.exe /MERGE:.idata=.text ...

# Good - keep sections separate
link.exe ...

Project Properties

  1. Open Project Properties
  2. Navigate to Linker → Advanced
  3. Review "Merge Sections" - ensure .idata is not merged into executable sections

When to Suppress

This rule should rarely be suppressed. Possible exceptions:

  • Custom PE loaders: Non-standard loading that requires executable imports
  • Obfuscation tools: Some protection tools intentionally modify section attributes
  • Legacy constraints: Very old code with non-standard layouts

Caveats

  • Some packers and protectors may trigger this rule
  • Custom linker scripts might inadvertently set wrong attributes
  • Third-party tools that modify PE files may introduce this issue

References