Created
September 25, 2016 20:45
-
-
Save Anaminus/f4f7caba01d749eb8fd855ee64861f5e to your computer and use it in GitHub Desktop.
Bruteforce Roblox members.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| -- Brute.lua -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
| --[[ | |
| # Instructions | |
| - Create Script in game.ServerStorage, named "Words". | |
| - Fill it with any words that may be a potential instance or member name (one | |
| word per line). | |
| - Exclude words with 3 or less characters (these are generated automatically). | |
| - Run this script via Execute Script. | |
| - To stop, set `_G.stopped = true`. | |
| - Delete game.ServerStorage.State if you need to restart from the beginning. | |
| # Word Filtering | |
| Use something that can extract strings from binary files. Get strings from | |
| `RobloxPlayerBeta.exe` or `RobloxStudioBeta.exe`. | |
| - Include basic words, underscore, and spaces: | |
| ^[0-9A-Za-z_ ]+$ | |
| - Exclude long words: | |
| ^.{64,}$ | |
| - Exclude leading and trailing spaces: | |
| ^ +.*$ | |
| ^.* +$ | |
| - Exclude numbers and leading numbers: | |
| ^/d+$ | |
| ^\d.*$ | |
| - Exclude runs of 3 or more of the same character: | |
| ^.*(.)\1{2,}.*$ | |
| - Include some literal words with stupid characters: | |
| <<<ROOT>>> | |
| Auto-Save Path | |
| Auto-Save Enabled | |
| Auto-Save Interval (Minutes) | |
| Select/Hover Color | |
| Built-in Function Color | |
| # Searching | |
| Brute.lua searches for instances, and members of instances, and members of | |
| types. | |
| When a member of a type is userdata, the value is bruteforced for members, to | |
| hint at the member's actual type. | |
| ]] | |
| -- How to generate types. | |
| local types = { | |
| Axes = Axes.new; | |
| BrickColor = BrickColor.new; | |
| CFrame = CFrame.new; | |
| Color3 = Color3.new; | |
| Faces = Faces.new; | |
| Ray = Ray.new; | |
| Region3 = Region3.new; | |
| Region3int16 = Region3int16.new; | |
| UDim = UDim.new; | |
| UDim2 = UDim2.new; | |
| Vector2 = Vector2.new; | |
| Vector3 = Vector3.new; | |
| Vector3int16 = Vector3int16.new; | |
| Vector2int16 = Vector2int16.new; | |
| CellId = CellId.new; | |
| EnumItem = function() return Enum.NormalId.Front end; | |
| Enum = function() return Enum.NormalId end; | |
| EnumContainer = function() return Enum end; | |
| RBXScriptSignal = function() return game.Changed end; | |
| RBXScriptConnection = function() return game.Changed:connect(function()end) end; | |
| -- RbxLibrary = function() return LoadLibrary("RbxGui") end; | |
| ColorSequence = function() return ColorSequence.new(Color3.new()) end; | |
| ColorSequenceKeypoint = function() return ColorSequenceKeypoint.new(0,Color3.new()) end; | |
| NumberRange = function() return NumberRange.new(0) end; | |
| NumberSequence = function() return NumberSequence.new(0,0) end; | |
| NumberSequenceKeypoint = function() return NumberSequenceKeypoint.new(0,0) end; | |
| Rect2D = function() return Rect.new() end; | |
| PhysicalProperties = function() return PhysicalProperties.new(0,0,0,0,0) end; | |
| } | |
| -- How to generate specific classes. | |
| local instgen = { | |
| GlobalSettings = settings; | |
| UserSettings = UserSettings; | |
| DebuggerManager = DebuggerManager; | |
| ScriptDebugger = function() return DebuggerManager():AddDebugger(Instance.new("Script")) end; | |
| DebuggerWatch = function() return DebuggerManager():AddDebugger(Instance.new("Script")):AddWatch("") end; | |
| DebuggerBreakpoint = function() return DebuggerManager():AddDebugger(Instance.new("Script")):SetBreakpoint(1) end; | |
| PluginManager = PluginManager; | |
| Plugin = function() PluginManager():CreatePlugin() end; | |
| Toolbar = function() PluginManager():CreatePlugin():CreateToolbar() end; | |
| Button = function() PluginManager():CreatePlugin():CreateToolbar(""):CreateButton("","","") end; | |
| DataModel = function() return game end; | |
| Player = function() local p = game.Players:GetPlayers() if #p == 0 then return game.Players:CreateLocalPlayer(-1) else return p[1] end end; | |
| } | |
| -------------------------------- | |
| -------------------------------- | |
| -------------------------------- | |
| -------------------------------- | |
| local print = print | |
| if game.ServerStorage:FindFirstChild("Words") == nil then | |
| error("requires game.ServerStorage.Words (Script)",0) | |
| end | |
| -- GUI | |
| local className, | |
| classLabel, | |
| classProg, | |
| memberProg, | |
| superCount, | |
| lastSuper, | |
| memberCount, | |
| lastMember, | |
| unstableCount, | |
| lastUnstable, | |
| stopButton | |
| local screen do | |
| local lsize = 120 | |
| local fsize = 200 | |
| local sfsize = 40 | |
| local lines = 6 | |
| screen = Instance.new("ScreenGui") | |
| local frame = Instance.new("Frame") | |
| frame.Size = UDim2.new(1,0,1,0) | |
| local cont = Instance.new("Frame") | |
| cont.Size = UDim2.new(1,0,1/lines,0) | |
| cont.BackgroundTransparency = 1 | |
| local label = Instance.new("TextLabel") | |
| label.Name = "Label" | |
| label.Size = UDim2.new(1,0,1,0) | |
| label.BackgroundTransparency = 1 | |
| label.Font = "SourceSans" | |
| label.FontSize = "Size18" | |
| local field = Instance.new("TextLabel") | |
| field.Name = "Field" | |
| field.Text = "" | |
| field.Size = UDim2.new(1,0,1,0) | |
| field.Font = "SourceSans" | |
| field.FontSize = "Size18" | |
| local button = Instance.new("TextButton") | |
| button.Name = "Button" | |
| button.Text = "Button" | |
| button.Size = UDim2.new(1,0,1,0) | |
| button.Font = "SourceSans" | |
| button.FontSize = "Size18" | |
| local progress = frame:Clone() | |
| progress.Name = "Progress" | |
| do | |
| local f = frame:Clone() | |
| f.Name = "Bar" | |
| f.BackgroundColor3 = Color3.new(0,1,1) | |
| f.BorderSizePixel = 0 | |
| f.Parent = progress | |
| local l = label:Clone() | |
| l.Text = "" | |
| l.BackgroundTransparency = 1 | |
| l.Parent = progress | |
| end | |
| local top = frame:Clone() | |
| top.Size = UDim2.new(0,600,0,200) | |
| top.Position = UDim2.new(0.5,-300,0.5,-100) | |
| top.Parent = screen | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,0/lines,0) | |
| line.Parent = top | |
| classLabel = label:Clone() | |
| classLabel.Size = UDim2.new(0,lsize,1,0) | |
| classLabel.Position = UDim2.new(0,0,0,0) | |
| classLabel.Text = "Class" | |
| classLabel.Parent = line | |
| className = field:Clone() | |
| className.Size = UDim2.new(0,fsize,1,0) | |
| className.Position = UDim2.new(0,lsize,0,0) | |
| className.Parent = line | |
| classProg = progress:Clone() | |
| classProg.Size = UDim2.new(1,-fsize-lsize,1,0) | |
| classProg.Position = UDim2.new(0,fsize+lsize,0,0) | |
| classProg.Parent = line | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,1/lines,0) | |
| line.Parent = top | |
| local memberLabel = label:Clone() | |
| memberLabel.Size = UDim2.new(0,lsize,1,0) | |
| memberLabel.Position = UDim2.new(0,0,0,0) | |
| memberLabel.Text = "Members" | |
| memberLabel.Parent = line | |
| memberProg = progress:Clone() | |
| memberProg.Size = UDim2.new(1,-lsize,1,0) | |
| memberProg.Position = UDim2.new(0,lsize,0,0) | |
| memberProg.Parent = line | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,2/lines,0) | |
| line.Parent = top | |
| local superCountLabel = label:Clone() | |
| superCountLabel.Size = UDim2.new(0,lsize,1,0) | |
| superCountLabel.Position = UDim2.new(0,0,0,0) | |
| superCountLabel.Text = "Superclass Count" | |
| superCountLabel.Parent = line | |
| superCount = field:Clone() | |
| superCount.Size = UDim2.new(0,sfsize,1,0) | |
| superCount.Position = UDim2.new(0,lsize,0,0) | |
| superCount.Parent = line | |
| lastSuper = field:Clone() | |
| lastSuper.Size = UDim2.new(0,fsize,1,0) | |
| lastSuper.Position = UDim2.new(0,sfsize+lsize,0,0) | |
| lastSuper.Parent = line | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,3/lines,0) | |
| line.Parent = top | |
| local memberCountLabel = label:Clone() | |
| memberCountLabel.Size = UDim2.new(0,lsize,1,0) | |
| memberCountLabel.Position = UDim2.new(0,0,0,0) | |
| memberCountLabel.Text = "Member Count" | |
| memberCountLabel.Parent = line | |
| memberCount = field:Clone() | |
| memberCount.Size = UDim2.new(0,sfsize,1,0) | |
| memberCount.Position = UDim2.new(0,lsize,0,0) | |
| memberCount.Parent = line | |
| lastMember = field:Clone() | |
| lastMember.Size = UDim2.new(0,fsize,1,0) | |
| lastMember.Position = UDim2.new(0,sfsize+lsize,0,0) | |
| lastMember.Parent = line | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,4/lines,0) | |
| line.Parent = top | |
| local unstableCountLabel = label:Clone() | |
| unstableCountLabel.Size = UDim2.new(0,lsize,1,0) | |
| unstableCountLabel.Position = UDim2.new(0,0,0,0) | |
| unstableCountLabel.Text = "Unstable Count" | |
| unstableCountLabel.Parent = line | |
| unstableCount = field:Clone() | |
| unstableCount.Size = UDim2.new(0,sfsize,1,0) | |
| unstableCount.Position = UDim2.new(0,lsize,0,0) | |
| unstableCount.Parent = line | |
| lastUnstable = field:Clone() | |
| lastUnstable.Size = UDim2.new(0,fsize,1,0) | |
| lastUnstable.Position = UDim2.new(0,sfsize+lsize,0,0) | |
| lastUnstable.Parent = line | |
| ---- | |
| local line = cont:Clone() | |
| line.Position = UDim2.new(0,0,5/lines,0) | |
| line.Parent = top | |
| stopButton = button:Clone() | |
| button.Text = "Stop" | |
| button.Parent = line | |
| end | |
| screen.Name = "Brute" | |
| do local s = game.CoreGui:FindFirstChild(screen.Name) | |
| if s then s:Destroy() end end | |
| screen.Parent = game.CoreGui | |
| for i,v in pairs(settings():GetChildren()) do | |
| instgen[v.ClassName] = function() return v end | |
| end | |
| for i,v in pairs(UserSettings():GetChildren()) do | |
| instgen[v.ClassName] = function() return v end | |
| end | |
| -- Build list of words. | |
| local Words do | |
| Words = {} | |
| local sc = game.ServerStorage.Words.Source | |
| local i = 0 | |
| for line in sc:gmatch('[^\r\n]+') do | |
| i = i + 1 | |
| Words[i] = line | |
| end | |
| end | |
| -- Include words with 3 or less letters. | |
| do | |
| local cs = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_' | |
| local chars = {} | |
| for i = 1,#cs do chars[i] = cs:sub(i,i) end | |
| for a = 1,#chars do | |
| local A = chars[a] | |
| if not A:match('^%d$') then | |
| Words[#Words+1] = A | |
| for b = 1,#chars do | |
| local B = chars[b] | |
| Words[#Words+1] = A .. B | |
| for c = 1,#chars do | |
| Words[#Words+1] = A .. B .. chars[c] | |
| end | |
| end | |
| end | |
| end | |
| end | |
| table.sort(Words) | |
| -- Attempt to load state of previous run. | |
| local State do | |
| local state = game.ServerStorage:FindFirstChild("State") | |
| if state == nil then | |
| state = Instance.new("StringValue") | |
| state.Name = "State" | |
| state.Parent = game.ServerStorage | |
| state.Value = "1;1;1" | |
| end | |
| local t,c,m = state.Value:match("^(%d+);(%d+);(%d+)$") | |
| State = { | |
| Type = tonumber(t) or 1, | |
| Class = tonumber(c) or 1, | |
| Member = tonumber(m) or 1, | |
| update = function() | |
| state.Value = State.Type .. ";" .. State.Class .. ";" .. State.Member | |
| end, | |
| } | |
| end | |
| -- Setup Output script (hook into print). | |
| do | |
| local output = game.ServerStorage:FindFirstChild("Output") | |
| if output == nil then | |
| output = Instance.new("Script") | |
| output.Name = "Output" | |
| output.Parent = game.ServerStorage | |
| end | |
| if State.Type == 1 and State.Class == 1 and State.Member == 1 then | |
| output.Source = "" | |
| end | |
| local pr = print | |
| function print(...) | |
| local s = "" | |
| for i = 1,select("#",...) do | |
| if i > 1 then s = s .. " " end | |
| s = tostring(select(i,...)) | |
| end | |
| output.Source = output.Source .. s .. "\n" | |
| pr(...) | |
| end | |
| end | |
| local function get(t,k) return type(t[k]) end | |
| local function isa(t,k) return t:IsA(k) end | |
| _G.stopped = false | |
| -- This doesn't work for some reason. | |
| stopButton.MouseButton1Down:connect(function() _G.stopped = true end) | |
| -- Function to pause and update GUI. | |
| local t=tick() | |
| local function count(d,over) | |
| if _G.stopped then error("STOPPED",0) end | |
| if over or tick()-t > 0.5 then | |
| className.Text = d.className | |
| classProg.Label.Text = string.format(unpack(d.classProgText)) | |
| classProg.Bar.Size = UDim2.new(d.classProgBar,0,1,0) | |
| memberProg.Label.Text = string.format(unpack(d.memberProgText)) | |
| memberProg.Bar.Size = UDim2.new(d.memberProgBar,0,1,0) | |
| superCount.Text = d.superCount | |
| lastSuper.Text = d.lastSuper | |
| memberCount.Text = d.memberCount | |
| lastMember.Text = d.lastMember | |
| unstableCount.Text = d.unstableCount | |
| lastUnstable.Text = d.lastUnstable | |
| State.update() | |
| wait() | |
| t=tick() | |
| end | |
| end | |
| local Data = { | |
| classProgText = {}, | |
| memberProgText = {}, | |
| } | |
| -- Bruteforce instances and members. | |
| if State.Type <= 1 then | |
| State.Type = 1 | |
| print("---- INSTANCES:") | |
| for q = State.Class,#Words do | |
| State.Class = q | |
| local name = Words[q] | |
| local method | |
| local data | |
| if not data then | |
| local ok,d = pcall(game.GetService,game,name) | |
| if ok then data = d method = 'from GetService' end | |
| end | |
| if not data then | |
| local ok,d = pcall(Instance.new,name) | |
| if ok then data = d method = 'from Instance.new' end | |
| end | |
| if not data and instgen[name] then | |
| local ok,d = pcall(instgen[name]) | |
| if ok then data = d method = 'generated' end | |
| end | |
| Data.className = name | |
| Data.classProgText[1] = "%d/%d (%d%%)" | |
| Data.classProgText[2] = q | |
| Data.classProgText[3] = #Words | |
| Data.classProgText[4] = q/#Words*100 | |
| Data.classProgBar = q/#Words | |
| Data.memberProgBar = 0 | |
| Data.memberProgText[1] = "" | |
| Data.memberProgText[2] = nil | |
| Data.memberProgText[3] = nil | |
| Data.memberProgText[4] = nil | |
| Data.superCount = "0" | |
| Data.lastSuper = "" | |
| Data.memberCount = "0" | |
| Data.lastMember = "" | |
| Data.unstableCount = "0" | |
| Data.lastUnstable = "" | |
| if data then | |
| print(string.format("%s (%s)",name,method)) | |
| count(Data,true) | |
| local nsup = 0 | |
| local nuns = 0 | |
| local nmem = 0 | |
| for i = 1,#Words do | |
| Data.memberProgText[1] = "%d/%d (%d%%)" | |
| Data.memberProgText[2] = i | |
| Data.memberProgText[3] = #Words | |
| Data.memberProgText[4] = i/#Words*100 | |
| Data.memberProgBar = i/#Words | |
| local s,sup = pcall(isa,data,Words[i]) | |
| if s and sup then | |
| print(string.format("\tIsA: %s",Words[i])) | |
| nsup = nsup+1 | |
| Data.superCount = nsup | |
| Data.lastSuper = Words[i] | |
| count(Data,true) | |
| end | |
| local s,ty = pcall(get,data,Words[i]) | |
| if not s and not ty:match('is not a valid member of') then | |
| print(string.format("\tUnstable: %s",Words[i])) | |
| nmem = nmem+1 | |
| Data.memberCount = nmem | |
| Data.lastMember = Words[i] | |
| nuns = nuns+1 | |
| Data.unstableCount = nuns | |
| Data.lastUnstable = Words[i] | |
| count(Data,true) | |
| elseif s and ty then | |
| print(string.format("\tMember: %s (%s)",Words[i],ty)) | |
| nmem = nmem+1 | |
| Data.memberCount = nmem | |
| Data.lastMember = Words[i] | |
| count(Data,true) | |
| end | |
| count(Data) | |
| end | |
| end | |
| count(Data) | |
| State.Member = 1 | |
| end | |
| count(Data,true) | |
| end | |
| -- Bruteforce type members. | |
| if State.Type <= 2 then | |
| State.Type = 2 | |
| print("---- TYPES:") | |
| classLabel.Text = "Type" | |
| local sorted = {} | |
| for name in pairs(types) do | |
| sorted[#sorted+1] = name | |
| end | |
| table.sort(sorted) | |
| for q = State.Class,#sorted do | |
| State.Class = q | |
| local name = sorted[q] | |
| local new = types[name] | |
| print(name) | |
| local data = new() | |
| Data.className = name | |
| Data.classProgText[1] = "%d/%d (%d%%)" | |
| Data.classProgText[2] = q | |
| Data.classProgText[3] = #sorted | |
| Data.classProgText[4] = q/#sorted*100 | |
| Data.classProgBar = q/#sorted | |
| Data.memberProgBar = 0 | |
| Data.memberProgText[1] = "" | |
| Data.memberProgText[2] = nil | |
| Data.memberProgText[3] = nil | |
| Data.memberProgText[4] = nil | |
| Data.superCount = "0" | |
| Data.lastSuper = "" | |
| Data.memberCount = "0" | |
| Data.lastMember = "" | |
| Data.unstableCount = "0" | |
| Data.lastUnstable = "" | |
| for i = State.Member,#Words do | |
| State.Member = i | |
| Data.memberProgText[1] = "%d/%d (%d%%)" | |
| Data.memberProgText[2] = i | |
| Data.memberProgText[3] = #Words | |
| Data.memberProgText[4] = i/#Words*100 | |
| Data.memberProgBar = i/#Words | |
| local s,ty = pcall(get,data,Words[i]) | |
| if s and ty then | |
| print("\t" .. ty .. ' ' .. name .. '.' .. Words[i]) | |
| count(Data,true) | |
| local val = data[Words[i]] | |
| if ty == 'userdata' then | |
| for i = 1,#Words do | |
| local s,ty = pcall(get,val,Words[i]) | |
| if s and ty then | |
| print("\t\t" .. ty .. ' .' .. Words[i]) | |
| count(Data,true) | |
| end | |
| end | |
| end | |
| end | |
| count(Data) | |
| end | |
| count(Data,true) | |
| State.Member = 1 | |
| end | |
| end | |
| print("---- DONE") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
And it's for?