Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Windows.h>
- #include <string>
- #include <thread>
- #include <vector>
- #include <iostream>
- // --- Shuffles and Encs Provided by User ---
- // These preprocessor macros are essential for correctly defining the memory layout
- // of Roblox's obfuscated internal data structures.
- #define LUAU_SHUFFLE3(s, a1, a2, a3) a1 s a3 s a2
- #define LUAU_SHUFFLE4(s, a1, a2, a3, a4) a3 s a1 s a2 s a4
- #define LUAU_SHUFFLE5(s, a1, a2, a3, a4, a5) a5 s a4 s a1 s a3 s a2
- #define LUAU_SHUFFLE6(s, a1, a2, a3, a4, a5, a6) a2 s a4 s a3 s a1 s a5 s a6
- #define LUAU_SHUFFLE7(s, a1, a2, a3, a4, a5, a6, a7) a4 s a5 s a1 s a7 s a2 s a3 s a6
- #define LUAU_SHUFFLE8(s, a1, a2, a3, a4, a5, a6, a7, a8) a6 s a4 s a1 s a2 s a8 s a5 s a7 s a3
- #define LUAU_SHUFFLE9(s, a1, a2, a3, a4, a5, a6, a7, a8, a9) a1 s a8 s a5 s a3 s a4 s a6 s a7 s a9 s a2
- // Structure Member Encryption/Renaming
- #define LSTATE_STACKSIZE_ENC VMValue2
- #define LSTATE_GLOBAL_ENC VMValue0
- #define CLOSURE_FUNC_ENC VMValue0
- #define TSTRING_LEN_ENC VMValue0
- // --- Roblox Offsets Provided by User ---
- namespace Offsets {
- const DWORD TaskSchedulerPointer = 0x6884DC8;
- const DWORD VisualEnginePointer = 0x6606128;
- const DWORD ScriptContext = 0x3B0;
- const DWORD VisualEngineToDataModel1 = 0x720;
- const DWORD VisualEngineToDataModel2 = 0x1B8;
- const DWORD GetGlobalState = 0x140; // This might be an offset to a function or a direct pointer.
- const DWORD Job_Name = 0x18;
- const DWORD Name = 0x78; // Offset for an instance's name
- }
- // --- Roblox Function Typedefs & Structure Recreation ---
- // We must recreate the structures using the provided macros to match their in-memory layout.
- // NOTE: Base types like GCObject, TValue, etc., are simplified for clarity.
- // The primary goal is to demonstrate the use of the shuffle/enc macros.
- struct GCObject {
- void* next; // Simplified GCObject
- byte tt;
- byte marked;
- };
- struct TString {
- GCObject GCO; // Common header for garbage collected objects
- // Using the ENC macro to define the length member
- size_t TSTRING_LEN_ENC;
- // Other members would follow, defined by their ENC macros
- };
- struct lua_State {
- // This demonstrates the reordering of members. The preprocessor will expand this
- // into the shuffled order defined by LUAU_SHUFFLE*.
- LUAU_SHUFFLE9(;,
- GCObject* LSTATE_GLOBAL_ENC, // VMValue0
- void* next,
- int LSTATE_STACKSIZE_ENC, // VMValue2
- void* top,
- void* base,
- void* ci,
- void* savedpc,
- byte status,
- byte tt
- );
- };
- struct ScriptContext {
- // We assume a simple layout here. The key is accessing it via the offset.
- char padding[Offsets::GetGlobalState];
- lua_State* main_L; // The member at offset GetGlobalState
- };
- struct Job {
- char padding[Offsets::Job_Name];
- TString* job_name;
- };
- struct TaskScheduler {
- char padding[0x1D0]; // JobStart offset from your list
- void* jobs_start;
- void* jobs_end;
- Job* GetJobByName(const std::string& name) {
- // Iterate through the scheduler's jobs to find the correct one
- for (Job** job_ptr = (Job**)jobs_start; job_ptr < jobs_end; ++job_ptr) {
- Job* job = *job_ptr;
- if (job && job->job_name) {
- // Check if the job name matches "WaitingHybridScriptsJob"
- const char* jobNameStr = (const char*)(job->job_name + 1); // TString data is after the header
- if (name == jobNameStr) {
- return job;
- }
- }
- }
- return nullptr;
- }
- };
- // --- Function Pointers to Roblox's Internal Functions ---
- // These addresses must be found via reverse engineering (e.g., signature scanning).
- // They are ESSENTIAL for execution. The offsets you provided get us the objects,
- // but we need the functions to interact with them.
- DWORD roblox_base = (DWORD)GetModuleHandleA("RobloxPlayerBeta.exe");
- // PLACEHOLDER ADDRESSES - THESE MUST BE FOUND AND UPDATED
- typedef lua_State* (*rbx_lua_newthread_t)(lua_State* L);
- rbx_lua_newthread_t rbx_lua_newthread = (rbx_lua_newthread_t)(roblox_base + 0x123456);
- typedef int (*rbx_lua_load_t)(lua_State* L, const char* chunkname, const char* data, size_t size, int env);
- rbx_lua_load_t rbx_lua_load = (rbx_lua_load_t)(roblox_base + 0x654321);
- typedef void (*rbx_spawn_job_t)(TaskScheduler* scheduler, Job* job);
- rbx_spawn_job_t rbx_spawn_job = (rbx_spawn_job_t)(roblox_base + 0xABCDEF);
- // --- Core Executor Logic ---
- namespace Executor {
- lua_State* GetLuaState() {
- // Pointer chain to get ScriptContext
- DWORD* visualEngine = (DWORD*)(roblox_base + Offsets::VisualEnginePointer);
- DWORD* dataModel_step1 = (DWORD*)(*visualEngine + Offsets::VisualEngineToDataModel1);
- DWORD* dataModel = (DWORD*)(*dataModel_step1 + Offsets::VisualEngineToDataModel2);
- ScriptContext* scriptContext = (ScriptContext*)((char*)dataModel + Offsets::ScriptContext);
- // Return the lua_State using the offset within ScriptContext
- return scriptContext->main_L;
- }
- void Execute(const std::string& script) {
- // Get the main Task Scheduler and Lua State using the offsets.
- TaskScheduler* scheduler = *(TaskScheduler**)(roblox_base + Offsets::TaskSchedulerPointer);
- lua_State* main_L = GetLuaState();
- if (!scheduler || !main_L) {
- MessageBoxA(NULL, "Failed to find Scheduler or Lua State. Offsets may be outdated.", "Error", MB_OK | MB_ICONERROR);
- return;
- }
- // Create a new Lua thread (coroutine) to run our script in.
- // This is safer than running directly on the main state.
- lua_State* script_L = rbx_lua_newthread(main_L);
- // Load the script bytecode into the new thread.
- // This converts the text script into a function that Lua can run.
- rbx_lua_load(script_L, "Dolphin", script.c_str(), script.length(), 0);
- // Find the "WaitingHybridScriptsJob" which is responsible for running scripts.
- Job* script_job = scheduler->GetJobByName("WaitingHybridScriptsJob");
- if (!script_job) {
- MessageBoxA(NULL, "Failed to find WaitingHybridScriptsJob.", "Error", MB_OK | MB_ICONERROR);
- return;
- }
- // We would now need to create a custom "Script" object, assign our new thread (script_L) to it,
- // and add it to the job's queue. This is a highly complex step involving allocating and
- // structuring memory to perfectly match Roblox's internal script object.
- // For simplicity, we'll represent this with a call to a hypothetical "spawn" function.
- // A real implementation would manually construct this object in memory.
- rbx_spawn_job(scheduler, script_job); // This conceptual function would resume the thread in script_L.
- // This is a more robust and common method than calling pcall directly.
- }
- }
- // --- DLL Entry Point & Pipe Handling (Unchanged) ---
- void PipeThread() {
- char buffer[1024 * 32];
- HANDLE pipe;
- pipe = CreateNamedPipeA(
- "\\\\.\\pipe\\DolphinExecutorPipe",
- PIPE_ACCESS_INBOUND,
- PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
- 1, sizeof(buffer), sizeof(buffer), NMPWAIT_USE_DEFAULT_WAIT, NULL
- );
- while (pipe != INVALID_HANDLE_VALUE) {
- if (ConnectNamedPipe(pipe, NULL) != FALSE) {
- DWORD bytesRead;
- while (ReadFile(pipe, buffer, sizeof(buffer) - 1, &bytesRead, NULL) != FALSE) {
- buffer[bytesRead] = '\0';
- Executor::Execute(buffer);
- }
- }
- DisconnectNamedPipe(pipe);
- }
- }
- BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
- if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
- DisableThreadLibraryCalls(hModule);
- std::thread(PipeThread).detach();
- }
- return TRUE;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement