Выполнение shellcode путем приведения к указателю функции в Visual C++

в gcc это работает нормально. Код звучит примерно так:

unsigned char b[50] = "xdaxd1 ... 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

кто-нибудь знает, почему это так?

2 ответов


правильный отладчик скажет вам, что происходит неправильно. Я могу только догадываться, что ваш код вызывает нарушение доступа, потому что буфер, к которому вы хотите перейти, не является исполняемым.

Вероятно, вы находитесь по умолчанию -DEP-включена система, такая как Vista или 7, поэтому вы должны убедиться, что ваш shellcode является исполняемым. Для этого сначала используйте VirtualAlloc чтобы выделить новый исполняемый буфер и скопировать в него шеллкод, выполните его:

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

кстати, вам не нужно null-terminate shellcode (C++ автоматически завершит строковый литерал для вас, но это не обязательно). Вам также не нужно указывать размер:

unsigned char b[] = "\xcc";

типичный способ переинтерпретировать данные как другой тип-скопировать двоичное представление:

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

это позволяет избежать неопределенного поведения, вызванного нарушениями сглаживания и выравнивания.