0

I have downloaded and compiled Apples source and added it to Xcode.app/Contents/Developer/usr/bin/include/c++/v1. Now how do I go about implementing in C? The code I am working with is from this post about Hackadays shellcode executer. My code is currently like so:

#include <stdio.h>
#include <stdlib.h>

unsigned char shellcode[] = "\x31\xFA......";

int main()
{
  int *ret;
  ret = (int *)&ret + 2;
  (*ret) = (int)shellcode;
  printf("2\n");
}

I have compiled with both:

gcc -fno-stack-protector shell.c
clang -fno-stack-protector shell.c

I guess my final question is, how do I tell the compiler to implement "__enable_execute_stack"?

Community
  • 1
  • 1
Jlegend
  • 531
  • 1
  • 6
  • 19

2 Answers2

2

The stack protector is different from an executable stack. That introduces canaries to detect when the stack has been corrupted.

To get an executable stack, you have to link saying to use an executable stack. It goes without saying that this is a bad idea as it makes attacks easier.

The option for the linker is -allow_stack_execute, which turns into the gcc/clang command line:

clang -Wl,-allow_stack_execute -fno-stack-protector shell.c

your code, however, does not try to execute code on the stack, but it does attempt to change a small amount of the stack content, trying to accomplish a return to the shellcode, which is one of the most common ROP attacks.

On a typically compiled OSX 32bit environment this would be attempting to overwrite what is called the linkage area (this is the address of the next instruction that will be called upon function return). This assumes that the code was not compiled with -fomit-frame-pointer. If it's compiled with this option, then you're actually moving one extra address up.

On OSX 64bit it uses the 64bit ABI, the registers are 64bit, and all the values would need to be referenced by long rather than by int, however the manner is similar.

The shellcode you've got there, though, is actually in the data segment of your code (because it's a char [] it means that it's readable/writable, not readable-executable. You would need to either mmap it (like nneonneo's answer) or copy it into the now-executable stack, get it's address and call it that way.

However, if you're just trying to get code to run, then nneonneo's answer makes it pretty easy, but if you're trying to experiment with exploit-y code, then you're going to have to do a little more work. Because of the non-executable stack, the new kids use return-to-library mechanisms, trying to get the return to call, say, one of the exec/system calls with data from the stack.

Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
  • It's worth noting that the poster **is** attempting to corrupt his own stack by writing over the saved EIP. (Whether this works or not depends on the optimization settings, frame layout, stack alignment, and possibly other factors). So, turning off stack protection _might_ be necessary. (although, since `main` lacks a stack buffer, it may not have a stack protector at all). – nneonneo Jun 24 '15 at 08:07
0

With modern execution protections in place, it's a bit tricky to get shellcode to run like this. Note that your code is not attempting to execute code on the stack; rather, it is storing the address of the shellcode on the stack, and the actual code is in the program's data segment.

You've got a couple options to make it work:

  1. Put the shellcode in an actual executable section, so it is executable code. You can do this with __attribute__((section("name"))) with GCC and Clang. On OS X:

    const char code[] __attribute__((section("__TEXT,__text"))) = "...";
    

    followed by a

    ((void (*)(void))code)();
    

    works great. On Linux, use the section name ".text" instead.

  2. Use mmap to create a read-write section of memory, copy your shellcode, then mprotect it so it has read-execute permissions, then execute it. This is how modern JITs execute dynamically-generated code. An example:

    #include <sys/mman.h>
    
    void execute_code(const void *code, size_t codesize) {
        size_t pagesize = (codesize + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1);
        void *chunk = mmap(NULL, pagesize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANON, -1, 0);
        if(chunk == MAP_FAILED) return;
        memcpy(chunk, code, codesize);
        mprotect(chunk, pagesize, PROT_READ|PROT_EXEC);
        ((void (*)(void)chunk)();
        munmap(chunk, pagesize);
    }
    

Neither of these methods requires you to specify any special compiler flags to work properly, and neither of them require fiddling with the saved EIP on the stack.

nneonneo
  • 171,345
  • 36
  • 312
  • 383