- Статус
- Оффлайн
- Регистрация
- 1 Фев 2020
- Сообщения
- 1,333
- Реакции
- 536
реализация просто капец, но это ведь не главное
C++:
local ffi = require 'ffi'
local bit = require 'bit'
local cast = ffi.cast
local typeof = ffi.typeof
local bor, lshift = bit.bor, bit.lshift
local void_ptr = typeof('void*')
local ulong_arr = typeof('unsigned long[1]')
local uint32_arr = typeof('uint32_t[1]')
local uintptr_t = typeof('uintptr_t')
local old_find_signature = client.find_signature
client.find_signature = function(module, pattern, offset)
local sig = old_find_signature(module, pattern)
if sig then
return cast(uintptr_t, sig) + (offset or 0)
end
end
local jmp_ecx = client.find_signature('engine.dll', '\xFF\xE1')
local get_proc_addr = cast('uint32_t**', cast('uint32_t', client.find_signature('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', client.find_signature('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 function proc_bind(module_name, function_name, typedef)
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)
return function(...)
return call_fn(proc_address, 0, ...)
end
end
local native_virtual_protect = proc_bind(
'kernel32.dll',
'VirtualProtect',
'int(__fastcall*)(unsigned int, unsigned int, void*, unsigned long, unsigned long, unsigned long*)'
)
local protect_buf = ffi.new(ulong_arr)
local function virtual_protect(addr, size, new_protect)
return native_virtual_protect(cast(void_ptr, addr), size, new_protect, protect_buf)
end
local function write_bytes(address, data, size)
local ptr = cast(void_ptr, address)
virtual_protect(ptr, size, 0x40)
ffi.copy(ptr, data, size)
virtual_protect(ptr, size, protect_buf[0])
end
local color_buf = ffi.new(uint32_arr)
local function write_color(address, r, g, b, a)
color_buf[0] = bor(lshift(a, 24), lshift(b, 16), lshift(g, 8), r)
write_bytes(address, color_buf, 4)
end
local healthbar = {
is_patched = false,
original_bytes = ffi.new('uint8_t[35]', {
0x0F, 0xB6, 0x74, 0x24, 0x54, -- movzx esi,byte ptr [esp+54]
0xF3, 0x0F, 0x5C, 0xC1, -- subss xmm0,xmm1
0x81, 0xCE, 0x00, 0x50, 0xFF, 0xFF, -- or esi,0FFFF5000h
0xC1, 0xE6, 0x08, -- shl esi,08
0xF3, 0x0F, 0x58, 0xC2, -- addss xmm0,xmm2
0xF3, 0x0F, 0x11, 0x44, 0x24, 0x10, -- movss [esp+10],xmm0
0x0F, 0xB6, 0x44, 0x24, 0x10, -- movzx eax,byte ptr [esp+10]
0x0B, 0xF0 -- or esi,eax
}),
nop_bytes = ffi.new('uint8_t[30]', {
0x90, 0x90, 0x90, 0x90, -- 4340A4BE: nop nop nop nop
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -- 4340A4C2: nop nop nop nop nop nop
0x90, 0x90, 0x90, -- 4340A4C8: nop nop nop
0x90, 0x90, 0x90, 0x90, -- 4340A4CB: nop nop nop nop
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, -- 4340A4CF: nop nop nop nop nop nop
0x90, 0x90, 0x90, 0x90, 0x90, -- 4340A4D5: nop nop nop nop nop
0x90, 0x90 -- 4340A4DA: nop nop
}),
mov_instruction = ffi.new('uint8_t[5]', { 0xBE, 0xFF, 0xFF, 0xFF, 0xFF }),
patch = function(self)
if self.is_patched then return end
write_bytes(0x4340A4B9, self.mov_instruction, 5)
write_bytes(0x4340A4B9 + 5, self.nop_bytes, 30)
self.is_patched = true
end,
restore = function(self)
if not self.is_patched then return end
write_bytes(0x4340A4B9, self.original_bytes, 35)
self.is_patched = false
end
}
healthbar:patch()
local color_picker = ui.new_color_picker('LUA', 'A', 'Color', 255, 255, 255, 255)
local function on_color_change()
local r, g, b, a = ui.get(color_picker)
write_color(0x4340A4BA, r, g, b, a)
end
ui.set_callback(color_picker, on_color_change)
on_color_change()
client.set_event_callback('shutdown', function()
healthbar:restore()
end)