Хукаем write_user_cmd_delta_to_buffer

Модератор раздела "Создание скриптов для читов"
Модератор
Статус
Оффлайн
Регистрация
1 Фев 2020
Сообщения
1,241
Реакции[?]
408
Поинты[?]
45K
Введение:
В этой статье я бы хотел рассмотреть интересный подход к модификации игровых функций, находящихся в виртуальной таблице, на языке программирования LUA. Пример кода, который будет разобран, демонстрирует способ хука внутриигровой функции write_user_cmd_delta_to_buffer. Используемый метод взят из скрипта "Item crash fix" от qhouz :
Пожалуйста, авторизуйтесь для просмотра ссылки.


Описание кода:
Основная задача данного кода — модификация внутриигровой функции через "хукирование" виртуальной таблицы

Определение типа функции:

code_language.lua:
local write_user_cmd_delta_to_buffer_t = ffi.typeof [[
    bool(__thiscall*)(void*, int, void*, int, int, bool) //we must define the function type
]]
Этот код сообщает Lua, как выглядит функция WriteUserCmdDeltaToBuffer: какие типы данных она принимает в качестве аргументов (void*, int, void*, int, int, bool) и что возвращает (true или false).

Получение интерфейса:
Дальше нам нужно получить доступ к самой функции. Функция get.vclient() предоставляет доступ к VClient018

code_language.lua:
local VClient018 = utils.create_interface("client.dll", "VClient018")
Работа с виртуальной таблицей:

code_language.lua:
local pointer = ffi.cast("uintptr_t**", interface)
local vtable = ffi.cast("uintptr_t*", pointer[0])
Здесь мы получаем указатель на саму виртуальную таблицу

Создание и замена виртуальной таблицы:

code_language.lua:
local hooked_vtable = ffi.new("uintptr_t[?]", size)
for i = 0, size - 1 do
    hooked_vtable[i] = vtable[i]
end
Создаём новый массив с тем же размером, что и оригинальная таблица, а затем копируем туда все элементы. Это позволит безопасно подменять функцию, не затрагивая оригинальную таблицу.

Подменяем функцию:
code_language.lua:
hooked_vtable[24] = ffi.cast("uintptr_t", ffi.cast(write_user_cmd_delta_to_buffer_t, write_user_cmd_delta_to_buffer))
В данном случае мы подменяем 24-ю функцию в таблице на нашу собственную. Теперь при вызове WriteUserCmdDeltaToBuffer будет выполняться наш код

Восстановление оригинальной таблицы:
code_language.lua:
client.add_callback("unload", function()
    hooked_vtable[24] = vtable[24]
    pointer[0] = vtable
end)
Это позволяет вернуть оригинальную таблицу обратно и предотвратить сбои в работе игры после выгрузки скрипта (чаще всего будет происходить краш при повторной загрузке скрипта)


Заключение:
Хочу повторить, что данный метод хука был взят из скрипта qhouz'a. Я не претендую на авторство, а просто показываю примеры того, как еще можно использовать предоставленный метод.


Полный код:

code_language.lua:
--[[


The main code used to write this code was written by qhouz: https://github.com/qhouz/scripting/blob/main/neverlose/item_crash_fix.lua.
I am not claiming authorship, but just showing examples of how else the provided method can be used

In this example we will be trying to hook the game function write_user_cmd_delta_to_buffer


]]

local ffi = require "ffi"

do
    local write_user_cmd_delta_to_buffer_t = ffi.typeof [[
        bool(__thiscall*)(void*, int, void*, int, int, bool) //we must define the function type
    ]]

    local get = {
        vclient = function() --@note: this function is used to get a pointer to the interface
            local VClient018 = utils.create_interface("client.dll", "VClient018")
            if VClient018 == nil then
                print("failed to get interface") --@note: even though it's impossible, it's better to be safe
                return
            end
         
            return VClient018
        end,

        vtable = {
            _self = function(interface) --@note: this function is used to retrieve a pointer to a virtual table and a pointer to the interface itself from a given interface
                local pointer = ffi.cast("uintptr_t**", interface)
                local vtable = ffi.cast("uintptr_t*", pointer[0])

                if vtable == nil or pointer == nil then
                    print("vtable: "..vtable.." | pointer: "..pointer) --@note: even though it's impossible, it's better to be safe
                    return
                end

                return pointer, vtable
            end,

            size = function(vtable) --@note: determine the size of the virtual table by traversing its elements until we find the null pointer (0x0), which marks the end of this virtual table
                local size = 0
                while vtable[size] ~= 0x0 do
                    size = size + 1
                end

                return size
            end
        }
    }

    local _create = {
        hooked_vtable = function(vtable, size) --@note: this function creates a new array hooked_vtable of size and copies all elements from the original virtual table into it
            local hooked_vtable = ffi.new("uintptr_t[?]", size)
            for i = 0, size - 1 do
                hooked_vtable[i] = vtable[i]
            end
            return hooked_vtable
        end
    }

    local function hook_write_user_cmd_delta_to_buffer(vtable, hooked_vtable)
        local original_write_user_cmd_delta_to_buffer = ffi.cast(write_user_cmd_delta_to_buffer_t, vtable[24])

        local function write_user_cmd_delta_to_buffer(thisptr, slot, buf, from, to, is_new_cmd)

            --@note: you can add your own code here
         
            print("hooked") --@note: for example

            return original_write_user_cmd_delta_to_buffer(thisptr, slot, buf, from, to, is_new_cmd) --@note: return original function
        end

        client.add_callback("unload", function()
            hooked_vtable[24] = vtable[24]
            pointer[0] = vtable
        end)

        hooked_vtable[24] = ffi.cast("uintptr_t", ffi.cast(write_user_cmd_delta_to_buffer_t, write_user_cmd_delta_to_buffer))
    end

    local VClient018 = get.vclient()
    local pointer, vtable = get.vtable._self(VClient018)
    local size = get.vtable.size(vtable)
    local hooked_vtable = _create.hooked_vtable(vtable, size)
    pointer[0] = hooked_vtable --@note: replaces the original virtual table with hooked virtual table
    hook_write_user_cmd_delta_to_buffer(vtable, hooked_vtable)
end

P.S. Если у вас есть какие-либо замечания по поводу моего материала или предложения, пожалуйста, напишите их в теме.
 
Модератор раздела "Создание скриптов для читов"
Модератор
Статус
Оффлайн
Регистрация
1 Фев 2020
Сообщения
1,241
Реакции[?]
408
Поинты[?]
45K
А в чем смысл поста
Основная идея темы заключается в анализе метода хука, применённого qhouz в его скрипте, а также в демонстрации его использования на другой внутриигровой функции.
 
Пользователь
Статус
Оффлайн
Регистрация
2 Май 2022
Сообщения
360
Реакции[?]
46
Поинты[?]
24K
Основная идея темы заключается в анализе метода хука, применённого qhouz в его скрипте, а также в демонстрации его использования на другой внутриигровой функции.
это вообще никакой не анализ, ты просто сурскод сюда закинул, и говоришь "СОЗДАЕМ ТАБЛИЦУ НУЖНУЮ ДЛЯ ДАЛЬНЕЙШИХ ДЕЙСТВИЙ"
 
Пользователь
Статус
Оффлайн
Регистрация
8 Апр 2022
Сообщения
671
Реакции[?]
106
Поинты[?]
69K
Основная идея темы заключается в анализе метода хука, применённого qhouz в его скрипте, а также в демонстрации его использования на другой внутриигровой функции.
всм это дефолт вмт хук
 
Пользователь
Статус
Оффлайн
Регистрация
2 Май 2022
Сообщения
360
Реакции[?]
46
Поинты[?]
24K
я тоже самое могу сделать, ток не хуком
прост переопределил функцию чтобы текст 'some string to delete' не рендерился
Код:
local renderer_text = renderer.text

function renderer.text(x, y, r, g, b, a, flags, max_width, ...)
    if flags:find("b") and (...):find("some string to delete") then
        return
    end

    return renderer_text(x, y, r, g, b, a, flags, max_width, ...)
end
норм iq у создателя поста
 
Модератор раздела "Создание скриптов для читов"
Модератор
Статус
Оффлайн
Регистрация
1 Фев 2020
Сообщения
1,241
Реакции[?]
408
Поинты[?]
45K
это вообще никакой не анализ, ты просто сурскод сюда закинул, и говоришь "СОЗДАЕМ ТАБЛИЦУ НУЖНУЮ ДЛЯ ДАЛЬНЕЙШИХ ДЕЙСТВИЙ"
Будьте так добры, перешлите сообщение, где я писал "создаём таблицу нужную для дальнейших действий", либо хоть что-то связанное с этим предложением.


я тоже самое могу сделать, ток не хуком
прост переопределил функцию чтобы текст 'some string to delete' не рендерился
Код:
local renderer_text = renderer.text

function renderer.text(x, y, r, g, b, a, flags, max_width, ...)
    if flags:find("b") and (...):find("some string to delete") then
        return
    end

    return renderer_text(x, y, r, g, b, a, flags, max_width, ...)
end
норм iq у создателя поста
Не сочтите за грубость, но как связана моя тема, где я разбираю метод хука, и Ваш код..


всм это дефолт вмт хук
У меня про это вся тема написана... Просто каких-то "запоминающихся" скриптов, где используется данный метод хука, не было, поэтому решил разобрать на примере темы от qhouz'a
 
SenkoTech dev
Пользователь
Статус
Оффлайн
Регистрация
4 Янв 2020
Сообщения
327
Реакции[?]
113
Поинты[?]
7K
я тоже самое могу сделать, ток не хуком
прост переопределил функцию чтобы текст 'some string to delete' не рендерился
Код:
local renderer_text = renderer.text

function renderer.text(x, y, r, g, b, a, flags, max_width, ...)
    if flags:find("b") and (...):find("some string to delete") then
        return
    end

    return renderer_text(x, y, r, g, b, a, flags, max_width, ...)
end
норм iq у создателя поста
ну это уже другое, конечно. абсолютно
неудачный пример ты привёл здесь

я насчёт поста в принципе ничего не имею
но у меня используется дефолт свап вмт

его можно было и не разбирать вовсе
да и пост вообще не в той тематике находится

это скорее относится к "вопросы и помощь новичкам"
просьба поменять тематику поста, ибо пост не скрипт вовсе
 
Privatny p100 DT Airlag Break LC Teleport Exploit
Участник
Статус
Оффлайн
Регистрация
27 Янв 2021
Сообщения
983
Реакции[?]
151
Поинты[?]
74K
Основная идея темы заключается в анализе метода хука, применённого qhouz в его скрипте, а также в демонстрации его использования на другой внутриигровой функции.
Ты еблан? Этот код опенсурс лежит, кому надо без тебя проанализируют там ничего сложного нет
 
Сверху Снизу