Lua Arizona Возвращаем старый VIP чат на Arizona RP

kernelich

Участник
28
19
Аризона опять чёт мутит, а так _chat.asi перехватывает сообщение от сервера с item, подменяет там и уже дальше прокидывает как бы копию сообщения.


Lua:
local hooks = require 'hooks'
local ffi = require 'ffi'
local sampev = require 'samp.events'

ffi.cdef [[
    void* VirtualAlloc(void* lpAddress, uint32_t dwSize, uint32_t flAllocationType, uint32_t flProtect);
]]

ffi.cdef [[
    void* GetModuleHandleA(const char* lpModuleName);
]]

function patternScan(module, pattern)
    local base = ffi.cast('uint8_t*', ffi.C.GetModuleHandleA(module))
    if base == nil then return nil end

    local dos = ffi.cast('uint32_t*', base)
    local nt = ffi.cast('uint32_t*', base + dos[15] / 4)
    local size = nt[20]

    local pat, mask = {}, {}

    for byte in pattern:gmatch("%S+") do
        if byte == "?" then
            table.insert(pat, 0)
            table.insert(mask, false)
        else
            table.insert(pat, tonumber(byte, 16))
            table.insert(mask, true)
        end
    end

    for i = 0, size - #pat do
        local found = true
        for j = 1, #pat do
            if mask[j] and base[i + j - 1] ~= pat[j] then
                found = false
                break
            end
        end
        if found then
            return tonumber(ffi.cast('uintptr_t', base + i))
        end
    end

    return nil
end

local STR_LEN_OFFSET  = 9
local STR_DATA_OFFSET = 11
local SCRATCH_SIZE    = 4096

local ANNOUNCE_TAG    = string.char(0xCE, 0xE1, 0xFA, 0xFF, 0xE2, 0xEB, 0xE5, 0xED, 0xE8, 0xE5, 0x3A)

local RULES           = {
    [":uf280::uf286::uf290:"] = "{d568d5}[PREMIUM]",
    [":uf280::uf286::uf291:"] = "{d568d5}[PREMIUM]",
    [":uf280::uf286::uf292:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf293:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf294:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf295:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf296:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf297:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf298:"] = "{ffd632}[FOREVER]",
    [":uf280::uf286::uf299:"] = "{ffd632}[FOREVER]",
    [":uf280::uf287:"]        = "{ffd632}[ADMIN]",
    [":uf280::uf285:"]        = "{6891db}[VIP]",
    [":uf280::uf286:"]        = "{d568d5}[PREMIUM]",

    [":uf230:"]               = "{788FD4}[VIP]",
    [":uf231:"]               = "{B56CFF}[PREMIUM]",
    [":uf232:"]               = "{B56CFF}[FOREVER]",
    [":uf233:"]               = "{DF8426}[FOREVER]",
    [":uf234:"]               = "{D7A926}[FOREVER]",
    [":uf235:"]               = "{F2C455}[ADMIN]",
    [":uf236:"]               = "{E75773}[VIP ADV]",
    [":uf237:"]               = "{E75773}[VIP ADV]",
    [":uf238:"]               = "{E75773}[VIP ADV]",
    [":uf239:"]               = "{E75773}[VIP ADV]",
    [":uf23a:"]               = "{E75773}[VIP ADV]",

    -- анонсы
    [":uf23b:"]               = ":envelope: {079C1C}" .. ANNOUNCE_TAG,
    [":uf23c:"]               = ":envelope: {FCAA4D}[VIP] " .. ANNOUNCE_TAG,

    -- короны
    [":uf240:"]               = "",
    [":uf241:"]               = "",
    [":uf242:"]               = "",
    [":uf243:"]               = "",
    [":uf244:"]               = "",
}
function escapePattern(s)
    return (s:gsub("[%(%)%.%%%+%-%*%?%[%]%^%$]", "%%%1"))
end

function buildRuleList(map)
    local list = {}
    for from, to in pairs(map) do
        list[#list + 1] = { from = from, to = to, pat = escapePattern(from) }
    end
    table.sort(list, function(a, b) return #a.from > #b.from end)
    return list
end

local RULE_LIST = buildRuleList(RULES)

function applyReplacements(text)
    for _, rule in ipairs(RULE_LIST) do
        text = text:gsub(rule.pat, rule.to)
    end
    text = text:gsub("  +", " ")
    text = text:gsub(" :", ":")
    return text
end

local SCRATCH = ffi.cast('uint8_t*', ffi.C.VirtualAlloc(nil, SCRATCH_SIZE, 0x1000, 0x40))

local myHook

function onChatPacket(packet)
    local pktPtr     = ffi.cast('uint8_t*', packet)
    local dataField  = ffi.cast('uint8_t**', pktPtr + 0x10)
    local sizeField  = ffi.cast('uint32_t*', pktPtr + 0x08)
    local data, size = dataField[0], sizeField[0]

    if data == nil or size < STR_DATA_OFFSET + 1 or data[0] ~= 0xDC or data[1] ~= 0xD2 then
        return myHook.call(packet)
    end

    local oldStrLen = ffi.cast('uint16_t*', data + STR_LEN_OFFSET)[0]
    if oldStrLen == 0 or STR_DATA_OFFSET + oldStrLen > size then
        return myHook.call(packet)
    end
    local text = ffi.string(data + STR_DATA_OFFSET, oldStrLen)
    local newText = applyReplacements(text)

    if newText == text then
        return myHook.call(packet)
    end

    local newStrLen = #newText
    local tailLen = size - (STR_DATA_OFFSET + oldStrLen)
    local newPktSize = STR_DATA_OFFSET + newStrLen + tailLen

    if newPktSize > SCRATCH_SIZE then
        return myHook.call(packet)
    end

    -- [header 9b][uint16 newStrLen][newText][tail]
    ffi.copy(SCRATCH, data, STR_LEN_OFFSET)
    ffi.cast('uint16_t*', SCRATCH + STR_LEN_OFFSET)[0] = newStrLen
    ffi.copy(SCRATCH + STR_DATA_OFFSET, newText, newStrLen)
    if tailLen > 0 then
        ffi.copy(SCRATCH + STR_DATA_OFFSET + newStrLen, data + STR_DATA_OFFSET + oldStrLen, tailLen)
    end

    dataField[0] = SCRATCH
    sizeField[0] = newPktSize
    local result = myHook.call(packet)
    dataField[0] = data
    sizeField[0] = size

    return result
end

--myHook = hooks.jmp.new('void(__cdecl*)(int)', onChatPacket, 0x6B70FEEE, 5, true)

function sampev.onServerMessage(color, text)
    print(text)
    if text:find(":uf2", 1, true) then
        local newText = applyReplacements(text)
        if newText ~= text then
            return { color, newText }
        end
    end
end

function main()
    while not isSampAvailable() do wait(100) end
    wait(2000)

    local addr = patternScan("_chat.asi", "68 E4 02 00 00 ? ? ? ? ?")

    if addr == nil then
        print("hook not found")
        return
    end

    print(string.format("hook found at 0x%X", addr))

    myHook = hooks.jmp.new('void(__cdecl*)(int)', onChatPacket, addr, 5, true)

    wait(-1)
end



На счёт сигнатуры не уверен что будет работать у всех, не тестил
 
  • Нравится
Реакции: OpJLaH и .Makarov.

chapo

tg/inst: @moujeek
Всефорумный модератор
9,235
12,650
@pewpewpewpew Замени луа на гитхабе на json. Мы не можем регулярно проверять луашку с гита на наличие вредоносов
 

pewpewpewpew

Известный
Автор темы
542
150
@pewpewpewpew Замени луа на гитхабе на json. Мы не можем регулярно проверять луашку с гита на наличие вредоносов
json мне игру ложит моментально. я не могу его юзать как таблицу. поэтому решение было спарсить на луа и юзать его

@pewpewpewpew Замени луа на гитхабе на json. Мы не можем регулярно проверять луашку с гита на наличие вредоносов
поковырялся чуть-чуть, нашел проблему, починил. залил новый файл с json


добавили уровни випок в короне. корона без уровня - по прежнему убивается. скрипт не сломался.
выглядит это примерно так:
1777954713257.png


убивать короны с уровнем или нет - я хз. мне даже и понравилось чет. в любом случае, кому это будет необходимо - пишите в теме.

кто хочет и умеет - можете сами убивать их. юфки от первого по десятый уровень:
:uf245: :uf246: :uf247: :uf248: :uf249: :uf24a: :uf24b: :uf24c: :uf24d: :uf24e:
1777954662703.png
 
Последнее редактирование:

pewpewpewpew

Известный
Автор темы
542
150
обновил. заменил lua таблицу на json таблицу (во избежание неприятных моментов с возможной подгрузкой вредоноса, сделано по просьбе ВФМ). если нужна будет версия с убиванием уровней вип - черканите.
1778077971689.png
 

kyrtion

Известный
1,398
540
@pewpewpewpew Замени луа на гитхабе на json. Мы не можем регулярно проверять луашку с гита на наличие вредоносов
а что, если бх создаст группу в гитхаб, а затем создает репозитории для разраба. каждый коммит проверяет модеры и пускает в ветку.
что скажешь?