2
void foo(int a)
{ printf ("In foo, a = %d\n", a); }

unsigned char code[9];
* ((DWORD *) &code[0]) = 0x042444FF; /* inc dword ptr [esp+4] */
              code[4]  = 0xe9;       /* JMP */
* ((DWORD *) &code[5]) = (DWORD) &foo - (DWORD) &code[0] - 9; 
void (*pf)(int/* a*/) = (void (*)(int)) &code[0];
pf (6);

6上記のコードのどこで?がインクリメントされるかは誰でも知っています1か?

4

1 に答える 1

3

foo()、およびサンクは__cdecl、呼び出し元の変換を使用します。これには、呼び出し元がパラメーターをスタックにプッシュする必要があります。したがって、pf(6)が呼び出されると、命令6によってスタックにプッシュされ、PUSH 6命令によってサンクが入力されCALL pfます。6スタック上で占有するメモリESP+4は、サンクが入力された時点、つまり、スタック ポインタ レジスタの現在の値から 4 バイトの位置にありますESP。サンクの最初の命令は、 が指す値をインクリメントすることですESP+4。したがって、値 '6' は '7' にインクリメントされます。 foo()その後、サンクのJMP foo命令によって入力されます。 サンクが変更されたため、元のパラメーターではなく、foo()そのaパラメーターが表示されます76foo()の呼び出しスタック。

于 2010-09-15T05:02:01.357 に答える