# Работа с сетью import socket from requests import get # Очевидно import os from random import randint # Работа с архивами from shutil import unpack_archive, copytree, rmtree # Убираем ненужное (../some => some) from re import compile, sub # Работа с БД и json from db import read from json import loads # Логирование ошибок import logging from verify import * from domain_check import * # Здесь идёт обработка всех запросов через сеть # TODO: # 1. [+] Пинг # 2. [+] Проверка существования сайта # 3. [+] Передача сайта # 4. [+] Приём рассылки сайтов # 5. [ ] Проверка всех сайтов def port_gen(st = 25000, end = 25200): port = randint(st, end) if client(port) == None: return port while client(port) != None: port = randint(st, end) return port def server_http(): run = True while run == True: try: os.system("python -m http.server --directory cached") except KeyboardInterrupt: run = False except Exception as e: print("SERVER_HTTP FALLED") logging.critical(e, exc_info=True) def server(http_port): while True: try: host = "127.0.0.1" port = 8001 s = socket.socket() s.bind((host, port)) while True: s.listen(2) conn, address = s.accept() print("Connection from: " + str(address)) while True: try: op = conn.recv(1024).decode() except: pass if not op: break if op == "ping": conn.send("pong".encode()) elif op[:3] == "is_": check = op[3:] # Защита от доступа выше и т.п. check = domain_ok(check) if os.path.exists(f'cached/{check}'): conn.send(str(http_port).encode()) else: conn.send("not_exist".encode()) elif op[:8] == "publish_": data = op[8:] site, u_port = data.split("<>") if domain_ok(site): conn.send("accepted".encode()) client(u_port, f"get_{site}") elif op == "check_all": try: sites = next(os.walk('cached/'), (None, None, []))[1] sites_comp = "" for i in sites: # Проверяем версию ver = read(f"cached/{i}/config.json")["ver"] sites_comp += i + f"_{ver}<>" sites_comp = sites_comp[:-2] if sites_comp == "": conn.send("None".encode()) else: conn.send(sites_comp.encode()) except: conn.send("None".encode()) conn.close() except Exception as e: print("SERVER_HTTP FALLED") logging.critical(e, exc_info=True) from time import time from threading import Thread from queue import Queue def recv(s, data_out): okay = False while not okay: try: data = s.recv(1024).decode() okay = True except: pass print(data) data_out.put(data) # op = operation def client(port, op = "ping", host = 'bore.pub'): # Если порт не определён if not port: return None if op == "ping" or op[:3] == "is_" or op[:8] == "publish_" or op == "check_all": s = socket.socket() try: s.connect((host, port)) except: return None s.send(op.encode()) data = Queue() ping = Thread(target = recv, args=(s, data,)) # Стартуем пинг ping.start() # Ждём 8 секунд ping.join(6) # Закрываем соединение s.close() if not data.empty(): return data.get() else: return None elif op[:4] == "get_": site = op[4:] # Проверяем версию если сайт кеширован if os.path.exists(f"cached/{site}"): # Версия запрашиваемого dest_conf = get(f"http://{host}:{str(port)}/{site}/config.json") conf_unform = dest_conf.content.decode('utf8') conf = loads(conf_unform) dest_ver = conf["ver"] # Версия нашего сайта our_conf = read(f"cached/{site}/config.json") our_ver = our_conf["ver"] # Если версия не новее - не скачиваем if our_ver >= dest_ver: return "old" # Скачиваем файлы g_site = get(f"http://{host}:{str(port)}/{site}.zip") print('SIZE: ', g_site.headers['Content-Length']) # Размер with open(f"verify/{site}.zip", "wb") as f: f.write(g_site.content) f.close() g_sig = get(f"http://{host}:{str(port)}/{site}.sig") with open(f"verify/{site}.sig", "wb") as f: f.write(g_sig.content) f.close() g_key = get(f"http://{host}:{str(port)}/{site}.pem") with open(f"verify/{site}.pem", "wb") as f: f.write(g_key.content) f.close() # Проверяем подпись # Если сайт уже есть в кэше: if os.path.exists(f'cached/{site}'): okay = verify(f"verify/{site}.zip", f"cached/{site}.pem", f"verify/{site}.sig") else: okay = verify(f"verify/{site}.zip", f"verify/{site}.pem", f"verify/{site}.sig") # Распаковываем архив с сайтом unpack_archive(f"verify/{site}.zip", f"verify/{site}") # Вторичная проверка версии если сайт в кэше # (мало ли какие гении нехорошие появятся) if os.path.exists(f'cached/{site}'): # Версия полученного dest_conf = read(f"verify/{site}/config.json") dest_ver = dest_conf["ver"] # Версия нашего сайта our_conf = read(f"cached/{site}/config.json") our_ver = our_conf["ver"] # Если версия не новее - злоумышленник if our_ver >= dest_ver: print("[!] Обнаружена подмена версии сайта.") # Сохраняем ключ злоумышленника os.replace(f"verify/{site}.pem", f"verify/{site}.pem.FAKE") print(f"[!] Порт злоумышленника: {port}") # Удаляем фальшивые файлы os.remove(f"verify/{site}.zip") os.remove(f"verify/{site}.sig") rmtree(f"verify/{site}") return "fake" if okay: # Перемещаем файлы, т.к. всё хорошо os.replace(f"verify/{site}.zip", f"cached/{site}.zip") os.replace(f"verify/{site}.sig", f"cached/{site}.sig") os.replace(f"verify/{site}.pem", f"cached/{site}.pem") # Переносим папку с файлами if os.path.exists(f'cached/{site}'): rmtree(f"cached/{site}") copytree(f"verify/{site}", f"cached/{site}") rmtree(f"verify/{site}") else: print("[!] Обнаружена подмена сайта.") # Сохраняем ключ злоумышленника os.replace(f"verify/{site}.pem", f"verify/{site}.pem.FAKE") print(f"[!] Порт злоумышленника: {port}") print(f"[!] Ключ (вероятно) злоумышленника сохранён в verify/{site}.pem.FAKE\n") # Удаляем фальшивые файлы os.remove(f"verify/{site}.zip") os.remove(f"verify/{site}.sig") # Перезаписываем index.html на всякий случай # Проверяем тип сайта type = read(f"cached/{site}/config.json")["type"] # Если динамический if type == "dynamic": port = read(f"cached/{site}/config.json")["port"] with open(f"cached/{site}/index.html", "w") as f: f.write(f'') f.close() global ports ports = [] def check_current(cur_port): global ports if client(cur_port, "ping"): ports.append(cur_port) def check_wait(port): ping = Thread(target = check_current, args=(port,)) ping.start() ping.join(8) exit() # 1. Стартуем все потоки которые вырубают другие потоки, если прошло 8 секунд # 2. Ожидающие потоки стартуют проверку порта # => моментальная проверка 200 портов from tqdm import tqdm from time import sleep def port_check(your_port): global ports ports = [] checks = list(range(25000, 25200)) checks.remove(your_port) for port in tqdm(checks): wait = Thread(target = check_wait, args=(port,)) wait.start() sleep(10) return ports