Client-Server Anti-Cheat System with Custom Encryption

Yeah you don’t know what you are talking about. An anti tamper for an obfuscator isn’t gonna stop dynamic analysis

1 Like

Secure Key Retrieval: The client uses a specially encrypted default key to securely request the next encryption key from the server. This process allows the client to access one of the 50 dynamically generated strings stored in replicated storage.

1 Like

that was not implemented it was an idea that system hasn’t been implemented.

1 Like

As I said earlier, some information that isn’t encrypted must be present to start the exchange between the client and server. It doesn’t matter how you implement it. It can be grabbed, and then, no matter how many layers you add on after that, they can all be easily pushed through. Encryption is really only good against external attacks, which are irrelevant here. The only thing this stops is incompetent people, and that is much more easily done with simpler systems that don’t drag down the performance of your game.

1 Like

That is just talking about the security of your network traffic. Even if somehow you can magically 100% guarantee your traffic is secure. All that does is ensure your anti-cheat stays running. An exploiter can modify the game state and spoof the data your anti-cheat is reading. What does your anti-cheat ultimately do that actual sanity checks and proper security can’t?

1 Like

how do you know this drags performance there is no visible or even micro performance effects from this system

the client can read client memory levels theres lots of detections that can be opened up just from securing the client so that you have access to allt hat information

1 Like

You don’t even understand what I said, so I’ll spell it out for you. Exploiters can spoof any value, anything, even to the client itself. They can have it so that when your anti-cheat checks the value of any property, it will be given a fake value. But when anything else checks for that value, it’s given the value they want it to be. They can make it so that any function you call for your detections returns anything they want. It is incredibly trivial; it takes one hookmetamethod.

as an example, we can go over anti-fog. They can check the security level of whatever is accessing a property they have hooked. If it’s Roblox itself, then they get given a fog value of zero; if it’s your anti-cheat, they will give you the value the anti-cheat expects. You can’t secure roblox’s properties and functions because you cannot control their implementation. Your anti-cheat entirely relies on roblox’s properties and functions. your whole game does.

4 Likes

Using memory levels as a detection is incredibly stupid for obvious reasons

2 Likes

not really the more detections you have the better the anti-cheat is. obviously it wouldnt outright ban you if one thing was suspicious but we can determine a credibility score and take actions based of that information and other detections

1 Like

StarterPlayer.StarterPlayerScripts.CanSecurity (LOCAL)


-- Decompiler will be improved soon!
-- Decompiled with Konstant V2.1, a fast Luau decompiler made in Luau by plusgiant5 (https://discord.gg/wyButjTMhM)
-- Decompiled on 2025-01-01 21:20:40
-- Luau version 6, Types version 3
-- Time taken: 0.004230 seconds

return (function(...) -- Line 1
	-- KONSTANTERROR: [0] 1. Error Block 48 start (CF ANALYSIS FAILED)
	local tbl_upvr = {"f/IDUwLFRF==", "CzLuKtaLfpKLfF==", "Apl6QnvPVn23fF==", "FNEzwBKhyM==", "7np2Nd+Eff4tMWv4/M5Gi3VK7P59ylCZKI5R72zGdA==", "kH20ELFc0y8LZAzS610hYq1PBpXvF2FMH5mHQdWNjsdHHBGYZxCuyM==", "Qo3eNaCd6GW=", "3qNUVe73", "RUDEIdRi/NlN", "tnD6X8K3fZa+Yo2Z", "gHsEKo7=", "CntwCItmQntqKIDqXrB=", "KnDvKA==", "NTPUxdOTCRZiwmu+XOM1hImA/BfbsLSixBOvIHMhPkOIEpE8JQoMp0mzeHbFhl/auRJqDR/EWlwRqFQrnCdBbL2Q", "J4tdq/NwjrW=", "amyB/2wqtiF1", "WokvfY7RvVf=", "sJrZugzE", "CPFlYhJv0M==", "krwMzYeB", "fSCuYoUp", "5WjF", "VSDya8agttKhKk8mYF==", "Ccio6LMC", "fIaxVIM=", "q8WZ9fiNAZRb", "DoRG9B5ciraZuAW=", "MEFdRviW", "", "pCgB+VH5mxv+", "PE5yl8yZZyolD8dVPZruvFJA5TxtygUJ", "kr2kzFaHdq9=", "li0AmDW=", "B3UNGBZv", "3oKQtF==", "zaG/u1Xj", "5iaa9VBbywEUW1+=", "Vgnv5634zlVRpdE=", "XnD6X5==", "ZzM5489T3cav/A==", "fnauYgNw", "/SLOKh9H", "CoM+2XGBe/siWnRV2UjZJcuvK4JyRlZqNBZZKFJVrNi8vF==", "BPXOkHNPYt9SkIvBAA==", "OgaN", "G8gKhisaoHaO7bMxxU9PmVFobOwRnQGttDK6ivgHsVGhXJpPqR+MQCILPwg76zv/vwvxb4f2FBt96ag7d/xInDTnPFAh+Qf=", "OH0KE9uk7M==", "Rrm2", "CPCBoZxWQL62anxHdPW=", "BD7LJsA5kAobw2Shq3cdGW4qL46Jhzljv11it9IRWEMsHHT4nddOSy6pXGGSYsARNdf=", "BrCPKgDuX8HUXoxGQzA=", "Vpl2p8PT", "+SR2yidR", "9kfaAVWCFysx8qACBXhLklaNVTj1qT/r3XvrUd7kT9j055==", "/Uv9FucECXqPCsJ79kM=", "aWbrxP4Lh5==", "gwf=", "dgtPf8xafzLnCmxBkL9=", "tZPn4kG8", "5kJ9raA55tpB", "/8DRFLjlpDLiTj0HWPMHUVGL1xp+F6y9Bq873M==", "gplTAVay5M==", "QptzKztu", "YZtLBpCe9PaAVrC+fF==", "KLtvXzLpCp5UakXAOM==", "XnsuYSaMQoaL", "OmZuoIHDbZvzB8lEKSZ=", "XzDIKrlGYztLQZtiBF==", "j/0Q/cKs2XfqepnjrUqbkPqCy0v5Qu89HxDOW8B9uVc8S35mPbusCzjYa7hbrJm6+ss0xQu0se16c3E=", "Ji4u/DpayP4KjFdBxcN1EjBJtKaA7dQs", "hw44vtc7SA8nNLF=", "LuQawmI8hJ6xUc/G7pq3psZzqkkdeYWqqenJXv8o7qj+ns5PAHxH+mk7TdX0UjVyG8t02ElJbOeU66PH3TVO8Hig2PzT", "+Ye/+elICk6P", "AnsqVztcX5==", "AnxxVzXL9SCxXI9=", "64b5ZchxLtE=", "IRy0lW1QYOseAiqf", "E6m9NfQ=", "CzLqK8K6fpawAnx6VIA=", "QnsuVStwYoUL", "J6X3PD1v", "gHspQM==", "GQvHTsr/zAoqtdJKRM==", "GAcMuA==", "KLfnKVP9QwTf", "QnsqQnDw", "CtKDXZUia8XnQotp", "4TdXC2q+yAgY", "nQcjWNR9", "oeSkc8VTURDq", "CoUHVA==", "VjI99WEan9W6HiM=", "827WgtLmMBv6YTKeQRpLHF+y5NTwHgM=", "tosrV8X+CnU9Vz6Db5==", "B9hzICT1CayJ", "WvmJ2M==", "KSaHQF==", "bPxNoov4XZlZBZahtnB=", "KLYTbzkT", "fYDdWmtQVrBREM==", "C7inoF==", "VijdGX25", "fztvVSKL", "piHXxwBP4tkj", "7PpuwF==", "Ob0pTN5ubQh+NoCIrfRi8nM=", "N+/M/F==", "/DA5NQON", "YICttSDuarCQKn6iBHW=", "CItmXrl3bA==", "AtKOaSDYAw2LYPtUX5==", "n3hPMCO8M72nEqrhsaQs24NGiUTyM0VcFGgl", "YgNxYglm", "bJciOAVxF2c9", "frl6VpA=", "muaIBRef", "BgKEHQbXrF==", "PldCRci4e5==", "VrxUK8L7QwaDdtLIYmA=", "qfecJpqx", "DmDjtecWtq7nrL+=", "rF5tQIuRN/5fROCQ39fhI7KpCnrSRuxJjrQM4IEs", "AnL4VSNpCzstKZ6gBA==", "JY8oo6PxkSdgChDlFBqBhpxjufa74hBAbWCphaI3+ixYy0YKxFRsCJRVeZhMJcyseF==", "cgEjhKGV2P1JhZIJ25==", "VItq", "gHs6VzCLb5==", "Ecy6xdTNNF==", "XoUMQoae", "Cntw9ntuXzLcKA==", "Yg6A9p+UBIDKtnvDBwj=", "iIlLKo3VfNHtV/E=", "Bns8XSKBQL9uVwUDAF==", "KnHxXIa+", "c3ZrNjbt", "fID6fpB=", "gHsvKgCxXIDiVI9=", "wTQdz8vsSF0T7KipDH7g", "GteSmmBzZVQ=", "FoVSyIwFD1db3521oYMkprVLDxaENCY7oWbdBAiP+dXb0ezgdCHV/GxDs9YGGCAQFF==", "CVdhi/l4", "diFLK0+6dF==", "XnDuVF==", "YeHOvrGvXjA=", "KgluVSW=", "k8W9EIlTY/mf", "IxnN8K+K9FpaTbsjq40MrYSvV/pGkirqYkw=", "dIU3Kmt0anAuAp6c", "CtsvoqR/87AZB8j=", "M2t9a437WTtyy2a2E3z34Mr8SIn/rWId8xi4Jt5jve5y3dMhxM==", "kpaJd8sw9LxPCkaMCF==", "Kz23VSW=", "BosOKgtM9gL7Xwli", "XIsmXrl6Vzf=", "xwWHKjTWOce1DKHin0F/9qsjvEvN3Qrq39fl/SWXl0PNRMwZfII+A62VEkx2JrA=", "Kds/+MRG7A7m4MJu2crE4+9=", "Lt+srAKg", "6VaZ9UCS", "TOYSknCL+5==", "OL6zOrDrAnKoogao", "ssJylqhdm5==", "R67LPUV3z+Qf", "gDtoTA==", "EfD/HK00", "eBTFRGKG4M==", "t9ve9ZaabP9maLXQC5==", "jjbNlA==", "CvppCpqmQWdJ9q3n5yyca0zp1IVtvmSDiW60x6YPUyIXtRpJKjtn1A==", "XtaYfPXhkrZ29rx0C5==", "3OwXRM==", "wS52UdvTYMjWqJVuiAo0DB9=", "Zx7Q2AamrA==", "XIsqXoHiKgW=", "9zDxXPyw", "KntwKztqXF==", "9kau9tCBBPxnOpKrkF==", "mQdsY39XfkAha5==", "AjdRf1ri/WGa", "aIKU9pKpfDC2o9ULd88=", "QpLwKA==", "87zz4oOwgJRDsbDxI6nQt5qDfhFBttd29c3UYPRBCP6PA+jp8F==", "BXuDeLc1fct98TY6VA==", "VIld", "K0ZVTM==", "oovdfWpstF==", "Jul6vYxd", "gSEYlwRlkpNeOlYuFYYfkYS0a12MEPjyUo45KY2s4LwoIl9g6KEsw5==", "fzt2XoLuKA==", "OnUI9rtlYLDQAwKm", "tPLLCSt6BZxcfH6CkLB=", "OnLcYM==", "EQt5oa2ZG1w0kK0KhsSOdVX2kdn5KvIEAEEEfU7u7c+grNMqerNFTeKlCubStJP13BrCgM==", "XIDmYM==", "KHLdoPLOVclBYmxyazB=", "AwKuQoHL", "6Lo6CITF", "WVsHDvEX", "tIDvfItuW8CLXItcXItZWA==", "NqPsO+wSQxoBD9+lTt77SuH2zgTNPwYtbEUjEuAXwMfmIArw1747mCFqCF==", "vd+AwCbJAuBb3A==", "qDFZ+p8YtV0v", "KZ2N9o6NCrQwK9tyftZ=", "kPDQoLfuo9lhVg+HAZB=", "YnH8attLApLeYtaMY9A=", "6PGo1A==", "76FVAJTB+7VgKi5PnC9R", "2U+3kcXtsAL0459=", "GnsbXEcKmFsHjM==", "dF==", "HcRd8Zyf", "4LG2HLEJg3+UV+4QbF==", "TBeLh5==", "bLCUkwDgCnK4YnDU9H5=", "QnxxfF==", "1H3p18w=", "2zbSjsmmVNM=", "abkfU6fP40k8fhLo7n1MBdPn/pU9/xjfq02Cv6+s8k1+eJlrWloY4dQnabxrYg/QuK5BwzjMWC+=", "J0+Fym1x", "KaPHCI1i", "MlDiVfIrB2ePjcZjoOkq6fk2nA4YwYNdc3MwFO7v47RuRrPm6cJRhF==", "XrLMKA==", "vlolzViH", "w74m+IAXskwRPxBSCpIjiKWTkeMQl9aeeO00IxrLumJB+XfxBDdkcuGMOxM9wp/fipytW8C09W3PJJoIS5==", "o+I3FZon", "WwKuSJUcx8xqNJnXgwi+", "fntwVotwQgCxQz2L", "kD8uQS+=", "CpDEkD6UkDDNOZ2QXZw=", "XIDiVI9=", "VPW=", "VoDwY5==", "vhxaZjwSNCLpk1F=", "XpxOXwsSfmlckw2WBD8=", "dDtDB8xqf9CqbIU8", "hQEzt53Jq1J4eUw3EKfwdxQ7QHQZUSNunLg/KknE7FP5r9bK+A3SYVwzwfcyzK8/n7Z1g/ClA2yqFdYfFGjOXA==", "VP8=", "fzDqKIsv", "tmX6QSKyaIlwbZCxCP8=", "gUlfoBmw+GuAjEw=", "9r6AYo62OZB7tpNYkA==", "jxtADp29EeyZipHwMY2M", "XrLMKosz", "RN8iAHKFnF==", "9S+SoLtaOtlCtgtpK5==", "jIaDtX6LzzKk6Gqv/FdwByNdOBoFDzfDzfvlWpvkYOecsG39efM=", "Stem", "KIWuoZDDbF=="}
	local function _(arg1) -- Line 1, Named "m"
		--[[ Upvalues[1]:
			[1]: tbl_upvr (readonly)
		]]
		return tbl_upvr[arg1 + 13234]
	end
	for _, v in ipairs({{1, 247}, {1, 143}, {144, 247}}) do
		while v[1] < v[2] do
			tbl_upvr[v[1]] = tbl_upvr[v[2]]
			tbl_upvr[v[2]] = tbl_upvr[v[1]]
			v[1] += 1
			v[2] -= 1
		end
	end
	local _ = {
		['6'] = 41;
		i = 34;
		A = 16;
		x = 33;
		c = 35;
		V = 27;
		P = 3;
		['1'] = 31;
		['/'] = 63;
		Y = 26;
		W = 8;
		u = 50;
		['3'] = 47;
		['9'] = 20;
		J = 58;
		O = 18;
		H = 53;
		t = 21;
		r = 7;
		F = 32;
		G = 10;
		['2'] = 49;
		K = 25;
		D = 5;
		S = 55;
		C = 17;
		z = 38;
		l = 9;
		s = 61;
		k = 19;
		m = 51;
		p = 39;
		I = 6;
		b = 30;
		['+'] = 40;
		g = 23;
		j = 60;
		h = 15;
		['5'] = 0;
		a = 13;
		R = 59;
		['7'] = 56;
		q = 46;
		n = 54;
		y = 11;
		B = 12;
		['8'] = 4;
		Z = 36;
		['0'] = 2;
		v = 45;
		N = 1;
		e = 43;
		E = 44;
		T = 62;
		o = 22;
		d = 14;
		L = 37;
		U = 57;
		X = 29;
		Q = 24;
		w = 52;
		['4'] = 42;
		f = 28;
		M = 48;
	}
	local _ = 1
	-- KONSTANTERROR: [0] 1. Error Block 48 end (CF ANALYSIS FAILED)
	-- KONSTANTERROR: [656] 544. Error Block 21 start (CF ANALYSIS FAILED)
	-- KONSTANTERROR: [656] 544. Error Block 21 end (CF ANALYSIS FAILED)
	-- KONSTANTERROR: [543] 444. Error Block 6 start (CF ANALYSIS FAILED)
	-- KONSTANTERROR: Expression was reused, decompilation is incorrect
	-- KONSTANTERROR: [543] 444. Error Block 6 end (CF ANALYSIS FAILED)
end)(...)```
`StarterPlayer.StarterPlayerScripts.CanSecurity (LOCAL).CanModule`

– Decompiler will be improved soon!
– Decompiled with Konstant V2.1, a fast Luau decompiler made in Luau by plusgiant5 (Variable! Luau uncompilings professional)
– Decompiled on 2025-01-01 21:23:19
– Luau version 6, Types version 3
– Time taken: 0.008507 seconds

local HttpService_upvr = game:GetService(“HttpService”)
local function base64Encode_upvr(arg1) – Line 7, Named “base64Encode”
return arg1:gsub(‘.’, function(arg1_2) – Line 9
local any_byte_result1_2 = arg1_2:byte()
local var6
for i = 8, 1, -1 do
local var7
if 0 < any_byte_result1_2 % 2 ^ i - any_byte_result1_2 % 2 ^ (i - 1) then
var7 = ‘1’
else
var7 = ‘0’
end
var6 = var6…var7
end
return var6
end)…“0000”:gsub(“%d%d%d?%d?%d?%d?”, function(arg1_3) – Line 13
local var11
if var11 < 6 then
var11 = “”
return var11
end
var11 = 0
for i_2 = 1, 6 do
local var12
local function INLINED() – Internal function, doesn’t exist in bytecode
var12 = 2 ^ (6 - i_2)
return var12
end
if arg1_3:sub(i_2, i_2) ~= ‘1’ or not INLINED() then
var12 = 0
end
var11 += var12
end
return “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”:sub(var11 + 1, var11 + 1)
end)…({“”, “==”, ‘=’})[#arg1 % 3 + 1]
end
local function base64Decode_upvr(arg1) – Line 22, Named “base64Decode”
return string.gsub(arg1, “[^”…“ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”…“=]”, “”):gsub(‘.’, function(arg1_4) – Line 25
if arg1_4 == ‘=’ then
return “”
end
local var17 = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/”:find(arg1_4) - 1
for i_3 = 6, 1, -1 do
local var18
if 0 < var17 % 2 ^ i_3 - var17 % 2 ^ (i_3 - 1) then
var18 = ‘1’
else
var18 = ‘0’
end
end
return “”…var18
end):gsub(“%d%d%d?%d?%d?%d?%d?%d?”, function(arg1_5) – Line 30
local var22
if var22 ~= 8 then
var22 = “”
return var22
end
var22 = 0
for i_4 = 1, 8 do
local var23
local function INLINED_2() – Internal function, doesn’t exist in bytecode
var23 = 2 ^ (8 - i_4)
return var23
end
if arg1_5:sub(i_4, i_4) ~= ‘1’ or not INLINED_2() then
var23 = 0
end
var22 += var23
end
return string.char(var22)
end)
end
local function bitwiseXOR_upvr(arg1, arg2) – Line 39, Named “bitwiseXOR”
local var25
while not (0 < arg1 or 0 >= arg2) do
if arg1 % 2 ~= arg2 % 2 then
var25 += 1
end
end
return var25
end
local function crc32_upvr(arg1) – Line 56, Named “crc32”
–[[ Upvalues[1]:
[1]: bitwiseXOR_upvr (readonly)
]]
local var30
for i_5 = 1, #arg1 do
var30 = bitwiseXOR_upvr(var30, string.byte(arg1, i_5))
for _ = 1, 8 do
if var30 % 2 ~= 0 then
var30 = bitwiseXOR_upvr(var30 // 2, 3988292384)
else
var30 //= 2
end
end
end
return string.char(var30 % 256)
end
local function customBitwiseOperation_upvr(arg1, arg2) – Line 73, Named “customBitwiseOperation”
local var33 = arg1
for i_7 = 0, 7 do
var33 = bit32.bxor(var33, bit32.lshift(bit32.band(arg2, 1), i_7))
end
return var33
end
local function substituteCipher_upvr(arg1, arg2) – Line 86, Named “substituteCipher”
–[[ Upvalues[1]:
[1]: customBitwiseOperation_upvr (readonly)
]]
local module_3 = {}
for i_8 = 1, #arg1 do
table.insert(module_3, string.char(customBitwiseOperation_upvr(string.byte(arg1, i_8), string.byte(arg2, (i_8 - 1) % #arg2 + 1))))
end
return table.concat(module_3)
end
local function xor_upvr(arg1, arg2) – Line 98, Named “xor”
local var39 = “”
for i_9 = 1, #arg1 do
var39 = var39…string.char(bit32.bxor(arg1:byte(i_9), arg2:byte((i_9 - 1) % #arg2 + 1)))
end
return var39
end
local function aesEncrypt_upvr(arg1, arg2) – Line 109, Named “aesEncrypt”
–[[ Upvalues[1]:
[1]: xor_upvr (readonly)
]]
local var42 = arg1…string.char(16 - #arg1 % 16):rep(16 - #arg1 % 16)
local var43 = “”
for i_10 = 1, #var42, 16 do
var43 = var43…xor_upvr(var42:sub(i_10, i_10 + 16 - 1), arg2)
end
return var43
end
local function aesDecrypt_upvr(arg1, arg2) – Line 120, Named “aesDecrypt”
–[[ Upvalues[1]:
[1]: xor_upvr (readonly)
]]
local var46 = “”
for i_11 = 1, #arg1, 16 do
var46 = var46…xor_upvr(arg1:sub(i_11, i_11 + 16 - 1), arg2)
end
return var46:sub(1, -var46:byte(-1) - 1)
end
local function customEncrypt_upvr(arg1, arg2) – Line 132, Named “customEncrypt”
–[[ Upvalues[5]:
[1]: substituteCipher_upvr (readonly)
[2]: aesEncrypt_upvr (readonly)
[3]: xor_upvr (readonly)
[4]: crc32_upvr (readonly)
[5]: base64Encode_upvr (readonly)
]]
local function rotateBits(arg1_6, arg2_2) – Line 140
local var49 = “”
for i_12 = 1, #arg1_6 do
local any_byte_result1_3 = arg1_6:byte(i_12)
var49 = var49…string.char(bit32.bor(bit32.lshift(any_byte_result1_3, arg2_2), bit32.rshift(any_byte_result1_3, 8 - arg2_2)) % 256)
end
return var49
end
local function bitwiseSwap(arg1_7) – Line 155
local var53 = “”
for i_13 = 1, #arg1_7, 2 do
var53 = var53…string.char(arg1_7:byte(i_13 + 1) or 0)…string.char(arg1_7:byte(i_13))
end
return var53
end
local bitwiseSwap_result1 = bitwiseSwap(xor_upvr(rotateBits(aesEncrypt_upvr(substituteCipher_upvr(arg1, arg2), arg2:sub(1, 16)), 3), arg2:sub(1, 16)))
return base64Encode_upvr(bitwiseSwap_result1…crc32_upvr(bitwiseSwap_result1))
end
local function customDecrypt_upvr(arg1, arg2) – Line 175, Named “customDecrypt”
–[[ Upvalues[5]:
[1]: base64Decode_upvr (readonly)
[2]: crc32_upvr (readonly)
[3]: xor_upvr (readonly)
[4]: aesDecrypt_upvr (readonly)
[5]: substituteCipher_upvr (readonly)
]]
local base64Decode_upvr_result1 = base64Decode_upvr(arg1)
local len = #base64Decode_upvr_result1
local any_sub_result1 = base64Decode_upvr_result1:sub(1, len - 1)
if base64Decode_upvr_result1:sub(len) == crc32_upvr(any_sub_result1) then
return substituteCipher_upvr(aesDecrypt_upvr((function(arg1_9, arg2_3) – Line 198, Named “rotateBits”
local var63 = “”
for i_15 = 1, #arg1_9 do
local any_byte_result1 = arg1_9:byte(i_15)
var63 = var63…string.char(bit32.bor(bit32.rshift(any_byte_result1, arg2_3), bit32.lshift(any_byte_result1, 8 - arg2_3)) % 256)
end
return var63
end)(xor_upvr((function(arg1_8) – Line 183, Named “bitwiseSwap”
local var60 = “”
for i_14 = 1, #arg1_8, 2 do
var60 = var60…string.char(arg1_8:byte(i_14 + 1) or 0)…string.char(arg1_8:byte(i_14))
end
return var60
end)(any_sub_result1), arg2:sub(1, 16)), 3), arg2:sub(1, 16)), arg2:sub(1, 16))
end
warn(“Data integrity check failed.”)
return nil
end
local function generateKey_upvr(arg1) – Line 225, Named “generateKey”
–[[ Upvalues[1]:
[1]: base64Encode_upvr (readonly)
]]
if arg1 == nil then
end
for _ = 1, math.min(16, 16) do
table.insert({}, string.char(math.random(0, 255)))
local var68
end
return base64Encode_upvr(table.concat(var68))
end
local function _(arg1) – Line 239, Named “serializeTable”
–[[ Upvalues[1]:
[1]: HttpService_upvr (readonly)
]]
local pcall_result1_4, pcall_result2_4 = pcall(function() – Line 240
–[[ Upvalues[2]:
[1]: HttpService_upvr (copied, readonly)
[2]: arg1 (readonly)
]]
return HttpService_upvr:JSONEncode(arg1)
end)
if pcall_result1_4 then
return pcall_result2_4
end
warn("Failed to serialize table: "…pcall_result2_4)
return nil
end
local function _(arg1) – Line 251, Named “deserializeTable”
–[[ Upvalues[1]:
[1]: HttpService_upvr (readonly)
]]
local pcall_result1_3, pcall_result2_3 = pcall(function() – Line 252
–[[ Upvalues[2]:
[1]: HttpService_upvr (copied, readonly)
[2]: arg1 (readonly)
]]
return HttpService_upvr:JSONDecode(arg1)
end)
if pcall_result1_3 then
return pcall_result2_3
end
return arg1
end
return {
EncryptData = function(arg1, arg2) – Line 271, Named “EncryptData”
–[[ Upvalues[4]:
[1]: generateKey_upvr (readonly)
[2]: HttpService_upvr (readonly)
[3]: base64Decode_upvr (readonly)
[4]: customEncrypt_upvr (readonly)
]]
– KONSTANTWARNING: Variable analysis failed. Output will have some incorrect variable assignments
local var75
if arg2 == nil then
var75 = 16
local _ = generateKey_upvr(var75)
else
end
local var77 = arg1
if type(arg1) == “table” then
local pcall_result1_2, pcall_result2_2 = pcall(function() – Line 240
–[[ Upvalues[2]:
[1]: HttpService_upvr (copied, readonly)
[2]: arg1 (readonly)
]]
return HttpService_upvr:JSONEncode(arg1)
end)
if pcall_result1_2 then
else
warn("Failed to serialize table: "…pcall_result2_2)
end
end
local var81
if var81 then
local module_2 = {
Status = “SUCCESS”;
Message = “Data was encrypted successfully”;
}
– KONSTANTERROR: Expression was reused, decompilation is incorrect
module_2.Key = arg2
module_2.Original = var77
module_2.EncryptedResult = customEncrypt_upvr(var81, base64Decode_upvr(arg2))
return module_2
end
return {
Status = “ERROR”;
Message = “Data encryption FAILED.”;
Key = nil;
Original = var77;
EncryptedResult = nil;
}
end;
DecryptData = function(arg1, arg2) – Line 319, Named “DecryptData”
–[[ Upvalues[3]:
[1]: base64Decode_upvr (readonly)
[2]: customDecrypt_upvr (readonly)
[3]: HttpService_upvr (readonly)
]]
local base64Decode_upvr_result1_2 = base64Decode_upvr(arg2)
local customDecrypt_result1_upvr = customDecrypt_upvr(arg1, base64Decode_upvr_result1_2)
if customDecrypt_result1_upvr then
local pcall_result1, pcall_result2 = pcall(function() – Line 252
–[[ Upvalues[2]:
[1]: HttpService_upvr (copied, readonly)
[2]: customDecrypt_result1_upvr (readonly)
]]
return HttpService_upvr:JSONDecode(customDecrypt_result1_upvr)
end)
if pcall_result1 then
base64Decode_upvr_result1_2 = pcall_result2
else
base64Decode_upvr_result1_2 = customDecrypt_result1_upvr
end
base64Decode_upvr_result1_2 = {}
base64Decode_upvr_result1_2.Status = “SUCCESS”
base64Decode_upvr_result1_2.Message = “Data Decryption Success.”
base64Decode_upvr_result1_2.Key = arg2
base64Decode_upvr_result1_2.OriginalEncrypted = arg1
base64Decode_upvr_result1_2.DecryptedResult = base64Decode_upvr_result1_2 or customDecrypt_result1_upvr
return base64Decode_upvr_result1_2
end
local module = {
Status = “ERROR”;
Message = “Data decryption FAILED.”;
Key = nil;
}
module.OriginalEncrypted = arg1
module.DecryptedResult = nil
return module
end;
generateKey = generateKey_upvr;
}

1 Like

u got the encryption part of it this is entirely useless because knowing the encryption process does not matter without the encryption key because this does not matter this is the only part of the script that is not obfuscated

i’ve identified how this script was accessed.

the bug occures because during initilization there is a slight wait before setting the parent of the client anti-cheat which creates an incredibly short interval in which the script can be interacted with.

thank you for bringing this to my attention i was unaware and under the assumption that most executors would not be able to inject into the client fast enough for this to occur.

1 Like

no matter where you parent it, it can be accessed

1 Like

jesus can u read the post no one has stated that and i’ve STATED LIKE FIVE TIMES IT DOES NOT MATTER IF ITS ACCESSED im just making it harder if another person replies without reading the post again im just gonna ignore them

1 Like

I’m sorry, but I have to disagree with this point. An obfuscator can strip away significant information by removing debugging symbols like line information, which immediately reduces the metadata available to reverse engineers. Beyond that, Luau obfuscators often flatten control flow, or replace high-level constructs with lower-level, harder-to-read equivalents (eg converting tables to buffers).

VM-based obfuscation goes even further by compiling into a custom bytecode format that runs, naturally, on a custom virtual machine. The original structure and logic are embedded in a completely new format, often obscured, and only the VM knows how to execute it.

Sure, in theory, the information still “exists” because the program behaves the same, but it’s not in a form that’s immediately understandable or even usable without significant reverse engineering effort.

2 Likes

modern obfuscators also offer anti-tamper protection and run the code in a sort of VM way, meaning that many debugging methods are blocked from even interacting. Thank you for saying this, as I’ve had to reiterate it like 20 times on this thread. Well said.

2 Likes

the key can be grabbed by any small vulnerability in your anti-cheat btw and exploiters dont necessarily have to replicate your handshake, they can just go around it

1 Like

man read the thread before you reply because if you did you would know that the “key” isnt just one key and it isnt just encoded in the script and they do have to replicate the handshake because they cant bypass the anti-cheat without replicating it

1 Like

here is ur bypass sir (WITHOUT Handshake replication): Put in auto execute

local old; old = hookfunction(coroutine.wrap, function(…)
if not checkcaller() then
return coroutine.yield()
end
return old(…)
end)
local old; old = hookfunction(table.create, function(…)
if not checkcaller() then
return coroutine.yield()
end
return old(…)
end)

2 Likes

Luau obfuscation is easy to deobfuscate with how simple luau is. You can hook everything in the obfuscator vm at the c level

1 Like

thank you ill test this later and find a patch

[UPDATE]

patched vulnerability please give me more of these so i can continue to make the anti-cheat stronger

update will be rolled out to the demo place in an hour or so but its patched on the dev place

added a backup method of communicating to the server incase the original method of communication is closed cant disclose how this works because it is easily bypassed but im sure if you use rspy it will be very obvious

1 Like