xboxxxxd

groundpickups (weapons), CallServerFunction leaks, any help?..

Recommended Posts

Hello there Humans :P,

a week or 2 ago i downloaded a resource from the resource community (https://community.multitheftauto.com/index.php?p=resources),

And it's a Groundpickups resource, it was outdated, like bugs appeared when i started using it and testing it,

i thought by myself, let's fix these render bugs and outdated functions, alright, about 1 week later i got it fixed,

i uploaded it to the resource community, BAM.. no problem!..

But like an hour or 2 later, ccw (an administrator) suspended it, while it's nearly the same piece of code like as that of GroundPickups,

and i look'd at the reason why it got suspended, well.. 'CallServerFunction' was that reason why it got suspended!.

And then i thought by myself, well.. if this is insecure against hackers and such, then why is the original GroundPickups not suspended (i send a message about it to ccw, he suspended it now).

 

But, now the following thing is, i now want to secure the 'callServerFunction',

But i don't even know and never used this type of function's before, so now to anyone who wil help me out, thanks for the help,

Now the script itself, i've try'ed some stuff and to merge the example's of 'callServerFunction' into the groundpickups script, but without success >.<

(There's 1 Export in the meta.xml, just for the info it's:     <export function = "createGroundWeapon" type = "server" /> )

So this is the script right before i started trying to add a secure method for this function:

client.lua (Client-Side Script):

screenWidth, screenHeight = guiGetScreenSize() -- Get the screen resolution
shrifteg = (0.015 * screenHeight) / 9
localPlayer = getLocalPlayer()
currentGround = nil
elementgg = {}
gta4markers = true

weaponmarkercolors = {
	[0] = {255,255,255},
	[1] = {100,100,255},
	[2] = {0,230,0},
	[3] = {0,150,0},
	[4] = {255,255,0},
	[5] = {255,204,0},
	[6] = {150,0,150},
	[7] = {255,0,255},
	[8] = {0,0,255},
	[9] = {204,255,255},
	[10] = {255,100,100},
	[11] = {255,255,255},
	[12] = {255,255,255}
}

slots = {
	[1] = 0,
	[2] = 1,[3] = 1,[4] = 1,[5] = 1,[6] = 1,[7] = 1,[8] = 1,[9] = 1,
	[24] = 2,[23] = 2,[22] = 2,
	[25] = 3,[26] = 3,[27] = 3,
	[29] = 4,[32] = 4,[28] = 4,
	[30] = 5,[31] = 5,
	[33] = 6,[34] = 6,
	[35] = 7,[36] = 7,[37] = 7,[38] = 7,
	[16] = 8,[17] = 8,[18] = 8,[39] = 8,
	[41] = 9,[42] = 9,[43] = 9,
	[10] = 10,[11] = 10,[12] = 10,[13] = 10,[14] = 10,[15] = 10,
	[44] = 11,[45] = 11,[46] = 11,
	[40] = 12
}

weaponsIDS = {
	--0
	[1] = 331,
	--1
	[2] = 333,
	[3] = 334,
	[4] = 335,
	[5] = 336,
	[6] = 337,
	[7] = 338,
	[8] = 339,
	[9] = 341,
	--2
	[22] = 346,
	[23] = 347,
	[24] = 348,
	--3
	[25] = 349,
	[26] = 350,
	[27] = 351,
	--4
	[28] = 352,
	[29] = 353,
	[32] = 372,
	--5
	[30] = 355,
	[31] = 356,
	--6
	[33] = 357,
	[34] = 358,
	--7
	[35] = 359,
	[36] = 360,
	[37] = 361,
	[38] = 362,
	--8
	[16] = 342,
	[17] = 343,
	[18] = 344,
	[39] = 363,
	--9
	[41] = 365,
	[42] = 366,
	[43] = 367,
	--10
	[10] = 321,
	[11] = 322,
	[12] = 323,
	[13] = 324,
	[14] = 325,
	[15] = 326,
	--11
	[44] = 368,
	[45] = 369,
	[46] = 371,
	--12
	[40] = 364
}

function client_createGroundWeapon(groundweapon)
	if(elementgg[groundweapon] == nil) then
		local temp = createColSphere(tonumber(getElementData(groundweapon, "posX")),tonumber(getElementData(groundweapon, "posY")),tonumber(getElementData(groundweapon, "posZ"))+0.5, 1)
		--[[local temp = createColCuboid(tonumber(getElementData(groundweapon, "posX"))-0.5,
		tonumber(getElementData(groundweapon, "posY"))-0.5,
		tonumber(getElementData(groundweapon, "posZ"))-1,
		1,1,2)]]
		
		setElementData(temp, "colshape.groundweapon", groundweapon)
		setElementData(temp, "colshape.weaponid", tonumber(getElementData(groundweapon, "weaponid")))
		setElementData(temp, "colshape.ammo", tonumber(getElementData(groundweapon, "ammo")))
		setElementData(temp, "colshape.clip", tonumber(getElementData(groundweapon, "clip")))
		elementgg[groundweapon] = temp
		local slot = slots[tonumber(getElementData(groundweapon, "weaponid"))]

		--createObject
		local object = createObject(weaponsIDS[tonumber(getElementData(groundweapon, "weaponid"))],
		tonumber(getElementData(groundweapon, "posX")),tonumber(getElementData(groundweapon, "posY")),tonumber(getElementData(groundweapon, "posZ")),
		tonumber(getElementData(groundweapon, "rotX")),tonumber(getElementData(groundweapon, "rotY")),tonumber(getElementData(groundweapon, "rotZ")))
		setObjectStatic(object, true)
		setElementCollisionsEnabled(object, false)

		setElementInterior(object, tonumber(getElementData(groundweapon, "interior")))
		setElementDimension(object, tonumber(getElementData(groundweapon, "dimension")))
		
		setElementData(temp, "colshape.object", object)

		--createMarker
		local marker = createMarker(tonumber(getElementData(groundweapon, "posX")),
		tonumber(getElementData(groundweapon, "posY")),
		tonumber(getElementData(groundweapon, "posZ"))+0.05,
		"corona", 0.5, weaponmarkercolors[slot][1],weaponmarkercolors[slot][2], weaponmarkercolors[slot][3], 20)

		setElementInterior(marker, tonumber(getElementData(groundweapon, "interior")))
		setElementDimension(marker, tonumber(getElementData(groundweapon, "dimension")))
			
		setElementData(temp, "colshape.marker", marker)

		local x,y,z = getElementPosition(localPlayer)
		if(getDistanceBetweenPoints2D(x,y,tonumber(getElementData(groundweapon, "posX")),tonumber(getElementData(groundweapon, "posY"))) < 0.25) then local_activate(temp, localPlayer,true) end
	end
end

function client_destroyGroundWeapon(groundweapon)
	local col = elementgg[groundweapon]
	local object = getElementData(col, "colshape.object")
	local marker = getElementData(col, "colshape.marker")
	if(isElement(object)) then destroyElement(object) end
	if(isElement(marker)) then destroyElement(marker) end
	if(isElement(col)) then destroyElement(col) end
	elementgg[groundweapon] = nil
end

function pickupCurrentWeapon()
	if(isElement(currentGround)) then
		local weaponid = getElementData(currentGround, "colshape.weaponid")
		local ammo = getElementData(currentGround, "colshape.ammo")
		local clip = getElementData(currentGround, "colshape.clip")

		if(getPedWeapon(localPlayer, slots[weaponid]) ~= 0) then dropWeapon(slots[weaponid]) end
		
		if(ammo) then
			local groundweapon = getElementData(currentGround, "colshape.groundweapon")
			callServerFunction("destroyElement", groundweapon)
			callServerFunction("giveWeapon", localPlayer, weaponid, ammo, true)
			callServerFunction("setWeaponAmmo", localPlayer, weaponid, ammo, clip)
			for i,p in ipairs(getElementsByType("colshape")) do
				if(isElementWithinColShape(localPlayer, p) == true) then
					local_activate(p, localPlayer,true)
				else
				if( not isElementWithinColShape(localPlayer, p) ) then
					break
					end
				end
			end
		end
	end
end

function dropWeapon(slot)
	if(slot > 0) then
		local weaponid = getPedWeapon(localPlayer, slot)
		if(weaponid ~= 0) then
			callServerFunction("takeWeapon", localPlayer, weaponid)
			local x,y,z = getElementPosition(localPlayer)
			local hit, hitX, hitY, hitZ, as = processLineOfSight(x, y, z, x, y, -3000, true, false, false, true, false, false, false, false)
			if(hit) then z = hitZ
			else z = z - 0.95 end
			callServerFunction("createGroundWeapon", weaponid, getPedTotalAmmo(localPlayer), getPedAmmoInClip(localPlayer), x,y,z, 97.3,120,math.random(0,359),getElementInterior(localPlayer),getElementDimension(localPlayer))
		end
	end
end

function local_activate(shape, element,dimension)
	if(element == localPlayer) then
		--local groundweapon = getElementData(shape, "colshape.groundweapon")
		--local object = getElementData(shape, "colshape.object")
		--local marker = getElementData(shape, "colshape.marker")
		currentGround = shape
	end
end

addEventHandler("onClientResourceStart", getRootElement(),
	function(startedRes)
		if(startedRes == getThisResource()) then
			bindKey("k", "down", "pickup/swap weapon")
			bindKey("l", "down", "drop weapon")
		else
			for i,p in pairs(getElementsByType("groundweapon")) do --getResourceRootElement(startedRes)
				client_createGroundWeapon(p)
			end
		end
	end
)

addEventHandler("onClientResourceStop", getResourceRootElement(),
	function(startedRes)
		for i,p in pairs(getElementsByType("groundweapon")) do
			client_destroyGroundWeapon(p)
		end
	end
)

addEventHandler("onClientRender", getRootElement(),
	function()
		if(isElement(currentGround)) then
			local weaponid = getElementData(currentGround, "colshape.weaponid")
			local ammo = getElementData(currentGround, "colshape.ammo")

			sx,sy = screenWidth/2, screenHeight/2

			local str = "false"
			
			dxDrawRectangle(sx-80, sy-20, 160, 75, tocolor(0, 0, 0, 128))

			if(getPedWeapon(localPlayer, slots[weaponid]) ~= 0) then
				str = "swap weapons"
				dxDrawImage(sx-13, sy+13, 26, 26, "img/swap.png")
				
				dxDrawImage(sx+20, sy-10, 50, 50, "img/" .. weaponid .. ".png")
				dxDrawImage(sx-70, sy-10, 50, 50, "img/" .. getPedWeapon(localPlayer, slots[weaponid]) .. ".png")
				
				dxDrawText(tostring(ammo),
				sx+45, sy+45, sx+45, sy+45,
				tocolor(255,255,255,255), 1, "default-bold", "center", "center")
				
				dxDrawText(tostring(getPedTotalAmmo(localPlayer, slots[weaponid])) .. " (you)",
				sx-45, sy+45, sx-45, sy+45,
				tocolor(255,255,255,255), 1, "default-bold", "center", "center")
			else
				str = "pickup weapon"
				dxDrawImage(sx-25, sy-10, 50, 50, "img/" .. tonumber(weaponid) .. ".png")
				
				dxDrawText(tostring(ammo),
				sx, sy+45, sx, sy+45,
				tocolor(255,255,255,255), 1, "default-bold", "center", "center")
			end

			dxDrawText("Use 'k' to " .. str,
			sx, sy-20, sx, sy-20,
			tocolor(255,255,50,255), 1, "default-bold", "center", "center")
		end
	end
)


addEventHandler("onClientPlayerWasted", localPlayer,
	function()
		dropWeapon(getPedWeaponSlot(localPlayer))
	end
)

addEventHandler("onClientElementDestroy", getRootElement(),
	function()
		if(getElementType(source) == "groundweapon") then
			client_destroyGroundWeapon(source)
		end
	end
)

addEventHandler("onClientColShapeHit", getResourceRootElement(),
	function(element,dimension)
		local_activate(source, element,dimension)
	end
)

addEventHandler("onClientColShapeLeave", getResourceRootElement(),
	function(element,dimension)
		if(element == localPlayer) then
			currentGround = nil
			for i,p in ipairs(getElementsByType("colshape")) do
				if(isElementWithinColShape(localPlayer, p) == true) then
					local_activate(p, localPlayer,true)
					else
				if( not isElementWithinColShape(localPlayer, p) ) then
					break
					end
				end
			end
		end
	end
)

addCommandHandler("pickup/swap weapon", function() pickupCurrentWeapon() end)

addCommandHandler("drop weapon", function() dropWeapon(slots[getPedWeapon(localPlayer)]) end)

function callServerFunction(funcname, ...)
    local arg = { ... }
    if (arg[1]) then
        for key, value in next, arg do
            if (type(value) == "number") then arg[key] = tostring(value) end
        end
    end
    -- If the serverside event handler is not in the same resource, replace 'resourceRoot' with the appropriate element
    triggerServerEvent("onClientCallsServerFunction", resourceRoot , funcname, unpack(arg))
end

function callClientFunction(funcname, ...)
    local arg = { ... }
    if (arg[1]) then
        for key, value in next, arg do arg[key] = tonumber(value) or value end
    end
    loadstring("return "..funcname)()(unpack(arg))
end
addEvent("onServerCallsClientFunction", true)
addEventHandler("onServerCallsClientFunction", resourceRoot, callClientFunction)

server.lua (Server-Side Script):

function createGroundWeapon(weaponid, ammo, clip, posX, posY, posZ, rotX, rotY, rotZ, interior, dimension)
	local temp = createElement("groundweapon")
	setElementData(temp, "weaponid", weaponid)
	setElementData(temp, "ammo", ammo)
	setElementData(temp, "clip", clip)
	setElementData(temp, "posX", posX)
	setElementData(temp, "posY", posY)
	setElementData(temp, "posZ", posZ)
	setElementData(temp, "rotX", rotX)
	setElementData(temp, "rotY", rotY)
	setElementData(temp, "rotZ", rotZ)
	setElementData(temp, "interior", interior)
	setElementData(temp, "dimension", dimension)
	for i,p in ipairs(getElementsByType("player")) do
		callClientFunction(p, "client_createGroundWeapon", temp)
	end
	return temp
end

addEventHandler("onResourceStop", getResourceRootElement(),
	function(startedRes)
		if(startedRes == getThisResource()) then
			for i,p in pairs(getElementsByType("groundweapon")) do
				destroyElement(p)
			end
		end
	end
)

function callServerFunction(funcname, ...)
    local arg = { ... }
    if (arg[1]) then
        for key, value in next, arg do arg[key] = tonumber(value) or value end
    end
    loadstring("return "..funcname)()(unpack(arg))
end
addEvent("onClientCallsServerFunction", true)
addEventHandler("onClientCallsServerFunction", resourceRoot , callServerFunction)

function callClientFunction(client, funcname, ...)
    local arg = { ... }
    if (arg[1]) then
        for key, value in next, arg do
            if (type(value) == "number") then arg[key] = tostring(value) end
        end
    end
    triggerClientEvent(client, "onServerCallsClientFunction", resourceRoot, funcname, unpack(arg or {}))
end

Like always, Thanks for any Answers and/or Solutions you people come up with!..

Gr.xboxxxxd

 

EDIT: If you want to, just make it in someway possible to replace all the call function's into events or somthing, ;)

Edited by xboxxxxd

Share this post


Link to post

We as staff decided to patch the vulnerability by removing insecure callServerFunction (replacing with alternative) so it's unsuspended and updated now.

https://community.multitheftauto.com/index.php?p=resources&s=details&id=1474

@Lex128 some structural improvements that were inevitable in improving script security even further were made, what do you think about it?

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Recently Browsing   0 members

    No registered users viewing this page.