Easy way to detect Dex Explorer

Good afternoon.

A simple method to detect Dex Explorer, regardless of its version, thanks to a simple method using weak tables.
The code itself:

if game:GetService("RunService"):IsClient() then
	task.spawn(function()
		while true do
			local serviceRef = game:GetService("WebSocketService") -- You have every right to replace with any other service that is never used in ROBLOX and is not held permanently.

			local weakTable = setmetatable({}, { __mode = "v" })
			table.insert(weakTable, serviceRef)

			serviceRef = nil -- We make the service nil so it's not held by anything, just in case anyway

			task.wait(2) -- The garbage collector clears it and doesn't hold it back

			if weakTable[1] then -- If it's held, it's detected
				warn("Detected")
			end
		end
	end)
end

Why does it work? Here is an example of the latest version of Dex Explorer:

local service = setmetatable({}, {
	__index = function(self, name)
		self[name] = cloneref(game:GetService(name))
		return self[name]
	end
})

Dex uses this as a caching method, in simple words it saves all found services for future and present use. Keeping the service in the Dex table just keeps it there, creating a strong link. As long as the Dex Explorer is active, the link will be held and the garbage collector will not remove it.

The method associated with weak tables is from here: Anti-Cheat Methods - Resources / Community Resources - Developer Forum | Roblox

24 Likes

How likely are false positives with this?

Could we see some proof of this working? If you do have proof, the executor used to test this must have a pretty poor implementation of cloneref.

Hi.

I don’t think they should be, I’ve checked several times and the limit for gc to be guaranteed to clean everything up, well, 2 seconds is the limit, and besides who would use WebSocketService for holding??

So rather the answer is no at all, you can increase from 2 seconds a bit more just in case.

Hello.

I’ve checked on Swift, bunni.lol, and a couple of mobile executors, what specifically evidence should I provide and how?

Just services though are cloned with cloneref(), definitely yes, and even the sunc documentation says that

cloneref() will protect completely against various weak tables attacks!!!

But as it seems to me, checking if something is in the service and checking for retention are a bit different. Anyway, if someone has a chance to check this on paid Executors, it will be great!

Rehash of a previously known detection.

Please don’t repost them and take credit for an already known method. Anti-Cheat Methods - Resources / Community Resources - Developer Forum | Roblox

You may get a false positive if code execution hitches (fps drops), because the GC may not step, and your thread may resume by then.

Also, please post in which executors you’re testing this as well, because they may not trip on good internals.

3 Likes

just some kind of output statement from the detection method… idk. Anything to prove that it works, because cloneref should completely bypass such a detection if implemented correctly.

The service ref applied to the weak table is just the userdata, and since cloneref creates a new userdata with the same underlying instance pointer, in theory this shouldn’t detect Dex provided the snippet you sent is the only way it references services (i.e. there isn’t another way which directly references the original userdata).

Hi.

I saw this thread, there’s a CoreGui related check and it’s a bit different from my weak tables, in terms of it being there better than mine I guess.

I also did an interesting check: I did the code to find all services and the weak table checked those services that are held and those that are not, I didn’t do anything like nil, CoreGui behaves unusually in terms of sometimes it is held and sometimes it is not. In terms of it’s a repository of various stuff that is sometimes held and sometimes not.

In my test result, 12 services were permanently held, 13 if CoreGui was also held. And the total services were about 94. That’s my point, services that aren’t being used, “just sleeping”, are literally never retained. And CoreGui is the opposite of that.

About the different executors, I can certainly make a statement about that, of course.

That’s the GC doing work.

Regardless, the reason this works is because dex’s service cache causes one reference to always live, so while one is collected, internally, when it is repushed again, it will use the clonerefd one instead. Ideally, you’d cloneref every time you get a service as to prevent this, and that probably will solve this detection, but I’d have to test to be sure

1 Like

So, as you requested, here are two videos. In the first one, I created a GUI that holds the service in the usual way and via cloneref(), and the results are obvious.

I believe the problem lies with Dex Explorer.

I tested it via Bunni.lol.


1 Like

I see - Dex must be referencing the original userdata internally. Surprised they didn’t patch that, honestly. Although this detection has been posted before, thank you for confirming.

1 Like

Pretty good detection, works like a charm. Poster also helped improve this for a specific game :smile:

3 Likes

872826x re-release of a detection known by man and non-man

Can you re-release some more, please? Maybe if I see the same detection once more, I’ll gain Alzheimer’s and forget that this was already released, so it can be something new to me.

Hello again.

It’s great to see you when you share different things based on your life experience; it brings out different emotions.

By the way, yes, you are right, any methods that have been posted, such as Celery Detection through weak tables or Electron Detection, will also detect Dex Explorer behind the scenes, so yes, there is something concrete in your words.

Either way, don’t bring up topics that are essentially empty and have no dramatic meaning.

Thank you for your post. :smiley:

1 Like

I’ve done a test phase with this in liveops

it does indeed create false positives

1 Like

yeah because you’re purely relying on roblox’s garbage collection :sob:

1 Like

yeah im aware but im bringing this up incase anyone else tries to use the detection method lmao

1 Like

so is this method bad?

local smth end do end (30)

WebsocketService is no longer available due to old ROBLOX updates, and will always return nil when accessed. It’s my fault for leaving it that way… Try this:

if game:GetService("RunService"):IsClient() then
	task.spawn(function()
		while true do
			local service = game:GetService("TestService")

			local cat1 = setmetatable({
				service,

				["cat2"] = newproxy(true)
			}, {
				__mode = "v"
			})

			service = nil

			repeat
				task.wait()
			until not cat1["cat2"]

			for index, value in cat1 do
				warn("Detected")
				break
			end

			task.wait(0.22)
		end
	end)
end
2 Likes

False positives DO HAPPEN, I tried using multipleservices(forgot the names of it)

Sometimes people’s GCs are insanely slow(android players etc) - they WILL get false flagged

this should merely be used as a detection flag rather than reason