How would I accurately compare values of a table to another tables values?

I’m trying to pass a table through a remote event then compare that to another table and if the tables don’t match it will kick the player (aka making an anti-cheat for the remote with 55 keys. Also, yes the key’s will be hard to predict & ik ofc not practical I just wanna see what I can make) I saw some other threads similar but they were confusing or didn’t answer the question directly.

My main issue right now is that it’s only checking for if there are 55 items in the table and not if the 55 items are the same value. (in this simplified case 3 items)

Local Script (This is a simplified version obv, not the real one)

local remote = game:GetService("SoundService"):WaitForChild("RemoteEvent")

local Arguments = {
    [1] = "a"
    [2] = "b"
    [3] = "c"
}

remote:FireServer(unpack(Arguments))

Server Script (Again simplified)

local remote = game:GetService("SoundService"):WaitForChild("RemoteEvent")

remote.OnServerEvent:Connect(function(plr,Arguments)
    local Arguments1 = {
        [1] = "a"
        [2] = "b"
        [3] = "c"
    }

    if unpack(Arguments) == unpack(Arguments1) then

    else
        plr:Kick("non epic gamer detected")
    end
end
1 Like

To answer your main question, your current script detects if the first value is the same in both tables.

Why is this happening? The simplest way to answer is that functions can return multiple values, but operators can accept only one on each side (some only on one). == is the equality operator and it checks if the value (not values) on the left is equal to the one on the right and returns a boolean.

unpack(tab) is a function which “unpacks” the array components of a given table into returned values. As said before, since functions return multiple values, there are cases where some aren’t required. Since == only accepts one value on each side, while your unpack of the table returns 3 values, it will take the first returned value from each. This means that instead of checking whether the 1st, 2nd and 3rd values of the tables are equal, it will only check the 1st.

Here’s a simple example:

local func1 = function ()
    return 1,2,3
end
local func2 = function()
    return 1,4,5
end
print(func1()==func2()) --> true because it never got 2, 3, 4 or 5

To fix this, here’s a simple check:

local function CheckTableEquality(t1,t2)
    for i,v in next, t1 do if t2[i]~=v then return false end end
    for i,v in next, t2 do if t1[i]~=v then return false end end
    return true
end

Here’s a slightly faster array variant:

local function CheckArrayEquality(t1,t2)
    if #t1~=#t2 then return false end
    for i=1,#t1 do if t1[i]~=t2[i] then return false end end
    return true
end

As for the actual anti-cheat method. I don’t exactly know what you are doing, but just the fact that you need to check validity of something on the client is already a red flag. Any sensitive information such as scores or inventory items should be stored 100% on the server. The client should just have a dumbed down simulation of what would happen if they had those items to avoid desyncs. Inconsistencies can then be checked through sent remotes when the player wants to interact with something.

16 Likes

Hey MasonTheCreeper,

It looks like you’re trying to provide a security measure with these tables. I don’t have a lot of information to go off of, but I think you might want to consider going about this another way.

First, the server should contain all data and be able to verify arguments passed from client using server-checks.

But you’re not relying on server-checks. So heres my observation:

The client has information that the server doesn’t, and it uses this table to verify such communication. But if the table on the server and the table on the client have to be the same. No new information will be put in the table sent from the client to the server.
So, this means that the tables entire purpose is a key.

But, the client knows the key, so it can send that table to the server to verify anything it sends in other arguments. Although, lets assume the client only knows the key when it sends information, the key is not dependent on information because the server doesn’t have it. And since, its not stored then the key isn’t random unless you have a psuedo-random function with a counter or some other variable(s). But it can’t rely on a psuedo-random function, because the server doesn’t have a key to generate one that the client does not.

So my point is that even though this throws attackers off, it can still be exploited; because the client can send the same table again and again. It simply knows the table, so it doesn’t need to guess it.

If you want to implement a situation that works then you can look at diffie hellman key exchanges.
But if the table is truly dependent on data that the server and client both know, its best to use a server check with an if statement comparing values.

2 Likes