Exploiters manipulating remotes

I think I have found the exploiter and currently trying to get info out of him.
Currently got so far that he is able to manipulate all number values with my unload gun event.
He is using some weird method, he told me that he is sending a table instead of my normal object value that it normally receives.

he uses something like this
UnloadEvent:FireServer({idk1=idk2, idk3=idk4})

my server script is below

local function onUnloadEvent(playerQ, itemQ) -- he sends a table here
	--print("unload")
	spawn(function()	
		local player, item = playerQ, itemQ
		local rs_player = game.ReplicatedStorage.Players:FindFirstChild(player.Name)
		
		local SecurityCheck = false
		if isInTable(InvSystemLocalTypes, item.Parent.Name) and item.Parent.Parent == rs_player then
			SecurityCheck = true -- checked if the gun is in players inv who fired it
		elseif rs_player.Status.Looting.CurrentContainer.Value ~= nil then
			local selectedContainer = rs_player.Status.Looting.CurrentContainer.Value
			local Inv = selectedContainer.Properties.Inventory
			local virtualInv = selectedContainer.Properties.VirtualInventory.Value
			if item.Parent.Parent == virtualInv then
				SecurityCheck = true -- checked if the gun is in the container that the player who sent it is looting
			end
		end
		if SecurityCheck == true then -- the weird thing is how can he pass the check
			local InventoryStorageEmptySlots = 24
			local InventoryStorage = {}
			for _, v  in pairs(rs_player.Inventory:GetChildren()) do table.insert(InventoryStorage, v) end
			InventoryStorageEmptySlots = InventoryStorageEmptySlots - #InventoryStorage
				
			local ToolbarStorageEmptySlots = 6
			local ToolbarStorage = {}
			for _, v  in pairs(rs_player.Toolbar:GetChildren()) do table.insert(ToolbarStorage, v) end
			ToolbarStorageEmptySlots = ToolbarStorageEmptySlots - #ToolbarStorage
			
			local needToStackMore = StackInto(player, rs_player.Inventory, item ,InventoryStorageEmptySlots)
			if needToStackMore > 0 then
				local needToStackMore = StackInto(player, rs_player.Toolbar, item, ToolbarStorageEmptySlots)
			end	
		end
	end)
end

ps. wanted to add that he can only lower values with that

there are other events possibly having the same bypass

what currently doesn’t make sense is how can he manipulate the check to let it pass and also how can he change the object that he can change all number values in game. This script is designed to only change “LoadedAmmo” value.

Don’t know the exact details of this but a general rule of thumb is that exploiters can and will be able to manipulate remotes in any way. They can do anything with that remote a local script can do.
Its also possible for exploiters to view which remotes are fired, what their values are and such.

1 Like

What exactly is he able to accomplish by forging the arguments to this event?

1 Like

yeah that’s pretty logical, clients can do anything to be honest.

But I don’t understand how can he bypass my checks and also how can he edit that server script to change other values that are stored in numbers.

Yeah good question, from what I understand he’s messing with the unloading time, I don’t see the part that does that in the script you provided.

1 Like

He can change any number value stored in the game that client and server can see.

He cant. It is and will always be an impossibility for exploiters and client sided scripts to change server scripts directly. There must be some other variable or such that the client has access to for him to be able to change it.

yep know that, but in some weird way he can manipulate any number value through this remote.
But I am not understanding how this would be possible in anyway this is why I came here.

For starters, I don’t understand or see any code that’s changing number values.
But what I do know is that you are letting the server trust the item the client sends.

Take these lines of code for example:

local player, item = playerQ, itemQ

This makes the server trust whatever the client has sent, which is the first rule of remote events:
Never trust the client. There should be a sanity check performed if your client scripts send Instances as arguments, because they can be faked as tables.

Now if I were to do:

UnloadEvent:FireServer({
    Parent = {
        Name = "some name",
        Parent = {
            Name = "some other name"
        }
    }
})

The server would interpret this as a valid “item” object. I’m not sure how important faking these arguments are; I still don’t know what StackInto is doing that trusts the item he’s sending. He’s most likely spied on your remote events and sent a fake table with modified info.

1 Like

Exactly. Thats what I was getting at

I don’t want to leak my whole script so i will give the part where it changes the current ammo value to 0 after creating a stack of ammo that the gun unloaded

Item.ItemProperties.LoadedAmmo.Value = 0

currently I still don’t understand how sending it as a table can bypass
if it’s a table shouldn’t it error, because it’s expecting an object value

Since the item is a table they can just send the following:

{
    ItemProperties = {
        LoadedAmmo = any_value_instance
    }
}

Your code will then follow the table and assign the .Value of whatever and any object that is at the LoadedAmmo key.

3 Likes

wait for real let me check real quick. So I should make a if table then stop or return check?

You can just check against the typeof(item) value and make sure it’s an Instance. But you also need to check that the instance being sent is parented to the right place, of the right class, etc.

You’re better off making it so the server finds this instance itself or already has access to it somehow rather than relying on the client passing an instance reference.

3 Likes

Thank you so much, didn’t think bypassing that way was possible.