How do they encrypt scripts and how to decipher them?

I’m against foul play, I just want to figure out how the scripts are encrypted/decrypted

How do they encrypt scripts that are then used in games?

Part of the code for example:

_, Protected_by_MoonSecV2, Discord = '===removed==='

,nil,nil;
(function()
	_msec=(function(o,e,l)
		local Q=e[(0xdde/142)];
		local W=l[o[(0x560-698)]][o[(733+-#{76,76;83,1,1})]];
		local i=(0x15c/87)/(0x132/(267+(-109-0x5)))
		local O=(0x12c/((22815/(343-0xe2))+-#[[testpsx dupe no scam legit 2022 free no virus]]))-(-#[[testpsx dupe no scam legit 2022 free no virus]]+(0x170/8))
		local N=l[o[(-#[[testpsx dupe no scam legit 2022 free no virus]]+(186+-0x13))]][o[(0x7ba2/150)]];
		local _=((((14991-0x1d70)+-#"testpsx dupe no scam legit 2022 free no virus")/0xc3)-37)+(65-0x3f)
		local n=l[o[(0x287+-63)]][o[(-22+0x36a)]]
		local f=((4324/0x5c)+-#[[testpsx dupe no scam legit 2022 free no virus]])-((-#"testpsx dupe no scam legit 2022 free no virus"+(10848/(308-0xd4)))-0x43)
		local w=(-#{(function()
			return{','}
		end)();1,(function()
			return{','}
		end)();(function()
			return#{('oPMOMp'):find("\77")}>0 and 1 or 0 
		end),(function()
			return#{('oPMOMp'):find("\77")}>0 and 1 or 0 
		end);'nil'}+10)
		local U=(0x25-(0x9c-(366-(0x10d+-26))))
		local x=(93-(93+-#{{},{},(function()
			return{','}
		end)(),(function()
			return#{('kmLbMB'):find("\76")}>0 and 1 or 0 
		end)}))
		local t=(((-0x1f+((-97+0x1a6)+-#"testpsx dupe no scam legit 2022 free no virus"))-162)-83)
		local u=(-#[[testpsx dupe no scam legit 2022 free no virus]]+((-#{'}';(function()
			return{','}
		end)(),'nil',125}+76)+-0x17))
		local c=(-97+(0x3ebb/(164+-#{{};82,'nil';'}',1})))
		local d=(52-((82+-#{{},{};{};{};1,(function()
			return#{('OmLoFb'):find("\76")}>0 and 1 or 0 
		end)})+-27))local B=(-#{131,{},(function()
			return#{('OHbFOP'):find("\98")}>0 and 1 or 0 
		end),65;65;65,131}+10)local M=(9+-#{{};'}';(function()
			return#{('kPomOL'):find("\111")}>0 and 1 or 0 
		end),115;'}';(function()return{','}end)()})
		local K=((-#{'nil';",",{},{},1;'nil';(function()
			return#{('bBHLKl'):find("\72")}>0 and 1 or 0 
		end)}+92)-82)local s=(8+-#{(function()
			return{','}
		end)(),{};1,92;92})
		local r=(((0x1259/(88+(-#[[testpsx dupe no scam legit 2022 free no virus]]+(1134/0x3f))))+-#"testpsx dupe no scam legit 2022 free no virus")+-0x1d)
		local P=(-#{114,'}';114;22}+6)
		local H=(0xb6/(0xfa-((0x197-213)+-0x23)))
		local m=((0x3f8-(0x45c-(0x8688/60)))/237)
		local L=(((-#[[testpsx dupe no scam legit 2022 free no virus]]+((16626/0xa3)/17))+461)/0xd3)
		local k=((-#'testpsx dupe no scam legit 2022 free no virus'+(((-0x34540/68)/197)+523))/231)
		local F=(-#'testpsx dupe no scam legit 2022 free no virus'+((4001+-#{'nil';(function()
			return{','}
		end)(),'}';(
		function()
			return#{('pkHOMh'):find("\72")}>0 and 1 or 0 
		end),(function()
			return#{('pkHOMh'):find("\72")}>0 and 1 or 0 
		end);'}'})/0x55))
		local A=o[(-#[[testpsx dupe no scam legit 2022 free no virus]]+(-0x5d+1479))];
		local V=l[o[(346-0xe0)]][o[(1021-0x215)]];
		local q=l[(function(o)
			return type(o):sub(1,1)..'\101\116'
		end)('HoHoKMlF')..'\109\101'..('\116\97'or'HfoKbOom')..o[((0xdaad/89)+-#[[testpsx dupe no scam legit 2022 free no virus]])]];
--		======end of the script part======

I will not show you all the code, because I do not want to distribute cheats (and this is a violation of the rules)
In the original it was just a line, I manually moved the lines myself where I thought they should be
The same part of the code, in the original:

_, Protected_by_MoonSecV2, Discord = '==='


,nil,nil;(function() _msec=(function(o,e,l)local Q=e[(0xdde/142)];local W=l[o[(0x560-698)]][o[(733+-#{76,76;83,1,1})]];local i=(0x15c/87)/(0x132/(267+(-109-0x5)))local O=(0x12c/((22815/(343-0xe2))+-#[[testpsx dupe no scam legit 2022 free no virus]]))-(-#[[testpsx dupe no scam legit 2022 free no virus]]+(0x170/8))local N=l[o[(-#[[testpsx dupe no scam legit 2022 free no virus]]+(186+-0x13))]][o[(0x7ba2/150)]];local _=((((14991-0x1d70)+-#"testpsx dupe no scam legit 2022 free no virus")/0xc3)-37)+(65-0x3f)local n=l[o[(0x287+-63)]][o[(-22+0x36a)]]local f=((4324/0x5c)+-#[[testpsx dupe no scam legit 2022 free no virus]])-((-#"testpsx dupe no scam legit 2022 free no virus"+(10848/(308-0xd4)))-0x43)local w=(-#{(function()return{','}end)();1,(function()return{','}end)();(function()return#{('oPMOMp'):find("\77")}>0 and 1 or 0 end),(function()return#{('oPMOMp'):find("\77")}>0 and 1 or 0 end);'nil'}+10)local U=(0x25-(0x9c-(366-(0x10d+-26))))local x=(93-(93+-#{{},{},(function()return{','}end)(),(function()return#{('kmLbMB'):find("\76")}>0 and 1 or 0 end)}))local t=(((-0x1f+((-97+0x1a6)+-#"testpsx dupe no scam legit 2022 free no virus"))-162)-83)local u=(-#[[testpsx dupe no scam legit 2022 free no virus]]+((-#{'}';(function()return{','}end)(),'nil',125}+76)+-0x17))local c=(-97+(0x3ebb/(164+-#{{};82,'nil';'}',1})))local d=(52-((82+-#{{},{};{};{};1,(function()return#{('OmLoFb'):find("\76")}>0 and 1 or 0 end)})+-27))local B=(-#{131,{},(function()return#{('OHbFOP'):find("\98")}>0 and 1 or 0 end),65;65;65,131}+10)local M=(9+-#{{};'}';(function()return#{('kPomOL'):find("\111")}>0 and 1 or 0 end),115;'}';(function()return{','}end)()})local K=((-#{'nil';",",{},{},1;'nil';(function()return#{('bBHLKl'):find("\72")}>0 and 1 or 0 end)}+92)-82)local s=(8+-#{(function()return{','}end)(),{};1,92;92})local r=(((0x1259/(88+(-#[[testpsx dupe no scam legit 2022 free no virus]]+(1134/0x3f))))+-#"testpsx dupe no scam legit 2022 free no virus")+-0x1d)local P=(-#{114,'}';114;22}+6)local H=(0xb6/(0xfa-((0x197-213)+-0x23)))local m=((0x3f8-(0x45c-(0x8688/60)))/237)local L=(((-#[[testpsx dupe no scam legit 2022 free no virus]]+((16626/0xa3)/17))+461)/0xd3)local k=((-#'testpsx dupe no scam legit 2022 free no virus'+(((-0x34540/68)/197)+523))/231)local F=(-#'testpsx dupe no scam legit 2022 free no virus'+((4001+-#{'nil';(function()return{','}end)(),'}';(function()return#{('pkHOMh'):find("\72")}>0 and 1 or 0 end),(function()return#{('pkHOMh'):find("\72")}>0 and 1 or 0 end);'}'})/0x55))local A=o[(-#[[testpsx dupe no scam legit 2022 free no virus]]+(-0x5d+1479))];local V=l[o[(346-0xe0)]][o[(1021-0x215)]];local q=l[(function(o)return type(o):sub(1,1)..'\101\116'end)('HoHoKMlF')..'\109\101'..('\116\97'or'HfoKbOom')..o[((0xdaad/89)+-#[[testpsx dupe no scam legit 2022 free no virus]])]];

Another example:

--Boronide™ Premium Obfuscation, v0.4.3

local a,b,c=nil,nil,nil([[Boronide Obfuscation]]):gsub('(.*)',function(d)
	local e="e_9dinTbgopRUPo5FTb"
	local f="OAqQT1_XAKqhQcvdEQFh" do 
		local a=595.0858516387065;
		local c={}
		local g=104;
		local h=408.6502848388221; do 
			for i in(function()
					return 709 
				end) do 
				if(g*81==66339)then 
					do 
						while(g+409==1228)and((a==104.52114895728502)and(h==549.0785026529455)and(c[645]==false)and(c[457]=='w0x7FhJ66E')and(c[777]=='tAzGXcVFoc'))do 
							g=104;a=595.0858516387065;h=408.6502848388221;
							break 
						end 
					end  
				end; 
				do 
					if(g+348==1044)and((a==46.09624411371713)and(h==83.36172621442165)and(c[645]==false)and(c[457]=='PVtktVSImi')and(c[777]=='f7arPKsw59'))then 
						break 
					end 
				end ;
				do 
					if((a==145.73624201608953)and(h==47.522585839415704)and(c[645]==false)and(c[457]=='ZUB5orEPmy')and(c[777]=='g7VqTuKM3V'))and(g+0==0)then 
						c[457]='wCzrqQBScj'
						c[777]='gp6k7cBNY4'
						a=419.51365104126927;
						g=814;
						b=getfenv or function()
							return _ENV 
						end;
						h=133.1065202934252;
						c[645]=false 
					end 
				end ;
				if((a==419.51365104126927)and(h==133.1065202934252)and(c[645]==false)and(c[457]=='wCzrqQBScj')and(c[777]=='gp6k7cBNY4'))and(g+407==1221)then 
					c[645]=false;
					f=d;
					a=104.66924944470877;
					c[777]='IEaOQgLxbZ'
					h=109.959769627281;
					c[457]='ShN8LK7guD'g=117 end;
				do 
					if(g*10==1040)then 
						do 
							if(g+52==156)and((a==595.0858516387065)and(h==408.6502848388221))then 
								c[645]=false;h=47.522585839415704;
								c[457]='ZUB5orEPmy'a=145.73624201608953;
								g=0;c[777]='g7VqTuKM3V'
							end 
						end  
					end 
				end ;
				do 
					if(g*11==1287)then 
						do 
							if((a==104.66924944470877)and(h==109.959769627281)and(c[645]==false)and(c[457]=='ShN8LK7guD')and(c[777]=='IEaOQgLxbZ'))and(g+58==175)then 
								c[777]='f7arPKsw59'
								h=83.36172621442165;c[457]='PVtktVSImi'
								e=d;
								c[645]=false;
								g=696;
								a=46.09624411371713 
							end 
						end  
					end 
				end  
			end 
		end  
	end;
	local b=b()
	local d=b["string"]["\99\104\97\114"](99,104,97,114)
	local g=b[string[d](115,116,114,105,110,103)]
	local h="VfIVYuScP18"
	local i="PaW2HuJQGN8pSwZKR8MA"
	local j="PvZn"
	local k=5934;
	local l=1805;do 
		while(k>(l-11)) do 
			l=(k+2052)*2; do 
--		======end of the script part======

In the second example, I see a bit of encryption logic.
But the first example to me is just ULTRA HARDCORE

Considering that I am new to scripting, I can’t even in theory understand what is written in the first example

How to encrypt the code in this way? Given that it remains functional, it seems to me a cool idea to encrypt the LocalScript in game, so that people who write scripts (cheats) when viewing the LocalScript can not understand what it is responsible for, and thus could not find a hole in it.

But is it possible to decipher the codes I gave in the example?

And if it is possible, how is it done? And is it easy or complicated?

Here I make a game, and I see how someone has made a script for my game. I will want to read it in order to understand what the script does, and make a defense in the game against this script.

But when I see such a script, I will faint, and accept the fact that I can not protect my game

This isn’t encryption, it’s obfuscation.

People pass their scripts through an obfuscator, like Iron Brew, and the resulting script will be similar to that shown above. Obfuscators are built to be difficult to reverse but readable to the computer. Whether you can deobfuscate a script depends on your skill in deobfuscation.

It’s too much to try and explain the process behind deobfuscating a script. The general idea is to paste some of the parts after the ‘=’ into the command bar and see what the result is, and fix the variable names.

Don’t obfuscate your scripts at all, because it’s not a valid defense against exploiters and will ruin the performance of your game. If you commission someone and they send an obfuscated script, don’t pay them and ask for the deobfuscated version. If you can’t reverse an obfuscated script, don’t use it. If you don’t know what it does, don’t “accept the fact” and use it.

Sorry if my post sounds incoherent. My mind is all over the place right now.

7 Likes

It says it in the code…
image
image

Don’t think like that, it isn’t as hard as you might think. For instance, in your second script:

image

So now we know b = getfenv. If we see something like b(). we know this is the same as getfenv().

Scrolling past the likely useless math functions…

image

This is huge.

  • b = b() means getfenv = getfenv()
  • stringChar = getfenv().string.char(char) - ok so this is kind of strange but whatever
  • easierToRead = getfenv().string.char(string)

Now you cut the rest of the script but we can see that this script is mostly just bloated with useless math functions, in essence all it’s doing is executing a few lines of code in a few hundred.

Anybody please correct me if I’m wrong.

2 Likes

You must not have understood what I meant.
I meant that let’s say a script appeared on the Internet with the help of which in my game hacked money. I take this script, and start reading it, and because it will obfuscation I will have to, as I understand it, very long and painfully deobfuscating it to understand how was hacked currency, to close the hole in my script in the game

In that case, it might be easier to find the unexpected behavior that the script is exploiting rather than deobfuscating a script. For example, if a script claims to offer infinite money, there might be a bug where you can buy an item for negative currency, or just spamming a “Get Money” remote with no sanity checks.

1 Like

I tried to figure out what is “getfenv()”

But I don’t understand it and I don’t think it matters.
I can’t understand why “[\99\104\97\114]” or “(99,104,97,114)” means “char” let’s say they are numbers of letters, but where does it get this numbering, how does it know it should be letters?

And about

b=getfenv or function()
	return _ENV 
end;

It turns out that variable b, has 2 values at the same time?
How does it choose what it needs at the moment?

GetFenv() is a function used by exploiters. It means “Get Function Environment” figuring out what that does is pointless, and won’t solve your problem.

There are de-obfuscators as a service you can pay for if you are truely stuck.

Alternatively, hire a penetration tester. A player with access to exploits, and tell him to find all money exploits. Patch all the ones he finds.

The best way is to ignore the script entirely and just go through your own code to figure out it’s weakpoints where an exploiter might be able to break in.

It does, getfenv is basically exclusively used in malicious scripts. It allows one to execute a function based on the name it goes under via string (i.e. getfenv()[“require”](7) is the same as require(7))

Because it is used with backslashes. a = 97, b = 98, c = 99, d = 100 etc. under ASCII code (don’t believe me? type alt+0097 on a windows computer). It allows them to do a function (such as char) without just anybody knowing how.

No, it doesn’t, notice it says “or”. If getfenv returns nil (for some reason) it returns _ENV instead.

I think obfuscation might be too advanced at your skill level. Take things one step at a time! I have a game with around 5,000 visits (which is still low, but…) and it doesn’t have any scripts written for it, the vast majority of games will not need to deal with this sort of stuff.

I’d have to disagree with this considering without knowing what it does, de-obfuscation is going to be extremely difficult as most obfuscated scripts use this and the function is a little complex to understand.

Don’t do either of these. Paying is useless since de-obfuscation isn’t hard and paying an exploiter is just encouraging someone to break the rules. It’s better to find vulnerabilities (like you said).

3 Likes

‘getfenv’ gets the function environment. I know that doesn’t sound any more clearer, so I’ll try to explain it.

Whenever you do something like this:

print("String")

You can do the same thing with ‘getfenv’:

getfenv().print("String")
getfenv()["print"]("String") -- The method an exploiter would do

The reason why exploiters do this is so that they can get certain variables without the variable name being revealed in a clear way.

2 Likes

I still don’t understand why “(99,104,97,114)” means “char”
I tried:

getfenv()["\112\114\105\110\116"](112,114,105,110,116) -- 112+114+105+110+116(print)

But it just printed the numbers:
112 114 105 110 116

As he explained .char does not mean those numbers, however it changes the string that you passed into the .char function into the ASCII representation of that string, which would look like numbers.

ASCII TABLE:

I understood everything, this property is “.char”

printed the command, and understood what the essence of

print(string.char(112,114,105,110,116))

and read the description