R

simplespy 2.2

public
rrixh Jun 07, 2024 Never 45
Clone
Lua simplespy2.2rrixh.zip 2006 lines (1886 loc) | 76.51 KB
1
--[[
2
SimpleSpy v2.2 SOURCE
3
4
Credits:
5
exx - basically everything
6
Frosty - GUI to Lua
7
]]
8
9
-- shuts down the previous instance of SimpleSpy
10
if _G.SimpleSpyExecuted and type(_G.SimpleSpyShutdown) == "function" then
11
_G.SimpleSpyShutdown()
12
end
13
14
local Players = game:GetService("Players")
15
local CoreGui = game:GetService("CoreGui")
16
local Highlight = loadstring(game:HttpGet("https://github.com/exxtremestuffs/SimpleSpySource/raw/master/highlight.lua"))()
17
18
---- GENERATED (kinda sorta mostly) BY GUI to LUA ----
19
20
-- Instances:
21
22
local SimpleSpy2 = Instance.new("ScreenGui")
23
local Background = Instance.new("Frame")
24
local LeftPanel = Instance.new("Frame")
25
local LogList = Instance.new("ScrollingFrame")
26
local UIListLayout = Instance.new("UIListLayout")
27
local RemoteTemplate = Instance.new("Frame")
28
local ColorBar = Instance.new("Frame")
29
local Text = Instance.new("TextLabel")
30
local Button = Instance.new("TextButton")
31
local RightPanel = Instance.new("Frame")
32
local CodeBox = Instance.new("Frame")
33
local ScrollingFrame = Instance.new("ScrollingFrame")
34
local UIGridLayout = Instance.new("UIGridLayout")
35
local FunctionTemplate = Instance.new("Frame")
36
local ColorBar_2 = Instance.new("Frame")
37
local Text_2 = Instance.new("TextLabel")
38
local Button_2 = Instance.new("TextButton")
39
local TopBar = Instance.new("Frame")
40
local Simple = Instance.new("TextButton")
41
local CloseButton = Instance.new("TextButton")
42
local ImageLabel = Instance.new("ImageLabel")
43
local MaximizeButton = Instance.new("TextButton")
44
local ImageLabel_2 = Instance.new("ImageLabel")
45
local MinimizeButton = Instance.new("TextButton")
46
local ImageLabel_3 = Instance.new("ImageLabel")
47
local ToolTip = Instance.new("Frame")
48
local TextLabel = Instance.new("TextLabel")
49
50
--Properties:
51
52
SimpleSpy2.Name = "SimpleSpy2"
53
SimpleSpy2.ResetOnSpawn = false
54
55
Background.Name = "Background"
56
Background.Parent = SimpleSpy2
57
Background.BackgroundColor3 = Color3.new(1, 1, 1)
58
Background.BackgroundTransparency = 1
59
Background.Position = UDim2.new(0, 500, 0, 200)
60
Background.Size = UDim2.new(0, 450, 0, 268)
61
62
LeftPanel.Name = "LeftPanel"
63
LeftPanel.Parent = Background
64
LeftPanel.BackgroundColor3 = Color3.new(0.207843, 0.203922, 0.215686)
65
LeftPanel.BorderSizePixel = 0
66
LeftPanel.Position = UDim2.new(0, 0, 0, 19)
67
LeftPanel.Size = UDim2.new(0, 131, 0, 249)
68
69
LogList.Name = "LogList"
70
LogList.Parent = LeftPanel
71
LogList.Active = true
72
LogList.BackgroundColor3 = Color3.new(1, 1, 1)
73
LogList.BackgroundTransparency = 1
74
LogList.BorderSizePixel = 0
75
LogList.Position = UDim2.new(0, 0, 0, 9)
76
LogList.Size = UDim2.new(0, 131, 0, 232)
77
LogList.CanvasSize = UDim2.new(0, 0, 0, 0)
78
LogList.ScrollBarThickness = 4
79
80
UIListLayout.Parent = LogList
81
UIListLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
82
UIListLayout.SortOrder = Enum.SortOrder.LayoutOrder
83
84
RemoteTemplate.Name = "RemoteTemplate"
85
RemoteTemplate.Parent = LogList
86
RemoteTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
87
RemoteTemplate.BackgroundTransparency = 1
88
RemoteTemplate.Size = UDim2.new(0, 117, 0, 27)
89
90
ColorBar.Name = "ColorBar"
91
ColorBar.Parent = RemoteTemplate
92
ColorBar.BackgroundColor3 = Color3.new(1, 0.94902, 0)
93
ColorBar.BorderSizePixel = 0
94
ColorBar.Position = UDim2.new(0, 0, 0, 1)
95
ColorBar.Size = UDim2.new(0, 7, 0, 18)
96
ColorBar.ZIndex = 2
97
98
Text.Name = "Text"
99
Text.Parent = RemoteTemplate
100
Text.BackgroundColor3 = Color3.new(1, 1, 1)
101
Text.BackgroundTransparency = 1
102
Text.Position = UDim2.new(0, 12, 0, 1)
103
Text.Size = UDim2.new(0, 105, 0, 18)
104
Text.ZIndex = 2
105
Text.Font = Enum.Font.SourceSans
106
Text.Text = "TEXT"
107
Text.TextColor3 = Color3.new(1, 1, 1)
108
Text.TextSize = 14
109
Text.TextXAlignment = Enum.TextXAlignment.Left
110
111
Button.Name = "Button"
112
Button.Parent = RemoteTemplate
113
Button.BackgroundColor3 = Color3.new(0, 0, 0)
114
Button.BackgroundTransparency = 0.75
115
Button.BorderColor3 = Color3.new(1, 1, 1)
116
Button.Position = UDim2.new(0, 0, 0, 1)
117
Button.Size = UDim2.new(0, 117, 0, 18)
118
Button.AutoButtonColor = false
119
Button.Font = Enum.Font.SourceSans
120
Button.Text = ""
121
Button.TextColor3 = Color3.new(0, 0, 0)
122
Button.TextSize = 14
123
124
RightPanel.Name = "RightPanel"
125
RightPanel.Parent = Background
126
RightPanel.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
127
RightPanel.BorderSizePixel = 0
128
RightPanel.Position = UDim2.new(0, 131, 0, 19)
129
RightPanel.Size = UDim2.new(0, 319, 0, 249)
130
131
CodeBox.Name = "CodeBox"
132
CodeBox.Parent = RightPanel
133
CodeBox.BackgroundColor3 = Color3.new(0.0823529, 0.0745098, 0.0784314)
134
CodeBox.BorderSizePixel = 0
135
CodeBox.Size = UDim2.new(0, 319, 0, 119)
136
137
ScrollingFrame.Parent = RightPanel
138
ScrollingFrame.Active = true
139
ScrollingFrame.BackgroundColor3 = Color3.new(1, 1, 1)
140
ScrollingFrame.BackgroundTransparency = 1
141
ScrollingFrame.Position = UDim2.new(0, 0, 0.5, 0)
142
ScrollingFrame.Size = UDim2.new(1, 0, 0.5, -9)
143
ScrollingFrame.CanvasSize = UDim2.new(0, 0, 0, 0)
144
ScrollingFrame.ScrollBarThickness = 4
145
146
UIGridLayout.Parent = ScrollingFrame
147
UIGridLayout.HorizontalAlignment = Enum.HorizontalAlignment.Center
148
UIGridLayout.SortOrder = Enum.SortOrder.LayoutOrder
149
UIGridLayout.CellPadding = UDim2.new(0, 0, 0, 0)
150
UIGridLayout.CellSize = UDim2.new(0, 94, 0, 27)
151
152
FunctionTemplate.Name = "FunctionTemplate"
153
FunctionTemplate.Parent = ScrollingFrame
154
FunctionTemplate.BackgroundColor3 = Color3.new(1, 1, 1)
155
FunctionTemplate.BackgroundTransparency = 1
156
FunctionTemplate.Size = UDim2.new(0, 117, 0, 23)
157
158
ColorBar_2.Name = "ColorBar"
159
ColorBar_2.Parent = FunctionTemplate
160
ColorBar_2.BackgroundColor3 = Color3.new(1, 1, 1)
161
ColorBar_2.BorderSizePixel = 0
162
ColorBar_2.Position = UDim2.new(0, 7, 0, 10)
163
ColorBar_2.Size = UDim2.new(0, 7, 0, 18)
164
ColorBar_2.ZIndex = 3
165
166
Text_2.Name = "Text"
167
Text_2.Parent = FunctionTemplate
168
Text_2.BackgroundColor3 = Color3.new(1, 1, 1)
169
Text_2.BackgroundTransparency = 1
170
Text_2.Position = UDim2.new(0, 19, 0, 10)
171
Text_2.Size = UDim2.new(0, 69, 0, 18)
172
Text_2.ZIndex = 2
173
Text_2.Font = Enum.Font.SourceSans
174
Text_2.Text = "TEXT"
175
Text_2.TextColor3 = Color3.new(1, 1, 1)
176
Text_2.TextSize = 14
177
Text_2.TextStrokeColor3 = Color3.new(0.145098, 0.141176, 0.14902)
178
Text_2.TextXAlignment = Enum.TextXAlignment.Left
179
180
Button_2.Name = "Button"
181
Button_2.Parent = FunctionTemplate
182
Button_2.BackgroundColor3 = Color3.new(0, 0, 0)
183
Button_2.BackgroundTransparency = 0.69999998807907
184
Button_2.BorderColor3 = Color3.new(1, 1, 1)
185
Button_2.Position = UDim2.new(0, 7, 0, 10)
186
Button_2.Size = UDim2.new(0, 80, 0, 18)
187
Button_2.AutoButtonColor = false
188
Button_2.Font = Enum.Font.SourceSans
189
Button_2.Text = ""
190
Button_2.TextColor3 = Color3.new(0, 0, 0)
191
Button_2.TextSize = 14
192
193
TopBar.Name = "TopBar"
194
TopBar.Parent = Background
195
TopBar.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
196
TopBar.BorderSizePixel = 0
197
TopBar.Size = UDim2.new(0, 450, 0, 19)
198
199
Simple.Name = "Simple"
200
Simple.Parent = TopBar
201
Simple.BackgroundColor3 = Color3.new(1, 1, 1)
202
Simple.AutoButtonColor = false
203
Simple.BackgroundTransparency = 1
204
Simple.Position = UDim2.new(0, 5, 0, 0)
205
Simple.Size = UDim2.new(0, 57, 0, 18)
206
Simple.Font = Enum.Font.SourceSansBold
207
Simple.Text = "SimpleSpy"
208
Simple.TextColor3 = Color3.new(1, 1, 1)
209
Simple.TextSize = 14
210
Simple.TextXAlignment = Enum.TextXAlignment.Left
211
212
CloseButton.Name = "CloseButton"
213
CloseButton.Parent = TopBar
214
CloseButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
215
CloseButton.BorderSizePixel = 0
216
CloseButton.Position = UDim2.new(1, -19, 0, 0)
217
CloseButton.Size = UDim2.new(0, 19, 0, 19)
218
CloseButton.Font = Enum.Font.SourceSans
219
CloseButton.Text = ""
220
CloseButton.TextColor3 = Color3.new(0, 0, 0)
221
CloseButton.TextSize = 14
222
223
ImageLabel.Parent = CloseButton
224
ImageLabel.BackgroundColor3 = Color3.new(1, 1, 1)
225
ImageLabel.BackgroundTransparency = 1
226
ImageLabel.Position = UDim2.new(0, 5, 0, 5)
227
ImageLabel.Size = UDim2.new(0, 9, 0, 9)
228
ImageLabel.Image = "http://www.roblox.com/asset/?id=5597086202"
229
230
MaximizeButton.Name = "MaximizeButton"
231
MaximizeButton.Parent = TopBar
232
MaximizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
233
MaximizeButton.BorderSizePixel = 0
234
MaximizeButton.Position = UDim2.new(1, -38, 0, 0)
235
MaximizeButton.Size = UDim2.new(0, 19, 0, 19)
236
MaximizeButton.Font = Enum.Font.SourceSans
237
MaximizeButton.Text = ""
238
MaximizeButton.TextColor3 = Color3.new(0, 0, 0)
239
MaximizeButton.TextSize = 14
240
241
ImageLabel_2.Parent = MaximizeButton
242
ImageLabel_2.BackgroundColor3 = Color3.new(1, 1, 1)
243
ImageLabel_2.BackgroundTransparency = 1
244
ImageLabel_2.Position = UDim2.new(0, 5, 0, 5)
245
ImageLabel_2.Size = UDim2.new(0, 9, 0, 9)
246
ImageLabel_2.Image = "http://www.roblox.com/asset/?id=5597108117"
247
248
MinimizeButton.Name = "MinimizeButton"
249
MinimizeButton.Parent = TopBar
250
MinimizeButton.BackgroundColor3 = Color3.new(0.145098, 0.141176, 0.14902)
251
MinimizeButton.BorderSizePixel = 0
252
MinimizeButton.Position = UDim2.new(1, -57, 0, 0)
253
MinimizeButton.Size = UDim2.new(0, 19, 0, 19)
254
MinimizeButton.Font = Enum.Font.SourceSans
255
MinimizeButton.Text = ""
256
MinimizeButton.TextColor3 = Color3.new(0, 0, 0)
257
MinimizeButton.TextSize = 14
258
259
ImageLabel_3.Parent = MinimizeButton
260
ImageLabel_3.BackgroundColor3 = Color3.new(1, 1, 1)
261
ImageLabel_3.BackgroundTransparency = 1
262
ImageLabel_3.Position = UDim2.new(0, 5, 0, 5)
263
ImageLabel_3.Size = UDim2.new(0, 9, 0, 9)
264
ImageLabel_3.Image = "http://www.roblox.com/asset/?id=5597105827"
265
266
ToolTip.Name = "ToolTip"
267
ToolTip.Parent = SimpleSpy2
268
ToolTip.BackgroundColor3 = Color3.fromRGB(26, 26, 26)
269
ToolTip.BackgroundTransparency = 0.1
270
ToolTip.BorderColor3 = Color3.new(1, 1, 1)
271
ToolTip.Size = UDim2.new(0, 200, 0, 50)
272
ToolTip.ZIndex = 3
273
ToolTip.Visible = false
274
275
TextLabel.Parent = ToolTip
276
TextLabel.BackgroundColor3 = Color3.new(1, 1, 1)
277
TextLabel.BackgroundTransparency = 1
278
TextLabel.Position = UDim2.new(0, 2, 0, 2)
279
TextLabel.Size = UDim2.new(0, 196, 0, 46)
280
TextLabel.ZIndex = 3
281
TextLabel.Font = Enum.Font.SourceSans
282
TextLabel.Text = "This is some slightly longer text."
283
TextLabel.TextColor3 = Color3.new(1, 1, 1)
284
TextLabel.TextSize = 14
285
TextLabel.TextWrapped = true
286
TextLabel.TextXAlignment = Enum.TextXAlignment.Left
287
TextLabel.TextYAlignment = Enum.TextYAlignment.Top
288
289
-------------------------------------------------------------------------------
290
-- init
291
local RunService = game:GetService("RunService")
292
local UserInputService = game:GetService("UserInputService")
293
local TweenService = game:GetService("TweenService")
294
local ContentProvider = game:GetService("ContentProvider")
295
local TextService = game:GetService("TextService")
296
local Mouse = game:GetService("Players").LocalPlayer:GetMouse()
297
298
local selectedColor = Color3.new(0.321569, 0.333333, 1)
299
local deselectedColor = Color3.new(0.8, 0.8, 0.8)
300
--- So things are descending
301
local layoutOrderNum = 999999999
302
--- Whether or not the gui is closing
303
local mainClosing = false
304
--- Whether or not the gui is closed (defaults to false)
305
local closed = false
306
--- Whether or not the sidebar is closing
307
local sideClosing = false
308
--- Whether or not the sidebar is closed (defaults to true but opens automatically on remote selection)
309
local sideClosed = false
310
--- Whether or not the code box is maximized (defaults to false)
311
local maximized = false
312
--- The event logs to be read from
313
local logs = {}
314
--- The event currently selected.Log (defaults to nil)
315
local selected = nil
316
--- The blacklist (can be a string name or the Remote Instance)
317
local blacklist = {}
318
--- The block list (can be a string name or the Remote Instance)
319
local blocklist = {}
320
--- Whether or not to add getNil function
321
local getNil = false
322
--- Array of remotes (and original functions) connected to
323
local connectedRemotes = {}
324
--- True = hookfunction, false = namecall
325
local toggle = false
326
local gm = getrawmetatable(game)
327
local original = gm.__namecall
328
setreadonly(gm, false)
329
--- used to prevent recursives
330
local prevTables = {}
331
--- holds logs (for deletion)
332
local remoteLogs = {}
333
--- used for hookfunction
334
local remoteEvent = Instance.new("RemoteEvent")
335
--- used for hookfunction
336
local remoteFunction = Instance.new("RemoteFunction")
337
local originalEvent = remoteEvent.FireServer
338
local originalFunction = remoteFunction.InvokeServer
339
--- the maximum amount of remotes allowed in logs
340
_G.SIMPLESPYCONFIG_MaxRemotes = 500
341
--- how many spaces to indent
342
local indent = 4
343
--- used for task scheduler
344
local scheduled = {}
345
--- RBXScriptConnect of the task scheduler
346
local schedulerconnect
347
local SimpleSpy = {}
348
local topstr = ""
349
local bottomstr = ""
350
local remotesFadeIn
351
local rightFadeIn
352
local codebox
353
local p
354
local getnilrequired = false
355
356
-- autoblock variables
357
local autoblock = false
358
local history = {}
359
local excluding = {}
360
361
-- function info variables
362
local funcEnabled = true
363
364
-- remote hooking/connecting api variables
365
local remoteSignals = {}
366
local remoteHooks = {}
367
368
-- original mouse icon
369
local oldIcon = Mouse.Icon
370
371
-- if mouse inside gui
372
local mouseInGui = false
373
374
-- handy array of RBXScriptConnections to disconnect on shutdown
375
local connections = {}
376
377
-- whether or not SimpleSpy uses 'getcallingscript()' to get the script (default is false because detection)
378
local useGetCallingScript = false
379
380
-- functions
381
382
--- 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:FireServer`)
383
--- @param method string
384
--- @param args any[]
385
--- @return string
386
function SimpleSpy:ArgsToString(method, args)
387
assert(typeof(method) == "string", "string expected, got " .. typeof(method))
388
assert(typeof(args) == "table", "table expected, got " .. typeof(args))
389
return v2v({args = args}) .. "\n\n" .. method .. "(unpack(args))"
390
end
391
392
--- Converts a value to variables with the specified index as the variable name (if nil/invalid then the name will be assigned automatically)
393
--- @param t any[]
394
--- @return string
395
function SimpleSpy:TableToVars(t)
396
assert(typeof(t) == "table", "table expected, got " .. typeof(t))
397
return v2v(t)
398
end
399
400
--- Converts a value to a variable with the specified `variablename` (if nil/invalid then the name will be assigned automatically)
401
--- @param value any
402
--- @return string
403
function SimpleSpy:ValueToVar(value, variablename)
404
assert(variablename == nil or typeof(variablename) == "string", "string expected, got " .. typeof(variablename))
405
if not variablename then
406
variablename = 1
407
end
408
return v2v({[variablename] = value})
409
end
410
411
--- Converts any value to a string, cannot preserve function contents
412
--- @param value any
413
--- @return string
414
function SimpleSpy:ValueToString(value)
415
return v2s(value)
416
end
417
418
--- Generates the simplespy function info
419
--- @param func function
420
--- @return string
421
function SimpleSpy:GetFunctionInfo(func)
422
assert(typeof(func) == "function", "Instance expected, got " .. typeof(func))
423
return v2v{functionInfo = {
424
info = debug.getinfo(func),
425
constants = debug.getconstants(func)
426
}}
427
end
428
429
--- Gets the ScriptSignal for a specified remote being fired
430
--- @param remote Instance
431
function SimpleSpy:GetRemoteFiredSignal(remote)
432
assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
433
if not remoteSignals[remote] then
434
remoteSignals[remote] = newSignal()
435
end
436
return remoteSignals[remote]
437
end
438
439
--- Allows for direct hooking of remotes **THIS CAN BE VERY DANGEROUS**
440
--- @param remote Instance
441
--- @param f function
442
function SimpleSpy:HookRemote(remote, f)
443
assert(typeof(remote) == "Instance", "Instance expected, got " .. typeof(remote))
444
assert(typeof(f) == "function", "function expected, got " .. typeof(f))
445
remoteHooks[remote] = f
446
end
447
448
--- Blocks the specified remote instance/string
449
--- @param remote any
450
function SimpleSpy:BlockRemote(remote)
451
assert(typeof(remote) == "Instance" or typeof(remote) == "string", "Instance | string expected, got " .. typeof(remote))
452
blocklist[remote] = true
453
end
454
455
--- Excludes the specified remote from logs (instance/string)
456
--- @param remote any
457
function SimpleSpy:ExcludeRemote(remote)
458
assert(typeof(remote) == "Instance" or typeof(remote) == "string", "Instance | string expected, got " .. typeof(remote))
459
blacklist[remote] = true
460
end
461
462
--- Creates a new ScriptSignal that can be connected to and fired
463
--- @return table
464
function newSignal()
465
local connected = {}
466
return {
467
Connect = function(self, f)
468
assert(connected, "Signal is closed")
469
connected[tostring(f)] = f
470
return setmetatable({
471
Connected = true,
472
Disconnect = function(self)
473
if not connected then
474
warn("Signal is already closed")
475
end
476
self.Connected = false
477
connected[tostring(f)] = nil
478
end
479
},
480
{
481
__index = function(self, i)
482
if i == "Connected" then
483
return not not connected[tostring(f)]
484
end
485
end
486
})
487
end,
488
Fire = function(self, ...)
489
for _, f in pairs(connected) do
490
coroutine.wrap(f)(...)
491
end
492
end
493
}
494
end
495
496
--- Prevents remote spam from causing lag (clears logs after `_G.SIMPLESPYCONFIG_MaxRemotes` or 500 remotes)
497
function clean()
498
local max = _G.SIMPLESPYCONFIG_MaxRemotes
499
if not typeof(max) == "number" and math.floor(max) ~= max then
500
max = 500
501
end
502
if #remoteLogs > max then
503
for i = 100, #remoteLogs do
504
local v = remoteLogs[i]
505
if typeof(v[1]) == "RBXScriptConnection" then
506
v[1]:Disconnect()
507
end
508
if typeof(v[2]) == "Instance" then
509
v[2]:Destroy()
510
end
511
end
512
local newLogs = {}
513
for i = 1, 100 do
514
table.insert(newLogs, remoteLogs[i])
515
end
516
remoteLogs = newLogs
517
end
518
end
519
520
--- Scales the ToolTip to fit containing text
521
function scaleToolTip()
522
local size = TextService:GetTextSize(TextLabel.Text, TextLabel.TextSize, TextLabel.Font, Vector2.new(196, math.huge))
523
TextLabel.Size = UDim2.new(0, size.X, 0, size.Y)
524
ToolTip.Size = UDim2.new(0, size.X + 4, 0, size.Y + 4)
525
end
526
527
--- Executed when the toggle button (the SimpleSpy logo) is hovered over
528
function onToggleButtonHover()
529
if not toggle then
530
TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(252, 51, 51)}):Play()
531
else
532
TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(68, 206, 91)}):Play()
533
end
534
end
535
536
--- Executed when the toggle button is unhovered over
537
function onToggleButtonUnhover()
538
TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(255, 255, 255)}):Play()
539
end
540
541
--- Executed when the X button is hovered over
542
function onXButtonHover()
543
TweenService:Create(CloseButton, TweenInfo.new(0.2), {BackgroundColor3 = Color3.fromRGB(255, 60, 60)}):Play()
544
end
545
546
--- Executed when the X button is unhovered over
547
function onXButtonUnhover()
548
TweenService:Create(CloseButton, TweenInfo.new(0.2), {BackgroundColor3 = Color3.fromRGB(37, 36, 38)}):Play()
549
end
550
551
--- Toggles the remote spy method (when button clicked)
552
function onToggleButtonClick()
553
if toggle then
554
TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(252, 51, 51)}):Play()
555
else
556
TweenService:Create(Simple, TweenInfo.new(0.5), {TextColor3 = Color3.fromRGB(68, 206, 91)}):Play()
557
end
558
toggleSpyMethod()
559
end
560
561
--- Reconnects bringBackOnResize if the current viewport changes and also connects it initially
562
function connectResize()
563
local lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
564
workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(function()
565
lastCam:Disconnect()
566
if workspace.CurrentCamera then
567
lastCam = workspace.CurrentCamera:GetPropertyChangedSignal("ViewportSize"):Connect(bringBackOnResize)
568
end
569
end)
570
end
571
572
--- Brings gui back if it gets lost offscreen (connected to the camera viewport changing)
573
function bringBackOnResize()
574
local currentX = Background.AbsolutePosition.X
575
local currentY = Background.AbsolutePosition.Y
576
local viewportSize = workspace.CurrentCamera.ViewportSize
577
if (currentX < 0) or (currentX > (viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X))) then
578
if currentX < 0 then
579
currentX = 0
580
else
581
currentX = viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)
582
end
583
end
584
if (currentY < 0) or (currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36)) then
585
if currentY < 0 then
586
currentY = 0
587
else
588
currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
589
end
590
end
591
TweenService.Create(TweenService, Background, TweenInfo.new(0.1), {Position = UDim2.new(0, currentX, 0, currentY)}):Play()
592
end
593
594
--- Drags gui (so long as mouse is held down)
595
function onBarInput(input)
596
if input.UserInputType == Enum.UserInputType.MouseButton1 then
597
local lastPos = UserInputService.GetMouseLocation(UserInputService)
598
local mainPos = Background.AbsolutePosition
599
local offset = mainPos - lastPos
600
local currentPos = offset + lastPos
601
RunService.BindToRenderStep(RunService, "drag", 1,
602
function()
603
local newPos = UserInputService.GetMouseLocation(UserInputService)
604
if newPos ~= lastPos then
605
local currentX = (offset + newPos).X
606
local currentY = (offset + newPos).Y
607
local viewportSize = workspace.CurrentCamera.ViewportSize
608
if (currentX < 0 and currentX < currentPos.X) or (currentX > (viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)) and currentX > currentPos.X) then
609
if currentX < 0 then
610
currentX = 0
611
else
612
currentX = viewportSize.X - (sideClosed and 131 or TopBar.AbsoluteSize.X)
613
end
614
end
615
if (currentY < 0 and currentY < currentPos.Y) or (currentY > (viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36) and currentY > currentPos.Y) then
616
if currentY < 0 then
617
currentY = 0
618
else
619
currentY = viewportSize.Y - (closed and 19 or Background.AbsoluteSize.Y) - 36
620
end
621
end
622
currentPos = Vector2.new(currentX, currentY)
623
lastPos = newPos
624
TweenService.Create(TweenService, Background, TweenInfo.new(0.1), {Position = UDim2.new(0, currentPos.X, 0, currentPos.Y)}):Play()
625
end
626
if not UserInputService:IsMouseButtonPressed(Enum.UserInputType.MouseButton1) then
627
RunService.UnbindFromRenderStep(RunService, "drag")
628
end
629
end
630
)
631
end
632
end
633
634
--- Fades out the table of elements (and makes them invisible), returns a function to make them visible again
635
function fadeOut(elements)
636
local data = {}
637
for _, v in pairs(elements) do
638
if typeof(v) == "Instance" and v:IsA("GuiObject") and v.Visible then
639
coroutine.wrap(function()
640
data[v] = {
641
BackgroundTransparency = v.BackgroundTransparency
642
}
643
TweenService:Create(v, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
644
if v:IsA("TextBox") or v:IsA("TextButton") or v:IsA("TextLabel") then
645
data[v].TextTransparency = v.TextTransparency
646
TweenService:Create(v, TweenInfo.new(0.5), {TextTransparency = 1}):Play()
647
elseif v:IsA("ImageButton") or v:IsA("ImageLabel") then
648
data[v].ImageTransparency = v.ImageTransparency
649
TweenService:Create(v, TweenInfo.new(0.5), {ImageTransparency = 1}):Play()
650
end
651
wait(0.5)
652
v.Visible = false
653
for i, x in pairs(data[v]) do
654
v[i] = x
655
end
656
data[v] = true
657
end)()
658
end
659
end
660
return function()
661
for i, _ in pairs(data) do
662
coroutine.wrap(function()
663
local properties = {
664
BackgroundTransparency = i.BackgroundTransparency
665
}
666
i.BackgroundTransparency = 1
667
TweenService:Create(i, TweenInfo.new(0.5), {BackgroundTransparency = properties.BackgroundTransparency}):Play()
668
if i:IsA("TextBox") or i:IsA("TextButton") or i:IsA("TextLabel") then
669
properties.TextTransparency = i.TextTransparency
670
i.TextTransparency = 1
671
TweenService:Create(i, TweenInfo.new(0.5), {TextTransparency = properties.TextTransparency}):Play()
672
elseif i:IsA("ImageButton") or i:IsA("ImageLabel") then
673
properties.ImageTransparency = i.ImageTransparency
674
i.ImageTransparency = 1
675
TweenService:Create(i, TweenInfo.new(0.5), {ImageTransparency = properties.ImageTransparency}):Play()
676
end
677
i.Visible = true
678
end)()
679
end
680
end
681
end
682
683
--- Expands and minimizes the gui (closed is the toggle boolean)
684
function toggleMinimize(override)
685
if mainClosing and not override or maximized then
686
return
687
end
688
mainClosing = true
689
closed = not closed
690
if closed then
691
if not sideClosed then
692
toggleSideTray(true)
693
end
694
LeftPanel.Visible = true
695
TweenService:Create(LeftPanel, TweenInfo.new(0.5), {Size = UDim2.new(0, 131, 0, 0)}):Play()
696
wait(0.5)
697
remotesFadeIn = fadeOut(LeftPanel:GetDescendants())
698
wait(0.5)
699
else
700
TweenService:Create(LeftPanel, TweenInfo.new(0.5), {Size = UDim2.new(0, 131, 0, 249)}):Play()
701
wait(0.5)
702
if remotesFadeIn then
703
remotesFadeIn()
704
remotesFadeIn = nil
705
end
706
bringBackOnResize()
707
end
708
mainClosing = false
709
end
710
711
--- Expands and minimizes the sidebar (sideClosed is the toggle boolean)
712
function toggleSideTray(override)
713
if sideClosing and not override or maximized then
714
return
715
end
716
sideClosing = true
717
sideClosed = not sideClosed
718
if sideClosed then
719
rightFadeIn = fadeOut(RightPanel:GetDescendants())
720
wait(0.5)
721
minimizeSize(0.5)
722
wait(0.5)
723
RightPanel.Visible = false
724
else
725
if closed then
726
toggleMinimize(true)
727
end
728
RightPanel.Visible = true
729
maximizeSize(0.5)
730
wait(0.5)
731
if rightFadeIn then
732
rightFadeIn()
733
end
734
bringBackOnResize()
735
end
736
sideClosing = false
737
end
738
739
--- Expands code box to fit screen for more convenient viewing
740
function toggleMaximize()
741
if not sideClosed and not maximized then
742
maximized = true
743
local disable = Instance.new("TextButton")
744
local prevSize = UDim2.new(0, CodeBox.AbsoluteSize.X, 0, CodeBox.AbsoluteSize.Y)
745
local prevPos = UDim2.new(0,CodeBox.AbsolutePosition.X, 0, CodeBox.AbsolutePosition.Y)
746
disable.Size = UDim2.new(1, 0, 1, 0)
747
disable.BackgroundColor3 = Color3.new()
748
disable.BorderSizePixel = 0
749
disable.Text = 0
750
disable.ZIndex = 3
751
disable.BackgroundTransparency = 1
752
disable.AutoButtonColor = false
753
CodeBox.ZIndex = 4
754
CodeBox.Position = prevPos
755
CodeBox.Size = prevSize
756
TweenService:Create(CodeBox, TweenInfo.new(0.5), {Size = UDim2.new(0.5, 0, 0.5, 0), Position = UDim2.new(0.25, 0, 0.25, 0)}):Play()
757
TweenService:Create(disable, TweenInfo.new(0.5), {BackgroundTransparency = 0.5}):Play()
758
disable.MouseButton1Click:Connect(function()
759
if UserInputService:GetMouseLocation().Y + 36 >= CodeBox.AbsolutePosition.Y and UserInputService:GetMouseLocation().Y + 36 <= CodeBox.AbsolutePosition.Y + CodeBox.AbsoluteSize.Y
760
and UserInputService:GetMouseLocation().X >= CodeBox.AbsolutePosition.X and UserInputService:GetMouseLocation().X <= CodeBox.AbsolutePosition.X + CodeBox.AbsoluteSize.X then
761
return
762
end
763
TweenService:Create(CodeBox, TweenInfo.new(0.5), {Size = prevSize, Position = prevPos}):Play()
764
TweenService:Create(disable, TweenInfo.new(0.5), {BackgroundTransparency = 1}):Play()
765
wait(0.5)
766
disable:Destroy()
767
CodeBox.Size = UDim2.new(1, 0, 0.5, 0)
768
CodeBox.Position = UDim2.new(0, 0, 0, 0)
769
CodeBox.ZIndex = 0
770
maximized = false
771
end)
772
end
773
end
774
775
--- Checks if cursor is within resize range
776
--- @param p Vector2
777
function isInResizeRange(p)
778
local relativeP = p - Background.AbsolutePosition
779
local range = 5
780
if relativeP.X >= TopBar.AbsoluteSize.X - range and relativeP.Y >= Background.AbsoluteSize.Y - range
781
and relativeP.X <= TopBar.AbsoluteSize.X and relativeP.Y <= Background.AbsoluteSize.Y then
782
return true, 'B'
783
elseif relativeP.X >= TopBar.AbsoluteSize.X - range and relativeP.X <= Background.AbsoluteSize.X then
784
return true, 'X'
785
elseif relativeP.Y >= Background.AbsoluteSize.Y - range and relativeP.Y <= Background.AbsoluteSize.Y then
786
return true, 'Y'
787
end
788
return false
789
end
790
791
--- Called when mouse enters SimpleSpy
792
function mouseEntered()
793
local customCursor = Instance.new("ImageLabel")
794
customCursor.Size = UDim2.fromOffset(200, 200)
795
customCursor.ZIndex = 1e5
796
customCursor.BackgroundTransparency = 1
797
customCursor.Image = ""
798
customCursor.Parent = SimpleSpy2
799
UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.ForceHide
800
RunService:BindToRenderStep("SIMPLESPY_CURSOR", 1, function()
801
if mouseInGui and _G.SimpleSpyExecuted then
802
local mouseLocation = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
803
customCursor.Position = UDim2.fromOffset(mouseLocation.X - customCursor.AbsoluteSize.X / 2, mouseLocation.Y - customCursor.AbsoluteSize.Y / 2)
804
local inRange, type = isInResizeRange(mouseLocation)
805
if inRange and not sideClosed and not closed then
806
customCursor.Image = type == 'B' and "rbxassetid://6065821980" or type == 'X' and "rbxassetid://6065821086" or type == 'Y' and "rbxassetid://6065821596"
807
elseif inRange and not closed and type == 'Y' or type == 'B' then
808
customCursor.Image = "rbxassetid://6065821596"
809
elseif customCursor.Image ~= "rbxassetid://6065775281" then
810
customCursor.Image = "rbxassetid://6065775281"
811
end
812
else
813
UserInputService.OverrideMouseIconBehavior = Enum.OverrideMouseIconBehavior.None
814
customCursor:Destroy()
815
RunService:UnbindFromRenderStep("SIMPLESPY_CURSOR")
816
end
817
end)
818
end
819
820
--- Called when mouse moves
821
function mouseMoved()
822
local mousePos = UserInputService:GetMouseLocation() - Vector2.new(0, 36)
823
if not closed
824
and mousePos.X >= TopBar.AbsolutePosition.X and mousePos.X <= TopBar.AbsolutePosition.X + TopBar.AbsoluteSize.X
825
and mousePos.Y >= Background.AbsolutePosition.Y and mousePos.Y <= Background.AbsolutePosition.Y + Background.AbsoluteSize.Y then
826
if not mouseInGui then
827
mouseInGui = true
828
mouseEntered()
829
end
830
else
831
mouseInGui = false
832
end
833
end
834
835
--- Adjusts the ui elements to the 'Maximized' size
836
function maximizeSize(speed)
837
if not speed then
838
speed = 0.05
839
end
840
TweenService:Create(LeftPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
841
TweenService:Create(RightPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
842
TweenService:Create(TopBar, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }):Play()
843
TweenService:Create(ScrollingFrame, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, 110), Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
844
TweenService:Create(CodeBox, TweenInfo.new(speed), { Size = UDim2.fromOffset(Background.AbsoluteSize.X - LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
845
TweenService:Create(LogList, TweenInfo.new(speed), { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }):Play()
846
end
847
848
--- Adjusts the ui elements to close the side
849
function minimizeSize(speed)
850
if not speed then
851
speed = 0.05
852
end
853
TweenService:Create(LeftPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
854
TweenService:Create(RightPanel, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y) }):Play()
855
TweenService:Create(TopBar, TweenInfo.new(speed), { Size = UDim2.fromOffset(LeftPanel.AbsoluteSize.X, TopBar.AbsoluteSize.Y) }):Play()
856
TweenService:Create(ScrollingFrame, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, 119), Position = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
857
TweenService:Create(CodeBox, TweenInfo.new(speed), { Size = UDim2.fromOffset(0, Background.AbsoluteSize.Y - 119 - TopBar.AbsoluteSize.Y) }):Play()
858
TweenService:Create(LogList, TweenInfo.new(speed), { Size = UDim2.fromOffset(LogList.AbsoluteSize.X, Background.AbsoluteSize.Y - TopBar.AbsoluteSize.Y - 18) }):Play()
859
end
860
861
--- Called on user input while mouse in 'Background' frame
862
--- @param input InputObject
863
function backgroundUserInput(input)
864
local inRange, type = isInResizeRange(UserInputService:GetMouseLocation() - Vector2.new(0, 36))
865
if input.UserInputType == Enum.UserInputType.MouseButton1 and inRange then
866
local lastPos = UserInputService:GetMouseLocation()
867
local offset = Background.AbsoluteSize - lastPos
868
local currentPos = lastPos + offset
869
RunService:BindToRenderStep("SIMPLESPY_RESIZE", 1, function()
870
local newPos = UserInputService:GetMouseLocation()
871
if newPos ~= lastPos then
872
local currentX = (newPos + offset).X
873
local currentY = (newPos + offset).Y
874
if currentX < 450 then
875
currentX = 450
876
end
877
if currentY < 268 then
878
currentY = 268
879
end
880
currentPos = Vector2.new(currentX, currentY)
881
Background.Size = UDim2.fromOffset((not sideClosed and not closed and (type == "X" or type == "B")) and currentPos.X or Background.AbsoluteSize.X, (--[[(not sideClosed or currentPos.X <= LeftPanel.AbsolutePosition.X + LeftPanel.AbsoluteSize.X) and]] not closed and (type == "Y" or type == "B")) and currentPos.Y or Background.AbsoluteSize.Y)
882
if sideClosed then
883
minimizeSize()
884
else
885
maximizeSize()
886
end
887
lastPos = newPos
888
end
889
end)
890
table.insert(connections, UserInputService.InputEnded:Connect(function(inputE)
891
if input == inputE then
892
RunService:UnbindFromRenderStep("SIMPLESPY_RESIZE")
893
end
894
end))
895
end
896
end
897
898
--- Gets the player an instance is descended from
899
function getPlayerFromInstance(instance)
900
for _, v in pairs(Players:GetPlayers()) do
901
if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
902
return v
903
end
904
end
905
end
906
907
--- Runs on MouseButton1Click of an event frame
908
function eventSelect(frame)
909
if selected and selected.Log then
910
TweenService:Create(selected.Log.Button, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(0, 0, 0)}):Play()
911
selected = nil
912
end
913
for _, v in pairs(logs) do
914
if frame == v.Log then
915
selected = v
916
end
917
end
918
if selected and selected.Log then
919
TweenService:Create(frame.Button, TweenInfo.new(0.5), {BackgroundColor3 = Color3.fromRGB(92, 126, 229)}):Play()
920
codebox:setRaw(selected.GenScript)
921
end
922
if sideClosed then
923
toggleSideTray()
924
end
925
end
926
927
--- Updates the canvas size to fit the current amount of function buttons
928
function updateFunctionCanvas()
929
ScrollingFrame.CanvasSize = UDim2.fromOffset(UIGridLayout.AbsoluteContentSize.X, UIGridLayout.AbsoluteContentSize.Y)
930
end
931
932
--- Updates the canvas size to fit the amount of current remotes
933
function updateRemoteCanvas()
934
LogList.CanvasSize = UDim2.fromOffset(UIListLayout.AbsoluteContentSize.X, UIListLayout.AbsoluteContentSize.Y)
935
end
936
937
--- Allows for toggling of the tooltip and easy setting of le description
938
--- @param enable boolean
939
--- @param text string
940
function makeToolTip(enable, text)
941
if enable then
942
if ToolTip.Visible then
943
ToolTip.Visible = false
944
RunService:UnbindFromRenderStep("ToolTip")
945
end
946
local first = true
947
RunService:BindToRenderStep("ToolTip", 1, function()
948
local topLeft = Vector2.new(Mouse.X + 20, Mouse.Y + 20)
949
local bottomRight = topLeft + ToolTip.AbsoluteSize
950
if topLeft.X < 0 then
951
topLeft = Vector2.new(0, topLeft.Y)
952
elseif bottomRight.X > workspace.CurrentCamera.ViewportSize.X then
953
topLeft = Vector2.new(workspace.CurrentCamera.ViewportSize.X - ToolTip.AbsoluteSize.X, topLeft.Y)
954
end
955
if topLeft.Y < 0 then
956
topLeft = Vector2.new(topLeft.X, 0)
957
elseif bottomRight.Y > workspace.CurrentCamera.ViewportSize.Y - 35 then
958
topLeft = Vector2.new(topLeft.X, workspace.CurrentCamera.ViewportSize.Y - ToolTip.AbsoluteSize.Y - 35)
959
end
960
if topLeft.X <= Mouse.X and topLeft.Y <= Mouse.Y then
961
topLeft = Vector2.new(Mouse.X - ToolTip.AbsoluteSize.X - 2, Mouse.Y - ToolTip.AbsoluteSize.Y - 2)
962
end
963
if first then
964
ToolTip.Position = UDim2.fromOffset(topLeft.X, topLeft.Y)
965
first = false
966
else
967
ToolTip:TweenPosition(UDim2.fromOffset(topLeft.X, topLeft.Y), "Out", "Linear", 0.1)
968
end
969
end)
970
TextLabel.Text = text
971
ToolTip.Visible = true
972
else
973
if ToolTip.Visible then
974
ToolTip.Visible = false
975
RunService:UnbindFromRenderStep("ToolTip")
976
end
977
end
978
end
979
980
--- Creates new function button (below codebox)
981
--- @param name string
982
---@param description function
983
---@param onClick function
984
function newButton(name, description, onClick)
985
local button = FunctionTemplate:Clone()
986
button.Text.Text = name
987
button.Button.MouseEnter:Connect(function()
988
makeToolTip(true, description())
989
end)
990
button.Button.MouseLeave:Connect(function()
991
makeToolTip(false)
992
end)
993
button.AncestryChanged:Connect(function()
994
makeToolTip(false)
995
end)
996
button.Button.MouseButton1Click:Connect(function(...)
997
onClick(button, ...)
998
end)
999
button.Parent = ScrollingFrame
1000
updateFunctionCanvas()
1001
end
1002
1003
--- Adds new Remote to logs
1004
--- @param name string The name of the remote being logged
1005
--- @param type string The type of the remote being logged (either 'function' or 'event')
1006
--- @param gen_script any
1007
--- @param remote any
1008
--- @param function_info string
1009
--- @param blocked any
1010
function newRemote(type, name, gen_script, remote, function_info, blocked, src)
1011
local remoteFrame = RemoteTemplate:Clone()
1012
remoteFrame.Text.Text = name
1013
remoteFrame.ColorBar.BackgroundColor3 = type == "event" and Color3.new(255, 242, 0) or Color3.fromRGB(99, 86, 245)
1014
local id = Instance.new("IntValue")
1015
id.Name = "ID"
1016
id.Value = #logs + 1
1017
id.Parent = remoteFrame
1018
logs[#logs + 1] = {
1019
Name = name,
1020
GenScript = gen_script,
1021
Function = function_info,
1022
Remote = remote,
1023
Log = remoteFrame,
1024
Blocked = blocked,
1025
Source = src
1026
}
1027
if blocked then
1028
logs[#logs].GenScript = "-- THIS REMOTE WAS PREVENTED FROM FIRING THE SERVER BY SIMPLESPY\n\n" .. logs[#logs].GenScript
1029
end
1030
local connect = remoteFrame.Button.MouseButton1Click:Connect(function()
1031
eventSelect(remoteFrame)
1032
end)
1033
if layoutOrderNum < 1 then
1034
layoutOrderNum = 999999999
1035
end
1036
remoteFrame.LayoutOrder = layoutOrderNum
1037
layoutOrderNum = layoutOrderNum - 1
1038
remoteFrame.Parent = LogList
1039
table.insert(remoteLogs, 1, {connect, remoteFrame})
1040
clean()
1041
updateRemoteCanvas()
1042
end
1043
1044
--- Generates a script from the provided arguments (first has to be remote path)
1045
function genScript(remote, ...)
1046
prevTables = {}
1047
local gen = ""
1048
local args = {...}
1049
if #args > 0 then
1050
if not pcall(function()
1051
gen = v2v({args = args}) .. "\n"
1052
end)
1053
then
1054
gen = gen .. "-- TableToString failure! Reverting to legacy functionality (results may vary)\nlocal args = {"
1055
if
1056
not pcall(
1057
function()
1058
for i, v in pairs(args) do
1059
if type(i) ~= "Instance" and type(i) ~= "userdata" then
1060
gen = gen .. "\n [" .. tostring(i) .. "] = "
1061
elseif type(i) == "string" then
1062
gen = gen .. '\n ["' .. tostring(i) .. '"] = '
1063
elseif type(i) == "userdata" and typeof(i) ~= "Instance" then
1064
gen = gen .. "\n [" .. typeof(i) .. ".new(" .. tostring(i) .. ")] = "
1065
elseif type(i) == "userdata" then
1066
gen = gen .. "\n [game." .. i:GetFullName() .. ")] = "
1067
end
1068
if type(v) ~= "Instance" and type(v) ~= "userdata" then
1069
gen = gen .. tostring(v)
1070
elseif type(v) == "string" then
1071
gen = gen .. '"' .. tostring(v) .. '"'
1072
elseif type(v) == "userdata" and typeof(v) ~= "Instance" then
1073
gen = gen .. typeof(v) .. ".new(" .. tostring(v) .. ")"
1074
elseif type(v) == "userdata" then
1075
gen = gen .. "game." .. v:GetFullName()
1076
end
1077
end
1078
gen = gen .. "\n}\n\n"
1079
end
1080
)
1081
then
1082
gen = gen .. "}\n-- Legacy tableToString failure! Unable to decompile."
1083
end
1084
end
1085
if not remote:IsDescendantOf(game) and not getnilrequired then
1086
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" .. gen
1087
end
1088
if remote:IsA("RemoteEvent") then
1089
gen = gen .. v2s(remote) .. ":FireServer(unpack(args))"
1090
elseif remote:IsA("RemoteFunction") then
1091
gen = gen .. v2s(remote) .. ":InvokeServer(unpack(args))"
1092
end
1093
else
1094
if remote:IsA("RemoteEvent") then
1095
gen = gen .. v2s(remote) .. ":FireServer()"
1096
elseif remote:IsA("RemoteFunction") then
1097
gen = gen .. v2s(remote) .. ":InvokeServer()"
1098
end
1099
end
1100
gen = "" .. gen
1101
prevTables = {}
1102
return gen
1103
end
1104
1105
--- value-to-string: value, string (out), level (indentation), parent table, var name, is from tovar
1106
function v2s(v, l, p, n, vtv, i, pt, path, tables)
1107
if typeof(v) == "number" then
1108
if v == math.huge then
1109
return "math.huge"
1110
elseif tostring(v):match("nan") then
1111
return "0/0 --[[NaN]]"
1112
end
1113
return tostring(v)
1114
elseif typeof(v) == "boolean" then
1115
return tostring(v)
1116
elseif typeof(v) == "string" then
1117
return formatstr(v)
1118
elseif typeof(v) == "function" then
1119
return f2s(v)
1120
elseif typeof(v) == "table" then
1121
return t2s(v, l, p, n, vtv, i, pt, path, tables)
1122
elseif typeof(v) == "Instance" then
1123
return i2p(v)
1124
elseif typeof(v) == "userdata" then
1125
return "newproxy(true)"
1126
elseif type(v) == "userdata" then
1127
return u2s(v)
1128
else
1129
return "nil --[[" .. typeof(v) .. "]]"
1130
end
1131
end
1132
1133
--- value-to-variable
1134
--- @param t any
1135
function v2v(t)
1136
topstr = ""
1137
bottomstr = ""
1138
getnilrequired = false
1139
local ret = ""
1140
local count = 1
1141
for i, v in pairs(t) do
1142
if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
1143
ret = ret .. "local " .. i .. " = " .. v2s(v, nil, nil, i, true) .. "\n"
1144
elseif tostring(i):match("^[%a_]+[%w_]*$") then
1145
ret = ret .. "local " .. tostring(i):lower() .. "_" .. tostring(count) .. " = " .. v2s(v, nil, nil, tostring(i):lower() .. "_" .. tostring(count), true) .. "\n"
1146
else
1147
ret = ret .. "local " .. type(v) .. "_" .. tostring(count) .. " = " .. v2s(v, nil, nil, type(v) .. "_" .. tostring(count), true) .. "\n"
1148
end
1149
count = count + 1
1150
end
1151
if getnilrequired then
1152
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" .. topstr
1153
end
1154
if #topstr > 0 then
1155
ret = topstr .. "\n" .. ret
1156
end
1157
if #bottomstr > 0 then
1158
ret = ret .. bottomstr
1159
end
1160
return ret
1161
end
1162
1163
--- table-to-string
1164
--- @param t table
1165
--- @param l number
1166
--- @param p table
1167
--- @param n string
1168
--- @param vtv boolean
1169
--- @param i any
1170
--- @param pt table
1171
--- @param path string
1172
--- @param tables table
1173
function t2s(t, l, p, n, vtv, i, pt, path, tables)
1174
for k, x in pairs(getrenv()) do
1175
local isgucci, gpath
1176
if rawequal(x, t) then
1177
isgucci, gpath = true, ""
1178
elseif type(x) == "table" then
1179
isgucci, gpath = v2p(t, x)
1180
end
1181
if isgucci then
1182
if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
1183
return k .. gpath
1184
else
1185
return "getrenv()[" .. v2s(k) .. "]" .. gpath
1186
end
1187
end
1188
end
1189
if not path then
1190
path = ""
1191
end
1192
if not l then
1193
l = 0
1194
tables = {}
1195
end
1196
if not p then
1197
p = t
1198
end
1199
for _, v in pairs(tables) do
1200
if n and rawequal(v, t) then
1201
bottomstr = bottomstr .. "\n" .. tostring(n) .. tostring(path) .. " = " .. tostring(n) .. tostring(({v2p(v, p)})[2])
1202
return "{} --[[DUPLICATE]]"
1203
end
1204
end
1205
table.insert(tables, t)
1206
local s = "{"
1207
local size = 0
1208
l = l + indent
1209
for k, v in pairs(t) do
1210
size = size + 1
1211
if size > (_G.SimpleSpyMaxTableSize and _G.SimpleSpyMaxTableSize or 1000) then
1212
break
1213
end
1214
if rawequal(k, t) then
1215
bottomstr = bottomstr .. "\n" .. tostring(n) .. tostring(path) .. "[" .. tostring(n) .. tostring(path) .. "]" .. " = " .. (v == k and tostring(n) .. tostring(path) or v2s(v, l, p, n, vtv, k, t, path .. "[" .. tostring(n) .. tostring(path) .. "]", tables))
1216
size -= 1
1217
continue
1218
end
1219
local currentPath = ""
1220
if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
1221
currentPath = "." .. k
1222
else
1223
currentPath = "[" .. v2s(k, nil, p, n, vtv, i, pt, path) .. "]"
1224
end
1225
s = s .. "\n" .. string.rep(" ", l) .. "[" .. v2s(k, l, p, n, vtv, k, t, path .. currentPath, tables) .. "] = " .. v2s(v, l, p, n, vtv, k, t, path .. currentPath, tables) .. ","
1226
end
1227
if #s > 1 then
1228
s = s:sub(1, #s - 1)
1229
end
1230
if size > 0 then
1231
s = s .. "\n" .. string.rep(" ", l - indent)
1232
end
1233
return s .. "}"
1234
end
1235
1236
--- function-to-string
1237
function f2s(f)
1238
for k, x in pairs(getgenv()) do
1239
local isgucci, gpath
1240
if rawequal(x, f) then
1241
isgucci, gpath = true, ""
1242
elseif type(x) == "table" then
1243
isgucci, gpath = v2p(f, x)
1244
end
1245
if isgucci then
1246
if type(k) == "string" and k:match("^[%a_]+[%w_]*$") then
1247
return k .. gpath
1248
else
1249
return "getgenv()[" .. v2s(k) .. "]" .. gpath
1250
end
1251
end
1252
end
1253
-- uwu some cool stuff here once bork finishes up
1254
-- if SimpleSpy.GetExternalLoader then
1255
-- local ExternalLoader = SimpleSpy:GetExternalLoader()
1256
-- local loaded, path = pcall(function() ExternalLoader:LoadAsset("Bork_Functions") end)
1257
-- if loaded then
1258
-- local functions = loadfile(path .. "functions.lua")
1259
-- local out = functions[f]
1260
-- if out then
1261
-- return out
1262
-- end
1263
-- end
1264
-- end
1265
-- local isgucci, gpath = v2p(f, getgc())
1266
-- if isgucci then
1267
-- return "getgc()" .. gpath
1268
-- end
1269
if debug.getinfo(f).name:match("^[%a_]+[%w_]*$") then
1270
return "function()end --[[" .. debug.getinfo(f).name .. "]]"
1271
end
1272
return "function()end --[[" .. tostring(f) .. "]]"
1273
end
1274
1275
--- instance-to-path
1276
--- @param i userdata
1277
function i2p(i)
1278
local player = getplayer(i)
1279
local parent = i
1280
local out = ""
1281
if parent == nil then
1282
return "nil"
1283
elseif player then
1284
while true do
1285
if parent and parent == player.Character then
1286
if player == Players.LocalPlayer then
1287
return 'game:GetService("Players").LocalPlayer.Character' .. out
1288
else
1289
return i2p(player) .. ".Character" .. out
1290
end
1291
else
1292
if parent.Name:match("[%a_]+[%w+]*") ~= parent.Name then
1293
out = '[' .. formatstr(parent.Name) .. ']' .. out
1294
else
1295
out = "." .. parent.Name .. out
1296
end
1297
end
1298
parent = parent.Parent
1299
end
1300
elseif parent ~= game then
1301
while true do
1302
if parent and parent.Parent == game then
1303
if game:GetService(parent.ClassName) then
1304
if parent.ClassName == "Workspace" then
1305
return "workspace" .. out
1306
else
1307
return 'game:GetService("' .. parent.ClassName .. '")' .. out
1308
end
1309
else
1310
if parent.Name:match("[%a_]+[%w_]*") then
1311
return "game." .. parent.Name .. out
1312
else
1313
return 'game[' .. formatstr(parent.Name) .. ']' .. out
1314
end
1315
end
1316
elseif parent.Parent == nil then
1317
getnilrequired = true
1318
return 'getNil(' .. formatstr(parent.Name) .. ', "' .. parent.ClassName .. '")' .. out
1319
elseif parent == Players.LocalPlayer then
1320
out = ".LocalPlayer" .. out
1321
else
1322
if parent.Name:match("[%a_]+[%w_]*") ~= parent.Name then
1323
out = '[' .. formatstr(parent.Name) .. ']' .. out
1324
else
1325
out = "." .. parent.Name .. out
1326
end
1327
end
1328
parent = parent.Parent
1329
end
1330
else
1331
return "game"
1332
end
1333
end
1334
1335
--- userdata-to-string: userdata
1336
--- @param u userdata
1337
function u2s(u)
1338
if typeof(u) == "TweenInfo" then
1339
-- TweenInfo
1340
return "TweenInfo.new(" ..tostring(u.Time) .. ", Enum.EasingStyle." .. tostring(u.EasingStyle) .. ", Enum.EasingDirection." .. tostring(u.EasingDirection) .. ", " .. tostring(u.RepeatCount) .. ", " .. tostring(u.Reverses) .. ", " .. tostring(u.DelayTime) .. ")"
1341
elseif typeof(u) == "Ray" then
1342
-- Ray
1343
return "Ray.new(" .. u2s(u.Origin) .. ", " .. u2s(u.Direction) .. ")"
1344
elseif typeof(u) == "NumberSequence" then
1345
-- NumberSequence
1346
local ret = "NumberSequence.new("
1347
for i, v in pairs(u.KeyPoints) do
1348
ret = ret .. tostring(v)
1349
if i < #u.Keypoints then
1350
ret = ret .. ", "
1351
end
1352
end
1353
return ret .. ")"
1354
elseif typeof(u) == "DockWidgetPluginGuiInfo" then
1355
-- DockWidgetPluginGuiInfo
1356
return "DockWidgetPluginGuiInfo.new(Enum.InitialDockState" .. tostring(u) .. ")"
1357
elseif typeof(u) == "ColorSequence" then
1358
-- ColorSequence
1359
local ret = "ColorSequence.new("
1360
for i, v in pairs(u.KeyPoints) do
1361
ret = ret .. "Color3.new(" .. tostring(v) .. ")"
1362
if i < #u.Keypoints then
1363
ret = ret .. ", "
1364
end
1365
end
1366
return ret .. ")"
1367
elseif typeof(u) == "BrickColor" then
1368
-- BrickColor
1369
return "BrickColor.new(" .. tostring(u.Number) .. ")"
1370
elseif typeof(u) == "NumberRange" then
1371
-- NumberRange
1372
return "NumberRange.new(" .. tostring(u.Min) .. ", " .. tostring(u.Max) .. ")"
1373
elseif typeof(u) == "Region3" then
1374
-- Region3
1375
local center = u.CFrame.Position
1376
local size = u.CFrame.Size
1377
local vector1 = center - size / 2
1378
local vector2 = center + size / 2
1379
return "Region3.new(" .. u2s(vector1) .. ", " .. u2s(vector2) .. ")"
1380
elseif typeof(u) == "Faces" then
1381
-- Faces
1382
local faces = {}
1383
if u.Top then
1384
table.insert(faces, "Enum.NormalId.Top")
1385
end
1386
if u.Bottom then
1387
table.insert(faces, "Enum.NormalId.Bottom")
1388
end
1389
if u.Left then
1390
table.insert(faces, "Enum.NormalId.Left")
1391
end
1392
if u.Right then
1393
table.insert(faces, "Enum.NormalId.Right")
1394
end
1395
if u.Back then
1396
table.insert(faces, "Enum.NormalId.Back")
1397
end
1398
if u.Front then
1399
table.insert(faces, "Enum.NormalId.Front")
1400
end
1401
return "Faces.new(" .. table.concat(faces, ", ") .. ")"
1402
elseif typeof(u) == "EnumItem" then
1403
return tostring(u)
1404
elseif typeof(u) == "Enums" then
1405
return "Enum"
1406
elseif typeof(u) == "Enum" then
1407
return "Enum." .. tostring(u)
1408
elseif typeof(u) == "RBXScriptSignal" then
1409
return "nil --[[RBXScriptSignal]]"
1410
elseif typeof(u) == "Vector3" then
1411
return string.format("Vector3.new(%s, %s, %s)", v2s(u.X), v2s(u.Y), v2s(u.Z))
1412
elseif typeof(u) == "CFrame" then
1413
return string.format("CFrame.new(%s, %s)", v2s(u.Position), v2s(u.LookVector))
1414
elseif typeof(u) == "DockWidgetPluginGuiInfo" then
1415
return string.format("DockWidgetPluginGuiInfo(%s, %s, %s, %s, %s, %s, %s)", "Enum.InitialDockState.Right", v2s(u.InitialEnabled), v2s(u.InitialEnabledShouldOverrideRestore), v2s(u.FloatingXSize), v2s(u.FloatingYSize), v2s(u.MinWidth), v2s(u.MinHeight))
1416
elseif typeof(u) == "RBXScriptConnection" then
1417
return "nil --[[RBXScriptConnection " .. tostring(u) .. "]]"
1418
elseif typeof(u) == "RaycastResult" then
1419
return "nil --[[RaycastResult " .. tostring(u) .. "]]"
1420
elseif typeof(u) == "PathWaypoint" then
1421
return string.format("PathWaypoint.new(%s, %s)", v2s(u.Position), v2s(u.Action))
1422
else
1423
return typeof(u) .. ".new(" .. tostring(u) .. ")"
1424
end
1425
end
1426
1427
--- Gets the player an instance is descended from
1428
function getplayer(instance)
1429
for _, v in pairs(Players:GetPlayers()) do
1430
if v.Character and (instance:IsDescendantOf(v.Character) or instance == v.Character) then
1431
return v
1432
end
1433
end
1434
end
1435
1436
--- value-to-path (in table)
1437
function v2p(x, t, path, prev)
1438
if not path then
1439
path = ""
1440
end
1441
if not prev then
1442
prev = {}
1443
end
1444
if rawequal(x, t) then
1445
return true, ""
1446
end
1447
for i, v in pairs(t) do
1448
if rawequal(v, x) then
1449
if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
1450
return true, (path .. "." .. i)
1451
else
1452
return true, (path .. "[" .. v2s(i) .. "]")
1453
end
1454
end
1455
if type(v) == "table" then
1456
local duplicate = false
1457
for _, y in pairs(prev) do
1458
if rawequal(y, v) then
1459
duplicate = true
1460
end
1461
end
1462
if not duplicate then
1463
table.insert(prev, t)
1464
local found
1465
found, p = v2p(x, v, path, prev)
1466
if found then
1467
if type(i) == "string" and i:match("^[%a_]+[%w_]*$") then
1468
return true, "." .. i .. p
1469
else
1470
return true, "[" .. v2s(i) .. "]" .. p
1471
end
1472
end
1473
end
1474
end
1475
end
1476
return false, ""
1477
end
1478
1479
--- format s: string, byte encrypt (for weird symbols)
1480
function formatstr(s)
1481
return '"' .. handlespecials(s) .. '"'
1482
end
1483
1484
--- Adds \'s to the text as a replacement to whitespace chars and other things because string.format can't yayeet
1485
function handlespecials(s)
1486
local i = 0
1487
repeat
1488
i = i + 1
1489
local char = s:sub(i, i)
1490
if string.byte(char) then
1491
if char == "\n" then
1492
s = s:sub(0, i - 1) .. "\\n" .. s:sub(i + 1, -1)
1493
i = i + 1
1494
elseif char == "\t" then
1495
s = s:sub(0, i - 1) .. "\\t" .. s:sub(i + 1, -1)
1496
i = i + 1
1497
elseif char == "\\" then
1498
s = s:sub(0, i - 1) .. "\\\\" .. s:sub(i + 1, -1)
1499
i = i + 1
1500
elseif char == '"' then
1501
s = s:sub(0, i - 1) .. '\\"' .. s:sub(i + 1, -1)
1502
i = i + 1
1503
elseif string.byte(char) > 126 or string.byte(char) < 32 then
1504
s = s:sub(0, i - 1) .. "\\" .. string.byte(char) .. s:sub(i + 1, -1)
1505
i = i + #tostring(string.byte(char))
1506
end
1507
end
1508
until char == ""
1509
return s
1510
end
1511
1512
--- finds script from 'src' from getinfo, returns nil if not found
1513
--- @param src string
1514
function getScriptFromSrc(src)
1515
local realPath
1516
local runningTest
1517
--- @type number
1518
local s, e
1519
local match = false
1520
if src:sub(1, 1) == "=" then
1521
realPath = game
1522
s = 2
1523
else
1524
runningTest = src:sub(2, e and e - 1 or -1)
1525
for _, v in pairs(getnilinstances()) do
1526
if v.Name == runningTest then
1527
realPath = v
1528
break
1529
end
1530
end
1531
s = #runningTest + 1
1532
end
1533
if realPath then
1534
e = src:sub(s, -1):find("%.")
1535
local i = 0
1536
repeat
1537
i += 1
1538
if not e then
1539
runningTest = src:sub(s, -1)
1540
local test = realPath.FindFirstChild(realPath, runningTest)
1541
if test then
1542
realPath = test
1543
end
1544
match = true
1545
else
1546
runningTest = src:sub(s, e)
1547
local test = realPath.FindFirstChild(realPath, runningTest)
1548
local yeOld = e
1549
if test then
1550
realPath = test
1551
s = e + 2
1552
e = src:sub(e + 2, -1):find("%.")
1553
e = e and e + yeOld or e
1554
else
1555
e = src:sub(e + 2, -1):find("%.")
1556
e = e and e + yeOld or e
1557
end
1558
end
1559
until match or i >= 50
1560
end
1561
return realPath
1562
end
1563
1564
--- schedules the provided function (and calls it with any args after)
1565
function schedule(f, ...)
1566
table.insert(scheduled, {f, ...})
1567
end
1568
1569
--- the big (well tbh small now) boi task scheduler himself, handles p much anything as quicc as possible
1570
function taskscheduler()
1571
if not toggle then
1572
scheduled = {}
1573
return
1574
end
1575
if #scheduled > 1000 then
1576
table.remove(scheduled, #scheduled)
1577
end
1578
if #scheduled > 0 then
1579
local currentf = scheduled[1]
1580
table.remove(scheduled, 1)
1581
if type(currentf) == "table" and type(currentf[1]) == "function" then
1582
pcall(unpack(currentf))
1583
end
1584
end
1585
end
1586
1587
--- Handles remote logs
1588
function remoteHandler(hookfunction, methodName, remote, args, func, calling)
1589
if remote:IsA("RemoteEvent") or remote:IsA("RemoteFunction") then
1590
if funcEnabled and not calling then
1591
_, calling = pcall(getScriptFromSrc, debug.getinfo(func).source)
1592
end
1593
coroutine.wrap(function()
1594
if remoteSignals[remote] then
1595
remoteSignals[remote]:Fire(args)
1596
end
1597
end)()
1598
if autoblock then
1599
if excluding[remote] then
1600
return
1601
end
1602
if not history[remote] then
1603
history[remote] = {badOccurances = 0, lastCall = tick()}
1604
end
1605
if tick() - history[remote].lastCall < 1 then
1606
history[remote].badOccurances += 1
1607
return
1608
else
1609
history[remote].badOccurances = 0
1610
end
1611
if history[remote].badOccurances > 3 then
1612
excluding[remote] = true
1613
return
1614
end
1615
history[remote].lastCall = tick()
1616
end
1617
local functionInfoStr
1618
local src
1619
if func and islclosure(func) then
1620
local functionInfo = {}
1621
pcall(function() functionInfo.info = debug.getinfo(func) end)
1622
pcall(function() functionInfo.constants = debug.getconstants(func) end)
1623
pcall(function() functionInfoStr = v2v{functionInfo = functionInfo} end)
1624
pcall(function() if type(calling) == "userdata" then src = calling end end)
1625
end
1626
if methodName:lower() == "fireserver" then
1627
newRemote("event", remote.Name, genScript(remote, table.unpack(args)), remote, functionInfoStr, (blocklist[remote] or blocklist[remote.Name]), src)
1628
elseif methodName:lower() == "invokeserver" then
1629
newRemote("function", remote.Name, genScript(remote, table.unpack(args)), remote, functionInfoStr, (blocklist[remote] or blocklist[remote.Name]), src)
1630
end
1631
end
1632
end
1633
1634
--- Used for hookfunction
1635
function hookRemote(remoteType, remote, ...)
1636
local args = {...}
1637
if remoteHooks[remote] then
1638
args = remoteHooks[remote](args)
1639
end
1640
if typeof(remote) == "Instance" and not (blacklist[remote] or blacklist[remote.Name]) then
1641
local func
1642
local calling
1643
if funcEnabled then
1644
func = debug.getinfo(4).func
1645
calling = useGetCallingScript and getcallingscript() or nil
1646
end
1647
schedule(remoteHandler, true, remoteType == "RemoteEvent" and "fireserver" or "invokeserver", remote, args, func, calling)
1648
if (blocklist[remote] or blocklist[remote.Name]) then
1649
return
1650
end
1651
end
1652
if remoteType == "RemoteEvent" then
1653
if remoteHooks[remote] then
1654
return originalEvent(remote, unpack(args))
1655
end
1656
return originalEvent(remote, ...)
1657
else
1658
if remoteHooks[remote] then
1659
return originalFunction(remote, unpack(args))
1660
end
1661
return originalFunction(remote, ...)
1662
end
1663
end
1664
1665
local newnamecall = newcclosure(function(...)
1666
local args = {...}
1667
local methodName = getnamecallmethod()
1668
local remote = args[1]
1669
if (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and not (blacklist[remote] or blacklist[remote.Name]) then
1670
if remoteHooks[remote] then
1671
args = remoteHooks[remote]({args, unpack(args, 2)})
1672
end
1673
local func
1674
local calling
1675
if funcEnabled then
1676
func = debug.getinfo(3).func
1677
calling = useGetCallingScript and getcallingscript() or nil
1678
end
1679
coroutine.wrap(function()
1680
schedule(remoteHandler, false, methodName, remote, {unpack(args, 2)}, func, calling)
1681
end)()
1682
end
1683
if typeof(remote) == "Instance" and (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and (blocklist[remote] or blocklist[remote.Name]) then
1684
return nil
1685
elseif (methodName:lower() == "invokeserver" or methodName:lower() == "fireserver") and remoteHooks[remote] then
1686
return original(unpack(args))
1687
else
1688
return original(...)
1689
end
1690
end)
1691
1692
local newFireServer = newcclosure(function(...) return hookRemote("RemoteEvent", ...) end)
1693
1694
local newInvokeServer = newcclosure(function(...) return hookRemote("RemoteFunction", ...) end)
1695
1696
--- Toggles on and off the remote spy
1697
function toggleSpy()
1698
if not toggle then
1699
setreadonly(gm, false)
1700
if not original then
1701
original = gm.__namecall
1702
if not original then
1703
warn("SimpleSpy: namecall method not found!\n")
1704
onToggleButtonClick()
1705
return
1706
end
1707
end
1708
gm.__namecall = newnamecall
1709
originalEvent = hookfunction(remoteEvent.FireServer, newFireServer)
1710
originalFunction = hookfunction(remoteFunction.InvokeServer, newInvokeServer)
1711
else
1712
setreadonly(gm, false)
1713
gm.__namecall = original
1714
hookfunction(remoteEvent.FireServer, originalEvent)
1715
hookfunction(remoteFunction.InvokeServer, originalFunction)
1716
end
1717
end
1718
1719
--- Toggles between the two remotespy methods (hookfunction currently = disabled)
1720
function toggleSpyMethod()
1721
toggleSpy()
1722
toggle = not toggle
1723
end
1724
1725
--- Shuts down the remote spy
1726
function shutdown()
1727
if schedulerconnect then
1728
schedulerconnect:Disconnect()
1729
end
1730
for _, connection in pairs(connections) do
1731
coroutine.wrap(function()
1732
connection:Disconnect()
1733
end)()
1734
end
1735
setreadonly(gm, false)
1736
SimpleSpy2:Destroy()
1737
hookfunction(remoteEvent.FireServer, originalEvent)
1738
hookfunction(remoteFunction.InvokeServer, originalFunction)
1739
gm.__namecall = original
1740
_G.SimpleSpyExecuted = false
1741
end
1742
1743
-- main
1744
if not _G.SimpleSpyExecuted then
1745
local succeeded, err = pcall(function()
1746
_G.SimpleSpyShutdown = shutdown
1747
ContentProvider:PreloadAsync({"rbxassetid://6065821980", "rbxassetid://6065774948", "rbxassetid://6065821086", "rbxassetid://6065821596", ImageLabel, ImageLabel_2, ImageLabel_3})
1748
onToggleButtonClick()
1749
RemoteTemplate.Parent = nil
1750
FunctionTemplate.Parent = nil
1751
codebox = Highlight.new(CodeBox)
1752
codebox:setRaw("")
1753
getgenv().SimpleSpy = SimpleSpy
1754
TextLabel:GetPropertyChangedSignal("Text"):Connect(scaleToolTip)
1755
TopBar.InputBegan:Connect(onBarInput)
1756
MinimizeButton.MouseButton1Click:Connect(toggleMinimize)
1757
MaximizeButton.MouseButton1Click:Connect(toggleSideTray)
1758
Simple.MouseButton1Click:Connect(onToggleButtonClick)
1759
CloseButton.MouseEnter:Connect(onXButtonHover)
1760
CloseButton.MouseLeave:Connect(onXButtonUnhover)
1761
Simple.MouseEnter:Connect(onToggleButtonHover)
1762
Simple.MouseLeave:Connect(onToggleButtonUnhover)
1763
CloseButton.MouseButton1Click:Connect(shutdown)
1764
table.insert(connections, UserInputService.InputBegan:Connect(backgroundUserInput))
1765
table.insert(connections, Mouse.Move:Connect(mouseMoved))
1766
connectResize()
1767
SimpleSpy2.Enabled = true
1768
coroutine.wrap(function()
1769
wait(1)
1770
onToggleButtonUnhover()
1771
end)()
1772
schedulerconnect = RunService.Heartbeat:Connect(taskscheduler)
1773
if syn and syn.protect_gui then pcall(syn.protect_gui, SimpleSpy2) end
1774
SimpleSpy2.Parent = gethui and gethui() or CoreGui
1775
end)
1776
if succeeded then
1777
_G.SimpleSpyExecuted = true
1778
else
1779
warn("A fatal error has occured, SimpleSpy was unable to launch properly.\nPlease DM this error message to @exx#9394:\n\n" .. tostring(err))
1780
SimpleSpy2:Destroy()
1781
hookfunction(remoteEvent.FireServer, originalEvent)
1782
hookfunction(remoteFunction.InvokeServer, originalFunction)
1783
gm.__namecall = original
1784
return
1785
end
1786
else
1787
SimpleSpy2:Destroy()
1788
return
1789
end
1790
1791
----- ADD ONS ----- (easily add or remove additonal functionality to the RemoteSpy!)
1792
--[[
1793
Some helpful things:
1794
- add your function in here, and create buttons for them through the 'newButton' function
1795
- the first argument provided is the TextButton the player clicks to run the function
1796
- generated scripts are generated when the namecall is initially fired and saved in remoteFrame objects
1797
- blacklisted remotes will be ignored directly in namecall (less lag)
1798
- the properties of a 'remoteFrame' object:
1799
{
1800
Name: (string) The name of the Remote
1801
GenScript: (string) The generated script that appears in the codebox (generated when namecall fired)
1802
Source: (Instance (LocalScript)) The script that fired/invoked the remote
1803
Remote: (Instance (RemoteEvent) | Instance (RemoteFunction)) The remote that was fired/invoked
1804
Log: (Instance (TextButton)) The button being used for the remote (same as 'selected.Log')
1805
}
1806
- globals list: (contact @exx#9394 for more information or if you have suggestions for more to be added)
1807
- closed: (boolean) whether or not the GUI is currently minimized
1808
- logs: (table[remoteFrame]) full of remoteFrame objects (properties listed above)
1809
- selected: (remoteFrame) the currently selected remoteFrame (properties listed above)
1810
- blacklist: (string[] | Instance[] (RemoteEvent) | Instance[] (RemoteFunction)) an array of blacklisted names and remotes
1811
- codebox: (Instance (TextBox)) the textbox that holds all the code- cleared often
1812
]]
1813
-- Copies the contents of the codebox
1814
newButton(
1815
"Copy Code",
1816
function() return "Click to copy code" end,
1817
function()
1818
setclipboard(codebox:getString())
1819
TextLabel.Text = "Copied successfully!"
1820
end
1821
)
1822
1823
--- Copies the source script (that fired the remote)
1824
newButton(
1825
"Copy Remote",
1826
function() return "Click to copy the path of the remote" end,
1827
function()
1828
if selected then
1829
setclipboard(v2s(selected.Remote))
1830
TextLabel.Text = "Copied!"
1831
end
1832
end
1833
)
1834
1835
-- Executes the contents of the codebox through loadstring
1836
newButton(
1837
"Run Code",
1838
function() return "Click to execute code" end,
1839
function()
1840
local orText = "Click to execute code"
1841
TextLabel.Text = "Executing..."
1842
local succeeded = pcall(function() return loadstring(codebox:getString())() end)
1843
if succeeded then
1844
TextLabel.Text = "Executed successfully!"
1845
else
1846
TextLabel.Text = "Execution error!"
1847
end
1848
end
1849
)
1850
1851
--- Gets the calling script (not super reliable but w/e)
1852
newButton(
1853
"Get Script",
1854
function() return "Click to copy calling script to clipboard\nWARNING: Not super reliable, nil == could not find" end,
1855
function()
1856
if selected then
1857
setclipboard(SimpleSpy:ValueToString(selected.Source))
1858
TextLabel.Text = "Done!"
1859
end
1860
end
1861
)
1862
1863
--- Decompiles the script that fired the remote and puts it in the code box
1864
newButton(
1865
"Function Info",
1866
function() return "Click to view calling function information" end,
1867
function()
1868
if selected then
1869
if selected.Function then
1870
codebox:setRaw("-- Calling function info\n-- Generated by the SimpleSpy serializer\n\n" .. tostring(selected.Function))
1871
end
1872
TextLabel.Text = "Done! Function info generated by the SimpleSpy Serializer."
1873
end
1874
end
1875
)
1876
1877
--- Clears the Remote logs
1878
newButton(
1879
"Clr Logs",
1880
function() return "Click to clear logs" end,
1881
function()
1882
TextLabel.Text = "Clearing..."
1883
logs = {}
1884
for _, v in pairs(LogList:GetChildren()) do
1885
if not v:IsA("UIListLayout") then
1886
v:Destroy()
1887
end
1888
end
1889
codebox:setRaw("")
1890
selected = nil
1891
TextLabel.Text = "Logs cleared!"
1892
end
1893
)
1894
1895
--- Excludes the selected.Log Remote from the RemoteSpy
1896
newButton(
1897
"Exclude (i)",
1898
function() return "Click to exclude this Remote" end,
1899
function()
1900
if selected then
1901
blacklist[selected.Remote] = true
1902
TextLabel.Text = "Excluded!"
1903
end
1904
end
1905
)
1906
1907
--- Excludes all Remotes that share the same name as the selected.Log remote from the RemoteSpy
1908
newButton(
1909
"Exclude (n)",
1910
function() return "Click to exclude all remotes with this name" end,
1911
function()
1912
if selected then
1913
blacklist[selected.Name] = true
1914
TextLabel.Text = "Excluded!"
1915
end
1916
end
1917
)
1918
1919
--- clears blacklist
1920
newButton(
1921
"Clr Blacklist",
1922
function() return "Click to clear the blacklist" end,
1923
function()
1924
blacklist = {}
1925
TextLabel.Text = "Blacklist cleared!"
1926
end
1927
)
1928
1929
--- Prevents the selected.Log Remote from firing the server (still logged)
1930
newButton(
1931
"Block (i)",
1932
function() return "Click to stop this remote from firing" end,
1933
function()
1934
if selected then
1935
blocklist[selected.Remote] = true
1936
TextLabel.Text = "Excluded!"
1937
end
1938
end
1939
)
1940
1941
--- Prevents all remotes from firing that share the same name as the selected.Log remote from the RemoteSpy (still logged)
1942
newButton(
1943
"Block (n)",
1944
function() return "Click to stop remotes with this name from firing" end,
1945
function()
1946
if selected then
1947
blocklist[selected.Name] = true
1948
TextLabel.Text = "Excluded!"
1949
end
1950
end
1951
)
1952
1953
--- clears blacklist
1954
newButton(
1955
"Clr Blocklist",
1956
function() return "Click to stop blocking remotes" end,
1957
function()
1958
blocklist = {}
1959
TextLabel.Text = "Blocklist cleared!"
1960
end
1961
)
1962
1963
--- Attempts to decompile the source script
1964
newButton(
1965
"Decompile",
1966
function() return "Attempts to decompile source script\nWARNING: Not super reliable, nil == could not find" end,
1967
function()
1968
if selected then
1969
if selected.Source then
1970
codebox:setRaw(decompile(selected.Source))
1971
TextLabel.Text = "Done!"
1972
else
1973
TextLabel.Text = "Source not found!"
1974
end
1975
end
1976
end
1977
)
1978
1979
newButton(
1980
"Disable Info",
1981
function() return string.format("[%s] Toggle function info (because it can cause lag in some games)", funcEnabled and "ENABLED" or "DISABLED") end,
1982
function()
1983
funcEnabled = not funcEnabled
1984
TextLabel.Text = string.format("[%s] Toggle function info (because it can cause lag in some games)", funcEnabled and "ENABLED" or "DISABLED")
1985
end
1986
)
1987
1988
newButton(
1989
"Autoblock",
1990
function() return string.format("[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs", autoblock and "ENABLED" or "DISABLED") end,
1991
function()
1992
autoblock = not autoblock
1993
TextLabel.Text = string.format("[%s] [BETA] Intelligently detects and excludes spammy remote calls from logs", autoblock and "ENABLED" or "DISABLED")
1994
history = {}
1995
excluding = {}
1996
end
1997
)
1998
1999
newButton(
2000
"CallingScript",
2001
function() return string.format("[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.", useGetCallingScript and "ENABLED" or "DISABLED") end,
2002
function()
2003
useGetCallingScript = not useGetCallingScript
2004
TextLabel.Text = string.format("[%s] [UNSAFE] Uses 'getcallingscript' to get calling script for Decompile and GetScript. Much more reliable, but opens up SimpleSpy to detection and/or instability.", useGetCallingScript and "ENABLED" or "DISABLED")
2005
end
2006
)