Understanding method hooking and keeping your game protected

function Checks.RobloxLocked()
	return Player.Name
end
function Checks.SecurityContext()
	assert(not pcall(function() return workspace.DataCost end))
	assert(not pcall(function() return workspace.RobloxLocked end))
	assert(not pcall(function() return game:GetService("CoreGui").Name end))
	assert(not pcall(function() return game:GetService("CoreGui").SelectionImageObject end))
	assert(not pcall(function() return game:GetService("Chat"):GetShouldUseLuaChat() end))
end
local function validateTrace(trace)
	local prev trace = trace:gsub("^.-Begin","")
	for v in trace:gmatch("Script '.-, Line") do
		assert(not prev or prev == v) prev = v
	end
end
function Checks.InstanceMetatable()
	assert(RF.InvokeServer == Instance.new("RemoteFunction").InvokeServer)
	validateTrace(xpcall(function() return game.Banana end,function() return debug.traceback() end))
	validateTrace(xpcall(function()  RF:InvokeServer({[game]=1}) end,function() return debug.traceback() end))
	validateTrace(xpcall(function()  RE:FireServer({[game]=1}) end,function() return debug.traceback() end))
	assert(getmetatable(game) == getmetatable(RF)) assert(type(getmetatable(game)) == "string")
end

Didn’t add a “check if InvokeServer has changed since the script started, just in case”.
(not that it should matter with the other checks, unless they return a C-function, like GetFullName)
Also need to do the InvokeServer check for all RE/RF methods.

7 Likes

that looks really interesting!! i’ve never used the debugger like that, ill have to look more deeply into what’s going on when i get home :stuck_out_tongue:

Every client-related problem is solved by not trusting the client. It’s pretty straightforward. If you trust the client then FE is pointless because you’ve just made a way around it. The whole point of FE is don’t trust the client, so naturally anything you write should be handled on the server and only relayed to the client. It’s not that complicated.

4 Likes

Because it contributes to stopping people from even trying to hack my game. It’s a plugin that runs before I upload the game that insures that anyone stealing my code(or even the whole game, which will be possible again like always eventually) wont be able to do much with the source. No comments, no variable names that make sense, and even half of the instances have obfuscated names. It’s tough to take advantage of that.

the problem, especially in a game like a competitive fps where low response times are really important (especialy moreso in roblox because servers are known for high ping), is establishing the middle ground between the client and the server so that you can have a game that feels responsive and flows well without sacrificing any of your security. while it may work for other kinds of games, handling every single thing on the server just isn’t an option in shooters because of latency, especially in roblox, so you have to come up with solutions to differentiate what and what aren’t valid actions the client can perform.

2 Likes

Thank you for posting this.

Remember kids: Sometimes all it takes is a few conditional statements on the server to do a sanity check on remotes coming in.

1 Like

Oh it’s a plugin? Is it available for other people to have, or should I just make my own? :stuck_out_tongue:

It’s not currently available for anyone. It’s not compatible with everyone’s game either, it happens to work for mine because I know exactly how everything is set up(what variable names can be changed, what instance names can be changed, my coding punctuation habits)

Unfortunately no hassle-free obfuscator can exist(I think), because there would be almost no way of knowing what variables are safe to scramble and which are not.

Ah well, it was worth asking.

@stravant 's Minifier is great

7 Likes

running the code using this through a beautifier produces readable results :c

Does it distinguish between variables saved to datastores that should not be renamed?

I don’t know much about lua but i just want to say that’s a beautuful domain.

2 Likes

It should only rename globals and locals, no table indexes (which would be very tricky anyway)
Unless you save getfenv() to the DataStore, nothing should change data-wise.

i haven’t looked at it in too much detail, but it seems like the checks are preformed under the assumption that id7 exploits elevate the permissions of all local scripts on the client. this isn’t the case, those scripts still run with normal script security permissions. it’s only scripts executed by the exploit that run with level 7 perms. additionally, the id7’s use functions that are custom to their respective lua environments to access the instance metatable, the normal getmetatable() function wouldn’t work on instances, even with level 7 permissions.

(also: i redid the last section of the post and updated some parts because i had some inaccurate information)

I know they have things like getrawmetatable() they have access to. I added the checks because there have been exploits that raised the context of all scripts. Might as well check for that, in case such an exploit still exists/returns. The Checks.InstanceMetatable() tries to see if InvokeServer/FireServer has been replaced. In theory, some of these checks could break into the exploit’s environment and make it unuseable.

Mind that some of this code isn’t tested yet, only parts of it. E.g. I checked if the xpcall returns what I expected it to return, but as you can see in the code above, I didn’t account for xpcall also returning a boolean as the first value.

I was given RC7 by someone and ran a few test, eventually leading to my quick patch that I gave to @ScriptOn. From what I’ve seen, RC7 loads a LocalScript into Script Context and parents it to nil or something. When you try to call .ChildAdded on Script Context nothing appears as RC7 somehow is able to re parent the script before events even detect it being added. The only solution to exploits like RC7 that I can see being viable is to just create white list for sensitive services such as Script Context and CoreGui as that is where these exploits hide. There is absolutely no way of protecting against RC7 etc without ROBLOX protecting these services as we as developer are not even allowed into them because of them being RobloxLocked.

2 Likes

RC7 works similar to all other exploits I’ve seen such as Seven, etc. They don’t necessarily parent it to nil manually, that’s an automatic thing that is done. Basically, they create a LocalScript instance to run code locally, they need to create this instance or else it wouldn’t be able to run code.

They use ScriptContext for a few reasons, one being to execute code

blob.png

and uses ScriptContext to change the execution level. As seen above, it sets the level identity to 7 (This means it will show as though it has all permissions from the client however internally, there’s only 6 levels on Roblox - since they start from 0 instead of 1).

Another use for ScriptContext is actually to decompile LocalScripts and ModuleScripts loaded on the client memory. This also applies if the ModuleScript is required from the server and not the client, the source of server-side required ModuleScripts replicate to the client because it just… does?

blob.png

Now, your solution you stated about creating a whitelist of instances for RobloxLocked services such as CoreGui, ScriptContext, etc wouldn’t work as the CoreGui service creates instances all the time and these instances may change due to either edits on Roblox’s side or simply because a CoreScript created an instance such as creating frames for username display on the leaderboard.

There is no simple solution to these exploits because if there was, I’m sure it would be fixed already. It’s a complicated situation where you need to take into account what needs to be fixed but how to fix the exploit without interfering with the game functionality and development in a sense like, Roblox in the past have disabled client-side loadstring as a result of exploiters. They had to make this change but they try to avoid making patches which would interfere with the gameplay on a whole scale.

The solutions for some of these issues would require some re-development of the game client which would be a very tedious task to do. Now sadly, I cannot propose many solutions myself since I simply don’t have the information to make an educated decision on what would be the best way to patch these exploits without understanding fully how the Roblox client works. All I know is the information I’ve gathered by doing tests, etc.

The only simple solution I would put on the table would be since these exploits like to C++ hook onto the Roblox client and create themselves a sub-process inside the main Roblox client process would be to detect that and close the client and report the event internally to an analytics tracking so they can look into what happened.

7 Likes

Note that there’s a lot of kiddos on http://v3rmillion.net whom are leaking accounts to RC7, therefore causing more of these people to wreak havoc.