Что значит "использование VirtualFn1_t = void (__ thiscall *) (void * thisptr);" значит в с ++? - PullRequest
0 голосов
/ 13 апреля 2020

Я пытаюсь понять перехват при чтении исходного кода. Для перехвата таблиц методов виртуальных функций из википедии я наткнулся на эту строку.

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

Ответы [ 2 ]

2 голосов
/ 13 апреля 2020

VirtualFn1_t определяется как псевдоним для следующего типа: указатель на функцию, принимающую параметр void*, возвращающий void и использующий __thiscall соглашение о вызовах.

1 голос
/ 13 апреля 2020

Начиная с 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() hook.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...