I’ve been wondering about this for quite a while now and I’ve decided to try and find out exactly how this works. For those who are familiar with the Adonis Admin System by @Sceleratis and his team, they have a specific command known as :s which allows the following example to run.
Now, I know this is super easy to do with loadstring enabled however places that run this admin do not have this enabled and yet the ‘script’ works. Adventuring into their source code module (which is publicly open), I found the command in question and found that they seemed to manage it by using what looked to be bytecode and then setting it inside a function to the script’s environment.
I’ve tried to have a go at making it here but to no success, as expected.
My attempt:
game.Players.PlayerAdded:connect(function(player)
player.Chatted:connect(function(msg)
local prefix = ':s '
if msg:sub(1, prefix:len()) == prefix then
local command = msg:sub(prefix:len())
getfenv()['ExecuteCode'] = command
ExecuteCode()
end
end)
end)
Any and all ideas and solutions are appreciated, I’d love to know how to do this!
Mind dumping the bit of code that performs that operation? I’m really stumped about that as well though… It would be interesting to be able to implement something like this on the client however. Clientside intentional script execution could be an interesting game mechanic.
So I presume that you added this bytecode interpreter into a module and then turned the string command from :s workspace.RoyallyFlushed:BreakJoints() into bytecode and then dumped it into a function and stored it in a script’s function environment using getfenv?
It converts the provided string into bytecode using modules provided by @einsteinK and then interprets it using @Rerumu’s Rerubi module. This is basically all it does, and you can read through Rerubi to learn more about how it goes about actually running things. Adonis does a few different, extra, things that make the whole process seem more complicated but are more related to how the script is handling stuff and isn’t required for execution to work.
A wild reru is lurking nearby, maybe it will grace us with its magical wisdom.
If you want to take a look at the modules that handle it all, I believe I have them all in the (server) dependencies folder under a module named “Loadstring”
Rerubi is a remake of the Lua VM interpreter; not sure who the original was made by, but Rerubi is an aim to fix all bugs and implement a faster form of execution with minimal readability concerns.
It executes standard Lua 5.1 bytecode, much like the original, but has full opcode support, recursion, proper multithreading, and some other minor changes.
The actual compiler is the LuLu compiler I believe.
Yeah. I believe he just ported them into roblox and made a module to handle the process. Their authors should still have all of their credits and comments in each module. Originally it was using LuLu to interpret, then was switched to LBI, and now it’s using Rerubi.
The original code for bytecode compilation comes from a project called Yueliang which can be found here.
I believe @einsteinK, @stravant and @cntkillme were the original people that got this working on Roblox initially, it’s pretty interesting to see how much work has been done on this since then. I remember looking at how hard it would be to get LuLu working on Roblox many years ago and it seemed really inaccessible to me but they made it happen.
@TheGamer101@Sceleratis I don’t believe I ever published a full bytecode interpreter (Though I’ve published so many Lua related tools I wouldn’t be surprised if I actually had. Though I didn’t write them, LBI and some of the other tools definitely have some chunks of code that smell strongly of being copied out of something I did write style-wise).
I think stravant (and some other people?) is the best you can do. Like I said, I’m pretty sure that at least some of the parts of the code are copied out of something I did write, but also pretty sure I didn’t write the main piece of code.
8 years and hundreds of programming projects later I can’t really remember what all I did on that topic. I know I wrote LASM and a couple of other tools, but I can’t find the other ones.
I’ve started several small projects to parse and/or execute a language. The LBI port @Sceleratis mentioned was just something I ported early on and adapted a bit to work with roblox instances and such.
Right now, I have a module (that I use in script builders now and then) that uses @stravant’s Lua-to-AST module (which I got from his Minify/Beautify plugin) that converts the Lua to kind of a table format. My “VM” just “executes” the table. Not the most efficient way, but it was fun to create and relatively easy to study/modify/… I think I added some very small modifications to stravant’s module to fix a bug with locals, but it’s been a while, so can’t remember
Originally, EISS/Adonis still used the Lua VM that I ported, which was LuLu I think. @Rerumu just made a better VM, so @Sceleratis replaced the VM part with reru’s thing. I remember looking for a weird bug in the VM for an hour, finally fixing it, wanting to make a pull request for it on the github, finding out there was already an issue (with fix) logged… oh well