Non-eXec Stack – Analysis   4 comments

  • Post Info:
    1. # Author: Flavio do Carmo Junior aka waKKu
      # URL: Author’s Webpage
      # Date: November 25, 2011
      # Category: Assembly, Exploiting, Programming, Security

    Hi folks… Long time no see, huh?

    Yeah, Aussie life has kept me quite busy, however, if you live in Sydney you know that the weather has not been friendly lately…

    Enough of BS, let’s see what matters.

    I was following a thread in one of those maillists, and someone said that he was having difficult to see how Non-eXecutable Stack works properly, so I will try to illustrate it here.

    First of all, we need to separate things. There are two things that are usually mistaken by the same.
    Executable Space Protection: The PTE (Page Table Entry) is a set of control bits at the begining of each page (1 page = 4096 bytes), responsible to control things such as readable, writeable, user or supervisor, present or not, physical address, etc. At this moment, there was no eXecutable bit, therefore a readable page was also considered eXecutable. Those guys from PaX are always trying to make the world more secure and then they came with a solution to protect some memory areas from execution. However, the only alternative was a control by memory segment, what was cool but not perfect. This technique is based on highest address execution, where you can set the highest address which can be executable, but the start point is always the same. Therefore, if your application needs execution at 0xbeefdead address, it will need to mark everything from the 0x08048000 up to 0xbeefdead.

    Hardware Bit: With the introduction of 64bits CPUs the word size doubled, allowing enough space to add a new bit, eXecutable bit, within the PTE. The 63rd bit (Most Significant Bit) was chosen to control eXectuable/Not eXecutable page. At this time, guys from PaX and other implementations (Red Hat Exec-Shield, for instance), improved their control to a page level in 64bits CPUs. The RH exec-shield patch was merged into the kernel 2.6.8 (IIRC) mainstream and now Linux has native Executable Space Protection for x86_64. Nevertheless,

    Physical (memory) Address Extension: The PAE patch brought the HIGHMEM feature, which allows 32bits CPU address 4Gb+ of memory and, in the same vein, is able to emulate the NX Bit on x86 kernels.

    To sum up, we have 3 ways to use Executable Space Protection:
    1. – x86_64 CPU + Kernel > 2.6.8
    2. – x86 CPU + Kernel > 2.6.8 with HIGHMEM
    3. – x86 CPU + Patch to segment protection

    Compatability:
    Suddenly everything changed. How to make this change as seamless as possible for users.
    The Exec Shield patch added a new kernel command line (or /proc) option:
    /proc/sys/kernel/exec-shield, which allows to choose 4 states:
    exec-shield=0 – always-disabled
    exec-shield=1 – default disabled, except binaries that enable it
    exec-shield=2 – default enabled, except binaries that disable it
    exec-shield=3 – always-enabled

    The default option is exec-shield=2, which allows a good level of security and almost no headaches for the majority of users.
    This option is not present in every Linux distribution, but each one has its own way to control this behavior.

    How this stuff works…

    1. Examples

    waKKu@0xcd80$ grep stack /proc/self/maps
    7fff7246e000-7fff7248f000 rw-p 00000000 00:00 0                          [stack]
    waKKu@0xcd80$ gcc -m32 -z execstack -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
    waKKu@0xcd80$ gcc -m32 -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
    

    As we can see, there are at least 2 ways to check which permissions a specific memory area was linked with.
    /proc/$PID/maps
    readelf

    2. Our program
    As our program, I did some modifications on that one from Linux Shellcodes 101 in order to ensure it will put the shellcode in the stack area.

    #include
    #include
    
    // Linux x86 ShellCodes: 101 - exit(69)
    
    int main(void)
    {
    	char shellcode[10]; // Make room for our shellcode into the stack area
    	strncpy(shellcode, "\x31\xc0\x40\x31\xdb\xb3\x45\xcd\x80", 9); // write the exit shellcode
    	shellcode[9] = 0x00; // just precautions
            int (*ret)() = (int(*)())shellcode; //function pointer = casting variavel -> function
            ret(); // Once we have our pointer, we call it from the stack
    }
    

    – So far so good, right? Nothing new…

    3. Tests

    #include
    #include
    
    // Linux x86 ShellCodes: 101 - exit(69)
    
    int main(void)
    {
            char shellcode[10]; // Make room for our shellcode into the stack area
            strncpy(shellcode, "\x31\xc0\x40\x31\xdb\xb3\x45\xcd\x80", 9); // write the exit shellcode
            shellcode[9] = 0x00; // just precautions
            int (*ret)() = (int(*)())shellcode; //function pointer = casting variavel -> function
            ret(); // Once we have our pointer, we call it from the stack
    }
    
    waKKu@0xcd80$ gcc -m32 -z execstack -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep GNU_STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
    waKKu@0xcd80$ ./ryu
    waKKu@0xcd80$ echo $?
    69
    waKKu@0xcd80$ # WORKS
    waKKu@0xcd80$ gcc -m32 -z noexecstack -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep GNU_STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
    waKKu@0xcd80$ ./ryu
    Segmentation fault
    waKKu@0xcd80$ echo $?
    139
    waKKu@0xcd80$ # DOESNT WORK - as expected
    

    4. The Innards

    a. Stack Execution Allowed:

    waKKu@0xcd80$ gcc -ggdb -m32 -z execstack -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep GNU_STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4
    waKKu@0xcd80$ gdb -q ./ryu
    Reading symbols from /home/waKKu/0xcd80/posts/NX-Stack/ryu...done.
    (gdb) break main
    Breakpoint 1 at 0x804839d: file ryu.c, line 9.
    (gdb) r
    Starting program: /home/waKKu/0xcd80/ryu
    
    Breakpoint 1, main () at ryu.c:9
    9	        strncpy(shellcode, "\x31\xc0\x40\x31\xdb\xb3\x45\xcd\x80", 9); // write the exit shellcode
    Missing separate debuginfos, use: debuginfo-install glibc-2.14-5.i686
    (gdb) shell pidof ryu
    4204
    (gdb) shell grep stack /proc/4204/maps
    fffdd000-ffffe000 rwxp 00000000 00:00 0                                  [stack]
    (gdb) # STACK AREA => from 0xfffdd000 upto 0xffffe000
    (gdb) disass
    Dump of assembler code for function main:
       0x08048394 :	push   %ebp
       0x08048395 :	mov    %esp,%ebp
       0x08048397 :	and    $0xfffffff0,%esp
       0x0804839a :	sub    $0x10,%esp
    => 0x0804839d :	mov    $0x80484a8,%edx
       0x080483a2 :	lea    0x2(%esp),%eax
       0x080483a6 :	mov    (%edx),%ecx
       0x080483a8 :	mov    %ecx,(%eax)
       0x080483aa :	mov    0x4(%edx),%ecx
       0x080483ad :	mov    %ecx,0x4(%eax)
       0x080483b0 :	movzbl 0x8(%edx),%edx
       0x080483b4 :	mov    %dl,0x8(%eax)
       0x080483b7 :	movb   $0x0,0xb(%esp)
       0x080483bc :	lea    0x2(%esp),%eax
       0x080483c0 :	mov    %eax,0xc(%esp)
       0x080483c4 :	mov    0xc(%esp),%eax
       0x080483c8 :	call   *%eax
       0x080483ca :	leave
       0x080483cb :	ret
    End of assembler dump.
    (gdb) # The most important line here is "037 (call *%eax)". It is where our execution flow is deviated to the stack.
    (gdb) # let's set a breakpoint nearby there...
    (gdb) break *main+48
    Breakpoint 2 at 0x80483c4: file ryu.c, line 12.
    (gdb) continue
    Continuing.
    
    Breakpoint 2, main () at ryu.c:12
    12	        ret(); // Once we have our pointer, we call it from the stack
    (gdb) x/4i $eip
    => 0x80483c4 :	mov    0xc(%esp),%eax
       0x80483c8 :	call   *%eax
       0x80483ca :	leave
       0x80483cb :	ret
    (gdb) #  is adjusting our %eax to point to the beginning of our shellcode
    (gdb) x/x $esp+0xc
    0xffffd2cc:	0xffffd2c2
    (gdb) i r eax
    eax            0xffffd2c2	-11582
    (gdb) x/5i $eax
       0xffffd2c2:	xor    %eax,%eax
       0xffffd2c4:	inc    %eax
       0xffffd2c5:	xor    %ebx,%ebx
       0xffffd2c7:	mov    $0x45,%bl
       0xffffd2c9:	int    $0x80
    (gdb) # this is our exit(69) shellcode...
    (gdb) nexti
    0x080483c8	12	        ret(); // Once we have our pointer, we call it from the stack
    (gdb) x/3i $eip
    => 0x80483c8 :	call   *%eax
       0x80483ca :	leave
       0x80483cb :	ret
    (gdb) # at this time, call will replace the value on EIP with the value of EAX (our shellcode)
    (gdb) i r eax eip
    eax            0xffffd2c2	-11582
    eip            0x80483c8	0x80483c8
    (gdb) nexti
    0xffffd2c2 in ?? ()
    (gdb) i r eax eip
    eax            0xffffd2c2	-11582
    eip            0xffffd2c2	0xffffd2c2
    (gdb) x/5i $eip
    => 0xffffd2c2:	xor    %eax,%eax
       0xffffd2c4:	inc    %eax
       0xffffd2c5:	xor    %ebx,%ebx
       0xffffd2c7:	mov    $0x45,%bl
       0xffffd2c9:	int    $0x80
    (gdb) # So, at this time EIP points to the stack, and is ready to execute instructions from it. Thus, allowing our stack-placed shellcode to execute.
    (gdb) i r eax
    eax            0xffffd2c2	-11582
    (gdb) nexti
    0xffffd2c4 in ?? ()
    (gdb) i r eax
    eax            0x0	0
    (gdb) # No problem to execute anything from the stack...
    (gdb) continue
    Continuing.
    [Inferior 1 (process 3167) exited with code 0105]
    (gdb) p /d 0105
    $5 = 69
    (gdb) # Shellcode executed successfully - from the stack...
    (gdb) quit
    

    b. Stack Execution NOT Allowed:

    waKKu@0xcd80$ gcc -ggdb -m32 -z noexecstack -o ryu ryu.c
    waKKu@0xcd80$ readelf -l ryu | grep GNU_STACK
      GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x4
    waKKu@0xcd80$ gdb -q ./ryu
    Reading symbols from /home/waKKu/0xcd80/ryu...done.
    (gdb) break main
    Breakpoint 1 at 0x804839d: file ryu.c, line 9.
    (gdb) run
    Starting program: /home/waKKu/0xcd80/ryu
    
    Breakpoint 1, main () at ryu.c:9
    9	        strncpy(shellcode, "\x31\xc0\x40\x31\xdb\xb3\x45\xcd\x80", 9); // write the exit shellcode
    Missing separate debuginfos, use: debuginfo-install glibc-2.14-5.i686
    (gdb) disass
    Dump of assembler code for function main:
       0x08048394 :	push   %ebp
       0x08048395 :	mov    %esp,%ebp
       0x08048397 :	and    $0xfffffff0,%esp
       0x0804839a :	sub    $0x10,%esp
    => 0x0804839d :	mov    $0x80484a8,%edx
       0x080483a2 :	lea    0x2(%esp),%eax
       0x080483a6 :	mov    (%edx),%ecx
       0x080483a8 :	mov    %ecx,(%eax)
       0x080483aa :	mov    0x4(%edx),%ecx
       0x080483ad :	mov    %ecx,0x4(%eax)
       0x080483b0 :	movzbl 0x8(%edx),%edx
       0x080483b4 :	mov    %dl,0x8(%eax)
       0x080483b7 :	movb   $0x0,0xb(%esp)
       0x080483bc :	lea    0x2(%esp),%eax
       0x080483c0 :	mov    %eax,0xc(%esp)
       0x080483c4 :	mov    0xc(%esp),%eax
       0x080483c8 :	call   *%eax
       0x080483ca :	leave
       0x080483cb :	ret
    End of assembler dump.
    (gdb) break *main+48
    Breakpoint 2 at 0x80483c4: file ryu.c, line 12.
    (gdb) c
    Continuing.
    
    Breakpoint 2, main () at ryu.c:12
    12	        ret(); // Once we have our pointer, we call it from the stack
    (gdb) x/4i $eip
    => 0x80483c4 :	mov    0xc(%esp),%eax
       0x80483c8 :	call   *%eax
       0x80483ca :	leave
       0x80483cb :	ret
    (gdb) # All the same here...  adjust EAX,  calls it
    (gdb) x/x $esp+0xc
    0xffffd2cc:	0xffffd2c2
    (gdb) p &shellcode
    $1 = (char (*)[10]) 0xffffd2c2
    (gdb) nexti
    0x080483c8	12	        ret(); // Once we have our pointer, we call it from the stack
    (gdb) i r eax
    eax            0xffffd2c2	-11582
    (gdb) x/3i $eip
    => 0x80483c8 :	call   *%eax
       0x80483ca :	leave
       0x80483cb :	ret
    (gdb) i r eip eax
    eip            0x80483c8	0x80483c8
    eax            0xffffd2c2	-11582
    (gdb) nexti
    0xffffd2c2 in ?? ()
    (gdb) i r eip eax
    eip            0xffffd2c2	0xffffd2c2
    eax            0xffffd2c2	-11582
    (gdb) x/5i $eip
    => 0xffffd2c2:	xor    %eax,%eax
       0xffffd2c4:	inc    %eax
       0xffffd2c5:	xor    %ebx,%ebx
       0xffffd2c7:	mov    $0x45,%bl
       0xffffd2c9:	int    $0x80
    (gdb) # Again, we are on the point to exec our shellcode - from the stack...
    (gdb) nexti
    
    Program received signal SIGSEGV, Segmentation fault.
    0xffffd2c2 in ?? ()
    (gdb) # No luck this time :( ...
    (gdb) quit
    waKKu@0xcd80$
    

    5. Conclusion

    Well, all this text just (trying) to show HOW and WHEN exactly the NX bit takes place to protect our programs…

    That’s all folks, cya.

    –waKKu

    Advertisements

    Posted November 24, 2011 by waKKu in Assembly, Exploiting, Programming, Security

    4 responses to “Non-eXec Stack – Analysis

    Subscribe to comments with RSS.

    1. Is this prevent code execution on heap too?

      • Hey Coco,

        Well, that depends.. HEAP has its own protection, it uses the same idea with a NX bit within PTE.
        On Windows the heap protection is called DEP (Data Execution Prevention), on Linux it’s pretty much the same, we have PT_GNU_STACK and PT_GNU_HEAP as ELF headers and PaX has its own way to do this job.

    2. i didn’t see any PT_GNU_HEAP header but if i make char shellcode[] to static (shellcode placed on heap) everything is worked like in previous situation.

      • Hey coco,

        Well, this things I wrote are specific to stack, however, if you want to go deeper with this HEAP thing, I recommend you install the “ht” package, it is an editor which has some properties about ELF.
        Install ht, open your binary there, press f6 (mode) and choose ELF section headers, choose a header and go over “details”.
        There you can check all binary flags, writeable, readable, executable, etc.

        On my Fedora 16, for a simple C code, heap and stack are non-exec by default. But I believe it may vary from distro to distro.

        Let me know if you find something interesting. See you.


        waKKu

    Leave a Reply

    Fill in your details below or click an icon to log in:

    WordPress.com Logo

    You are commenting using your WordPress.com account. Log Out / Change )

    Twitter picture

    You are commenting using your Twitter account. Log Out / Change )

    Facebook photo

    You are commenting using your Facebook account. Log Out / Change )

    Google+ photo

    You are commenting using your Google+ account. Log Out / Change )

    Connecting to %s

    %d bloggers like this: