tags:

views:

74

answers:

4

Hi,

I'm currently learning how to write shellcode and get a GCC warning "assignment of incompatible pointer type". Why?

Greetings, LM


char shellcode[] = 
  "\x31\xc0"
  "\xb0\x01"
  "\x31\xdb"
  "\xcd\x80";


int main() {
  void (*func)() = shellcode;

  func();

  return 0;
}
A: 

Because char[] is incompatible with void(*)()!! What on earth would that even mean?

Oli Charlesworth
Well, they're both pointers. An explicit cast will do the trick. What would it mean? It would mean that the `char[]` contains something that will be run as a function.
You
You might get away with this with a given compiler, but it is undefined behavior and generally frowned upon.
Jens Gustedt
@Oli Charlesworth "What on earth would that even mean?" -- I believe the OP is trying to learn how to be an "31337 h4x0r" by getting the computer to execute the machine code in the `char[]`, perhaps with the intention of using it in a buffer overflow attack. (That's what "shellcode" means in this context.) One can only hope it's for educational purposes only. ;)
David
Yes it is, I'm currently exploring the fundamentals of the buffer overflow attack. I intent no harm, just want to know how these things work, don't worry.
Laughingman
Now, **this** is interesting!
ysap
+1  A: 

There is no implicit conversion of object pointers to function pointers. You'll need an explicit cast (void(*)()) (and even that isn't guaranteed to work, or compile).

caf
+2  A: 
Laughingman
It could be improved with a typedef, otherwise it was exactly was I was about to answer :-)
Christoffer
Don't do that, really. Look into your compiler manual and learn how to include assembler code into a function, I guess all mondern compilers should have such an extension. Or if your compiler doesn't have that, just write your code as assembler and link to the object that you define.
Jens Gustedt
+2  A: 

I'll write my suggestion as an answer and whore for some reputation :-)

You need to explicitly cast the data pointer into a function pointer. With a typedef for the appropriate function pointer, you can do so without making the code too hard to read:

char shellcode[] = 
    "\x31\xc0"
    "\xb0\x01"
    "\x31\xdb"
    "\xcd\x80";

typedef void (*SHELLCODE)(void);

int main() {
    SHELLCODE func = (SHELLCODE) shellcode;
    func();

    /* ...and this will work as well, which some might find more readable: */
    ((SHELLCODE) shellcode)();

    return 0;
}

This compiles cleanly with clang 1.1, but GCC 4.4.3 will still give you a warning about the pointer conversion -- although now it is a more precise warning:

$ gcc -Wall -Wextra -ansi -pedantic shellcode.c 
shellcode.c: In function ‘main’:
shellcode.c:10: warning: ISO C forbids conversion of object pointer to function pointer type
shellcode.c:14: warning: ISO C forbids conversion of object pointer to function pointer type

Skipping the "-pedantic" flag will make it compile cleanly with GCC too, but who ever does that seriously?

Christoffer