How does the :s command in Adonis work?

Hello!

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.

Example: :s workspace.RoyallyFlushed:BreakJoints()

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!

-RoyallyFlushed

6 Likes

As far as I know it uses a version of the LuLu Lua VM (an implementation of the LuaVM that is written in Lua) which was modified to work on Roblox.

The most taken Lua in Lua implementation I found in the catalog was the following but it might be a different one that is used in this Admin script.

4 Likes

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.

2 Likes

Uses @Rerumu’s Rerubi

7 Likes

I can’t remember where exactly the code was because the command module is very long, however

Source code: Adonis MainModule - Roblox

Use the find command to search for ‘script’ in the command module and it will take you to the script called ‘Script Base’

Image

image

1 Like

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?

1 Like

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.

10 Likes

Ah I see. Still seems complicated but I guess that is to be expected. I appreciate the help & solution though.

:slight_smile:

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.

5 Likes

Ah I see that! I’ve actually seen these names before, I don’t know where though. Probably from @einsteinK

Img

image

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.

1 Like

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.

4 Likes

Oh that’s awesome! I just sliced the loadstring module and stuck a script to its calling environment to test it. It worked.

Now I’m going to spend the next 6 years trying to understand it all.

Not for long probably – I’ve been working on and off on a more compact compiler out of boredom. :wink:

2 Likes

Yeah, really impressive work. I believe @stravant was the one who made LBI aswell.

2 Likes

@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 my primary contribution in that area was probably this, the LASM tools ca. 2010, which can easily act as an intermediary layer for someone trying to experiment with / write that sort of stuff. As a baseline they provide a working reference implementation of decoding binary Lua chunks using only vanilla Lua.

2 Likes

I’d appreciate it if you could clarify as to who to properly credit in the original writing of the LBI, which was the base concept for Rerubi.

I was sorta out in the blue about it so…

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.

1 Like

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

fun times

1 Like