Sempek_Official

Roblox remote spy (NEW)

Nov 7th, 2025
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.69 KB | Gaming | 0 0
  1. -- LocalScript: Full Remote Tester with Scrollable Console + Multiservice + Resizable UI
  2. -- Place in StarterGui. Development and debugging only.
  3.  
  4. local Players = game:GetService("Players")
  5. local ReplicatedStorage = game:GetService("ReplicatedStorage")
  6. local Workspace = game:GetService("Workspace")
  7. local Lighting = game:GetService("Lighting")
  8. local SoundService = game:GetService("SoundService")
  9. local StarterGui = game:GetService("StarterGui")
  10. local StarterPack = game:GetService("StarterPack")
  11. local StarterPlayer = game:GetService("StarterPlayer")
  12. local TextChatService = game:GetService("TextChatService")
  13. local UserInputService = game:GetService("UserInputService")
  14. local player = Players.LocalPlayer
  15. local playerGui = player:WaitForChild("PlayerGui")
  16.  
  17. -- =========================
  18. -- UTILITY FUNCTIONS
  19. -- =========================
  20.  
  21. -- Trim whitespace
  22. local function trim(s) return s:match("^%s*(.-)%s*$") end
  23.  
  24. -- Pretty print tables recursively
  25. local function pretty(v, depth)
  26.     depth = depth or 0
  27.     local t = typeof(v)
  28.     if t == "string" then
  29.         return '"' .. v .. '"'
  30.     elseif t == "number" or t == "boolean" or v == nil then
  31.         return tostring(v)
  32.     elseif t == "table" then
  33.         if depth > 4 then return "{...}" end
  34.         local parts = {}
  35.         for k,val in pairs(v) do
  36.             table.insert(parts, string.rep("  ", depth+1) ..
  37.                 "["..pretty(k,depth+1).."] = "..pretty(val,depth+1))
  38.         end
  39.         return "{\n"..table.concat(parts,",\n").."\n"..string.rep("  ",depth).."}"
  40.     else
  41.         return "<"..t..">"
  42.     end
  43. end
  44.  
  45. -- Parse a single token
  46. local function parseToken(tok)
  47.     tok = trim(tok)
  48.     if tok == "" then return nil end
  49.     local s = tok:match('^"(.*)"$') or tok:match("^'(.*)'$")
  50.     if s then return s end
  51.     if tok == "true" then return true end
  52.     if tok == "false" then return false end
  53.     if tok == "nil" then return nil end
  54.     local n = tonumber(tok)
  55.     if n then return n end
  56.     return tok
  57. end
  58.  
  59. -- Parse CSV arguments into Lua values
  60. local function parseArgs(csv)
  61.     csv = tostring(csv or "")
  62.     if csv == "" then return {} end
  63.     local out, cur, inQuotes, quoteChar = {}, "", false, nil
  64.     for i = 1, #csv do
  65.         local c = csv:sub(i,i)
  66.         if (c == '"' or c == "'") and not inQuotes then
  67.             inQuotes = true
  68.             quoteChar = c
  69.             cur ..= c
  70.         elseif c == quoteChar and inQuotes then
  71.             inQuotes = false
  72.             quoteChar = nil
  73.             cur ..= c
  74.         elseif c == "," and not inQuotes then
  75.             table.insert(out, parseToken(cur))
  76.             cur = ""
  77.         else
  78.             cur ..= c
  79.         end
  80.     end
  81.     if cur ~= "" then table.insert(out, parseToken(cur)) end
  82.     return out
  83. end
  84.  
  85. -- =========================
  86. -- REMOTE COLLECTION
  87. -- =========================
  88.  
  89. local function safeGetDescendants(parent)
  90.     local ok, descendants = pcall(function()
  91.         return parent:GetDescendants()
  92.     end)
  93.     return ok and descendants or {}
  94. end
  95.  
  96. local function collectRemotes()
  97.     local remotes = {}
  98.  
  99.     local services = {
  100.         ReplicatedStorage, Players, Workspace, StarterGui, StarterPack,
  101.         StarterPlayer, playerGui, Lighting, SoundService, ChatService,
  102.         TextChatService, CoreGui, UserGameSettings, VRService
  103.     }
  104.  
  105.     for _, svc in ipairs(services) do
  106.         for _, inst in ipairs(safeGetDescendants(svc)) do
  107.             if inst:IsA("RemoteEvent") or inst:IsA("RemoteFunction") then
  108.                 table.insert(remotes, inst)
  109.             end
  110.         end
  111.     end
  112.  
  113.     -- Include Backpack remotes
  114.     if player:FindFirstChild("Backpack") then
  115.         for _, inst in ipairs(safeGetDescendants(player.Backpack)) do
  116.             if inst:IsA("RemoteEvent") or inst:IsA("RemoteFunction") then
  117.                 table.insert(remotes, inst)
  118.             end
  119.         end
  120.     end
  121.  
  122.     -- Include Character tool remotes
  123.     if player.Character then
  124.         for _, inst in ipairs(safeGetDescendants(player.Character)) do
  125.             if inst:IsA("RemoteEvent") or inst:IsA("RemoteFunction") then
  126.                 table.insert(remotes, inst)
  127.             end
  128.         end
  129.     end
  130.  
  131.     -- Include StarterPack items
  132.     for _, inst in ipairs(safeGetDescendants(StarterPack)) do
  133.         if inst:IsA("RemoteEvent") or inst:IsA("RemoteFunction") then
  134.             table.insert(remotes, inst)
  135.         end
  136.     end
  137.  
  138.     table.sort(remotes, function(a,b) return a:GetFullName() < b:GetFullName() end)
  139.     return remotes
  140. end
  141.  
  142. -- =========================
  143. -- GUI SETUP
  144. -- =========================
  145.  
  146. local screenGui = Instance.new("ScreenGui")
  147. screenGui.Name = "RemoteTesterGUI"
  148. screenGui.ResetOnSpawn = false
  149. screenGui.Parent = playerGui
  150. screenGui.ZIndexBehavior = Enum.ZIndexBehavior.Sibling
  151.  
  152. local main = Instance.new("Frame")
  153. main.Size = UDim2.new(0.45,0,0.6,0)
  154. main.Position = UDim2.new(0.5,-260,0.15,0)
  155. main.AnchorPoint = Vector2.new(0.5,0)
  156. main.BackgroundColor3 = Color3.fromRGB(34,34,34)
  157. main.BorderSizePixel = 0
  158. main.Parent = screenGui
  159.  
  160. -- UIScale for optional zooming
  161. local uiScale = Instance.new("UIScale")
  162. uiScale.Scale = 1
  163. uiScale.Parent = main
  164.  
  165. -- Titlebar
  166. local titlebar = Instance.new("Frame")
  167. titlebar.Size = UDim2.new(1,0,0,34)
  168. titlebar.BackgroundColor3 = Color3.fromRGB(24,24,24)
  169. titlebar.BorderSizePixel = 0
  170. titlebar.Parent = main
  171.  
  172. local title = Instance.new("TextLabel")
  173. title.Size = UDim2.new(0.7,0,1,0)
  174. title.Position = UDim2.new(0,8,0,0)
  175. title.BackgroundTransparency = 1
  176. title.Text = "ReplicatedStorage Remote Tester + Scrollable Console"
  177. title.TextColor3 = Color3.fromRGB(230,230,230)
  178. title.Font = Enum.Font.SourceSansSemibold
  179. title.TextSize = 14
  180. title.TextXAlignment = Enum.TextXAlignment.Left
  181. title.Parent = titlebar
  182.  
  183. local btnClose = Instance.new("TextButton")
  184. btnClose.Size = UDim2.new(0,36,0,22)
  185. btnClose.Position = UDim2.new(1,-44,0,6)
  186. btnClose.Text = "X"
  187. btnClose.Parent = titlebar
  188.  
  189. local btnMin = Instance.new("TextButton")
  190. btnMin.Size = UDim2.new(0,36,0,22)
  191. btnMin.Position = UDim2.new(1,-88,0,6)
  192. btnMin.Text = "_"
  193. btnMin.Parent = titlebar
  194.  
  195. -- Content frame
  196. local content = Instance.new("Frame")
  197. content.Size = UDim2.new(1,-16,1,-50)
  198. content.Position = UDim2.new(0,8,0,40)
  199. content.BackgroundTransparency = 1
  200. content.Parent = main
  201.  
  202. -- Panels
  203. local leftPanel = Instance.new("Frame")
  204. leftPanel.Size = UDim2.new(0.55,0,1,0)
  205. leftPanel.Position = UDim2.new(0,0,0,0)
  206. leftPanel.BackgroundColor3 = Color3.fromRGB(28,28,28)
  207. leftPanel.BorderSizePixel = 0
  208. leftPanel.Parent = content
  209.  
  210. local rightPanel = Instance.new("Frame")
  211. rightPanel.Size = UDim2.new(0.43,0,1,0)
  212. rightPanel.Position = UDim2.new(0.57,0,0,0)
  213. rightPanel.BackgroundColor3 = Color3.fromRGB(30,30,30)
  214. rightPanel.BorderSizePixel = 0
  215. rightPanel.Parent = content
  216.  
  217. -- Scrollable console
  218. local consoleFrame = Instance.new("Frame")
  219. consoleFrame.Size = UDim2.new(1,0,0.25,0)
  220. consoleFrame.Position = UDim2.new(0,0,0.75,0)
  221. consoleFrame.BackgroundColor3 = Color3.fromRGB(20,20,20)
  222. consoleFrame.BorderSizePixel = 0
  223. consoleFrame.Parent = main
  224.  
  225. local consoleScroll = Instance.new("ScrollingFrame")
  226. consoleScroll.Size = UDim2.new(1,-8,1,-8)
  227. consoleScroll.Position = UDim2.new(0,4,0,4)
  228. consoleScroll.BackgroundTransparency = 1
  229. consoleScroll.CanvasSize = UDim2.new(0,0,0,0)
  230. consoleScroll.ScrollBarThickness = 6
  231. consoleScroll.Parent = consoleFrame
  232.  
  233. local consoleLayout = Instance.new("UIListLayout")
  234. consoleLayout.Padding = UDim.new(0,2)
  235. consoleLayout.Parent = consoleScroll
  236.  
  237. -- =========================
  238. -- LOGGING FUNCTION
  239. -- =========================
  240.  
  241. local function logConsole(msg,isError)
  242.     msg = tostring(msg)
  243.     local lines = msg:split("\n")
  244.     for _,line in ipairs(lines) do
  245.         local label = Instance.new("TextLabel")
  246.         label.Size = UDim2.new(1,0,0,16)
  247.         label.BackgroundTransparency = 1
  248.         label.Font = Enum.Font.Code
  249.         label.TextSize = 12
  250.         label.TextXAlignment = Enum.TextXAlignment.Left
  251.         label.Text = os.date("[%H:%M:%S] ") .. line
  252.         label.TextColor3 = isError and Color3.fromRGB(255,80,80) or Color3.fromRGB(0,255,0)
  253.         label.Parent = consoleScroll
  254.     end
  255.     consoleScroll.CanvasSize = UDim2.new(0,0,0,consoleLayout.AbsoluteContentSize.Y + 4)
  256.     consoleScroll.CanvasPosition = Vector2.new(0, consoleScroll.CanvasSize.Y.Offset)
  257. end
  258.  
  259. -- =========================
  260. -- REMOTES UI
  261. -- =========================
  262.  
  263. local remotesLabel = Instance.new("TextLabel")
  264. remotesLabel.Size = UDim2.new(1,0,0,26)
  265. remotesLabel.Position = UDim2.new(0,8,0,6)
  266. remotesLabel.BackgroundTransparency = 1
  267. remotesLabel.Text = "Remotes in accessible services"
  268. remotesLabel.TextColor3 = Color3.fromRGB(220,220,220)
  269. remotesLabel.Font = Enum.Font.SourceSansSemibold
  270. remotesLabel.TextSize = 14
  271. remotesLabel.TextXAlignment = Enum.TextXAlignment.Left
  272. remotesLabel.Parent = leftPanel
  273.  
  274. local refreshBtn = Instance.new("TextButton")
  275. refreshBtn.Size = UDim2.new(0,80,0,24)
  276. refreshBtn.Position = UDim2.new(1,-88,0,6)
  277. refreshBtn.Text = "Refresh"
  278. refreshBtn.Parent = leftPanel
  279.  
  280. local remotesList = Instance.new("ScrollingFrame")
  281. remotesList.Size = UDim2.new(1,-16,1,-50)
  282. remotesList.Position = UDim2.new(0,8,0,38)
  283. remotesList.CanvasSize = UDim2.new(0,0,0,0)
  284. remotesList.ScrollBarThickness = 6
  285. remotesList.BackgroundTransparency = 1
  286. remotesList.Parent = leftPanel
  287.  
  288. local uiListLayout = Instance.new("UIListLayout")
  289. uiListLayout.Padding = UDim.new(0,6)
  290. uiListLayout.Parent = remotesList
  291.  
  292. local selectedLabel = Instance.new("TextLabel")
  293. selectedLabel.Size = UDim2.new(1,-16,0,24)
  294. selectedLabel.Position = UDim2.new(0,8,0,8)
  295. selectedLabel.BackgroundTransparency = 1
  296. selectedLabel.Text = "Selected: (none)"
  297. selectedLabel.TextColor3 = Color3.fromRGB(230,230,230)
  298. selectedLabel.Font = Enum.Font.SourceSans
  299. selectedLabel.TextSize = 14
  300. selectedLabel.TextXAlignment = Enum.TextXAlignment.Left
  301. selectedLabel.Parent = rightPanel
  302.  
  303. local argsLabel = Instance.new("TextLabel")
  304. argsLabel.Size = UDim2.new(1,-16,0,18)
  305. argsLabel.Position = UDim2.new(0,8,0,36)
  306. argsLabel.BackgroundTransparency = 1
  307. argsLabel.Text = "Arguments (comma separated)"
  308. argsLabel.TextColor3 = Color3.fromRGB(200,200,200)
  309. argsLabel.Font = Enum.Font.SourceSans
  310. argsLabel.TextSize = 12
  311. argsLabel.TextXAlignment = Enum.TextXAlignment.Left
  312. argsLabel.Parent = rightPanel
  313.  
  314. local argsBox = Instance.new("TextBox")
  315. argsBox.Size = UDim2.new(1,-16,0,36)
  316. argsBox.Position = UDim2.new(0,8,0,56)
  317. argsBox.ClearTextOnFocus = false
  318. argsBox.PlaceholderText = [["hello",5,true]]
  319. argsBox.Text = ""
  320. argsBox.Parent = rightPanel
  321.  
  322. local fireButton = Instance.new("TextButton")
  323. fireButton.Size = UDim2.new(0,200,0,36)
  324. fireButton.Position = UDim2.new(0,8,0,100)
  325. fireButton.Text = "Fire / Invoke Selected Remote"
  326. fireButton.Parent = rightPanel
  327.  
  328. -- =========================
  329. -- DRAGGING AND RESIZING
  330. -- =========================
  331.  
  332. local dragging, dragStartPos, guiStartPos
  333. local resizing, resizeDir, resizeStartPos, resizeStartSize
  334. local edgeThreshold = 8
  335.  
  336. -- Determine which edge/corner is being hovered
  337. local function getResizeDirection(mousePos)
  338.     local absPos = main.AbsolutePosition
  339.     local absSize = main.AbsoluteSize
  340.     local rightEdge = absPos.X + absSize.X
  341.     local bottomEdge = absPos.Y + absSize.Y
  342.     local nearLeft = math.abs(mousePos.X - absPos.X) <= edgeThreshold
  343.     local nearRight = math.abs(mousePos.X - rightEdge) <= edgeThreshold
  344.     local nearTop = math.abs(mousePos.Y - absPos.Y) <= edgeThreshold
  345.     local nearBottom = math.abs(mousePos.Y - bottomEdge) <= edgeThreshold
  346.  
  347.     if nearLeft and nearTop then return "TopLeft"
  348.     elseif nearRight and nearTop then return "TopRight"
  349.     elseif nearLeft and nearBottom then return "BottomLeft"
  350.     elseif nearRight and nearBottom then return "BottomRight"
  351.     elseif nearLeft then return "Left"
  352.     elseif nearRight then return "Right"
  353.     elseif nearTop then return "Top"
  354.     elseif nearBottom then return "Bottom"
  355.     end
  356.     return nil
  357. end
  358.  
  359. -- Dragging
  360. titlebar.InputBegan:Connect(function(input)
  361.     if input.UserInputType == Enum.UserInputType.MouseButton1 then
  362.         if resizing then return end
  363.         dragging = true
  364.         dragStartPos = input.Position
  365.         guiStartPos = main.Position
  366.         input.Changed:Connect(function()
  367.             if input.UserInputState == Enum.UserInputState.End then
  368.                 dragging = false
  369.             end
  370.         end)
  371.     end
  372. end)
  373.  
  374. UserInputService.InputChanged:Connect(function(input)
  375.     -- Dragging
  376.     if dragging and input.UserInputType == Enum.UserInputType.MouseMovement then
  377.         if resizing then return end
  378.         local delta = input.Position - dragStartPos
  379.         main.Position = UDim2.new(guiStartPos.X.Scale, guiStartPos.X.Offset + delta.X,
  380.             guiStartPos.Y.Scale, guiStartPos.Y.Offset + delta.Y)
  381.     end
  382.  
  383.     -- Resizing
  384.     if resizing and input.UserInputType == Enum.UserInputType.MouseMovement then
  385.         local delta = input.Position - resizeStartPos
  386.         local newSize = resizeStartSize
  387.         local newPos = main.Position
  388.  
  389.         if resizeDir == "Right" or resizeDir == "TopRight" or resizeDir == "BottomRight" then
  390.             newSize = UDim2.new(0, math.max(240, resizeStartSize.X.Offset + delta.X), 0, newSize.Y.Offset)
  391.         elseif resizeDir == "Left" or resizeDir == "TopLeft" or resizeDir == "BottomLeft" then
  392.             local newWidth = math.max(240, resizeStartSize.X.Offset - delta.X)
  393.             newSize = UDim2.new(0, newWidth, 0, newSize.Y.Offset)
  394.             newPos = UDim2.new(newPos.X.Scale, newPos.X.Offset + delta.X, newPos.Y.Scale, newPos.Y.Offset)
  395.         end
  396.  
  397.         if resizeDir == "Bottom" or resizeDir == "BottomLeft" or resizeDir == "BottomRight" then
  398.             newSize = UDim2.new(0, newSize.X.Offset, 0, math.max(180, resizeStartSize.Y.Offset + delta.Y))
  399.         elseif resizeDir == "Top" or resizeDir == "TopLeft" or resizeDir == "TopRight" then
  400.             local newHeight = math.max(180, resizeStartSize.Y.Offset - delta.Y)
  401.             newSize = UDim2.new(0, newSize.X.Offset, 0, newHeight)
  402.             newPos = UDim2.new(newPos.X.Scale, newPos.X.Offset, newPos.Y.Scale, newPos.Y.Offset + delta.Y)
  403.         end
  404.  
  405.         main.Size = newSize
  406.         main.Position = newPos
  407.     end
  408. end)
  409.  
  410. main.InputBegan:Connect(function(input)
  411.     if input.UserInputType == Enum.UserInputType.MouseButton1 then
  412.         local dir = getResizeDirection(input.Position)
  413.         if dir then
  414.             resizing = true
  415.             resizeDir = dir
  416.             resizeStartPos = input.Position
  417.             resizeStartSize = main.Size
  418.             input.Changed:Connect(function()
  419.                 if input.UserInputState == Enum.UserInputState.End then
  420.                     resizing = false
  421.                     resizeDir = nil
  422.                 end
  423.             end)
  424.         end
  425.     end
  426. end)
  427.  
  428. -- =========================
  429. -- MINIMIZE / CLOSE
  430. -- =========================
  431.  
  432. btnClose.MouseButton1Click:Connect(function() screenGui:Destroy() end)
  433. local minimized = false
  434. btnMin.MouseButton1Click:Connect(function()
  435.     minimized = not minimized
  436.     content.Visible = not minimized
  437.     consoleFrame.Visible = not minimized
  438.     main.Size = minimized and UDim2.new(0,240,0,34) or UDim2.new(0.45,0,0.6,0)
  439. end)
  440.  
  441. -- =========================
  442. -- REMOTE LIST POPULATION
  443. -- =========================
  444.  
  445. local selectedRemote
  446. local function clearList()
  447.     for _,v in ipairs(remotesList:GetChildren()) do
  448.         if v:IsA("TextButton") then v:Destroy() end
  449.     end
  450. end
  451.  
  452. local function populate()
  453.     clearList()
  454.     local remotes = collectRemotes()
  455.     logConsole("Loading "..#remotes.." remotes...")
  456.    
  457.     spawn(function()  -- run asynchronously to avoid freezing the main thread
  458.         for _,inst in ipairs(remotes) do
  459.             local btn = Instance.new("TextButton")
  460.             btn.Size = UDim2.new(1,-8,0,28)
  461.             btn.BackgroundColor3 = Color3.fromRGB(38,38,38)
  462.             btn.BorderSizePixel = 0
  463.             btn.Text = inst:GetFullName()
  464.             btn.Font = Enum.Font.SourceSans
  465.             btn.TextSize = 13
  466.             btn.TextColor3 = Color3.fromRGB(230,230,230)
  467.             btn.Parent = remotesList
  468.  
  469.             btn.MouseButton1Click:Connect(function()
  470.                 for _,b in ipairs(remotesList:GetChildren()) do
  471.                     if b:IsA("TextButton") then
  472.                         b.BackgroundColor3 = Color3.fromRGB(38,38,38)
  473.                     end
  474.                 end
  475.                 btn.BackgroundColor3 = Color3.fromRGB(60,60,60)
  476.                 selectedRemote = inst
  477.                 selectedLabel.Text = "Selected: " .. inst:GetFullName()
  478.             end)
  479.  
  480.             -- Yield a little to avoid freezing on low-end
  481.             task.wait(0.05)
  482.         end
  483.         remotesList.CanvasSize = UDim2.new(0,0,0,uiListLayout.AbsoluteContentSize.Y + 8)
  484.         logConsole("Finished loading "..#remotes.." remotes.")
  485.     end)
  486. end
  487.  
  488.  
  489. refreshBtn.MouseButton1Click:Connect(function()
  490.     populate()
  491.     logConsole("Manual refresh triggered.")
  492. end)
  493.  
  494. ReplicatedStorage.DescendantAdded:Connect(function(d)
  495.     if d:IsA("RemoteEvent") or d:IsA("RemoteFunction") then populate() end
  496. end)
  497. ReplicatedStorage.DescendantRemoving:Connect(function(d)
  498.     if d:IsA("RemoteEvent") or d:IsA("RemoteFunction") then
  499.         if selectedRemote == d then selectedRemote = nil end
  500.         populate()
  501.     end
  502. end)
  503.  
  504. -- =========================
  505. -- FIRE REMOTE
  506. -- =========================
  507.  
  508. fireButton.MouseButton1Click:Connect(function()
  509.     if not selectedRemote then
  510.         logConsole("No remote selected.",true)
  511.         return
  512.     end
  513.     local args = parseArgs(argsBox.Text)
  514.     local ok, res = pcall(function()
  515.         if selectedRemote:IsA("RemoteEvent") then
  516.             selectedRemote:FireServer(table.unpack(args))
  517.             return "Fired RemoteEvent."
  518.         else
  519.             local result = selectedRemote:InvokeServer(table.unpack(args))
  520.             return "InvokeServer returned: " .. pretty(result)
  521.         end
  522.     end)
  523.     if ok then
  524.         logConsole(res)
  525.     else
  526.         logConsole("Error: "..tostring(res),true)
  527.     end
  528. end)
  529.  
  530. -- =========================
  531. -- INITIALIZATION
  532. -- =========================
  533.  
  534. populate()
  535. logConsole("Ready.")
  536.  
Tags: Roblox Exploit
Advertisement
Add Comment
Please, Sign In to add comment