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:
- The section does not have the
IMAGE_SCN_MEM_EXECUTEflag set - 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:
- At load time: The loader resolves import addresses and writes them to the Import Address Table (IAT)
- 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:
- Custom linker scripts: Merging .idata with .text
- Section attribute flags: Explicitly adding execute permission
- Packers/Protectors: Some modify section attributes
- 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:
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¶
- Open Project Properties
- Navigate to Linker → Advanced
- 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