Download “Evenicle” Installer (Supports Resumable Downloads). Open the Installer, Click Next and choose the directory where to Install. Let it Download Full Version game in your specified directory. Open the Game and Enjoy Playing. In this case, whenever a player clicks on the NPC, a variable named dialogueIndex, will increment by 1 to display the next line of dialogue. To keep track of the current index, add a new variable named dialogueIndex. Set the variable to 1 to start at the beginning of the array.
Apr 17th, 2017
Never
Not a member of Pastebin yet?Sign Up, it unlocks many cool features!
- The idea behind RC7 and other, unheard (private) exploits
- PRESENTED BY
- Scripting and reversing group.
- ❏ Brandon/Chirality: For inventing the first modern script execution exploit that
- preceded the most recent exploits, such as Intriga and Elysian. He’s also the
- ❏ Jordan/KingJordan: For inventing the concept of bytecode conversion and using it
- to create the exploit known as RC7, which is one of the most popular exploits.
- ❏ Rain: Rain is the spiritual successor to FaZe, and (personally speaking) one of
- the best reversing groups out here. Previous FaZe members still interested in
- Roblox exploiting found themselves in Rain shortly after its introduction to the
- Roblox exploit scene. I need to credit Rain for trying (and succeeding at that!)
- to improve the exploit section. They’re doing a good job.
- ❏ Louka: For creating and designing this document. That’s me! :P
- ❏ ConvexHero: For not doing anything. Well, he did implement callcheck, but that’s
- it. He’s doing relatively nothing that prevents exploits from happening.
- Bytecode is basically the compiled form of source code. When you create a C++
- application in Visual Studio and build it, the compiler (MSVC) simply takes your source
- code then translates it into a set of simple instructions called assembly, which is
- then optimized (for speed and/or size) and put into an executable file. The executable
- code contains bytecode (along with resources, constant data and etc.)
- This does not only apply to C++ applications. In fact, almost every language in the
- world is compiled to another language easier to understand by your computer. Languages
- that are considered “interpreted” are usually compiled to a form of bytecode, which is
- then read by the interpreter to execute what the code does.
- Bytecode, unlike executable binaries, are very portable. Yeah, executable binaries ARE
- portable (it’s in their name: PE, portable executable), but bytecode is usually smaller
- Today, we’re going to talk about Lua bytecode.
- So, we know that bytecode is mainly constituted of instructions. Let’s take a look at
- ❖ Each instruction has four parameters: the opcode, the A register, the B register
- and the C register. Each are one byte long, which forms a single signed integer.
- An instruction that uses all three registers is of type iABC.
- ❖ Certain instructions merges the B register with the C register to form a short (an
- integer with two bytes), which can store bigger values. This creates the Bx (B
- extended) register. An instruction that uses the A and Bx registers is of type
- ❖ Certain instructions have a signed Bx register (it can contain negative values).
- They are of the iAsBx type. (instruction, A, signed Bx)
- ❖ And there are instructions that simply uses the A register. They are of the iA
- A short overview on Lua bytecode (pt. 2)
- In the previous slide, I’ve mentioned opcodes. Opcodes is what tells the interpreter
- what the instruction does. If the instruction’s opcode is OP_ADD (iABC), then it tells
- the interpreter to put in the A register the sum of the values located at B and C.
- Lua has exactly 37 instructions, which is small if you compare Lua’s instruction set
- to, for example, x86’s instruction set (hint: on average, ~2000 instructions. CPUs are
- different so they all have different instruction sets, so the number of instructions is
- different depending on the CPU brand and the architecture.)
- Due to the opcode being stored as a single byte, there could be a maximum of 255
- instructions if Lua’s development team wanted to add more instructions. If they reach
- that number, then they would need to switch to 64bit integers (8 bytes). This also
- means they would be able to add in more registers, which could mean a more performant
- VM, but this is just a dream that’ll never happen.
- First, let’s consider those facts:
- ❖ When you run a Lua script, Lua automatically compiles it to an intermediary format
- resembling bytecode before feeding it to the virtual machine.
- ❖ This “intermediary format” (which is a mere Proto struct) can be serialized then
- dumped as bytecode, which can be saved as a file.
- ❖ Then, if you wanted to run the bytecode, you just have to feed it to luaU_undump,
- which will convert the bytecode into Lua’s intermediary format (a Proto).
- ❖ Once you obtained the Proto, you can insert it into a Lua function (LClosure) then
- ❖ If a developer removes Lua’s compiler, then Lua could only run bytecode.
- Therefore, in theory, we could simply dump bytecode from an external Lua instance then
- feed it to another Lua instance so that other Lua instance can run a script for us
- without having to go through the compiler. This is in fact pretty useful, as Roblox
- removed the compiler, preventing us from compiling scripts on the client.
- So, how could we use it for Roblox script execution?
- 1) Compile a Lua function on your own Lua environment.
- 2) Dump it into bytecode via either lua_dump or string.dump.
- 3) Save that bytecode somewhere, preferably in memory.
- 4) Call Roblox’s lua_loadbuffer to load in the bytecode, which will eventually invoke
- 5) You insert the obtained Proto into a Lua function (LClosure)
- 6) You call the resulting function, effectively running your script.
- While the above would work in any other standard Lua environment, sadly, it doesn’t
- work in Roblox for a multitude of reasons, but the most important being the fact that
- Roblox has heavily modified their instruction set and added some obfuscation to it.
- This was done in order to prevent exploiters from simply copy and pasting Lua bytecode
- over to the client and expecting it to run. However, just like every security measure
- in the world, this does not prevent anybody from running bytecode, it just makes their
- task harder as they have to convert their bytecode, hence the name of the procedure:
- BYTECODE CONVERSION. You convert bytecode into Roblox’s format.
- Differences between Lua and Roblox Lua bytecode (pt. 1)
- ❖ Roblox Lua bytecode instructions are changed. That is, OP_MOVE in a normal Lua
- environment is 0, but in Roblox’s Lua environment, it’s 6. This is very easy to
- ❖ Certain Roblox Lua instructions are obfuscated using a mixture of modular
- multiplicative inverses and a lot of bit math. To be honest, it’s a lot of boring
- stuff and it almost requires someone to possess a computer science degree to
- understand what Roblox is doing. Fortunately, we have smart people out here (cough
- Chirality, Alureon, Austin <3) who figured most of it out and were able to reverse
- Roblox’s obfuscation process. This obfuscation is only applied to OP_CALL,
- OP_TAILCALL, OP_RETURN and OP_CLOSURE. Every other encryption is not affected.
- ❖ Every instruction is obfuscated, albeit this form of obfuscation is easier to
- reverse than CALL/TAILCALL/RETURN/CLOSURE’s special encryption, as it’s virtually
- only multiplication. (deobfuscated opcode = obfusop * key). Of course, OBFUSCATING
- ❖ OP_MOVE now uses the C register (normal Lua only used the A and B registers),
- turning it into an iABC instruction. The difference is only artificial and doesn’t
- Differences between Lua and Roblox Lua bytecode (pt. 2)
- ❖ The bytecode magic header (what is used by the undumper to verify if what you gave
- it is actually bytecode) has a different value. Of course, if you find this hard
- to reverse, you probably have to study reverse engineering a lil’ bit more :u
- ❖ The bytecode is compressed using LZ4, which is an extremely fast compression
- algorithm. This, again, isn’t difficult to reverse either, considering LZ4’s
- ❖ The registers are reversed. That is, in normal Lua, the registers are ordered like
- this in the integer: A, B and C. In Roblox Lua, it’s C, B and A.
- This is all the differences we currently know of. There are some additional obfuscation
- and protection steps Roblox took but they’re only superficial and obvious so it’s not
- worth mentioning here. They would only take tens of minutes to reverse.
- I mean, that’s how much they took for me. Maybe some people will reverse it slower than
- How would someone convert Lua BC to Roblox BC?
- 1. The most important thing is converting instructions. You do it like this for every
- a. You take the opcode and find the corresponding Roblox opcode as they’ve
- changed. Then, you set the opcode in your instruction to that one.
- b. You set the C, B and A registers. Don’t forget that they’re reversed!
- c. If it’s OP_MOVE, then don’t forget to set the C register. They use it now as
- d. If it’s an instruction with special encryption (OP_CALL, OP_TAILCALL,
- OP_RETURN and OP_CLOSURE), you apply the special encryption to the
- e. Finally, you apply general encryption to the instruction then put it into your
- 2. The second most important thing is moving stuff around. Of course, the bytecode
- dump’s structure must be changed in order for Roblox to accept it. In fact, Roblox
- has completely remade Lua’s bytecode format. They didn’t just modify it.
- 3. You also have to fix line number as well. Roblox now encrypts line numbers based
- Decompilation and such things
- Decompilers in modern exploits (Seven, Elysian, Intriga (if it has one) and etc) works
- by simply doing the reverse of bytecode conversion: converting Roblox bytecode into Lua
- bytecode. Then, the Lua bytecode is fed to a program (usually luadec) which creates
- pseudocode from the bytecode dump you obtained from your conversion.
- This process, however, is not without issues: my previous attempts at doing the reverse
- of bytecode conversion had a lot of issues (usually things with decryption and etc)
- which generated artifacts during the decompilation process. Relatively simple scripts,
- however, decompiled with a moderate amount of success.
- You could theoretically use proto conversion to achieve decompilation too: you convert
- a Roblox proto into a normal Lua proto, push it to a normal Lua state then call
- lua_dump or string.dump on it, which will return a valid bytecode dump you can feed to
- If you wondered how script decompilation worked, now you know.
- Lua VM
- Client
- Lua Function
- (OP_CALL)
- Exploit
- Server
- Standard Lua Bytecode
- ● Proto Conversion: Proto conversion is obtaining the intermediary format used by
- Lua obtained after compilation then converting it into Roblox’s intermediary
- format. This is very fast and is used by most script execution exploits out here,
- albeit it’s very insecure and can be easily patched. Just like bytecode conversion
- ● CLVM (Custom Lua Virtual Machine): Considered the fastest and most secure yet
- unstable script execution method there is. Relatively new too, but sadly hard to
- develop and requires a lot of manhours to get working. This method is simply
- making a custom Lua virtual machine that uses Roblox’s own lua state rather than
- yours. It works, it’s been proven to work with a certain degree of success, but
- maintaining the VM is quite hard and a lot of errors could occur if you don’t know
- what you’re doing. Despite those cons, it’s very secure and considered unpatchable
- The End
- - Louka
10 min
Tables are a way to group multiple values together. Unlike variables that store just a single value, tables don’t have a fixed size and can hold a mix of different value types. With tables, you can group together stats for an in-game item, or create a list of thousands of player names.
There are different types of tables. One type is an array, which store lists of values in a specific order.
Example Array
To create an array, name the array and use curly brackets
{ }
. Separate values inside the brackets with commas like below:local myArray = {“item1”, “item2”, 10, Workplace.Part, myVariable}
To explore arrays, you’ll work with a non-playable character (NPC), that when clicked, will show a different line of dialogue stored in an array.
Set Up the Project
This project will use a premade NPC model which includes a script and Click Detector, but lacks dialogue.
- Download the premade NPC.
- In the Explorer, import the NPC by right-clicking on Workspace > Insert From File > select
Starter_NPC.rbxm
. Or, drag the file into Studio.
Creating an Array for Dialogue
Create dialogue for the NPC to use by storing individual strings in an array. Each line will appear as a chat bubble when the NPC is clicked.
- In the Explorer, expand NPC and open DialogueScript.
- Between the variables and
speak()
, create an empty array to store dialogue by typinglocal dialogueArray = {}
.
- Between the brackets
{}
, type at least three strings of dialogue, separated by commas.
Now that an array is created, you’ll need a way to display the values in it.
Typing
print(dialogueArray)
won’t print the array. It’ll just output the a series of numbers. Not very useful.To get anything from an array, the script needs to know the location of that value in the array. Whenever a value is added to an array, it’s assigned a number called an index. In Lua, Indexes start at one, and go up by one for every value added.
In this example,
'Hi'
is at index 1 and 'Good bye!'
is at index 3.Value | 'Hi!' | 'Today's a great day!' | 'Good bye!' |
---|---|---|---|
Index | 1 | 2 | 3 |
Keep in mind, not every coding language starts indexes at 1. Others, like Java for example, start at 0.
Getting Single Array Values
To use a value at a specific index, add the index after the array’s name without any spaces, like
dialogueArray[1]
.- To test out the array, replace the current value of the variable
dialogue
with the second index by typing= dialogueArray[2]
.
Avoiding Index Errors
If the index doesn’t exist, you’ll receive a
nil
error.For example, the above array only has 3 values, so trying to get
dialogueArray[4]
will result in an error.- Play the project and click the NPC to see the second array value appear in the chat bubble. Try changing the code to test out each value in the table.
Variables can be used in place of the index number to make code more flexible. For instance, a variable can be used to get a random index number or be increased each time a function is called to get to the next value in the array.
Change Dialogue Lines
In this case, whenever a player clicks on the NPC, a variable named
dialogueIndex
, will increment by 1 to display the next line of dialogue.- To keep track of the current index, add a new variable named
dialogueIndex
. Set the variable to1
to start at the beginning of the array.
How To Download Increments For Roblox
- In
speak()
, replace the index number indialogueArray[2]
with the variable you just created.
- At the bottom of the function, add
1
todialogueIndex
. That way, the next timespeak()
is called, the next string in the array will be displayed.
- Playtest amd click the NPC to see each dialogue string from the array.
Existing Error in the Script
Notice there’s an error in the Output Window once the script reaches the end of the array. You’ll fix this in the next section so the dialogue restarts from the beginning after it shows the last string.
One benefit of using variables in place of index numbers is that they can be compared to the size of the array to know when the end has been reached. The size of an array can be found by typing
#
, without spaces, before an array’s name.Players age 12 and younger have their posts and chats filtered both for inappropriate content and to prevent personal information from being posted. Players age 13 and older have the ability to say more words and phrases than younger players. This filtering system covers all areas of communication on Roblox, public and private. Can I Get Banned For Using A Roblox Hack/Exploit? If you decide to abuse these hacks and make it very obvious that you are hacking people can report you and after around a 1-2 weeks your account will be flagged as a cheater and you may be banned for around 1 – 7 days after that you will be on a list of cheaters that if you continue to be reported for hacking you will be permanently. Roblox hacks read peoples private chats.
For example:
#dialogueArray
Once you have how many elements are in the array, you can check it against the current value of the variable to know when it’s time to start back at the beginning.
Restart the Dialogue
- Code a new if statement that checks if
dialogueIndex
is equal to#dialogueArray
. In the statement, restartdialogueIndex
by setting it back to 1.
- If
dialogueIndex
isn’t at the end, it should still add 1 todialogueIndex
. To do this, move this line under anelse
statement.
- Play the project. Check that you can cycle through the array without errors.
Troubleshooting Tips »
Issue: Dialogue doesn’t restart after reaching the end.
- Check in the if statement that
dialogueIndex
is set back to 1. In the else statement, check thatdialogueIndex
has 1 added to itself. - When getting the size of the array, make sure there is no space after the # in #dialogueArray.
Optional Challenges »
Challenge: Code the script so that the NPC’s dialogue goes backwards through the array. The
dialogueIndex
should start at the array and subtract each time instead of adding.Challenge: Instead of showing dialogue in order, have the NPC show a random line of dialogue each time using Random.new.
Show/Hide
Project File
Download the finished project here.
Finished Script
DialogueScript »
These documents are licensed by Roblox Corporation under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License. Roblox, Powering Imagination, and Robux are trademarks of Roblox Corporation, registered in the United States and other countries.