Вопрос [gamesense] vmt-hook

  • Автор темы Автор темы amiiiil
  • Дата начала Дата начала
есть ли у кого? мне нужно именно хукнуть таблицу, пожалуйста! :cryingcat:
Код:
Expand Collapse Copy
local ffi = require("ffi")
ffi.cdef[[
    typedef int BOOL;
    typedef void* LPVOID;
    typedef unsigned long DWORD;
    typedef DWORD* PDWORD;
    typedef unsigned long ULONG_PTR;
    typedef ULONG_PTR SIZE_T;
    BOOL VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD  flNewProtect, PDWORD lpflOldProtect);
    LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD  flAllocationType, DWORD  flProtect);
]]
local get_pattern = {
    GetModuleHandlePtr = ffi.cast("void***", ffi.cast("uint32_t", client.find_signature("engine.dll", "\xFF\x15\xCC\xCC\xCC\xCC\x85\xC0\x74\x0B")) + 2)[0][0],
    GetProcAddressPtr = ffi.cast("void***", ffi.cast("uint32_t", client.find_signature("engine.dll", "\xFF\x15\xCC\xCC\xCC\xCC\xA3\xCC\xCC\xCC\xCC\xEB\x05")) + 2)[0][0],
    reinterpret_cast = function(addr, typestring)
        return function(...) return ffi.cast(typestring, client.find_signature("engine.dll", "\xFF\xE1"))(addr, ...) end
    end,
}

do
    get_pattern.fnGetModuleHandle = get_pattern.reinterpret_cast(get_pattern.GetModuleHandlePtr, "void*(__thiscall*)(void*, const char*)")
    get_pattern.fnGetProcAddress = get_pattern.reinterpret_cast(get_pattern.GetProcAddressPtr, "void*(__thiscall*)(void*, void*, const char*)")
    get_pattern.GetModuleHandle = get_pattern.fnGetModuleHandle
    get_pattern.GetProcAddress = get_pattern.fnGetProcAddress

    get_pattern.lib = { kernel32 = get_pattern.GetModuleHandle("kernel32.dll") }
    get_pattern.export = {
        kernel32 = {
            VirtualProtect = get_pattern.reinterpret_cast(get_pattern.GetProcAddress(get_pattern.lib.kernel32, "VirtualProtect"), "BOOL(__thiscall*)(void*, LPVOID, SIZE_T, DWORD, PDWORD)"),
            VirtualAlloc = get_pattern.reinterpret_cast(get_pattern.GetProcAddress(get_pattern.lib.kernel32, "VirtualAlloc"), "LPVOID(__thiscall*)(void*, LPVOID, SIZE_T, DWORD, DWORD)"),
        }
    }
end
local hook = {all = {}}
do
    hook.new = function(vtable)
        local chook = {
            data = {},
            ogfunc = {},
            oldProto = ffi.new("DWORD[1]"),
            vtable = vtable,
        }
        chook.data.hook = function(typestr, ind, __func, len)
            if len < 5 then return 0 end
            chook.ogfunc[ind] = {vtable[ind], len}
            get_pattern.export.kernel32.VirtualProtect(vtable + ind, len, 0x40, chook.oldProto)
            vtable[ind] = ffi.cast("intptr_t", ffi.cast(typestr, __func))
            get_pattern.export.kernel32.VirtualProtect(vtable + ind, len, chook.oldProto[0], chook.oldProto)
            return ffi.cast(typestr, chook.ogfunc[ind][1])
        end
        chook.data.unhook = function(ind)
            get_pattern.export.kernel32.VirtualProtect(chook.vtable + ind, chook.ogfunc[ind][2], 0x40, chook.oldProto)

            local alloc_addr = ffi.cast("intptr_t", get_pattern.export.kernel32.VirtualAlloc(nil, 5, 0x1000, 0x40))
            local trampoline_bytes = ffi.new("uint8_t[?]", 5, 0x90)
    
            trampoline_bytes[0] = 0xE9
            ffi.cast("int32_t*", trampoline_bytes + 1)[0] = chook.ogfunc[ind][1] - tonumber(alloc_addr) - 5
    
            ffi.copy(ffi.cast("void*", alloc_addr), trampoline_bytes, chook.ogfunc[ind][2])
            chook.vtable[ind] = ffi.cast("intptr_t", alloc_addr)
            get_pattern.export.kernel32.VirtualProtect(chook.vtable + ind, chook.ogfunc[ind][2], chook.oldProto[0], chook.oldProto)
            chook.ogfunc[ind] = nil
        end
        chook.data.unhook_all = function()
            for ind, _ in pairs(chook.ogfunc) do
                chook.data.unhook(ind)
            end
        end
        table.insert(hook.all, chook.data.unhook_all)
        return chook.data
    end
end
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
Код:
Expand Collapse Copy
local ffi = require("ffi")
ffi.cdef[[
    typedef int BOOL;
    typedef void* LPVOID;
    typedef unsigned long DWORD;
    typedef DWORD* PDWORD;
    typedef unsigned long ULONG_PTR;
    typedef ULONG_PTR SIZE_T;
    BOOL VirtualProtect(LPVOID lpAddress, SIZE_T dwSize, DWORD  flNewProtect, PDWORD lpflOldProtect);
    LPVOID VirtualAlloc(LPVOID lpAddress, SIZE_T dwSize, DWORD  flAllocationType, DWORD  flProtect);
]]
local get_pattern = {
    GetModuleHandlePtr = ffi.cast("void***", ffi.cast("uint32_t", client.find_signature("engine.dll", "\xFF\x15\xCC\xCC\xCC\xCC\x85\xC0\x74\x0B")) + 2)[0][0],
    GetProcAddressPtr = ffi.cast("void***", ffi.cast("uint32_t", client.find_signature("engine.dll", "\xFF\x15\xCC\xCC\xCC\xCC\xA3\xCC\xCC\xCC\xCC\xEB\x05")) + 2)[0][0],
    reinterpret_cast = function(addr, typestring)
        return function(...) return ffi.cast(typestring, client.find_signature("engine.dll", "\xFF\xE1"))(addr, ...) end
    end,
}

do
    get_pattern.fnGetModuleHandle = get_pattern.reinterpret_cast(get_pattern.GetModuleHandlePtr, "void*(__thiscall*)(void*, const char*)")
    get_pattern.fnGetProcAddress = get_pattern.reinterpret_cast(get_pattern.GetProcAddressPtr, "void*(__thiscall*)(void*, void*, const char*)")
    get_pattern.GetModuleHandle = get_pattern.fnGetModuleHandle
    get_pattern.GetProcAddress = get_pattern.fnGetProcAddress

    get_pattern.lib = { kernel32 = get_pattern.GetModuleHandle("kernel32.dll") }
    get_pattern.export = {
        kernel32 = {
            VirtualProtect = get_pattern.reinterpret_cast(get_pattern.GetProcAddress(get_pattern.lib.kernel32, "VirtualProtect"), "BOOL(__thiscall*)(void*, LPVOID, SIZE_T, DWORD, PDWORD)"),
            VirtualAlloc = get_pattern.reinterpret_cast(get_pattern.GetProcAddress(get_pattern.lib.kernel32, "VirtualAlloc"), "LPVOID(__thiscall*)(void*, LPVOID, SIZE_T, DWORD, DWORD)"),
        }
    }
end
local hook = {all = {}}
do
    hook.new = function(vtable)
        local chook = {
            data = {},
            ogfunc = {},
            oldProto = ffi.new("DWORD[1]"),
            vtable = vtable,
        }
        chook.data.hook = function(typestr, ind, __func, len)
            if len < 5 then return 0 end
            chook.ogfunc[ind] = {vtable[ind], len}
            get_pattern.export.kernel32.VirtualProtect(vtable + ind, len, 0x40, chook.oldProto)
            vtable[ind] = ffi.cast("intptr_t", ffi.cast(typestr, __func))
            get_pattern.export.kernel32.VirtualProtect(vtable + ind, len, chook.oldProto[0], chook.oldProto)
            return ffi.cast(typestr, chook.ogfunc[ind][1])
        end
        chook.data.unhook = function(ind)
            get_pattern.export.kernel32.VirtualProtect(chook.vtable + ind, chook.ogfunc[ind][2], 0x40, chook.oldProto)

            local alloc_addr = ffi.cast("intptr_t", get_pattern.export.kernel32.VirtualAlloc(nil, 5, 0x1000, 0x40))
            local trampoline_bytes = ffi.new("uint8_t[?]", 5, 0x90)
   
            trampoline_bytes[0] = 0xE9
            ffi.cast("int32_t*", trampoline_bytes + 1)[0] = chook.ogfunc[ind][1] - tonumber(alloc_addr) - 5
   
            ffi.copy(ffi.cast("void*", alloc_addr), trampoline_bytes, chook.ogfunc[ind][2])
            chook.vtable[ind] = ffi.cast("intptr_t", alloc_addr)
            get_pattern.export.kernel32.VirtualProtect(chook.vtable + ind, chook.ogfunc[ind][2], chook.oldProto[0], chook.oldProto)
            chook.ogfunc[ind] = nil
        end
        chook.data.unhook_all = function()
            for ind, _ in pairs(chook.ogfunc) do
                chook.data.unhook(ind)
            end
        end
        table.insert(hook.all, chook.data.unhook_all)
        return chook.data
    end
end
окей, пройдемся по твоим ошибкам
client.find_signature("engine.dll", "\xFF\xE1") здесь не нужен это просто jmp ecx и не участвует в кастинге адреса
VirtualProtect меняет защиту по адресу vtable + ind но vtable указатель а не адрес памяти
vtable это массив указателей vtable + ind не обязательно указывает на корректную область памяти для VirtualProtect
chook.ogfunc[ind][2] это len но ты копируешь всегда 5 байт а длина оригинального хука может быть другой
VirtualProtect и VirtualAlloc это stdcall не thiscall
 
круто, чувак дальше думай что все люди в этом мире используют чат гпт
ты не то что не в состоянии накодить что то свое ты умудрился еще больше хуйни наделать потому что ты ссаный пастерок шизоидный который видимо не понимает что он делает
ну скиньте тогда правильный код я не знаю :smilingimp:
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
ну скиньте тогда правильный код я не знаю :smilingimp:
я не делаю ничего на луа
большинство моментов я уже описал
чувак банально не понимает что он делает и пытается хоть как то задефаться позор
 
я твоей бабке щас кишки вырву и твою мать шлюху на них повешу, пастерок ты удумал что я твою маманю шлюху тут не убью своим биг диком или чо ты как там терпел мой пенис?
я понимаю что начались каникулы и ты жиробасный пидорас пошел пастить луашечки на свой скитик но поверь мне сын бляди однажды я приду к тебе и выебу всю твою семейку отсталых дегенератов

тебе бы для начала понять что ты делаешь и как а потом уже пытаться вывозить за базар дружочек))
теперь слушай мя сюда
в тот линк чо ты мне кинул какие то тоже дефектные проблемы

передача неверного размера памяти в VirtualProtect
не проверяется успех VirtualProtect
неверный расчет смещения для trampoline jmp
это прям минимальные чо я увидел за 2 секунды в твоем говно коде сынок хуйни и отсосник моего дика под провокациями своей бабки и своего мертвого деда
мне не интересно вести с тобой диалог, ты не понимаешь о чем пишешь:
я не делаю ничего на луа
Так что на твои хуевые потуги я больше внимания обращать не буду.
после __stdcall сразу стало понятно, что ты пишешь по ответу из чата гпт, сам не протестировав код 🤷‍♂️
 
и наверное самое главное, что я лишь переписал код как он есть под апи скита со скрипта с нла, при этом этот скрипт доступен на маркете нла и он опенсурс, не думаю, что администрация нла пропустила бы нерабочий код себе на маркет
давай так, найди хоть одну тему, где я выложил спащенный код.
Либо ты соврал
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
и наверное самое главное, что я лишь переписал код как он есть под апи скита со скрипта с нла, при этом этот скрипт доступен на маркете нла и он опенсурс, не думаю, что администрация нла пропустила бы нерабочий код себе на маркет
я и не говорил что он не рабочий
я лишь сказал о том что он может некоторые приколы выдавать на которые я указал выше
тебе бы для начала разобраться в ситуации и понять что я никакой агрессии к тебе изначально не проявлял
 
я и не говорил что он не рабочий
я лишь сказал о том что он может некоторые приколы выдавать на которые я указал выше
тебе бы для начала разобраться в ситуации и понять что я никакой агрессии к тебе изначально не проявлял
интересно, ты не зная луа и то, как там реализованы поинтеры как гений одним взглядом определил где появляются приколы, притом, что я сам отлаживал данный код, и работает он толкьо в таком виде, потому что не дереференсинг, ни смена соглашения о вызове никак не приводят скрипт в рабочее состояние.
клеймо от тебя долбаеба заработаю? я не знаю кто ты и что ты мне поебать на тебя
как угодно можешь воспринимать мою инфу и думать что ты прав(хотя это не так)
так ты не знаешь, о чем говоришь чел, ты насмотрелься хаудихо и думаешь что самый умный, лезешь в тему, в которой 0
ты просто выскочка и все
только и можешь обзывать людей пастерами, без пруфов, в мое время за такое рид онли на 3 месяца давали
то, что ты чето там выдумал не отменяет факта, что если сделать как ты сказал, скрипт просто не будет работать
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
интересно, ты не зная луа и то, как там реализованы поинтеры как гений одним взглядом определил где появляются приколы, притом, что я сам отлаживал данный код, и работает он толкьо в таком виде, потому что не дереференсинг, ни смена соглашения о вызове никак не приводят скрипт в рабочее состояние.

так ты не знаешь, о чем говоришь чел, ты насмотрелься хаудихо и думаешь что самый умный, лезешь в тему, в которой 0
ты просто выскочка и все
только и можешь обзывать людей пастерами, без пруфов, в мое время за такое рид онли на 3 месяца давали
это все очень круто очень
я тебя начал обзывать после того как ты начал на меня какую то хуйню катить
поэтому мне похуй
да немного почитав крутые вещи в lua jit, ffi соглашения о вызове работают немного иначе чем в классическом c/c++ поэтому __thiscall в твоем коде именно так и должен быть чтобы корректно вызывать функции через ffi попытка сменить на __stdcall ломает логику из за особенностей lua jit
на счет всего остального я не отказываюсь длина хука может быть разной и это правда но 5 байтов это минимальный размер для jmp инструкции
и так далее мне лень уже чет те расписывать
 
на счет всего остального я не отказываюсь длина хука может быть разной и это правда но 5 байтов это минимальный размер для jmp инструкции
и так далее мне лень уже чет те расписывать
минимальный размер jmp это 2 байта:grinning: максимальный джамп может достигать 6 байтов максимум, но тут джамп на релятивный адрес в 32 битной системе. максимум 5 байтов
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
минимальный размер jmp это 2 байта:grinning: максимальный джамп может достигать 6 байтов максимум, но тут джамп на релятивный адрес в 32 битной системе. максимум 5 байтов
2 байта это скорее короткий jmp с 8 битным смещением но он ограничен диапазоном -128..+127 байт и для хуков его использовать нельзя
джамп на релятивный адрес в 32 битной системе. максимум 5 байтов
я говорил про длину а 5 в твоем коде это количество байт оригинального кода которые ты заменяешь на jmp чтобы поставить хук
если ты затираешь меньше 5 байт хук просто не работает если больше норм просто остальное дополняешь nop`ами или переносишь в trampoline
 
я говорил про длину а 5 в твоем коде это количество байт оригинального кода которые ты заменяешь на jmp чтобы поставить хук
если ты затираешь меньше 5 байт хук просто не работает если больше норм просто остальное дополняешь nop`ами или переносишь в trampoline
так там и так trampoline забит нопами изночально, даже если я заменю 4 байта, в которых только 3 будут джампом, то все равно 4 байт будет нопом. или что ты имеешь в виду? и вообще прчием тут пять? если len всегда можно сделать меньше? пятерка там только как размер трамплина, ведь больше 5 байт джамп там не получится.
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
даже если я заменю 4 байта, в которых только 3 будут джампом
jmp не занимает 3 байта он всегда 5(если это e9 rel32)
даже если ты добавишь nop все равно затирается оригинальный код и нужно затереть целиком 5 байт оригинального кода чтобы вставить хук
если len всегда можно сделать меньше
len должен быть >= 5 и должен покрывать целые инструкции
нельзя просто сделать len меньше если ты хочешь сделать jmp потому что он требует 5 байт пространства
 
jmp не занимает 3 байта он всегда 5(если это e9 rel32)
даже если ты добавишь nop все равно затирается оригинальный код и нужно затереть целиком 5 байт оригинального кода чтобы вставить хук

len должен быть >= 5 и должен покрывать целые инструкции
нельзя просто сделать len меньше если ты хочешь сделать jmp потому что он требует 5 байт пространства
изначальный вопрос, зачем делать лен меньше 5? кто так сделает? никто так не делает, доеб никчему
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
насчет указателя на функцию в втейбле, я сейчас даже специально протестил, каст к поинтеру -> хук в никуда(оригинальная функция не меняется), дереференсинг поинтера -> моменталнный краш, то есть vtable + ind луа, пишет в регистр не lea'ом из за которого будет поинтер на поинтер, а mov'ом получая адрес конкретной функции
 
Обратите внимание, пользователь заблокирован на форуме. Не рекомендуется проводить сделки.
дереференсинг поинтера -> моменталнный краш
потому что ты получаешь адрес по адресу функции то есть лезешь по адресу .text секции(где находятся байты самой функции) и читаешь его как intptr_t что приводит к обращению к невалидной памяти
на счет всего остального ладно
 
потому что ты получаешь адрес по адресу функции
в таком случае адрес функции это и есть vtable+ind, но ты же и писал, что это хуйня на самом деле будет памятью содержащим поинтер на функцию
 
Назад
Сверху Снизу