ROBLOX 沙盒

ROBLOX sandboxing

我是 Lua 中沙盒的新手,想学习如何过滤 :GetChildren() 或 :Kick() 之类的内容。

这是我目前拥有的:

function safeGetChildren(obj)
    local objs = {}
    for _,v in pairs(obj) do
        if not v.Name:match("^^") then
            table.insert(objs, v.Name)
        end
    end

    return objs
end

function safeClearAllChildren(obj)
    if obj:IsA("Player") or obj:IsA("Players") or obj:IsA("Workspace") or obj:IsA("ServerScriptService") or obj:IsA("Lighting") or obj:IsA("ReplicatedStorage") or obj:IsA("StarterGui") then
        return error("Cannot clear this object!");
    else
        obj:ClearAllChildren();
    end
end

function safeRemoveObject(obj)
    local name = obj.Name:lower();

    if obj:IsA("Player") or  name == "remoteevents" or obj.Parent == "RemoteEvents" or obj.Parent == "ReplicatedStorage" or obj.Parent == "StarterGui" or obj.Parent == "ServerScriptService" or obj.Parent == "TinySB" then
        return error("Cannot destroy this object!");
    else
        obj:Destroy();
    end
end

local Globals = {
    -- Globals
    workspace = workspace,
    print = print,
    error = error,
    table = table,
    pairs = pairs,
    game = game,
    string = string,
    _G = _G,
    getfenv = getfenv,
    loadstring = loadstring,
    ipairs = ipairs,
    next = next,
    os = os,
    pcall = pcall,
    rawequal = rawequal,
    rawget = rawget,
    rawset = rawset,
    select = select,
    setfenv = setfenv,
    setmetatable = setmetatable,
    tonumber = tonumber,
    tostring = tostring,
    type = type,
    unpack = unpack,
    _VERSION = _VERSION,
    xpcall = xpcall,
    collectgarbage = collectgarbage,
    assert = assert,
    gcinfo = gcinfo,
    coroutine = coroutine,
    string = string,
    table = table,
    math = math,
    delay = delay,
    LoadLibrary = LoadLibrary,
    printidentity = printidentity,
    spawn = spawn,
    tick = tick,
    time = time,
    UserSettings = UserSettings,
    Version = Version,
    wait = wait,
    warn = warn,
    ypcall = ypcall,
    PluginManager = PluginManager,
    LoadRobloxLibrary = LoadRobloxLibrary,
    settings = settings,
    stats = stats,

    -- Functions
    ["require"] = function(...)
        return error("Cannot require object (API disabled)");
    end,
    ["getchildren"] = function(...)
        return safeGetChildren(...);
    end,
    ['children'] = function(...)
        return safeGetChildren(...);
    end,
    ['clearallchildren'] = function(...)
        return safeClearAllChildren(...);
    end,
    ['destroy'] = function(...)
        return safeRemoveObject(...);
    end,
    ['remove'] = function(...)
        return safeRemoveObject(...);
    end,
    ['kick'] = function(...)
        return safeRemoveObject(...);
    end,
    ['saveplace'] = function(...)
        return error("Cannot save place (API Disabled)");
    end
}
setfenv(1, Globals)
table.foreach(workspace:GetChildren(), print)

我在几个小时内完成了这个,但是像 :GetChildren() 这样的东西在这个环境中没有被过滤。如果有人可以帮助我解释所需代码的每个部分的作用,那将真正有帮助。

您正在新环境中使用名称 'getchildren' 设置安全包装器。但是稍后,在测试时,您调用 'GetChildren',取自 'workspace' table,而不是新环境中的全局变量。
替换全局环境中的函数并不意味着替换所有 tables/objects 中同名的函数。为此,对象必须从当前全局环境调用函数,而不是从内部 tables 或词法闭包调用函数。