What Colbert has said is correct, the only way Ive found of accessing if a player has added an item into coregui is very hacky and requires you to process the error called by game.Descendantadded if you need a higher script context. There is however the menu in game which is part of the coregui which gets triggered by opening and closing which you will need to integrate into your anti exploit if you take this path. The only way I’ve managed to detect it is by having a trigger point for the amount of items which can be added to coregui. This method allows for me to catch Dex as a large amount of items are added but won’t work for smaller things depending on how many times you allow the “items” to be added for false positive prevention (speaking on the menu in the top left being open here). You can detect if the menu itself has been opened and disregard those items checked using the MenuIsOpen() but it will not allow you to detect the reset portion of the menu being opened (at least so far) so I have a bindable event in place to keep that greyed out and set the trigger point to 70 items max to prevent false positives and be able to catch Bigger guis.
Circumventable or not, this is still better than not having anything on the client. The strawman argument that it’s a “waste of time because it can be circumvented” serves no purpose other than to shut down any solutions that will work to an extent, if you know what you are doing. For instance, you could tie the above code to your game’s framework, set the script’s parent to nil, etc. etc.
Would really love it if people would stop using strawman arguments when it comes to solving problems that need fixing - they’re not constructive at all and honestly serve no purpose. I’m pretty sure other games use client-sided checks that aren’t circumventable by 99% of people.
It’s better how though? I don’t see the point, which is why I’m using the strawman argument in the first place. Explanations help to not have that brought up - it’s used when there’s not enough understanding.
The least you’re going to stop is a casual exploiter who isn’t spending the time to find out how your checks work or bother to circumvent them - it’s not going to stop a dedicated exploiter. I prefer to secure my server and close up as many open leverage points as possible, rather than bother myself with what someone is doing with a device they have full control over.
I don’t see client-side checks “working to an extent”. They sound more like band-aid solutions to me, which those band-aids can be pulled apart fairly quickly.
Like this. I don’t see how it works out for you. I’m not trying to shut it down; I genuinely don’t understand where you’re coming from. If you embed it into a game script then deleting the script means also breaking the rest of the game client-side; fine. It still comes off to me as a band-aid though.
Setting your script to nil won’t do anything except, as mentioned earlier, stop a casual without a function that can fetch nil instances. I don’t even believe LocalScripts run in nil.
See:
It’s better because for casual exploiters, they won’t know how break the checking system, and I’m sure a developer with enough knowledge on coding could easily stop any attempt to get past the checks. I know viruses in the past had a function that would re-add themselves upon being destroyed, but I’m not sure if that’s still possible.
There’s a better way. You can check the ClassName
of an object added to CoreGui in descendantadded, by indexing a nonexistant property in a pcall, like return obj[math.random()]
. It will return a string like 0.123456789 is not a valid member of ScreenGui
. From that point just grab the last part, check the name with tostring()
and match it against your exceptions/black list.
A dedicated dev can stop a dedicated exploiter
I made an anti exploit place myself for pure fun, and so far only one exploiter managed to bypass it.
While making it, I focused on using non obvious ways of detecting things, such as using game.ItemChanged
to detect WalkSpeed rather than connecting to a player’s Humanoid’s GetProppertyChangedSignal
each time (since they can spoof :Connect()
).
I also have a bunch of obstacles in place, such as
- not using remotes to send to the server unless necessary
- memchecks to prevent function replacing
- a method which crashes the exploiter when they try to use a function called “getconnections” to disconnect my events
- garbage collecting the primary modulescript and using a method which prevents them from obtaining a reference to it via “getloadedmodules”
- using LinkedSource which breaks the decompiler of a particular exploit
- having two methods of breaking unluac spread all over my script
- constants validation with string.char (or rather
("").char
, non-obvious as I said) - a few traps
Feel free to pm me a theoretical way you would use to bypass my checks if you were an exploiter, and I’ll see and tell you if it would work or not and why.
Not necessarily. Our code has lower context levels than their injected code. What I suggested is proper securing of the server, which is quite a bit of what you’ve done and that’s fine. Though a lot of it seems like obscurity. What client-side checks are you performing?
Okay so deep breath
- Connecting to
script.Changed
- Connecting to
ScriptContext.Error
and checking for stuff such as if the script argument is nil - If the script itself errored > instant crash (but again, without using
while true do end
as a primary way, because it can be easily bypassed withScriptContext:SetTimeout()
- Some variables which are metatables with
__tostring
field that when triggered, kicks the player - Checking for guis under CoreGui
- Setting
TextService
’s name to"CoreGui"
so when some exploits dogame.CoreGui
, they will index that service instead, which I connectedChildAdded
to - Checking for any changes to
TextService
- Comparing if
Instance.new("RemoteFunction").InvokeServer == cachedInvokeServer
- Comparing error messages to check if
InvokeServer
has been spoofed - Xpcalling
workspace:_____()
andworkspace[math.random()]
and comparing the stack trace returned by setting the error handler argument todebug.traceback
- Comparring error messages returned by the xpcall
- Checking if
Enum.HumanoidStateType.StrafingNoPhysics == cached
and iftypeof(it) == "EnumItem"
to detect NoClip bypass attempts - Setting the name of
game.Players
to" "
and detecting if it’s renamed - Checking for
BodyMovers
usingFindFirstChildWhichIsA("BodyMover")
(non obvious) - Detecting any changes to remotes
- Checking for
JumpPower
,WalkSpeed
andHipHeight
changes - Checking for
Position
,CFrame
andVelocity
changes of HumanoidRootPart - Checking for a fake humanoid
- Checking for noclip
- A method which sometimes detects a particular exploit that spoofs
__tostring
of robloxlocked guis to return a fake name - Checking if the main while loop has been aborted
- The only server-sided check - ping check (retcheck) with a remote function
- Checking for mismatch of
string.char(str bytes) == str
- Another check if the while loop was aborted, but in a different script
- Checking if
game:FindService("ServerStorage")
returns nil or not in order to detect Dex - Checking for FPS unlockers with
RenderStepped
- Memchecks
(all detections kick the player)
A lot of that seems useless personally without embedding it into core game logic (standalone checks are meh, circumvent A+). If they work for you, then by all means go ahead and do it if you want, I guess. As a personal preference, I will never perform any kind of client-side checks. I am always going to be focused on securing my server. What a client does with their device is nothing of my concern.
If you hide the checks inside of a localscript that is crucial to gameplay then it would break their game when they try to disable it.
See:
Again, this statement misses the point of anything I’m trying to say. See:
Don’t just assume that a client is able to leverage a point and give themselves advantages on my games. The only kind of advantage they would be able to receive in a model similar to mine (secure model) would only be for things they have authoritative control over.
I keep my server secure. I ensure my server checks any requests and validates their legitimacy. My problem is solved. Just because I don’t run checks on the client-side, doesn’t mean my game is insecure.
All in all, it comes down to preference. Kiriot thinks they are useful; I do not. That’s the end of it. I don’t waste my time doing client-side checks, Kiriot prefers to do them. I personally do not want to waste my time trying to add things to the client that can be circumvented, when I can focus my productivity on actually expanding and scaling my game.
I’m simply asking how kiriot finds them useful and what he does to gain an understanding of his view point on client-side checks not being “completely unnecessary”.
I could say it’s my hobby. If I know what other games are doing wrong in their clientsided anti exploits and if I also have some knowledge of how certain stuff works or how to patch it, then why couldn’t I cumulate all my knowledge and experience in one script?
If an exploiter wants to idk make an autofarm script for your game, they will most likely use stuff such as Dex or a remote spy. Kicking them each time they use either of these or make a mistake can make them finally get bored and give up.
It may seem like a waste of time to you and I understand that, but it’s not like it takes weeks to make a clientsided anti exploit either. That’s why i said “a dedicated dev can stop a dedicated exploiter”
Ad Hominem attacks are a fallacious and unproductive form of logic. To many of us, they say more about the attacker than the victim.
The success of one method does not prove that is it better than another method. Both methods can stop exploits, the difference is that client side patches can ALWAYS be circumvented where as server sided patches have the potential to be ineluctable. Admittedly, client side checks are usually simpler to implement and can prevent the unmotivated or unskilled from performing an exploit. The bottom line is, however, that client side security is fundamentally flawed. If you don’t believe so, I’d be happy to have a lengthier discussion on another topic to prevent derailing this one any further.
See:
Please do not make ad hominem attacks on the forums. I have flagged your post (and the second one for being off-topic).
It’s not that I don’t “understand the usefulness” of client-side checks: it’s that I don’t want them, nor do I see their usefulness. Securing my server along with productivity is my focus in development. Whereas you have to set aside some time to maintain such checks that are circumventable depending on your implementation, server-side checks are fairly flawless AND I can focus on pushing new content.
In a game with proper server-side security there is very little that can be leveraged from the client-side alone for gameplay-inhibiting effects. Client-side checks to me are merely something extraneous to pursue in a pocket of time for maximising how much you can “mitigate exploitation”.
The main argument for using client side checks is that you’ll stop people by making your game not worth messing with. Ultimately that’s a goal worth putting some time into because stopping people who don’t have the know how to bypass client checks is stopping most people. You’re not looking to stop the Tony Stark of exploits with these, just people who bought an exploit and are using it for h*cks and giggles.
Exploiters can decompile your local script and edit it to work without the client checks
You can also detect it when they “decompile” your Local script. You just need the right knowledge when it comes to that.
It’s pretty much a cat and mouse game, which is why I find it entertaining.
Not if you prevent them from getting a reference to the script and/or use a method or two which break unluac (which is what exploiters use to turn fetched bytecode into lua).
Edit: Scarperino beat me to it, but yea
Interesting, how exactly do you do that then?
So that only works for one exploit? There’s hundreds on the market.
This would be an impractical solution. It would be easier for the exploiter to just circumvent the checks in the first place.