3

リターン アドレスを返すインライン アセンブリ関数を C++ コードで記述したいとします。

したがって、関数 returnAddress() をあるアドレスから呼び出していて、関数が終了した後にアドレス X に戻る必要がある場合、returnAddress() が値 X を返すようにします。

returnAddress() のコード例:

void* getAddress()
{
    __asm {
        pop ebx;     // moving return offset to ebx?
        push ebx;    // restoring stack state
        xor eax, eax;
        mov ax, cs;  // ax <- code segment
        mov ecx, 16;
        mul ecx;     // multiplying the code segment by 16
        add eax, ebx;// adding offset
    }
}

前のコードは正しく動作しません。alt+8 を押すと、コードのアドレスがこの関数の戻り値と完全に異なることがはっきりとわかります。

メモリ内のコードのアドレスを見つけたいのは、コード自体の実行中にアドレスを変更しようとするためです。インライン アセンブリを使用せずに (おそらく Windows API を使用して) コードのアドレスを見つける方法が他にある場合は、お知らせください。

また、Visual Studio 2010 を使用して CS (コード セグメント) の値を使用することさえできないと確信しているので、おそらくそれが問題の原因です... CS は常に 35 に等しくなります。アセンブリ ビュー (alt+8) は正しく表示されませんか? VS2010 は仮想マシンを実行するため、アドレスは?

これは私の最初の投稿なので、私の主張をあまり明確にしていない可能性があります。より明確にするために自分自身を説明できるかどうか教えてください。

4

2 に答える 2

4

コード セグメントは、16 ビット システムでのみ使用されます。32 ビットの導入により、コード セグメントはなくなりました。

VisualStudio の組み込み_ReturnAddress()関数を使用できます。

void * _ReturnAddress(void);
#pragma intrinsic(_ReturnAddress)

void* getAddress()
{
    return _ReturnAddress();
}

VisualStudio 以外のコンパイラなどで手動で実行する場合、32 ビット x86 関数呼び出しのコール スタックには完全な 32 ビットの戻りアドレスが含まれているため、そのまま返すことができます。

void* __declspec(naked) getAddress()
{
    asm
    {
        mov eax, [esp];
        ret;
    }
}

x64 関数呼び出しの場合、同等の 64 ビット レジスタを使用できるはずです。

void* __declspec(naked) getAddress()
{
    asm
    {
        mov rax, [rsp];
        ret;
    }
}
于 2012-11-01T21:20:33.273 に答える
4

実は、私はあなたが返送先住所を復元するためだけに使用しているミステリーを理解するのに苦労しました. 一部の人が示唆したように、組み込みを使用できます_ReturnAddress。それでも、楽しみのために、次の簡単なコードを使用できます。

__declspec(naked) 
void* get_RetAddr()
{
    _asm {
        mov eax, [esp]
        ret
    }
}
于 2012-11-01T21:09:52.177 に答える