Skip to content

Instantly share code, notes, and snippets.

@maikka39
Created November 20, 2022 11:43
Show Gist options
  • Save maikka39/8019e2f1a45e1021fff05bd1e1688e14 to your computer and use it in GitHub Desktop.
Save maikka39/8019e2f1a45e1021fff05bd1e1688e14 to your computer and use it in GitHub Desktop.
Minecraft Server Scanner
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import masscan\n",
"import json\n",
"import os\n",
"from mcstatus import JavaServer\n",
"from queue import Queue, Empty\n",
"from threading import Thread\n",
"import base64\n",
"from time import sleep\n",
"from contextlib import suppress\n",
"from os import remove"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"ip_ranges = [\n",
" \"116.202.0.0/16\",\n",
" \"116.203.0.0/16\",\n",
" \"128.140.0.0/17\",\n",
" \"135.181.0.0/16\",\n",
" \"136.243.0.0/16\",\n",
" \"138.201.0.0/16\",\n",
" \"142.132.128.0/17\",\n",
" \"144.76.0.0/16\",\n",
" \"148.251.0.0/16\",\n",
" \"157.90.0.0/16\",\n",
" \"159.69.0.0/16\",\n",
" \"162.55.0.0/16\",\n",
" \"167.233.0.0/16\",\n",
" \"167.235.0.0/16\",\n",
" \"168.119.0.0/16\",\n",
" \"171.25.225.0/24\",\n",
" \"176.9.0.0/16\",\n",
" \"178.212.75.0/24\",\n",
" \"178.63.0.0/16\",\n",
" \"185.107.52.0/22\",\n",
" \"185.110.95.0/24\",\n",
" \"185.112.180.0/24\",\n",
" \"185.126.28.0/22\",\n",
" \"185.12.65.0/24\",\n",
" \"185.136.140.0/23\",\n",
" \"185.157.176.0/23\",\n",
" \"185.157.178.0/23\",\n",
" \"185.157.83.0/24\",\n",
" \"185.171.224.0/22\",\n",
" \"185.189.228.0/24\",\n",
" \"185.189.229.0/24\",\n",
" \"185.189.230.0/24\",\n",
" \"185.189.231.0/24\",\n",
" \"185.209.124.0/22\",\n",
" \"185.213.45.0/24\",\n",
" \"185.216.237.0/24\",\n",
" \"185.226.99.0/24\",\n",
" \"185.228.8.0/23\",\n",
" \"185.242.76.0/24\",\n",
" \"185.36.144.0/22\",\n",
" \"185.50.120.0/23\",\n",
" \"188.34.128.0/17\",\n",
" \"188.40.0.0/16\",\n",
" \"193.110.6.0/23\",\n",
" \"193.163.198.0/24\",\n",
" \"193.25.170.0/23\",\n",
" \"194.35.12.0/23\",\n",
" \"194.42.180.0/22\",\n",
" \"194.42.184.0/22\",\n",
" \"194.62.106.0/24\",\n",
" \"195.201.0.0/16\",\n",
" \"195.248.224.0/24\",\n",
" \"195.60.226.0/24\",\n",
" \"195.96.156.0/24\",\n",
" \"197.242.84.0/22\",\n",
" \"201.131.3.0/24\",\n",
" \"213.133.96.0/19\",\n",
" \"213.232.193.0/24\",\n",
" \"213.239.192.0/18\",\n",
" \"23.88.0.0/17\",\n",
" \"45.136.70.0/23\",\n",
" \"45.148.28.0/22\",\n",
" \"45.15.120.0/22\",\n",
" \"46.4.0.0/16\",\n",
" \"49.12.0.0/16\",\n",
" \"49.13.0.0/16\",\n",
" \"5.75.128.0/17\",\n",
" \"5.9.0.0/16\",\n",
" \"65.108.0.0/16\",\n",
" \"65.109.0.0/16\",\n",
" \"65.21.0.0/16\",\n",
" \"78.46.0.0/15\",\n",
" \"85.10.192.0/18\",\n",
" \"88.198.0.0/16\",\n",
" \"88.99.0.0/16\",\n",
" \"91.107.128.0/17\",\n",
" \"91.190.240.0/21\",\n",
" \"91.233.8.0/22\",\n",
" \"94.130.0.0/16\",\n",
" \"94.154.121.0/24\",\n",
" \"95.216.0.0/16\",\n",
" \"95.217.0.0/16\",\n",
"]"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"thread_count = 100\n",
"# selected_range = \"176.9.0.0/16\"\n",
"selected_range = None"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"mas = masscan.PortScanner()\n",
"\n",
"ip_ranges_to_scan = [selected_range] if selected_range else ip_ranges\n",
"\n",
"for i, ip_range in enumerate(ip_ranges_to_scan):\n",
" print(f\"Starting on range: {ip_range} [{i+1}/{len(ip_ranges_to_scan)}]\")\n",
" mas.scan(ip_range, ports=\"25565\", arguments=\"--max-rate 8000\")\n",
" with open(\"hosts.json\", \"r+\") as file:\n",
" hosts_json = json.load(file)\n",
" previous_hosts = hosts_json.get(ip_range, [])\n",
" hosts_json[ip_range] = list(set(previous_hosts) | set(mas.all_hosts))\n",
" file.seek(0)\n",
" json.dump(hosts_json, file)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open(\"hosts.json\", \"r\") as file:\n",
" hosts_json = json.load(file)\n",
"\n",
"if selected_range:\n",
" hosts = hosts_json.get(selected_range, [])\n",
"else:\n",
" hosts = [host for ip_range in hosts_json.values() for host in ip_range]\n",
"\n",
"hosts = list(set(hosts))\n",
"hosts[:5], len(hosts)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open(\"masscans/output-25565-hetzner-full.json\", \"r\") as file:\n",
" json_data = json.load(file)\n",
"\n",
"hosts = [entry['ip'] for entry in json_data]\n",
"\n",
"hosts = list(set(hosts))\n",
"hosts[:5], len(hosts)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open(\"valid_hosts.json\", \"r\") as file:\n",
" valid_hosts = json.load(file)\n",
"\n",
"def handle_ip(ip):\n",
" try:\n",
" server = JavaServer.lookup(ip)\n",
" status = server.status()\n",
"\n",
" server_info = {\n",
" \"version\": status.version.name,\n",
" \"motd\": status.description,\n",
" \"favicon\": status.favicon is not None,\n",
" \"player_count\": status.players.online,\n",
" \"players\": [player.name for player in status.players.sample or []],\n",
" }\n",
"\n",
" valid_hosts[ip] = server_info\n",
"\n",
" if status.favicon:\n",
" with open(f\"servers/{ip}.png\", 'wb') as file:\n",
" file.write(base64.b64decode(status.favicon[len(\"data:image/png;base64,\"):]))\n",
" except Exception as e:\n",
" print(f\"Failed for IP: {ip} ({type(e)})\")\n",
"\n",
"\n",
"def do_stuff(queue):\n",
" with suppress(Empty):\n",
" while True:\n",
" handle_ip(queue.get(block=False))\n",
" queue.task_done()\n",
"\n",
"\n",
"def print_progress(queue):\n",
" initial_size = queue.qsize()\n",
" def p(current_size):\n",
" print(f\"Progress: {(((initial_size-current_size)/initial_size)*100):.2f}% [{initial_size-current_size}/{initial_size}]\")\n",
"\n",
" while (current_size := queue.qsize()) > 0:\n",
" p(current_size)\n",
" sleep(1)\n",
" p(current_size)\n",
"\n",
"\n",
"queue = Queue(maxsize=0)\n",
"for host in hosts:\n",
" queue.put(host)\n",
"\n",
"threads = []\n",
"\n",
"progress_printer = Thread(target=print_progress, args=(queue,))\n",
"progress_printer.daemon = True\n",
"progress_printer.start()\n",
"threads.append(progress_printer)\n",
"\n",
"for _ in range(thread_count):\n",
" worker = Thread(target=do_stuff, args=(queue,))\n",
" worker.daemon = True\n",
" worker.start()\n",
" threads.append(worker)\n",
"\n",
"queue.join()\n",
"for thread in threads:\n",
" thread.join()\n",
"\n",
"with open(\"valid_hosts.json\", \"w\") as file:\n",
" json.dump(valid_hosts, file)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"with open(\"valid_hosts.json\", \"r\") as file:\n",
" valid_hosts_data = json.load(file)\n",
"\n",
"\n",
"# list({data.get(\"version\") for ip, data in valid_hosts_data.items()})\n",
"current_servers = [filename[:-4] for filename in os.listdir(\"possible_hits\")]\n",
"\n",
"def is_1_19(ip) -> bool:\n",
" return \"1.19\" in valid_hosts_data.get(ip).get(\"version\")\n",
"\n",
"\n",
"valid_servers = list(filter(is_1_19, current_servers))\n",
"\n",
"for filename in os.listdir(\"possible_hits\"):\n",
" if filename[:-4] not in valid_servers:\n",
" remove(f\"possible_hits/{filename}\")\n",
"\n",
"print(len(current_servers))\n",
"print(len(valid_servers))\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.10.7 64-bit",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.8"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "e7370f93d1d0cde622a1f8e1c04877d8463912d04d973331ad4851f04de6915a"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment