Home How to enable DEP and ASLR to reduce the attack vector of your Delphi applications on Windows
Post
Cancel

How to enable DEP and ASLR to reduce the attack vector of your Delphi applications on Windows

TLDR; for 32-bit applications add this line to your DPR:

1
{$SETPEOPTFLAGS $140}

for 64-bit applications use:

1
2
{$SETPEOPTFLAGS $160}
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

or, if you do not have WinAPI.Windows in your uses list to support using constants, then simply use their values like:

1
2
{$SETPEOPTFLAGS $160}
{$SetPEFlags $20}

Enabled DEP in Delphi use SETPEOPTFLAGS

By default, Delphi applications are fairly resilient against buffer overflows and there was only one well-known published CVE related to Delphi XE6 and earlier, and it was an overflow in VCL.Graphics.TPicture.Bitmap due to not checking the number of colors in the image which could be overrun when processing the color palette. This was quickly addressed with a patch and Marco Cantu published a blog post on the subject and here is a link to the web archive version of the related CodeCentral article. (There is also a non-official workaround if you no longer have the source of the application.) Just because Delphi applications are resilient to attack, it does not mean that they are protected against all exploits.

Data Execution Prevention (DEP) and Address Space Layout Randomization (ASLR) are techniques that have been proven to mitigate a number of exploits that attack native applications. DEP helps to prevent code injection by marking memory regions as non-executable as protection against buffer overflows, and ASLR helps to protect against buffer overflows by randomizing the base memory load address of the executable and the heap and stack positions to prevent hackers from assuming consistent memory addresses for specific data elements. Note that DEP was introduced in Windows XP SP2 and ASLR was first supported in Windows Vista.

The following was taken from an old blog article announcing that Delphi 2007 first supported ASLR and DEP (NX page protection) and is also covered on Hallvard’s Blog.

1
2
3
4
5
6
7
8
9
10
The CodeGear Delphi 2007 compiler supports ASLR via any of these three techniques:**
- add the command-line switch --dynamicbase when compiling with dcc32**  
- add the preprocessor command '{$DYNAMICBASE ON}' to the source code**
- manually OR in the bit in the header, with '{$SETPEOPTFLAGS $40}' in the source code**
    
The CodeGear Delphi 2007 compiler supports NX via this technique:**
- manually OR in the bit in the header, with '{$SETPEOPTFLAGS $100}' in the source code**

The easiest way to enable both ASLR and NX is to do this:**
- add '{$SETPEOPTFLAGS $140}' to the project source file (.dpr or .dpk)**

64-bit executables obviously have more ability to randomize the address space with ASLR and can be harder to attack than 32-bit executables. You can further increase the memory address space of ASLR by enabling HIGHENTROPYVA which requires LargeAddressAware images:

1
{$SetPEFlags IMAGE_FILE_LARGE_ADDRESS_AWARE}

See Embarcadero’s wiki page and Microsoft docs page for more info on PE header flags.

The values for SETPEOPTFLAGS can be found in winnt.h which is installed along with the Windows SDK and the values should be OR’ed together:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// DllCharacteristics Entries
//      IMAGE_LIBRARY_PROCESS_INIT            0x0001     // Reserved.
//      IMAGE_LIBRARY_PROCESS_TERM            0x0002     // Reserved.
//      IMAGE_LIBRARY_THREAD_INIT             0x0004     // Reserved.
//      IMAGE_LIBRARY_THREAD_TERM             0x0008     // Reserved.
#define IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA    0x0020  // Image can handle a high entropy 64-bit virtual address space.
#define IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE 0x0040     // DLL can move.
#define IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY    0x0080     // Code Integrity Image
#define IMAGE_DLLCHARACTERISTICS_NX_COMPAT    0x0100     // Image is NX compatible
#define IMAGE_DLLCHARACTERISTICS_NO_ISOLATION 0x0200     // Image understands isolation and doesn't want it
#define IMAGE_DLLCHARACTERISTICS_NO_SEH       0x0400     // Image does not use SEH.  No SE handler may reside in this image
#define IMAGE_DLLCHARACTERISTICS_NO_BIND      0x0800     // Do not bind this image.
#define IMAGE_DLLCHARACTERISTICS_APPCONTAINER 0x1000     // Image should execute in an AppContainer
#define IMAGE_DLLCHARACTERISTICS_WDM_DRIVER   0x2000     // Driver uses WDM model
#define IMAGE_DLLCHARACTERISTICS_GUARD_CF     0x4000     // Image supports Control Flow Guard.
#define IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE     0x8000

According to Microsoft docs, ASLR and DEP are only effective when used together. Also note that there are inherent weaknesses to the ASLR protection - if a single pointer location is leaked (with an exception trace for example) then the attacker can find the offset and compute the relocated address locations if they can reproduce the same leak locally.

These advanced security options are not enabled by default due to backwards compatibility issues. However, as security continually becomes more of an issue, Windows has new options available to apply these anti-exploit mechanisms regardless of how the executables are built. In later versions of Windows, look for the Exploit protection in a System Settings screen to examine the options available. (While you can configure Windows to enforce DEP for all programs running in Windows, some well-known software, such as SolarWinds, have problems when DEP is enabled.)

We should obviously try to create applications that are able to be certified as secure. Delphi applications targeting Windows should be able to pass the current Microsoft certifications. If you have worked with Microsoft and completed the Windows 10 Desktop App Certification process for your Delphi created application, please let me know via one of the contact options listed below as I would be interested in any obstacles that you encountered. A quick search in the Quality Portal yielded one related open issue with only two votes: RSP-35641. I have not seen too many discussions on Microsoft certifications for Delphi applications over the years, but it seems like it should be much more common.

As shown in the screenshots above, you can easily see which processes have Data execution prevention enabled in Task Manager. (You will need to add a new column for “Data execution prevention” as this option is not displayed by default.)

I have utilized Microsoft EMET in the past to secure my service applications running on Windows Servers to satisfy third-party compliance audits. I have not enabled these specific PE header options directly in my Delphi projects before as I relied on EMET which has been replaced with enhanced functionality built into the Windows operating system as Windows Defender Exploit Guard.