Best ways to stop people leaking your game client side

Place copying is mostly ever done to reverse engineer a game with better context, not to just republish it. Having a “good enough” look at how it works is all people need to write scripts targeting the game itself.

If anyone really cared to steal it exactly as is including images with local paths, they could. Those images are still uploaded to the website and Roblox still stores their actual IDs internally.

2 Likes

Clearly you know nothing about how programs like synapse work and what their limitations are. Asset IDs are server sided associations that are associated internally and used or not. How they are referenced are exactly that. The only thing that allows place stealing as it is now is that asset IDs work essentially as a hyperlink. There is no means to force that hyperlink to exist when it does not outside of through the server.

If you wanted to steal an item this way, you “could”, but programs like synapse would have to be specifically written for that purpose. While I have no desire to put this out there, I will say that developers like those making synapse didn’t put place copying in so people could steal assets, thieves are not their demographic. They put it in there to facilitate writing hacks, which is their market. Even if they did though, it wouldn’t be easy.

If you think you know something in this field, try it. I know many who have and to be quite blunt, anyone who knows anything about how file paths are used and the limitations of programs like synapse would tell you this isn’t doable. At best, if the developers of programs like synapse re-wrote their programs in a way to facilitate this, it would just give them raw data copies of models and images. These people would have to figure out what every one is and attempt to piece it back together themselves.

This has has a few impacts that are very important.

  1. It wouldn’t work without the nature of Synapse or other programs like it being re-written.

  2. Doing so for programs like Synapse greatly complicates the scope of how the program operates and would make updating it specifically for that purpose more work than I think they would care for. Also it would make their program much easier to detect.

  3. Even if the things above both happened. The process would become difficult enough as to elininate 99.9% of the people doing it. It would turn it from something skill-less, to an actually time consuming skilled task.

This isn’t some “no big deal” issue. Switching an asset from using a universal Roblox hyperlink to using a local file path is a huge deal as far as someone outside trying to access that data. These hack tools can’t access server data. How it is loaded to the client matters because now we’re no longer talking about accessing a function within Roblox, we’re moving to things like accessing local cache and memory addresses, which is an entirely different animal.

Even with the place file uncopylocked, you cant download those files.

If you want to see this in action, make a place file in studio, link some images by their local path, and try to even download those images yourself without changing the path to an asset ID. Or just go to tribe sim and try to download that GUI from that place file.

The only way to access them would be to go into your “images”, find the file, and copy the ID. This information is not used when it’s not entered, so there’s no way to steal something that isn’t used.

For the record. Security is never about absolute protection, there’s no such thing.
It’s about making it difficult enough to deter people from it.

Nearly every game out there is possible to be exploited and have its assets stolen.
Right now, the Roblox asset ID linking system just makes it exceptionally easy.

Using local addresses comes with its own issues, but for securing assets, it’s worth it 100%
For one, you have to upload the assets by the same name to every place you intend to use them.
This means keeping a local directory structure that is a duplicate of your game’s with every raw file.
To any developer that cares about theft, this is a small cost.

But no, just because data exists on Roblox’s side doesn’t mean 3rd party programs access it.
The whole reason they “reverse engineer” games they steal is because they don’t have the server scripts or anything server-sided that isn’t copied to the client.

Currently, the asset ID or file path is copied to the client. If you don’t enter the asset ID, it’s not copied to the client, so they don’t have it. Sure, there are other ways they “could” obtain the models or images, in theory, but the odds are they won’t, and when they do it would be rare. Compare that to right now when every kid with any copy of synapse can steal your place with the click of a button vs. a solution that doesn’t yet exist that would be much more work no matter what… this is a no-brainer.

You don’t ignore security because in theory one day someone can do something to bypass it. If that was the case, the internet would have no security at all.

Edit: For the record, I’m not even saying they should switch it entirely. For many developers, this isn’t even worth the effort. I’m just saying that the option is already there. There are just changes that they have made that break a lot of them. They could just give us a button “use local path” that puts the local path in instead of the asset ID (if the file is local) or give us correct information to know the paths and make sure asset loading works with local paths for everything.

A really good way is to make all of your local script variables

local

.

And make all of your functions local too with

local function

This makes it so that exploiters can’t decode your variable name and function names.


Also make sure that you keep ModuleScripts that only the server uses in ServerStorage or ServerScriptService to prevent the client from decompiling them.


A DMCA costs no money


That’s a very bad design choice and makes your game lag a lot.

An exploit could easilly just download the relative images. Sure it needs some extra code but there are very talented exploit devs who can do that.

Besides even if they didn’t they’d still get everything else expect remotely downloaded assets.

It won’t lag if you let the server handle as many tasks as necessary, but you obviously shouldn’t literally dump everything on the server. You should never trust anything that comes from clients anyways.

Yes, they can. If information has to reach the client, the exploit can read it. There is no workaround for that. The client has to load the images, so at some point it must be told where on the site they are stored.

Also, this only applies to instance data fetched over the network, not instances themselves. This data is usually immutable, so this could never be applied to models or other constructs that can change as gameplay goes on.

Things like HTTPS (or public key/similar encryptions, which I assume you’re referring to) are proven to be physically impossible to crack using a traditional computer in a human-reasonable amount of time. This is not the case here. This is a 5 minute fix on the exploit developer’s part for the multiple hours it can take to manage assets for a large game developer.

If a player has a slow network it definetly lags.

That’s why you simulate server behavior. Your server code doesn’t have to be identical.

Thats literally the same as doing stuff locally.

Here is what each should handle



I said simulate, not run the same code. Let’s say you have an inventory system, but don’t want to make players wait for each action to replicate. You send a remote to the server to request an item move, but in the meanwhile you place the item where it should have been if the request were successful. In case of failure, the server returns false and you undo the movement.

This has hardly anything in common with the server code as it just simulates server behavior. There is a considerable amount of lag, but it’s masked by the UI.

This is absolutely false. If you list an asset as /images/imagename that IS the address it loads from. It is loading it from the local directory using a local path. Roblox isn’t taking /images/imagename and decoding that into an asset ID, then loading it from the asset ID, they are loading it directly from that image name.

Even IF you used a program that can search memory for images and downloaded all of the images related to a game, something Synapse can’t even do, you would need other programs which I don’t really feel the need to advertise here, it still would not magically generate an internal hyperlink that’s not even being used. That hyperlink (the asset ID) isn’t used AT ALL when it’s not entered that way into the image/texture/etc. So IF you scanned and got the image out of memory, you would have an image you need to identify unless Roblox uses absolutely 0 encryption at all. Then you would have to know that image is what belongs there and upload it to your local place using that same name or use your own asset ID.

Yes, the website might have that image and asset ID associated with it, but that information is in no way ever loaded onto the client, it would be completely unnecessary to do so. While yes, you can steal whatever information is loaded to the client, you can’t magically conjure information that isn’t.

Before I ever got into developing, I used to write exploits, I know how they work and they are not magic. They have limitations. The fact you think things can be done that can’t shows exactly how little understanding you have of this subject.

Your assumption was wrong, so I’m not even going to bother addressing this. You very clearly do not know what you are talking about.

There’s no amount of talent that can compensate for things that do not exist. Synapse is a script injector that uses the same structure for injecting scripts that Roblox uses in Studio, giving it the ability to modify or inject a local script or change local settings for the client. Basically, anything the client is made to be able to do, Synapse can do, including executing remote events or even downloading a local copy of everything currently loaded. That is it and its limitations are entirely defined by that. There are plugins that use data within that but those plugins still are bound to the same rules and just represent various ways of using local data.

You can’t scan memory with Synapse, that’s an entirely different kind of exploit. While those do exist, there are none I’ve seen that target Roblox. Even the most popular one I know of does not work with Roblox. Because of the way Roblox launches instances and the fact they are kind of sandboxed within Roblox, you would have to design it specifically for this purpose. No one has done it because there’s really no demand/market for it. Maybe if Roblox actually had some security, this might change, but I wouldn’t count on that.

Yes, you still would get all the stuff you normally get. Local scripts, etc. but that’s not the point. The point is that you could choose to protect more assets if this was more open. Currently, it only works on textures applied directly to the asset and GUI images.

Roblox uses asset IDs as a sort of internal hyperlink allowing the same asset to be used in multiple places. This is how you can have a GUI uploaded to one place, then copy it to 50 places and it still works. However, local addresses have access permissions. No one can just access /images or /meshes off your place file. Even if you open-source your game, people still can’t access this. So when you take an image that is loaded locally, that image can’t be accessed except as executed locally. So if I made a GUI and addressed all the images locally, I could open-source it or download a copy of its place and those images would not be there. When you uploaded it to your place, it would still say /images/imagename, but in your local image directory, no such image exists.

Yes, it’s “possible” to get those images from local memory off the client, but that’s not even accessible through scripts. We (Roblox Devs) can’t write scripts that access local memory on the player’s computer or inside the Roblox client and neither can exploiters. When you get into stuff like that, you’re talking about memory scrapers that scan targeted regions of memory for images loaded into memory. While yes, these programs exist and are used all the time, there are none that currently work with Roblox. Even if there was, these programs use local memory on the client, they do not have access to the server address of the image. They usually output to a local directory and you have to dig through them. They often don’t even have the file names (though this depends on the encryption or lack of).

This makes it a LOT of work to steal and rebuild someone’s game. Go to any site for exploiting, like the popular one everyone knows as the source for Synapse stuff. This is looked down upon even in those communities. Most exploiters are not looking to help people steal games and assets. That garbage community is looked down upon even by exploiters.

I will tell you factually, I know exactly how these things are done. There is nothing currently in Synapse or any of those programs that allows it and there are currently no programs designed for this purpose that work on Roblox. Regardless if this changes in the future or not, there’s nothing that just makes this easy. This small piece of security would be more than enough to make me happy. I know developers that use this currently for their GUIs and textures (I do this too). This is why there are so many people on Hidden Devs selling clearly stolen models with no textures.

“Filing for DMCA is not free either.”

Submitting a DMCA notice to Roblox doesn’t cost anything unless you actually end up going to court over it (you won’t). There’s really no practical way (other than maybe that memory spike method that has been mentioned) of detecting or preventing client sided exploits and theft, and when it happens, submitting a DMCA notice is the thing to do about it. Despite your darndest of attempts to convince everyone otherwise, it’s free to do. Please read section 5 of the Roblox Terms of Use for more information on how to do this.

The site you mentioned only costs $200 because youre getting them to do it for you instead of doing it yourself.

The entire basis to this post is false. There is no “local directory” at play with the client. You can pop open Fiddler or similar tools and clearly see an HTTP request be issued out from your computer to fetch the asset by its URL/ID. I also tested the case in which the client disconnects from the server, and then dynamically loads the image for the first time. As expected, it still made out a request to the proper place and loaded the image fine.

image
image
image

It’s probably the case here that on join the server sends a mapping of “paths” to “IDs” to each client so that they can load the images at their leisure. A program such as Synapse would simply have to provide a method to fetch said ID given a path, as Roblox is presumably already doing internally, locally.

Lastly, it’s not constructive to say things such as “Clearly you know nothing about how programs like synapse work” or “You very clearly do not know what you are talking about”, especially when it is quite easily verifiable that your claim is wrong.

1 Like

Bro what about Rolling Thunder…

In your example, //Images/DeerImage, you are not given the asset ID you show in the web link from the link used. Even if you scripted it this way, you do not get the asset ID you highlighted from the library. It’s simply not given and doesn’t exist within the script.

That address, as I said, is used locally. I’m not sure if you are misunderstanding the word locally, but I’ll make it quite clear in case you are struggling.

When you upload, in your example “DeerImage”.
You are uploading that to a specific place.
It does not exist in any other place.
If you want to use it in another place, you have to reference the asset ID, like what’s used in the library.
It does not exist in any other place.
If you have say a group and you upload “DeerImage” to say “Place 1”, you can not reference /Images/DeerImage from any other place.

When you use /Images/DeerImage, Roblox isn’t going “hmm… I wonder what this is”, translating that to an asset ID, then fetching the ID. No, that’s ridiculous, it’s loading it from the place file it exists within and it’s using the same path that was used, not making up a new one. Yes, it’s sending an HTTP request, but not for an asset ID. Why on earth would Roblox or anyone for that matter put in an ability to reference locally, which contrary to what you believe, yes, it is locally (to that place), just to have it need to convert that to an asset ID to look for it by asset ID somewhere else? What you are saying makes literally no sense.

If I’m running a server locally off my computer and during the execution of a file on my server, that file accesses another part of my server that’s also local, but that file isn’t shared, you don’t suddenly gain access to that file independently because you have access to the local file.

If you could fetch an asset ID from a local image, which I’m not entirely certain you can (I have one way I could test that I know of but I don’t know or even think it would work), that still doesn’t give you the asset ID on a place file download.

Just because you can, in studio, go to your assets, click on images, see a list of all the images uploaded to that place, click on that image and get the asset ID so you can find it in the library, doesn’t mean that anyone else accessing it can do that. I know if I give someone permission to edit a game but I don’t give them permission to edit group games, they can’t access what I upload. They can’t even play my animations in that place. So if someone with game edit permissions can’t access what another person uploads to a group because they don’t have group edit permissions, why would a player locally be able to access that same information?

rbxgameasset is not the same as assetid.
Even IF you could access the asset ID this way, which once again, I highly doubt you can, Roblox could EASILY change that and make that a permission-level access. It would not be hard on their end to rectify this at all.

So I double checked, and my theory of Roblox pre-fetching the IDs and storing them somewhere in memory was wrong. When the client sends the HTTP request, Roblox returns the asset ID with it in the headers. This is still of course in complete contradiction to your claim.

You may click the link below and see exactly that.

https://assetdelivery.roblox.com/v2/asset?universeId=242708590&assetName=Images%2FDeerImage
image

Breaking API backwards compatibility almost never happens on Roblox, not to mention that this sort of information has genuine use cases in tooling and such.

Lastly, I don’t see why they would try to do anything about it when in the worst case you can still automatically download all the images and bulk upload them for the place copy. In reality though, no one will care, because once again most people download places to see the context of scripts so that they may write better exploits, not to reupload.

I will no longer reply to random uninformed rants with interspersed insults.

Is this tested using an image that was added via asset ID or was it tested using an image that was only referenced in the place using nothing more than /Images/ImageName (i.e /Images/DeerImage)?

How exactly would you automatically download all the images in bulk?

The entire premise of this thread is written by and for people that very clearly care. Even if the bulk of these people are doing it for exploit purposes, enough of them do it strictly for theft that the number of people selling stolen assets is vastly greater than the number of people making legitimate assets. As the OP pointed out, beyond places like Hidden Devs, HD, and countless others, you can literally find professional sites with gig workers advertising things like they will steal you any place on Roblox for $5. There is more than enough reason to care enough to do something. Even if someone making scripts found a way to do this, they would most likely use it for their own gain. This would be a huge improvement over anyone and everyone who downloads even a hacked version of synapse being able to steal any place and all of its assets with a couple of mouse clicks that even an 8-year-old kid with no developing knowledge can do effortlessly.

I don’t know if it’s relevant or matters to you, but this post/thread is literally “Best ways to stop people leaking your game client side”. There’s not a single flawless proposal here. That doesn’t mean we should all give up and determine we’ll never stop people from stealing our games.

Most people on Roblox wouldn’t even do it, which is fine, because the less people using features like this, the less there will be people out there with an incentive to try to bypass it. I have yet to see a single person able to steal the images from a place like tribe sim, which is open source. I would take those odds over the current theft rate for everything else any day.

The image was brand new and added through the asset manager in that specific place.

The link I sent, which is what the client calls out to when loading the image, returns a CDN link from where you can directly download the raw data.

My point was never giving up; rather it’s about finding permanent solutions. This issue is an industry one anyways, since AAA games haven’t stopped asset ripping either.

1 Like