Quantcast
Channel: Tech Blog is Tech » pointers
Viewing all articles
Browse latest Browse all 6

Testing Shellcode on a Non-Executable Stack or Heap

$
0
0

EditIf you’re learning about buffer overflows and shellcode, chances are you’re exploiting some stack-based vulnerabilities. If you’re like me you might also find that when you compile your programs they have stack execution disabled by default. So instead of getting excited as you see your shellcode blissfully running after smashing the stack, you might just see this instead:

Program received signal SIGSEGV, Segmentation fault.
0x0000000000601018 in shellcode ()
“Noooo! You can’t do this to me! I want to write exploits!”

Ok.. calm down.. we just need to turn on stack execution when compiling.

Enabling Stack Execution

You can turn on stack execution when you compile your program using ld‘s execstack flag. To pass this parameter in from gcc, use the -z flag:

gcc -ggdb -fno-stack-protector -z execstack -o ShellCode ShellCode.c

The above flags will:

  • -ggdb: enable debugging symbols so we can load the application into gdb and step through it with detailed information
  • -fno-stack-protector: disable gcc‘s built-in stack protection just to be sure it doesn’t complain at you
  • -z execstack: allow code on the stack to execute; in other words, disable the NX bit. See also Intel’s xdbit or AMD’s EVP.

Example Code

Here is some example code written my 64-bit machine that will execute shell code on the stack after compiling using the aforementioned flags.

#include

/*
 * shell code based on an objdump of the exit() routine on my machine
 * # objdump -d ExitShellCode
 * 
 * ExitShellCode:     file format elf64-x86-64
 * 
 * 
 * Disassembly of section .text:
 * 
 * 0000000000400078 <_start>:
 *   400078:	48 c7 c7 00 00 00 00 	mov    $0x0,%rdi
 *   40007f:	b8 3c 00 00 00       	mov    $0x3c,%eax
 *   400084:	0f 05                	syscall
*/
char shellcode[] = "\x48\xc7\xc7\x00\x00\x00\x00"
                   "\xb8\x3c\x00\x00\x00"
                   "\x0f\05";

main() {
    // put a pointer on the stack
    long *ret;

    /*
     * we're going to point *ret to itself, then add 2 ints so that it points to main()'s
     * ret pointer on the stack
     *
     * in other words, we're doing this...
     *
     * bottom of  DDDDDDDD  DDDDEEEE  EEEEEEEE  EEEEFFFF  FFFFFFFF  FFFFFFFF     top of
     * memory     89ABCDEF  01234567  89ABCDEF  01234567  89ABCDEF  01234567     memory
     *            *ret      ebp       ret       a         b         c
     *
     * <-------   [0x010101][0x010101][0x010101][        ][        ][        ]
     *             |                          ^
     *             |--------------------------|
     * top of                                                                  bottom of
     * stack                                                                   stack
    */
    ret = (long *)&ret + 2;

    // now overwrite the ret value with the shellcode pointer so when main() returns the shellcode executes
    (*ret) = (long)shellcode;
}

Other Techniques

Return-to-libc Attack

Of course in a real situation you wouldn't be able to recompile the program so you would need another way to execute your shellcode. For that situation, you can try this technique, which is known as a return-to-libc attack. If you've been following Vivek's buffer overflow series, he made a video about return-to-libc here.

Anonymous Memory Maps

Another alternative is to use an anonymous memory map and then copy your shellcode into that memory. This has the added benefit of allowing you run code on a non-executable heap as well, but it's not as easy as passing the execstack flag to gcc.

Good Luck

I hope you learned something! Good luck with your exploits!


Viewing all articles
Browse latest Browse all 6

Trending Articles