How Was This Executable Built?
Over the last few years, there has been a push to severely limit entire categories of attacks (such as buffer overflows) by incorporating specific hardware functionality with various compiler options to produce more secure code. When developing software, it is easy to mandate that these compiler options be utilized during software development, but how does the end user determine if the options were actually used? Before we can determine what compiler options have been enabled, we must first examine some of the functionality that has been developed to help protect code. Some of the options include:
- Address space layout randomization (ASLR)
- Position independent executable (PIE) or Position Independent Code (PIC)
- Marking data sections as non-executable
- Detecting Stack corruption
ASLR allows the system to load a program at a different memory location each time the program is executed. For system processes, this usually means that the programs will assume a different memory location each time the system is booted. Nevertheless, different systems will have the same programs loaded at different locations in memory, making it more difficult for an attacker to predict target addresses. To utilize ASLR, you must have position independent code that can operate wherever it is loaded. Another common attack is to try to start executing the code that is located in the data section of a program (common in buffer overflow attacks). Current compilers implement NX (No eXecute) bit functionality that enables the processor to refuse to execute code that resides in memory that has been marked as non-executable. Many operating systems can also simulate NX bit functionality in software to support older hardware. Some of the data execution prevention technologies include:
Finally, a third common attack is to cause an overflow or other corruption in the stack. In this attack, the attacker overwrites information on the stack and either attempts to execute his own code or tries to run an existing system function to gain control. Stack canaries enable the system to determine if the stack has been overwritten and thus detect these types of attacks. They work by placing a value that is only known to the system on the stack when a function is invoked . If the value is overwritten or changed, then it indicates that something has corrupted the stack and the system can prevent the execution of the attacker’s code. Each of these options can help harden your system and the software running on it. But as with the locks on the doors of your house, these tools are only effective if they are enabled. Checking if a door is locked is fairly easy, but checking if these options are enabled on your system or on a specific piece of software may not be as easy. Besides running the program in a debugger, there are some simple techniques that you can use to check if these options are enabled on various systems. On many linux systems you can use a script called checksec. This script will check for the following items:
Note: When using checksec.sh be sure to use the correct path to the file. If you enter a file that does not exist, the output looks very similar to a file that does exist. This is shown in the sample output using /usr/sbin/ssh as a file.
You can also check for ASLR on many linux systems by executing the following command: $ cat /proc/sys/kernel/randomize_va_space If ASLR is enabled, this command should return value greater than 0. The value indicates the ASLR status based on the following:
- 0 – ASLR disabled
- 1 – Shared libraries and PIE binaries are randomized (conservative)
- 2 – Adds randomizing the start of the brk area, along with conservative settings (full)
On Windows-based systems, DEP is controlled by a system policy and can be either hardware-based using the NX-bit or software simulated. To determine if your hardware supports the NX-bit, execute the command: wmic OS Get DataExecutionPrevention_Available If your hardware supports the NX-bit, then this command will return “TRUE”. To determine the current DEP policy configuration for your system, execute the following command: wmic OS Get DataExecutionPrevention_SupportPolicy This command will return a value from 0-3 indicating the current policy based on the following:
- 0 – AlwaysOff
- 1 – AlwaysOn
- 2 – OptIn (default)
- 3 – OptOut
Note: Global DEP settings for Windows XP can be made with a switch called “no execute” in the Boot.ini file. To following screenshot shows a system in which hardware DEP is supported and the current policy is 2, indicating that it is configured for OptIn (the default). This means that applications have to choose to use DEP.
You can also use Process Explorer to view the DEP and ASLR status on specific processes. When you run process explorer, you will need to select the DEP and ASLR columns for the process display.
ASLR is not available on every Windows system. If you can’t select the ASLR column, then your system does not support ASLR. With Windows Vista, ASLR is enabled by default, resulting in a shuffling of addresses after every reboot. Once you have enabled the DEP or ASLR columns you can view the current status.
On Red Hat systems you can determine the ExecShield policy by executing the following command: $ cat /proc/sys/kernel/exec-shield This command will return a value from 0-2 indicating the current ExecShield policy based on the following options:
- 0 – Exec-shield (including randomized VM mapping) is disabled for all binaries, marked or not
- 1 – Exec-shield is enabled for all marked binaries (default)
- 2 – Exec-shield is enabled for all binaries, regardless of marking (to be used for testing purposes ONLY)
Similarly, you can check your VM policy (ASLR) by executing the following command: $ cat /proc/sys/kernel/exec-shield-randomize This command will return either 0 or 1 according to the following options:
- 0 – Randomized VM mapping is disabled
- 1 – Randomized VM mapping is enabled (default)
Note: Both of these options can be changed by using the echo command, as in the following example: echo 1 > /proc/sys/kernel/exec-shield To check if a Red Hat binary is compiled as PIE, use this command: $ readelf -h -d /usr/sbin/smbd | grep ‘Type:.*DYN’ If the file has been compiled for PIE, the command will return something similar to the following: Type: DYN (Shared object file) So without being a developer, you an usually get an idea of whether your system or software is enforcing data execution restrictions, randomizing address locations and potentially checking for stack corruption.