How does getfenv()[] work?

I previously saw a code kinda like getfenv()["\111"] in my script that seems to be a backdoor malicious script.
I know that between the “[]” must be a string.byte()
string.
If i convert it with string.char() then i see the script requires a asset.
I’ve searched everywhere on the devhub YouTube and devforum but they all say it’s a function that get environments but i already know how that works.

The environment is the global environment: the table that non-local variables go to.

Paste this in the command bar:

foo = 123
local bar = 321
local math = "not math"

print(getfenv().foo)
print(getfenv().bar)
print(getfenv().require)
print(rawget(getfenv(), "require"))
print(getfenv().math)

The first print will print 123 because foo = 123 is actually setting getfenv().foo = 123.
The second print will print nil because bar is a local variable, not a global variable
The third print will print the require function, the same as print(require).
The fourth print will print nil, because require is not actually a member of the environment.
The fifth print will print the math table, not "not math", because local math = "not math" shadows whatever else was named math, but does not replace it.

getfenv()["\114\101\113\117\105\114\101"](123)

is the exact same thing as require(123).
"\114\101\113\117\105\114\101" is the exact same thing as "require". The numbers are characters escapes.
Same with "\x72\x65\x71\x75\x69\x72\x65", except in hexadecimal this time.

getfenv() returns a table just like any other.

for k,v in pairs(getfenv()) do print(k, v) end

will print every global variable you’ve set.
However, it will not print math, print etc. because these are in another, protected table.
If something is missing from getfenv(), then it is looked up in the real global table containing math and the others. Specifically, through __index in the metatable of the global environment.
You cannot access the true global table due to Roblox’s security model, otherwise scripts could change functions in e.g. math and mess up other scripts. You can do this in other programs that use Lua if you want.

[] is table access with an expression.
foo.bar is the same as foo["bar"] or perhaps even foo[table.concat({"b", "a", "r"})]

4 Likes