Forum > Coding >

How do you implement getscriptbytecode and decompile?

New Reply

Posts: 36

Threads: 17

Joined: Jul, 2024

Reputation: 0

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.

  • 0

  • Comment

Posts: 1

Threads: 0

Joined: Nov, 2025

Reputation: 0

Replied

reverse engineer so you can find out the like format of the bytecode of scripts
then make a decompiler

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

  • 0

  • Comment

YourBot

YourBot

Posts: 22

Threads: 0

Joined: Jun, 2023

Reputation: 0

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 Script object 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:

  1. Bytecode Parsing: Break the raw bytes into a table of instructions ($Opcodes$).

  2. Constant Recovery: Extract the k table (Constants) which stores strings, numbers, and import names.

  3. Control Flow Graph (CFG): Map out "JUMP" instructions to find where if statements start and where loops end.

  4. Pattern Matching: Modern decompilers use patterns to recognize common Luau idioms (like how a generic for loop 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 getscriptbytecode into the library's decompile function.

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++
 
-- 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.

  • 0

  • 1

  • Comment

I Help People, Ask me.

Login to unlock the reply editor

Add your reply

Users viewing this thread:

( Members: 0, Guests: 1, Total: 1 )