簡體   English   中英

C ++,如何找到成員函數的地址?

[英]C++, how do I find the address of a member function?

我有一個特定的問題,我想解決,我需要找到一個類的方法的位置(在內存中)。 我想我已經達到語法約束,因為指向方法的指針作為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是“ &Foo::targetFunction 1762

首先,成員指針使用成員指針運算符正確工作.*->* 如果我將targetAddress轉發回成員指針,它仍然有效!

第二,位置可以是一個thunk功能!

最后,如果我使用VS2008的調試器將targetFunction的值從member pointer的地址1762更改為VS調試器報告的值B890,我的代碼可以正常工作!

是否有一種特定於C ++的方法來獲取地址值(B890)而不是成員指針值(1762)?


根據要求,這是我正在努力工作的代碼:

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);
}

如果我將findLocation的第一行從member pointer替換為實際的function pointer它可以完美地工作。 但是,我需要讀取和寫入幾個類方法,這個方法被奇數member pointer s打破。

另外,我有一些本地功能也沒有報告正確的地址(最近)。 是否有其他方法可以在不受編譯器行為約束的情況下查找函數地址?

聽起來你正在嘗試將成員函數調用壓縮為單個函數指針。 這是不可能的。

記得:

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);

因為你已經搶奪了它的對象上下文的成員函數。

如果沒有函數的地址和實例的地址,就無法調用對象成員函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM