game structure dumper
Key RequiredUniversal

game structure dumper

Universal ScriptGBernGBern 14.3K views 5.3K executesUpdated Apr 22, 2026
4.3/ 5(14 votes)
12286% Positive
Lua Script•1092 lines (43009 chars)
local CFG = {
    MAX_DEPTH      = 12,
    VERIFY         = true,
    RF_TIMEOUT     = 2,
    VERIFY_RF      = true,
    VERIFY_RF_MAX  = 30,
    VERIFY_RV_PAIR = false,
    SAMPLE_VALUES   = true,
    SAMPLE_INTERVAL = 3,
    SAMPLE_COUNT    = 4,
    SAMPLE_SERVICES = {"Workspace", "ReplicatedStorage"},
}

local OUTPUT        = {}
local REGISTRY      = {}
local VALUE_TARGETS = {}

local VULN_GROUPS = {
    WRITABLE_VALUE    = {label="WRITABLE_VALUE     - Value writable from client",         items={}, detail=true,  threshold=1},
    CALLABLE_RF       = {label="CALLABLE_RF        - RemoteFunction responds to invoke",  items={}, detail=true,  threshold=1},
    API_SURFACE       = {label="API_SURFACE        - exposed Remote API",                 items={}, detail=true,  threshold=1},
    NAKED_REMOTE      = {label="NAKED_REMOTE       - Remote at root without structure",   items={}, detail=true,  threshold=1},
    REMOTE_VALUE_PAIR = {label="REMOTE_VALUE_PAIR  - Remote writes to Value directly",    items={}, detail=true,  threshold=1},
    READABLE_MODULE   = {label="READABLE_MODULE    - ModuleScript loadable from client",  items={}, detail=false, threshold=5},
    ANTICHEAT         = {label="ANTICHEAT          - AC system",                  items={}, detail=true,  threshold=1},
    SURFACE_SUMMARY   = {label="SURFACE_SUMMARY    - vulns statistics",          items={}, detail=true,  threshold=1},
}

local VULN_ORDER = {
    "WRITABLE_VALUE","CALLABLE_RF","API_SURFACE",
    "NAKED_REMOTE","REMOTE_VALUE_PAIR",
    "READABLE_MODULE","ANTICHEAT","SURFACE_SUMMARY",
}

local SERVICES = {
    "Workspace","Players","ReplicatedStorage","ReplicatedFirst",
    "ServerStorage","ServerScriptService","StarterGui",
    "StarterPack","StarterPlayer","Lighting","SoundService","Teams","Chat",
}

local function ulen(s)
    local n, i = 0, 1
    while i <= #s do
        local b = s:byte(i)
        if     b >= 240 then i = i + 4
        elseif b >= 224 then i = i + 3
        elseif b >= 192 then i = i + 2
        else              i = i + 1
        end
        n = n + 1
    end
    return n
end

local B = 70
local function bTop() return "╔"..string.rep("═",B).."╗" end
local function bBot() return "╚"..string.rep("═",B).."╝" end
local function bMid() return "╠"..string.rep("═",B).."╣" end
local function bLine(text)
    local s = "  "..(text or "")
    local pad = math.max(0, B - ulen(s))
    return "║"..s..string.rep(" ",pad).."║"
end
local function bEmpty() return "║"..string.rep(" ",B).."║" end
local function out(line) table.insert(OUTPUT, line or "") end

-- legend
local function writeLegend()
    out(bTop())
    out(bLine("GAME DUMPER"))
    out(bMid())
    out(bEmpty())
    out(bLine("OBJECT TREE:"))
    out(bLine("  ├── / └──  [ClassName] Name  — object"))
    out(bLine("  │  ┊ @KEY = val [type]        — attribute of the object above"))
    out(bLine("  ‹pos:X,Y,Z›      BasePart position"))
    out(bLine("  ‹PP:Name›        model PrimaryPart"))
    out(bLine("  ‹= value›        Value object's value"))
    out(bLine("  ‹Script›         script type"))
    out(bLine("  ‹RemoteEvent›    RemoteEvent"))
    out(bLine("  ‹RemoteFunction› RemoteFunction"))
    out(bEmpty())
    out(bLine("VALUE MONITOR:"))
    out(bLine("  [STATIC]                  did not change during observation"))
    out(bLine("  [DYNAMIC: RISING a→b]     value was increasing"))
    out(bLine("  [DYNAMIC: FALLING a→b]    value was decreasing"))
    out(bLine("  [DYNAMIC: FLUCTUATING]    changed without clear trend"))
    out(bEmpty())
    out(bLine("PRIORITY LEVELS:"))
    out(bLine("  [P1] CRITICAL  test passed - confirmed working"))
    out(bLine("  [P2] LIKELY    structural indicators - prob working"))
    out(bLine("  [P3] POSSIBLE  pattern found - requires manual verification"))
    out(bLine("  [--] FALSE+    test failed - not working"))
    out(bEmpty())
    out(bLine("FINDING TYPES:"))
    out(bEmpty())
    out(bLine("  WRITABLE_VALUE"))
    out(bLine("    Value object in Workspace/ReplicatedStorage"))
    out(bLine("    CRITICAL - server did not reset value after client write"))
    out(bLine("    FALSE+   - server restored original value (serverside)"))
    out(bEmpty())
    out(bLine("  CALLABLE_RF"))
    out(bLine("    RemoteFunction responded to InvokeServer()"))
    out(bLine("    CRITICAL - handler exists and accepts the call"))
    out(bEmpty())
    out(bLine("  API_SURFACE"))
    out(bLine("    Folder in ReplicatedStorage where 70%+ children are Remotes"))
    out(bLine("    Each Remote here is a separate entry point to the server"))
    out(bEmpty())
    out(bLine("  NAKED_REMOTE"))
    out(bLine("    Remote directly in the root of ReplicatedStorage"))
    out(bEmpty())
    out(bLine("  REMOTE_VALUE_PAIR"))
    out(bLine("    Remote and Value with similar names in the same folder"))
    out(bLine("    CRITICAL - value changed after calling the Remote"))
    out(bEmpty())
    out(bLine("  READABLE_MODULE"))
    out(bLine("    ModuleScript in ReplicatedStorage"))
    out(bLine("    CRITICAL - require() executed successfully"))
    out(bEmpty())
    out(bLine("  ANTICHEAT"))
    out(bLine("    [AC:NAME]     name matches known AC patterns"))
    out(bLine("    [AC:CHILDREN] child objects contain AC patterns"))
    out(bLine("                  (works even if the script has a random name)"))
    out(bLine("    [AC:REMOTE]   Remote used for reporting/flagging"))
    out(bLine("    [AC:ISOLATED] single Remote with no neighboring Remotes"))
    out(bLine("    [AC:FOLDER]   protection system folder"))
    out(bLine("    [AC:VALUE]    violation/ban flag Value"))
    out(bEmpty())
    out(bBot())
    out("")
end

-- obj metadata
local function getMeta(obj)
    local parts = {}
    local cls = obj.ClassName
    if cls == "RemoteEvent"      then table.insert(parts, "RemoteEvent")      end
    if cls == "RemoteFunction"   then table.insert(parts, "RemoteFunction")   end
    if cls == "BindableEvent"    then table.insert(parts, "BindableEvent")    end
    if cls == "BindableFunction" then table.insert(parts, "BindableFunction") end
    if obj:IsA("Script") or obj:IsA("LocalScript") or obj:IsA("ModuleScript") then
        table.insert(parts, cls)
    end
    if obj:IsA("BasePart") then
        local p = obj.Position
        table.insert(parts, string.format("pos:%.0f,%.0f,%.0f", p.X, p.Y, p.Z))
    end
    if obj:IsA("IntValue") or obj:IsA("NumberValue")
    or obj:IsA("StringValue") or obj:IsA("BoolValue") then
        local ok, v = pcall(function() return obj.Value end)
        if ok then
            local vs = tostring(v)
            if #vs > 40 then vs = vs:sub(1,40).."…" end
            table.insert(parts, "= "..vs)
        end
    end
    if obj:IsA("Model") then
        local pp = obj.PrimaryPart
        table.insert(parts, "PP:"..(pp and pp.Name or "nil"))
    end
    if #parts == 0 then return "" end
    return "  ‹"..table.concat(parts, " | ").."›"
end

-- attributes
local function dumpAttributes(obj, attrPfx)
    local ok, attrs = pcall(function() return obj:GetAttributes() end)
    if not ok then return end
    local list = {}
    for k, v in pairs(attrs) do table.insert(list, {k, v, typeof(v)}) end
    if #list == 0 then return end
    table.sort(list, function(a,b) return a[1] < b[1] end)
    for _, t in ipairs(list) do
        local vs = tostring(t[2])
        if #vs > 60 then vs = vs:sub(1,60).."…" end
        out(attrPfx.."┊ @"..t[1].." = "..vs.."  ["..t[3].."]")
    end
end

-- recursive dump
local BORING_VALUES = {
    idle=true,walk=true,run=true,jump=true,climb=true,
    fall=true,sit=true,toolnone=true,Weight=true,
    ScaleDampeningPercent=true,AvatarPartScaleType=true,
    Animation1=true,Animation2=true,
}

local function dump(obj, depth, prefix, isLast, path, service)
    if depth > CFG.MAX_DEPTH then
        out(prefix.."└── ... [MAX DEPTH]")
        return
    end
    local connector = isLast and "└── " or "├── "
    local childPfx  = prefix..(isLast and "    " or "│   ")
    local attrPfx   = prefix..(isLast and "   "  or "│  ")
    local fullPath  = path.."/"..obj.Name
    local cls       = obj.ClassName

    out(prefix..connector.."["..cls.."] "..obj.Name..getMeta(obj))
    local lineIdx = #OUTPUT

    if CFG.SAMPLE_VALUES then
        local svcSet = {}
        for _, s in ipairs(CFG.SAMPLE_SERVICES) do svcSet[s] = true end
        if svcSet[service]
        and (cls=="IntValue" or cls=="NumberValue"
          or cls=="StringValue" or cls=="BoolValue")
        and not BORING_VALUES[obj.Name]
        and obj.Parent then
            table.insert(VALUE_TARGETS, {
                lineIdx=lineIdx, obj=obj,
                name=obj.Name, path=fullPath,
                service=service, samples={},
            })
        end
    end

    dumpAttributes(obj, attrPfx)
    table.insert(REGISTRY, {
        name=obj.Name, class=cls, path=fullPath,
        parent=path, service=service, depth=depth, obj=obj,
    })

    local ok, children = pcall(function() return obj:GetChildren() end)
    if not ok then return end
    for i, child in ipairs(children) do
        dump(child, depth+1, childPfx, i==#children, fullPath, service)
    end
end

-- value monitor
local function runValueMonitorInline()
    if not CFG.SAMPLE_VALUES or #VALUE_TARGETS == 0 then return end
    print(string.format("[DUMP] Monitoring %d Value objects (%dx%ds)...",
        #VALUE_TARGETS, CFG.SAMPLE_COUNT, CFG.SAMPLE_INTERVAL))

    for i = 1, CFG.SAMPLE_COUNT do
        for _, t in ipairs(VALUE_TARGETS) do
            if t.obj and t.obj.Parent then
                local ok, v = pcall(function() return t.obj.Value end)
                if ok then table.insert(t.samples, tostring(v)) end
            end
        end
        if i < CFG.SAMPLE_COUNT then
            print(string.format("[DUMP] Sample %d/%d...", i, CFG.SAMPLE_COUNT))
            task.wait(CFG.SAMPLE_INTERVAL)
        end
    end

    for _, t in ipairs(VALUE_TARGETS) do
        if #t.samples >= 2 then
            local seen2, unique = {}, {}
            for _, s in ipairs(t.samples) do
                if not seen2[s] then seen2[s]=true; table.insert(unique,s) end
            end
            local first, last = t.samples[1], t.samples[#t.samples]
            local tag = ""
            if #unique > 1 then
                local trend = "FLUCTUATING"
                local n1, n2 = tonumber(first), tonumber(last)
                if n1 and n2 then
                    if     n2 > n1 then trend = "RISING"
                    elseif n2 < n1 then trend = "FALLING"
                    end
                end
                tag = string.format("  [DYNAMIC: %s  %s→%s]", trend, first, last)
            else
                tag = "  [STATIC]"
            end
            if OUTPUT[t.lineIdx] then
                OUTPUT[t.lineIdx] = OUTPUT[t.lineIdx]..tag
            end
        end
    end
end

-- analysis utilities
local function isValueClass(cls)
    return cls=="IntValue" or cls=="NumberValue" or cls=="StringValue"
        or cls=="BoolValue" or cls=="ObjectValue"
        or cls=="Color3Value" or cls=="Vector3Value" or cls=="CFrameValue"
end

local function isRemoteClass(cls)
    return cls=="RemoteEvent" or cls=="RemoteFunction"
        or cls=="BindableEvent" or cls=="BindableFunction"
end

local PLAYER_NAMES_CACHE = nil
local function getPlayerNames()
    if PLAYER_NAMES_CACHE then return PLAYER_NAMES_CACHE end
    PLAYER_NAMES_CACHE = {}
    local ok, players = pcall(function()
        return game:GetService("Players"):GetPlayers()
    end)
    if ok then
        for _, p in ipairs(players) do PLAYER_NAMES_CACHE[p.Name] = true end
    end
    return PLAYER_NAMES_CACHE
end

local function isInPlayerChar(path, service)
    if service ~= "Workspace" then return false end
    local names = getPlayerNames()
    local root = path:match("^[^/]+/([^/]+)")
    return root ~= nil and names[root] == true
end

local function nameSimilarStrict(a, b)
    a = a:lower():gsub("[^%a%d]","")
    b = b:lower():gsub("[^%a%d]","")
    if #a < 4 or #b < 4 then return false end
    if a == b then return true end
    if a:find("^"..b) or b:find("^"..a) then return true end
    local common = 0
    for i = 1, math.min(#a,#b) do
        if a:sub(i,i) == b:sub(i,i) then
            common = common + 1
        else
            break
        end
    end
    return common >= 5
end

local function addItem(groupId, item)
    if VULN_GROUPS[groupId] then
        table.insert(VULN_GROUPS[groupId].items, item)
    end
end

--  anticheat detection

local AC_NAME_PATTERNS = {
    "anticheat","anti_cheat","acheat","hackdetect","exploitdetect",
    "cheatdetect","securitycheck","securitymanager","securityhandler",
    "speedcheck","flycheck","noclipcheck","teleportcheck",
    "walkspeedcheck","positioncheck","movementcheck",
    "validator","sanitizer","serverguard","watchdog",
    "integritycheck","trustcheck","playerguard",
    "kickhandler","banhandler","autoban","autokick",
    "moderationsystem","punishsystem","cheatprevention",
    "exploitprevention","antifly","antinoclip","antispeed",
    "antiteleport","antijump","exploitguard","hackguard",
}

-- child value names that indicate the parent is an AC script
-- even if the parent itself has a random/obfuscated name
local AC_CHILD_VALUE_PATTERNS = {
    "flagged","isflagged","violation","violations","strike","strikes",
    "isbanned","banned","iskicked","warned","warnings",
    "suspicious","issuspicious","cheatdetected","hackdetected",
    "exploitdetected","trustlevel","trustscore","reputation",
    "anticheatflag","securityflag","violationcount",
}

local AC_REMOTE_PATTERNS = {
    "report","flag","flagplayer","reportplayer","reportcheat",
    "reportexploit","flagcheat","flagexploit","detectcheat",
    "oncheatdetected","exploitdetected","hackdetected",
    "kickplayer","banplayer","punishplayer","warnplayer",
    "securityevent","cheatevent","violationevent",
    "anticheatfire","guardfire","shadowban",
}

local AC_VALUE_PATTERNS = {
    "ishacking","ischeating","flagged","violation","violations",
    "cheatdetected","exploitdetected","suspicious","banned",
    "kicked","warned","strike","trustlevel","trustscore",
    "reputation","securityflag","anticheatflag",
}

local AC_FOLDER_PATTERNS = {
    "anticheat","security","protection","guard","checks",
    "validators","detection","moderation","cheatprevention",
    "exploitprevention","antiexploit","securefolder",
}

local function matchesAny(name, patterns)
    local low = name:lower():gsub("[^%a%d_]","")
    for _, p in ipairs(patterns) do
        if low == p or low:find(p, 1, true) then return true, p end
    end
    return false, nil
end

local function checkAnticheat(rec, byParent)
    local name = rec.name
    local cls  = rec.class
    local path = rec.path
    local svc  = rec.service

    -- AC:NAME - name matches known AC patterns
    if cls=="Script" or cls=="LocalScript"
    or cls=="ModuleScript" or cls=="Folder" or cls=="Model" then
        local matched, pattern = matchesAny(name, AC_NAME_PATTERNS)
        if matched then
            local state = "n/a"
            if rec.obj and rec.obj.Parent and
            (cls=="Script" or cls=="LocalScript" or cls=="ModuleScript") then
                local ok, dis = pcall(function() return rec.obj.Disabled end)
                if ok then state = dis and "inactive" or "active" end
            end
            addItem("ANTICHEAT", {
                subtype = "AC:NAME",
                name=name, cls=cls, svc=svc, path=path,
                detail  = string.format(
                    "name matches pattern '%s'  |  state: %s",
                    pattern, state),
                status="POSSIBLE", note=""
            })
            return
        end
    end

    -- AC:CHILDREN - child values contain AC patterns
    if cls=="Script" or cls=="LocalScript" or cls=="ModuleScript" then
        local children = byParent[path] or {}
        local acChildren = {}
        for _, child in ipairs(children) do
            if isValueClass(child.class) then
                local matched2, pattern2 = matchesAny(child.name, AC_CHILD_VALUE_PATTERNS)
                if matched2 then
                    table.insert(acChildren, child.name.."("..pattern2..")")
                end
            end
        end
        if #acChildren > 0 then
            addItem("ANTICHEAT", {
                subtype = "AC:CHILDREN",
                name=name, cls=cls, svc=svc, path=path,
                detail  = string.format(
                    "script contains Values with AC patterns: %s",
                    table.concat(acChildren, ", ")),
                status="LIKELY",
                note="child objects indicate AC regardless of the script's name"
            })
            return
        end
    end

    -- AC:REMOTE - Remote used for reporting/flagging
    if cls=="RemoteEvent" or cls=="BindableEvent" or cls=="RemoteFunction" then
        local matched, pattern = matchesAny(name, AC_REMOTE_PATTERNS)
        if matched then
            addItem("ANTICHEAT", {
                subtype = "AC:REMOTE",
                name=name, cls=cls, svc=svc, path=path,
                detail  = string.format("report/flag Remote  |  pattern='%s'", pattern),
                status="POSSIBLE",
                note="this Remote is used to send a violation signal to the server"
            })
            return
        end
    end

    -- AC:ISOLATED - single RemoteEvent with no neighboring Remotes
    -- gameplay Remotes usually live in groups
    -- alone Remote often serves only as an internal ac signal
    if cls=="RemoteEvent" then
        local siblings = byParent[rec.parent] or {}
        local remoteCount = 0
        for _, sib in ipairs(siblings) do
            if isRemoteClass(sib.class) then
                remoteCount = remoteCount + 1
            end
        end
        if remoteCount == 1 and rec.depth >= 1 then
            addItem("ANTICHEAT", {
                subtype = "AC:ISOLATED",
                name=name, cls=cls, svc=svc, path=path,
                detail  = "only Remote in its folder with no neighbors",
                status="POSSIBLE",
                note="isolated Remotes are often used exclusively for internal AC signals"
            })
            return
        end
    end

    -- AC:VALUE - violation/ban flag value
    if isValueClass(cls) then
        local matched, pattern = matchesAny(name, AC_VALUE_PATTERNS)
        if matched then
            local ok, val = pcall(function() return rec.obj.Value end)
            addItem("ANTICHEAT", {
                subtype = "AC:VALUE",
                name=name, cls=cls, svc=svc, path=path,
                detail  = string.format(
                    "violation flag Value  |  pattern='%s'  |  current value: %s",
                    pattern, ok and tostring(val) or "?"),
                status="POSSIBLE",
                note="resetting or changing this flag may bypass a block"
            })
            return
        end
    end

    -- AC:FOLDER - AC system folder
    if cls=="Folder" or cls=="Model" then
        local matched, pattern = matchesAny(name, AC_FOLDER_PATTERNS)
        if matched then
            local children = byParent[path] or {}
            local scripts = 0
            for _, child in ipairs(children) do
                if child.class=="Script" or child.class=="LocalScript"
                or child.class=="ModuleScript" then
                    scripts = scripts + 1
                end
            end
            addItem("ANTICHEAT", {
                subtype = "AC:FOLDER",
                name=name, cls=cls, svc=svc, path=path,
                detail  = string.format(
                    "protection system folder  |  pattern='%s'  |  scripts inside: %d",
                    pattern, scripts),
                status="POSSIBLE",
                note="inspect the contents"
            })
            return
        end
    end
end

-- structural analysis
local function runStructuralAnalysis()
    local byParent = {}
    local stats = {re=0, rf=0, ls=0, ss=0, me=0, ac=0}

    for _, rec in ipairs(REGISTRY) do
        if not byParent[rec.parent] then byParent[rec.parent] = {} end
        table.insert(byParent[rec.parent], rec)
    end

    local seen = {}
    local function isNew(key)
        if seen[key] then return false end
        seen[key] = true
        return true
    end

    getPlayerNames()

    for _, rec in ipairs(REGISTRY) do
        local cls  = rec.class
        local svc  = rec.service
        local path = rec.path
        local name = rec.name
        local obj  = rec.obj
        local inChar = isInPlayerChar(path, svc)

        -- WRITABLE_VALUE
        if isValueClass(cls)
        and (svc=="Workspace" or svc=="ReplicatedStorage")
        and rec.depth <= 3
        and not inChar
        and obj and obj.Parent
        and isNew("WV|"..path) then
            addItem("WRITABLE_VALUE", {
                name=name, cls=cls, path=path, obj=obj,
                status="UNVERIFIED", note=""
            })
        end

        -- CALLABLE_RF
        if cls=="RemoteFunction" then
            stats.rf = stats.rf + 1
            if isNew("RF|"..path) then
                addItem("CALLABLE_RF", {
                    name=name, path=path, obj=obj,
                    status="UNVERIFIED", note=""
                })
            end
        end

        -- NAKED_REMOTE
        if isRemoteClass(cls)
        and rec.depth == 0
        and svc=="ReplicatedStorage"
        and isNew("NR|"..path) then
            addItem("NAKED_REMOTE", {
                name=name, cls=cls, path=path, obj=obj,
                status="LIKELY",
                note="direct child of ReplicatedStorage - no structure"
            })
        end

        -- READABLE_MODULE
        if cls=="ModuleScript"
        and svc=="ReplicatedStorage"
        and rec.depth <= 1
        and isNew("ME|"..path) then
            stats.me = stats.me + 1
            addItem("READABLE_MODULE", {
                name=name, path=path, obj=obj,
                status="UNVERIFIED", note=""
            })
        end

        -- ANTICHEAT
        if isNew("AC|"..path) then
            checkAnticheat(rec, byParent)
        end

        if cls=="RemoteEvent" then stats.re = stats.re + 1 end
        if cls=="Script"      then stats.ss = stats.ss + 1 end
        if cls=="LocalScript" then stats.ls = stats.ls + 1 end
    end

    -- API_SURFACE
    local checkedFolders = {}
    for parentPath, children in pairs(byParent) do
        if not checkedFolders[parentPath] then
            checkedFolders[parentPath] = true
            local inRS = parentPath:find("^ReplicatedStorage") ~= nil
            if inRS then
                local total, remotes = #children, 0
                local names = {}
                for _, rec in ipairs(children) do
                    if isRemoteClass(rec.class) then
                        remotes = remotes + 1
                        table.insert(names, "["..rec.class.."] "..rec.name)
                    end
                end
                if remotes >= 3 and total > 0 and remotes/total >= 0.7
                and isNew("AS|"..parentPath) then
                    local sample = table.concat(names, "\n     ")
                    addItem("API_SURFACE", {
                        path=parentPath, remotes=remotes, total=total,
                        sample=sample, status="LIKELY",
                        note="each Remote here is a separate entry point to the server"
                    })
                end
            end
        end
    end

    -- REMOTE_VALUE_PAIR
    local pairDone = {}
    for parentPath, children in pairs(byParent) do
        local inRS = parentPath:find("^ReplicatedStorage") ~= nil
        if inRS then
            local remotes, values = {}, {}
            for _, rec in ipairs(children) do
                if rec.class=="RemoteEvent" or rec.class=="RemoteFunction" then
                    table.insert(remotes, rec)
                end
                if isValueClass(rec.class) then
                    table.insert(values, rec)
                end
            end
            for _, rem in ipairs(remotes) do
                for _, val in ipairs(values) do
                    local key = rem.path.."|"..val.path
                    if not pairDone[key] and nameSimilarStrict(rem.name, val.name) then
                        pairDone[key] = true
                        addItem("REMOTE_VALUE_PAIR", {
                            path=parentPath,
                            remCls=rem.class, remName=rem.name, remObj=rem.obj,
                            valCls=val.class, valName=val.name, valObj=val.obj,
                            status="LIKELY",
                            note="names match - Remote likely sets Value directly"
                        })
                    end
                end
            end
        end
    end

    -- SURFACE_SUMMARY
    local ratio = stats.ss > 0
        and string.format("%.1f:1", stats.ls/stats.ss) or "inf"
    local risk = "low"
    if stats.re + stats.rf > 30 then risk = "medium" end
    if stats.re + stats.rf > 80 then risk = "high"   end
    if stats.me > 50            then risk = "high"   end

    local acByType = {NAME=0, CHILDREN=0, REMOTE=0, ISOLATED=0, VALUE=0, FOLDER=0}
    for _, item in ipairs(VULN_GROUPS["ANTICHEAT"].items) do
        local t = item.subtype:gsub("AC:","")
        if acByType[t] then acByType[t] = acByType[t] + 1 end
    end

    addItem("SURFACE_SUMMARY", {
        path = "—",
        text = string.format(
            "  RemoteEvent:              %d\n"..
            "  RemoteFunction:           %d\n"..
            "  ModuleScript (readable):  %d\n"..
            "  LocalScript:              %d\n"..
            "  Script (serverside):     %d\n"..
            "  LS/SS ratio:              %s\n"..
            "  Risk level:               %s\n"..
            "\n"..
            "  Anticheat:\n"..
            "    AC:NAME      %d  - by script/folder name\n"..
            "    AC:CHILDREN  %d  - by child Values (obfuscation)\n"..
            "    AC:REMOTE    %d  - report/flag Remote\n"..
            "    AC:ISOLATED  %d  - isolated Remote\n"..
            "    AC:VALUE     %d  - violation flag Value\n"..
            "    AC:FOLDER    %d  - protection system folder",
            stats.re, stats.rf, stats.me, stats.ls, stats.ss, ratio, risk,
            acByType.NAME, acByType.CHILDREN, acByType.REMOTE,
            acByType.ISOLATED, acByType.VALUE, acByType.FOLDER),
        status="POSSIBLE", note="informational statistics"
    })
end

--  verification
local function invokeRF(rf, timeout)
    local done, callOk, result = false, false, nil
    task.spawn(function()
        callOk, result = pcall(function() return rf:InvokeServer() end)
        done = true
    end)
    local t = 0
    while not done and t < timeout do task.wait(0.1); t = t + 0.1 end
    if not done then return "TIMEOUT", nil end
    return callOk and "OK" or "ERROR", tostring(result or ""):sub(1,100)
end

local function runVerification()
    local total = 0
    for _, g in pairs(VULN_GROUPS) do total = total + #g.items end
    print(string.format("[DUMP] Verifying %d objects...", total))

    local done  = 0
    local rfCnt = 0

    for _, id in ipairs(VULN_ORDER) do
        local g = VULN_GROUPS[id]
        if g then
            for _, item in ipairs(g.items) do

                if id == "WRITABLE_VALUE" then
                    local obj = item.obj
                    if obj and obj.Parent then
                        local ok, original = pcall(function() return obj.Value end)
                        if not ok then
                            item.status = "FALSE+"
                            item.note   = "could not read value"
                        else
                            local testVal
                            local n = tonumber(original)
                            if n then
                                testVal = n + 99999
                            elseif typeof(original) == "boolean" then
                                testVal = not original
                            else
                                testVal = tostring(original).."_TEST"
                            end

                            local writeOk = pcall(function() obj.Value = testVal end)
                            if not writeOk then
                                item.status = "FALSE+"
                                item.note   = "write blocked"
                            else
                                task.wait(2)
                                local _, afterWait = pcall(function() return obj.Value end)
                                local afterStr  = tostring(afterWait)
                                local testStr   = tostring(testVal)
                                local originStr = tostring(original)

                                pcall(function() obj.Value = original end)

                                if afterStr == testStr then
                                    item.status = "CRITICAL"
                                    item.note   = string.format(
                                        "server did not reset value after 2s (%s→%s) - likely trusts client",
                                        originStr, testStr)
                                elseif afterStr == originStr then
                                    item.status = "FALSE+"
                                    item.note   = string.format(
                                        "server restored original (%s→%s→%s) - serverside value",
                                        originStr, testStr, originStr)
                                else
                                    item.status = "LIKELY"
                                    item.note   = string.format(
                                        "server set a third value (%s→%s→%s) - reacts to change",
                                        originStr, testStr, afterStr)
                                end
                            end
                        end
                    else
                        item.status = "FALSE+"
                        item.note   = "object unavailable"
                    end

                elseif id == "CALLABLE_RF" then
                    local obj = item.obj
                    if obj and obj.Parent then
                        if rfCnt >= CFG.VERIFY_RF_MAX then
                            item.status = "LIKELY"
                            item.note   = "RF limit ("..CFG.VERIFY_RF_MAX..") reached"
                        elseif CFG.VERIFY_RF then
                            rfCnt = rfCnt + 1
                            local state, res = invokeRF(obj, CFG.RF_TIMEOUT)
                            if state == "OK" then
                                item.status = "CRITICAL"
                                item.note   = "returned: "..tostring(res)
                            elseif state == "ERROR" then
                                if res:find("attempt") or res:find("expected")
                                or res:find("bad arg") or res:find("nil value") then
                                    item.status = "CRITICAL"
                                    item.note   = "handler exists, argument error: "..res
                                elseif res:find("unauthori") or res:find("denied")
                                or res:find("not allow") or res:find("forbidden") then
                                    item.status = "FALSE+"
                                    item.note   = "explicitly rejected: "..res
                                else
                                    item.status = "LIKELY"
                                    item.note   = "responded with error: "..res
                                end
                            else
                                item.status = "FALSE+"
                                item.note   = "no response within "..CFG.RF_TIMEOUT.."s"
                            end
                        else
                            item.status = "LIKELY"
                            item.note   = "VERIFY_RF disabled"
                        end
                    else
                        item.status = "FALSE+"
                        item.note   = "object unavailable"
                    end

                elseif id == "READABLE_MODULE" then
                    local obj = item.obj
                    if obj and obj.Parent then
                        local done2, callOk2, result2 = false, false, nil
                        task.spawn(function()
                            callOk2, result2 = pcall(require, obj)
                            done2 = true
                        end)
                        local t2 = 0
                        while not done2 and t2 < 2 do
                            task.wait(0.1); t2 = t2 + 0.1
                        end
                        if not done2 then
                            item.status = "FALSE+"
                            item.note   = "require() hung"
                        elseif callOk2 then
                            item.status = "CRITICAL"
                            item.note   = "require() succeeded, type: "..typeof(result2)
                        else
                            local err = tostring(result2 or ""):sub(1,80)
                            if err:find("cannot be required") or err:find("protected") then
                                item.status = "FALSE+"
                                item.note   = "protected: "..err
                            else
                                item.status = "LIKELY"
                                item.note   = "loaded with error: "..err
                            end
                        end
                    else
                        item.status = "FALSE+"
                        item.note   = "object unavailable"
                    end

                elseif id == "REMOTE_VALUE_PAIR" then
                    if CFG.VERIFY_RV_PAIR then
                        local remObj = item.remObj
                        local valObj = item.valObj
                        if remObj and remObj.Parent and valObj and valObj.Parent then
                            local _, before = pcall(function() return valObj.Value end)
                            pcall(function()
                                if remObj.ClassName == "RemoteEvent" then
                                    remObj:FireServer()
                                else
                                    task.spawn(function()
                                        pcall(function() remObj:InvokeServer() end)
                                    end)
                                end
                            end)
                            task.wait(1.0)
                            local _, after = pcall(function() return valObj.Value end)
                            if tostring(after) ~= tostring(before) then
                                item.status = "CRITICAL"
                                item.note   = string.format("value changed: %s → %s",
                                    tostring(before):sub(1,30), tostring(after):sub(1,30))
                            else
                                item.status = "LIKELY"
                                item.note   = "value did not change"
                            end
                        else
                            item.status = "LIKELY"
                            item.note   = "objects unavailable"
                        end
                    end
                end

                done = done + 1
                if done % 10 == 0 then
                    print(string.format("[DUMP] Verified %d/%d...", done, total))
                end
            end
        end
    end
end

-- findings output
local function statusTag(status)
    if status == "CRITICAL" then return "[P1] CRITICAL"
    elseif status == "LIKELY" then return "[P2] LIKELY  "
    elseif status == "FALSE+" then return "[--] FALSE+  "
    else                           return "[P3] POSSIBLE"
    end
end

local function writeVulns()
    local sc = {CRITICAL=0, LIKELY=0, POSSIBLE=0, ["FALSE+"]=0}
    local total = 0
    for _, g in pairs(VULN_GROUPS) do
        for _, item in ipairs(g.items) do
            total = total + 1
            if sc[item.status] then sc[item.status] = sc[item.status] + 1 end
        end
    end

    out("")
    out(bTop())
    out(bLine("STRUCTURAL ANALYSIS"))
    out(bLine(string.format(
        "P1(CRITICAL)=%d  P2(LIKELY)=%d  P3(POSSIBLE)=%d  FALSE+=%d  Total=%d",
        sc.CRITICAL, sc.LIKELY, sc.POSSIBLE, sc["FALSE+"], total)))
    out(bBot())
    out("")

    out("  !! WARNING !!")
    out("")
    out("  This script uses structural and behavioral analysis to identify")
    out("  potential vulns and weak spots in the game.")
    out("  Results are based on patterns and automated tests - this is not a")
    out("  guarantee that a finding is exploitable or will produce the desired result.")
    out("  It is recommended to manually verify each finding if needed.")
    out("")
    out("  [P1] CRITICAL means the automated test passed, but does not guarantee")
    out("  the intended effect in the context of this specific game")
    out("  [P3] POSSIBLE findings should be prioritized for manual review")
    out("")
    out(string.rep("-", 72))
    out("")

    for _, id in ipairs(VULN_ORDER) do
        local g = VULN_GROUPS[id]
        if g then
            local real, fp = {}, {}
            for _, item in ipairs(g.items) do
                if item.status == "FALSE+" then
                    table.insert(fp, item)
                else
                    table.insert(real, item)
                end
            end

            out("── "..g.label
                .."  ("..#real.." findings"
                ..(#fp > 0 and " / "..#fp.." FALSE+" or "")..")")

            if #real == 0 then
                out("   (none found or all FALSE+)")
            else
                local useDetail = g.detail or (#real <= g.threshold)

                if useDetail then
                    for _, item in ipairs(real) do
                        out("")
                        if id == "API_SURFACE" then
                            out("   "..statusTag(item.status).."  "..item.path)
                            out(string.format("   Remotes: %d of %d (%.0f%%)",
                                item.remotes, item.total,
                                item.remotes/item.total*100))
                            out("   List:")
                            for line in (item.sample.."\n"):gmatch("([^\n]*)\n") do
                                if line ~= "" then out("     "..line) end
                            end
                        elseif id == "REMOTE_VALUE_PAIR" then
                            out("   "..statusTag(item.status).."  "..item.path)
                            out("   Remote: ["..item.remCls.."] "..item.remName)
                            out("   Value:  ["..item.valCls.."] "..item.valName)
                        elseif id == "SURFACE_SUMMARY" then
                            out("   "..statusTag(item.status))
                            out(item.text)
                        elseif id == "ANTICHEAT" then
                            out("   "..statusTag(item.status)
                                .."  ["..item.subtype.."]  "
                                ..item.name.."  ["..item.cls.."]"
                                .."  svc="..item.svc)
                            out("   "..item.detail)
                            out("   └─ "..item.path)
                        else
                            out("   "..statusTag(item.status)
                                .."  "..(item.name or ""))
                            out("   └─ "..item.path)
                        end
                        if item.note and item.note ~= "" then
                            out("   test: "..item.note)
                        end
                    end
                else
                    local order = {CRITICAL=1, LIKELY=2, POSSIBLE=3}
                    table.sort(real, function(a,b)
                        return (order[a.status] or 9) < (order[b.status] or 9)
                    end)
                    out("")
                    for _, item in ipairs(real) do
                        local tag = item.status=="CRITICAL" and "[P1]"
                                 or item.status=="LIKELY"   and "[P2]" or "[P3]"
                        out(string.format("   %s  %-35s  %s",
                            tag, item.name or "", item.path))
                        if item.note and item.note ~= "" then
                            out("         test: "..item.note)
                        end
                    end
                end

                if #fp > 0 then
                    out("")
                    out("   -- FALSE+ ("..#fp.." items):")
                    for _, item in ipairs(fp) do
                        out("   [--]  "..(item.name or "?").."  →  "..item.path)
                    end
                end
            end

            out("")
        end
    end
end

-- main
writeLegend()

out(bTop())
out(bLine(string.format("GAME DUMP |  PlaceId: %s  |  GameId: %s",
    tostring(game.PlaceId), tostring(game.GameId))))
out(bLine("Name: "..tostring(game.Name):sub(1,66)))
out(bBot())
out("")

for _, svcName in ipairs(SERVICES) do
    local ok, svc = pcall(function() return game:GetService(svcName) end)
    out("┌────────────────────────────────────────────────────────")
    out("│  SERVICE: "..svcName)
    out("└────────────────────────────────────────────────────────")
    if ok and svc then
        local ok2, children = pcall(function() return svc:GetChildren() end)
        if ok2 then
            for i, child in ipairs(children) do
                dump(child, 0, "", i==#children, svcName, svcName)
            end
        end
    else
        out("  [UNAVAILABLE]")
    end
    out("")
end

print("[DUMP] Monitoring values...")
runValueMonitorInline()

print("[DUMP] Structural analysis...")
runStructuralAnalysis()

print("[DUMP] Verifying findings...")
runVerification()

writeVulns()

out("")
out(string.format("Total lines: %d  |  Objects: %d", #OUTPUT, #REGISTRY))

-- save
local content = "\239\187\191"..table.concat(OUTPUT, "\n")
local saved = false
if writefile then
    local fname = "dump_"..tostring(game.PlaceId)..".txt"
    pcall(function()
        writefile(fname, content)
        saved = true
        print("[DUMP] Saved → "..fname)
    end)
end
if not saved then
    if setclipboard then
        setclipboard(content)
        print("[DUMP] Copied to clipboard")
    else
        for i = 1, #content, 3000 do print(content:sub(i, i+2999)) end
    end
end
print(string.format("[DUMP] Done! Lines: %d | Objects: %d", #OUTPUT, #REGISTRY))

Features & Information

its a simple script that saves the games full structure to a txt file and looks for possible vulnerabilities using a special algorithm. thats it. i think its useful if u an ai scripter

Community Comments (17)

zosynzosynApr 22, 2026

there are signs of AI

Replying to @zosyn
SakuraguysSakuraguysSep 15, 2026

@realheckersbrother dork

SpyDotSpyDotJul 17, 2026

Looks good. "There are signs of AI👶". Idc if it's AI. It does what it should. Idgaf if it's AI or not. He probably worked long to achieve this, so don't talk *. Good work, I tried it myself and failed. Also, thanks for making it open source. Nowadays, people are having a stick up their * because "someone could steal it". Have fun, skids, with my skid *. Hope you get some nut faces to buy that. This message is not hate speech or har*ment: no protected-group attacks, no threats, and my swearing is allowed. My "skids" and "nut faces" comments are general venting, not targeting any specific user. 🥀

Replying to @SpyDot
Dirt66Dirt66Jul 18, 2026

@SpyDot can you tell me how to get the game

Replying to @Dirt66
SpyDotSpyDotJul 18, 2026

@Dirt66 Its simple enough. 1) Install a high UNC executor (e.g., Pot*ssium). 2) Paste the script, join any game, wait for full load, then execute. 3) Check the executor's workspace folder (e.g., `%localappdata%\YourExec\workspace`) for `dump_(...).txt`. Done.

dotggdotggJul 19, 2026

nice

FunnyGuyReaperFunnyGuyReaperJul 27, 2026

how does this works

Replying to @FunnyGuyReaper
GBernGBernAug 2, 2026

@FunnyGuyReaper 1) Install a high UNC executor (e.g., Pot*ssium). 2) Paste the script, join any game, wait for full load, then execute. 3) Check the executor's workspace folder (e.g., `%localappdata%\YourExec\workspace`) for `dump_(...).txt`. Done. (from SpyDot)

VelxzzVelxzzAug 22, 2026

What is this script made for?

justflaxojustflaxoAug 31, 2026

the game i used it in banned me for "exploiting remote events"

Replying to @justflaxo
GBernGBernSep 1, 2026

@batman4u what game

IrddenIrddenSep 15, 2026

Mfs be calling this guy a skid and a ai user but in a few years they will use Ai too😭

Replying to @Irdden
noicnoicSep 15, 2026

@Irdden true but its literally just dex

LunadevLunadevSep 28, 2026

very good, thanks <3

SuperLossSuperLossSep 28, 2026

nice, i needed that

LitiumLitiumOct 8, 2026

still working really good!

ytkoxytkoxOct 8, 2026

я тебя крякну

More Scripts for Universal Scripts