7

在 gcc 中,这工作正常。代码类似于:

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

但是当它被放入 Visual C++ 中时,它会吐出以下错误消息:

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

有谁知道为什么会这样?

4

2 回答 2

13

适当的调试器会告诉您出了什么问题。我只能猜测您的代码导致访问冲突,因为您要跳转到的缓冲区不可执行。

可能您使用的是默认启用DEP的系统,例如 Vista 或 7,因此您必须确保您的 shellcode 是可执行的。为此,首先使用VirtualAlloc分配一个新的可执行缓冲区并将您的 shellcode 复制到其中,然后执行它:

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

顺便说一句,您不需要以空值终止 shellcode(C++ 会自动为您终止字符串文字,但这不是必需的)。您也不需要指定大小:

unsigned char b[] = "\xcc";
于 2012-03-06T23:29:14.737 回答
1

将数据重新解释为不同类型的典型方法是复制二进制表示:

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

这避免了由混叠和对齐违规引起的未定义行为。

于 2012-03-06T23:07:14.787 回答