Исходник LuaJIT hook obfuscate/joiner

The Spark

Известный
Автор темы
656
690
решил посмотреть что к чему, так как довольно заманчивый заголовок темы. вот что получилось.
проверить, к сожалению, возможности нету. но я уверен, мой код будет незаметным.

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

давай разберем пример с функцией error. твой код может переопределить эту функцию, чтобы перехватывать ошибки и управлять их обработкой. Но в предоставленном мной коде, я сохранил оригинальную версию функции error в переменной original_error. Все вызовы original_error в коде будут использовать оригинальную функцию error, а не измененную твоим кодом.

таким образом, мой код обходит любые попытки твоего кода установить заглушки или переопределить поведение функций, используя оригинальные версии функций. это делает мой код "невидимым" для твоего кода, поскольку твой код не сможет перехватить или контролировать поведение моего, связанного с использованием этих функций.

методика обхода состоит в том, чтобы изолировать и сохранить оригинальные версии ключевых функций и объектов перед тем, как они могут быть переопределены или изменены. Такой подход позволяет обеспечить стабильное поведение кода, несмотря на попытки внешнего воздействия.

ничего личного. только опыт🤝.


bypassing nop.lua:
local ffi = require('ffi')

-- сохраняем оригинальные функции
local original_error = error
local original_setmetatable = setmetatable
local original_getmetatable = getmetatable
local original_rawset = rawset
local original_rawget = rawget

-- функция скачивания файла
function download_file(url, filename, callback)
    local requests = require("requests")
    local response = requests.get(url)
    if response.status_code == 200 then
        local file = io.open(filename, "wb")
        if file then
            file:write(response.content)
            file:close()
            if callback then
                callback(true)
            end
        else
            original_error("не удалось открыть файл")
        end
    else
        original_error("не удалось скачать файл")
    end
end

-- пример использования
download_file("https://example.com/file.txt", "downloaded_file.txt", function(success)
    if success then
        print("файл успешно скачан")
    else
        print("ошибка скачивания файла")
    end
end)
Возможно ты не понял, но nop.lua подгружается до загрузки скрипта, который мы собираемся проксировать.
Lua:
require('nop')
xpcall(fFunction, errorHandler)
Тот же эффект можно было достичь через setfenv, это я когда-нибудь перепишу

Как только подгружается nop.lua, глобальное окружение изменяется и скрипт более не имеет доступ к оригинальным функциям:
Lua:
-- сохраняем оригинальные функции
local original_error = error
local original_setmetatable = setmetatable
local original_getmetatable = getmetatable
local original_rawset = rawset
local original_rawget = rawget

original_error("myerror")

Заглушка в nop.lua:
Lua:
error = function(message, level)
    print('call error', message, level)
end
Выхлоп:
1680084526312.png


Сохраняя "оригинальные функции", в коде выше, ты уже сохраняешь заглушку, а не оригинальную функцию.
Доступ к оригинальной функции имеет только сам nop.lua, но никак не его ребенок (скрипт, который мы проксируем):
Lua:
local _error = error
error = function(message, level)
    print('call error', message, level)
end
print("nop:", error)
print("nop:", _error)

Ребенок:
Lua:
-- test.lua
print("test:", error)

Выхлоп:
1680085005904.png


ничего личного. только опыт🤝.
Мне нужны способы обхода данных заглушек, но никак не прямой вызов.
 
Последнее редактирование:

Jertshat

Участник
25
43
Возможно ты не понял, но nop.lua подгружается до загрузки скрипта, который мы собираемся проксировать.
сорри за путаницу. действительно, в случае с luajit.exe и последовательной загрузкой скриптов, мой предыдущий ответ не сработает, поскольку nop.lua уже будет подгружен и переопределит функции перед исполнением скрипта.

тогда сделаем так:
создаем изолированную среду для скрипта, используя setfenv (в Lua 5.1) или _ENVLua 5.2 и выше).
Вот пример для Lua 5.1 с использованием setfenv:
Lua:
local newEnv = setmetatable({}, {
    __index = function(_, key)
        if key == "originals" then
            return {
                error = error,
                setmetatable = setmetatable,
                getmetatable = getmetatable,
                rawset = rawset,
                rawget = rawget
            }
        end
        return _G[key]
    end
})

local fFunction, sErrorText = loadfile(arg[1])

if fFunction then
    setfenv(fFunction, newEnv)
    local errorHandler = function(err)
        print("Error:")
        print(err)
    end

    xpcall(fFunction, errorHandler)
    print("Script executed successfully")
else
    print('Error load script:')
    print(sErrorText)
end

W40Kp5s.png


теперь в скрипте сможем получить доступ к оригинальным функциям через таблицу originals:
Lua:
-- ваш скрипт
local original_error = originals.error
local original_setmetatable = originals.setmetatable
local original_getmetatable = originals.getmetatable
local original_rawset = originals.rawset
local original_rawget = originals.rawget

-- теперь вы можете использовать оригинальные функции
original_error("myerror")

не забываем, что если работаем на Lua 5.1, используем setfenv. если Lua 5.2 или выше, подход будет в виде переменной _ENV.

test.luac
1680096983743.png



test2.luac
1680097040220.png


исполняем
1680097095687.png
 
Последнее редактирование:

The Spark

Известный
Автор темы
656
690
сорри за путаницу. действительно, в случае с luajit.exe и последовательной загрузкой скриптов, мой предыдущий ответ не сработает, поскольку nop.lua уже будет подгружен и переопределит функции перед исполнением скрипта.

тогда сделаем так:
создаем изолированную среду для скрипта, используя setfenv (в Lua 5.1) или _ENVLua 5.2 и выше).
Вот пример для Lua 5.1 с использованием setfenv:
Lua:
local newEnv = setmetatable({}, {
    __index = function(_, key)
        if key == "originals" then
            return {
                error = error,
                setmetatable = setmetatable,
                getmetatable = getmetatable,
                rawset = rawset,
                rawget = rawget
            }
        end
        return _G[key]
    end
})

local fFunction, sErrorText = loadfile(arg[1])

if fFunction then
    setfenv(fFunction, newEnv)
    local errorHandler = function(err)
        print("Error:")
        print(err)
    end

    xpcall(fFunction, errorHandler)
    print("Script executed successfully")
else
    print('Error load script:')
    print(sErrorText)
end

W40Kp5s.png


теперь в скрипте сможем получить доступ к оригинальным функциям через таблицу originals:
Lua:
-- ваш скрипт
local original_error = originals.error
local original_setmetatable = originals.setmetatable
local original_getmetatable = originals.getmetatable
local original_rawset = originals.rawset
local original_rawget = originals.rawget

-- теперь вы можете использовать оригинальные функции
original_error("myerror")

не забываем, что если работаем на Lua 5.1, используем setfenv. если Lua 5.2 или выше, подход будет в виде переменной _ENV.

Это как пример реализации безопасной песочницы или пример избавления костыля require("nop")?

Если не то и не другое, то, возможно:
теперь в скрипте сможем получить доступ к оригинальным функциям через таблицу originals:
Скрипт, который пользователь кидает на батник, не должен иметь никакой возможности вызывать небезопасные функции.
Вот пример, https://www.blast.hk/threads/127048/post-1004549. Он выключает компьютер через execute
 

The Spark

Известный
Автор темы
656
690
по итогу он safe to use? или его лучше на вм юзать
По итогу пока никто не нашел дыры в нем, кроме меня (которые я исправил).
Я уверен что они есть, но я так же уверен что есть эксплоит, с помощью которого я могу залезть в твой ПК и вытащить фотки из папки Лето 2019.
Это я к тому, что все очевидные и не очевидные дыры были закрыты и использование безопасно.
Шанс того, что автор какого-то "Курд Мастера 2023" будет писать свои проверки на проксирование именно под этот хук и вызывать возможные дыры - равен нулю.
 

memir

🇷🇺
Всефорумный модератор
339
611
загрузка байткода луа/лж небезопасна по своей сути, интерпретер не чекает его валидность при исполнении
 
  • Нравится
Реакции: chromiusj