【问题标题】:What does "using VirtualFn1_t = void(__thiscall*)(void* thisptr);" means in c++?“使用 VirtualFn1_t = void(__thiscall*)(void* thisptr);”是什么意思在 C++ 中是什么意思?
【发布时间】:2020-04-13 14:29:34
【问题描述】:

我在阅读源代码时试图理解挂钩对于来自维基百科的虚函数方法表挂钩,我遇到了这一行。

using VirtualFn1_t = void(__thiscall*)(void* thisptr);

我不知道这是什么意思。是否将 void 指针转换为调用约定并将其重新转换为 void 指针并将其用作 VirtualFn1_t 别名。我也想了解void (__thiscall*)(void* thisptr)(__thiscall*)(void* thisptr)是什么意思。

这是来自维基百科的完整来源。

#include <iostream>
#include "windows.h"

using namespace std;

class VirtualClass
{
public:

    int number;

    virtual void VirtualFn1() //This is the virtual function that will be hooked.
    {
        cout << "VirtualFn1 called " << number++ << "\n\n";
    }
};




using VirtualFn1_t = void(__thiscall*)(void* thisptr); 
VirtualFn1_t orig_VirtualFn1;


void __fastcall hkVirtualFn1(void* thisptr, int edx) //This is our hook function which we will cause the program to call instead of the original VirtualFn1 function after hooking is done.
{
    cout << "Hook function called" << "\n";

    orig_VirtualFn1(thisptr); //Call the original function.
}




int main()
{
    VirtualClass* myClass = new VirtualClass(); //Create a pointer to a dynamically allocated instance of VirtualClass.

    void** vTablePtr = *reinterpret_cast<void***>(myClass); //Find the address that points to the base of VirtualClass' VMT (which then points to VirtualFn1) and store it in vTablePtr.

    DWORD oldProtection;
    VirtualProtect(vTablePtr, 4, PAGE_EXECUTE_READWRITE, &oldProtection); //Removes page protection at the start of the VMT so we can overwrite its first pointer.

    orig_VirtualFn1 = reinterpret_cast<VirtualFn1_t>(*vTablePtr); //Stores the pointer to VirtualFn1 from the VMT in a global variable so that it can be accessed again later after its entry in the VMT has been 
                                                                  //overwritten with our hook function.

    *vTablePtr = &hkVirtualFn1; //Overwrite the pointer to VirtualFn1 within the virtual table to a pointer to our hook function (hkVirtualFn1).

    VirtualProtect(vTablePtr, 4, oldProtection, 0); //Restore old page protection.

    myClass->VirtualFn1(); //Call the virtual function from our class instance. Because it is now hooked, this will actually call our hook function (hkVirtualFn1).
    myClass->VirtualFn1();
    myClass->VirtualFn1();

    delete myClass;

    return 0;
}

【问题讨论】:

  • __thiscall 的文档。这个问题似乎不是关于 C 编程语言的,不应该有 c 标签。

标签: windows winapi hook


【解决方案1】:

自 C++11 起,using 是创建类型别名的新方法。它与typedef 相似(但更灵活)。

此问题中的using 语句:

using VirtualFn1_t = void(__thiscall*)(void* thisptr);

相当于这个typedef:

typedef void (__thiscall *VirtualFn1_t)(void* thisptr); 

两个语句都将VirtualFn1_t 定义为一个新类型,它是一个指针,指向一个函数:

  • void* 作为输入参数
  • 使用__thiscall 调用约定
  • 返回void

orig_VirtualFn1 被声明为VirtualFn1_t 类型的变量(因此orig_VirtualFn1 是一个指针),并且在运行时被指向原始VirtualClass::VirtualFn1() 方法的内存地址,在vtable(虚拟方法VirtualClass 类的表)被修改为使VirtualFn1() 的插槽指向hkVirtualFn1() 挂钩函数。

【讨论】:

  • 谢谢现在我已经完全了解VirtualFn1_t了。
【解决方案2】:

VirtualFn1_t 被定义为以下类型的别名:指向采用void* 参数、返回void 并使用__thiscall 调用约定的函数的指针。

【讨论】:

  • Igor Tandetnik,感谢您的回答。所以void(__thiscall*)(void* thisptr); 应该与void (__thiscall *void)(void * ptr); 相同,因为它们是关于函数指针的??
  • 不,不一样:void (__thiscall *void)(void *) 无法编译。试试看。
  • 我的意思是void (__thiscall *void)(void * ptr); 也是一个函数指针。
  • 不,void (__thiscall *void)(void * ptr); 没有意义并产生编译器错误。试试看。
  • 好吧,编译失败了。。谢谢,我明白了……
猜你喜欢
  • 2013-03-09
  • 1970-01-01
  • 2012-03-11
  • 1970-01-01
  • 2020-05-01
  • 1970-01-01
  • 2019-12-08
  • 2015-01-26
  • 1970-01-01
相关资源
最近更新 更多