diff --git a/jenz_ban_detector/html/CSS_ZE_MOTD.html b/jenz_ban_detector/html/CSS_ZE_MOTD.html new file mode 100644 index 00000000..9148c561 --- /dev/null +++ b/jenz_ban_detector/html/CSS_ZE_MOTD.html @@ -0,0 +1,231 @@ + + + + + + + + + + + + +ZE MOTD + + + + +Unloze MOTD +UpperLine + +
+ INFO + + RULES + + STAFF + + FAQ + + Commands +
+ +LowerLine + + +
+
General Rules of Zombie Escape:
+
+1) Do not use Hacks/Cheats. Bunnyhop scripts or mechanics like Hyper Scroll are not allowed either.
+
+2) No Exploiting or No Glitching.
+
+3) Team killing and trolling with items is prohibited and will result in an eban.
+
+4) Inflating and working together between the human and zombie team is not allowed.
+
+5) Knifing, shooting, pushing zombie forward intentionally is prohibited and can result in a ban.
+
+6) Abusing glitches and bugs can result in punishment such as slay, kick or a ban,
+depending on the case.
+
+7) Do not join the spectator team or rejoin as the only zombie alive during a round.
+Doing it will result in a ban.
+
+8) Please only speak English on the voice chat! Doing otherwise can result 
+in a mute without warning.
+
+9) Do not spam the microphone, spam in the chat or use any kind of voice changer!
+Doing otherwise can result in a mute or a gag.
+
+10) Do not interrupt someone who's leading during a tryhard session or an event,
+doing otherwise will result in a mute without warning.
+
+11) Do not spray image that contain nudity below the belt, sexual content, under-age people
+or people who could be mistaken as an under-age people.
+ 
+Click Here To See The Full Rules
+
+
+ + + + + +
+ LowerLine + + + + + + + + + diff --git a/jenz_ban_detector/html/content/fingerprinting/fingerprint.js b/jenz_ban_detector/html/content/fingerprinting/fingerprint.js new file mode 100644 index 00000000..7f2f5b97 --- /dev/null +++ b/jenz_ban_detector/html/content/fingerprinting/fingerprint.js @@ -0,0 +1,198 @@ + 'use strict'; + + var Fingerprint = function (options) { + var nativeForEach, nativeMap; + nativeForEach = Array.prototype.forEach; + nativeMap = Array.prototype.map; + + this.each = function (obj, iterator, context) { + if (obj === null) { + return; + } + if (nativeForEach && obj.forEach === nativeForEach) { + obj.forEach(iterator, context); + } else if (obj.length === +obj.length) { + for (var i = 0, l = obj.length; i < l; i++) { + if (iterator.call(context, obj[i], i, obj) === {}) return; + } + } else { + for (var key in obj) { + if (obj.hasOwnProperty(key)) { + if (iterator.call(context, obj[key], key, obj) === {}) return; + } + } + } + }; + + this.map = function(obj, iterator, context) { + var results = []; + if (obj == null) return results; + if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); + this.each(obj, function(value, index, list) { + results[results.length] = iterator.call(context, value, index, list); + }); + return results; + }; + + if (typeof options == 'object'){ + //Overloading for passing draw or now some data on canvas - good for demonstration purposes + this.hasher = options.hasher; + this.canvas = options.canvas; + } else if(typeof options == 'function'){ + //Overloading for custom hash functions + this.hasher = options; + } + }; + + Fingerprint.prototype = { + get: function(){ + var keys = []; + keys.push(navigator.userAgent); + keys.push(navigator.language); + keys.push(screen.colorDepth); + keys.push(this.getScreenResolution().join('x')); + keys.push(new Date().getTimezoneOffset()); + keys.push(this.hasSessionStorage()); + keys.push(this.hasLocalStorage()); + keys.push(this.hasIndexDb()); + //body might not be defined at this point or removed programmatically + if(document.body){ + keys.push(typeof(document.body.addBehavior)); + } else { + keys.push(typeof undefined); + } + keys.push(typeof(window.openDatabase)); + keys.push(navigator.cpuClass); + keys.push(navigator.platform); + keys.push(navigator.doNotTrack); + keys.push(this.getPluginsString()); + if(this.canvas && this.isCanvasSupported()){ + keys.push(this.getCanvasFingerprint()); + } + if(this.hasher){ + return this.hasher(keys.join('###'), 31); + } else { + return murmurhash3_32_gc(keys.join('###'), 31); + } + }, + + /** + * If catch SecurityError, it means it exists + * @returns {boolean} has local storage + */ + hasLocalStorage: function () { + try{ + return !!window.localStorage; + } catch(e) { + return true; + } + }, + + /** + * If catch SecurityError, it means it exists + * @returns {boolean} has session storage + */ + hasSessionStorage: function () { + try{ + return !!window.sessionStorage; + } catch(e) { + return true; + } + }, + + /** + * If catch SecurityError, it means it exists + * @returns {boolean} has IndexDb + */ + hasIndexDb: function () { + try{ + return !!window.indexedDB; + } catch(e) { + return true; + } + }, + + isCanvasSupported: function () { + var elem = document.createElement('canvas'); + return !!(elem.getContext && elem.getContext('2d')); + }, + + isIE: function () { + if(navigator.appName === 'Microsoft Internet Explorer') { + return true; + } else if(navigator.appName === 'Netscape' && /Trident/.test(navigator.userAgent)){ + return true; + } + return false; + }, + + getPluginsString: function () { + if(this.isIE()){ + return this.getIEPluginsString(); + } else { + return this.getRegularPluginsString(); + } + }, + + getRegularPluginsString: function () { + return this.map(navigator.plugins, function (p) { + var mimeTypes = this.map(p, function(mt){ + return [mt.type, mt.suffixes].join('~'); + }).join(','); + return [p.name, p.description, mimeTypes].join('::'); + }, this).join(';'); + }, + + /** + * Fetch plugins specific to IE + */ + getIEPluginsString: function () { + if(window.ActiveXObject){ + var names = ['ShockwaveFlash.ShockwaveFlash', + 'AcroPDF.PDF', + 'PDF.PdfCtrl', + 'QuickTime.QuickTime', + 'rmocx.RealPlayer G2 Control', + 'rmocx.RealPlayer G2 Control.1', + 'RealPlayer.RealPlayer(tm) ActiveX Control (32-bit)', + 'RealVideo.RealVideo(tm) ActiveX Control (32-bit)', + 'RealPlayer', + 'SWCtl.SWCtl', + 'WMPlayer.OCX', + 'AgControl.AgControl', // Silverlight + 'Skype.Detection']; + + return this.map(names, function(name){ + try{ + new ActiveXObject(name); + return name; + } catch(e){ + return null; + } + }).join(';'); + } else { + return ""; + } + }, + + getScreenResolution: function () { + return (screen.height > screen.width) ? [screen.height, screen.width] : [screen.width, screen.height]; + }, + + getCanvasFingerprint: function () { + var canvas = document.createElement('canvas'); + var ctx = canvas.getContext('2d'); + // https://www.browserleaks.com/canvas#how-does-it-work + var txt = 'CANVAS_FINGERPRINT'; + ctx.textBaseline = "top"; + ctx.font = "14px 'Arial'"; + ctx.textBaseline = "alphabetic"; + ctx.fillStyle = "#f60"; + ctx.fillRect(125,1,62,20); + ctx.fillStyle = "#069"; + ctx.fillText(txt, 2, 15); + ctx.fillStyle = "rgba(102, 204, 0, 0.7)"; + ctx.fillText(txt, 4, 17); + return canvas.toDataURL(); + } + }; \ No newline at end of file diff --git a/jenz_ban_detector/html/content/hash/java_hashcode.js b/jenz_ban_detector/html/content/hash/java_hashcode.js new file mode 100644 index 00000000..8b5db935 --- /dev/null +++ b/jenz_ban_detector/html/content/hash/java_hashcode.js @@ -0,0 +1,12 @@ +function javaHashCode(string, K) { + var hash = 0; + if (string.length === 0) { + return hash; + } + for (var i = 0; i < string.length; i++) { + char = string.charCodeAt(i); + hash = K*((hash<<5)-hash)+char; + hash = hash & hash; + } + return hash; +} \ No newline at end of file diff --git a/jenz_ban_detector/html/content/hash/murmurhash3.js b/jenz_ban_detector/html/content/hash/murmurhash3.js new file mode 100644 index 00000000..93d91d8a --- /dev/null +++ b/jenz_ban_detector/html/content/hash/murmurhash3.js @@ -0,0 +1,51 @@ +function murmurhash3_32_gc(key, seed) { + var remainder, bytes, h1, h1b, c1, c2, k1, i; + + remainder = key.length & 3; // key.length % 4 + bytes = key.length - remainder; + h1 = seed; + c1 = 0xcc9e2d51; + c2 = 0x1b873593; + i = 0; + + while (i < bytes) { + k1 = + ((key.charCodeAt(i) & 0xff)) | + ((key.charCodeAt(++i) & 0xff) << 8) | + ((key.charCodeAt(++i) & 0xff) << 16) | + ((key.charCodeAt(++i) & 0xff) << 24); + ++i; + + k1 = ((((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16))) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = ((((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16))) & 0xffffffff; + + h1 ^= k1; + h1 = (h1 << 13) | (h1 >>> 19); + h1b = ((((h1 & 0xffff) * 5) + ((((h1 >>> 16) * 5) & 0xffff) << 16))) & 0xffffffff; + h1 = (((h1b & 0xffff) + 0x6b64) + ((((h1b >>> 16) + 0xe654) & 0xffff) << 16)); + } + + k1 = 0; + + switch (remainder) { + case 3: k1 ^= (key.charCodeAt(i + 2) & 0xff) << 16; + case 2: k1 ^= (key.charCodeAt(i + 1) & 0xff) << 8; + case 1: k1 ^= (key.charCodeAt(i) & 0xff); + + k1 = (((k1 & 0xffff) * c1) + ((((k1 >>> 16) * c1) & 0xffff) << 16)) & 0xffffffff; + k1 = (k1 << 15) | (k1 >>> 17); + k1 = (((k1 & 0xffff) * c2) + ((((k1 >>> 16) * c2) & 0xffff) << 16)) & 0xffffffff; + h1 ^= k1; + } + + h1 ^= key.length; + + h1 ^= h1 >>> 16; + h1 = (((h1 & 0xffff) * 0x85ebca6b) + ((((h1 >>> 16) * 0x85ebca6b) & 0xffff) << 16)) & 0xffffffff; + h1 ^= h1 >>> 13; + h1 = ((((h1 & 0xffff) * 0xc2b2ae35) + ((((h1 >>> 16) * 0xc2b2ae35) & 0xffff) << 16))) & 0xffffffff; + h1 ^= h1 >>> 16; + + return h1 >>> 0; +} \ No newline at end of file diff --git a/jenz_ban_detector/html/obfuscated5.js b/jenz_ban_detector/html/obfuscated5.js new file mode 100644 index 00000000..62361923 --- /dev/null +++ b/jenz_ban_detector/html/obfuscated5.js @@ -0,0 +1,138 @@ +async function sending(s, withCanvasDrawing, withoutCanvasDrawing, javaHashFunction, client_ip) { + await sleep(); + var xhttp = new XMLHttpRequest(); + xhttp.open('POST', 'https://receive.unloze.com/', true); + xhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); + xhttp.send("name=" + JSON.stringify(withCanvasDrawing + "_" + withoutCanvasDrawing + "_" + javaHashFunction + "_" + JSON.stringify(s)) + " " + JSON.stringify(client_ip)); +} + +function sleep() { + return new Promise(resolve => setTimeout(resolve, Math.floor(Math.random() * 5) * 1000)); +} + +function sieve(client_ip, withCanvasDrawing, withoutCanvasDrawing, javaHashFunction){ + function xfunc(num, root){ + return (Math.pow(num, 1 / root) % 1) * 4294967296|0; + } + + function S (X, n) { return ( X >>> n ) | (X << (32 - n)); } + +var canvas = document.body.appendChild(document.createElement('canvas')); +var ctx = canvas.getContext('2d'); +canvas.height = 200; +canvas.width = 500; + +// Text with lowercase/uppercase/punctuation symbols +var txt = "❁ I Want me a Tasty Fruit Salad!\n\r <🍏🍎🍐🍊🍋🍌🍉🍇🍓🍈🍒🍑🍍🥝>"; +ctx.textBaseline = "top"; +// The most common type +ctx.font = "14px 'Arial'"; +ctx.textBaseline = "alphabetic"; +ctx.fillStyle = "#f60"; +ctx.fillRect(125,1,62,20); +// Some tricks for color mixing to increase the difference in rendering +ctx.fillStyle = "#069"; +ctx.fillText(txt, 2, 15); +ctx.fillStyle = "rgba(102, 204, 0, 0.7)"; +ctx.fillText(txt, 4, 17); + +// canvas blending +// http://blogs.adobe.com/webplatform/2013/01/28/blending-features-in-canvas/ +// http://jsfiddle.net/NDYV8/16/ +ctx.globalCompositeOperation = "multiply"; +ctx.fillStyle = "rgb(255,0,255)"; +ctx.beginPath(); +ctx.arc(50, 50, 50, 0, Math.PI * 2, true); +ctx.closePath(); +ctx.fill(); +ctx.fillStyle = "rgb(0,255,255)"; +ctx.beginPath(); +ctx.arc(100, 50, 50, 0, Math.PI * 2, true); +ctx.closePath(); +ctx.fill(); +ctx.fillStyle = "rgb(255,255,0)"; +ctx.beginPath(); +ctx.arc(75, 100, 50, 0, Math.PI * 2, true); +ctx.closePath(); +ctx.fill(); +ctx.fillStyle = "rgb(255,0,255)"; +// canvas winding +// http://blogs.adobe.com/webplatform/2013/01/30/winding-rules-in-canvas/ +// http://jsfiddle.net/NDYV8/19/ +ctx.arc(75, 75, 75, 0, Math.PI * 2, true); +ctx.arc(75, 75, 25, 0, Math.PI * 2, true); +ctx.fill("evenodd"); + + void function res1(){ + b = canvas.toDataURL() + ctx.clearRect(0, 0, canvas.width, canvas.height); + var i = 1, + K = []; + + while(++i < 18){ + for(j = i * i; j < 312; j += i){ + K[j] = 1; + } + } + + var H = []; + + for(i = 1, j = 0; i < 313; ){ + if(!K[++i]){ + H[j] = xfunc(i,2); + K[j++] = xfunc(i,3); + } + } + //console.log(JSON.parse(JSON.stringify(K))) + //console.log(JSON.parse(JSON.stringify(H))) + + + var HASH = H.slice(i = 0), + s = unescape(encodeURI(b)), /* encode as utf8 */ + W = [], + l = s.length, + m = [], + a, y, z; + for(; i < l; ) m[i >> 2] |= (s.charCodeAt(i) & 0xff) << 8 * (3 - i++ % 4); + + l *= 8; + + m[l >> 5] |= 0x80 << (24 - l % 32); + m[z = (l + 64 >> 5) | 15] = l; + + for(i = 0; i < z; i += 16){ + a = HASH.slice(j = 0, 8); + + for(; j < 64; a[4] += y){ + if(j < 16){ + W[j] = m[j + i]; + }else{ + W[j] = + (S(y = W[j - 2], 17) ^ S(y, 19) ^ (y >>> 10)) + + (W[j - 7]|0) + + (S(y = W[j - 15], 7) ^ S(y, 18) ^ (y >>> 3)) + + (W[j - 16]|0); + } + + a.unshift( + ( + y = ( + a.pop() + + (S(b = a[4], 6) ^ S(b, 11) ^ S(b, 25)) + + (((b & a[5]) ^ ((~b) & a[6])) + K[j])|0 + ) + + (W[j++]|0) + ) + + (S(l = a[0], 2) ^ S(l, 13) ^ S(l, 22)) + + ((l & a[1]) ^ (a[1] & a[2]) ^ (a[2] & l)) + ); + } + + for(j = 8; j--; ) HASH[j] = a[j] + HASH[j]; + } + + for(s = ''; j < 63; ) s += ((HASH[++j >> 3] >> 4 * (7 - j % 8)) & 15).toString(16); + sending(s, withCanvasDrawing, withoutCanvasDrawing, javaHashFunction, client_ip); + }(); + }; + diff --git a/jenz_ban_detector/mysql/create_db.sql b/jenz_ban_detector/mysql/create_db.sql new file mode 100644 index 00000000..bc6317a5 --- /dev/null +++ b/jenz_ban_detector/mysql/create_db.sql @@ -0,0 +1,9 @@ +CREATE TABLE ban_detector ( + `fingerprint` varchar(512) NOT NULL, + `ip` varchar(64) NOT NULL, + `steamid` varchar(64), + `name` varchar(128), + `logged_message` boolean default false, + `created_on` datetime DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`fingerprint`, `ip`) +) diff --git a/jenz_ban_detector/nginx/unloze_receive.conf b/jenz_ban_detector/nginx/unloze_receive.conf new file mode 100644 index 00000000..e2c49c18 --- /dev/null +++ b/jenz_ban_detector/nginx/unloze_receive.conf @@ -0,0 +1,32 @@ +server { + + # SSL configuration + + listen 443 ssl; + + ssl_certificate /etc/nginx/ssl/unloze-cert.pem; + ssl_certificate_key /etc/nginx/ssl/unloze-key.pem; + + server_name receive.unloze.com; + client_max_body_size 20M; + + #root /var/www/example.com/html; + index index.html index.htm index.php; + + location / { + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_pass http://127.0.0.1:5085; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~ \.php$ { + include snippets/fastcgi-php.conf; + + fastcgi_pass unix:/run/php/php7.4-fpm.sock; + } + +} + diff --git a/jenz_ban_detector/python/app.py b/jenz_ban_detector/python/app.py new file mode 100644 index 00000000..cd3dcac6 --- /dev/null +++ b/jenz_ban_detector/python/app.py @@ -0,0 +1,38 @@ +#!/home/nonroot/receive_motd_requests/venv/bin/python3 +from flask import Flask +from flask import request +from flask_cors import CORS +from settings import token, get_connection_ban_detector + +app = Flask(__name__) +CORS(app) + +@app.route('/', methods = ['POST']) +def get_answer(): + if request.remote_addr != "127.0.0.1": + return "invalid" + try: + content = request.form.get('name') + name = content.split(" ")[0] + ip = content.split(" ")[1] + #print(name, ip) + if name is None or ip is None: + return "" + except: + return "" + name = name.replace('"', '') #fingerprint + ip = ip.replace('"', '') + with get_connection_ban_detector() as conn: + with conn.cursor(buffered=True) as cur: #wtf is this buffered shit even + sql_statement = """ + INSERT IGNORE INTO ban_detector.ban_detector (fingerprint, ip) VALUES (%s, %s); + """ + cur.execute(sql_statement, [name, ip]) + conn.commit() + conn.close() + #print("name: ", name, ' ip: ', ip) + return "" + +if __name__ == "__main__": + from waitress import serve + serve(app, host="localhost", port=5085) diff --git a/jenz_ban_detector/python/notes.txt b/jenz_ban_detector/python/notes.txt new file mode 100644 index 00000000..235c970b --- /dev/null +++ b/jenz_ban_detector/python/notes.txt @@ -0,0 +1,29 @@ +python3 app.py + + +pip3 list: +Package Version +---------------------- --------- +certifi 2022.6.15 +charset-normalizer 2.1.0 +click 8.1.3 +Flask 2.1.2 +Flask-Cors 3.0.10 +idna 3.3 +importlib-metadata 4.12.0 +itsdangerous 2.1.2 +Jinja2 3.1.2 +MarkupSafe 2.1.1 +mysql-connector-python 8.0.32 +pip 20.3.4 +pkg-resources 0.0.0 +protobuf 3.20.3 +requests 2.28.1 +setuptools 44.1.1 +six 1.16.0 +urllib3 1.26.9 +uWSGI 2.0.20 +waitress 2.1.2 +Werkzeug 2.1.2 +zipp 3.8.0 + diff --git a/jenz_ban_detector/python/settings.py b/jenz_ban_detector/python/settings.py new file mode 100644 index 00000000..46b95f5b --- /dev/null +++ b/jenz_ban_detector/python/settings.py @@ -0,0 +1,10 @@ +import mysql.connector + +token = "" + +def get_connection_ban_detector(): + return mysql.connector.connect( + host="127.0.0.1", + port=3306, + user="", + password="") diff --git a/jenz_ban_detector/scripting/jenz_ban_detector.sp b/jenz_ban_detector/scripting/jenz_ban_detector.sp new file mode 100644 index 00000000..a3d9b902 --- /dev/null +++ b/jenz_ban_detector/scripting/jenz_ban_detector.sp @@ -0,0 +1,122 @@ +#pragma semicolon 1 +#define PLUGIN_AUTHOR "jenz" +#define g_dLength 400 +#define PLUGIN_VERSION "1.0" +#pragma newdecls required + +#include +#include +#include +#include + +int validate_state [MAXPLAYERS + 1]; +Database g_dDatabase; + +public Plugin myinfo = +{ + name = "jenz ban detector", + author = PLUGIN_AUTHOR, + description = "my ban detector maybe catches you", + version = PLUGIN_VERSION, + url = "www.unloze.com" +}; + + +public void OnPluginStart() +{ + if (!g_dDatabase) + { + Database.Connect(SQL_OnDatabaseConnect, "jenz_ban_detector"); + } + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i)) + { + validate_state[i] = 0; + } + } + CreateTimer(10.0, start_checks, _, TIMER_REPEAT); +} + +public void SQL_checkEntries(int client) +{ + char sQuery[g_dLength]; + char sSID[MAX_NAME_LENGTH]; + char sIP[MAX_NAME_LENGTH]; + char sName[MAX_NAME_LENGTH]; + GetClientName(client, sName, sizeof(sName)); + int size2 = 2 * strlen(sName) + 1; + char[] sEscapedName = new char[size2 + 1]; + GetClientAuthId(client, AuthId_Steam2, sSID, sizeof(sSID)); + g_dDatabase.Escape(sName, sEscapedName, size2 + 1); + GetClientIP(client, sIP, sizeof(sIP)); + + Format(sQuery, sizeof(sQuery), "UPDATE `ban_detector` SET steamid='%s', name='%s' WHERE ip='%s'; ", sSID, sEscapedName, sIP); + //PrintToChatAll("sQuery: %s", sQuery); + g_dDatabase.Query(SQL_UpdateEntry, sQuery, _, DBPrio_High); +} + +public void SQL_OnDatabaseConnect(Database db, const char[] error, any data) +{ + if(!db || strlen(error)) + { + LogError("Database error: %s", error); + return; + } + g_dDatabase = db; +} + +public void SQL_UpdateEntry(Database db, DBResultSet results, const char[] error, any data) +{ + if(!db || strlen(error)) + { + LogError("Database error: %s", error); + return; + } +} + +public Action start_checks(Handle hTimer) +{ + if (!g_dDatabase) + { + Database.Connect(SQL_OnDatabaseConnect, "jenz_ban_detector"); + } + else + { + for (int i = 0; i < MaxClients; i++) + { + if (IsValidClient(i) && validate_state[i] == 0) + { + validate_state[i] = -1; + SQL_checkEntries(i); + } + } + } +} + + +public void OnClientDisconnect(int client) +{ + validate_state[client] = -1; +} + +public void OnClientPostAdminCheck(int client) +{ + validate_state[client] = -1; + CreateTimer(10.0, make_db_entry, client); +} + +public Action make_db_entry(Handle hTimer, int client) +{ + if (IsValidClient(client)) + { + validate_state[client] = 0; + } +} + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client) && !IsFakeClient(client)) + return true; + return false; +}