local ffi = require "ffi"
ffi.cdef [[
int __stdcall VirtualProtect(void* address, size_t size, unsigned long prot, unsigned long* prev_prot);
void* __stdcall VirtualAlloc(void* address, size_t size, unsigned long alloc_type, unsigned long prot);
int __stdcall VirtualFree(void* address, size_t size, unsigned long free_type);
void __stdcall MessageBoxA(int, const char*, const char*, int);
]]
local Kernel32 = ffi.load("Kernel32.dll")
local function showGameText(text, time, style)
local bs = raknetNewBitStream()
raknetBitStreamWriteInt32(bs, style)
raknetBitStreamWriteInt32(bs, time)
raknetBitStreamWriteInt32(bs, #text)
raknetBitStreamWriteString(bs, text)
raknetEmulRpcReceiveBitStream(73, bs)
end
--[[
original code with bug:
.text:101336E0 mov eax, [eax+4] <- bug here (EAX = 1)
.text:101336E3 test eax, eax
.text:101336E5 jz short loc_101336EB
.text:101336E7 mov byte ptr [eax+5], 1
fixed code:
fixed code is hooked at 101336E0 (jmp will be placed)
cmp eax, 0xffff <- actual fix
jb return <- actual fix
mov eax, dword ptr [eax + 4]
test eax, eax
jz return
mov byte ptr [eax+5], 1
return:
jmp 0x101336EB
]]
local FIXED_CODE = "\x3d\xff\xff\x00\x00\x72\x0b\x8b\x40\x04\x85\xc0\x74\x04\xc6\x40\x05\x01\xe9\xd4\x36\x13\x10"
local OFFSET_TO_JUMP = 19
local helper_address_voidptr
local helper_address_uintptr
local original_code = ffi.new("char[11]")
local old_prot = ffi.new("unsigned long[1]")
local function fixCrash()
local d3d9_base = getModuleHandle("C:\\Windows\\SysWOW64\\d3d9.dll")
if d3d9_base == 0 then
ffi.C.MessageBoxA(0, "DAUN", "No d3d9!!!\nAnd it's not my fault", 0)
print("no d3d9!!! can't fix crash. admini pobedili(((")
return
end
helper_address_voidptr = Kernel32.VirtualAlloc(nil, #FIXED_CODE, 0x00001000, 0x40)
helper_address_uintptr = tonumber(ffi.cast("uintptr_t", helper_address_voidptr))
ffi.copy(helper_address_voidptr, FIXED_CODE)
ffi.cast("uintptr_t*", helper_address_uintptr + OFFSET_TO_JUMP)[0] =
(d3d9_base + 0x1336EB) -
(helper_address_uintptr + OFFSET_TO_JUMP + 4)
local hook_place_voidptr = ffi.cast("void*", d3d9_base + 0x1336E0)
Kernel32.VirtualProtect(hook_place_voidptr, 11, 0x40, old_prot)
ffi.copy(original_code, hook_place_voidptr, 11)
ffi.cast("char*", d3d9_base + 0x1336E0)[0] = 0xE9
ffi.cast("uintptr_t*", d3d9_base + 0x1336E1)[0] = helper_address_uintptr - (d3d9_base + 0x1336E0 + 5)
Kernel32.VirtualProtect(hook_place_voidptr, 11, old_prot[0], old_prot)
print("crash fixed. sosat admini")
end
addEventHandler("onScriptTerminate", function(script, quitGame)
if script == thisScript() then
local d3d9_base = getModuleHandle("d3d9.dll")
local hook_place_voidptr = ffi.cast("void*", d3d9_base + 0x1336E0)
Kernel32.VirtualProtect(hook_place_voidptr, 11, 0x40, old_prot)
ffi.copy(hook_place_voidptr, original_code, 11)
Kernel32.VirtualProtect(hook_place_voidptr, 11, old_prot[0], old_prot)
end
end)
function main()
while not isSampAvailable() do wait(0) end
fixCrash()
sampRegisterChatCommand("crr", function()
lua_thread.create(function()
wait(0)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 1000, 0)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 2000, 1)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 3000, 2)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 4000, 3)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 5000, 4)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 6000, 5)
showGameText("•¤¶§!$$%&'()*+,-./01~!@#$^&*()_-+={[}]:;'<,>.?/", 7000, 6)
end)
end)
wait(-1)
end