[] SLVM (SecureLuaVirtualMachine)
SLVM (SecureLuaVirtualMachine) is a secure Lua virtual machine based on the FiOne Project by Rerumu, to provide a controlled execution environment for Lua code, mainly for games allowing the execution of untrusted usercode, like Studio Lite
or Lua Learning
. This topic provides an overview of the functionalities, usage instructions, and features of the Secure Lua Virtual Machine.
Testing place is available @ SLVM - SecureLuaVirtualMachine - Roblox
Features
SLVM has plenty of features to help you control execution of code:
- Closure Hooking: SLVM enables the exploit-like powerful hooking system of closures within the virtual machine, allowing controlled modifications to their behavior.
-
Read and Write Hooks: You can create read and write hooks, such as preventing read methods on specific objects (e.g., the
game
object) to restrict access to certain properties using theLuaVM:CheckCString
method to compare 2 strings safely. - Env Table for Custom Variables: The Env table allows the definition of custom variables and their associated behaviors within the virtual machine.
- Restrictions: It allows the prevention of access to sensitive elements like the game object or global instances using rules.
-
Call Sandboxing: (Additional setting) Prevents
xpcall
/ any callstack-based attack that circumvents hooks or restrictions by isolating every function call, which hides the callstack. -
Loop Throttling: (Additional setting) SLVM offers an optional loop throttler to prevent common crashing methods such as
while true do end
orfor i = 1, math.huge do
…and many more!
Usage
To use SLVM in your project, follow these steps:
- Installation:
Add the SLVM Module file onto a secure location likeServerScriptService
, then in one of your scripts, require the main module:
local SLVM = require(path.to.slvm)
- Creating a Secure Lua Virtual Machine Instance
--> First argument is `ChunkName` which is a string, second argument is `Env` which provides additional globals to the Virtual Machine. Both of them are optional.
local LuaVM = SLVM.LuaVM.new("UntrustedCode@" .. Player.Name, {
CodeInvoker = Player, --> Adds new variable to environment
_VERSION = "Lua 1.2.3" --> Overwrites built-in global "_VERSION"
})
Using the Secure Lua Virtual Machine
Once you’ve created an instance of the Secure Lua Virtual Machine (SLVM.LuaVM
), you can utilize its functionalities, such as:
- Managing Sandbox Rules:
-- Define and add a new rule
local TableFindRestriction = SLVM.Rule.new(SLVM.Enum.RuleType.ClosureRestriction, table.find, "Table.Find is not allowed to be referenced / returned by functions!") --> Analyzes stack, getglobal & call opcodes for hooks and restrictions
LuaVM:AddRule(TableFindRestriction)
-- Remove the newly added rule
LuaVM:RemoveRule(TableFindRestriction)
- Run code:
-- (i) -> Run is just a shortcut to LuaVM:Compile(Code)(...)!
local Number = LuaVM:Run("print('Hello, Secure Lua Virtual Machine!'); return ...", 123) --> will return 123
- Compile code:
local CompiledFunc, FailReason = LuaVM:Compile("return function(MyNumber) return MyNumber * 10; end")
if CompiledFunc then
print("Result with calling 10: " .. CompiledFunc(10)) --> Result with calling 10: 100
else
warn("Error compiling code: " .. FailReason)
end
- Hooking Closures
-- Hook a closure (in this example, print) inside the virtual machine
local OriginalPrint; OriginalPrint = LuaVM:ReplaceClosure(print, function(...)
return OriginalPrint("Hooked via SLVM!", ...)
end)
LuaVM:Run("print(123)") --> "Hooked via SLVM! 123"
- Hooking Read & Write on objects
Only use LuaVM:CheckCString
with the first argument being a string you want to check with (for example “Parent”) and the second string being the “Index” one (or any unknown string). It is very important to not switch up the two arguments as the behavior of the function will change
-- /!\ If an instance is passed to AddXHook, it will automatically apply that to all instances.
-- The following code snippet blocks the manipulation and reading of "Parent".
LuaVM:AddReadHook(game, function(self, Index, NormalValue)
if type(Index) == "string" then
if LuaVM:CheckCString("Parent", Index) or LuaVM:CheckCString("parent", Index) then
error("Not allowed to read Parent", 2)
end
end
return NormalValue
end)
LuaVM:AddWriteHook(game, function(self, Index, NewValue)
if type(Index) == "string" then
if LuaVM:CheckCString("Parent", Index) or LuaVM:CheckCString("parent", Index) then
error("Not allowed to write Parent", 2)
end
end
return NewValue
end)
- Managing Additional Settings
-- Check if a specific additional setting is enabled
local IsSettingEnabled = LuaVM:IsAdditionalSettingEnabled(SLVM.Enum.AdditionalSettings.SandboxCalls)
-- Enable or disable additional settings
LuaVM:EnableAdditionalSetting(SLVM.Enum.AdditionalSettings.ThrottleLoopInstructions)
LuaVM:DisableAdditionalSetting(SLVM.Enum.AdditionalSettings.ThrottleLoopInstructions)
Contributing
We welcome contributions from the community! If you have suggestions, improvements, or bug fixes, feel free to reply to this topic explaining the issue, shoot me a Devforum PM, or join the ASense Community Server!
Documentation
There isn’t any documentation right now simply because I am not sure what base to use for the documentation. If you have any good tool to help me out, feel free to contact me!
License
This project is licensed under the same terms as FiOne, the GNU GPL v3 License, allowing for free and commercial usage, modification, and distribution.
Credits
SLVM is developed and maintained by the ASense Team, and made possible thanks to more specifically:
- Especially Musli / thispassed (@AverageOnionUser) & Unlimited (@Unlimited_Objects): Helping finding sandbox escaping exploits in a real-case scenario
- omwot (@elomwot): Giving server crash method regarding threads
-
Daily (@daily3014TheGod): Giving server crash method regarding
SharedTable
-
Europa (@MrJake092209): Giving server crash method regarding the
buffer
library - XNX (@XoifailTheGod): Finding bug which would make a specific perlin benchmark error
- Jeremy (@CodedJer): Testing
- EDM (@OneEDM): Testing
- Thank you for using SLVM! If you encounter any issues or need some questions answered, don’t hesitate to reach out to me. Happy coding!