Skip to content

Update for latest GMod version #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions build.bat
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
@echo off
echo Generating Windows project...
premake5 vs2017
:: @echo off

echo Building Module.
echo Dependencies: GIT, PREMAKE5, VISUAL STUDIO 2015/2013.
echo.

:: Hacky way to ensure we've got a git repository & submodules at our disposal
git init
git submodule update --init --recursive
echo.

:: Attempt to load VS2017
CALL "%SYSTEMDRIVE%\PROGRA~2\Microsoft Visual Studio\2017\Community\Common7\Tools\VsDevCmd.bat" 2>nul >nul

:: Fire up a Visual Studio command-line environment and generate our solution
IF DEFINED VS150COMNTOOLS (
echo Preparing for build with Visual Studio 2017.
premake5 vs2017
) ELSE IF DEFINED VS140COMNTOOLS (
echo Preparing for build with Visual Studio 2015.
premake5 vs2015
CALL "%VS140COMNTOOLS%VSDevCmd.bat"
) ELSE IF DEFINED VS120COMNTOOLS (
echo Preparing for build with Visual Studio 2013.
premake5 vs2013
CALL "%VS120COMNTOOLS%VSDevCmd.bat"
) ELSE (
echo Failed to detect Visual Studio installation.
timeout 5
exit /B 1
)

echo.

for /R %%X in (*.sln) do (
msbuild %%X
)

:: We're done!
timeout 5

exit /B %ERRORLEVEL%
73 changes: 73 additions & 0 deletions include/vmthook.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#pragma once

// thanks https://github.com/aixxe/vmthook

#include <cstdint>
#include <cstddef>
#include <cstring>
#include <memory>

class VMTHook
{
private:
std::uintptr_t **baseclass = nullptr;
std::unique_ptr<std::uintptr_t[]> current_vft = nullptr;
std::uintptr_t *original_vft = nullptr;
std::size_t total_functions = 0;

public:
VMTHook(void) = default;

VMTHook(void *baseclass)
{
this->baseclass = static_cast<std::uintptr_t **>(baseclass);

while (static_cast<std::uintptr_t *>(*this->baseclass)[this->total_functions])
++this->total_functions;

const std::size_t table_size = this->total_functions * sizeof(std::uintptr_t);

this->original_vft = *this->baseclass;
this->current_vft = std::make_unique<std::uintptr_t[]>(this->total_functions);

std::memcpy(this->current_vft.get(), this->original_vft, table_size);

*this->baseclass = this->current_vft.get();
};

~VMTHook()
{
*this->baseclass = this->original_vft;
};

template <typename Function>
inline const Function GetOriginalFunction(std::size_t function_index)
{
return reinterpret_cast<Function>(this->original_vft[function_index]);
}

inline bool HookFunction(void *new_function, const std::size_t function_index)
{
if (function_index > this->total_functions)
return false;

this->current_vft[function_index] = reinterpret_cast<std::uintptr_t>(new_function);

return true;
}

inline bool UnhookFunction(const std::size_t function_index)
{
if (function_index > this->total_functions)
return false;

this->current_vft[function_index] = this->original_vft[function_index];

return true;
}

inline std::size_t GetTotalFunctions()
{
return this->total_functions;
}
};
61 changes: 0 additions & 61 deletions include/vtable.h

This file was deleted.

2 changes: 1 addition & 1 deletion premake5.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ solution "gm_roc2"
flags "StaticRuntime"
kind "SharedLib"

targetdir "C:/Program Files (x86)/Steam/steamapps/common/GarrysMod/garrysmod/lua/bin"
targetdir "bin"

buildoptions {"/Os", "/MP", "/arch:SSE2"}

Expand Down
70 changes: 27 additions & 43 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "GarrysMod/Lua/Interface.h"
#include "vtable.h"
#include "vmthook.h"
#include "util.h"
#include "windows.h"

Expand All @@ -9,36 +9,36 @@

typedef unsigned char uchar;

VTable* sharedHooker;
VTable* clientHooker;
VMTHook* luaSharedVMTHook;
VMTHook* luaClientVMTHook;

using namespace GarrysMod;

Lua::ILuaBase *MENU;
void *clientState;
lua_State *clientState;

typedef void *(__thiscall *hRunStringExFn)(void*, char const*, char const*, char const*, bool, bool, bool, bool);
void * __fastcall hRunStringEx(void *_this, void*, char const* filename, char const* path, char const* torun, bool run, bool showerrors, bool idk, bool idk2)
typedef void *(__thiscall *RunStringExHookFn)(void *thisptr, const char *fileName, const char *path, const char *stringToRun, bool run, bool showErrors, bool, bool);
void * __fastcall RunStringExHook(void *thisptr, int edx, const char *fileName, const char *path, const char *stringToRun, bool run, bool showErrors, bool a, bool b)
{
MENU->PushSpecial(Lua::SPECIAL_GLOB);
MENU->GetField(-1, "hook");
MENU->GetField(-1, "Call");
MENU->PushString("RunOnClient");
MENU->PushNil();
MENU->PushString(filename);
MENU->PushString(torun);
MENU->PushString(fileName);
MENU->PushString(stringToRun);
MENU->Call(4, 1);
if (!MENU->IsType(-1, Lua::Type::NIL))
torun = MENU->CheckString();
stringToRun = MENU->CheckString();
MENU->Pop(3);

return hRunStringExFn(clientHooker->getold(RUNSTRINGEX))(_this, filename, path, torun, run, showerrors, idk, idk2);
return luaClientVMTHook->GetOriginalFunction<RunStringExHookFn>(RUNSTRINGEX)(thisptr, fileName, path, stringToRun, run, showErrors, a, b);
}

typedef void *(__thiscall *hCreateLuaInterfaceFn)(void *, uchar, bool);
void * __fastcall hCreateLuaInterface(void *_this, void *, uchar stateType, bool renew)
typedef lua_State *(__thiscall *CreateLuaInterfaceHookFn)(void *thisptr, unsigned char stateType, bool renew);
lua_State * __fastcall CreateLuaInterfaceHook(void *thisptr, int edx, unsigned char stateType, bool renew)
{
void *state = hCreateLuaInterfaceFn(sharedHooker->getold(CREATELUAINTERFACE))(_this, stateType, renew);
lua_State *state = luaSharedVMTHook->GetOriginalFunction<CreateLuaInterfaceHookFn>(CREATELUAINTERFACE)(thisptr, stateType, renew);

MENU->PushSpecial(Lua::SPECIAL_GLOB);
MENU->GetField(-1, "hook");
Expand All @@ -53,44 +53,29 @@ void * __fastcall hCreateLuaInterface(void *_this, void *, uchar stateType, bool

clientState = state;

clientHooker = new VTable(clientState);
clientHooker->hook(RUNSTRINGEX, hRunStringEx);
luaClientVMTHook = new VMTHook(state);
luaClientVMTHook->HookFunction(&RunStringExHook, RUNSTRINGEX);

return clientState;
}

typedef void *(__thiscall *hCloseLuaInterfaceFn)(void*, void*);
void * __fastcall hCloseLuaInterface(void *_this, void *ukwn, void *luaInterface)
typedef void *(__thiscall *CloseLuaInterfaceHookFn)(void *thisptr, void *state);
void * __fastcall CloseLuaInterfaceHook(void *thisptr, int edx, lua_State *state)
{
if (luaInterface == clientState)
if (state == clientState)
clientState = NULL;

return hCloseLuaInterfaceFn(sharedHooker->getold(CLOSELUAINTERFACE))(_this, luaInterface);
return luaSharedVMTHook->GetOriginalFunction<CloseLuaInterfaceHookFn>(CLOSELUAINTERFACE)(thisptr, state);
}

class CLuaInterface
{
private:
template<typename t>
inline t get(unsigned short which)
{
return t((*(char ***)(this))[which]);
}

public:
void RunStringEx(char const* filename, char const* path, char const* torun, bool run = true, bool showerrors = true, bool idk = true, bool idk2 = true)
{
return get<void(__thiscall *)(void*,char const*, char const*, char const*, bool, bool, bool, bool)>(RUNSTRINGEX)(this, filename, path, torun, run, showerrors, idk, idk2); //free cookies for people that know how to detect stuff
}

};

int RunOnClient(lua_State* state)
int RunOnClient(lua_State *state)
{
LUA->CheckType(1, GarrysMod::Lua::Type::STRING);

if (!clientState)
LUA->ThrowError("Not in game");

reinterpret_cast<CLuaInterface *>(clientState)->RunStringEx(LUA->CheckString(-3), LUA->CheckString(-2), LUA->CheckString());
luaClientVMTHook->GetOriginalFunction<RunStringExHookFn>(RUNSTRINGEX)(clientState, "", "", LUA->CheckString(1), true, true, true, true);

return 0;
}
Expand All @@ -100,15 +85,14 @@ GMOD_MODULE_OPEN()
MENU = LUA;

auto luaShared = util::GetInterfaceSingle<void *>("lua_shared.dll", "LUASHARED003");

if (!luaShared)
MessageBoxA(NULL, "gay", "gay", NULL);

sharedHooker = new VTable(luaShared);
luaSharedVMTHook = new VMTHook(luaShared);
luaSharedVMTHook->HookFunction(&CreateLuaInterfaceHook, CREATELUAINTERFACE);
luaSharedVMTHook->HookFunction(&CloseLuaInterfaceHook, CLOSELUAINTERFACE);

sharedHooker->hook(CREATELUAINTERFACE, hCreateLuaInterface);
sharedHooker->hook(CLOSELUAINTERFACE, hCloseLuaInterface);

LUA->PushSpecial(Lua::SPECIAL_GLOB);
LUA->PushString("RunOnClient");
LUA->PushCFunction(RunOnClient);
Expand Down