Начинающий
			
			
				
					
				
			
		Начинающий
		- Статус
 - Оффлайн
 
- Регистрация
 - 12 Ноя 2022
 
- Сообщения
 - 63
 
- Реакции
 - 23
 
Библиотека требует поддержки monadic функций для std::expected и std::optional 
Ориентирована на использование в Rust подобном стиле с выклченными исключениями и Error кодами.
RAII VMT хуки сами дестрактятся при выгрузке модуля, потому можно инжектить и выгружать dll множество раз во время разработки.
Ещё есть разного рода мелочи вроде поиска сигнатур с парсингом паттерна во время компиляции и удобный класс для адресов с monadic функциями.
Есть 2 варианта хуков. Unsafe хуки которые меняют оригинальную vmt и safe хуки, которые заменяют vptr объекта на скопированную vmt.
Вот небольшой пример unsafe хуков на SendNetMessage и PostReceivedNetMessage
и safe хука на NetworkSystem::CreateNetChannel для source 2 игр(cs2/d2)
	
	
	
	
	
	
		
			
			
			
			
			
		
	
	
	
		
	
	
		
	
с msvc работает отлично.
На clang будет работать только с 17.0.0 версии. Которая ещё не распространяется и её нужно билдить с исходников.
Есть покрытие тестами, но если встретите баг при использовании - пишите.
				
			
	Пожалуйста, авторизуйтесь для просмотра ссылки.
Ориентирована на использование в Rust подобном стиле с выклченными исключениями и Error кодами.
RAII VMT хуки сами дестрактятся при выгрузке модуля, потому можно инжектить и выгружать dll множество раз во время разработки.
Ещё есть разного рода мелочи вроде поиска сигнатур с парсингом паттерна во время компиляции и удобный класс для адресов с monadic функциями.
Есть 2 варианта хуков. Unsafe хуки которые меняют оригинальную vmt и safe хуки, которые заменяют vptr объекта на скопированную vmt.
Вот небольшой пример unsafe хуков на SendNetMessage и PostReceivedNetMessage
и safe хука на NetworkSystem::CreateNetChannel для source 2 игр(cs2/d2)
			
				C++:
			
		
		
		#include <reutl/safe_vmt.hh>
#include <reutl/scanner.hh>
#include <windows.h>
#include <Psapi.h>
#include <thread>
#include <iostream>
#include <memory>
#include <cstdint>
enum NetChannelBufType : int {
    K_BUF_DEFAULT    = -1,
    K_BUF_UNRELIABLE = 0,
    K_BUF_RELIABLE   = 1,
    K_BUF_VOICE      = 2,
};
struct CNetworkSerializerPB {
    const char* unscoped_name;
    std::uint32_t category_mask;
    [[maybe_unused]] int unk;
    void* pb_binding;
    const char* group_name;
    std::int16_t msg_id;
    std::uint8_t group_id;
    std::uint8_t default_buf_type;
    [[maybe_unused]] std::uint8_t pad[28];
};
std::unique_ptr<reutl::VmHook> g_recv_msg_hk = nullptr;
std::unique_ptr<reutl::VmHook> g_send_msg_hk = nullptr;
auto hook_send_recv_unsafe() -> void
{
    const auto net_chan_vmt =
        reutl::find_pattern_in_module<"40 53 56 57 41 56 48 83 EC ?? 45 33 F6 48 8D 71">(
            "networksystem.dll")
            .value_or(std::nullopt)
            .transform([](const reutl::Addr addr) {
                return addr
                    .offset(0x15) //
                    .deref_instr_rel<std::int32_t>(7)
                    .to_ptr();
            });
    if (!net_chan_vmt) {
        std::cout << "NetChannel signature not found\n";
        return;
    }
    using RecvMsg = auto (*)(void*, CNetworkSerializerPB*, void*, void*, int)->void;
    auto recv_msg_cb = [](void* self, CNetworkSerializerPB* msg_handle, void* pb_msg, void* type,
                          const int bits) -> void {
        std::cout << "recv: " << msg_handle->msg_id << '\n';
        const auto orig = static_cast<RecvMsg>(g_recv_msg_hk->get_orig());
        return orig(self, msg_handle, pb_msg, type, bits);
    };
    g_recv_msg_hk =
        reutl::make_vm_hook(net_chan_vmt.value(), 0x56, static_cast<RecvMsg>(recv_msg_cb))
            .value_or(nullptr);
    if (!g_recv_msg_hk) {
        std::cout << "Error occurred while installing PostReceivedNetMessage hook\n";
        std::abort();
    }
    using SendMsg = auto (*)(void*, CNetworkSerializerPB*, void*, NetChannelBufType)->bool;
    auto send_msg_cb = [](void* self, CNetworkSerializerPB* msg_handle, void* pb_msg,
                          NetChannelBufType buf_type) -> bool {
        std::cout << "send: " << msg_handle->msg_id << '\n';
        const auto orig = static_cast<SendMsg>(g_send_msg_hk->get_orig());
        return orig(self, msg_handle, pb_msg, buf_type);
    };
    g_send_msg_hk =
        reutl::make_vm_hook(net_chan_vmt.value(), 0x45, static_cast<SendMsg>(send_msg_cb))
            .value_or(nullptr);
    if (!g_send_msg_hk) {
        std::cout << "Error occurred while installing PostReceivedNetMessage hook\n";
        std::abort();
    }
}
std::unique_ptr<reutl::SafeVmt> g_nw_sys_vmt = nullptr;
auto safe_net_chan_hk() -> void
{
    using CreateInterface = auto (*)(const char*, int*)->void*;
    const auto create_interface = reinterpret_cast<CreateInterface>(
        GetProcAddress(GetModuleHandleA("networksystem.dll"), "CreateInterface"));
    void* nw_sys = create_interface("NetworkSystemVersion001", nullptr);
    g_nw_sys_vmt = std::make_unique<reutl::SafeVmt>(nw_sys);
    using CreateNetChan = auto (*)(void*, int, void*, const char*, unsigned, unsigned)->void*;
    auto create_net_chan_cb = [](void* self, int unk, void* ns_addr, const char* str, unsigned unk2,
                                 unsigned unk3) -> void* {
        std::cout << "NetChannel created\n";
        const auto orig = static_cast<CreateNetChan>(g_nw_sys_vmt->get_orig(0x1A).value());
        return orig(self, unk, ns_addr, str, unk2, unk3);
    };
    g_nw_sys_vmt->install_hook(0x1A, static_cast<CreateNetChan>(create_net_chan_cb));
}
auto on_inject() -> void
{
    safe_net_chan_hk();
    hook_send_recv_unsafe();
}
auto WINAPI DllMain(HINSTANCE dll, DWORD call_reason, LPVOID reserved) -> BOOL
{
    switch (call_reason) {
    case DLL_PROCESS_ATTACH: {
        AllocConsole();
        freopen_s(reinterpret_cast<FILE**> stdout, "CONOUT$", "w", stdout);
        CreateThread(nullptr, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(on_inject), 0, 0, 0);
        break;
    }
    case DLL_PROCESS_DETACH:
        if (reserved != nullptr)
            break; // do not do cleanup if process termination scenario
        // Perform any necessary cleanup.
        fclose(stdout);
        FreeConsole();
        break;
    default:
        break;
    }
    return TRUE;
}
	с msvc работает отлично.
На clang будет работать только с 17.0.0 версии. Которая ещё не распространяется и её нужно билдить с исходников.
Есть покрытие тестами, но если встретите баг при использовании - пишите.
	Пожалуйста, авторизуйтесь для просмотра ссылки.
				