1

So i am trying to "hack" a game however not for cheating purposes. I am looking to extend the games scripting functionality through a DLL that can look for processes and return them. The game I am looking to do this for is Train Simulator (i know, don't laugh) and the game uses lua to script all of the engine functionality within the game. All the 3rd party devs get to see is the lua script that they write.

Inside the games lua there is core functions. The main ones:

function Initialise()

end

function Update(time) -- time is the interval since the last update

end

There is also C functions that are used as such:

Call("SetControlValue", name, index, value)
or
Call("GetIsPlayer")

These return different values.

What i have so far with my DLL is as follows:

#include <windows.h>


BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        /* The DLL is being loaded for the first time by a given process.
        Perform per-process initialization here.  If the initialization
        is successful, return TRUE; if unsuccessful, return FALSE. */
        MessageBoxA(0, "TSDll has been attached !", "Train Sim Dll", MB_ICONEXCLAMATION | MB_OK);
        break;
    }
    return TRUE;
}

And this works. In my train sim engine script i am using the loadlib library to load the DLL.

libinit, err = loadlib("plugins\\TSDll.dll", "libinit")
if _G["libinit"] then 
    Print("TSDll Library Loaded!")
    libinit()
else
    Print("loadlib on TSDll failed: ")
    Print(err)
end

And i get this result: Dll Popup

So the dll initialises properly.

The problem i face is that the Lua library is directly built in to the game binary (as far as i know) which means i am unable to reference lua.dll for fundamental functions such as lua_pushstring. Does anyone here know how i can find the address of these functions. I know a dll like this has been made before but the person who did it has been very secretive about how it has been done.

Thanks, Dan

2
  • What tools have you been using to reverse engineer your target? It stands to reason if you were using IDA that FLIRT/signatures could be of help. However, you may need to figure out first whether you are dealing with Lua or LuaJIT and (roughly) which version. The strings utility should be of help here.
    – 0xC0000022L
    Feb 26, 2019 at 9:43
  • I haven't been using anything to reverse engineer yet, that is what i am trying to figure out how to do.
    – DanH50049
    Feb 27, 2019 at 16:51

2 Answers 2

1

As you said, the Lua engine is embedded directly into the game. It's inside plugins/GameManagerVC.dll (or GameManagerVC64.dll in case of 64-bit). So, first step will be finding out, which version of Lua it is. So put this DLL into Ghidra or IDA Pro. The most easiest way of figuring out, what version of Lua it uses, is by searching for "Lua" string in string list (In case of IDA Pro Views > Open Subviews > Strings). In case of Train Simulator, we found Lua 5.0.2. Then we should download the Lua 5.0.2 source code, so we can search for functions. The easiest way of search for functions, is by picking some function, which have some strings, and search those strings in your disassembled file. Then rename them, look for references, etc. This way, you shold be able to find all functions, you're looking for.

4
  • 1
    A DLL placement attack could be a useful for this. If you only have a handful of functions in the target DLL you could figure out the prototypes and simply forward the ones you aren't interested in but intercept the calls you are interested in. I have used this successfully in the past and it seems this could be applicable here.
    – 0xC0000022L
    Apr 22, 2021 at 14:57
  • 1
    @0xC0000022L yes, this method can spare a lot of time, although, in this DLL, lua functions are not exported, thus, this method is not possible.
    – GAMELASTER
    Apr 22, 2021 at 17:03
  • 1
    That's one aspect I find annoying about this question. I still have no clue how I could get those DLLs to take a look. So this question has a very narrow audience.
    – 0xC0000022L
    Apr 22, 2021 at 20:33
  • It is incredibly specific but I tried to make it as broad as possible. I have disassembled GameManagerVC.dll however I am unsure what is am looking for in order to push a string back or something similar.
    – DanH50049
    Apr 24, 2021 at 23:03
0

The best way you can get access to Lua when it's statically linked to the game is by writing a detour to the lua_gettop() method in the Lua library. I actually wrote a guide explaining how to do this with the Microsoft Research Detours Package. See my guide here, which explains how to hook the method and the lua_State here.

Example Detour Code

typedef int(__cdecl *gettop)(unsigned long);
gettop lua_gettop_p = (gettop)0x18121A870; // Might change if the game updates

unsigned long lua_State = 0;

// This is our version of the gettop function from IDA
DWORD _gettop(__int64 state)
{
    // If Lua State is not already set then log it and set it
    if (lua_State == 0) {
        lua_State = state;
    }

    // This is from the decompiled function and cannot be changed
    return (unsigned long)(*((QWORD *)state + 2) - *((QWORD *)state + 3)) >> 4;
}

// Here we setup the detour to "replace" the games function with ours
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(LPVOID&)lua_gettop_p, (PBYTE)_gettop);
DetourTransactionCommit();
1
  • 2
    Hello and welcome to re.se. Good Answer but in its current state is mostly dependent on that notion link. If notion goes down the answer is worthless. Can you edit the answer to add more details such that it's relevant and works without depending on any link outside of re.se.
    – sudhackar
    Apr 10, 2022 at 11:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.