Streaming game development: https://www.twitch.tv/stabyourself Image

glaux - Garry's Mod Lua execution thing [also has source]

Feel free to showcase your own projects!
Wary
User avatar
Posts: 638
Joined: 03 Jun 2012, 14:30
Reputation: 57

Post » 23 May 2016, 00:42

(this is the most appropriate section I could find for this. Move to twatter if the section is inappropriate)

Earlier today, I made a thing that allows you to run your own lua scripts (in gmod) on any server.
I guess you could call this a "hack".

To use this, get a dll injector.
Once injected, a console window will open from the gmod process. Just type the filename of your lua script (the script must be located in garrysmod\lua, and don't forget the .lua extension) then press enter to run a script. Take note that some scripts will crash gmod simply because I'm a total retard and I'm too lazy to make my shit work properly. Most of the scripts I tested works correctly so it should be fit for release.

I didn't intensively test scripts on multiplayer, but my simple test script (its literally print("Hello world!", LocalPlayer())) works so I guess the rest should too.

Here's the source if you want to know how it works. It's in C++. (should be compiled with MSVC)

Code: Select all

#include "stdafx.h"

int (__cdecl* luaL_loadstring)(int lua_State, const char* src);
int (__cdecl* lua_gettop)(int lua_State);
int (__cdecl* lua_pcall)(int lua_State, int args, int results, int pr);
int (__cdecl* lua_settop)(int lua_State, int idx);
int (__cdecl* lua_getfield)(int lua_State, int idx, const char* fieldname);
const char* (__cdecl* lua_tolstring)(int lua_State, int idx, size_t* l);

int g_lua_State;

int __cdecl GetLuaState(int state)
{
   if (!g_lua_State)
   {
      g_lua_State = state;
   }
   return (*(DWORD *)(state + 20) - *(DWORD *)(state + 16)) >> 3;
}

BOOL GetFunctions()
{
   DWORD lua_shared = (DWORD)GetModuleHandleA("lua_shared.dll");
   if(!lua_shared)
      return FALSE;
   lua_gettop = (int(__cdecl*)(int))(lua_shared + 0xD780);
   lua_settop = (int(__cdecl*)(int,int))(lua_shared + 0xD790);
   lua_pcall = (int(__cdecl*)(int,int,int,int))(lua_shared + 0xF100);
   lua_tolstring = (const char* (__cdecl*)(int,int,size_t*))(lua_shared + 0xDFF0);
   lua_getfield = (int(__cdecl*)(int,int,const char*))(lua_shared + 0xE8A0);
   luaL_loadstring = (int(__cdecl*)(int,const char*))(lua_shared + 0x11490);
   return TRUE;
}

std::string get_hl2_path() { // not fully original, i copied some of the code from somewhere
   char buffer[MAX_PATH];
   GetModuleFileName(GetModuleHandleA("hl2.exe"), buffer, MAX_PATH);
   std::string::size_type pos = std::string(buffer).find_last_of("\\/");
   return std::string(buffer).substr(0, pos);
}

BOOL hax()
{
   AllocConsole();
   SetConsoleTitleA("glaux | by Louka/Wary @ V3rmillion");
   freopen("CONOUT$", "w", stdout);
   freopen("CONIN$", "r", stdin);
   std::cout << "glaux - by Louka/Wary @ V3rmillion\n\n";
   if (!GetFunctions())
   {
      FreeConsole();
      return FALSE;
   }

   BYTE bck[7];
   DWORD p;

   VirtualProtect((PVOID)lua_gettop, 7, PAGE_EXECUTE_READWRITE, &p);               // Set permissions to PAGE_EXECUTE_READWRITE
   memcpy(&bck, lua_gettop, 7);                                          // Copy 7 bytes ahead lua_gettop
   *(BYTE*)lua_gettop = 0xE9;                                             // Write a relative jmp instruction (0xE9) to the location of lua_gettop (aka hooking)
   *(DWORD*)((DWORD)lua_gettop + 1) = ((DWORD)GetLuaState - (DWORD)lua_gettop) - 5;
   *(BYTE*)((DWORD)lua_gettop + 5) = 0x90;                                    // Remove additional bytes
   *(BYTE*)((DWORD)lua_gettop + 6) = 0x90;                                  // Remove additional bytes
   while (!g_lua_State) // Wait for lua_gettop to be called
   {
      Sleep(15); // Less CPU intensive
   }
   memcpy(lua_gettop, &bck, 7); // Restore original bytes
   VirtualProtect((PVOID)lua_gettop, 7, p, &p); // Set original permissions. Not really needed but just in case garry decides to add some check for changed permissions
   while (true)
   {
      std::cout << "> ";
      std::string p;
      std::string t = get_hl2_path() + "\\garrysmod\\lua\\";
      getline(std::cin, p);
      t += p;
      
      std::ifstream file = std::ifstream(t);
      std::stringstream strm;
      if (!file.is_open())
      {
         std::cout << "Failed to open file: " << t.c_str() << std::endl;
         continue;
      }
      strm << file.rdbuf();
      int s = luaL_loadstring(g_lua_State, strm.str().c_str());
      if (!s)
      {
         try
         {
            s = lua_pcall(g_lua_State, 0, 0, 0);
            if (s)
            {
               const char* t = lua_tolstring(g_lua_State, -1, nullptr);
               std::cout << t << std::endl;
               lua_settop(g_lua_State, -(1) - 1);
            }
         }
         catch (...) // I don't really know how gmod throws exceptions :u
         {
            std::cout << "An error occured :u" << std::endl;
         }
      }
      else
      {
         const char* t = lua_tolstring(g_lua_State, -1, nullptr);
         std::cout << t << std::endl;
         lua_settop(g_lua_State, -(1)-1); // == lua_pop(state, 1)
      }
      
   }
}


Image

(If you are wondering: v3rmillion is another forum I'm really active on)

Click here for download.

Return to “Game development”

Who is online

Users browsing this forum: No registered users and 4 guests

cron