11

私がこのようなことをしていると想像してください:

void *p = malloc (1000);
*((char*)p) = some_opcode;
*((char*)p+1) = another_opcode; // for the sake of the example: the opcodes are ok

....
etc...

関数であるかのように p を呼び出す関数ポインタを定義するにはどうすればよいですか? (私は VC++ 2008 Express を使用しています)。

ありがとう

4

4 に答える 4

12

実際、malloc はおそらくそれをカットしません。Windows では、おそらく [VirtualAlloc]( http://msdn.microsoft.com/en-us/library/aa366887(VS.85).aspx)のようなものを呼び出して、メモリの実行可能なページを取得する必要があります。

小さく始める:

void main(void)
{
    char* p = (char*)VirtualAlloc(NULL, 4096, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    p[0] = (char)0xC3;  // ret

    typedef void (*functype)();
    functype func = (functype)p;
    (*func)();
}

コードをうまく操作するための次のステップは、EBP レジスターを保存することです。これは練習問題として残します。:-)

これを書いた後、mallocで実行しましたが、うまくいきました。Windows 2000 Server で管理者アカウントを実行していることが原因である可能性があります。他のバージョンの Windows では、VirtualAlloc 呼び出しが実際に必要になる場合があります。知るか。

于 2008-12-29T03:52:15.510 に答える
12

コメントのスペースが足りませんでした。Joe_Muc は正しいです。mallocまたはによって取得されたメモリにコードを詰め込むべきではありませんnew。Windows が割り当てるページのページ プロパティを変更すると、問題が発生します。

VirtualAlloc() と関連する WIn32 API を使用するのは簡単なので、これは問題ではありません: VirtualAlloc( ) を呼び出してflProtect[PAGE_EXECUTE_READWRITE][2]

おそらく、1 つのガード ページ、コードに必要なページ、そして別のガード ページの 3 つの割り当てを行う必要があることに注意してください。これにより、悪いコードから少し保護されます。

また、構造化された例外処理を使用して、生成されたコードへの呼び出しをラップします。

次に、Windows X86 ABI (呼び出し規約) は十分に文書化されていません (私は知っています、私は見ました)。ここにいくつかの情報があります ここここここ 物事がどのように機能するかを確認する最良の方法は、コンパイラによって生成されたコードを見ることです。これは、スイッチを使用して簡単に行うことができます (\FAスイッチは 4 つあります)。

64 ビットの呼び出し規約については、こちらを参照してください。

また、Microsoft の Macro Assembler MASM は、ここから入手できます。MASM でマシン コードを記述し、その出力を確認してから、マシン コード ジェネレーターで同様のことを行うことをお勧めします。

IntelおよびAMD のプロセッサ マニュアルは参考になります。お持ちでない場合は入手してください。

于 2008-12-29T05:20:30.137 に答える
6

適切なオペコードが配置されている場合、呼び出しは、関数ポインターにキャストして呼び出すのと同じくらい簡単です。

typedef void (*voidFunc)();

char *p = malloc (1000);
p[0] = some_opcode;
p[1] = another_opcode; // for the sake of the example: the opcodes are ok
p[n] = // return opcode...

((voidFunc)p)();

ただし、ページを実行可能としてマークしない限り、ヒープ上で生成されたコードをプロセッサが実行できない可能性があることに注意してください。

于 2008-12-29T03:14:15.743 に答える
0

私は現在、生成されたコードの実行も検討しています。ここでの回答では、必要なものが正確に得られませんでしたが、皆さんは私を正しい軌道に乗せてくれました。

ページを POSIX システム (Linux、BSD など) で実行可能としてマークする必要がある場合は、mmap(2) 関数を確認してください。

于 2012-01-12T22:28:43.797 に答える