Files
wnsrc/addons/eprotect_1.3.15/lua/e_protect/server/sv_eprotect.lua
lifestorm 324f19217d Upload
2024-08-05 18:40:29 +03:00

575 lines
15 KiB
Lua

--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
eProtect = eProtect or {}
eProtect.queneData = eProtect.queneData or {}
eProtect.saveQueue = eProtect.saveQueue or {}
eProtect.data = eProtect.data or {}
eProtect.data.disabled = eProtect.data.disabled or {}
local ignoreSaving = {
["fakeNets"] = true,
["netLogging"] = true,
["exploitPatcher"] = true
}
util.AddNetworkString("eP:Handeler")
local function openMenu(ply)
net.Start("eP:Handeler")
net.WriteUInt(2, 3)
net.Send(ply)
end
local convertedTbl
convertedTbl = function(tbl)
local converted_tbl = {}
for k,v in pairs(tbl) do
if istable(v) then v = convertedTbl(v) end
local isSID = util.SteamIDFrom64(k) != "STEAM_0:0:0"
if isSID then
converted_tbl["sid64_"..k] = v
else
converted_tbl[k] = v
end
end
return converted_tbl
end
local function networkData(ply, data, specific)
if !data then return end
local data = util.TableToJSON(convertedTbl(data))
data = util.Compress(data)
net.Start("eP:Handeler")
net.WriteUInt(1, 3)
net.WriteUInt(#data, 32)
net.WriteData(data, #data)
if specific then
net.WriteString(specific)
end
net.Send(ply)
end
eProtect.hasPermission = function(ply, specific)
return eProtect.config["permission"][ply:GetUserGroup()]
end
local punished = {}
eProtect.getData = function(specific)
local data = file.Read("eprotect/data.json", "DATA")
if !data then return end
data = util.JSONToTable(data)
if specific then
data = data[specific]
end
for k,v in pairs(data) do
eProtect.data[k] = v
end
return table.Copy(data)
end
eProtect.dataVerification = function()
local data = eProtect.getData()
data = data or {}
data["general"] = data["general"] or {}
for k,v in pairs(eProtect.BaseConfig) do
if data["general"][k] then continue end
data["general"][k] = v[1]
end
for k,v in pairs(eProtect.data) do
if ignoreSaving[k] or k == "general" then continue end
data[k] = v
end
file.CreateDir("eprotect")
file.Write("eprotect/data.json", util.TableToJSON(data))
eProtect.getData()
eProtect.queueNetworking()
end
eProtect.saveData = function()
file.CreateDir("eprotect")
local data = table.Copy(eProtect.data)
for k, v in pairs(data) do
if ignoreSaving[k] then data[k] = nil end
end
file.Write("eprotect/data.json", util.TableToJSON(data))
end
eProtect.canNetwork = function(ply, netstring)
if !IsValid(ply) or !ply:IsPlayer() then return end
if (punished[ply:SteamID()] or eProtect.data.disabled[ply:SteamID()] or eProtect.data.general["disable-all-networking"]) and (netstring ~= "eP:Handeler") then return false end
return true
end
eProtect.punish = function(ply, type, msg, duration)
if eProtect.data.general["bypassgroup"][ply:GetUserGroup()] or eProtect.data.general["bypass_sids"][ply:SteamID()] or eProtect.data.general["bypass_sids"][ply:SteamID64()] then return end
msg = eProtect.config["prefix"]..msg
punished[ply:SteamID()] = true
slib.punish(ply, type, msg, duration)
end
eProtect.networkData = function(ply)
if eProtect.queneData[ply:SteamID()] then
for k,v in pairs(eProtect.queneData[ply:SteamID()]) do
networkData(ply, eProtect.data[k], k)
eProtect.queneData[ply:SteamID()][k] = nil
end
end
end
local function registerQuene(ply, specific)
if specific then
eProtect.queneData[ply:SteamID()] = eProtect.queneData[ply:SteamID()] and eProtect.queneData[ply:SteamID()] or {}
eProtect.queneData[ply:SteamID()][specific] = true
else
for k,v in pairs(eProtect.data) do
registerQuene(ply, k)
end
end
end
eProtect.queueNetworking = function(ply, specific)
if ply then
registerQuene(ply, specific)
else
for k,v in pairs(player.GetAll()) do
if !IsValid(v) then continue end
registerQuene(v, specific)
end
end
end
local screenshotRequested = {}
local idRequested = {}
local dataRequested = {}
local limitSC = {}
local function requestData(ply, target, type)
local data
if type == 1 then
local sid = target:SteamID()
if limitSC[sid] and CurTime() - limitSC[sid] < 10 then
slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "sc-timeout", math.Round(10 - (CurTime() - limitSC[sid])), target:Nick()), ply)
return end
limitSC[sid] = CurTime()
data = screenshotRequested
elseif type == 2 then
data = idRequested
elseif type == 3 then
data = dataRequested
end
if data[target] then return end
data[target] = ply
net.Start("eP:Handeler")
net.WriteUInt(3, 3)
net.WriteUInt(type, 2)
net.WriteBool(false)
net.Send(target)
timer.Simple(10, function()
if !target or !ply then return end
if data[target] then
data[target] = nil
slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "sc-failed", target:Nick()), ply)
end
end)
end
hook.Add("PlayerInitialSpawn", "eP:NetworkingQueuer", function(ply)
eProtect.queueNetworking(ply)
local sid = ply:SteamID()
if punished[sid] then punished[sid] = nil end
end)
local function verifyBannedAlt(ply, sid64, type)
sid64 = sid64 or ply:SteamID64()
local isBanned = slib.isBanned(sid64, function(banned, sid) if banned then if IsValid(ply) then slib.punish(ply, type, eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "punished-alt")) end end end)
if isBanned then
slib.punish(ply, type, eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "punished-alt"))
end
return isBanned
end
local settingConverter = { // Its reverted on clientside
[1] = 3,
[2] = 1,
[3] = 2
}
hook.Add("PlayerInitialSpawn", "eP:AutomaticChecks", function(ply)
local automatic_identifier = tonumber(eProtect.data.general["automatic-identifier"]) or 1
timer.Simple(1.5, function() -- Giving time to set usergroup.
if !IsValid(ply) or !ply:IsPlayer() or ply:IsBot() or eProtect.data.general["bypassgroup"][ply:GetUserGroup()] or eProtect.data.general["bypass_sids"][ply:SteamID64()] or eProtect.data.general["bypass_sids"][ply:SteamID()] then return end
if eProtect.data.general["block-vpn"] and !eProtect.data.general["bypass-vpn"][ply:GetUserGroup()] and !eProtect.data.general["bypass-vpn"][ply:SteamID64()] then
local ip = ""
for k,v in ipairs(string.ToTable(ply:IPAddress())) do
if v == ":" then break end
ip = ip..v
end
http.Fetch("https://proxycheck.io/v2/"..ip.."?vpn=1", function(result)
result = result and util.JSONToTable(result)
if result[ip] and result[ip].proxy == "yes" then
ply:Kick(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "vpn-blocked"))
end
end)
end
if automatic_identifier > 0 then
eProtect.correlateIP(ply, function(result)
local correlatedIPs = result
local plysid64, ownerplysid64 = ply:SteamID64(), ply:OwnerSteamID64()
local familyShare = ply:SteamID64() ~= ply:OwnerSteamID64()
local detections = !familyShare and !table.IsEmpty(correlatedIPs)
local altsDetected = {}
if detections then
local detect_type
detections = ""
if correlatedIPs and istable(correlatedIPs) and !table.IsEmpty(correlatedIPs) then
detect_type = "correlated-ip"
local foundAlts = {}
for k,v in ipairs(correlatedIPs) do
table.insert(altsDetected, v.sid64)
end
detections = slib.getLang("eprotect", eProtect.config["language"], "correlated-ip")
end
if familyShare then
detect_type = "family-share"
detections = detections == "" and slib.getLang("eprotect", eProtect.config["language"], "family-share") or detections.." "..slib.getLang("eprotect", eProtect.config["language"], "and").." "..slib.getLang("eprotect", eProtect.config["language"], "family-share")
table.insert(altsDetected, ownerplysid64)
end
if detections ~= "" then
local doneAction
if automatic_identifier == 1 then
for k, v in ipairs(player.GetAll()) do
if eProtect.data.general["notification-groups"][v:GetUserGroup()] then
slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "auto-detected-alt", ply:Nick(), detections), ply)
end
end
doneAction = true
elseif automatic_identifier == 2 then
for k,v in ipairs(altsDetected) do
doneAction = doneAction or verifyBannedAlt(ply, v, 1)
end
elseif automatic_identifier == 3 then
for k,v in ipairs(altsDetected) do
doneAction = doneAction or verifyBannedAlt(ply, v, 2)
end
end
if doneAction then
eProtect.logDetectionHandeler(ply, "alt-detection", slib.getLang("eprotect", eProtect.config["language"], detect_type), settingConverter[automatic_identifier])
end
end
end
end)
end
end)
end)
hook.Add("PlayerSay", "eP:OpenMenu", function(ply, text, public)
if eProtect.config["command"] == string.lower(text) then
if !eProtect.hasPermission(ply) then
return text
end
eProtect.networkData(ply)
openMenu(ply)
return ""
end
end )
hook.Add("eP:PreNetworking", "eP:Restrictions", function(ply, netstring, len)
if !eProtect.canNetwork(ply, netstring) then return false end
if len >= 512000 then eProtect.logDetectionHandeler(ply, "net-overflow", netstring, 1) eProtect.punish(ply, 1, slib.getLang("eprotect", eProtect.config["language"], "kick-net-overflow")) return false end
end)
hook.Add("eP:PreHTTP", "eP:PreventBlockedHTTP", function(url)
if eProtect.data.general["httpfocusedurls"] then
return eProtect.data.general["httpfocusedurlsisblacklist"] == !tobool(eProtect.data.general["httpfocusedurls"][url])
end
end)
timer.Create("eP:SaveCache", eProtect.config["process-save-queue"], 0, function()
if !eProtect.saveQueue then return end
eProtect.saveData()
eProtect.saveQueue = nil
end)
net.Receive("eP:Handeler", function(len, ply)
local gateway = net.ReadBit()
local action = net.ReadUInt(2)
if tobool(gateway) then
if !eProtect.hasPermission(ply) then return end
if action == 0 then
local id = net.ReadUInt(1)
local page = net.ReadUInt(15)
local search = net.ReadString()
if id == 0 then
eProtect.requestHTTPLog(ply, page, search)
elseif id == 1 then
eProtect.requestDetectionLog(ply, page, search)
end
elseif action == 1 then
local specific = net.ReadUInt(3)
local strings = {}
for i=1,specific do
strings[i] = net.ReadString()
end
local statement = net.ReadUInt(2)
local data
if statement == 1 then
data = net.ReadBool()
elseif statement == 2 then
data = net.ReadInt(32)
elseif statement == 3 then
local chunk = net.ReadUInt(32)
data = net.ReadData(chunk)
data = util.Decompress(data)
data = util.JSONToTable(data)
local converted_tbl = {}
for k, v in pairs(data) do
if string.sub(k, 1, 6) == "sid64_" then
local sid64 = string.sub(k, 7, #k)
if util.SteamIDFrom64(sid64) != "STEAM_0:0:0" then
k = sid64
end
end
converted_tbl[k] = v
end
data = converted_tbl
end
local finaldestination = eProtect.data
for k,v in ipairs(strings) do
finaldestination = finaldestination[v]
if k >= (#strings - 1) then break end
end
finaldestination[strings[#strings]] = data
eProtect.saveQueue = true
eProtect.queueNetworking(nil, strings[1])
elseif action == 2 then
local subaction = net.ReadUInt(3)
local target = net.ReadUInt(14)
target = Entity(target)
if !IsValid(target) or !target:IsPlayer() then slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "invalid-player"), ply) return end
local sid = target:SteamID()
if subaction == 1 then
eProtect.data.disabled[sid] = net.ReadBool()
eProtect.queueNetworking(nil, "disabled")
elseif subaction == 2 then
requestData(ply, target, net.ReadUInt(2))
elseif subaction == 3 then
local bit = net.ReadBit()
if tobool(bit) then
eProtect.correlateIP(target, function(result)
if !IsValid(target) or !IsValid(ply) then return end
if table.IsEmpty(result) then slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "no-correlation", target:Nick()), ply) return end
result = util.TableToJSON(result)
result = util.Base64Encode(result)
net.Start("eP:Handeler")
net.WriteUInt(4,3)
net.WriteUInt(target:EntIndex(), 14)
net.WriteString(result)
net.WriteBit(1)
net.Send(ply)
end)
else
eProtect.showIPs(target, ply)
end
elseif subaction == 4 then
local sid64 = target:SteamID64()
local ownersid64 = target:OwnerSteamID64()
if sid64 == ownersid64 then
slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "no-family-share", target:Nick()), ply)
else
slib.notify(eProtect.config["prefix"]..slib.getLang("eprotect", eProtect.config["language"], "has-family-share", target:Nick(), ownersid64), ply)
end
end
end
else
if action == 1 then
local subaction = net.ReadUInt(2)
local data
if subaction == 1 then
data = screenshotRequested
elseif subaction == 2 then
data = idRequested
elseif subaction == 3 then
data = dataRequested
end
if !data[ply] then if eProtect.config["punishMaliciousIntent"] then eProtect.punish(ply, 1, slib.getLang("eprotect", eProtect.config["language"], "kick-malicious-intent")) end return end
local target = data[ply]
data[ply] = nil
local id
if subaction == 3 then
local chunk = net.ReadUInt(32)
id = net.ReadData(chunk)
else
id = net.ReadString()
end
if !id or id == "" then
if eProtect.config["punishMaliciousIntent"] then
eProtect.punish(ply, 1, slib.getLang("eprotect", eProtect.config["language"], "kick-malicious-intent"))
end
return end
net.Start("eP:Handeler")
net.WriteUInt(3, 3)
net.WriteUInt(subaction, 2)
net.WriteUInt(ply:EntIndex(), 14)
net.WriteBool(true)
if subaction == 3 then
local chunk = #id
net.WriteUInt(chunk, 32)
net.WriteData(id, chunk)
else
net.WriteString(id)
end
net.Send(target)
elseif action == 2 then
local menu = net.ReadUInt(2)
local menus = {
[1] = "Loki",
[2] = "Exploit City"
}
eProtect.logDetectionHandeler(ply, "exploit-menu", menus[menu], 2)
eProtect.punish(ply, 2, slib.getLang("eprotect", eProtect.config["language"], "banned-exploit-menu"))
end
end
end)
hook.Add("eP:SQLConnected", "eP:TransferOldIPs", function()
local files = file.Find("eprotect/ips/*", "DATA")
for k,v in pairs(files) do
local sid64 = string.gsub(v, ".json", "")
local ips = file.Read("eprotect/ips/"..v, "DATA")
ips = util.JSONToTable(ips)
if !ips then continue end
for ip, data in pairs(ips) do
eProtect.registerIP(sid64, ip, data[1], data[2])
end
file.Delete("eprotect/ips/"..v)
end
file.Delete("eprotect/ips")
local save = false
if eProtect.data.httpLogging then
for url, v in pairs(eProtect.data.httpLogging) do
eProtect.logHTTP(url, v.type, v.called)
end
eProtect.data.httpLogging = nil
save = true
end
if eProtect.data.punishmentLogging then
for i = #eProtect.data.punishmentLogging, 1, -1 do
local data = eProtect.data.punishmentLogging[i]
eProtect.logDetection(data.ply, "", data.reason, data.info, data.type)
end
eProtect.data.punishmentLogging = nil
save = true
end
if save then
eProtect.saveData()
end
end)
eProtect.dataVerification()