0

解決しようとしている特定の問題があります。クラスのメソッドの場所 (メモリ内) を見つける必要があります。メソッドへのポインタが処理されるため、構文制約にぶつかったと思いますmember pointer 例:

class Foo {
public:
  int targetFunction(int value) { return value + 5; }
};

DWORD findLocation() { // ignore the fact that DWORD might not equal pointer size.
  int (Foo::*address)(int) = &(Foo::targetFunction); // member function pointer
  void* typeHide = (void*)&address; // Remove type
  DWORD targetAddress = *(DWORD*)typeHide; // Convert type from void* to DWORD* and dereference to DWORD
  return targetAddress;
}

int (Foo::*address)(int) = のように書くこともできます auto address =

現在、VS2008では、Foo::targetFunctionのアドレスは「0x000F B890」ですが、&Foo::targetFunction「0x000F 1762」と表示されています

まず、メンバー ポインターは、メンバー ポインター演算子.*およびを使用して正しく機能します->*。targetAddress をメンバー ポインターにキャストしても、まだ機能します。

第二に、場所はサンク関数にすることができます!

最後に、VS2008 のデバッガーを使用して targetFunction の値をmember pointerのアドレス 1762 から VS デバッガーが報告する値 B890 に変更すると、私のコードは正しく動作します!

メンバー ポインター値 (1762) の代わりにアドレス値 (B890) を取得する C++ 固有の方法はありますか?


リクエストに応じて、私が機能させようとしているコードは次のとおりです。

BYTE overwriteStorage[300][2];

void NOP(void)
{
  // hackish, but works for now.
}

void disableOlderVersions(DWORD _address, int index)
{
    //...
    _address = findLocation();

DWORD protectionStorage = 0;

VirtualProtect((void *)_address, 1+4, PAGE_WRITECOPY, &protectionStorage); // windows.h: Make Read/Write the location in code
{
    BYTE *edit = (BYTE*)_address;
    overwriteStorage[index][0] = *(edit+0); // store previous value to revert if needed
    *(edit+0) = 0XE9; // JUMP (32-bit)

    overwriteStorage[index][1] = *(edit+1); // store second value
    signed int correctOffset = (signed int)NOP - (signed int)_address - 5; // calculate 0xE9 relative jump
    *(signed int*)(edit+1) = correctOffset; // set jump target
}
VirtualProtect((void *)_address, 1+4, PAGE_EXECUTE, &protectionStorage);
}

findLocationfrom aの最初の行をmember pointer実際のに置き換えると、function pointer完全に機能します。ただし、いくつかのクラスメソッドに対しても読み書きする必要があります。このメソッドは奇妙なmember pointers によって壊れています。

また、いくつかのローカル関数が正しいアドレスを報告しないこともありました (最近)。コンパイラの動作に制約されずに関数アドレスを見つける別の方法はありますか?

4

1 に答える 1

2

メンバー関数呼び出しを単一の関数ポインターに圧縮しようとしているようです。不可能です。

覚えて:

Object x;
x.a(1);

実際にはの略です

a(&x /*this*/, 1 /*arg1, ... */); //approximation, leprechauns may be involved in actual implementations.

その最初の議論は重要です、それは「これ」になるでしょう。

したがって、次のようなことはできません。

class Object {
public:
    void f(int);
}

typedef void (*FNPTR)(int);
Object a;
void (Object::* memberFuncPtr)(int);
void* nerfedPtr = (void*)memberFuncPtrl
FNPTR funcPtr = static_cast<FNPTR>(nerfedPtr);
funcPtr(1);

オブジェクトコンテキストのメンバー関数を奪ったためです。

関数のアドレスとインスタンスのアドレスの両方がなければ、オブジェクト メンバー関数を呼び出す方法はありません。

于 2013-11-10T07:49:10.070 に答える