Исходник Гайд Lua vmt+jmp/call hook | Библиотека hooks.lua

RTD

Нестандартное звание
Автор темы
Модератор
391
413
Здрасте, продолжаем насиловать игру хуками, только уже виртуальных таблиц(обычный jmp hook - https://www.blast.hk/threads/39138/).
Решил сделать либу, в которой этот и jmp хук, ее нужно кинуть в папку /moonloader/lib/
Затрагивая jmp hook, использование никак не изменилось, только пишем
Lua:
local hook = require("hooks")
tableHook = hook.jmp.new(прототип, калбэк, адрес, размер)
--вместо tableHook = hook.new(прототип, калбэк, адрес, размер)

Хуки при завершении скрипта сами снимутся

Теперь про vmt hook, его использование
Требования
  • Знать FFI
  • Знать прототип метода
  • Знать индекс метода
Использование
Покажу на примере хука метода ракнета, т.к. изначально под него и писалось это чудо. Только там для SAMP R3 было, а тут будет R1
Собственно пишем под ракнет, значит качаем SF.lua(https://github.com/SF-lua/SF.lua/tree/master/SFlua) или хотя бы его библиотеку bitstream.lua. Спасибо за это чудо
Первым делом подключаем либы
Lua:
local ffi = require("ffi")
local bitstream = require("SFlua.bitstream")
local hook = require("hooks")
Далее ждем инициализации SAMP и узнаем указатель на RakClientInterface
Lua:
local samp = getModuleHandle("samp.dll")
local pSAMPInfo = 0
while pSAMPInfo == 0 do wait(0)
    pSAMPInfo = ffi.cast("uintptr_t*", samp + 0x21A0F8)[0]
end
local pRakClient = ffi.cast("intptr_t*", pSAMPInfo + 0x3C9)[0]
Инициализируем хук
Lua:
local rakClient = hook.vmt.new(pRakClient)
--или не выпендриваться и плевать на зависимости - юзаем sampGetRakclientInterface(), но тогда зависимость сампфункс
И нам становятся доступны методы
Lua:
rakClient.hookMethod(cast, func, method)
rakClient.unHookMethod(method)
rakClient.unHookAll()
rakClient.this
Узнаем прототип, индекс, пишем калбек и ставим хук на функцию отправки пакетов
Lua:
sendPacket = rakClient.hookMethod("bool(__thiscall*)(void* this, SFL_BitStream* bitStream, char priority, char reliability, char orderingChannel)", sendPacket, 6)
--Структура SFL_BitStream доступна только если подключена либа bitstream с SF-lua
--нам возвращается оригинальная функция

function sendPacket(this, bitStream, priority, reliability, orderingChannel)
    print("packet id", bitStream.data[0]) --выводим ид пакета, посмотреть названия пакетов можно в встроенной в мун библиотеке sampfuncs.lua(не путать с SF.lua)
    local res = sendPacket(this, bitStream, priority, reliability, orderingChannel) --вызываем оригинальную функцию(или не вызываем и пакет не отправится)
    return res
end

Полный код
Lua:
local ffi = require 'ffi'
local bitstream = require("bitstream")
local hook = require("hooks")

function main()
    local samp = getModuleHandle("samp.dll")
    local pSAMPInfo = 0
    while pSAMPInfo == 0 do wait(0)
        pSAMPInfo = ffi.cast("uintptr_t*", samp + 0x21A0F8)[0]
    end
    local pRakClient = ffi.cast("intptr_t*", pSAMPInfo + 0x3C9)[0]

    local rakClient = hook.vmt.new(pRakClient)
    --[[
        original_method = rakClient.hookMethod(cast, func, method)
        rakClient.unHookMethod(method)
        rakClient.unHookAll()
        rakClient.this
    ]]
    sendPacket = rakClient.hookMethod("bool(__thiscall*)(void* this, SFL_BitStream* bitStream, char priority, char reliability, char orderingChannel)", sendPacket, 6)
    --нам возвращается оригинальная функция
    wait(-1)
end

function sendPacket(this, bitStream, priority, reliability, orderingChannel)
    print("packet id", bitStream.data[0]) --выводим ид пакета, посмотреть названия пакетов можно в встроенной в мун библиотеке sampfuncs.lua(не путать с SF.lua)
    local res = sendPacket(this, bitStream, priority, reliability, orderingChannel) --вызываем оригинальную функцию(или не вызываем и пакет не отправится)
    return res
end
Всем добра, любви и процветания, спасибо за внимание
p.s. можете так еще насиловать directx9, как тут: https://www.blast.hk/threads/13380/post-890736
 

Вложения

  • hooks.lua
    7 KB · Просмотры: 3,499
Последнее редактирование:

RTD

Нестандартное звание
Автор темы
Модератор
391
413
небезопасное дело
Да, если больше чем 2 скрипта будут использовать один и тот же хук и эти скрипты будут перезагружаться, то очень высокий шанс конфликта и краш. Но в принципе использовать можно
В планах написать на С++ менеджер, который точно не выгружался бы и контролил все это дело
К слову, на данный момент vmt ведет себя стабильнее чем jmp

Обновил снятие хуков виртуальных методов, в теории должно гарантировать что игра хотя бы не крашнет, это стоит 5 байт при каждом снятии хука. Старые хуки прикрепил в этом ответе. Возможно сделаю так же для jmp хука
 

Вложения

  • hooks.lua
    4.8 KB · Просмотры: 133
Последнее редактирование:

user164451

Потрачен
411
128
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Автор Юрия смотрел.

(автор понимает что за Юрий, мне просто лень писать полностью)
 
  • Нравится
Реакции: RTD

RTD

Нестандартное звание
Автор темы
Модератор
391
413
Было интересно... Добавил call хук, не знаю будет ли кто-то юзать, но типа пусть будет
Предназначена для хуков операции call внутри тела функции как пример
1605985693923.png

Для хука указываем адрес на опкод "call", конкретно в этом случае "samp.dll + 0x70F4E"
В коде выглядит аналогично jmp
Прототип указывается той функции что вызывается в оригинале
Пример:
Lua:
local hook = require 'hooks'
function main()
    renderNick = hook.call.new('int(__cdecl *)(char* buf, const char* fmt, const char* nick, int id)', renderNick, getModuleHandle('samp.dll') + 0x70F4E)
    wait(-1)
end
function renderNick(buf, fmt, nick, id)
    return renderNick(buf, 'Какой-то поц под именем "%s" {FFFFFF} с айдишником [%d]', nick, id)
end
И он сделает сие чудо -
1605986018380.png
 
Последнее редактирование:

FYP

Известный
Администратор
1,757
5,684
я выявил возможное решение для проблемы с нестабильностью хуков, с самодельными хуками оно помогает, но нужно сделать больше тестов и если его работа подтвердится, то не помешало бы добавить его в эту либу.
 
  • Нравится
Реакции: Shepi, etereon и RTD

RTD

Нестандартное звание
Автор темы
Модератор
391
413
Добавил в суме 3 строчки 👍
Кто может, тестируйте, я не имею сейчас возможности
Предварительный код, при котором вроде бы крашился скрипт:
Lua:
local hook = require("hooks")
function main()
    sampChatHook = hook.jmp.new("void(__thiscall *)(uintptr_t this, uint32_t type, const char* text, const char* prefix, uint32_t color, uint32_t pcolor)", sampChatHook, getModuleHandle('samp.dll') + 0x64010)
    while true do
        wait(0)
        sampAddChatMessage("1", -1)
    end
end
function sampChatHook(this, type, text, prefix, color, pcolor)
    sampChatHook(this, type, text, prefix, color, pcolor)
end
p.s. тестирование предполагает что вы дадите отчет
 

Вложения

  • hooks.lua
    7 KB · Просмотры: 114
Последнее редактирование:

RTD

Нестандартное звание
Автор темы
Модератор
391
413
В принципе стабильность значительно повысилась, тем не менее используя 2+ скрипта которые хукают одну функцию - им нельзя перезагружаться, вы попадаете в ситуацию 70% краш из-за того что либа примитивная
Если развивать дальше эту идею с хуками луа и на луа, то лучше вывести эту либу в скрипт(некий менеджер хуков) и подключать через import(). Но кому это нужно?
 

chapo

🫡 В армии с 17.10.2023. В ЛС НЕ ОТВЕЧАЮ
Друг
8,747
11,156
в чем проблема? D:\SAMP\moonloader\lib\hooks.lua:64: bad argument #1 to 'off' (function expected, got table)
в либе посмотрел, в функцию передаю функцию
Скрытое содержимое для пользователя(ей): RTD
 

Hideme Flow

Известный
555
193
в чем проблема? D:\SAMP\moonloader\lib\hooks.lua:64: bad argument #1 to 'off' (function expected, got table)
в либе посмотрел, в функцию передаю функцию
+
Lua:
[ML] (error) hok.lua: D:\SAMP\1K FPS\moonloader\lib\hooks.lua:64: bad argument #1 to 'off' (function expected, got table)
stack traceback:
    [C]: in function 'off'
    D:\SAMP\1K FPS\moonloader\lib\hooks.lua:64: in function 'new'
    D:\SAMP\1K FPS\moonloader\hok.lua:7: in function <D:\SAMP\1K FPS\moonloader\hok.lua:5>
    [C]: in function 'wait'
    D:\SAMP\1K FPS\moonloader\hok.lua:9: in function <D:\SAMP\1K FPS\moonloader\hok.lua:5>
[ML] (error) hok.lua: Script died due to an error. (0F75702C)

P.S: решил проблему.
с
local sp = require('lib.samp.events')
Не работает, а если убрать - то работает
 
Последнее редактирование:

RTD

Нестандартное звание
Автор темы
Модератор
391
413
в чем проблема? D:\SAMP\moonloader\lib\hooks.lua:64: bad argument #1 to 'off' (function expected, got table)
в либе посмотрел, в функцию передаю функцию
*** Скрытый текст не может быть процитирован. ***
А это тебе похоже от луа привет, main вызвался второй раз
Старая проблема еще с начала написания...
Можешь закостылить так
Lua:
local init = false
function main()
    if init then
        script.this:reload() --без перезагрузки main будет вызываться каждый раз, почему-то багует
        return
    end
    --.....
    init = true
end
Я не знаю как это со стороны луа решать. У меня он практически не появляется, у других постоянно, у третьих раз в минут 30
 

Gorskin

I shit on you
Проверенный
1,237
1,002
Как хукнуть d3d9 Reset с помощью этой библиотеки?
 

RTD

Нестандартное звание
Автор темы
Модератор
391
413
Как хукнуть d3d9 Reset с помощью этой библиотеки?

Lua:
function hkReset(pDevice, pPresentationParameters)
        
    return hkReset(pDevice, pPresentationParameters)
end
local D3D9Device = hook.vmt.new(ffi.cast('intptr_t*', 0xC97C28)[0]) --getD3DDevicePtr()
hkReset = D3D9Device.hookMethod('long(__stdcall*)(void*, void*)', hkReset, 16)
 

Gorskin

I shit on you
Проверенный
1,237
1,002

Lua:
function hkReset(pDevice, pPresentationParameters)
     
    return hkReset(pDevice, pPresentationParameters)
end
local D3D9Device = hook.vmt.new(ffi.cast('intptr_t*', 0xC97C28)[0]) --getD3DDevicePtr()
hkReset = D3D9Device.hookMethod('long(__stdcall*)(void*, void*)', hkReset, 16)
Скрытое содержимое для пользователя(ей): RTD