Advertisement
ExecutorForALLdomain

Untitled

Jul 30th, 2024
32
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 80.39 KB | None | 0 0
  1. --[[
  2. SimpleSpy v2.2 SOURCE
  3.  
  4. SimpleSpy is a lightweight penetration testing tool that logs remote calls.
  5.  
  6. Credits:
  7. exx - basically everything
  8. Frosty - GUI to Lua
  9. ]]
  10.  
  11. -- shuts down the previous instance of SimpleSpy
  12. if _G.SimpleSpyExecuted and type(_G.SimpleSpyShutdown) == "function" then
  13. print(pcall(_G.SimpleSpyShutdown))
  14. end
  15.  
  16. local cloneref = cloneref or function(...) return ... end
  17. local Players = cloneref(game:GetService("Players"))
  18. local CoreGui = cloneref(game:GetService("CoreGui"))
  19. local Highlight =
  20. loadstring(
  21. game:HttpGet("https://github.com/exxtremestuffs/SimpleSpySource/raw/master/highlight.lua")
  22. )()
  23.  
  24. ---- GENERATED (kinda sorta mostly) BY GUI to LUA ----
  25.  
  26. -- Instances:
  27.  
  28. local SimpleSpy2 = Instance.new("ScreenGui")
  29. local Background = Instance.new("Frame")
  30. local LeftPanel = Instance.new("Frame")
  31. local LogList = Instance.new("ScrollingFrame")
  32. local UIListLayout = Instance.new("UIListLayout")
  33. local RemoteTemplate = Instance.new("Frame")
  34. local ColorBar = Instance.new("Frame")
  35. local Text = Instance.new("TextLabel")
  36. local Button = Instance.new("TextButton")
  37. local RightPanel = Instance.new("Frame")
  38. local CodeBox = Instance.new("Frame")
  39. local ScrollingFrame = Instance.new("ScrollingFrame")
  40. local UIGridLayout = Instance.new("UIGridLayout")
  41. local FunctionTemplate = Instance.new("Frame")
  42. local ColorBar_2 = Instance.new("Frame")
  43. local Text_2 = Instance.new("TextLabel")
  44. local Button_2 = Instance.new("TextButton")
  45. local TopBar = Instance.new("Frame")
  46. local Simple = Instance.new("TextButton")
  47. local CloseButton = Instance.new("TextButton")
  48. local ImageLabel = Instance.new("ImageLabel")
  49. local MaximizeButton = Instance.new("TextButton")
  50. local ImageLabel_2 = Instance.new("ImageLabel")
  51. local MinimizeButton = Instance.new("TextButton")
  52. local ImageLabel_3 = Instance.new("ImageLabel")
  53. local ToolTip = Instance.new("Frame")
  54. local TextLabel = Instance.new("TextLabel")
  55.  
  56. --Properties:
  57.  
  58. SimpleSpy2.Name = "SimpleSpy2"
  59. SimpleSpy2.ResetOnSpawn = false
  60.  
  61. Background.Name = "Background"
  62. Background.Parent = SimpleSpy2
  63. Background.BackgroundColor3 = Color3.new(1, 1, 1)
  64. Background.BackgroundTransparency = 1
  65. Background.Position = UDim2.new(0, 500, 0, 200)
  66. Background.Size = UDim2.new(0, 450, 0, 268)
  67.  
  68. LeftPanel.Name = "LeftPanel"
  69. LeftPanel.Parent = Background
  70. LeftPanel.BackgroundColor3 = Color3.fromRGB(53, 52, 55)
  71. LeftPanel.BorderSizePixel = 0
  72. LeftPanel.Position = UDim2.new(0, 0, 0, 19)
  73. LeftPanel.Size = UDim2.new(0, 131, 0, 249)
  74.  
  75. LogList.Name = "LogList"
  76. LogList.Parent = LeftPanel
  77. LogList.Active = true
  78. LogList.BackgroundColor3 = Color3.new(1, 1, 1)
  79. LogList.BackgroundTransparency = 1
  80. LogList.BorderSizePixel = 0
  81. LogList.Position = UDim2.new(0, 0, 0, 9)
  82. LogList.Size = UDim2.new(0, 131, 0, 232)
  83. LogList.CanvasSize = UDim2.new(0, 0, 0, 0)
  84. LogList.ScrollBarThickness = 4
  85.  
  86. UIListLayout.Parent = LogList
  87. UIListLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
  88. UIListLayout.SortOrder = Enum.SortOrder.LayoutOrder
  89.  
  90. RemoteTemplate.Name = "RemoteTemplate"
  91. RemoteTemplate.Parent = LogList
  92. RemoteTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
  93. RemoteTemplate.BackgroundTransparency = 1
  94. RemoteTemplate.Size = UDim2.new(0, 117, 0, 27)
  95.  
  96. ColorBar.Name = "ColorBar"
  97. ColorBar.Parent = RemoteTemplate
  98. ColorBar.BackgroundColor3 = Color3.fromRGB(255, 242, 0)
  99. ColorBar.BorderSizePixel = 0
  100. ColorBar.Position = UDim2.new(0, 0, 0, 1)
  101. ColorBar.Size = UDim2.new(0, 7, 0, 18)
  102. ColorBar.ZIndex = 2
  103.  
  104. Text.Name = "Text"
  105. Text.Parent = RemoteTemplate
  106. Text.BackgroundColor3 = Color3.new(1, 1, 1)
  107. Text.BackgroundTransparency = 1
  108. Text.Position = UDim2.new(0, 12, 0, 1)
  109. Text.Size = UDim2.new(0, 105, 0, 18)
  110. Text.ZIndex = 2
  111. Text.Font = Enum.Font.SourceSans
  112. Text.Text = "TEXT"
  113. Text.TextColor3 = Color3.new(1, 1, 1)
  114. Text.TextSize = 14
  115. Text.TextXAlignment = Enum.TextXAlignment.Left
  116. Text.TextWrapped = true
  117.  
  118. Button.Name = "Button"
  119. Button.Parent = RemoteTemplate
  120. Button.BackgroundColor3 = Color3.new(0, 0, 0)
  121. Button.BackgroundTransparency = 0.75
  122. Button.BorderColor3 = Color3.new(1, 1, 1)
  123. Button.Position = UDim2.new(0, 0, 0, 1)
  124. Button.Size = UDim2.new(0, 117, 0, 18)
  125. Button.AutoButtonColor = false
  126. Button.Font = Enum.Font.SourceSans
  127. Button.Text = ""
  128. Button.TextColor3 = Color3.new(0, 0, 0)
  129. Button.TextSize = 14
  130.  
  131. RightPanel.Name = "RightPanel"
  132. RightPanel.Parent = Background
  133. RightPanel.BackgroundColor3 = Color3.fromRGB(37, 36, 38)
  134. RightPanel.BorderSizePixel = 0
  135. RightPanel.Position = UDim2.new(0, 131, 0, 19)
  136. RightPanel.Size = UDim2.new(0, 319, 0, 249)
  137.  
  138. CodeBox.Name = "CodeBox"
  139. CodeBox.Parent = RightPanel
  140. CodeBox.BackgroundColor3 = Color3.new(0.0823529, 0.0745098, 0.0784314)
  141. CodeBox.BorderSizePixel = 0
  142. CodeBox.Size = UDim2.new(0, 319, 0, 119)
  143.  
  144. ScrollingFrame.Parent = RightPanel
  145. ScrollingFrame.Active = true
  146. ScrollingFrame.BackgroundColor3 = Color3.new(1, 1, 1)
  147. ScrollingFrame.BackgroundTransparency = 1
  148. ScrollingFrame.Position = UDim2.new(0, 0, 0.5, 0)
  149. ScrollingFrame.Size = UDim2.new(1, 0, 0.5, -9)
  150. ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
  151. ScrollingFrame.ScrollBarThickness = 4
  152.  
  153. UIGridLayout.Parent = ScrollingFrame
  154. UIGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
  155. UIGridLayout.SortOrder = Enum.SortOrder.LayoutOrder
  156. UIGridLayout.CellPadding = UDim2.new(0, 0, 0, 0)
  157. UIGridLayout.CellSize = UDim2.new(0, 94, 0, 27)
  158.  
  159. FunctionTemplate.Name = "FunctionTemplate"
  160. FunctionTemplate.Parent = ScrollingFrame
  161. FunctionTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
  162. FunctionTemplate.BackgroundTransparency = 1
  163. FunctionTemplate.Size = UDim2.new(0, 117, 0, 23)
  164.  
  165. ColorBar_2.Name = "ColorBar"
  166. ColorBar_2.Parent = FunctionTemplate
  167. ColorBar_2.BackgroundColor3 = Color3.new(1, 1, 1)
  168. ColorBar_2.BorderSizePixel = 0
  169. ColorBar_2.Position = UDim2.new(0, 7, 0, 10)
  170. ColorBar_2.Size = UDim2.new(0, 7, 0, 18)
  171. ColorBar_2.ZIndex = 3
  172.  
  173. Text_2.Name = "Text"
  174. Text_2.Parent = FunctionTemplate
  175. Text_2.BackgroundColor3 = Color3.new(1, 1, 1)
  176. Text_2.BackgroundTransparency = 1
  177. Text_2.Position = UDim2.new(0, 19, 0, 10)
  178. Text_2.Size = UDim2.new(0, 69, 0, 18)
  179. Text_2.ZIndex = 2
  180. Text_2.Font = Enum.Font.SourceSans
  181. Text_2.Text = "TEXT"
  182. Text_2.TextColor3 = Color3.new(1, 1, 1)
  183. Text_2.TextSize = 14
  184. Text_2.TextStrokeColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  185. Text_2.TextXAlignment = Enum.TextXAlignment.Left
  186. Text_2.TextWrapped = true
  187.  
  188. Button_2.Name = "Button"
  189. Button_2.Parent = FunctionTemplate
  190. Button_2.BackgroundColor3 = Color3.new(0, 0, 0)
  191. Button_2.BackgroundTransparency = 0.69999998807907
  192. Button_2.BorderColor3 = Color3.new(1, 1, 1)
  193. Button_2.Position = UDim2.new(0, 7, 0, 10)
  194. Button_2.Size = UDim2.new(0, 80, 0, 18)
  195. Button_2.AutoButtonColor = false
  196. Button_2.Font = Enum.Font.SourceSans
  197. Button_2.Text = ""
  198. Button_2.TextColor3 = Color3.new(0, 0, 0)
  199. Button_2.TextSize = 14
  200.  
  201. TopBar.Name = "TopBar"
  202. TopBar.Parent = Background
  203. TopBar.BackgroundColor3 = Color3.fromRGB(37, 35, 38)
  204. TopBar.BorderSizePixel = 0
  205. TopBar.Size = UDim2.new(0, 450, 0, 19)
  206.  
  207. Simple.Name = "Simple"
  208. Simple.Parent = TopBar
  209. Simple.BackgroundColor3 = Color3.new(1, 1, 1)
  210. Simple.AutoButtonColor = false
  211. Simple.BackgroundTransparency = 1
  212. Simple.Position = UDim2.new(0, 5, 0, 0)
  213. Simple.Size = UDim2.new(0, 57, 0, 18)
  214. Simple.Font = Enum.Font.SourceSansBold
  215. Simple.Text = "SimpleSpy"
  216. Simple.TextColor3 = Color3.new(1, 1, 1)
  217. Simple.TextSize = 14
  218. Simple.TextXAlignment = Enum.TextXAlignment.Left
  219.  
  220. CloseButton.Name = "CloseButton"
  221. CloseButton.Parent = TopBar
  222. CloseButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  223. CloseButton.BorderSizePixel = 0
  224. CloseButton.Position = UDim2.new(1, -19, 0, 0)
  225. CloseButton.Size = UDim2.new(0, 19, 0, 19)
  226. CloseButton.Font = Enum.Font.SourceSans
  227. CloseButton.Text = ""
  228. CloseButton.TextColor3 = Color3.new(0, 0, 0)
  229. CloseButton.TextSize = 14
  230.  
  231. ImageLabel.Parent = CloseButton
  232. ImageLabel.BackgroundColor3 = Color3.new(1, 1, 1)
  233. ImageLabel.BackgroundTransparency = 1
  234. ImageLabel.Position = UDim2.new(0, 5, 0, 5)
  235. ImageLabel.Size = UDim2.new(0, 9, 0, 9)
  236. ImageLabel.Image = "http://www.roblox.com/asset/?id=5597086202"
  237.  
  238. MaximizeButton.Name = "MaximizeButton"
  239. MaximizeButton.Parent = TopBar
  240. MaximizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  241. MaximizeButton.BorderSizePixel = 0
  242. MaximizeButton.Position = UDim2.new(1, -38, 0, 0)
  243. MaximizeButton.Size = UDim2.new(0, 19, 0, 19)
  244. MaximizeButton.Font = Enum.Font.SourceSans
  245. MaximizeButton.Text = ""
  246. MaximizeButton.TextColor3 = Color3.new(0, 0, 0)
  247. MaximizeButton.TextSize = 14
  248.  
  249. ImageLabel_2.Parent = MaximizeButton
  250. ImageLabel_2.BackgroundColor3 = Color3.new(1, 1, 1)
  251. ImageLabel_2.BackgroundTransparency = 1
  252. ImageLabel_2.Position = UDim2.new(0, 5, 0, 5)
  253. ImageLabel_2.Size = UDim2.new(0, 9, 0, 9)
  254. ImageLabel_2.Image = "http://www.roblox.com/asset/?id=5597108117"
  255.  
  256. MinimizeButton.Name = "MinimizeButton"
  257. MinimizeButton.Parent = TopBar
  258. MinimizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
  259. MinimizeButton.BorderSizePixel = 0
  260. MinimizeButton.Position = UDim2.new(1, -57, 0, 0)
  261. MinimizeButton.Size = UDim2.new(0, 19, 0, 19)
  262. MinimizeButton.Font = Enum.Font.SourceSans
  263. MinimizeButton.Text = ""
  264. MinimizeButton.TextColor3 = Color3.new(0, 0, 0)
  265. MinimizeButton.TextSize = 14
  266.  
  267. ImageLabel_3.Parent = MinimizeButton
  268. ImageLabel_3.BackgroundColor3 = Color3.new(1, 1, 1)
  269. ImageLabel_3.BackgroundTransparency = 1
  270. ImageLabel_3.Position = UDim2.new(0, 5, 0, 5)
  271. ImageLabel_3.Size = UDim2.new(0, 9, 0, 9)
  272. ImageLabel_3.Image = "http://www.roblox.com/asset/?id=5597105827"
  273.  
  274. ToolTip.Name = "ToolTip"
  275. ToolTip.Parent = SimpleSpy2
  276. ToolTip.BackgroundColor3 = Color3.fromRGB(26, 26, 26)
  277. ToolTip.BackgroundTransparency = 0.1
  278. ToolTip.BorderColor3 = Color3.new(1, 1, 1)
  279. ToolTip.Size = UDim2.new(0, 200, 0, 50)
  280. ToolTip.ZIndex = 3
  281. ToolTip.Visible = false
  282.  
  283. TextLabel.Parent = ToolTip
  284. TextLabel.BackgroundColor3 = Color3.new(1, 1, 1)
  285. TextLabel.BackgroundTransparency = 1
  286. TextLabel.Position = UDim2.new(0, 2, 0, 2)
  287. TextLabel.Size = UDim2.new(0, 196, 0, 46)
  288. TextLabel.ZIndex = 3
  289. TextLabel.Font = Enum.Font.SourceSans
  290. TextLabel.Text = "This is some slightly longer text."
  291. TextLabel.TextColor3 = Color3.new(1, 1, 1)
  292. TextLabel.TextSize = 14
  293. TextLabel.TextWrapped = true
  294. TextLabel.TextXAlignment = Enum.TextXAlignment.Left
  295. TextLabel.TextYAlignment = Enum.TextYAlignment.Top
  296.  
  297. -------------------------------------------------------------------------------
  298. -- init
  299. local RunService = game:GetService("RunService")
  300. local UserInputService = game:GetService("UserInputService")
  301. local TweenService = game:GetService("TweenService")
  302. local ContentProvider = game:GetService("ContentProvider")
  303. local TextService = game:GetService("TextService")
  304. local Mouse
  305.  
  306. local selectedColor = Color3.new(0.321569, 0.333333, 1)
  307. local deselectedColor = Color3.new(0.8, 0.8, 0.8)
  308. --- So things are descending
  309. local layoutOrderNum = 999999999
  310. --- Whether or not the gui is closing
  311. local mainClosing = false
  312. --- Whether or not the gui is closed (defaults to false)
  313. local closed = false
  314. --- Whether or not the sidebar is closing
  315. local sideClosing = false
  316. --- Whether or not the sidebar is closed (defaults to true but opens automatically on remote selection)
  317. local sideClosed = false
  318. --- Whether or not the code box is maximized (defaults to false)
  319. local maximized = false
  320. --- The event logs to be read from
  321. local logs = {}
  322. --- The event currently selected.Log (defaults to nil)
  323. local selected = nil
  324. --- The blacklist (can be a string name or the Remote Instance)
  325. local blacklist = {}
  326. --- The block list (can be a string name or the Remote Instance)
  327. local blocklist = {}
  328. --- Whether or not to add getNil function
  329. local getNil = false
  330. --- Array of remotes (and original functions) connected to
  331. local connectedRemotes = {}
  332. --- True = hookfunction, false = namecall
  333. local toggle = false
  334. local gm
  335. local original
  336. --- used to prevent recursives
  337. local prevTables = {}
  338. --- holds logs (for deletion)
  339. local remoteLogs = {}
  340. --- used for hookfunction
  341. local remoteEvent = Instance.new("RemoteEvent")
  342. --- used for hookfunction
  343. local remoteFunction = Instance.new("RemoteFunction")
  344. local originalEvent = remoteEvent.FireServer
  345. local originalFunction = remoteFunction.InvokeServer
  346. --- the maximum amount of remotes allowed in logs
  347. _G.SIMPLESPYCONFIG_MaxRemotes = 500
  348. --- how many spaces to indent
  349. local indent = 4
  350. --- used for task scheduler
  351. local scheduled = {}
  352. --- RBXScriptConnect of the task scheduler
  353. local schedulerconnect
  354. local SimpleSpy = {}
  355. local topstr = ""
  356. local bottomstr = ""
  357. local remotesFadeIn
  358. local rightFadeIn
  359. local codebox
  360. local p
  361. local getnilrequired = false
  362.  
  363. -- autoblock variables
  364. local autoblock = false
  365. local history = {}
  366. local excluding = {}
  367.  
  368. -- function info variables
  369. local funcEnabled = true
  370.  
  371. -- remote hooking/connecting api variables
  372. local remoteSignals = {}
  373. local remoteHooks = {}
  374.  
  375. -- original mouse icon
  376. local oldIcon
  377.  
  378. -- if mouse inside gui
  379. local mouseInGui = false
  380.  
  381. -- handy array of RBXScriptConnections to disconnect on shutdown
  382. local connections = {}
  383.  
  384. -- whether or not SimpleSpy uses 'getcallingscript()' to get the script (default is false because detection)
  385. local useGetCallingScript = false
  386.  
  387. --- used to enable/disable SimpleSpy's keyToString for remotes
  388. local keyToString = false
  389.  
  390. -- determines whether return values are recorded
  391. local recordReturnValues = false
  392.  
  393. -- functions
  394.  
  395. --- Converts arguments to a string and generates code that calls the specified method with them, recommended to be used in conjunction with ValueToString (method must be a string, e.g. `game:GetService("ReplicatedStorage").Remote.remote:FireServer`)
  396. --- @param method string
  397. --- @param args any[]
  398. --- @return string
  399. function SimpleSpy:ArgsToString(method, args)
  400. assert(typeof(method) == "string", "string expected, got " .. typeof(method))
  401. assert(typeof(args) == "table", "table expected, got " .. typeof(args))
  402. return v2v({ args = args }) .. "\n\n" .. method .. "(unpack(args))"
  403. end
  404.  
  405. --- Converts a value to variables with the specified index as the variable name (if nil/invalid then the name will be assigned automatically)
  406. --- @param t any[]
  407. --- @return string
  408. function SimpleSpy:TableToVars(t)
  409. assert(typeof(t) == "table", "table expected, got " .. typeof(t))
  410. return v2v(t)
  411. end
  412.  
  413. --- Converts a value to a variable with the specified `variablename` (if nil/invalid then the name will be assigned automatically)
  414. --- @param value any
  415. --- @return string
  416. function SimpleSpy:ValueToVar(value, variablename)
  417. assert(variablename == nil or typeof(variablename) == "string", "string expected, got " .. typeof(variablename))
  418. if not variablename then
  419. variablename = 1
  420. end
  421. return v2v({ [variablename] = value })
  422. end
  423.  
  424. --- Converts any value to a string, cannot preserve function contents
  425. --- @param value any
  426. --- @return string
  427. function SimpleSpy:ValueToString(value)
  428. return v2s(value)
  429. end
  430.  
  431. --- Generates the simplespy function info
  432. --- @param func function
  433. --- @return string
  434. function SimpleSpy:GetFunctionInfo(func)
  435. assert(typeof(func) == "function", "Instance expected, got " .. typeof(func))
  436. warn("Function info currently unavailable due to crashing in Synapse X")
  437. return v2v({ functionInfo = {
  438. info = debug.getinfo(func),
  439. constants = debug.getconstants(func),
  440. } })
  441. end
  442.  
  443. --- Gets the ScriptSignal for a specified remote being fired
  444. --- @param remote Instance
  445. function SimpleSpy:GetRemoteFiredSignal(remote)
  446. assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
  447. if not remoteSignals[remote] then
  448. remoteSignals[remote] = newSignal()
  449. end
  450. return remoteSignals[remote]
  451. end
  452.  
  453. --- Allows for direct hooking of remotes **THIS CAN BE VERY DANGEROUS**
  454. --- @param remote Instance
  455. --- @param f function
  456. function SimpleSpy:HookRemote(remote, f)
  457. assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
  458. assert(typeof(f) == "function", "function expected, got " .. typeof(f))
  459. remoteHooks[remote] = f
  460. end
  461.  
  462. --- Blocks the specified remote instance/string
  463. --- @param remote any
  464. function SimpleSpy:BlockRemote(remote)
  465. assert(
  466. typeof(remote) == "Instance" or typeof(remote) == "string",
  467. "Instance | string expected, got " .. typeof(remote)
  468. )
  469. blocklist[remote] = true
  470. end
  471.  
  472. --- Excludes the specified remote from logs (instance/string)
  473. --- @param remote any
  474. function SimpleSpy:ExcludeRemote(remote)
  475. assert(
  476. typeof(remote) == "Instance" or typeof(remote) == "string",
  477. "Instance | string expected, got " .. typeof(remote)
  478. )
  479. blacklist[remote] = true
  480. end
  481.  
  482. --- Creates a new ScriptSignal that can be connected to and fired
  483. --- @return table
  484. function newSignal()
  485. local connected = {}
  486. return {
  487. Connect = function(self, f)
  488. assert(connected, "Signal is closed")
  489. connected[tostring(f)] = f
  490. return {
  491. Connected = true,
  492. Disconnect = function(self)
  493. if not connected then
  494. warn("Signal is already closed")
  495. end
  496. self.Connected = false
  497. connected[tostring(f)] = nil
  498. end,
  499. }
  500. end,
  501. Wait = function(self)
  502. local thread = coroutine.running()
  503. local connection
  504. connection = self:Connect(function()
  505. connection:Disconnect()
  506. if coroutine.status(thread) == "suspended" then
  507. coroutine.resume(thread)
  508. end
  509. end)
  510. coroutine.yield()
  511. end,
  512. Fire = function(self, ...)
  513. for _, f in pairs(connected) do
  514. coroutine.wrap(f)(...)
  515. end
  516. end,
  517. }
  518. end
  519.  
  520. --- Prevents remote spam from causing lag (clears logs after `_G.SIMPLESPYCONFIG_MaxRemotes` or 500 remotes)
  521. function clean()
  522. local max = _G.SIMPLESPYCONFIG_MaxRemotes
  523. if not typeof(max) == "number" and math.floor(max) ~= max then
  524. max = 500
  525. end
  526. if #remoteLogs > max then
  527. for i = 100, #remoteLogs do
  528. local v = remoteLogs[i]
  529. if typeof(v[1]) == "RBXScriptConnection" then
  530. v[1]:Disconnect()
  531. end
  532. if typeof(v[2]) == "Instance" then
  533. v[2]:Destroy()
  534. end
  535. end
  536. local newLogs = {}
  537. for i = 1, 100 do
  538. table.insert(newLogs, remoteLogs[i])
  539. end
  540. remoteLogs = newLogs
  541. end
  542. end
  543.  
  544. --- Scales the ToolTip to fit containing text
  545. function scaleToolTip()
  546. local size = TextService:GetTextSize(
  547. TextLabel.Text,
  548. TextLabel.TextSize,
  549. TextLabel.Font,
  550. Vector2.new(196, math.huge)
  551. )
  552. TextLabel.Size = UDim2.new(0, size.X, 0, size.Y)
  553. ToolTip.Size = UDim2.new(0, size.X + 4, 0, size.Y + 4)
  554. end
  555.  
  556. --- Executed when the toggle button (the SimpleSpy logo) is hovered over
  557. function onToggleButtonHover()
  558. if not toggle then
  559. TweenService:Create(Simple, TweenInfo.new(0.5), { TextColor3 = Color3.fromRGB(252, 51, 51) }):Play()
  560. else
  561. TweenService:Create(Simple, TweenInfo.new(0.5), { TextColor3 = Color3.fromRGB(68, 206, 91) }):Play()
  562. end
  563. end
  564.  
  565. --- Executed when the toggle button is unhovered over
  566. function onToggleButtonUnhover()
  567. TweenService:Create(Simple, TweenInfo.new(0.5), { TextColor3 = Color3.fromRGB(255, 255, 255) }):Play()
  568. end
  569.  
  570. --- Executed when the X button is hovered over
  571. function onXButtonHover()
  572. TweenService:Create(CloseButton, TweenInfo.new(0.2), { BackgroundColor3 = Color3.fromRGB(255, 60, 60) }):Play()
  573. end
  574.  
  575. --- Executed when the X button is unhovered over
  576. function onXButtonUnhover()
  577. TweenService:Create(CloseButton, TweenInfo.new(0.2), { BackgroundColor3 = Color3.fromRGB(37, 36, 38) }):Play()
  578. end
  579.  
  580. --- Toggles the remote spy method (when button clicked)
  581. function onToggleButtonClick()
  582. if toggle then
  583. TweenService:Create(Simple, TweenInfo.new(0.5), { TextColor3 = Color3.fromRGB(252, 51, 51) }):Play()
  584. else
  585. TweenService:Create(Simple, TweenInfo.new(0.5), { TextColor3 = Color3.fromRGB(68, 206, 91) }):Play()
  586. end
  587. toggleSpyMethod()
  588. end
  589.  
  590. --- Reconnects bringBackOnResize if the current viewport changes and also connects it initially
  591. function connectResize()
  592. local lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
  593. workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
  594. lastCam:Disconnect()
  595. if workspace.CurrentCamera then
  596. lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
  597. end
  598. end)
  599. end
  600.  
  601. --- Brings gui back if it gets lost offscreen (connected to the camera viewport changing)
  602. function bringBackOnResize()
  603. validateSize()
  604. if sideClosed then
  605. minimizeSize()
  606. else
  607. maximizeSize()
  608. end
  609. local currentX = Background.AbsolutePosition.X
  610. local currentY = Background.AbsolutePosition.Y
  611. local viewportSize = workspace.CurrentCamera.ViewportSize
  612. if (currentX < 0) or (currentX > (viewportSize.X - (sideClosed and 131 or Background.AbsoluteSize.X))) then
  613. if currentX < 0 then
  614. currentX = 0
  615. else
  616. currentX = viewportSize.X - (sideClosed and 131 or Background.AbsoluteSize.X)
  617. end
  618. end
  619. if (currentY < 0) or (currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36)) then
  620. if currentY < 0 then
  621. currentY = 0
  622. else
  623. currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
  624. end
  625. end
  626. TweenService.Create(
  627. TweenService,
  628. Background,
  629. TweenInfo.new(0.1),
  630. { Position = UDim2.new(0, currentX, 0, currentY) }
  631. ):Play()
  632. end
  633.  
  634. --- Drags gui (so long as mouse is held down)
  635. --- @param input InputObject
  636. function onBarInput(input)
  637. if input.UserInputType == Enum.UserInputType.MouseButton1 then
  638. local lastPos = UserInputService.GetMouseLocation(UserInputService)
  639. local mainPos = Background.AbsolutePosition
  640. local offset = mainPos - lastPos
  641. local currentPos = offset + lastPos
  642. RunService.BindToRenderStep(RunService, "drag", 1, function()
  643. local newPos = UserInputService.GetMouseLocation(UserInputService)
  644. if newPos ~= lastPos then
  645. local currentX = (offset + newPos).X
  646. local currentY = (offset + newPos).Y
  647. local viewportSize = workspace.CurrentCamera.ViewportSize
  648. if
  649. (currentX < 0 and currentX < currentPos.X)
  650. or (
  651. currentX > (viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X))
  652. and currentX > currentPos.X
  653. )
  654. then
  655. if currentX < 0 then
  656. currentX = 0
  657. else
  658. currentX = viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)
  659. end
  660. end
  661. if
  662. (currentY < 0 and currentY < currentPos.Y)
  663. or (
  664. currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36)
  665. and currentY > currentPos.Y
  666. )
  667. then
  668. if currentY < 0 then
  669. currentY = 0
  670. else
  671. currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
  672. end
  673. end
  674. currentPos = Vector2.new(currentX, currentY)
  675. lastPos = newPos
  676. TweenService.Create(
  677. TweenService,
  678. Background,
  679. TweenInfo.new(0.1),
  680. { Position = UDim2.new(0, currentPos.X, 0, currentPos.Y) }
  681. ):Play()
  682. end
  683. -- if input.UserInputState ~= Enum.UserInputState.Begin then
  684. -- RunService.UnbindFromRenderStep(RunService, "drag")
  685. -- end
  686. end)
  687. table.insert(
  688. connections,
  689. UserInputService.InputEnded:Connect(function(inputE)
  690. if input == inputE then
  691. RunService:UnbindFromRenderStep("drag")
  692. end
  693. end)
  694. )
  695. end
  696. end
  697.  
  698. --- Fades out the table of elements (and makes them invisible), returns a function to make them visible again
  699. function fadeOut(elements)
  700. local data = {}
  701. for _, v in pairs(elements) do
  702. if typeof(v) == "Instance" and v:IsA("GuiObject") and v.Visible then
  703. coroutine.wrap(function()
  704. data[v] = {
  705. BackgroundTransparency = v.BackgroundTransparency,
  706. }
  707. TweenService:Create(v, TweenInfo.new(0.5), { BackgroundTransparency = 1 }):Play()
  708. if v:IsA("TextBox") or v:IsA("TextButton") or v:IsA("TextLabel") then
  709. data[v].TextTransparency = v.TextTransparency
  710. TweenService:Create(v, TweenInfo.new(0.5), { TextTransparency = 1 }):Play()
  711. elseif v:IsA("ImageButton") or v:IsA("ImageLabel") then
  712. data[v].ImageTransparency = v.ImageTransparency
  713. TweenService:Create(v, TweenInfo.new(0.5), { ImageTransparency = 1 }):Play()
  714. end
  715. wait(0.5)
  716. v.Visible = false
  717. for i, x in pairs(data[v]) do
  718. v[i] = x
  719. end
  720. data[v] = true
  721. end)()
  722. end
  723. end
  724. return function()
  725. for i, _ in pairs(data) do
  726. coroutine.wrap(function()
  727. local properties = {
  728. BackgroundTransparency = i.BackgroundTransparency,
  729. }
  730. i.BackgroundTransparency = 1
  731. TweenService
  732. :Create(i, TweenInfo.new(0.5), { BackgroundTransparency = properties.BackgroundTransparency })
  733. :Play()
  734. if i:IsA("TextBox") or i:IsA("TextButton") or i:IsA("TextLabel") then
  735. properties.TextTransparency = i.TextTransparency
  736. i.TextTransparency = 1
  737. TweenService
  738. :Create(i, TweenInfo.new(0.5), { TextTransparency = properties.TextTransparency })
  739. :Play()
  740. elseif i:IsA("ImageButton") or i:IsA("ImageLabel") then
  741. properties.ImageTransparency = i.ImageTransparency
  742. i.ImageTransparency = 1
  743. TweenService
  744. :Create(i, TweenInfo.new(0.5), { ImageTransparency = properties.ImageTransparency })
  745. :Play()
  746. end
  747. i.Visible = true
  748. end)()
  749. end
  750. end
  751. end
  752.  
  753. --- Expands and minimizes the gui (closed is the toggle boolean)
  754. function toggleMinimize(override)
  755. if mainClosing and not override or maximized then
  756. return
  757. end
  758. mainClosing = true
  759. closed = not closed
  760. if closed then
  761. if not sideClosed then
  762. toggleSideTray(true)
  763. end
  764. LeftPanel.Visible = true
  765. TweenService:Create(LeftPanel, TweenInfo.new(0.5), { Size = UDim2.new(0, 131, 0, 0) }):Play()
  766. wait(0.5)
  767. remotesFadeIn = fadeOut(LeftPanel:GetDescendants())
  768. wait(0.5)
  769. else
  770. TweenService:Create(LeftPanel, TweenInfo.new(0.5), { Size = UDim2.new(0, 131, 0, 249) }):Play()
  771. wait(0.5)
  772. if remotesFadeIn then
  773. remotesFadeIn()
  774. remotesFadeIn = nil
  775. end
  776. bringBackOnResize()
  777. end
  778. mainClosing = false
  779. end
  780.  
  781. --- Expands and minimizes the sidebar (sideClosed is the toggle boolean)
  782. function toggleSideTray(override)
  783. if sideClosing and not override or maximized then
  784. return
  785. end
  786. sideClosing = true
  787. sideClosed = not sideClosed
  788. if sideClosed then
  789. rightFadeIn = fadeOut(RightPanel:GetDescendants())
  790. wait(0.5)
  791. minimizeSize(0.5)
  792. wait(0.5)
  793. RightPanel.Visible = false
  794. else
  795. if closed then
  796. toggleMinimize(true)
  797. end
  798. RightPanel.Visible = true
  799. maximizeSize(0.5)
  800. wait(0.5)
  801. if rightFadeIn then
  802. rightFadeIn()
  803. end
  804. bringBackOnResize()
  805. end
  806. sideClosing = false
  807. end
  808.  
  809. --- Expands code box to fit screen for more convenient viewing
  810. function toggleMaximize()
  811. if not sideClosed and not maximized then
  812. maximized = true
  813. local disable = Instance.new("TextButton")
  814. local prevSize = UDim2.new(0, CodeBox.AbsoluteSize.X, 0, CodeBox.AbsoluteSize.Y)
  815. local prevPos = UDim2.new(0, CodeBox.AbsolutePosition.X, 0, CodeBox.AbsolutePosition.Y)
  816. disable.Size = UDim2.new(1, 0, 1, 0)
  817. disable.BackgroundColor3 = Color3.new()
  818. disable.BorderSizePixel = 0
  819. disable.Text = 0
  820. disable.ZIndex = 3
  821. disable.BackgroundTransparency = 1
  822. disable.AutoButtonColor = false
  823. CodeBox.ZIndex = 4
  824. CodeBox.Position = prevPos
  825. CodeBox.Size = prevSize
  826. TweenService
  827. :Create(
  828. CodeBox,
  829. TweenInfo.new(0.5),
  830. { Size = UDim2.new(0.5, 0, 0.5, 0), Position = UDim2.new(0.25, 0, 0.25, 0) }
  831. )
  832. :Play()
  833. TweenService:Create(disable, TweenInfo.new(0.5), { BackgroundTransparency = 0.5 }):Play()
  834. disable.MouseButton1Click:Connect(function()
  835. if
  836. UserInputService:GetMouseLocation().Y + 36 >= CodeBox.AbsolutePosition.Y
  837. and UserInputService:GetMouseLocation().Y + 36 <= CodeBox.AbsolutePosition.Y + CodeBox.AbsoluteSize.Y
  838. and UserInputService:GetMouseLocation().X >= CodeBox.AbsolutePosition.X
  839. and UserInputService:GetMouseLocation().X <= CodeBox.AbsolutePosition.X + CodeBox.AbsoluteSize.X
  840. then
  841. return
  842. end
  843. TweenService:Create(CodeBox, TweenInfo.new(0.5), { Size = prevSize, Position = prevPos }):Play()
  844. TweenService:Create(disable, TweenInfo.new(0.5), { BackgroundTransparency = 1 }):Play()
  845. maximized = false
  846. wait(0.5)
  847. disable:Destroy()
  848. CodeBox.Size = UDim2.new(1, 0, 0.5, 0)
  849. CodeBox.Position = UDim2.new(0, 0, 0, 0)
  850. CodeBox.ZIndex = 0
  851. end)
  852. end
  853. end
  854.  
  855. --- Checks if cursor is within resize range
  856. --- @param p Vector2
  857. function isInResizeRange(p)
  858. local relativeP = p - Background.AbsolutePosition
  859. local range = 5
  860. if
  861. relativeP.X >= TopBar.AbsoluteSize.X - range
  862. and relativeP.Y >= Background.AbsoluteSize.Y - range
  863. and relativeP.X <= TopBar.AbsoluteSize.X
  864. and relativeP.Y <= Background.AbsoluteSize.Y
  865. then
  866. return true, "B"
  867. elseif relativeP.X >= TopBar.AbsoluteSize.X - range and relativeP.X <= Background.AbsoluteSize.X then
  868. return true, "X"
  869. elseif relativeP.Y >= Background.AbsoluteSize.Y - range and relativeP.Y <= Background.AbsoluteSize.Y then
  870. return true, "Y"
  871. end
  872. return false
  873. end
  874.  
  875. --- Checks if cursor is within dragging range
  876. --- @param p Vector2
  877. function isInDragRange(p)
  878. local relativeP = p - Background.AbsolutePosition
  879. if
  880. relativeP.X <= TopBar.AbsoluteSize.X - CloseButton.AbsoluteSize.X * 3
  881. and relativeP.X >= 0
  882. and relativeP.Y <= TopBar.AbsoluteSize.Y
  883. and relativeP.Y >= 0
  884. then
  885. return true
  886. end
  887. return false
  888. end
  889.  
  890. --- Called when mouse enters SimpleSpy
  891. function mouseEntered()
  892. local existingCursor = SimpleSpy2:FindFirstChild("Cursor")
  893. while existingCursor do
  894. existingCursor:Destroy()
  895. existingCursor = SimpleSpy2:FindFirstChild("Cursor")
  896. end
  897. local customCursor = Instance.new("ImageLabel")
  898. customCursor.Name = "Cursor"
  899. customCursor.Size = UDim2.fromOffset(200, 200)
  900. customCursor.ZIndex = 1e5
  901. customCursor.BackgroundTransparency = 1
  902. customCursor.Image = ""
  903. customCursor.Parent = SimpleSpy2
  904. UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide
  905. RunService:BindToRenderStep("SIMPLESPY_CURSOR", 1, function()
  906. if mouseInGui and _G.SimpleSpyExecuted then
  907. local mouseLocation = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
  908. customCursor.Position = UDim2.fromOffset(
  909. mouseLocation.X - customCursor.AbsoluteSize.X / 2,
  910. mouseLocation.Y - customCursor.AbsoluteSize.Y / 2
  911. )
  912. local inRange, type = isInResizeRange(mouseLocation)
  913. if inRange and not sideClosed and not closed then
  914. customCursor.Image = type == "B" and "rbxassetid://6065821980"
  915. or type == "X" and "rbxassetid://6065821086"
  916. or type == "Y" and "rbxassetid://6065821596"
  917. elseif inRange and not closed and type == "Y" or type == "B" then
  918. customCursor.Image = "rbxassetid://6065821596"
  919. elseif customCursor.Image ~= "rbxassetid://6065775281" then
  920. customCursor.Image = "rbxassetid://6065775281"
  921. end
  922. else
  923. UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None
  924. customCursor:Destroy()
  925. RunService:UnbindFromRenderStep("SIMPLESPY_CURSOR")
  926. end
  927. end)
  928. end
  929.  
  930. --- Called when mouse moves
  931. function mouseMoved()
  932. local mousePos = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
  933. if
  934. not closed
  935. and mousePos.X >= TopBar.AbsolutePosition.X
  936. and mousePos.X <= TopBar.AbsolutePosition.X + TopBar.AbsoluteSize.X
  937. and mousePos.Y >= Background.AbsolutePosition.Y
  938. and mousePos.Y <= Background.AbsolutePosition.Y + Background.AbsoluteSize.Y
  939. then
  940. if not mouseInGui then
  941. mouseInGui = true
  942. mouseEntered()
  943. end
  944. else
  945. mouseInGui = false
  946. end
  947. end
  948.  
  949. --- Adjusts the ui elements to the 'Maximized' size
  950. function maximizeSize(speed)
  951. if not speed then
  952. speed = 0.05
  953. end
  954. TweenService
  955. :Create(
  956. LeftPanel,
  957. TweenInfo.new(speed),
  958. { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }
  959. )
  960. :Play()
  961. TweenService
  962. :Create(RightPanel, TweenInfo.new(speed), {
  963. Size = UDim2.fromOffset(
  964. Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X,
  965. Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y
  966. ),
  967. })
  968. :Play()
  969. TweenService
  970. :Create(
  971. TopBar,
  972. TweenInfo.new(speed),
  973. { Size = UDim2.fromOffset(Background.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }
  974. )
  975. :Play()
  976. TweenService
  977. :Create(ScrollingFrame, TweenInfo.new(speed), {
  978. Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, 110),
  979. Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y),
  980. })
  981. :Play()
  982. TweenService
  983. :Create(CodeBox, TweenInfo.new(speed), {
  984. Size = UDim2.fromOffset(
  985. Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X,
  986. Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y
  987. ),
  988. })
  989. :Play()
  990. TweenService
  991. :Create(
  992. LogList,
  993. TweenInfo.new(speed),
  994. { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }
  995. )
  996. :Play()
  997. end
  998.  
  999. --- Adjusts the ui elements to close the side
  1000. function minimizeSize(speed)
  1001. if not speed then
  1002. speed = 0.05
  1003. end
  1004. TweenService
  1005. :Create(
  1006. LeftPanel,
  1007. TweenInfo.new(speed),
  1008. { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }
  1009. )
  1010. :Play()
  1011. TweenService
  1012. :Create(
  1013. RightPanel,
  1014. TweenInfo.new(speed),
  1015. { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }
  1016. )
  1017. :Play()
  1018. TweenService
  1019. :Create(
  1020. TopBar,
  1021. TweenInfo.new(speed),
  1022. { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }
  1023. )
  1024. :Play()
  1025. TweenService
  1026. :Create(ScrollingFrame, TweenInfo.new(speed), {
  1027. Size = UDim2.fromOffset(0, 119),
  1028. Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y),
  1029. })
  1030. :Play()
  1031. TweenService
  1032. :Create(
  1033. CodeBox,
  1034. TweenInfo.new(speed),
  1035. { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }
  1036. )
  1037. :Play()
  1038. TweenService
  1039. :Create(
  1040. LogList,
  1041. TweenInfo.new(speed),
  1042. { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }
  1043. )
  1044. :Play()
  1045. end
  1046.  
  1047. --- Ensures size is within screensize limitations
  1048. function validateSize()
  1049. local x, y = Background.AbsoluteSize.X, Background.AbsoluteSize.Y
  1050. local screenSize = workspace.CurrentCamera.ViewportSize
  1051. if x + Background.AbsolutePosition.X > screenSize.X then
  1052. if screenSize.X - Background.AbsolutePosition.X >= 450 then
  1053. x = screenSize.X - Background.AbsolutePosition.X
  1054. else
  1055. x = 450
  1056. end
  1057. elseif y + Background.AbsolutePosition.Y > screenSize.Y then
  1058. if screenSize.X - Background.AbsolutePosition.Y >= 268 then
  1059. y = screenSize.Y - Background.AbsolutePosition.Y
  1060. else
  1061. y = 268
  1062. end
  1063. end
  1064. Background.Size = UDim2.fromOffset(x, y)
  1065. end
  1066.  
  1067. --- Called on user input while mouse in 'Background' frame
  1068. --- @param input InputObject
  1069. function backgroundUserInput(input)
  1070. local mousePos = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
  1071. local inResizeRange, type = isInResizeRange(mousePos)
  1072. if input.UserInputType == Enum.UserInputType.MouseButton1 and inResizeRange then
  1073. local lastPos = UserInputService:GetMouseLocation()
  1074. local offset = Background.AbsoluteSize - lastPos
  1075. local currentPos = lastPos + offset
  1076. RunService:BindToRenderStep("SIMPLESPY_RESIZE", 1, function()
  1077. local newPos = UserInputService:GetMouseLocation()
  1078. if newPos ~= lastPos then
  1079. local currentX = (newPos + offset).X
  1080. local currentY = (newPos + offset).Y
  1081. if currentX < 450 then
  1082. currentX = 450
  1083. end
  1084. if currentY < 268 then
  1085. currentY = 268
  1086. end
  1087. currentPos = Vector2.new(currentX, currentY)
  1088. Background.Size = UDim2.fromOffset(
  1089. (not sideClosed and not closed and (type == "X" or type == "B")) and currentPos.X
  1090. or Background.AbsoluteSize.X,
  1091. (--[[(not sideClosed or currentPos.X <= LeftPanel.AbsolutePosition.X + LeftPanel.AbsoluteSize.X) and]]not closed and (type == "Y" or type == "B"))
  1092. and currentPos.Y
  1093. or Background.AbsoluteSize.Y
  1094. )
  1095. validateSize()
  1096. if sideClosed then
  1097. minimizeSize()
  1098. else
  1099. maximizeSize()
  1100. end
  1101. lastPos = newPos
  1102. end
  1103. end)
  1104. table.insert(
  1105. connections,
  1106. UserInputService.InputEnded:Connect(function(inputE)
  1107. if input == inputE then
  1108. RunService:UnbindFromRenderStep("SIMPLESPY_RESIZE")
  1109. end
  1110. end)
  1111. )
  1112. elseif isInDragRange(mousePos) then
  1113. onBarInput(input)
  1114. end
  1115. end
  1116.  
  1117. --- Gets the player an instance is descended from
  1118. function getPlayerFromInstance(instance)
  1119. for _, v in pairs(Players:GetPlayers()) do
  1120. if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
  1121. return v
  1122. end
  1123. end
  1124. end
  1125.  
  1126. --- Runs on MouseButton1Click of an event frame
  1127. function eventSelect(frame)
  1128. if selected and selected.Log and selected.Log.Button then
  1129. TweenService
  1130. :Create(selected.Log.Button, TweenInfo.new(0.5), { BackgroundColor3 = Color3.fromRGB(0, 0, 0) })
  1131. :Play()
  1132. selected = nil
  1133. end
  1134. for _, v in pairs(logs) do
  1135. if frame == v.Log then
  1136. selected = v
  1137. end
  1138. end
  1139. if selected and selected.Log then
  1140. TweenService
  1141. :Create(frame.Button, TweenInfo.new(0.5), { BackgroundColor3 = Color3.fromRGB(92, 126, 229) })
  1142. :Play()
  1143. codebox:setRaw(selected.GenScript)
  1144. end
  1145. if sideClosed then
  1146. toggleSideTray()
  1147. end
  1148. end
  1149.  
  1150. --- Updates the canvas size to fit the current amount of function buttons
  1151. function updateFunctionCanvas()
  1152. ScrollingFrame.CanvasSize = UDim2.fromOffset(UIGridLayout.AbsoluteContentSize.X, UIGridLayout.AbsoluteContentSize.Y)
  1153. end
  1154.  
  1155. --- Updates the canvas size to fit the amount of current remotes
  1156. function updateRemoteCanvas()
  1157. LogList.CanvasSize = UDim2.fromOffset(UIListLayout.AbsoluteContentSize.X, UIListLayout.AbsoluteContentSize.Y)
  1158. end
  1159.  
  1160. --- Allows for toggling of the tooltip and easy setting of le description
  1161. --- @param enable boolean
  1162. --- @param text string
  1163. function makeToolTip(enable, text)
  1164. if enable then
  1165. if ToolTip.Visible then
  1166. ToolTip.Visible = false
  1167. RunService:UnbindFromRenderStep("ToolTip")
  1168. end
  1169. local first = true
  1170. RunService:BindToRenderStep("ToolTip", 1, function()
  1171. local topLeft = Vector2.new(Mouse.X + 20, Mouse.Y + 20)
  1172. local bottomRight = topLeft + ToolTip.AbsoluteSize
  1173. if topLeft.X < 0 then
  1174. topLeft = Vector2.new(0, topLeft.Y)
  1175. elseif bottomRight.X > workspace.CurrentCamera.ViewportSize.X then
  1176. topLeft = Vector2.new(workspace.CurrentCamera.ViewportSize.X - ToolTip.AbsoluteSize.X, topLeft.Y)
  1177. end
  1178. if topLeft.Y < 0 then
  1179. topLeft = Vector2.new(topLeft.X, 0)
  1180. elseif bottomRight.Y > workspace.CurrentCamera.ViewportSize.Y - 35 then
  1181. topLeft = Vector2.new(topLeft.X, workspace.CurrentCamera.ViewportSize.Y - ToolTip.AbsoluteSize.Y - 35)
  1182. end
  1183. if topLeft.X <= Mouse.X and topLeft.Y <= Mouse.Y then
  1184. topLeft = Vector2.new(Mouse.X - ToolTip.AbsoluteSize.X - 2, Mouse.Y - ToolTip.AbsoluteSize.Y - 2)
  1185. end
  1186. if first then
  1187. ToolTip.Position = UDim2.fromOffset(topLeft.X, topLeft.Y)
  1188. first = false
  1189. else
  1190. ToolTip:TweenPosition(UDim2.fromOffset(topLeft.X, topLeft.Y), "Out", "Linear", 0.1)
  1191. end
  1192. end)
  1193. TextLabel.Text = text
  1194. ToolTip.Visible = true
  1195. else
  1196. if ToolTip.Visible then
  1197. ToolTip.Visible = false
  1198. RunService:UnbindFromRenderStep("ToolTip")
  1199. end
  1200. end
  1201. end
  1202.  
  1203. --- Creates new function button (below codebox)
  1204. --- @param name string
  1205. ---@param description function
  1206. ---@param onClick function
  1207. function newButton(name, description, onClick)
  1208. local button = FunctionTemplate:Clone()
  1209. button.Text.Text = name
  1210. button.Button.MouseEnter:Connect(function()
  1211. makeToolTip(true, description())
  1212. end)
  1213. button.Button.MouseLeave:Connect(function()
  1214. makeToolTip(false)
  1215. end)
  1216. button.AncestryChanged:Connect(function()
  1217. makeToolTip(false)
  1218. end)
  1219. button.Button.MouseButton1Click:Connect(function(...)
  1220. onClick(button, ...)
  1221. end)
  1222. button.Parent = ScrollingFrame
  1223. updateFunctionCanvas()
  1224. end
  1225.  
  1226. --- Adds new Remote to logs
  1227. --- @param name string The name of the remote being logged
  1228. --- @param type string The type of the remote being logged (either 'function' or 'event')
  1229. --- @param args any
  1230. --- @param remote any
  1231. --- @param function_info string
  1232. --- @param blocked any
  1233. function newRemote(type, name, args, remote, function_info, blocked, src, returnValue)
  1234. local remoteFrame = RemoteTemplate:Clone()
  1235. remoteFrame.Text.Text = string.sub(name, 1, 50)
  1236. remoteFrame.ColorBar.BackgroundColor3 = type == "event" and Color3.new(255, 242, 0) or Color3.fromRGB(99, 86, 245)
  1237. local id = Instance.new("IntValue")
  1238. id.Name = "ID"
  1239. id.Value = #logs + 1
  1240. id.Parent = remoteFrame
  1241. local weakRemoteTable = setmetatable({ remote = remote }, { __mode = "v" })
  1242. local log = {
  1243. Name = name,
  1244. Function = function_info,
  1245. Remote = weakRemoteTable,
  1246. Log = remoteFrame,
  1247. Blocked = blocked,
  1248. Source = src,
  1249. GenScript = "-- Generating, please wait... (click to reload)\n-- (If this message persists, the remote args are likely extremely long)",
  1250. ReturnValue = returnValue,
  1251. }
  1252. logs[#logs + 1] = log
  1253. schedule(function()
  1254. log.GenScript = genScript(remote, args)
  1255. if blocked then
  1256. logs[#logs].GenScript = "-- THIS REMOTE WAS PREVENTED FROM FIRING THE SERVER BY SIMPLESPY\n\n"
  1257. .. logs[#logs].GenScript
  1258. end
  1259. end)
  1260. local connect = remoteFrame.Button.MouseButton1Click:Connect(function()
  1261. eventSelect(remoteFrame)
  1262. end)
  1263. if layoutOrderNum < 1 then
  1264. layoutOrderNum = 999999999
  1265. end
  1266. remoteFrame.LayoutOrder = layoutOrderNum
  1267. layoutOrderNum = layoutOrderNum - 1
  1268. remoteFrame.Parent = LogList
  1269. table.insert(remoteLogs, 1, { connect, remoteFrame })
  1270. clean()
  1271. updateRemoteCanvas()
  1272. end
  1273.  
  1274. --- Generates a script from the provided arguments (first has to be remote path)
  1275. function genScript(remote, args)
  1276. prevTables = {}
  1277. local gen = ""
  1278. if #args > 0 then
  1279. if not pcall(function()
  1280. gen = v2v({ args = args }) .. "\n"
  1281. end) then
  1282. gen = gen
  1283. .. "-- TableToString failure! Reverting to legacy functionality (results may vary)\nlocal args = {"
  1284. if
  1285. not pcall(function()
  1286. for i, v in pairs(args) do
  1287. if type(i) ~= "Instance" and type(i) ~= "userdata" then
  1288. gen = gen .. "\n [object] = "
  1289. elseif type(i) == "string" then
  1290. gen = gen .. '\n ["' .. i .. '"] = '
  1291. elseif type(i) == "userdata" and typeof(i) ~= "Instance" then
  1292. gen = gen .. "\n [" .. string.format("nil --[[%s]]", typeof(v)) .. ")] = "
  1293. elseif type(i) == "userdata" then
  1294. gen = gen .. "\n [game." .. i:GetFullName() .. ")] = "
  1295. end
  1296. if type(v) ~= "Instance" and type(v) ~= "userdata" then
  1297. gen = gen .. "object"
  1298. elseif type(v) == "string" then
  1299. gen = gen .. '"' .. v .. '"'
  1300. elseif type(v) == "userdata" and typeof(v) ~= "Instance" then
  1301. gen = gen .. string.format("nil --[[%s]]", typeof(v))
  1302. elseif type(v) == "userdata" then
  1303. gen = gen .. "game." .. v:GetFullName()
  1304. end
  1305. end
  1306. gen = gen .. "\n}\n\n"
  1307. end)
  1308. then
  1309. gen = gen .. "}\n-- Legacy tableToString failure! Unable to decompile."
  1310. end
  1311. end
  1312. if not remote:IsDescendantOf(game) and not getnilrequired then
  1313. gen = "function getNil(name,class) for _,v in pairs(getnilinstances())do if v.ClassName==class and v.Name==name then return v;end end end\n\n"
  1314. .. gen
  1315. end
  1316. if remote:IsA("RemoteEvent") then
  1317. gen = gen .. v2s(remote) .. ":FireServer(unpack(args))"
  1318. elseif remote:IsA("RemoteFunction") then
  1319. gen = gen .. v2s(remote) .. ":InvokeServer(unpack(args))"
  1320. end
  1321. else
  1322. if remote:IsA("RemoteEvent") then
  1323. gen = gen .. v2s(remote) .. ":FireServer()"
  1324. elseif remote:IsA("RemoteFunction") then
  1325. gen = gen .. v2s(remote) .. ":InvokeServer()"
  1326. end
  1327. end
  1328. gen = "-- Script generated by SimpleSpy - credits to exx#9394\n\n" .. gen
  1329. prevTables = {}
  1330. return gen
  1331. end
  1332.  
  1333. --- value-to-string: value, string (out), level (indentation), parent table, var name, is from tovar
  1334. function v2s(v, l, p, n, vtv, i, pt, path, tables, tI)
  1335. if not tI then
  1336. tI = { 0 }
  1337. else
  1338. tI[1] += 1
  1339. end
  1340. if typeof(v) == "number" then
  1341. if v == math.huge then
  1342. return "math.huge"
  1343. elseif tostring(v):match("nan") then
  1344. return "0/0 --[[NaN]]"
  1345. end
  1346. return tostring(v)
  1347. elseif typeof(v) == "boolean" then
  1348. return tostring(v)
  1349. elseif typeof(v) == "string" then
  1350. return formatstr(v, l)
  1351. elseif typeof(v) == "function" then
  1352. return f2s(v)
  1353. elseif typeof(v) == "table" then
  1354. return t2s(v, l, p, n, vtv, i, pt, path, tables, tI)
  1355. elseif typeof(v) == "Instance" then
  1356. return i2p(v)
  1357. elseif typeof(v) == "userdata" then
  1358. return "newproxy(true)"
  1359. elseif type(v) == "userdata" then
  1360. return u2s(v)
  1361. elseif type(v) == "vector" then
  1362. return string.format("Vector3.new(%s, %s, %s)", v2s(v.X), v2s(v.Y), v2s(v.Z))
  1363. else
  1364. return "nil --[[" .. typeof(v) .. "]]"
  1365. end
  1366. end
  1367.  
  1368. --- value-to-variable
  1369. --- @param t any
  1370. function v2v(t)
  1371. topstr = ""
  1372. bottomstr = ""
  1373. getnilrequired = false
  1374. local ret = ""
  1375. local count = 1
  1376. for i, v in pairs(t) do
  1377. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1378. ret = ret .. "local " .. i .. " = " .. v2s(v, nil, nil, i, true) .. "\n"
  1379. elseif tostring(i):match("^[%a_]+[%w_]*$") then
  1380. ret = ret
  1381. .. "local "
  1382. .. tostring(i):lower()
  1383. .. "_"
  1384. .. tostring(count)
  1385. .. " = "
  1386. .. v2s(v, nil, nil, tostring(i):lower() .. "_" .. tostring(count), true)
  1387. .. "\n"
  1388. else
  1389. ret = ret
  1390. .. "local "
  1391. .. type(v)
  1392. .. "_"
  1393. .. tostring(count)
  1394. .. " = "
  1395. .. v2s(v, nil, nil, type(v) .. "_" .. tostring(count), true)
  1396. .. "\n"
  1397. end
  1398. count = count + 1
  1399. end
  1400. if getnilrequired then
  1401. topstr = "function getNil(name,class) for _,v in pairs(getnilinstances())do if v.ClassName==class and v.Name==name then return v;end end end\n"
  1402. .. topstr
  1403. end
  1404. if #topstr > 0 then
  1405. ret = topstr .. "\n" .. ret
  1406. end
  1407. if #bottomstr > 0 then
  1408. ret = ret .. bottomstr
  1409. end
  1410. return ret
  1411. end
  1412.  
  1413. --- table-to-string
  1414. --- @param t table
  1415. --- @param l number
  1416. --- @param p table
  1417. --- @param n string
  1418. --- @param vtv boolean
  1419. --- @param i any
  1420. --- @param pt table
  1421. --- @param path string
  1422. --- @param tables table
  1423. --- @param tI table
  1424. function t2s(t, l, p, n, vtv, i, pt, path, tables, tI)
  1425. local globalIndex = table.find(getgenv(), t) -- checks if table is a global
  1426. if type(globalIndex) == "string" then
  1427. return globalIndex
  1428. end
  1429. if not tI then
  1430. tI = { 0 }
  1431. end
  1432. if not path then -- sets path to empty string (so it doesn't have to manually provided every time)
  1433. path = ""
  1434. end
  1435. if not l then -- sets the level to 0 (for indentation) and tables for logging tables it already serialized
  1436. l = 0
  1437. tables = {}
  1438. end
  1439. if not p then -- p is the previous table but doesn't really matter if it's the first
  1440. p = t
  1441. end
  1442. for _, v in pairs(tables) do -- checks if the current table has been serialized before
  1443. if n and rawequal(v, t) then
  1444. bottomstr = bottomstr
  1445. .. "\n"
  1446. .. tostring(n)
  1447. .. tostring(path)
  1448. .. " = "
  1449. .. tostring(n)
  1450. .. tostring(({ v2p(v, p) })[2])
  1451. return "{} --[[DUPLICATE]]"
  1452. end
  1453. end
  1454. table.insert(tables, t) -- logs table to past tables
  1455. local s = "{" -- start of serialization
  1456. local size = 0
  1457. l = l + indent -- set indentation level
  1458. for k, v in pairs(t) do -- iterates over table
  1459. size = size + 1 -- changes size for max limit
  1460. if size > (_G.SimpleSpyMaxTableSize or 1000) then
  1461. s = s
  1462. .. "\n"
  1463. .. string.rep(" ", l)
  1464. .. "-- MAXIMUM TABLE SIZE REACHED, CHANGE '_G.SimpleSpyMaxTableSize' TO ADJUST MAXIMUM SIZE "
  1465. break
  1466. end
  1467. if rawequal(k, t) then -- checks if the table being iterated over is being used as an index within itself (yay, lua)
  1468. bottomstr = bottomstr
  1469. .. "\n"
  1470. .. tostring(n)
  1471. .. tostring(path)
  1472. .. "["
  1473. .. tostring(n)
  1474. .. tostring(path)
  1475. .. "]"
  1476. .. " = "
  1477. .. (
  1478. rawequal(v, k) and tostring(n) .. tostring(path)
  1479. or v2s(v, l, p, n, vtv, k, t, path .. "[" .. tostring(n) .. tostring(path) .. "]", tables)
  1480. )
  1481. size -= 1
  1482. continue
  1483. end
  1484. local currentPath = "" -- initializes the path of 'v' within 't'
  1485. if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then -- cleanly handles table path generation (for the first half)
  1486. currentPath = "." .. k
  1487. else
  1488. currentPath = "[" .. k2s(k, l, p, n, vtv, k, t, path .. currentPath, tables, tI) .. "]"
  1489. end
  1490. if size % 100 == 0 then
  1491. scheduleWait()
  1492. end
  1493. -- actually serializes the member of the table
  1494. s = s
  1495. .. "\n"
  1496. .. string.rep(" ", l)
  1497. .. "["
  1498. .. k2s(k, l, p, n, vtv, k, t, path .. currentPath, tables, tI)
  1499. .. "] = "
  1500. .. v2s(v, l, p, n, vtv, k, t, path .. currentPath, tables, tI)
  1501. .. ","
  1502. end
  1503. if #s > 1 then -- removes the last comma because it looks nicer (no way to tell if it's done 'till it's done so...)
  1504. s = s:sub(1, #s - 1)
  1505. end
  1506. if size > 0 then -- cleanly indents the last curly bracket
  1507. s = s .. "\n" .. string.rep(" ", l - indent)
  1508. end
  1509. return s .. "}"
  1510. end
  1511.  
  1512. --- key-to-string
  1513. function k2s(v, ...)
  1514. if keyToString then
  1515. if typeof(v) == "userdata" and getrawmetatable(v) then
  1516. return string.format(
  1517. '"<void> (%s)" --[[Potentially hidden data (tostring in SimpleSpy:HookRemote/GetRemoteFiredSignal at your own risk)]]',
  1518. safetostring(v)
  1519. )
  1520. elseif typeof(v) == "userdata" then
  1521. return string.format('"<void> (%s)"', safetostring(v))
  1522. elseif type(v) == "userdata" and typeof(v) ~= "Instance" then
  1523. return string.format('"<%s> (%s)"', typeof(v), tostring(v))
  1524. elseif type(v) == "function" then
  1525. return string.format('"<Function> (%s)"', tostring(v))
  1526. end
  1527. end
  1528. return v2s(v, ...)
  1529. end
  1530.  
  1531. --- function-to-string
  1532. function f2s(f)
  1533. for k, x in pairs(getgenv()) do
  1534. local isgucci, gpath
  1535. if rawequal(x, f) then
  1536. isgucci, gpath = true, ""
  1537. elseif type(x) == "table" then
  1538. isgucci, gpath = v2p(f, x)
  1539. end
  1540. if isgucci and type(k) ~= "function" then
  1541. if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
  1542. return k .. gpath
  1543. else
  1544. return "getgenv()[" .. v2s(k) .. "]" .. gpath
  1545. end
  1546. end
  1547. end
  1548. if funcEnabled and debug.getinfo(f).name:match("^[%a_]+[%w_]*$") then
  1549. return "function()end --[[" .. debug.getinfo(f).name .. "]]"
  1550. end
  1551. return "function()end --[[" .. tostring(f) .. "]]"
  1552. end
  1553.  
  1554. --- instance-to-path
  1555. --- @param i userdata
  1556. function i2p(i)
  1557. local player = getplayer(i)
  1558. local parent = i
  1559. local out = ""
  1560. if parent == nil then
  1561. return "nil"
  1562. elseif player then
  1563. while true do
  1564. if parent and parent == player.Character then
  1565. if player == Players.LocalPlayer then
  1566. return 'game:GetService("Players").LocalPlayer.Character' .. out
  1567. else
  1568. return i2p(player) .. ".Character" .. out
  1569. end
  1570. else
  1571. if parent.Name:match("[%a_]+[%w+]*") ~= parent.Name then
  1572. out = ":FindFirstChild(" .. formatstr(parent.Name) .. ")" .. out
  1573. else
  1574. out = "." .. parent.Name .. out
  1575. end
  1576. end
  1577. parent = parent.Parent
  1578. end
  1579. elseif parent ~= game then
  1580. while true do
  1581. if parent and parent.Parent == game then
  1582. local service = game:FindService(parent.ClassName)
  1583. if service then
  1584. if parent.ClassName == "Workspace" then
  1585. return "workspace" .. out
  1586. else
  1587. return 'game:GetService("' .. service.ClassName .. '")' .. out
  1588. end
  1589. else
  1590. if parent.Name:match("[%a_]+[%w_]*") then
  1591. return "game." .. parent.Name .. out
  1592. else
  1593. return "game:FindFirstChild(" .. formatstr(parent.Name) .. ")" .. out
  1594. end
  1595. end
  1596. elseif parent.Parent == nil then
  1597. getnilrequired = true
  1598. return "getNil(" .. formatstr(parent.Name) .. ', "' .. parent.ClassName .. '")' .. out
  1599. elseif parent == Players.LocalPlayer then
  1600. out = ".LocalPlayer" .. out
  1601. else
  1602. if parent.Name:match("[%a_]+[%w_]*") ~= parent.Name then
  1603. out = ":FindFirstChild(" .. formatstr(parent.Name) .. ")" .. out
  1604. else
  1605. out = "." .. parent.Name .. out
  1606. end
  1607. end
  1608. parent = parent.Parent
  1609. end
  1610. else
  1611. return "game"
  1612. end
  1613. end
  1614.  
  1615. --- userdata-to-string: userdata
  1616. --- @param u userdata
  1617. function u2s(u)
  1618. if typeof(u) == "TweenInfo" then
  1619. -- TweenInfo
  1620. return "TweenInfo.new("
  1621. .. tostring(u.Time)
  1622. .. ", Enum.EasingStyle."
  1623. .. tostring(u.EasingStyle)
  1624. .. ", Enum.EasingDirection."
  1625. .. tostring(u.EasingDirection)
  1626. .. ", "
  1627. .. tostring(u.RepeatCount)
  1628. .. ", "
  1629. .. tostring(u.Reverses)
  1630. .. ", "
  1631. .. tostring(u.DelayTime)
  1632. .. ")"
  1633. elseif typeof(u) == "Ray" then
  1634. -- Ray
  1635. return "Ray.new(" .. u2s(u.Origin) .. ", " .. u2s(u.Direction) .. ")"
  1636. elseif typeof(u) == "NumberSequence" then
  1637. -- NumberSequence
  1638. local ret = "NumberSequence.new("
  1639. for i, v in pairs(u.KeyPoints) do
  1640. ret = ret .. tostring(v)
  1641. if i < #u.Keypoints then
  1642. ret = ret .. ", "
  1643. end
  1644. end
  1645. return ret .. ")"
  1646. elseif typeof(u) == "DockWidgetPluginGuiInfo" then
  1647. -- DockWidgetPluginGuiInfo
  1648. return "DockWidgetPluginGuiInfo.new(Enum.InitialDockState" .. tostring(u) .. ")"
  1649. elseif typeof(u) == "ColorSequence" then
  1650. -- ColorSequence
  1651. local ret = "ColorSequence.new("
  1652. for i, v in pairs(u.KeyPoints) do
  1653. ret = ret .. "Color3.new(" .. tostring(v) .. ")"
  1654. if i < #u.Keypoints then
  1655. ret = ret .. ", "
  1656. end
  1657. end
  1658. return ret .. ")"
  1659. elseif typeof(u) == "BrickColor" then
  1660. -- BrickColor
  1661. return "BrickColor.new(" .. tostring(u.Number) .. ")"
  1662. elseif typeof(u) == "NumberRange" then
  1663. -- NumberRange
  1664. return "NumberRange.new(" .. tostring(u.Min) .. ", " .. tostring(u.Max) .. ")"
  1665. elseif typeof(u) == "Region3" then
  1666. -- Region3
  1667. local center = u.CFrame.Position
  1668. local size = u.CFrame.Size
  1669. local vector1 = center - size / 2
  1670. local vector2 = center + size / 2
  1671. return "Region3.new(" .. u2s(vector1) .. ", " .. u2s(vector2) .. ")"
  1672. elseif typeof(u) == "Faces" then
  1673. -- Faces
  1674. local faces = {}
  1675. if u.Top then
  1676. table.insert(faces, "Enum.NormalId.Top")
  1677. end
  1678. if u.Bottom then
  1679. table.insert(faces, "Enum.NormalId.Bottom")
  1680. end
  1681. if u.Left then
  1682. table.insert(faces, "Enum.NormalId.Left")
  1683. end
  1684. if u.Right then
  1685. table.insert(faces, "Enum.NormalId.Right")
  1686. end
  1687. if u.Back then
  1688. table.insert(faces, "Enum.NormalId.Back")
  1689. end
  1690. if u.Front then
  1691. table.insert(faces, "Enum.NormalId.Front")
  1692. end
  1693. return "Faces.new(" .. table.concat(faces, ", ") .. ")"
  1694. elseif typeof(u) == "EnumItem" then
  1695. return tostring(u)
  1696. elseif typeof(u) == "Enums" then
  1697. return "Enum"
  1698. elseif typeof(u) == "Enum" then
  1699. return "Enum." .. tostring(u)
  1700. elseif typeof(u) == "RBXScriptSignal" then
  1701. return "nil --[[RBXScriptSignal]]"
  1702. elseif typeof(u) == "Vector3" then
  1703. return string.format("Vector3.new(%s, %s, %s)", v2s(u.X), v2s(u.Y), v2s(u.Z))
  1704. elseif typeof(u) == "CFrame" then
  1705. local xAngle, yAngle, zAngle = u:ToEulerAnglesXYZ()
  1706. return string.format(
  1707. "CFrame.new(%s, %s, %s) * CFrame.Angles(%s, %s, %s)",
  1708. v2s(u.X),
  1709. v2s(u.Y),
  1710. v2s(u.Z),
  1711. v2s(xAngle),
  1712. v2s(yAngle),
  1713. v2s(zAngle)
  1714. )
  1715. elseif typeof(u) == "DockWidgetPluginGuiInfo" then
  1716. return string.format(
  1717. "DockWidgetPluginGuiInfo(%s, %s, %s, %s, %s, %s, %s)",
  1718. "Enum.InitialDockState.Right",
  1719. v2s(u.InitialEnabled),
  1720. v2s(u.InitialEnabledShouldOverrideRestore),
  1721. v2s(u.FloatingXSize),
  1722. v2s(u.FloatingYSize),
  1723. v2s(u.MinWidth),
  1724. v2s(u.MinHeight)
  1725. )
  1726. elseif typeof(u) == "PathWaypoint" then
  1727. return string.format("PathWaypoint.new(%s, %s)", v2s(u.Position), v2s(u.Action))
  1728. elseif typeof(u) == "UDim" then
  1729. return string.format("UDim.new(%s, %s)", v2s(u.Scale), v2s(u.Offset))
  1730. elseif typeof(u) == "UDim2" then
  1731. return string.format(
  1732. "UDim2.new(%s, %s, %s, %s)",
  1733. v2s(u.X.Scale),
  1734. v2s(u.X.Offset),
  1735. v2s(u.Y.Scale),
  1736. v2s(u.Y.Offset)
  1737. )
  1738. elseif typeof(u) == "Rect" then
  1739. return string.format("Rect.new(%s, %s)", v2s(u.Min), v2s(u.Max))
  1740. else
  1741. return string.format("nil --[[%s]]", typeof(u))
  1742. end
  1743. end
  1744.  
  1745. --- Gets the player an instance is descended from
  1746. function getplayer(instance)
  1747. for _, v in pairs(Players:GetPlayers()) do
  1748. if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
  1749. return v
  1750. end
  1751. end
  1752. end
  1753.  
  1754. --- value-to-path (in table)
  1755. function v2p(x, t, path, prev)
  1756. if not path then
  1757. path = ""
  1758. end
  1759. if not prev then
  1760. prev = {}
  1761. end
  1762. if rawequal(x, t) then
  1763. return true, ""
  1764. end
  1765. for i, v in pairs(t) do
  1766. if rawequal(v, x) then
  1767. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1768. return true, (path .. "." .. i)
  1769. else
  1770. return true, (path .. "[" .. v2s(i) .. "]")
  1771. end
  1772. end
  1773. if type(v) == "table" then
  1774. local duplicate = false
  1775. for _, y in pairs(prev) do
  1776. if rawequal(y, v) then
  1777. duplicate = true
  1778. end
  1779. end
  1780. if not duplicate then
  1781. table.insert(prev, t)
  1782. local found
  1783. found, p = v2p(x, v, path, prev)
  1784. if found then
  1785. if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
  1786. return true, "." .. i .. p
  1787. else
  1788. return true, "[" .. v2s(i) .. "]" .. p
  1789. end
  1790. end
  1791. end
  1792. end
  1793. end
  1794. return false, ""
  1795. end
  1796.  
  1797. --- format s: string, byte encrypt (for weird symbols)
  1798. function formatstr(s, indentation)
  1799. if not indentation then
  1800. indentation = 0
  1801. end
  1802. local handled, reachedMax = handlespecials(s, indentation)
  1803. return '"'
  1804. .. handled
  1805. .. '"'
  1806. .. (
  1807. reachedMax
  1808. and " --[[ MAXIMUM STRING SIZE REACHED, CHANGE '_G.SimpleSpyMaxStringSize' TO ADJUST MAXIMUM SIZE ]]"
  1809. or ""
  1810. )
  1811. end
  1812.  
  1813. --- Adds \'s to the text as a replacement to whitespace chars and other things because string.format can't yayeet
  1814. function handlespecials(value, indentation)
  1815. local buildStr = {}
  1816. local i = 1
  1817. local char = string.sub(value, i, i)
  1818. local indentStr
  1819. while char ~= "" do
  1820. if char == '"' then
  1821. buildStr[i] = '\\"'
  1822. elseif char == "\\" then
  1823. buildStr[i] = "\\\\"
  1824. elseif char == "\n" then
  1825. buildStr[i] = "\\n"
  1826. elseif char == "\t" then
  1827. buildStr[i] = "\\t"
  1828. elseif string.byte(char) > 126 or string.byte(char) < 32 then
  1829. buildStr[i] = string.format("\\%d", string.byte(char))
  1830. else
  1831. buildStr[i] = char
  1832. end
  1833. i = i + 1
  1834. char = string.sub(value, i, i)
  1835. if i % 200 == 0 then
  1836. indentStr = indentStr or string.rep(" ", indentation + indent)
  1837. table.move({ '"\n', indentStr, '... "' }, 1, 3, i, buildStr)
  1838. i += 3
  1839. end
  1840. end
  1841. return table.concat(buildStr)
  1842. end
  1843.  
  1844. -- safe (ish) tostring
  1845. function safetostring(v: any)
  1846. if typeof(v) == "userdata" or type(v) == "table" then
  1847. local mt = getrawmetatable(v)
  1848. local badtostring = mt and rawget(mt, "__tostring")
  1849. if mt and badtostring then
  1850. rawset(mt, "__tostring", nil)
  1851. local out = tostring(v)
  1852. rawset(mt, "__tostring", badtostring)
  1853. return out
  1854. end
  1855. end
  1856. return tostring(v)
  1857. end
  1858.  
  1859. --- finds script from 'src' from getinfo, returns nil if not found
  1860. --- @param src string
  1861. function getScriptFromSrc(src)
  1862. local realPath
  1863. local runningTest
  1864. --- @type number
  1865. local s, e
  1866. local match = false
  1867. if src:sub(1, 1) == "=" then
  1868. realPath = game
  1869. s = 2
  1870. else
  1871. runningTest = src:sub(2, e and e - 1 or -1)
  1872. for _, v in pairs(getnilinstances()) do
  1873. if v.Name == runningTest then
  1874. realPath = v
  1875. break
  1876. end
  1877. end
  1878. s = #runningTest + 1
  1879. end
  1880. if realPath then
  1881. e = src:sub(s, -1):find("%.")
  1882. local i = 0
  1883. repeat
  1884. i += 1
  1885. if not e then
  1886. runningTest = src:sub(s, -1)
  1887. local test = realPath.FindFirstChild(realPath, runningTest)
  1888. if test then
  1889. realPath = test
  1890. end
  1891. match = true
  1892. else
  1893. runningTest = src:sub(s, e)
  1894. local test = realPath.FindFirstChild(realPath, runningTest)
  1895. local yeOld = e
  1896. if test then
  1897. realPath = test
  1898. s = e + 2
  1899. e = src:sub(e + 2, -1):find("%.")
  1900. e = e and e + yeOld or e
  1901. else
  1902. e = src:sub(e + 2, -1):find("%.")
  1903. e = e and e + yeOld or e
  1904. end
  1905. end
  1906. until match or i >= 50
  1907. end
  1908. return realPath
  1909. end
  1910.  
  1911. --- schedules the provided function (and calls it with any args after)
  1912. function schedule(f, ...)
  1913. table.insert(scheduled, { f, ... })
  1914. end
  1915.  
  1916. --- yields the current thread until the scheduler gives the ok
  1917. function scheduleWait()
  1918. local thread = coroutine.running()
  1919. schedule(function()
  1920. coroutine.resume(thread)
  1921. end)
  1922. coroutine.yield()
  1923. end
  1924.  
  1925. --- the big (well tbh small now) boi task scheduler himself, handles p much anything as quicc as possible
  1926. function taskscheduler()
  1927. if not toggle then
  1928. scheduled = {}
  1929. return
  1930. end
  1931. if #scheduled > 1000 then
  1932. table.remove(scheduled, #scheduled)
  1933. end
  1934. if #scheduled > 0 then
  1935. local currentf = scheduled[1]
  1936. table.remove(scheduled, 1)
  1937. if type(currentf) == "table" and type(currentf[1]) == "function" then
  1938. pcall(unpack(currentf))
  1939. end
  1940. end
  1941. end
  1942.  
  1943. --- Handles remote logs
  1944. function remoteHandler(hookfunction, methodName, remote, args, funcInfo, calling, returnValue)
  1945. local validInstance, validClass = pcall(function()
  1946. return remote:IsA("RemoteEvent") or remote:IsA("RemoteFunction")
  1947. end)
  1948. if validInstance and validClass then
  1949. local func = funcInfo.func
  1950. if not calling then
  1951. _, calling = pcall(getScriptFromSrc, funcInfo.source)
  1952. end
  1953. coroutine.wrap(function()
  1954. if remoteSignals[remote] then
  1955. remoteSignals[remote]:Fire(args)
  1956. end
  1957. end)()
  1958. if autoblock then
  1959. if excluding[remote] then
  1960. return
  1961. end
  1962. if not history[remote] then
  1963. history[remote] = { badOccurances = 0, lastCall = tick() }
  1964. end
  1965. if tick() - history[remote].lastCall < 1 then
  1966. history[remote].badOccurances += 1
  1967. return
  1968. else
  1969. history[remote].badOccurances = 0
  1970. end
  1971. if history[remote].badOccurances > 3 then
  1972. excluding[remote] = true
  1973. return
  1974. end
  1975. history[remote].lastCall = tick()
  1976. end
  1977. local functionInfoStr
  1978. local src
  1979. if func and islclosure(func) then
  1980. local functionInfo = {}
  1981. functionInfo.info = funcInfo
  1982. pcall(function()
  1983. functionInfo.constants = debug.getconstants(func)
  1984. end)
  1985. pcall(function()
  1986. functionInfoStr = v2v({ functionInfo = functionInfo })
  1987. end)
  1988. pcall(function()
  1989. if type(calling) == "userdata" then
  1990. src = calling
  1991. end
  1992. end)
  1993. end
  1994. if methodName:lower() == "fireserver" then
  1995. newRemote(
  1996. "event",
  1997. remote.Name,
  1998. args,
  1999. remote,
  2000. functionInfoStr,
  2001. (blocklist[remote] or blocklist[remote.Name]),
  2002. src
  2003. )
  2004. elseif methodName:lower() == "invokeserver" then
  2005. newRemote(
  2006. "function",
  2007. remote.Name,
  2008. args,
  2009. remote,
  2010. functionInfoStr,
  2011. (blocklist[remote] or blocklist[remote.Name]),
  2012. src,
  2013. returnValue
  2014. )
  2015. end
  2016. end
  2017. end
  2018.  
  2019. --- Used for hookfunction
  2020. function hookRemote(remoteType, remote, ...)
  2021. if typeof(remote) == "Instance" then
  2022. local args = { ... }
  2023. local validInstance, remoteName = pcall(function()
  2024. return remote.Name
  2025. end)
  2026. if validInstance and not (blacklist[remote] or blacklist[remoteName]) then
  2027. local funcInfo = {}
  2028. local calling
  2029. if funcEnabled then
  2030. funcInfo = debug.getinfo(4) or funcInfo
  2031. calling = useGetCallingScript and getcallingscript() or nil
  2032. end
  2033. if recordReturnValues and remoteType == "RemoteFunction" then
  2034. local thread = coroutine.running()
  2035. local args = { ... }
  2036. task.defer(function()
  2037. local returnValue
  2038. if remoteHooks[remote] then
  2039. args = { remoteHooks[remote](unpack(args)) }
  2040. returnValue = originalFunction(remote, unpack(args))
  2041. else
  2042. returnValue = originalFunction(remote, unpack(args))
  2043. end
  2044. schedule(
  2045. remoteHandler,
  2046. true,
  2047. remoteType == "RemoteEvent" and "fireserver" or "invokeserver",
  2048. remote,
  2049. args,
  2050. funcInfo,
  2051. calling,
  2052. returnValue
  2053. )
  2054. if blocklist[remote] or blocklist[remoteName] then
  2055. coroutine.resume(thread)
  2056. else
  2057. coroutine.resume(thread, unpack(returnValue))
  2058. end
  2059. end)
  2060. else
  2061. schedule(
  2062. remoteHandler,
  2063. true,
  2064. remoteType == "RemoteEvent" and "fireserver" or "invokeserver",
  2065. remote,
  2066. args,
  2067. funcInfo,
  2068. calling
  2069. )
  2070. if blocklist[remote] or blocklist[remoteName] then
  2071. return
  2072. end
  2073. end
  2074. end
  2075. end
  2076. if recordReturnValues and remoteType == "RemoteFunction" then
  2077. return coroutine.yield()
  2078. elseif remoteType == "RemoteEvent" then
  2079. if remoteHooks[remote] then
  2080. return originalEvent(remote, remoteHooks[remote](...))
  2081. end
  2082. return originalEvent(remote, ...)
  2083. else
  2084. if remoteHooks[remote] then
  2085. return originalFunction(remote, remoteHooks[remote](...))
  2086. end
  2087. return originalFunction(remote, ...)
  2088. end
  2089. end
  2090.  
  2091. local newnamecall = newcclosure(function(remote, ...)
  2092. if typeof(remote) == "Instance" then
  2093. local args = { ... }
  2094. local methodName = getnamecallmethod()
  2095. local validInstance, remoteName = pcall(function()
  2096. return remote.Name
  2097. end)
  2098. if
  2099. validInstance
  2100. and (methodName == "FireServer" or methodName == "fireServer" or methodName == "InvokeServer" or methodName == "invokeServer")
  2101. and not (blacklist[remote] or blacklist[remoteName])
  2102. then
  2103. local funcInfo = {}
  2104. local calling
  2105. if funcEnabled then
  2106. funcInfo = debug.getinfo(3) or funcInfo
  2107. calling = useGetCallingScript and getcallingscript() or nil
  2108. end
  2109. if recordReturnValues and (methodName == "InvokeServer" or methodName == "invokeServer") then
  2110. local namecallThread = coroutine.running()
  2111. local args = { ... }
  2112. task.defer(function()
  2113. local returnValue
  2114. setnamecallmethod(methodName)
  2115. if remoteHooks[remote] then
  2116. args = { remoteHooks[remote](unpack(args)) }
  2117. returnValue = { original(remote, unpack(args)) }
  2118. else
  2119. returnValue = { original(remote, unpack(args)) }
  2120. end
  2121. coroutine.resume(namecallThread, unpack(returnValue))
  2122. coroutine.wrap(function()
  2123. schedule(remoteHandler, false, methodName, remote, args, funcInfo, calling, returnValue)
  2124. end)()
  2125. end)
  2126. else
  2127. coroutine.wrap(function()
  2128. schedule(remoteHandler, false, methodName, remote, args, funcInfo, calling)
  2129. end)()
  2130. end
  2131. end
  2132. if recordReturnValues and (methodName == "InvokeServer" or methodName == "invokeServer") then
  2133. return coroutine.yield()
  2134. elseif
  2135. validInstance
  2136. and (methodName == "FireServer" or methodName == "fireServer" or methodName == "InvokeServer" or methodName == "invokeServer")
  2137. and (blocklist[remote] or blocklist[remoteName])
  2138. then
  2139. return nil
  2140. elseif
  2141. (not recordReturnValues or methodName ~= "InvokeServer" or methodName ~= "invokeServer")
  2142. and validInstance
  2143. and (methodName == "FireServer" or methodName == "fireServer" or methodName == "InvokeServer" or methodName == "invokeServer")
  2144. and remoteHooks[remote]
  2145. then
  2146. return original(remote, remoteHooks[remote](...))
  2147. else
  2148. return original(remote, ...)
  2149. end
  2150. end
  2151. return original(remote, ...)
  2152. end, original)
  2153.  
  2154. local newFireServer = newcclosure(function(...)
  2155. return hookRemote("RemoteEvent", ...)
  2156. end, originalEvent)
  2157.  
  2158. local newInvokeServer = newcclosure(function(...)
  2159. return hookRemote("RemoteFunction", ...)
  2160. end, originalFunction)
  2161.  
  2162. --- Toggles on and off the remote spy
  2163. function toggleSpy()
  2164. if not toggle then
  2165. if hookmetamethod then
  2166. local oldNamecall = hookmetamethod(game, "__namecall", newnamecall)
  2167. original = original or function(...)
  2168. return oldNamecall(...)
  2169. end
  2170. _G.OriginalNamecall = original
  2171. else
  2172. gm = gm or getrawmetatable(game)
  2173. original = original or function(...)
  2174. return gm.__namecall(...)
  2175. end
  2176. setreadonly(gm, false)
  2177. if not original then
  2178. warn("SimpleSpy: namecall method not found!")
  2179. onToggleButtonClick()
  2180. return
  2181. end
  2182. gm.__namecall = newnamecall
  2183. setreadonly(gm, true)
  2184. end
  2185. originalEvent = hookfunction(remoteEvent.FireServer, newFireServer)
  2186. originalFunction = hookfunction(remoteFunction.InvokeServer, newInvokeServer)
  2187. else
  2188. if hookmetamethod then
  2189. if original then
  2190. hookmetamethod(game, "__namecall", original)
  2191. end
  2192. else
  2193. gm = gm or getrawmetatable(game)
  2194. setreadonly(gm, false)
  2195. gm.__namecall = original
  2196. setreadonly(gm, true)
  2197. end
  2198. hookfunction(remoteEvent.FireServer, originalEvent)
  2199. hookfunction(remoteFunction.InvokeServer, originalFunction)
  2200. end
  2201. end
  2202.  
  2203. --- Toggles between the two remotespy methods (hookfunction currently = disabled)
  2204. function toggleSpyMethod()
  2205. toggleSpy()
  2206. toggle = not toggle
  2207. end
  2208.  
  2209. --- Shuts down the remote spy
  2210. function shutdown()
  2211. if schedulerconnect then
  2212. schedulerconnect:Disconnect()
  2213. end
  2214. for _, connection in pairs(connections) do
  2215. coroutine.wrap(function()
  2216. connection:Disconnect()
  2217. end)()
  2218. end
  2219. SimpleSpy2:Destroy()
  2220. hookfunction(remoteEvent.FireServer, originalEvent)
  2221. hookfunction(remoteFunction.InvokeServer, originalFunction)
  2222. if hookmetamethod then
  2223. if original then
  2224. hookmetamethod(game, "__namecall", original)
  2225. end
  2226. else
  2227. gm = gm or getrawmetatable(game)
  2228. setreadonly(gm, false)
  2229. gm.__namecall = original
  2230. setreadonly(gm, true)
  2231. end
  2232. _G.SimpleSpyExecuted = false
  2233. end
  2234.  
  2235. -- main
  2236. if not _G.SimpleSpyExecuted then
  2237. local succeeded, err = pcall(function()
  2238. if not RunService:IsClient() then
  2239. error("SimpleSpy cannot run on the server!")
  2240. end
  2241. if
  2242. not hookfunction
  2243. or not getrawmetatable
  2244. or getrawmetatable and not getrawmetatable(game).__namecall
  2245. or not setreadonly
  2246. then
  2247. local missing = {}
  2248. if not hookfunction then
  2249. table.insert(missing, "hookfunction")
  2250. end
  2251. if not getrawmetatable then
  2252. table.insert(missing, "getrawmetatable")
  2253. end
  2254. if getrawmetatable and not getrawmetatable(game).__namecall then
  2255. table.insert(missing, "getrawmetatable(game).__namecall")
  2256. end
  2257. if not setreadonly then
  2258. table.insert(missing, "setreadonly")
  2259. end
  2260. shutdown()
  2261. error(
  2262. "This environment does not support method hooks!\n(Your exploit is not capable of running SimpleSpy)\nMissing: "
  2263. .. table.concat(missing, ", ")
  2264. )
  2265. end
  2266. _G.SimpleSpyShutdown = shutdown
  2267. ContentProvider:PreloadAsync({
  2268. "rbxassetid://6065821980",
  2269. "rbxassetid://6065774948",
  2270. "rbxassetid://6065821086",
  2271. "rbxassetid://6065821596",
  2272. ImageLabel,
  2273. ImageLabel_2,
  2274. ImageLabel_3,
  2275. })
  2276. -- if gethui then funcEnabled = false end
  2277. onToggleButtonClick()
  2278. RemoteTemplate.Parent = nil
  2279. FunctionTemplate.Parent = nil
  2280. codebox = Highlight.new(CodeBox)
  2281. codebox:setRaw("")
  2282. getgenv().SimpleSpy = SimpleSpy
  2283. getgenv().getNil = function(name, class)
  2284. for _, v in pairs(getnilinstances()) do
  2285. if v.ClassName == class and v.Name == name then
  2286. return v
  2287. end
  2288. end
  2289. end
  2290. TextLabel:GetPropertyChangedSignal("Text"):Connect(scaleToolTip)
  2291. -- TopBar.InputBegan:Connect(onBarInput)
  2292. MinimizeButton.MouseButton1Click:Connect(toggleMinimize)
  2293. MaximizeButton.MouseButton1Click:Connect(toggleSideTray)
  2294. Simple.MouseButton1Click:Connect(onToggleButtonClick)
  2295. CloseButton.MouseEnter:Connect(onXButtonHover)
  2296. CloseButton.MouseLeave:Connect(onXButtonUnhover)
  2297. Simple.MouseEnter:Connect(onToggleButtonHover)
  2298. Simple.MouseLeave:Connect(onToggleButtonUnhover)
  2299. CloseButton.MouseButton1Click:Connect(shutdown)
  2300. table.insert(connections, UserInputService.InputBegan:Connect(backgroundUserInput))
  2301. connectResize()
  2302. SimpleSpy2.Enabled = true
  2303. coroutine.wrap(function()
  2304. wait(1)
  2305. onToggleButtonUnhover()
  2306. end)()
  2307. schedulerconnect = RunService.Heartbeat:Connect(taskscheduler)
  2308. if syn and syn.protect_gui then
  2309. pcall(syn.protect_gui, SimpleSpy2)
  2310. end
  2311. bringBackOnResize()
  2312. SimpleSpy2.Parent = --[[gethui and gethui() or]]
  2313. CoreGui
  2314. _G.SimpleSpyExecuted = true
  2315. if not Players.LocalPlayer then
  2316. Players:GetPropertyChangedSignal("LocalPlayer"):Wait()
  2317. end
  2318. Mouse = Players.LocalPlayer:GetMouse()
  2319. oldIcon = Mouse.Icon
  2320. table.insert(connections, Mouse.Move:Connect(mouseMoved))
  2321. end)
  2322. if not succeeded then
  2323. warn(
  2324. "A fatal error has occured, SimpleSpy was unable to launch properly.\nPlease DM this error message to @exx#9394:\n\n"
  2325. .. tostring(err)
  2326. )
  2327. SimpleSpy2:Destroy()
  2328. hookfunction(remoteEvent.FireServer, originalEvent)
  2329. hookfunction(remoteFunction.InvokeServer, originalFunction)
  2330. if hookmetamethod then
  2331. if original then
  2332. hookmetamethod(game, "__namecall", original)
  2333. end
  2334. else
  2335. setreadonly(gm, false)
  2336. gm.__namecall = original
  2337. setreadonly(gm, true)
  2338. end
  2339. return
  2340. end
  2341. else
  2342. SimpleSpy2:Destroy()
  2343. return
  2344. end
  2345.  
  2346. ----- ADD ONS ----- (easily add or remove additonal functionality to the RemoteSpy!)
  2347. --[[
  2348. Some helpful things:
  2349. - add your function in here, and create buttons for them through the 'newButton' function
  2350. - the first argument provided is the TextButton the player clicks to run the function
  2351. - generated scripts are generated when the namecall is initially fired and saved in remoteFrame objects
  2352. - blacklisted remotes will be ignored directly in namecall (less lag)
  2353. - the properties of a 'remoteFrame' object:
  2354. {
  2355. Name: (string) The name of the Remote
  2356. GenScript: (string) The generated script that appears in the codebox (generated when namecall fired)
  2357. Source: (Instance (LocalScript)) The script that fired/invoked the remote
  2358. Remote: (Instance (RemoteEvent) | Instance (RemoteFunction)) The remote that was fired/invoked
  2359. Log: (Instance (TextButton)) The button being used for the remote (same as 'selected.Log')
  2360. }
  2361. - globals list: (contact @exx#9394 for more information or if you have suggestions for more to be added)
  2362. - closed: (boolean) whether or not the GUI is currently minimized
  2363. - logs: (table[remoteFrame]) full of remoteFrame objects (properties listed above)
  2364. - selected: (remoteFrame) the currently selected remoteFrame (properties listed above)
  2365. - blacklist: (string[] | Instance[] (RemoteEvent) | Instance[] (RemoteFunction)) an array of blacklisted names and remotes
  2366. - codebox: (Instance (TextBox)) the textbox that holds all the code- cleared often
  2367. ]]
  2368. -- Copies the contents of the codebox
  2369. newButton("Copy Code", function()
  2370. return "Click to copy code"
  2371. end, function()
  2372. setclipboard(codebox:getString())
  2373. TextLabel.Text = "Copied successfully!"
  2374. end)
  2375.  
  2376. --- Copies the source script (that fired the remote)
  2377. newButton("Copy Remote", function()
  2378. return "Click to copy the path of the remote"
  2379. end, function()
  2380. if selected then
  2381. setclipboard(v2s(selected.Remote.remote))
  2382. TextLabel.Text = "Copied!"
  2383. end
  2384. end)
  2385.  
  2386. -- Executes the contents of the codebox through loadstring
  2387. newButton("Run Code", function()
  2388. return "Click to execute code"
  2389. end, function()
  2390. local orText = "Click to execute code"
  2391. TextLabel.Text = "Executing..."
  2392. local succeeded = pcall(function()
  2393. return loadstring(codebox:getString())()
  2394. end)
  2395. if succeeded then
  2396. TextLabel.Text = "Executed successfully!"
  2397. else
  2398. TextLabel.Text = "Execution error!"
  2399. end
  2400. end)
  2401.  
  2402. --- Gets the calling script (not super reliable but w/e)
  2403. newButton("Get Script", function()
  2404. return "Click to copy calling script to clipboard\nWARNING: Not super reliable, nil == could not find"
  2405. end, function()
  2406. if selected then
  2407. setclipboard(SimpleSpy:ValueToString(selected.Source))
  2408. TextLabel.Text = "Done!"
  2409. end
  2410. end)
  2411.  
  2412. --- Decompiles the script that fired the remote and puts it in the code box
  2413. newButton("Function Info", function()
  2414. return "Click to view calling function information"
  2415. end, function()
  2416. if selected then
  2417. if selected.Function then
  2418. codebox:setRaw(
  2419. "-- Calling function info\n-- Generated by the SimpleSpy serializer\n\n" .. tostring(selected.Function)
  2420. )
  2421. end
  2422. TextLabel.Text = "Done! Function info generated by the SimpleSpy Serializer."
  2423. end
  2424. end)
  2425.  
  2426. --- Clears the Remote logs
  2427. newButton("Clr Logs", function()
  2428. return "Click to clear logs"
  2429. end, function()
  2430. TextLabel.Text = "Clearing..."
  2431. logs = {}
  2432. for _, v in pairs(LogList:GetChildren()) do
  2433. if not v:IsA("UIListLayout") then
  2434. v:Destroy()
  2435. end
  2436. end
  2437. codebox:setRaw("")
  2438. selected = nil
  2439. TextLabel.Text = "Logs cleared!"
  2440. end)
  2441.  
  2442. --- Excludes the selected.Log Remote from the RemoteSpy
  2443. newButton("Exclude (i)", function()
  2444. return "Click to exclude this Remote.\nExcluding a remote makes SimpleSpy ignore it, but it will continue to be usable."
  2445. end, function()
  2446. if selected then
  2447. blacklist[selected.Remote.remote] = true
  2448. TextLabel.Text = "Excluded!"
  2449. end
  2450. end)
  2451.  
  2452. --- Excludes all Remotes that share the same name as the selected.Log remote from the RemoteSpy
  2453. newButton("Exclude (n)", function()
  2454. return "Click to exclude all remotes with this name.\nExcluding a remote makes SimpleSpy ignore it, but it will continue to be usable."
  2455. end, function()
  2456. if selected then
  2457. blacklist[selected.Name] = true
  2458. TextLabel.Text = "Excluded!"
  2459. end
  2460. end)
  2461.  
  2462. --- clears blacklist
  2463. newButton("Clr Blacklist", function()
  2464. return "Click to clear the blacklist.\nExcluding a remote makes SimpleSpy ignore it, but it will continue to be usable."
  2465. end, function()
  2466. blacklist = {}
  2467. TextLabel.Text = "Blacklist cleared!"
  2468. end)
  2469.  
  2470. --- Prevents the selected.Log Remote from firing the server (still logged)
  2471. newButton("Block (i)", function()
  2472. return "Click to stop this remote from firing.\nBlocking a remote won't remove it from SimpleSpy logs, but it will not continue to fire the server."
  2473. end, function()
  2474. if selected then
  2475. if selected.Remote.remote then
  2476. blocklist[selected.Remote.remote] = true
  2477. TextLabel.Text = "Excluded!"
  2478. else
  2479. TextLabel.Text = "Error! Instance may no longer exist, try using Block (n)."
  2480. end
  2481. end
  2482. end)
  2483.  
  2484. --- Prevents all remotes from firing that share the same name as the selected.Log remote from the RemoteSpy (still logged)
  2485. newButton("Block (n)", function()
  2486. return "Click to stop remotes with this name from firing.\nBlocking a remote won't remove it from SimpleSpy logs, but it will not continue to fire the server."
  2487. end, function()
  2488. if selected then
  2489. blocklist[selected.Name] = true
  2490. TextLabel.Text = "Excluded!"
  2491. end
  2492. end)
  2493.  
  2494. --- clears blacklist
  2495. newButton("Clr Blocklist", function()
  2496. return "Click to stop blocking remotes.\nBlocking a remote won't remove it from SimpleSpy logs, but it will not continue to fire the server."
  2497. end, function()
  2498. blocklist = {}
  2499. TextLabel.Text = "Blocklist cleared!"
  2500. end)
  2501.  
  2502. --- Attempts to decompile the source script
  2503. newButton("Decompile", function()
  2504. return "Attempts to decompile source script\nWARNING: Not super reliable, nil == could not find"
  2505. end, function()
  2506. if selected then
  2507. if selected.Source then
  2508. codebox:setRaw(decompile(selected.Source))
  2509. TextLabel.Text = "Done!"
  2510. else
  2511. TextLabel.Text = "Source not found!"
  2512. end
  2513. end
  2514. end)
  2515.  
  2516. newButton("Disable Info", function()
  2517. return string.format(
  2518. "[%s] Toggle function info (because it can cause lag in some games)",
  2519. funcEnabled and "ENABLED" or "DISABLED"
  2520. )
  2521. end, function()
  2522. funcEnabled = not funcEnabled
  2523. TextLabel.Text = string.format(
  2524. "[%s] Toggle function info (because it can cause lag in some games)",
  2525. funcEnabled and "ENABLED" or "DISABLED"
  2526. )
  2527. end)
  2528.  
  2529. newButton("Autoblock", function()
  2530. return string.format(
  2531. "[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs",
  2532. autoblock and "ENABLED" or "DISABLED"
  2533. )
  2534. end, function()
  2535. autoblock = not autoblock
  2536. TextLabel.Text = string.format(
  2537. "[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs",
  2538. autoblock and "ENABLED" or "DISABLED"
  2539. )
  2540. history = {}
  2541. excluding = {}
  2542. end)
  2543.  
  2544. newButton("CallingScript", function()
  2545. return string.format(
  2546. "[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.",
  2547. useGetCallingScript and "ENABLED" or "DISABLED"
  2548. )
  2549. end, function()
  2550. useGetCallingScript = not useGetCallingScript
  2551. TextLabel.Text = string.format(
  2552. "[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.",
  2553. useGetCallingScript and "ENABLED" or "DISABLED"
  2554. )
  2555. end)
  2556.  
  2557. newButton("KeyToString", function()
  2558. return string.format(
  2559. "[%s] [BETA] Uses an experimental new function to replicate Roblox's behavior when a non-primitive type is used as a key in a table. Still in development and may not properly reflect tostringed (empty) userdata.",
  2560. keyToString and "ENABLED" or "DISABLED"
  2561. )
  2562. end, function()
  2563. keyToString = not keyToString
  2564. TextLabel.Text = string.format(
  2565. "[%s] [BETA] Uses an experimental new function to replicate Roblox's behavior when a non-primitive type is used as a key in a table. Still in development and may not properly reflect tostringed (empty) userdata.",
  2566. keyToString and "ENABLED" or "DISABLED"
  2567. )
  2568. end)
  2569.  
  2570. newButton("ToggleReturnValues", function()
  2571. return string.format(
  2572. "[%s] [EXPERIMENTAL] Enables recording of return values for 'GetReturnValue'\n\nUse this method at your own risk, as it could be detectable.",
  2573. recordReturnValues and "ENABLED" or "DISABLED"
  2574. )
  2575. end, function()
  2576. recordReturnValues = not recordReturnValues
  2577. TextLabel.Text = string.format(
  2578. "[%s] [EXPERIMENTAL] Enables recording of return values for 'GetReturnValue'\n\nUse this method at your own risk, as it could be detectable.",
  2579. recordReturnValues and "ENABLED" or "DISABLED"
  2580. )
  2581. end)
  2582.  
  2583. newButton("GetReturnValue", function()
  2584. return "[Experimental] If 'ReturnValues' is enabled, this will show the recorded return value for the RemoteFunction (if available)."
  2585. end, function()
  2586. if selected then
  2587. codebox:setRaw(SimpleSpy:ValueToVar(selected.ReturnValue, "returnValue"))
  2588. end
  2589. end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement