Код:
local ffi = require('ffi')
ffi.cdef[[
typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
struct voicedata_t {
char pad_0000[8];
uint32_t client;
uint32_t audible_mask;
uint64_t xuid;
void* voice_data_;
uint32_t proximity;
uint32_t format;
uint32_t sequence_bytes;
uint32_t section_number;
uint32_t uncompressed_sample_offset;
};
]]
local detour = (function()
local detour_lib = {}
local cast = ffi.cast
local copy = ffi.copy
local new = ffi.new
local typeof = ffi.typeof
local tonumber = tonumber
local insert = table.insert
local function opcode_scan(module, pattern, offset)
local sig = client.find_signature(module, pattern)
if not sig then
error(string.format('failed to find signature: %s', module))
end
return cast('uintptr_t', sig) + (offset or 0)
end
local jmp_ecx = opcode_scan('engine.dll', '\xFF\xE1')
local get_proc_addr = cast('uint32_t**', cast('uint32_t', opcode_scan('engine.dll', '\xFF\x15\xCC\xCC\xCC\xCC\xA3\xCC\xCC\xCC\xCC\xEB\x05')) + 2)[0][0]
local fn_get_proc_addr = cast('uint32_t(__fastcall*)(unsigned int, unsigned int, uint32_t, const char*)', jmp_ecx)
local get_module_handle = cast('uint32_t**', cast('uint32_t', opcode_scan('engine.dll', '\xFF\x15\xCC\xCC\xCC\xCC\x85\xC0\x74\x0B')) + 2)[0][0]
local fn_get_module_handle = cast('uint32_t(__fastcall*)(unsigned int, unsigned int, const char*)', jmp_ecx)
local proc_cache = {}
local function proc_bind(module_name, function_name, typedef)
local cache_key = module_name .. function_name
if proc_cache[cache_key] then
return proc_cache[cache_key]
end
local ctype = typeof(typedef)
local module_handle = fn_get_module_handle(get_module_handle, 0, module_name)
local proc_address = fn_get_proc_addr(get_proc_addr, 0, module_handle, function_name)
local call_fn = cast(ctype, jmp_ecx)
local fn = function(...)
return call_fn(proc_address, 0, ...)
end
proc_cache[cache_key] = fn
return fn
end
local native_virtualprotect = proc_bind(
'kernel32.dll',
'VirtualProtect',
'int(__fastcall*)(unsigned int, unsigned int, void* lpAddress, unsigned long dwSize, unsigned long flNewProtect, unsigned long* lpflOldProtect)'
)
local function virtualprotect(lpAddress, dwSize, flNewProtect, lpflOldProtect)
return native_virtualprotect(cast('void*', lpAddress), dwSize, flNewProtect, lpflOldProtect)
end
detour_lib.hooks = {}
function detour_lib.new(typedef, callback, hook_addr, size)
size = size or 5
local hook = {}
local mt = {}
local old_prot = new('unsigned long[1]')
local org_bytes = new('uint8_t[?]', size)
copy(org_bytes, hook_addr, size)
local detour_addr = tonumber(cast('intptr_t', cast('void*', cast(typedef, callback))))
hook.call = cast(typedef, hook_addr)
mt.__call = function(self, ...)
self.stop()
local res = self.call(...)
self.start()
return res
end
local hook_bytes = new('uint8_t[?]', size, 0x90)
hook_bytes[0] = 0xE9
cast('int32_t*', hook_bytes + 1)[0] = (detour_addr - tonumber(cast('intptr_t', hook_addr)) - 5)
hook.status = false
local function set_status(bool)
hook.status = bool
virtualprotect(hook_addr, size, 0x40, old_prot)
copy(hook_addr, bool and hook_bytes or org_bytes, size)
virtualprotect(hook_addr, size, old_prot[0], old_prot)
end
hook.stop = function() set_status(false) end
hook.start = function() set_status(true) end
hook.start()
insert(detour_lib.hooks, hook)
return setmetatable(hook, mt)
end
function detour_lib.unhook_all()
for _, hook in pairs(detour_lib.hooks) do
if hook.status then
hook.stop()
end
end
proc_cache = {}
collectgarbage('collect')
end
client.set_event_callback('shutdown', detour_lib.unhook_all)
return detour_lib
end)()
local signature = "\x55\x8B\xEC\x83\xE4\xF8\xA1\xCC\xCC\xCC\xCC\x81\xEC\xCC\xCC\xCC\xCC\x53\x56\x8B\xF1\xB9\xCC\xCC\xCC\xCC\x57\xFF\x50\x34\x8B\x7D\x08"
local sub_102866A0 = client.find_signature("engine.dll", signature)
if not sub_102866A0 then
error("Failed to find sub_102866A0 signature")
end
local function hook_sub_ANA0(this, voice_data)
local a2 = voice_data.client
local v17 = voice_data.sequence_bytes
local v16 = voice_data.section_number
local v2 = voice_data.uncompressed_sample_offset
print(string.format("Voice packet: client=%d, sequence_bytes=%d, section_number=%d, uncompressed_sample_offset=%d",
a2, v17, v16, v2))
return detour_lib.hooks[1].call(this, voice_data)
end
local hook = detour.new("char(__thiscall*)(void*, struct voicedata_t*)", hook_sub_ANA0, sub_102866A0)