Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Execute shellcode by casting to function pointer in Visual C++

In gcc this works fine. The code goes something like:

unsigned char b[50] = "\xda\xd1 ... \x0"; //some shellcode with terminating \x0
( (void(*)())b )(); //cast b to function pointer from void to void, then run it

But when this is put in Visual C++, it spits out this error message:

1>..\test.cpp(132): error C2440: 'type cast' : cannot convert from 'unsigned char [50]' to 'void (__cdecl *)(void)'
1>          There is no context in which this conversion is possible

Anyone know why this is so?

like image 803
jcai Avatar asked Mar 06 '12 22:03

jcai


2 Answers

A proper debugger will tell you what's going wrong. I can only guess that your code is causing an access violation because the buffer you want to jump to is not executable.

Probably you're on a default-DEP-enabled system like Vista or 7, so you have to make sure that your shellcode is executable. To do that, first use VirtualAlloc to allocate a new, executable buffer and copy your shellcode into it, then execute it:

void *exec = VirtualAlloc(0, sizeof b, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, b, sizeof b);
((void(*)())exec)();

By the way, you don't need to null-terminate the shellcode (C++ will terminate the string literal automatically for you, but this is not necessary). You also don't need to specify a size:

unsigned char b[] = "\xcc";
like image 112
Niklas B. Avatar answered Oct 05 '22 22:10

Niklas B.


The typical way to reinterpret data as a different type is by copying the binary representation:

void (*fp)();
unsigned char buf[50];
char const * p = reinterpret_cast<char const *>(&buf);

std::copy(p, p + sizeof(char const *), reinterpret_cast<char*>(&fp));

// now fp contains the same value as &buf

fp();  // call

This avoids undefined behaviour caused by aliasing and alignment violations.

like image 42
Kerrek SB Avatar answered Oct 05 '22 23:10

Kerrek SB