--[[
AntiExploitDetector (LocalScript)
Place under ReplicatedFirst (runs earliest, before most game content
loads) or StarterPlayerScripts. Pairs with AntiExploitHandler (a
normal Script) in ServerScriptService, which does the actual
banning/kicking.
Two detection methods:
1) Suspicious globals - functions like getgenv/hookfunction that
executors expose so exploit scripts can call them, but that never
exist on a normal client.
2) Dex Explorer - Dex (and forks like Dark Dex) builds its UI out of
named frames (ExplorerPanel, PropertiesFrame, SaveInstance)
parented into CoreGui or PlayerGui. Watching for those names is a
long-standing, widely used way to catch it.
Neither method is a guarantee - see the message alongside this file.
]]
local Players = game:GetService("Players")
local CoreGui = game:GetService("CoreGui")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local player = Players.LocalPlayer
local report = ReplicatedStorage:WaitForChild("AntiExploitReport")
local reported = false
local function flag(reason)
if reported then
return
end
reported = true
pcall(function()
report:FireServer(reason)
end)
end
-- 1) Suspicious globals ---------------------------------------------------
local SUSPICIOUS_GLOBALS = {
"getgenv", "getrenv", "getreg", "getgc", "getinstances",
"hookfunction", "hookmetamethod", "replaceclosure",
"getrawmetatable", "setrawmetatable",
"checkcaller", "iscclosure", "islclosure", "isexecutorclosure",
"getconnections", "identifyexecutor", "getexecutorname",
"fireclickdetector", "firetouchinterest", "fireproximityprompt",
}
local function scanGlobals()
local env = getfenv()
for _, name in ipairs(SUSPICIOUS_GLOBALS) do
if env[name] ~= nil then
return name
end
end
return nil
end
local hit = scanGlobals()
if hit then
flag("global:" .. hit)
end
-- Some exploits inject after this script has already run once, so keep watching.
task.spawn(function()
while true do
task.wait(10)
local again = scanGlobals()
if again then
flag("global:" .. again)
end
end
end)
-- 2) Dex Explorer (and forks) ---------------------------------------------
local DEX_NAMES = {
ExplorerPanel = true,
PropertiesFrame = true,
SaveInstance = true,
}
local function checkInstance(inst)
if DEX_NAMES[inst.Name] then
flag("dex:" .. inst.Name)
end
end
local function watch(container)
-- Catch anything already present (best-effort; CoreGui's own built-in
-- elements are hidden from scripts, but injected ones usually aren't).
pcall(function()
for _, inst in ipairs(container:GetDescendants()) do
checkInstance(inst)
end
end)
-- Catch anything added later - this is the part that reliably works.
pcall(function()
container.DescendantAdded:Connect(checkInstance)
end)
end
watch(CoreGui)
local ok, playerGui = pcall(function()
return player:WaitForChild("PlayerGui")
end)
if ok and playerGui then
watch(playerGui)
end1 views