This appendix contains information about mitigation techniques.
Various exploit mitigation techniques and mechanisms available today are designed to make exploiting memory corruption vulnerabilities as difficult as possible. The most prevalent ones are these:
There are other mitigation techniques that are bound to an operating system platform, a special heap implementation, or a file format like SafeSEH, SEHOP, or RELRO (see Section C.2). There are also various heap mitigation techniques (heap cookies, randomization, safe unlinking, etc.).
The many mitigation techniques could easily fill another book, so I will focus on the most prevalent ones, as well as on some tools used to detect them.
There is a continuous race between exploit mitigation techniques and ways of bypassing them. Even systems using all of these mechanisms may be successfully exploited under certain circumstances.
ASLR randomizes the location of key areas of a process space (usually the base address of the executable, the position of the stack, the heap, the libraries, and others) to prevent an exploit writer from predicting target addresses. Say you find a write4 primitive vulnerability that presents you with the opportunity to write 4 bytes of your choosing to any memory location you like. That gives you a powerful exploit if you choose a stable memory location to overwrite. If ASLR is in place, it’s much harder to find a reliable memory location to overwrite. Of course, ASLR is effective only if it’s implemented correctly.[100]
These methods normally inject a canary or cookie into a stack frame to protect the function’s metadata associated with procedure invocation (e.g., the return address). Before the return address is processed, the validity of the cookie or canary is checked, and the data in the stack frame is reorganized to protect the pointers and arguments of the function. If you find a stack buffer overflow in a function that is protected by this mitigation technique, exploitation can be tough.[101]
The No eXecute (NX) bit is a CPU feature that helps prevent code execution from data pages of a process. Many modern operating systems take advantage of the NX bit. Under Microsoft Windows, hardware-enforced Data Execution Prevention (DEP) enables the NX bit on compatible CPUs and marks all memory locations in a process as nonexecutable unless the location explicitly contains executable code. DEP was introduced in Windows XP SP2 and Windows Server 2003 SP1. Under Linux, NX is enforced by the kernel on 64-bit CPUs of AMD and Intel. ExecShield[102] and PaX[103] emulate the NX functionality on older 32-bit x86 CPUs under Linux.
Before you can try to circumvent these mitigation techniques, you have to determine which ones an application or a running process actually uses.
Mitigations can be controlled by system policy, by special APIs, and by compile-time options. For example, the default system-wide DEP policy for Windows client–operating systems is called OptIn. In this mode of operation, DEP is enabled only for processes that explicitly opt in to DEP. There are different ways to opt a process in to DEP. For example, you could use the appropriate linker switch (/NXCOMPAT) at compile time, or you could use the SetProcessDEPPolicy
API to allow an application to opt in to DEP programmatically. Windows supports four system-wide configurations for hardware-enforced DEP.[104] On Windows Vista and later, you can use the bcdedit.exe console application to verify the system-wide DEP policy, but this must be done from an elevated Windows command prompt. To verify the DEP and ASLR settings of an application, you can use Sysinternals’s Process Explorer.[105]
To configure Process Explorer so that it shows the processes’ DEP and ASLR status, add the following columns to the view: View ▸ Select Columns ▸ DEP Status and View ▸ Select Columns ▸ ASLR Enabled. Additionally, set the lower pane to view DLLs for a process and add the “ASLR Enabled” column to the view (see Figure C-1).
The newer versions of Windows (Vista or later) also support ASLR by default, but the DLLs and EXEs must opt in to support ASLR using the /DYNAMICBASE linker option. It is important to note that protection is significantly weaker if not all modules of a process opt in to ASLR. In practice, the effectiveness of mitigations like DEP and ASLR is heavily dependent on how completely each mitigation technology has been enabled by an application.[106]
Figure C-1 shows an example of Process Explorer being used to observe the DEP and ASLR settings of Internet Explorer. Note that the Java DLLs that have been loaded into the context of Internet Explorer do not make use of ASLR (denoted by an empty value for the ASLR column in the lower pane). Microsoft has also released a tool called BinScope Binary Analyzer,[107] which analyzes binaries for a wide variety of security protections with a straightforward, easy-to-use interface.
If both DEP and ASLR are correctly deployed, exploit development is a lot harder.
To see if a Windows binary supports the security cookie (/GS) mitigation technique, you can disassemble the binary with IDA Pro and look for references to the security cookie in the function epilogue and prologue, as shown in Figure C-2.
To check the system-wide configurations of Linux systems as well as ELF binaries and processes for different exploit mitigation techniques, you can use my checksec.sh
[108] script.