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

適切なデバッガーは、何が問題なのかを教えてくれます。ジャンプ先のバッファが実行可能でないため、コードがアクセス違反を引き起こしていると推測できます。

おそらく、Vista や 7 などのデフォルトのDEP対応システムを使用しているため、シェルコードが実行可能であることを確認する必要があります。これを行うには、まず を使用VirtualAllocして新しい実行可能バッファを割り当て、シェルコードをそこにコピーしてから実行します。

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

ところで、シェルコードを null で終了する必要はありません (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 に答える