Search code examples
carrayspointersshellcode

Difference between declaring shellcode as a char[] array and char*?


Hi all,

I'm trying to learn basic shellcoding and I've run across something curious that I hope someone can explain to me. I've compiled the following code two ways: declaring the shellcode as an array and as a char*. When I declare shellcode as an array, linux detects that I am trying to execute data and I get a segfault on the first instruction. However, when I declare shellcode as a char* all of the shellcode executes and I get a "Hello world!". How does the compiler treat these two declarations differently and why does one end in shellcode that lives in memory that is unprotected? Thanks in advance.

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

/* This declaration ends in a segfault */
//char shellcode[] =

/* This declaration ends in successful execution */
char* shellcode = 

/* Shellcode prints "Hello world!" and exits */    
"\xeb\x1f\x48\x31\xc0\x48\x31\xdb\x48\x31\xc9\x48\x31\xd2\xb0\x04\xb3\x01\x59\xb2\x0c\xcd\x80\x48\x31\xc0\xb0\x01\x48\x31\xdb\xcd\x80\xe8\xdc\xff\xff\xff\x48\x65\x6c\x6c\x6f\x20\x57\x6f\x72\x6c\x64\x21";

int main()
{
    void (*f)();
    f = (void (*)())shellcode;
    (void)(*f)();
}

Solution

  • When you declare it as a char[], the memory is on the stack. When you declare it as a char* and assign it a string literal, the memory is in the executable image itself. Linux doesn't like you executing code on the stack, but is fine with you executing memory in that part of the executable image. That is because it is trying to avoid a certain type of stack overflow attack where people can overflow the stack with some arbitrary instructions and then execute them.

    You can use mprotect on Linux to set the permissions for a region of memory or VirtualProtectEx on Windows. That way you can explicitly set the permissions of the memory to be executable.