theghostcmd commited on
Commit
758edb3
·
verified ·
1 Parent(s): d5cb401

Upload 10 files

Browse files
Files changed (10) hide show
  1. .gitignore +43 -0
  2. LICENSE +21 -0
  3. README.md +39 -3
  4. ai/anomaly_model.py +47 -0
  5. ai/risk_scoring.py +23 -0
  6. config.py +40 -0
  7. main.py +135 -0
  8. requirements.txt +9 -0
  9. test_framework.py +49 -0
  10. test_simulator.py +39 -0
.gitignore ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @"
2
+ # Python
3
+ __pycache__/
4
+ *.py[cod]
5
+ *.so
6
+ .Python
7
+ env/
8
+ venv/
9
+ *.egg-info/
10
+ dist/
11
+ build/
12
+
13
+ # Database files
14
+ *.db
15
+ *.sqlite
16
+ *.sqlite3
17
+
18
+ # Logs
19
+ logs/*.log
20
+ *.log
21
+
22
+ # Models
23
+ models/
24
+ *.pkl
25
+
26
+ # GeoIP database
27
+ geoip/*.mmdb
28
+
29
+ # Sensitive config
30
+ config_local.py
31
+
32
+ # IDE
33
+ .vscode/
34
+ .idea/
35
+ *.swp
36
+
37
+ # OS junk
38
+ .DS_Store
39
+ Thumbs.db
40
+
41
+ # Temporary PCAP exports
42
+ *.pcap
43
+ "@ | Out-File -FilePath .gitignore -Encoding utf8
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GhostCmd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,3 +1,39 @@
1
- ---
2
- license: mit
3
- ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MayOne Security Framework
2
+
3
+ **AI‑powered Intrusion Detection & Response for Windows**
4
+
5
+ ![Dashboard Preview](docs/dashboard.png)
6
+
7
+ ## Features
8
+
9
+ - Real‑time packet capture (Scapy)
10
+ - Rule‑based threat detection (port scan, brute force, DDoS, bursts)
11
+ - AI anomaly detection (Isolation Forest) – learns normal traffic
12
+ - Risk scoring (0–100) with threat levels: LOW, MEDIUM, HIGH, CRITICAL
13
+ - Automatic IP blocking via Windows Firewall (inbound+outbound)
14
+ - SQLite database for events, threats, blocked IPs, reports
15
+ - Live Flask dashboard with:
16
+ - Traffic statistics
17
+ - Protocol distribution & top ports charts
18
+ - Recent threats table
19
+ - Manual IP block/unblock
20
+ - Geo‑IP blocking (optional, MaxMind GeoLite2)
21
+ - Scheduled & emergency PDF reports (with logo watermark)
22
+ - PCAP export (full buffer)
23
+ - Multithreaded, thread‑safe, low CPU usage
24
+
25
+ ## Requirements
26
+
27
+ - Windows 10/11 (or Windows Server)
28
+ - Python 3.10 or higher
29
+ - Npcap (with WinPcap API compatibility) – [Download](https://npcap.com)
30
+ - Administrator privileges (for sniffing and firewall changes)
31
+
32
+ ## Installation
33
+
34
+ 1. Clone the repository:
35
+ ```bash
36
+ git clone https://github.com/yourusername/MayOne-Security-Framework.git
37
+ cd MayOne-Security-Framework
38
+ pip install -r requirements.txt
39
+ python main.py
ai/anomaly_model.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from sklearn.ensemble import IsolationForest
3
+ import pickle
4
+ import os
5
+ import threading
6
+
7
+ class AnomalyModel:
8
+ def __init__(self, buffer_size=500):
9
+ self.model = None
10
+ self.feature_buffer = []
11
+ self.buffer_size = buffer_size
12
+ self.is_trained = False
13
+ self.lock = threading.Lock()
14
+
15
+ def _extract_features(self, packet_info):
16
+ size = packet_info['size']
17
+ proto = packet_info['protocol']
18
+ proto_map = {'TCP': 0, 'UDP': 1, 'ICMP': 2, 'OTHER': 3}
19
+ proto_code = proto_map.get(proto, 3)
20
+ return [size, proto_code]
21
+
22
+ def add_packet(self, packet_info):
23
+ feats = self._extract_features(packet_info)
24
+ with self.lock:
25
+ self.feature_buffer.append(feats)
26
+ if len(self.feature_buffer) >= self.buffer_size and not self.is_trained:
27
+ self._train()
28
+ return feats
29
+
30
+ def _train(self):
31
+ X = np.array(self.feature_buffer)
32
+ self.model = IsolationForest(contamination=0.1, random_state=42)
33
+ self.model.fit(X)
34
+ self.is_trained = True
35
+ print(f"[AI] Anomaly model trained on {len(X)} samples.")
36
+
37
+ def predict_anomaly_score(self, packet_info):
38
+ if not self.is_trained:
39
+ return 0.0
40
+ feats = self._extract_features(packet_info)
41
+ pred = self.model.predict([feats])[0]
42
+ if pred == -1:
43
+ score = -self.model.decision_function([feats])[0]
44
+ score = np.clip(score, 0, 1)
45
+ else:
46
+ score = 0.0
47
+ return score
ai/risk_scoring.py ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class RiskScorer:
2
+ def __init__(self, rule_weight=0.6, ai_weight=0.4):
3
+ self.rule_weight = rule_weight
4
+ self.ai_weight = ai_weight
5
+
6
+ def compute_risk(self, rule_threats, ai_anomaly_score):
7
+ if rule_threats:
8
+ max_rule_risk = max(score for _, score in rule_threats) / 100.0
9
+ else:
10
+ max_rule_risk = 0.0
11
+
12
+ combined = self.rule_weight * max_rule_risk + self.ai_weight * ai_anomaly_score
13
+ return min(100, int(combined * 100))
14
+
15
+ def threat_level(self, risk_score):
16
+ if risk_score >= 80:
17
+ return "CRITICAL"
18
+ elif risk_score >= 60:
19
+ return "HIGH"
20
+ elif risk_score >= 30:
21
+ return "MEDIUM"
22
+ else:
23
+ return "LOW"
config.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration file for MayOne Security Framework
2
+
3
+ # Detection thresholds
4
+ THRESHOLD = 0.6 # Risk threshold (0-1) above which action is taken
5
+ TIME_WINDOW = 10 # Time window in seconds for burst/scan detection
6
+ PORT_SCAN_THRESHOLD = 20 # Number of unique ports from one src in TIME_WINDOW
7
+ BRUTE_FORCE_THRESHOLD = 10 # Number of failed-like packets (e.g., TCP to port 22/3389)
8
+ DDoS_THRESHOLD = 100 # Packets per second from one src to trigger DDoS suspicion
9
+ BURST_THRESHOLD = 50 # Packets in 1 second from one src
10
+
11
+ # Response
12
+ AUTO_BLOCK = True # Automatically block IP via Windows Firewall
13
+ LOG_LEVEL = "INFO" # DEBUG, INFO, WARNING, ERROR
14
+ REPORT_INTERVAL = 600 # Seconds between automatic reports (10 minutes)
15
+
16
+ # Network interface to sniff (use None for default)
17
+ NETWORK_INTERFACE = None # e.g., "Ethernet" or "Wi-Fi"
18
+
19
+ # Dashboard
20
+ DASHBOARD_HOST = "127.0.0.1"
21
+ DASHBOARD_PORT = 5000
22
+
23
+ # Database
24
+ DB_PATH = "database/security_events.db"
25
+
26
+ # Whitelisted private IP ranges (CIDR)
27
+ PRIVATE_RANGES = [
28
+ "127.0.0.0/8",
29
+ "10.0.0.0/8",
30
+ "172.16.0.0/12",
31
+ "192.168.0.0/16",
32
+ ]
33
+
34
+ # GeoIP blocking
35
+ ENABLE_GEOIP_BLOCK = True # Default state (can be toggled from dashboard)
36
+ GEOIP_DB_PATH = "geoip/GeoLite2-Country.mmdb"
37
+ HIGH_RISK_COUNTRIES = ["RU", "CN", "KP", "IR", "SY", "UA", "AF", "IQ", "LY", "SO"]
38
+
39
+ # PCAP export
40
+ PCAP_BUFFER_SIZE = 10000 # Max number of raw packets to keep
main.py ADDED
@@ -0,0 +1,135 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import threading
3
+ import queue
4
+ import time
5
+ import logging
6
+ import signal
7
+ import sys
8
+ import ipaddress
9
+ from config import *
10
+ from database.db import Database
11
+ from monitor.packet_sniffer import PacketSniffer
12
+ from detection.threat_detector import ThreatDetector
13
+ from ai.anomaly_model import AnomalyModel
14
+ from ai.risk_scoring import RiskScorer
15
+ from response.block_ip import block_ip_windows
16
+ from reports.report_generator import ReportGenerator
17
+ from dashboard.app import run_dashboard
18
+ from geoip.blocker import GeoIPBlocker
19
+
20
+ logging.basicConfig(
21
+ filename='logs/system.log',
22
+ level=getattr(logging, LOG_LEVEL),
23
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
24
+ )
25
+ console = logging.StreamHandler()
26
+ console.setLevel(logging.INFO)
27
+ logging.getLogger('').addHandler(console)
28
+
29
+ # Global variable that can be toggled from dashboard
30
+ geoip_enabled = ENABLE_GEOIP_BLOCK
31
+
32
+ def is_private_ip(ip):
33
+ try:
34
+ addr = ipaddress.ip_address(ip)
35
+ for cidr in PRIVATE_RANGES:
36
+ if addr in ipaddress.ip_network(cidr):
37
+ return True
38
+ return False
39
+ except:
40
+ return False
41
+
42
+ class MayOneEngine:
43
+ def __init__(self):
44
+ self.packet_queue = queue.Queue(maxsize=10000)
45
+ self.db = Database()
46
+ self.sniffer = PacketSniffer(self.packet_queue, NETWORK_INTERFACE, PCAP_BUFFER_SIZE)
47
+ self.detector = ThreatDetector(TIME_WINDOW, PORT_SCAN_THRESHOLD,
48
+ BRUTE_FORCE_THRESHOLD, DDoS_THRESHOLD, BURST_THRESHOLD)
49
+ self.anomaly_model = AnomalyModel()
50
+ self.scorer = RiskScorer()
51
+ self.reporter = ReportGenerator(self.db)
52
+ self.geoip = GeoIPBlocker() if ENABLE_GEOIP_BLOCK else None
53
+ self.running = True
54
+ self.last_report_time = time.time()
55
+ self.recently_blocked = set()
56
+
57
+ def start(self):
58
+ logging.info("Starting MayOne Security Framework")
59
+ self.sniffer.start()
60
+ dash_thread = threading.Thread(target=run_dashboard, args=(DASHBOARD_HOST, DASHBOARD_PORT, self.sniffer), daemon=True)
61
+ dash_thread.start()
62
+ while self.running:
63
+ try:
64
+ packet = self.packet_queue.get(timeout=1)
65
+ self.process_packet(packet)
66
+ except queue.Empty:
67
+ self.check_auto_report()
68
+ continue
69
+ except Exception as e:
70
+ logging.error(f"Main loop error: {e}", exc_info=True)
71
+
72
+ def process_packet(self, packet):
73
+ global geoip_enabled
74
+ src_ip = packet['src_ip']
75
+
76
+ # GeoIP blocking check (if enabled)
77
+ if geoip_enabled and self.geoip and not is_private_ip(src_ip):
78
+ if self.geoip.is_high_risk(src_ip):
79
+ logging.info(f"GeoIP high-risk country detected: {src_ip}")
80
+ if AUTO_BLOCK and src_ip not in self.recently_blocked:
81
+ if block_ip_windows(src_ip, "GeoIP high-risk country"):
82
+ self.db.insert_blocked_ip(src_ip, "GeoIP auto-block")
83
+ self.recently_blocked.add(src_ip)
84
+ action = "GEO_BLOCKED"
85
+ self.db.insert_event(src_ip, packet['dst_ip'], packet['protocol'],
86
+ packet['port'], packet['size'], "GEOIP_RISK", 90, action)
87
+ self.db.insert_threat(src_ip, "GEOIP_RISK", 90, f"Country: high-risk")
88
+ return # skip further processing
89
+
90
+ # Normal AI + rule detection
91
+ anomaly_score = self.anomaly_model.predict_anomaly_score(packet)
92
+ rule_threats = self.detector.detect(packet)
93
+ risk = self.scorer.compute_risk(rule_threats, anomaly_score)
94
+ threat_level = self.scorer.threat_level(risk)
95
+ action = None
96
+
97
+ if risk >= THRESHOLD * 100 and AUTO_BLOCK and not is_private_ip(src_ip):
98
+ if src_ip not in self.recently_blocked:
99
+ if block_ip_windows(src_ip, f"{threat_level} risk {risk}"):
100
+ self.db.insert_blocked_ip(src_ip, f"{threat_level} risk")
101
+ self.recently_blocked.add(src_ip)
102
+ action = "BLOCKED"
103
+
104
+ threat_type = rule_threats[0][0] if rule_threats else None
105
+ self.db.insert_event(
106
+ src_ip, packet['dst_ip'], packet['protocol'],
107
+ packet['port'], packet['size'], threat_type, risk, action
108
+ )
109
+ if threat_type or anomaly_score > 0.3:
110
+ self.db.insert_threat(src_ip, threat_type or "ANOMALY", risk,
111
+ f"Anomaly={anomaly_score:.2f}")
112
+
113
+ if threat_level == "CRITICAL":
114
+ logging.warning(f"CRITICAL threat from {src_ip} - generating emergency report")
115
+ threading.Thread(target=self.reporter.generate_report, args=("critical_threat",)).start()
116
+
117
+ self.anomaly_model.add_packet(packet)
118
+
119
+ def check_auto_report(self):
120
+ if time.time() - self.last_report_time >= REPORT_INTERVAL:
121
+ logging.info("Generating scheduled report")
122
+ self.reporter.generate_report("scheduled")
123
+ self.last_report_time = time.time()
124
+
125
+ def shutdown(self):
126
+ logging.info("Shutting down MayOne Security Framework")
127
+ self.running = False
128
+ self.sniffer.stop()
129
+ self.db.close()
130
+ sys.exit(0)
131
+
132
+ if __name__ == "__main__":
133
+ engine = MayOneEngine()
134
+ signal.signal(signal.SIGINT, lambda sig, frame: engine.shutdown())
135
+ engine.start()
requirements.txt ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ scapy==2.5.0
2
+ pandas==2.0.3
3
+ numpy==1.24.3
4
+ scikit-learn==1.3.0
5
+ flask==2.3.3
6
+ reportlab==4.0.4
7
+ waitress==2.1.2
8
+ geoip2==4.8.1
9
+ maxminddb==2.6.2
test_framework.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import sys
4
+ sys.path.append('.')
5
+ from database.db import Database
6
+ from detection.threat_detector import ThreatDetector
7
+ from ai.risk_scoring import RiskScorer
8
+ from reports.report_generator import ReportGenerator
9
+
10
+ def test_db():
11
+ db = Database()
12
+ db.insert_event("192.168.1.100", "8.8.8.8", "TCP", 443, 1500, "TEST", 50, None)
13
+ events = db.get_recent_events()
14
+ assert len(events) >= 1
15
+ print("[OK] Database works")
16
+
17
+ def test_detector():
18
+ det = ThreatDetector(time_window=10, port_scan_th=3)
19
+ packets = [
20
+ {'src_ip': '1.2.3.4', 'port': 80, 'timestamp': 100},
21
+ {'src_ip': '1.2.3.4', 'port': 81, 'timestamp': 101},
22
+ {'src_ip': '1.2.3.4', 'port': 82, 'timestamp': 102},
23
+ {'src_ip': '1.2.3.4', 'port': 83, 'timestamp': 103},
24
+ ]
25
+ for p in packets:
26
+ threats = det.detect(p)
27
+ assert any(t[0]=='PORT_SCAN' for t in threats)
28
+ print("[OK] Threat detector works")
29
+
30
+ def test_risk_scorer():
31
+ scorer = RiskScorer()
32
+ risk = scorer.compute_risk([('PORT_SCAN', 80)], 0.5)
33
+ assert 0 <= risk <= 100
34
+ print("[OK] Risk scoring works")
35
+
36
+ def test_report(db):
37
+ gen = ReportGenerator(db)
38
+ paths = gen.generate_report("test")
39
+ for p in paths:
40
+ assert os.path.exists(p)
41
+ print("[OK] Report generation works")
42
+
43
+ if __name__ == "__main__":
44
+ test_db()
45
+ test_detector()
46
+ test_risk_scorer()
47
+ db = Database()
48
+ test_report(db)
49
+ print("All tests passed.")
test_simulator.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ import time
3
+ import random
4
+ from scapy.all import IP, TCP, UDP, send
5
+
6
+ def port_scan(target_ip="127.0.0.1", ports=range(1, 100)):
7
+ print(f"[SIM] Port scanning {target_ip}...")
8
+ for port in ports:
9
+ pkt = IP(dst=target_ip)/TCP(dport=port, flags="S")
10
+ send(pkt, verbose=False)
11
+ time.sleep(0.01)
12
+
13
+ def brute_force(target_ip="127.0.0.1", port=22, attempts=50):
14
+ print(f"[SIM] Brute force simulation on {target_ip}:{port}")
15
+ for i in range(attempts):
16
+ pkt = IP(dst=target_ip)/TCP(dport=port, flags="S")
17
+ send(pkt, verbose=False)
18
+ time.sleep(0.05)
19
+
20
+ def ddos_flood(target_ip="127.0.0.1", duration=5, rate=200):
21
+ print(f"[SIM] DDoS flood on {target_ip} for {duration}s at {rate} pps")
22
+ end = time.time() + duration
23
+ while time.time() < end:
24
+ for _ in range(rate):
25
+ pkt = IP(dst=target_ip)/UDP(dport=random.randint(1, 65535))
26
+ send(pkt, verbose=False)
27
+ time.sleep(1)
28
+
29
+ if __name__ == "__main__":
30
+ print("Choose attack: 1=Port Scan, 2=Brute Force, 3=DDoS Flood")
31
+ choice = input("> ")
32
+ if choice == "1":
33
+ port_scan()
34
+ elif choice == "2":
35
+ brute_force()
36
+ elif choice == "3":
37
+ ddos_flood()
38
+ else:
39
+ print("Invalid")