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