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

  • Автор темы Автор темы amiiiil
  • Дата начала Дата начала
Read Only
Read Only
Статус
Оффлайн
Регистрация
2 Май 2022
Сообщения
460
Реакции
68
есть ли у кого? мне нужно именно хукнуть таблицу, пожалуйста! :cryingcat:
 
есть ли у кого? мне нужно именно хукнуть таблицу, пожалуйста! :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, но ты же и писал, что это хуйня на самом деле будет памятью содержащим поинтер на функцию
 
Назад
Сверху Снизу