Theoretical end to backdoored workshop shit?

Okay, so I was recently looking into swift and other bullshit Apple based stuff and remembered about their alpha app quick scan stuff that has a quick look for certain calls to certain functions and files and flags them. See, could we not in theory have a check on key functions like RunConsoleCommand, looking for keywords, looking for calls to ulx data files out with ulx and then return a list of suspicious calls to the user with a reference?

Okay so how, there has to be some way of checking all server side script before execution right?

Appreciate any tips sent my way,

[editline]20th May 2015[/editline]

And yes, obviously would be horrible in practice but hey, it’s worth even a look right?

If you loaded before autorun on the server and detoured commonly exploitable functions like that, yes. However, the script would have to be run on the server to do any detections. “scanning” lua files with regex searches can easily be hidden from by clever malware writers due to how flexible lua really is.

Perhaps just some kind of way to allow people to manually accept workshop updates and to do a diff on the content like you can do on github and stuff. Or just a general content browser. Backdoors usually get added unnoticed using an update.

You could take a look at one of my tools:

Console command logger which adds a few useful hooks…

GM:CanPlayerRunConCommand( _p, _cmd, _args, _arg_text )
GM:ShouldLogConCommand( _p, _cmd, _args, _arg_text, _server )

The old version ( ) injected a function over top of the concommand.Add callback referenced function, and ensured all console commands were injected upon by modifying concommand.Add and checking any pre-existing console commands and re-running the code on top… This is not the best way to do it, but it works.

The first example overwrites concommand.Run( _p, _cmd, _args, _arg_text ) which can control how console commands are executed, but I was mid-update on it so there is still some useless code in it but it should give you an idea on how to prevent backdoors via concommand… You have several options… You can either whitelist all commands that are allowed, or blacklist all.

There are pros and cons to both…

With the Whitelist, it means you need to authorize all commands you want to be allowed BUT if concommand.Add was used to create the command then it can just as easily be overwritten with one that introduces a backdoor meaning you would need to also whitelist data that can be used, etc…

You could extend the whitelist into something more “intelligent” by ensuring a command that is added is paired with a security key, or with a specific reference which can’t be changed but this limits auto-refresh which is bad for dev-work but ideal for live servers.

And, with the Blacklist you will need to build up a database of potentially unlimited number of commands that shouldn’t be allowed. The blacklist can be good in certain situations but this is unlikely to solve the problem because changing the command name would bypass it…

You could limit usage of console commands to all but a few users, but the issue is a console command isn’t even required to exist for a backdoor to be present, and some addons use console command calls on the server ( where the player object is NULL which is the only way, I know of, to see if the server is making the call ) so even by limiting you’d still factor in NULL as an allowed player because it is the server, either way it won’t solve the issue really… The code executes in the same environment as non-addon/gma code so that isn’t secure either…

The best course of action is to find which addons have backdoors and which authors incorporate them into their code and ban their use on your servers ( and report them to workshop ).

Due to the dynamic dispatch problem, you can’t know 100% sure which functions are being called by static analysis. This is proven by Rice’s theorem.

Have a term explanation though, this is shit I learned in a master course:
Dynamic dispatch problem: finding out which variables(/table values /function return values/etc.) return to which functions
Rice’s theorem: see wiki, it’s a generalisation of the halting problem, which states that it is, and will forever be impossible to write a program that will accurately tell you in finite time whether a given program runs infinitely long.

Tl;Dr, you can try to make it, but it can always be circumvented.

Which type is loaded first, legacy or workshop addons?

workshop addons I think

But it would at the very least decrease the quantity of backdoored addons especially those really poorly made ones?

Lua doesn’t have polymorphism or overloading, though, and the number of ways you can index globals with strings is limited to one or two chokepoints which you can’t get around without binary modules (like the crowd favorite _G["\82\117\110\83\116\114\105\110\103"]) and can themselves be easily found by a scanner. It might take more than one pass to track localization or renaming or other naughty things, but it’s possible.

Lua is a higher order language. That’s enough to make it undecidable.
You can do fancy shit similar to this:
[lua]BadFunctionLocation = 241
i = 0
res = nil
for a, b in pairs(_R) do
i = i + 1
if i == BadFunctionLocation then res = b end

res(permaban everyone)
Of course you’ll have to hope this always goes right, but it should get the point across.
You can arbitrarily complicate this with fancy calculations. Return functions with functions that do really weird computations to decide which function to return etc. Try to figure that out with static analysis.

Ah, sorry, I should’ve clarified that I meant just a simple file search and not actual semantic analysis. If you want to do something evil and hide it you don’t have very many starting points – whatever ungodly things you do to generate the key, you still have to refer to _G, or package.loaded._G, or hook, or game, or whatever library you’re after, and you have to do it somewhere, and that somewhere would be relatively easy to find.

This is similar to the halting problem. You can’t find out if the code is malicious without running it.

You can probably use the same trick to hide references to _G. Besides, is referring to _G necessarily a bad thing?

No, and there’re a couple of legitimate reasons to do it (like Tacoscript’s awful string-to-enum lookups), but it’s rare enough to be a red flag.

And if you want to get to _G you have to do this:
local g = package[shit][fuck]

e: (forgot about getfenv/debug.getfenv, i’m too used to 5.2)


There’s a million ways to get _G without actually using _G, getfenv probably being the most obvious one.

Point being that there are Lua scanners out there that find most backdoors, but there’s no way there is ever going to be “automatic script blocking” or something equivalent in Garry’s Mod. For that to happen there would have to be some function that is solely used by backdoors but none of the legitimate scripts. Otherwise there are too many false positives.

you could always use the !cake method of obfuscating and do shit like this

local • = _G
local ••=’%c’
local • = string
•[•••] = •.
•[•••] = •.
•[•••] = •.
local • = •[•.••(•••.•••(•,9), 82, 117, 110, 83, 116, 114, 105, 110, 103)]

your average goofball server owner wouldn’t have a damn clue what to make of that
edit: facepunch turns invisible chars into dots but you get my drift

"Finding most exploits " is sadly a flawed approach. Once it’s made, it will find quite a few backdoored addons at the start, but once people find out it’s there they’ll start to circumvent it. This becomes a cat and mouse game that you’re bound to lose because fooling the analysis is childishly easy. This is of course unless you’re an academic willing to spend huge amounts of time and research into it, trying, like antivirus programs, to find malicious patterns of code.

A workshop addon scanner is risky: one is easily assured that the program works because the baddies generally don’t advertise that they’ve worked around it. This could lead to the false belief that the workshop would be safer than it was before the scanner was there.

One of the things I worked on for my anti-cheat / admin-mod is a readonly type object which is loaded prior to anything… Basically a meta-table that allows one-time data-setting and never allows overwrite so you can load functions into it and run it from there as long as they were inserted prior to anything else loading or being able to tamper with it.

The issue with it is: You can wipe readonly and re-create it unless you turn _G into a meta-table and restrict readonly…

I haven’t messed with it in a few weeks because of appointments and declining health, but I plan on, at the very least, to finish it and see if there are any ways to get past it although something like this would be great to be integrated into the Lua version compiled with GMod which would, hopefully, guarantee that nothing could get by it or overwrite any references and so that it can be pre-populated with certain functions such as RunString to prevent redirects if a game-mode / addon author wants to ensure the client doesn’t redirect it to save anything being run through it, etc…

But, maybe it should be something we ask someone to compile into GMod as a way to reference original references to specific functions to prevent redirects created by addons ( because my idea about being able to disable Lua from running in specific / all addons is either on the back-burner or denied for whatever reason – some addons are poorly coded but have great models so I still think this is a viable option to prevent backdoors / memory-waste and memory-leaks )…

I don’t want to sound insensitive but this is the Developer Discussion section, I don’t want to read about how someone is dying here. I wish you all the best but please stop posting about that everywhere.

What’s the point of a readonly object if it’s not readonly? I mean it literally serves no purpose at all. I’m sure I can find plenty of ways besides the one that you listed to modify the table.

You can’t rely on the fact that it’s loaded before anything else, too. If someone wants to they will load before you.

On topic: there’s no way to reliably do anything. Any detection method you can think of, someone else can think of a way to avoid it. I’m not against the creation of something that’ll catch half-arsed backdoors but if it’s released to the public, it’s really just a false sense of security.