Как использовать указатели функций для вызова функций-членов из адреса памяти? - PullRequest
0 голосов
/ 12 февраля 2019

Я разрабатываю патч для старого приложения, у владельцев которого больше нет кода src.

Я внедряю dll в .exe целевого приложения перед его main ().Эта dll устанавливает патчи, которые я сделал.

Приложение имеет пользовательский тип C ++ (класс или структуру), похожий на менеджер шрифтов чертежа, в котором есть функции, которые мне нужно вызывать через некоторые из этих патчей.

Обычно я называю эти "родные" функции-члены созданием функции-оболочки, которая вызывает встроенную функцию-член через asm inline.Я делаю это потому, что не могу понять, как это сделать с помощью указателей на функции C ++.

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

Этопример того, что я пытаюсь сделать:

/* NC for Native Class */
class NC_FontDevice
{
public:
    typedef void(NC_FontDevice::*_UseTexturesTransparency)();

    _UseTexturesTransparency *UseTexturesTransparency = reinterpret_cast<_UseTexturesTransparency*>(0x635FD0);

private:
    NC_FontDevice(){}
};

NC_FontDevice* GetFontDevice()
{
    NC_FontDevice* lpFontDevice = nullptr;

    /* 
        This asm inline block is here to show more or less what I do in those wrappers I told.
        I know this can be converted to a simple function pointer.
    */
    __asm
    {
        mov eax, 0x0041FE10
        call eax
        mov lpFontDevice, eax
    }

    return lpFontDevice;
}

void foo()
{
    auto lpFontDevice = GetFontDevice();

    // Here I get and "identifier X is undefined"
    (lpFontDevice->**UseTexturesTransparency)();
}

Если понятно, чего я хочу, есть ли лучший способ добиться этого, кроме обёрток функций?

Спасибо завперед.

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Одна из ваших проблем - по крайней мере, ваш код не соответствует вашему вопросу.Вы говорите о функциональных указателях, но пишете void(NC_FontDevice::*_UseTexturesTransparency)().То есть не указатель на функцию.Это указатель на функцию-член (PMF).Совершенно разные звери, и вы не можете предполагать, что это простые указатели.Как правило, они даже не одного размера.

Я подозреваю, что вы нашли функцию на 0x635FD0.Эта функция, вероятно, выглядит как void _UseTexturesTransparency(NC_FontDevice*).Конечно, это могло быть (частью) функции-члена, когда она была скомпилирована, но это не имеет значения.Это хакерство, мы здесь прагматичны.Зачем бороться со сложностями PMF, если мы можем рассматривать это как указатель на обычную функцию?

[править] В комментариях MSVC ++ будет использовать ECX для аргумента this в функциях-членах;как это происходит, он также поддерживает соглашение о вызовах __fastcall для обычных функций, которое помещает первый 32-битный аргумент в ECX.Это не идеальная замена;__fastcall также использует EDX для второго аргумента.Там вам может понадобиться фиктивный аргумент, если существующий код ожидает дальнейших аргументов в стеке.

Вы можете проверить аргументы стека, поскольку в соответствии с соглашением о вызовах __thiscall для функций-членов вызываемый объект очищает стек.К счастью, это соответствует соглашению __fastcall.

0 голосов
/ 12 февраля 2019

Задумывались ли вы об использовании вместо них std :: bind и std :: function?C ++ 11 и boost имеют его.

    std::function x = std::bind(&ClassName::function,this);

Это создаст функцию обратного вызова, которая будет работать с вашим объектом.

...