Указатель на тело функции?

111
21 апреля 2021, 04:10

Столкнулся я с проблемой изменения кода функции в целях оптимизации (прошу прощения за си-стиль):

    static inline bool ECX_to_EBX(void *ptr) {
        map<byte*, byte> ecxs;
        ecxs[(((byte*)ptr) + 18)] = 0xBB;
        ecxs[(((byte*)ptr) + 67)] = 0x5D;
        ecxs[(((byte*)ptr) + 69)] = 0x53;
        size_t wr;
        for (map<byte*, byte>::iterator pair_item = ecxs.begin(); pair_item != ecxs.end(); ++pair_item)
        {
            WriteProcessMemory(GetCurrentProcess(), pair_item->first, &pair_item->second, sizeof(byte), (SIZE_T*)&wr);          
            if (wr == 0) return true;
#ifdef LOG
            else MessageBoxA(0, "", "replaced", 0);
#endif
        }
        return 0;
    }

где в ptr ожидается указатель на конкретную функцию, которую я уже разобрал на ассемблерные составляющие и хочу немного подкорректировать (заменить регистр ECX на EBX). Эта конкретная функция выглядит так:

struct MyClass{
    static void MyFunc();
}

Передаю ее в качестве аргумента:

Utils::ECX_to_EBX(MyClass::MyFunc);

Смотрю в памяти, а там не то. Оказывается, что MyClass::MyFunc дает указатель на jmp MyProgram.MyClass::MyFunc вместо указателя на само тело функции. Собственно вопрос, как получить указатель на первый байт тела (без вычисления относительного адреса относительно jmp) и почему я получаю указатель на jmp вместо него?

Это особенность компилятора visual-c++ или какие-то ключи компиляции?

На MinGW я такого казуса не припомню

Answer 1

как получить указатель на первый байт тела

При наличии полных отладочных символов (компоновка с /DEBUG:FULL для VS 2017+) как-то так:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <windows.h>
#include "DbgHelp.h"
#pragma comment(lib, "Dbghelp.lib")
struct Function {
    const char* name;
    uintptr_t address;
    bool success;
};
BOOL CALLBACK EnumSymProc(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, PVOID context) {
    Function* pfstruct = (Function*)context;
    if (strcmp(pSymInfo->Name, pfstruct->name) == 0) {
        pfstruct->address = pSymInfo->Address;      
        pfstruct->success = true;
        return FALSE; //закончить поиск
    }
    return TRUE; //продолжить поиск
}
bool GetFunctionAddress(const char* fname, uintptr_t& resultvar) {
    bool ret;
    Function fstruct;
    fstruct.name = fname;
    fstruct.address = 0;
    fstruct.success = false;
    HANDLE hProcess = GetCurrentProcess(); //текущий процесс
    char Mask[] = "*!"; //искать среди всех модулей
    BOOL status;
    status = SymInitialize(hProcess, NULL, TRUE); //загрузка символов
    if (status == FALSE)
    {
        printf("SymInitialize failed. Error code: %d\n", GetLastError());
        return false;
    }
    //поиск символов
    if (SymEnumSymbols(hProcess, 0, Mask, &EnumSymProc, (void*)&fstruct))
    {
        if (fstruct.success != false) {
            resultvar = fstruct.address; 
            ret = true;
        }
        else {
            printf("Symbol [%s] not found\n", fname);
            ret = false;
        }
    }
    else
    {
        printf("SymEnumSymbols failed. Error code: %d\n", GetLastError());
        ret = false;
    }
    SymCleanup(hProcess);
    return ret;
}
//**********************************
void Func() {
    printf("Hello, World!\n");
}
int main(int argc, char **argv)
{
    uintptr_t p;
    if (GetFunctionAddress("Func", p) != false) {
        //можно привести p к нужному типу и использовать...
    }
    return 0;
}

и почему я получаю указатель на jmp вместо него

Трудно сказать. Скорее всего, вы делаете что-то не то. Обычно, когда необходимо работать с неким куском кода как с машинным кодом, целесообразно реализовать его полностью ассемблерной вставкой, как например здесь. Это гарантирует, что формат машинного кода будет наиболее близок к тому, что вы ожидаете.

READ ALSO
Почему получаю ошибку `copy assignment operator is implicitly deleted`?

Почему получаю ошибку `copy assignment operator is implicitly deleted`?

Есть класс в котором есть вот такая переменная

115
Подключить SFML в VS Code

Подключить SFML в VS Code

Нужно подключить SFML для работы в VS Code на WindowsНикакой адекватной информации не нашел, разве что для Linux

83
Как функция передаётся в качестве параметра?

Как функция передаётся в качестве параметра?

Не совсем могу понять как в шестой строке функция передаётся в качестве параметраКак я понял, код string(*fun)() должен обьявлять указатель fun, которому...

104
Обратиться к псевдониму типа в определении метода вне класса

Обратиться к псевдониму типа в определении метода вне класса

Составил небольшой примерКомпилятор не может найти тип ref как возвращаемое значение метода getA()

92