Posted
How would getscriptbytecode and decompile be made, the first one might not be to hard if you have the offsets to the bytecode of the script instance but decompile is another story. How can you go from bytecode to decompiled lua? And is there any tool that let's you do that or do you have to make it manually or maybe you need to call a function that does it for you idk, if you know how to please answer i really need it for my executor.
Cancel
Post
Replied
reverse engineer so you can find out the like format of the bytecode of scripts
then make a decompiler
Cancel
Post
Replied
To handle getscriptbytecode and decompile in a modern Luau environment, you are essentially dealing with the relationship between the Instruction Set Architecture (ISA) and the Virtual Machine (VM) state.
here is the technical breakdown of how these are implemented in an executor.
1. How getscriptbytecode is made
This function is a memory operation. Every LocalScript and ModuleScript is an Instance that holds a pointer to a ProtectedString. Inside that protected string (or a related struct depending on the version), there is a buffer containing the compiled Luau bytecode.
-
The Logic: You locate the
Scriptobject in the DM (DataModel). -
The Offset: You find the offset to the bytecode within the script class.
-
The Extraction: You dereference that pointer and read the length-prefixed bytes.
-
The Result: You return a raw string of hex/bytes.
2. How decompile is made
Decompilation is significantly harder because Luau is "lossy." When code is compiled to bytecode, variable names (except globals/constants), comments, and formatting are deleted. Reconstructing it requires a Static Analysis engine.
The Process:
-
Bytecode Parsing: Break the raw bytes into a table of instructions ($Opcodes$).
-
Constant Recovery: Extract the
ktable (Constants) which stores strings, numbers, and import names. -
Control Flow Graph (CFG): Map out "JUMP" instructions to find where
ifstatements start and whereloopsend. -
Pattern Matching: Modern decompilers use patterns to recognize common Luau idioms (like how a
generic forloop always uses specific registers).
Tools & Integration
You don't have to make this manually from scratch. Most top-tier executors use one of these three methods:
A. Ririchi's Luau-Decompiler (C++)
This is the industry standard for DLL-based executors. It is written in C++ and can be linked directly into your project.
-
Pros: Fast, native, handles most Luau optimizations.
-
Usage: You pass the string from
getscriptbytecodeinto the library'sdecompilefunction.
B. Unluau (Rust)
A very high-accuracy decompiler.
-
Pros: Extremely readable output.
-
Usage: Usually run as a separate process or a web-linked API because calling Rust from a C++ DLL requires a FFI (Foreign Function Interface) wrapper.
C. Manual "Opcode" Mapping
If you want to build a simple one yourself, you must follow the official Luau Bytecode Format.
Implementation Example (Pseudo-Logic for Executor DLL)
-- C++ Bytecode Logic
-- 1. Get the Script Instance from the Lua stack
-- 2. Traverse the Instance to the Bytecode Offset
-- 3. Return the data as a Lua string
std::string get_script_bytecode(uintptr_t script_ptr) {
uintptr_t bytecode_ptr = *(uintptr_t*)(script_ptr + 0x120); -- Example Offset
if (!bytecode_ptr) return "";
int len = *(int*)(bytecode_ptr + 0x10);
char* data = (char*)(bytecode_ptr + 0x20);
return std::string(data, len);
}
-- Decompile Wrapper
-- 1. Call get_script_bytecode
-- 2. Pass result to Ririchi/Unluau library
-- 3. Push the resulting source code string back to the user
int lua_decompile(lua_State* L) {
uintptr_t script = (uintptr_t)lua_touserdata(L, 1);
std::string bc = get_script_bytecode(script);
std::string source = ririchi::decompile(bc);
lua_pushstring(L, source.c_str());
return 1;
}
Comments
HexDX_nbVKCH 0 Reputation
Commented
Atrexus Unluau on github? Because i tried passing it a bin file of the bytecode and it said: Bytecode version mismatch, expected version 3...6, got 82.
Cancel
Post
I Help People, Ask me.
Users viewing this thread:
( Members: 0, Guests: 1, Total: 1 )
Comments
HexDX_nbVKCH 0 Reputation
Commented
Ok i get it, but localscript + bytecodeOffset isn't bytecode? Is it like encrypted if yes how do you decrypt it, and why is it that injecting your own RSB1 encoded bytecode works then if the bytecode stored in scripts is supposed to not really be bytecode why is it you can put your own and it works?
0