Как использовать WinAppDbg для подключения и вызова существующих функций с учетом RVA этой функции? - PullRequest
1 голос
/ 01 мая 2020

Я пытаюсь использовать WinAppDbg для написания плагинов для игры, которая включает в себя перехват и вызов существующих функций в этой игре. После некоторого реверс-инжиниринга я получил RVA и подписи некоторых целевых функций или методов класса. Но вскоре я обнаружил, что документ WinAppDbg только говорит мне, как перехватывать существующие функции, а не вызывать их. Кроме того, обычно адрес целевой функции получается из Process.resolve_label, но у меня есть только RVA. Как я могу подключить функцию с ее RVA? Спасибо!

------------------ Обновление 1 ---------------------- -

Чтобы прояснить, что я пытаюсь сделать, рассмотрим следующий случай:

Существует метод класса с именем bool Player::attack(this, Animal *some_animal) в some_game.exe, который будет вызываться когда я нападаю на любое животное. Я хочу отслеживать событие атаки и, возможно, имитировать / инициировать событие атаки, когда захочу.

После изучения файла some_game.pdb я выяснил, что RVA целевой функции, т.е. Player::attack 0x00678840. И я сделал myplugin.dll файл, который будет вставлен в процессе игры.

Тогда довольно просто вызвать эту функцию в myplugin.dll, как это

#include <windows.h>

auto module_addr = reinterpret_cast<unsigned int>(GetModuleHandle(NULL));
attack_func = reinterpret_cast<void(*)(void*, void*)>(0x00678840+module_addr);
attack_func(...)

И перехват также довольно просто с помощью библиотеки Microsoft Detours , сначала определив функцию вспомогательного хука void RegisterStaticHook(RVA sym, void* hook, void** org);:

#include <windows.h>
// Detours
#include <detours/detours.h>

typedef uint64_t VA;
typedef unsigned int RVA;

template<typename Type>
using Ptr = Type*;

enum class HookErrorCode {
    ERR_SUCCESS,
    ERR_TRANSACTION_BEGIN,
    ERR_UPDATE_THREAD,
    ERR_ATTACH,
    ERR_DETACH,
    ERR_TRANSACTION_COMMIT
};
template<typename T = Ptr<void>>
auto Hook(Ptr<T> p, T f) {
    int error = DetourTransactionBegin();
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_TRANSACTION_BEGIN;
    }
    error = DetourUpdateThread(GetCurrentThread());
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_UPDATE_THREAD;
    }
    error = DetourAttach(
        reinterpret_cast<Ptr<PVOID>>(p),
        reinterpret_cast<PVOID>(f)
    );
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_ATTACH;
    }
    error = DetourTransactionCommit();
    if (error != NO_ERROR) {
        return HookErrorCode::ERR_TRANSACTION_COMMIT;
    }
    return HookErrorCode::ERR_SUCCESS;
}

void RegisterStaticHook(RVA sym, void* hook, void** org) {
    auto base = reinterpret_cast<VA>(GetModuleHandle(NULL));
    *org = reinterpret_cast<void*>(base + sym);
    auto ret = Hook<void*>(org, hook);
    if (ret != HookErrorCode::ERR_SUCCESS) {
        std::cout << "[Error] ";
        switch (ret) {
        case HookErrorCode::ERR_TRANSACTION_BEGIN:
            std::cout << "DetourTransactionBegin";
            break;
        case HookErrorCode::ERR_UPDATE_THREAD:
            std::cout << "DetourUpdateThread";
            break;
        case HookErrorCode::ERR_ATTACH:
            std::cout << "DetourAttach";
            break;
        case HookErrorCode::ERR_DETACH:
            std::cout << "DetourDetach";
            break;
        case HookErrorCode::ERR_TRANSACTION_COMMIT:
            std::cout << "DetourTransactionCommit";
            break;
        default:
            break;
        }
        std::cout << "failed!" << std::endl;
    }
}

, затем перехват my_attack с помощью RegisterStaticHook, как это:

void** org;
bool my_attack(void* player_this, void* animal){
...
}

RegisterStaticHook(0x00678840, my_attack, org);

У меня вопрос, как это сделать с WinAppDbg.

1 Ответ

1 голос
/ 02 мая 2020

TL; DR: WinAppDbg действительно не поддерживает это, и это было бы довольно сложно сделать. Вместо этого попробуйте Microsoft Detours.

Длинное объяснение:

WinAppDbg - это отладчик, который означает целевую программу, которую вы хотите пропатчить / перехватить и пр. c. выполняется в отдельном Windows процессе, чем ваш Python скрипт. Он может взаимодействовать с отлаживаемым процессом только теми способами, которые разрешены Win32 API, и, к сожалению, нет механизма для выполнения функций в целевом процессе.

При некоторой работе вы могли бы немного эмулировать эту функциональность. По сути, это будет означать изменение регистров и стека для выполнения начала перехваченной функции, убедитесь, что все указатели в стеке фактически указывают на допустимую память в процессе, и, возможно, выделят некоторый батутный код, чтобы позволить WinAppDbg прервать выполнение после выполнения функции. вернулся. Это должно быть сделано заново для 32 и 64 бит из-за различий в архитектуре. Это в основном то, что делают отладчики, такие как GDB.

С другой стороны, Detours работает, внедряя DLL непосредственно в память процесса, на который вы хотите нацелиться - так что выполнение кода будет быстрым, так как вы не приходится иметь дело со странными вызовами Win32 API или отображать память между процессами. Это также намного быстрее. Но вам придется кодировать C вместо Python.

...