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

  • Автор темы Автор темы amiiiil
  • Дата начала Дата начала
в таком случае адрес функции это и есть vtable+ind, но ты же и писал, что это хуйня на самом деле будет памятью содержащим поинтер на функцию
vtable + ind это просто адрес ячейки содержащей указатель на функцию
в луа через ffi vtable[ind] уже дает сам адрес функции
 
vtable + ind = vtable[ind], это тоже самое, арифметика указателей 🤷‍♂️
или ты про дереференсинг? который и так крашит
не совсем
давай разберем
если ты сделаешь VirtualProtect(vtable + ind, ...) то ты меняешь защиту на адресе где лежит указатель то есть внутри самой втейбл
а если сделаешь VirtualProtect(vtable[ind], ...) то меняешь защиту уже на функции куда втейбл указывает
upd: все зависит от того хочешь ты заменить указатель или байты по адресу
 
не совсем
давай разберем
если ты сделаешь VirtualProtect(vtable + ind, ...) то ты меняешь защиту на адресе где лежит указатель то есть внутри самой втейбл
а если сделаешь VirtualProtect(vtable[ind], ...) то меняешь защиту уже на функции куда втейбл указывает
это два разных случая, мы говорим о методе хука или анхука?
 
Код:
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
ачо вообще за движуха с LUA скриптами? Разве не было всегда так что кфг было, или луа скрипты это типо продвинутые кфг? Чесно вообще не шарю что там с кской
 
ачо вообще за движуха с LUA скриптами? Разве не было всегда так что кфг было, или луа скрипты это типо продвинутые кфг? Чесно вообще не шарю что там с кской
луа и кфг это разные вещи, кфг - настройки чита(настройки луа тоже), луа же в свою очередь некий аддон, который может расширить функционал чита исходя из его апи(набор имплементированных на стороне чита функций доступных внутри скрипта) либо ffi - некий мост между Си и Луа.
Как пример на луа можно написать скрипты взаимодействующие как с самим читом(поменять значения в меню по кнопке или быстро изменять какой либо стейт) или напрямую с игрой если есть такая возможность(например доступ к createmove через луа апи в котором можно самому поставить yaw и pitch, или посмотреть сколько комманд чокает клиент)
 
луа и кфг это разные вещи, кфг - настройки чита(настройки луа тоже), луа же в свою очередь некий аддон, который может расширить функционал чита исходя из его апи(набор имплементированных на стороне чита функций доступных внутри скрипта) либо ffi - некий мост между Си и Луа.
Как пример на луа можно написать скрипты взаимодействующие как с самим читом(поменять значения в меню по кнопке или быстро изменять какой либо стейт) или напрямую с игрой если есть такая возможность(например доступ к createmove через луа апи в котором можно самому поставить yaw и pitch, или посмотреть сколько комманд чокает клиент)
поэтому инвайт в gamesense столько стоит?
 
поэтому инвайт в gamesense столько стоит?
нет :CoolStoryBob: инвайт в gamesense стоит много, потому что на него есть спрос и потому что продавать инвайты в скит запрещено, а тем более запрещена регистрация на форуме лиц проживающих на территориях бывших\стран СНГ. Именно по этому инвайты в скит стоят так необоснованно дорого.
 
не совсем
давай разберем
если ты сделаешь VirtualProtect(vtable + ind, ...) то ты меняешь защиту на адресе где лежит указатель то есть внутри самой втейбл
а если сделаешь VirtualProtect(vtable[ind], ...) то меняешь защиту уже на функции куда втейбл указывает
upd: все зависит от того хочешь ты заменить указатель или байты по адресу
Потрошитель гпт разлогинься
 
дима приди порядок наведи
 
Код:
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 function reinterpret_cast(addr, cdecl_type)
    return ffi.cast(cdecl_type, tonumber(ffi.cast("intptr_t", addr)))
end

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],
}

get_pattern.fnGetModuleHandle = reinterpret_cast(get_pattern.GetModuleHandlePtr, "void*(__cdecl*)(void*, const char*)")
get_pattern.fnGetProcAddress  = reinterpret_cast(get_pattern.GetProcAddressPtr,  "void*(__cdecl*)(void*, void*, const char*)")

get_pattern.lib = {
    kernel32 = get_pattern.fnGetModuleHandle(nil, "kernel32.dll")
}

get_pattern.export = {
    kernel32 = {
        VirtualProtect = reinterpret_cast(
            get_pattern.fnGetProcAddress(nil, get_pattern.lib.kernel32, "VirtualProtect"),
            "BOOL(__stdcall*)(LPVOID, SIZE_T, DWORD, PDWORD)"
        ),
        VirtualAlloc = reinterpret_cast(
            get_pattern.fnGetProcAddress(nil, get_pattern.lib.kernel32, "VirtualAlloc"),
            "LPVOID(__stdcall*)(LPVOID, SIZE_T, DWORD, DWORD)"
        )
    }
}

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 nil
            end

            chook.ogfunc[ind] = { vtable[ind], len }

            get_pattern.export.kernel32.VirtualProtect(
                ffi.cast("void*", ffi.cast("intptr_t*", vtable) + ind),
                ffi.sizeof("intptr_t"),
                0x40,
                chook.oldProto
            )

            vtable[ind] = ffi.cast("intptr_t", ffi.cast(typestr, __func))

            get_pattern.export.kernel32.VirtualProtect(
                ffi.cast("void*", ffi.cast("intptr_t*", vtable) + ind),
                ffi.sizeof("intptr_t"),
                chook.oldProto[0],
                chook.oldProto
            )

            return ffi.cast(typestr, chook.ogfunc[ind][1])
        end

        chook.data.unhook = function(ind)
            if not chook.ogfunc[ind] then return end

            get_pattern.export.kernel32.VirtualProtect(
                ffi.cast("void*", ffi.cast("intptr_t*", chook.vtable) + ind),
                ffi.sizeof("intptr_t"),
                0x40,
                chook.oldProto
            )

            local trampoline_size = chook.ogfunc[ind][2]
            local alloc = get_pattern.export.kernel32.VirtualAlloc(nil, trampoline_size, 0x1000, 0x40)
            local trampoline = ffi.new("uint8_t[?]", trampoline_size, 0x90)

            trampoline[0] = 0xE9
            ffi.cast("int32_t*", trampoline + 1)[0] =
                tonumber(ffi.cast("intptr_t", chook.ogfunc[ind][1])) - tonumber(ffi.cast("intptr_t", alloc)) - 5

            ffi.copy(alloc, trampoline, trampoline_size)
            chook.vtable[ind] = ffi.cast("intptr_t", alloc)

            get_pattern.export.kernel32.VirtualProtect(
                ffi.cast("void*", ffi.cast("intptr_t*", chook.vtable) + ind),
                ffi.sizeof("intptr_t"),
                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

return hook
 
Назад
Сверху Снизу