SecureLuaVirtualMachine - Controlled Execution Environment

[:lock:] SLVM (SecureLuaVirtualMachine)

SLVM (SecureLuaVirtualMachine) is a secure Lua virtual machine based on the FiOne Project by Rerumu, and designed by the ASense Team 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

:sparkles: Features

SLVM has plenty of features to help you control execution of code:

  • :hook: Closure Hooking: SLVM enables the exploit-like powerful hooking system of closures within the virtual machine, allowing controlled modifications to their behavior.
  • :open_book: 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 the LuaVM:CheckCString method to compare 2 strings safely.
  • :brain: Env Table for Custom Variables: The Env table allows the definition of custom variables and their associated behaviors within the virtual machine.
  • :no_entry_sign: Restrictions: It allows the prevention of access to sensitive elements like the game object or global instances using rules.
  • :parasol_on_ground: Call Sandboxing: (Additional setting) Prevents xpcall / any callstack-based attack that circumvents hooks or restrictions by isolating every function call, which hides the callstack.
  • :repeat: Loop Throttling: (Additional setting) SLVM offers an optional loop throttler to prevent common crashing methods such as while true do end or for i = 1, math.huge do

…and many more!

:hammer_and_wrench: Usage

To use SLVM in your project, follow these steps:

  1. Installation:
    Add the SLVM Module file onto a secure location like ServerScriptService, then in one of your scripts, require the main module:
local SLVM = require(path.to.slvm)
  1. 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"
})

:rocket: 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

:warning: 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)

:handshake: 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!

:scroll: 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!

:memo: 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.

:medal_military: Credits

SLVM is developed and maintained by the ASense Team, and made possible thanks to more specifically:

:question: - 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!

109 Likes

This is probably one of the most useful community resources in my opinion.

14 Likes

Useful post, will try this out later :sweat_smile: make some more stuff like this! :pray:

8 Likes

Hey guys, have you heard of this silly thing called the buffer library

Nevermind

7 Likes

What do you mean by that @MrJake092209 ?

7 Likes

Absolutely nothing important :alien:

6 Likes

If you are talking about the crash method concerning buffer.fill, me and @AverageOnionUser are trying to mitigate this ASAP. Will push the update once buffer is no longer a studio beta.

7 Likes

this is great, however would be better if it had Luau support.
luau projects: Fiu and LuauInLuau

7 Likes

LuauInLuau is NOT made to be used in production
Maybe, just maybe ill take Fiu into consideration

Luau support would be considerably harder, which is why it is not on my list of priorities. Thank you for your suggestion though!

(I’m getting lazy, it’s like the 75th time I’ve switched VMs for performance purposes lol)

7 Likes

idk what u mean by that but would be really helpful if you added Fiu support, I’m currently remaking roblox studio inside roblox and it would make things much better! keep up the good work

8 Likes

When taking a quick look at this gist, you can see that the file size is GINORMOUS Luau translated to Luau, as a Studio compatible script · GitHub

This is because it is WebAssembly translated back to Lua using Wasynth
Fiu on the other hand is just the Luau bytecode interpreter and is way easier to modify

image

7 Likes

oh alr, thanks for the explanation!

8 Likes

also, I tried the testing place and scripts seems to take a bit to actually run, is there any way of speeding it up?

8 Likes

I genuinely don’t know why that happens
It happened when I was testing with friends

I’m actually trying to fix that; Im gonna continue after resting
image

7 Likes


This appeared to be the issue. Commenting it out fixed the problem.
The root cause of the issue was the RunService event I was using (PreRender) when it should have been Heartbeat.


image

I am publishing the changes on the Model Page and in-game.

3 Likes

SLVM Update

  • Fixed slow execution caused by the SandboxCalls additional setting.
  • Fixed a possible sandbox-escape vulnerability in the isolate_call_synchronous function

NOTE: It is VERY RECOMMENDED that you enable the SandboxCalls additional setting by adding the following:

LuaVM:EnableAdditionalSetting(SLVM.Enum.AdditionalSettings.SandboxCalls)

Update now: https://create.roblox.com/marketplace/asset/15839058628/Secure-Lua-Virtual-Machine

6 Likes

We really needed a new lua compiler! Thanks for working really hard to make this.

8 Likes

doesn’t work on my machine, please fix

1 Like

what do you mean???ㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤㅤ

3 Likes

Looks good. Now make SLVM so advanced that even my computer’s feelings are protected. I don’t want my pc catching emotions from malicious code. :cry:

2 Likes