Загадка века или allocateMemory

Vintik

Через тернии к звёздам
Автор темы
Проверенный
1,526
1,011
Может это я дурак, но...
Почему не работает этот код?
Изначально тут было две функции, каждая создавала хук: то есть джамп в заранее выделенную область с помощью allocateMemory, далее запись значения в регистр и возврат.
Всё бы хорошо, но я в main-е вызывал эту функции сначала 1ю, потом сразу же 2ю. И прикол в том, что каждая по отдельности работает, а вместе - нихера не работает.
Решил объединить в одну функцию (выделил первую часть функции - изначально это была 1я из 2х функций) - результат аналогичный. Каким-то странным образом работает часть, причём в памяти gta_sa.exe и samp.dll джампы записываются всегда, а проблема именно с записью в выделенную память allocateMemory. Я уже всю голову сломал, что же я упустил? Вроде всё ок.
Lua:
local wm = require 'windows.message'
local memory = require 'memory'

local h_was_just_pressed = false

local sampdll = 0
local alloc_for_function_address = 0
local alloc_for_function_address_2 = 0
local alloc_for_byte_address = 0
local alloc_for_dword_address = 0

function main()
    if not isSampLoaded() or not isSampfuncsLoaded() then return end
    while not isSampAvailable() do wait(0) end
    sampdll = getModuleHandle('samp.dll')
    AllocateMemoryForValues()
    AllocateMemoryAndSetFunction()
    wait(-1)
end

function AllocateMemoryAndSetFunction()
    alloc_for_function_address = allocateMemory(21) -- выделяем место для функции

    local function_bytes = { 233, 0,0,0,0,  144, 144, 144, 144, 144 } -- сохраняем байты (для прыжка в функцию)
    for i = 0, 9 do -- от 0 до 9 включительно (10 раз)
        memory.setint8(sampdll + 30775 + i, function_bytes[i + 1], true)
    end
    local jmp_address = alloc_for_function_address - (sampdll + 30775 + 5) -- считаем относительный адрес прыжка
    memory.setint32(sampdll + 30775 + 1, jmp_address, true)

    function_bytes = { 199, 134, 167, 1, 0, 0, 1, 0, 0, 0,  137, 53, 0,0,0,0,  233, 0,0,0,0 } -- сохраняем байты (для функции)
    for i = 0, 20 do -- от 0 до 20 включительно (21 раз)
        memory.setint8(alloc_for_function_address + i, function_bytes[i + 1], true)
    end
    memory.setint32(alloc_for_function_address + 12, alloc_for_byte_address, true)
    jmp_address = (sampdll + 30785) - (alloc_for_function_address + 21) -- считаем относительный адрес прыжка
    memory.setint32(alloc_for_function_address + 17, jmp_address, true)

    alloc_for_function_address_2 = allocateMemory(18) -- выделяем место для функции

    local function_bytes_2 = { 233, 0,0,0,0,  144, 144 } -- сохраняем байты (для прыжка в функцию)
    for i = 0, 6 do -- от 0 до 6 включительно (7 раз)
        memory.setint8(6823244 + i, function_bytes_2[i + 1], true)
    end
    local jmp_address_2 = alloc_for_function_address_2 - (6823244 + 5) -- считаем относительный адрес прыжка
    memory.setint32(6823244 + 1, jmp_address_2, true)

    function_bytes_2 = { 199, 4, 190, 0, 0, 0, 0,  137, 53, 0,0,0,0,  233, 0,0,0,0 } -- сохраняем байты (для функции)
    for i = 0, 17 do -- от 0 до 17 включительно (18 раз)
        memory.setint8(alloc_for_function_address_2 + i, function_bytes_2[i + 1], true)
    end
    memory.setint32(alloc_for_function_address_2 + 9, alloc_for_dword_address, true)
    jmp_address_2 = 6823251 - (alloc_for_function_address_2 + 18) -- считаем относительный адрес прыжка
    memory.setint32(alloc_for_function_address_2 + 14, jmp_address_2, true)
end

function AllocateMemoryForValues()
    alloc_for_byte_address = allocateMemory(4)
    memory.setint32(alloc_for_byte_address, 0, true)
    alloc_for_dword_address = allocateMemory(4)
    memory.setint32(alloc_for_dword_address, 0, true)
end
 
Решение
Короче, решения, которые нашёл я:
1) Выделять память с помощью allocateMemory 1 раз.
Если количество памяти заранее неизвестно (например, нужно выделить для динамического массива) - каждый раз "перевыделять" заново (но уже другое количество байт), сохраняя в памяти скрипта все данные из старой выделенной памяти, а потом их записывать в новую.
Гемор, потому что если выделять память для строки (массива символов заранее неизвестной длины) и для функции хука, к примеру, то при перевыделении нужно каждый раз меня адреса JMP в хуках. Лучше не связываться, но на крайняк пойдёт.
2) Использовать ffi.new (работает как new в C) и забыть про эту проблему.

Vintik

Через тернии к звёздам
Автор темы
Проверенный
1,526
1,011
Короче, решения, которые нашёл я:
1) Выделять память с помощью allocateMemory 1 раз.
Если количество памяти заранее неизвестно (например, нужно выделить для динамического массива) - каждый раз "перевыделять" заново (но уже другое количество байт), сохраняя в памяти скрипта все данные из старой выделенной памяти, а потом их записывать в новую.
Гемор, потому что если выделять память для строки (массива символов заранее неизвестной длины) и для функции хука, к примеру, то при перевыделении нужно каждый раз меня адреса JMP в хуках. Лучше не связываться, но на крайняк пойдёт.
2) Использовать ffi.new (работает как new в C) и забыть про эту проблему.
 

AdCKuY_DpO4uLa

Адский дрочер
Друг
315
667
Короче, решения, которые нашёл я:
1) Выделять память с помощью allocateMemory 1 раз.
Если количество памяти заранее неизвестно (например, нужно выделить для динамического массива) - каждый раз "перевыделять" заново (но уже другое количество байт), сохраняя в памяти скрипта все данные из старой выделенной памяти, а потом их записывать в новую.
Гемор, потому что если выделять память для строки (массива символов заранее неизвестной длины) и для функции хука, к примеру, то при перевыделении нужно каждый раз меня адреса JMP в хуках. Лучше не связываться, но на крайняк пойдёт.
2) Использовать ffi.new (работает как new в C) и забыть про эту проблему.
Ещё не стоит забывать о том, что старую, не нужную память, которую ты уже выделял, нужно освобождать, иначе будет утечка, а из-за частых выделений памяти в скрипе, ты просто будешь забивать оперативку процесса
 
  • Нравится
  • Клоун
Реакции: Fott и Vintik