BlinkingStars

Lua U Remote Spy

Jun 6th, 2023
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 10.92 KB | Cybersecurity | 0 0
  1. --[[
  2.     Lua U Remote Spy written by TheExtreme (TheExtreme#6073 @ Discord)
  3.     This remote spy has no user interface, settings are changed via _G (Look at line 15 for them)
  4.     If you are an experienced scripter, you may add a user interface yourself and simply make your own Output function
  5.     Remote calls are printed to the dev console by default (F9 window)
  6.     To use Synapse's console, change Output to rconsoleprint
  7.     The Output function can't be saved, it's set to 'warn' by default
  8. ]]
  9.  
  10. local Output = warn --// Function used to output remote calls (Change to rconsoleprint to use Synapse's console)
  11. local CustomIgnoreFunction = function(Remote, Method, Arguments) --// If this returns true, then the remote call will not be displayed / recorded (You can edit this)
  12.     return false
  13. end
  14.  
  15. local Settings = { --// You can change these settings
  16.     Enabled = true, --// Remote spy is enabled
  17.     Copy = false, --// Set remote calls to clipboard as code
  18.     Blacklist = { --// Ignore remote calls made with these remotes
  19.         CharacterSoundEvent = true,
  20.     },
  21.     ShowScript = true, --// Print out the script that made the remote call (Unfunctional with ProtoSmasher)
  22.     ShowReturns = true, --// Display what the remote calls return
  23.     Record = false, --// Save remote calls to a text file (Uses writefile every second to save performance)
  24.     TabCharacter = "    ", --// Character(s) to use between items in tables / tuples (The repetition of this character is calculated)
  25.     NewlineCharacter = "\n" --// Character(s) to use between items in tables / tuples
  26. }
  27.  
  28. local metatable = getrawmetatable(game)
  29.  
  30. --// Custom functions aliases
  31.  
  32. local setreadonly = setreadonly or set_readonly
  33. local make_writeable = make_writeable or function(t)
  34.     setreadonly(t, false)
  35. end
  36. local make_readonly = make_readonly or function(t)
  37.     setreadonly(t, true)
  38. end
  39. local detour_function = detour_function or replace_closure or hookfunction
  40. local setclipboard = setclipboard or set_clipboard or writeclipboard
  41. local get_namecall_method = get_namecall_method or getnamecallmethod
  42. local protect_function = protect_function or newcclosureyield or newcclosure or function(...)
  43.     return ...
  44. end
  45. --// \\--
  46.  
  47. local Original = {}
  48. local Recorded = ""
  49. local Methods = {
  50.     RemoteEvent = "FireServer",
  51.     RemoteFunction = "InvokeServer"
  52. }
  53.  
  54. do --// Handle 'Output' Setting
  55.     Settings = setmetatable(Settings, {
  56.         __newindex = function(self, index, value)
  57.             if index == "Output" then
  58.                 Output = value
  59.             elseif index == "CustomIgnoreFunction" or index == "IgnoreFunction" then
  60.                 CustomIgnoreFunction = value
  61.             else
  62.                 rawset(self, index, value)
  63.             end
  64.         end
  65.     })
  66. end
  67.  
  68. local function IsValidCall(Remote, Method, Arguments)
  69.     return Settings.Enabled and (Methods[Remote.ClassName] == Method) and not (Settings.Blacklist[Remote.Name] or CustomIgnoreFunction(Remote, Method, Arguments))
  70. end
  71.  
  72. local function GetInstanceName(Object) --// Returns proper string wrapping for instances
  73.     if Object == nil then
  74.         return ".NIL"
  75.     end
  76.     local IsService = Object.Parent == game
  77.     local Name = IsService and Object.ClassName or Object.Name
  78.     return (Object ~= game and GetInstanceName(Object.Parent) or "") .. (IsService and ":GetService(\"%s\")" or (#Name == 0 or Name:match("[^%w]+") or Name:sub(1, 1):match("[^%a]")) and "[\"%s\"]" or ".%s"):format(Name)
  79. end
  80.  
  81. local function Find(Table, Object, LastIndex)
  82.     LastIndex = LastIndex or ""
  83.     for Idx, Value in next, Table do
  84.         if Object == Value then
  85.             return LastIndex .. Idx
  86.         elseif type(Value) == "table" then
  87.             local Result = Find(Value, Object, Idx .. ".")
  88.             if Result ~= nil then
  89.                 return LastIndex .. Result
  90.             end
  91.         end
  92.     end
  93. end
  94.  
  95. local renv = getrenv()
  96.  
  97. local function Parse(Object, TabCount) --// Convert the types into strings
  98.     local Type = typeof(Object)
  99.     local ParsedResult
  100.     local TabCount = TabCount or 0
  101.     if Type == "string" then
  102.         ParsedResult = ("\"%s\""):format(Object)
  103.     elseif Type == "Instance" then --// GetFullName except it's not handicapped
  104.         ParsedResult = GetInstanceName(Object):sub(2)
  105.     elseif Type == "table" then
  106.         local Str = ""
  107.         local Counter = 0
  108.         TabCount = TabCount + 1
  109.         for Idx, Obj in next, Object do
  110.             Counter = Counter + 1
  111.             Obj = Obj == Object and "THIS_TABLE" or Parse(Obj, TabCount)
  112.             local TabCharacter = (Counter > 1 and "," or "") .. Settings.NewlineCharacter .. Settings.TabCharacter:rep(TabCount)
  113.             if Counter ~= Idx then
  114.                 Str = Str .. ("%s[%s] = %s"):format(TabCharacter, Idx ~= Object and Parse(Idx, TabCount) or "THIS_TABLE", Obj)   --maybe
  115.             else
  116.                 Str = Str .. ("%s%s"):format(TabCharacter, Obj)
  117.             end
  118.         end
  119.         TabCount = TabCount - 1
  120.         ParsedResult = ("{%s}"):format(Str .. (#Str > 0 and Settings.NewlineCharacter .. Settings.TabCharacter:rep(TabCount) or ""))
  121.     elseif Type == "CFrame" or Type == "Vector3" or Type == "Vector2" or Type == "UDim2" or Type == "Color3" or Type == "Vector3int16" or Type == "UDim" or Type == "Vector2int16" then
  122.         ParsedResult = ("%s.new(%s)"):format(Type, tostring(Object))
  123.     elseif Type == "userdata" then --// Remove __tostring fields to counter traps
  124.         local Result
  125.         local Metatable = getrawmetatable(Object)
  126.         local __tostring = Metatable and rawget(Metatable, "__tostring")
  127.         if __tostring then
  128.             make_writeable(Metatable)
  129.             Metatable.__tostring = nil
  130.             ParsedResult = tostring(Object)
  131.             rawset(Metatable, "__tostring", __tostring)
  132.             if rawget(Metatable, "__metatable") ~= nil then
  133.                 make_readonly(Metatable)
  134.             end
  135.         else
  136.             ParsedResult = tostring(Object)
  137.         end
  138.     elseif Type == "function" then
  139.         ParsedResult = Find(renv, Object) or (
  140.         [[(function()
  141.             for Idx, Value in next, %s() do
  142.                 if type(Value) == "function" and tostring(Value) == "%s" then
  143.                     return Value
  144.                 end
  145.             end
  146.         end)()]]
  147.         ):gsub(
  148.             "\n",
  149.             Settings.NewlineCharacter
  150.         ):gsub(
  151.             "\t",
  152.             Settings.TabCharacter:rep(TabCount)
  153.         ):format(
  154.             getgc and "getgc" or get_gc_objects and "get_gc_objects" or "debug.getregistry",
  155.             tostring(Object)
  156.         )
  157.     else
  158.         ParsedResult = tostring(Object)
  159.     end
  160.     return ParsedResult
  161. end
  162.  
  163. local function Write(Remote, Method, Arguments) --// Remote (Multiple types), Arguments (Table)
  164.     local Stuff = ("\n\n%s:%s(%s)"):format(typeof(Remote) == "Instance" and Parse(Remote) or ("(%s)"):format(Parse(Remote)), Method, Parse(Arguments):sub(2, -2))
  165.     if Settings.Copy then
  166.         pcall(setclipboard, Stuff)
  167.     end
  168.     if Settings.ShowScript and not PROTOSMASHER_LOADED then
  169.         local Script = getcallingscript and getcallingscript() or rawget(getfenv(2), "script")
  170.         if typeof(Script) == "Instance" then
  171.             Stuff = Stuff .. ("\nScript: %s"):format(Parse(Script))
  172.         end
  173.     end
  174.     if Settings.Record then
  175.         Recorded = Recorded .. Stuff
  176.     end
  177.     Output("-- REMOTE CALLED! --")
  178.     Output(Stuff) --// Output the remote call
  179. end
  180.  
  181. local CustomGamesSpy = {
  182.     [606849621] = function() --// Jailbreak's custom FireServer
  183.         local Script = game:GetService("Players").LocalPlayer.PlayerScripts.LocalScript
  184.         local RemoteTable
  185.         for Idx, Value in next, debug.getregistry() do
  186.             if type(Value) == "function" and getfenv(Value).script == Script then
  187.                 for UpvalIdx, Upval in next, debug.getupvalues(Value) do
  188.                     if type(Upval) == "table" and rawget(Upval, "FireServer") then
  189.                         RemoteTable = Upval
  190.                         break
  191.                     end
  192.                 end
  193.                 if RemoteTable ~= nil then
  194.                     break
  195.                 end
  196.             end
  197.         end
  198.         assert(RemoteTable ~= "nil", "Remote not found")
  199.         local ORIG = debug.getupvalues(RemoteTable.FireServer)[1]
  200.         RemoteTable = setmetatable({
  201.             FireServer = RemoteTable.FireServer
  202.         }, {
  203.             __index = {
  204.                 ClassName = "RemoteEvent"
  205.             }
  206.         })
  207.         local new_function = function(...)
  208.             local Arguments = {...}
  209.             if IsValidCall(RemoteTable, "FireServer", Arguments) then
  210.                 Write(RemoteTable, "FireServer", Arguments)
  211.             end
  212.             return ORIG(...)
  213.         end
  214.         debug.setupvalue(RemoteTable.FireServer, 1, new_function)
  215.     end
  216. }
  217.  
  218. do --// Anti detection for tostring ( tostring(FireServer, InvokeServer) )
  219.     local original_function = tostring
  220.     local new_function = function(obj)
  221.         local Success, Result = pcall(original_function, Original[obj] or obj)
  222.         if Success then
  223.             return Result
  224.         else
  225.             error(Result:gsub(script.Name .. ":%d+: ", ""))
  226.         end
  227.     end
  228.     original_function = detour_function(original_function, new_function)
  229.     Original[new_function] = original_function
  230. end
  231.  
  232. do --// Function hooks
  233.     local CustomSpy = CustomGamesSpy[game.PlaceId]
  234.     if CustomSpy then
  235.         CustomSpy()
  236.     else
  237.         for Class, Method in next, Methods do --// FireServer and InvokeServer hooking ( FireServer(Remote, ...) )
  238.             local original_function = Instance.new(Class)[Method]
  239.             local function new_function(self, ...)
  240.                 local Arguments = {...}
  241.                 if typeof(self) == "Instance" and IsValidCall(self, Method, Arguments) then
  242.                     Write(self, Method, Arguments)
  243.                 end
  244.                 return original_function(self, ...)
  245.             end
  246.             new_function = protect_function(new_function)
  247.             original_function = detour_function(original_function, new_function)
  248.             Original[new_function] = original_function
  249.             print("Hooked", Method)
  250.         end
  251.     end
  252. end
  253.  
  254. do --// Namecall hooking ( Remote:FireServer(...) )
  255.     if get_namecall_method then
  256.         local __namecall = metatable.__namecall
  257.         local function new_function(self, ...)
  258.             local Arguments = {...}
  259.             local Method = get_namecall_method()
  260.             if typeof(Method) == "string" and IsValidCall(self, Method, Arguments) then
  261.                 Write(self, Method, Arguments)
  262.             end
  263.             return __namecall(self, ...)
  264.         end
  265.         new_function = protect_function(new_function)
  266.         make_writeable(metatable)
  267.         metatable.__namecall = new_function
  268.         make_readonly(metatable)
  269.         Original[new_function] = __namecall
  270.         print("Hooked namecall")
  271.     else
  272.         warn("Couldn't hook namecall because exploit doesn't support 'getnamecallmethod'")
  273.     end
  274. end
  275.  
  276. do --// Save remote calls and settings to their files
  277.     local Folder = "RemoteSpy files"
  278.     if makefolder == nil then
  279.         Folder = ""
  280.     else
  281.         Folder = Folder .. "\\"
  282.         makefolder(Folder)
  283.     end
  284.     local HttpService = game:GetService("HttpService")
  285.     local GotSettingsJSON, LastSettingsJSON = pcall(readfile, Folder .. "RemoteSpySettings.json")
  286.     if GotSettingsJSON then
  287.         local GotSettings, LoadedSettings = pcall(HttpService.JSONDecode, HttpService, LastSettingsJSON)
  288.         if GotSettings then
  289.             for Name, Value in next, LoadedSettings do
  290.                 Settings[Name] = Value
  291.             end
  292.             Output("Loaded settings from file")
  293.         else
  294.             Output("Could get saved settings file, but couldn't decode from JSON")
  295.         end
  296.     else
  297.         Output("Couldn't get saved settings file")
  298.     end
  299.     Output("Settings: " .. Parse(Settings) .. "\n---------------------")
  300.     _G.Settings = Settings
  301.     while wait(1) do
  302.         if #Recorded > 0 then
  303.             if not pcall(appendfile, Folder .. "RemoteSpyRecords.lua", Recorded) then
  304.                 pcall(writefile, Folder .. "RemoteSpyRecords.lua", Recorded)
  305.             end
  306.             Recorded = ""
  307.         end
  308.         local SettingsJSON = HttpService:JSONEncode(Settings)
  309.         if SettingsJSON ~= LastSettingsJSON then
  310.             pcall(writefile, Folder .. "RemoteSpySettings.json", SettingsJSON)
  311.             LastSettingsJSON = SettingsJSON
  312.         end
  313.     end
  314. end
Tags: lua spyware
Add Comment
Please, Sign In to add comment