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

RTD

Потужно
Автор темы
Модератор
399
470
Здрасте, продолжаем насиловать игру хуками, только уже виртуальных таблиц(обычный 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 · Просмотры: 4,859
Последнее редактирование:

RTD

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

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

Вложения

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

user164451

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

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

RTD

Потужно
Автор темы
Модератор
399
470
Было интересно... Добавил 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,764
5,923
я выявил возможное решение для проблемы с нестабильностью хуков, с самодельными хуками оно помогает, но нужно сделать больше тестов и если его работа подтвердится, то не помешало бы добавить его в эту либу.
 

RTD

Потужно
Автор темы
Модератор
399
470
Добавил в суме 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. тестирование предполагает что вы дадите отчет
(вложение удалено)
 

RTD

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

chapo

чопа сребдс // @moujeek
Модератор
8,934
11,702
в чем проблема? D:\SAMP\moonloader\lib\hooks.lua:64: bad argument #1 to 'off' (function expected, got table)
в либе посмотрел, в функцию передаю функцию
Скрытое содержимое для пользователя(ей): RTD
 

Hideme Flow

Известный
573
199
в чем проблема? 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

Потужно
Автор темы
Модератор
399
470
в чем проблема? 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

♥ Love Lua ♥
Проверенный
1,339
1,178
Как хукнуть d3d9 Reset с помощью этой библиотеки?
 

RTD

Потужно
Автор темы
Модератор
399
470
Как хукнуть 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

♥ Love Lua ♥
Проверенный
1,339
1,178

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