Address Space Layout Randomization

You might also like

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 8

Address Space Layout Randomization

Dirk Gordon
Department of Computer Science and Software Engineering
University of Wisconsin-Platteville
gordondi@uwplatt.edu

Abstract
Address Space Layout Randomization (ASLR) is a security technique used to decrease
the probability of a buffer overflow attack from succeeding. ASLR does not remove
security vulnerabilities, but will instead obfuscate them through randomization of certain
elements in the processes memory. The computer utilizing ASLR is still susceptible to
brute force guessing of the targeted memory address. The a return-to-libc attack will
calculate the offset of system() from usleep(), and then the exploit program will be able to
bypass ASLR protection. ASLR has been implemented in many operating systems such
as Windows Vista and Linux. The effectiveness of ASLR is directly related to the amount
of bits used in the randomization process, so a 64 bit system will be more secure than a
32 bit system with ASLR. ASLR is not a solution that will stop all exploits, but the
technology allows the effectiveness of an exploit to be decreased.

Description
The theory of ASLR is that many exploits rely on static address values, so adding some
randomness to the memory layout will cause basic exploits to fail. ASLR will not
completely prevent an exploit that relies on hard coded memory address to succeed. If
the randomized process layout matches the exploit's targeted memory locations then the
exploit will correctly work. The purpose of ASLR is to randomize sections of a
program's memory layout, so that the chances of the exploit that relies on static memory
addresses to succeed is greatly reduced.[4] The most significant regions that ASLR
randomizes the starting location are the program's stack, heap and dynamic libraries.
ASLR will generate the locations one at a time until there are no memory conflicts.
ASLR was developed to reduce the ability and speed at which a given exploit code can
work because each computer running the vulnerable process with ASLR enabled will
have a different process memory layout. The result is the exploit code has to be crafted
to work on all possible memory layouts or that the exploit code must utilize a brute force
attack to succeed.

ASLR in Linux

Figure 1: Memory layout in Linux


Process Memory Layout in Linux
To understand the effects of ASLR on a process in Linux one must first understand how a
process' memory is mapped. The stack stores local variables and the return address of the
currently executing function. The stack is organized in a LIFO style that grows
downwards. When a function exits the function's data is removed from the stack. The
heap contains data that was created with malloc() or otherwise dynamically allocated.
The contents of the heap remain until a free() is used on each specific data item that was
created with malloc(). The heap grows upwards towards the stack. The .bss section
contains uninitialized data. Conversely, the .data section contains initialized data.
Finally, the .text section contains the program's code. ASLR will randomize the location
of the stack, heap, and any libraries used in the program.
Linux's Implementation of ASLR

08048000-08049000
08049000-0804a000
b7dec000-b7ded000
b7ded000-b7f42000
b7f42000-b7f43000
b7f43000-b7f45000
b7f45000-b7f48000
b7f53000-b7f56000
b7f56000-b7f57000
b7f57000-b7f71000
b7f71000-b7f73000
bfd5e000-bfd73000

r-xp
rw-p
rw-p
r-xp
r--p
rw-p
rw-p
rw-p
r-xp
r-xp
rw-p
rw-p

00000000
00000000
b7dec000
00000000
00155000
00156000
b7f45000
b7f53000
b7f56000
00000000
0001a000
bffeb000

03:01
03:01
00:00
03:01
03:01
03:01
00:00
00:00
00:00
03:01
03:01
00:00

49225
49225
0
188632
188632
188632
0
0
0
179874
179874
0

/home/dirk/aslr_demo
/home/dirk/aslr_demo
/lib/i686/cmov/libc-2.7.so
/lib/i686/cmov/libc-2.7.so
/lib/i686/cmov/libc-2.7.so
[vdso]
/lib/ld-2.7.so
/lib/ld-2.7.so
[stack]

Figure 2: aslr_demo process memory layout


08048000-08049000
08049000-0804a000
b7e74000-b7e75000
b7e75000-b7fca000
b7fca000-b7fcb000
b7fcb000-b7fcd000
b7fcd000-b7fd0000
b7fdb000-b7fde000
b7fde000-b7fdf000
b7fdf000-b7ff9000
b7ff9000-b7ffb000
bffe6000-bfffb000

r-xp
rw-p
rw-p
r-xp
r--p
rw-p
rw-p
rw-p
r-xp
r-xp
rw-p
rw-p

00000000
00000000
b7e74000
00000000
00155000
00156000
b7fcd000
b7fdb000
b7fde000
00000000
0001a000
bffeb000

03:01
03:01
00:00
03:01
03:01
03:01
00:00
00:00
00:00
03:01
03:01
00:00

49225
49225
0
188632
188632
188632
0
0
0
179874
179874
0

/home/dirk/aslr_demo
/home/dirk/aslr_demo
/lib/i686/cmov/libc-2.7.so
/lib/i686/cmov/libc-2.7.so
/lib/i686/cmov/libc-2.7.so
[vdso]
/lib/ld-2.7.so
/lib/ld-2.7.so
[stack]

Figure 3: aslr_demo process memory layout during another execution


Figure 2 and 3 show the memory layout of the demonstration program aslr_demo
running on Debian Linux kernel 2.6.26-2-686 with /proc/sys/kernel/randomize_va_space
set to 1. Compare the memory addresses of the two instances of the same program.
Notice how ASLR is changing the memory locations of the stack and dynamic libraries.
Each time the demo program is run it will generate a different combination of memory
locations. This methodology of layout randomization is the fundamental idea behind
ASLR.
Return-to-libc exploits rely on knowledge of the stack and libc memory addresses. On a
32 bit Linux system with ASLR enabled will use only 16 bits for the memory offset of
libc.[1] Resulting in 216 (65536) possible randomizations. The mean number of attempts
to succeed in determining the address of libc is 32767.5. In Linux ASLR will only
randomize the memory regions during a processes creation, so repeated attacks on the
same process are able to linearly search for the correct memory location.
Simple Buffer Overflow in Linux
#include <stdio.h>
int main()

{
char buffer[4];
gets(buffer);
puts(buffer);
return 0;
}
Figure 4: Vulnerable C code
Figure 4 shows a simple C program that is vulnerable to a buffer overflow because the
gets() function has no length checking, so that if the value from gets() is larger than 4
bytes there will be a buffer overflow which will overwrite the values of the nearby
memory.

Figure 5: Memory layout of the vulnerable C program


Figure 5 is the memory layout of the program during execution. To execute a return-to-c
exploit using this code would need at least 12 bytes of data to be passed into buffer to
overwrite Ret which is the return address. EBP register is the memory address of the
base of the stack, but the value of the EBP register is not important to execute the exploit.
The first 8 bytes can be anything as they are only padding to get to the return address of
the function. Bytes 9 to 12 will be the address in memory of the function to jump to.
Additional bytes would be used if there was a need to pass an argument to the function
that was being jumped to.

Figure 6: Memory layout of the vulnerable C program after a buffer overflow


Figure 6 shows what the memory layout would be if the sample program was passed the
input AAAAAAAA\x00\x00\x00\x00. The values of \x00 would point to the
memory address of where the attacker would want code to be executed. Not having
length checks on strings is one of the most common buffer overflow exploits.

Linux's ASLR Implementation Vulnerabilities


One of the limitations of ASLR which allows a buffer overflow exploit to function like in
the example above is that the current implementations of ASLR do not randomize the
data contained within sections of memory. Because data within regions of memory like
the stack and dynamic libraries are not randomized, if the program is disassembled to
determine the memory addresses of functions then it is possible to determine the memory
offsets. As long as the library or program is the same version it is possible to determine
the memory addresses within the memory segment from a remote compute. The goal of
the common return-to-libc exploit is to use the libc system() function because it will run
the passed string as a command in the exploited computer. The second libc function to
search for is the usleep() function which causes the process to sleep. The reason usleep()
is used is because you can easily determine when the correct memory location is found
because the process will sleep. Using objdump in Linux on libc to determine the memory
addresses of both system() and usleep() will allow the calculation of the memory offset
from usleep() to sytem(). Also, using gdb is another easy way to determine the memory
addresses. The return-to-libc exploit will use a brute force technique to guess the address
of usleep(), and then once usleep() has been found it will calculate the memory address of
system() using the offset that was previously calculated. The limitation of the usleep()
method is that a metric is needed to determine when the process slept or not, so this
method is best used on a process that listens for remote connections.

ASLR in Windows Vista


Vista's Implementation of ASLR
Windows Vista's implementation differs from Linux's implementation in several ways.
The main difference is that in Linux the position of libraries in memory is different for
each time a program is ran. Whereas in Vista the location in memory where a library is
located is generated at startup, and the location is the same across all processes.[2]
Having a global offset will result in a small gain in performance. Another key difference
is Vistas's offset is selected from a range of only 28 (256) values [3] compared to Linux's
65536. Although Vista's version of ASLR is much weaker compared to Linux's, ASLR
will still help to prevent simple buffer overflow attacks that do not try to guess the
randomized position in memory that the exploit code believes to be fixed.
Weaknesses in Vista's Implemenation
Symantec's research into ASLR randomization in Vista showed that there was a flaw in
the implementation. 25% of all executions chose a single address.[2] Symantec
concluded that there were simply not enough bits used in the implementation of ASLR in
32 bit Vista to provide an adequate protection with ASLR. This flaw greatly reduces
Vista's ability to prevent buffer overflow attacks using ASLR. The likelihood of an
exploit to correctly guess the memory locations is far greater in Vista than in Linux
because of the larger amount of bits used in the randomization process.
Adoption Problems of ASLR in Vista
Another problem with Vista's implementation of ASLR is in executable support for the
security feature. Unlike Linux which has the kernel controlling ASLR usage, Vista has
executables opt in to using ASLR by setting a flag to enable ASLR for the executable
during compilation. Popularly used software such as Internet Explorer 7, Adobe Flash,
and Adobe Acrobat did not support ASLR when Vista was first released. It wasn't until
Vista Service Pack 1 when support for ASLR was added to Internet Explorer. The lack of
support from software vendors for ASLR in Vista has slowed its adoption.

ASLR in 64 bit Operating Systems


With the advancement to 64 bit operating systems the amount of addressable memory
locations for each program to utilize has greatly increased. For 32 bit Linux 16 of the bits
were used for randomization, and in 32 bit Vista only 8 bits were used for randomization.

64 bit implementations of ASLR will allow for at least 40 bits to be used for
randomization.[1] Resulting in 240 (1099511627776) possible offsets to be utilized in
ASLR. Since the amount of permutations of randomness is directly correlated to the
amount of bits used in the randomization process the increase from 32 to 64 bit will
greatly increase the security provided by ASLR.

Conclusion
ASLR brings many advantages in security to operating systems. The ability of ASLR to
slow down, and prevent basic buffer overflow attacks from occurring increases the
security of operating systems, but the amount of security ASLR provides is limited to the
amount of bits that are used in the randomization process. Linux uses significantly more
bits for randomization when compared to Windows Vista which makes Linux's
implementation of ASLR to be more secure. The advancement of operating systems to
using 64 bit operating systems allows for more bits to be used in the randomization
process which will further increase the effects of ASLR. ASLR will prevent simple
attacks from succeeding most of the time, but it won't prevent it always. Also, a smart
attack that takes into account the targeted computer is utilizing ASLR will not be
prevented, and will only delay the exploits' ability to correctly guess the memory location
to target. It is important to remember that ASLR by itself will not prevent exploits from
occurring, and that the purpose of ASLR is to reduce the likelihood that an exploit will
succeed.

References
[1] (2004). On the effectiveness of address-space randomization. Retrieved from
http://stanford.edu/~blp/papers/asrandom.pdf
[2] (2007). An Analysis of Address Space Layout Randomization on Windows Vista.
Retrieved from
http://www.symantec.com/avcenter/reference/Address_Space_Layout_Randomization.pd
f
[3] (2006). Analysis of Microsft Windows Vista's ASLR. Retrieved from
http://www.packetstormsecurity.org/papers/win/Analysis-of-Microsoft-Windows-VistasASLR.pdf
[4] Address Obfuscation: an Efficient Approach to Combat a Broad Range of Memory
Error Exploits. Retrieved from http://seclab.cs.stonybrook.edu/seclab/pubs/usenix03.pdf

You might also like