Advertisement
Msizz

SimpleSpy [v3][Skire's Version]

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