I’m wondering if anyone can help me in blocking/detecting a function detour. To be specific, I’ve been trying to stop the RunString/CompileString from being detoured but I haven’t really come across a proper way of accomplishing this. I know of the method of assigning the functions to a variable and then overwriting the functions but this is not what I wish to accomplish.
I ask this because I’m working on a way of loading lua code from a webserver and the code can easily be revealed by using RunString = print or CompileString = print. To note, this is to be apart of a project that I plan on releasing and so people will have their hands on the files and that is how they can use the above method to reveal the code.
Localizing the function as soon as possible would be your first priority.
To check for changes that have happened before you get a local copy, you can use functions like debug.getinfo and debug.getupvalue to check for anything out of place.
Also, if you’re loading files from a webserver, who’s to say that someone wont find the address and simply download the files themselves? Or just capture packets while joining?
Thank you everyone, I’ll take a look into these methods.
The webserver interaction is done through PHP files. There’s only one public PHP file and the lua is stored in PHP files in password protected directories. If required information is not sent/received by the webserver then no lua will be displayed/sent. If someone happens to get the password to the directories, there is no chance of them getting the lua from the PHP file unless they have direct access to the webserver or that person has figured out a way on how to download PHP files. I only plan on loading serverside lua from the webserver as someone can easily get the clientside lua either way by just using a cache decrypter. As for interception the lua code, it’s entirely possible but only to those that know how to do so.
This is mainly to stop those that don’t know what they’re doing.
[editline]11th March 2014[/editline]
I’ve written some code that won’t load the required module and define some vital functions if it detects RunString as the print function. I was wondering, is it possible to do this detection through the module itself?
I made a system which does everything on the server. Basically anything the client needs while joining is in cl_init.lua; all of the client/shared files are compiled into a list and all of the file data is pulled into memory as one large chunk. I then process it by removing all comments, un-needed white-space, empty lines, etc. After that’s done ( I still need to finish up an encryption / obfuscation system ) it’s sent to the client and no cache is generated.
A few additional security measures are needed; RunString could be detoured and data could be retrieved if someone were to inject gmod. The users could capture packets from the server and splice all of them together if they’re not encrypted. So far I’m planning on overwriting RunString in a way that will allow me to encrypt the code where when it’s downloaded there will be a 5 second window for an unencryption key to be sent and useable whereby it’s then loaded in. The same issues remain depending on a few things. IF Garry didn’t make RunString obtain a new address on each run, then a user can easily use the address of the original RunString and bypass the encryption to get code; this also means they must inject into gmod. Secondly if they were to capture packets and somehow figure the key out which would be tied to time so they’d need to understand when the server starts sending data and when it stopped sending data for two of x parts of the key but it could be possible.
The other method would be to require a DLL for the client and use my game-engines networking system to download and run the code. This would be more of a hassle for clients to need a DLL to run the game-mode but would be the most secure in terms of detecting injected dlls, detecting root-kit style aimbots ( video driver-based aimbot, or hidden even deeper with cloaking abilities etc ), unlocks a wider array of encryption/decryption mechanisms for security, guarantees no cache is downloaded / stored unless in highly encrypted form, and other things.
Another method, also including a dll, would be to code all client/shared code in a dll which would require the download to run the game-mode.
I’m currently at about 2MB of client/shared code and over 3MB total, and unfortunately the limitation of sending code and other files is around 20KB/s so I was thinking about doing what you’re doing by going through a web-interface which would allow faster downloads at the risk of others potentially finding the code; alternatively it could be served by a PHP script whereby the code is outside of the html root directory and the PHP accesses it and applies encryption to it, pings the server to let the server know the unencryption key for the user at x ip and y steamid so that when the player fully joins the key can be sent and the code executed; this still has the other issues where RunString could be rerouted which would require an injected dll, or packets to be read.
Add me on Steam if you like; I’ve tried quite a few things.
I’m thinking of changing my method to instead download a file to the server’s autorun/server/ directory to have CompileFile called on the downloaded file and then just have it deleted once it is compiled. This would practically rule out using RunString = print; and the likes and the only way of getting the file would be to have a program to monitor incoming files being downloaded. I’m going to be staying away from loading clientside files and encryption for now until I get the above method complete.
The main reason I’m not going to be using RunString to do it any more is because sometimes it’ll work and sometimes it won’t work (oddly enough).
I got it all working now. Thankfully it wasn’t such a huge problem with converting it from using RunString to downloading the file and running CompileFile on it. I’m using cURL and my method to accomplish this is by getting the contents of the returned content from a PHP file and then creating/writing to a file before running CompileFile on it, then I just simply removed the file. From what I’ve tried so far, I haven’t been able to reveal anything from it (contents of the compiled/deleted file).
Loading lua from a webserver doesn’t have to just be used for DRM purposes. It could ensure that the latest version of the program is being run. But aside from that, I’m only compiling serverside files.
I originally wanted to know that as I was using RunString from the module. A simple way of getting the code being sent from the server was to use “RunString = print;” I’ve since switched to a different method (as I previously said).
In case anyone was wondering, here’s how I partially secured it:
[lua]if (tostring(debug.getinfo(RunString).func) == tostring(debug.getinfo(print).func or tostring(debug.getinfo(RunString).func) == tostring(debug.getinfo(Msg).func) or debug.getupvalue(debug.getinfo(RunString).func, 1) != nil) then
–RunString was detoured, do stuff here.
–RunString passed as what it was originally, do stuff here.
It checks if RunString is equal to print or Msg and also checks if the upvalue of RunString (by 1) doesn’t equal nil (to cover a general amount of other functions) as with RunString, it is equal to nil.
I wouldn’t call it DRM Johnny, it’s simply preventing keeping a stored copy on the client. DRM would be more like installing something on the client and having it run 24/7 for no reason ( like Sony root-kit or The new Tribes service that runs 24/7 on a free-to-play game )
I tutor a lot of people on my friends list, all of them know if they need help with something or if they need help with something they’re making they can ask me and I’ll be more than happy to help.
My issue with allowing client/shared cache is that some people will just rip it without asking; but if you ask then I’m more likely, than not, going to help you. If done correctly, most code is done on the client because it serves as the viewer while the server authenticates and manages data. I am considering releasing a base-gamemode with a lot of the helper functions and classes I’ve written over the past while, but meh, we’ll see.
The problem with using that RJ is that ( I haven’t verified this yet ) if Garry didn’t use a means to generate random addresses for functions each runtime, then once someone locates the original RunString function they’ll always know where it’s at. If he made it so that the address changes, it’ll make it more difficult. That’s why I’m not bothering too much with that system until I test that; I’ve been working on polish and other systems.
If by that you mean that when you try printing out debug.getinfo(RunString).func, it will always print it as something different, then yes, it generates a random address (but only when the server is restarted). It seems that RunString is different each time but print always comes up as “function: builtin#25.”
Thanks; that helps. I’m referring to outside programs ability to locate it such as a hex-editor, or an outside dll, so I’m planning on writing a utility which will allow me to more accurately pin-point it eventually.
Garry doesn’t “generate random addresses”. It’s an actual pointer to a function in memory, it changes because of how memory’s managed.
There’s currently two public ways to view clientside code, one is to detour functions that run the code (namely ILuaInterface::RunString) and decrypting the cache. With the latter, no matter what you do, your code WILL be dumped.
DRM in Garry’s Mod is absolutely pointless. If you squished/obfuscated your files, all that’d happen is; people wouldn’t be able to read it, they would still be able to run it just fine. That’s counter-productive, if you want people to learn from your code. If you don’t obfuscate it, people can and always will be able to access your code.
The best DRM is open-sourcing your code, it’ll never be stolen then.