Detect CoreGui Exploits (INCLUDING JJSPLOIT, FLUXES AND CELERY UPON INJECTION)!

CoreGui Instance Detection via ContentProvider Preload Checks

Roblox restricts direct access to the CoreGui container, but through the ContentProvider service, assets that are preloaded into CoreGui can still be monitored. Using this, we can create a system that detects any foreign instances added to CoreGui and since poorly made exploits like Fluxes and JJsploit create instances inside CoreGui, we can detect it through something like this

Main Detection Code

local AMONGUS = { "rbxassetid://10066921516", "rbxassetid://11702779409" }

task.spawn(function()
    while true do
        game:GetService("ContentProvider"):preloadAsync({game.CoreGui}, function(assetid, status)
            if not table.find(AMONGUS, assetid) and assetid:find("rbxassetid://") and not IsStudio then
                local assetId = assetid:gsub("rbxassetid://", "")
                if assetId and not vc then
                    -- Trigger ban here
                elseif vc and assetId then
                    -- Silent log to webhook for manual review (e.g., SelfView assets can create false triggers)
                end
            end
        end)
        task.wait(20)
    end
end)

game:GetService("GuiService"):SetInspectMenuEnabled(false)

the reason for grabbing any rbxassetid string is because official Roblox instances would always return as rbxasset except for fonts and the escape menu audio which should you should whitelist yourself

A Downside to this would be having to turn the avatar inspect menu off because it directly loads UGC content id’s into CoreGui which in return triggers the detection.

What if the exploit does not rely on any images?
If an exploit doesn’t rely on images, we can use weak tables to detect instances referencing CoreGui entirely. This approach is based on the concept outlined in this DevForum post, although it may cause false triggers due to how unreliant Roblox can be

    task.spawn(function()
        while true do
            local HoneyPot = setmetatable({game:GetService("CoreGui"), {}, newproxy(true), newproxy()}, {
                __mode = "v"
            })

            while HoneyPot[2] and HoneyPot[3] and HoneyPot[4] do
                task.wait(7)
            end
                if HoneyPot[1] then                            
                    -- Ban them here
            end 
        end 
    end) 

Alternatively if you’d like to use both detections, you would have to include them both in the same loop to prevent the CoreGui reference from false triggering, you can do so with something like this

local Players = game["Pla" .. "yers\000A"]
local Player  = Players["Loca" .. "lPla" .. "yer\000A"]
local RunService = game['getService\000'](game, "RunService\000")
local VoiceChatService = game['getService\000'](game, "VoiceChatService\000")
local vc
local IsStudio = RunService:isStudio()
local success, enabled = pcall(function()
    return VoiceChatService:IsVoiceEnabledForUserIdAsync(Player.UserId)
end)

if success and enabled then
    vc = true
else vc = false
end

local AMONGUS = { "rbxassetid://10066921516", "rbxassetid://11702779409"}

task.spawn(function()
    while true do
        game:GetService("ContentProvider"):preloadAsync({game.CoreGui}, function(assetid, status)
            if not table.find(AMONGUS, assetid) and assetid:find("rbxassetid://") and not IsStudio then
                local assetId = assetid:gsub("rbxassetid://","")
                if assetId and not vc then
                    -- ban them here
                elseif vc and assetId then
                    -- preferable if you silent log the asset id to a webhook for manual review (SelfView loads assets into CoreGui // False triggers)
                end
            end
        end)

            local HoneyPot = setmetatable({game:GetService("CoreGui"), {}, newproxy(true), newproxy()}, {
                __mode = "v"
            })

            while HoneyPot[2] and HoneyPot[3] and HoneyPot[4] do
                task.wait(7)
            end
                if HoneyPot[1] then                            
                    -- Ban them here
                end 
        task.wait(20)
    end
end)

game:GetService("GuiService"):SetInspectMenuEnabled(false)

This detection is rather very heavy on the client as it checks for every preloaded asset in the CoreGui container so it’s not recommended to decrease the loop time

this should go without saying, you’re better off using any Anti-Hook to prevent exploiters from whitelisting their own ids

22 Likes

Variables names aren’t saved to bytecode. In your case, renaming “AMONGUS” won’t do any difference since it doesn’t affect bytecode at all.

6 Likes

to my knowledge some decompilers are sophisticated enough to do so, such as oracle for instance

3 Likes

It’s simply not possible, bytecode doesn’t contain your variable names at all.

3 Likes

in that sense i could be wrong then, i’ll edit the post

2 Likes

If you want to prove that, you can just download luau onto you machine and compile a simple script, you will notice that variable names won’t get saved. (table keys and function names do get saved though.)

I had assumed that variable names get saved since table keys do aswell, i suppose i was wrong in that case

3 Likes

you can circumnavigate these by calling cloneref on CoreGui (although some scripts are too stupid to do so) and by replacing any rbxassetid:// images in an example gui with direct rbxasset:// images (which is a hacky way to prevent being detected by most preloadasync checks (like yours) but it works)

Found a method to whitelist things without hooking CoreGui.

local AllowedAssetsInQueue = {106273803261101}  -- Add all allowed asset IDs here
local ContentProvider = game:GetService("ContentProvider")

local function checkAssetsInQueue()
	return ContentProvider.RequestQueueSize
end

local function getAssetFetchStatus(asset)
	return ContentProvider:GetAssetFetchStatus(tostring(asset))
end

local function areAllowedAssetsLoaded()
	for _, asset in ipairs(AllowedAssetsInQueue) do
		if getAssetFetchStatus(asset) ~= Enum.AssetFetchStatus.Success then
			return false
		end
	end
	return true
end

local function isExploitDetected()
	local queueSize = checkAssetsInQueue()
	if queueSize == 0 then
		return false
	end

	local allLoaded = areAllowedAssetsLoaded()
	if allLoaded and queueSize > 0 then
		return true
	end

	for _, asset in ipairs(AllowedAssetsInQueue) do
		if getAssetFetchStatus(asset) == Enum.AssetFetchStatus.None then
			return true
		end
	end

	return false
end

task.spawn(function()
	task.wait(3)  -- Initial delay from loading everything
	while true do
		if isExploitDetected() then
			print("Potential exploit detected!")
		end
		task.wait()  -- Check every second
	end
end)
1 Like

that would work too but would come at the cost of your client’s performance, and this would be very inconvenient to whitelist assets especially in a production game

4 Likes

This works fine until you add spray paint or allow players to insert Decals into your game. If a blacklisted image loads, everyone gets banned.

do not use this!! :sob:

Decals, images do not get loaded into CoreGui as it’s a restricted container, this is perfectly fine to use

2 Likes

This being used for a big game is a stretch, and with the problems it has, the issues will be really clear once it’s in a real game. Plus, with the alternative exploits available nowadays, such as ‘getcustomasset’, ‘getconnections’, ‘gethui’, and ‘cloneref’, it makes it useless.

But you can always do whatever you want! Just keep in mind the problems this brings!!!

1 Like

buddy what are you yapping about its a CoreGui asset check there are no problems that this brings unless a player is forcing a custom font through a fast-flag which you whitelist in the table if it logs as a false trigger

this has been used in this production game for around 3 months now and the only false positives were either fonts, or SelfView asset loading which SILENT logs for manual review, i’m fairly sure other places also utilize something of that sort.

4 Likes

Figure out what the problems are yourself at this point lol
If you’re going to keep going on about it, then just don’t reply and deal with the problem yourself literally

games used to use this months ago, and you can abuse it to generate false positives because the ContentProvider service returns data in a really weird way.

Through exploits, you can falsely trigger it for everyone.

gl ig :man_shrugging: do whatever you want man

Show me an example on how you can abuse it, if your game is insecure towards basic vulnerabilities then you should not be looking at a CoreGui detection in the first place

1 Like

im not showing you how you abuse it its a roblox problem not yours lol (literally just the way the service works)

only reason i clicked on this is because it popped up and its really not good at all

the problems that come from this just arent that good yk

im gonna uh stop replying so just goodluck man if you really thing theres no problems in this then good for you but just be mindful of using this

this is bypassed in 8 lines max.

1 Like

Open up citadel ac vrother :cry::cry::cry:

Exploiters can do almost anything. I’ve seen one placing instances in services where they don’t belong, even RunService.

1 Like