RealClone

A from-scratch clone of the "Real" Roblox executor — injects into a live Roblox player (Hyperion protected) and executes Luau inside the game process.

Overall progress
78%
Injecting into a live Roblox client is done and verified. The scripts currently run in the Luau VM that is linked into the executor; the bridge into the Luau VM of the client itself is the open part.

Status

StateIN PROGRESS bridging the scripts into the Luau VM of the Roblox client
InjectionDONE verified in a live client, 19/20 and 12/12 runs
ExecutorDONE Luau VM, named pipe, script api, autoexec
Reverse engineering of RealDONE kernel level ETW trace of the original injector
Game bridgePARTIAL Luau code located, the lua_State is still missing

What is done

The four bugs that mattered

The first working version was reliable in about a third of the runs. Every defect was found by measuring, not by guessing.

1 · The import hook was installed too early. The stub that answers GetModuleHandleEx(FROM_ADDRESS) needs the resolved address of the real api to fall back to. Installed before the import table was resolved it read an empty slot and never worked — the static CRT then died inside DllMainCRTStartup. Fixing the order took the success rate from 3/8 to 8/8.
2 · Two stubs shared one address. The shellcode the hijacked thread jumps to and the GetModuleHandleEx stub were both written to base + size_of_image, so the shellcode silently overwrote the hook. The stubs now live at +0x000, +0x100 and +0x200.
3 · The jump offsets of the RtlPcToFileHeader stub were wrong. They landed inside the compare instruction of the stub and turned it into nonsense. The stub is now assembled with the jump positions recorded while it is built.
4 · The suspend count of the hijacked thread was wrong. NtAlertResumeThread already takes one suspend count down and aborts the wait of the thread; the ResumeThread that followed suspended it again, so the thread froze in the middle of the bootstrap. The symptom was an injection that worked half the time and a client that died with 0xC0000005.

How the injection works

  1. Manual map. The image is copied section by section into a private allocation, DIR64 relocations are applied, the import table is resolved against the target's module bases and the section protections are restored. NtCreateSection(SEC_IMAGE) is blocked on this machine (the kernel answers 0xC00000F4 for every variant, even for signed system dlls).
  2. Thread hijack. A thread is suspended, its context is rewritten and it is resumed so that it jumps into a stub inside the mapped image. The stub aligns the stack pointer, the kernel rejects a misaligned stack pointer when a hijacked thread returns from a system call.
  3. C runtime. The module uses the static CRT (/MT). The CRT cannot find its own module with GetModuleHandleEx(FROM_ADDRESS) because a manually mapped image is not in the loader lists, so that import slot is redirected to a stub that answers with the mapped base. The CRT keeps per module state below base + 0x4000, so the first pages stay writable.
  4. Executor. The module entry runs, the CRT is initialised and the worker serves the named pipe. The injector sends EXEC <source> and gets the output of the script back.

Currently being handled

WORKING ON the bridge into the Luau VM of the client, so that the scripts see game, workspace and the rest of the game, like the original product.

What is known:

Still open: the lua_State. The states live on the heap of the client and their layout is version specific, so they have to be found at runtime and validated against the api.

Remaining

Find the lua_StateOPEN locate the states on the heap of the client and validate them against the api
Call the apiOPEN push a chunk, call it, read the result back
Match the bytecode versionOPEN the version range of the client has to be found, the vendored Luau adjusted
Keep it undetectedOPEN every call into the client has to survive the anti cheat

How to reproduce

cd realclone
cmake -S . -B build/project -DCMAKE_BUILD_TYPE=Release
cmake --build build/project --config Release --target RealClone
cd injector && cargo build --release

# inject into a running client and run the smoke test
.\injector\target\release\realclone.exe run --pid <roblox pid> \
    --dll build\project\Release\RealClone.dll --script tests\smoke.lua

# reliability harness
powershell -File tools\reliability-test.ps1 -Runs 12 -Retries 1 -Wait 25

Verified numbers

Injection into a live client19 / 20 and 12 / 12 in two independent batches
Client after the injectionalive and responsive 70 threads, working set stable over 90 s
Script executionworks hello from mapped luau, 3, RealClone/0.1, done
Benign host (control)works same code path, no anti cheat