danielostrow commited on
Commit
4ddf4fa
·
verified ·
1 Parent(s): 3d181b1

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +30 -6
  2. app.py +221 -0
  3. requirements.txt +4 -0
README.md CHANGED
@@ -1,12 +1,36 @@
1
  ---
2
- title: C2sentinel
3
- emoji: 👁
4
- colorFrom: blue
5
- colorTo: red
6
  sdk: gradio
7
- sdk_version: 6.3.0
8
  app_file: app.py
9
  pinned: false
 
 
 
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
+ title: C2Sentinel
3
+ emoji: 🛡️
4
+ colorFrom: red
5
+ colorTo: gray
6
  sdk: gradio
7
+ sdk_version: 5.0.0
8
  app_file: app.py
9
  pinned: false
10
+ license: mit
11
+ models:
12
+ - danielostrow/c2sentinel
13
  ---
14
 
15
+ # C2Sentinel Demo
16
+
17
+ Interactive demo for C2Sentinel - a machine learning model for detecting Command and Control (C2) beacon communications in network traffic.
18
+
19
+ ## Features
20
+
21
+ - Analyze network connection patterns for C2 activity
22
+ - Preset examples for common scenarios (C2 beacons, legitimate traffic)
23
+ - Adjustable detection threshold
24
+ - Detailed risk factor analysis
25
+
26
+ ## Usage
27
+
28
+ 1. Paste connection data as JSON or select a preset example
29
+ 2. Adjust the detection threshold if needed
30
+ 3. Click "Analyze" to run the model
31
+
32
+ ## Model
33
+
34
+ See the [C2Sentinel model repository](https://huggingface.co/danielostrow/c2sentinel) for full documentation.
35
+
36
+ **Author:** Daniel Ostrow | [neuralintellect.com](https://neuralintellect.com)
app.py ADDED
@@ -0,0 +1,221 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ C2Sentinel Demo - HuggingFace Space
4
+ Interactive demo for testing C2 beacon detection.
5
+ """
6
+
7
+ import gradio as gr
8
+ import json
9
+ from huggingface_hub import hf_hub_download
10
+ import sys
11
+ import os
12
+
13
+ # Download model files from the model repo
14
+ model_dir = "."
15
+ try:
16
+ hf_hub_download(repo_id="danielostrow/c2sentinel", filename="c2sentinel.py", local_dir=model_dir)
17
+ hf_hub_download(repo_id="danielostrow/c2sentinel", filename="c2_sentinel.safetensors", local_dir=model_dir)
18
+ hf_hub_download(repo_id="danielostrow/c2sentinel", filename="c2_sentinel.json", local_dir=model_dir)
19
+ except Exception as e:
20
+ print(f"Error downloading model files: {e}")
21
+
22
+ # Import the model
23
+ from c2sentinel import C2Sentinel
24
+
25
+ # Load model
26
+ sentinel = C2Sentinel.load('c2_sentinel')
27
+
28
+ # Example connection data
29
+ EXAMPLES = {
30
+ "C2 Beacon (60s intervals)": json.dumps([
31
+ {"timestamp": 1705600000, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
32
+ {"timestamp": 1705600060, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
33
+ {"timestamp": 1705600120, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
34
+ {"timestamp": 1705600180, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
35
+ {"timestamp": 1705600240, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
36
+ {"timestamp": 1705600300, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
37
+ {"timestamp": 1705600360, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
38
+ {"timestamp": 1705600420, "dst_ip": "45.33.32.156", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},
39
+ ], indent=2),
40
+
41
+ "Metasploit Default Port": json.dumps([
42
+ {"timestamp": 1705600000, "dst_ip": "10.10.10.10", "dst_port": 4444, "bytes_sent": 150, "bytes_recv": 300},
43
+ {"timestamp": 1705600030, "dst_ip": "10.10.10.10", "dst_port": 4444, "bytes_sent": 150, "bytes_recv": 300},
44
+ {"timestamp": 1705600060, "dst_ip": "10.10.10.10", "dst_port": 4444, "bytes_sent": 150, "bytes_recv": 300},
45
+ {"timestamp": 1705600090, "dst_ip": "10.10.10.10", "dst_port": 4444, "bytes_sent": 150, "bytes_recv": 300},
46
+ {"timestamp": 1705600120, "dst_ip": "10.10.10.10", "dst_port": 4444, "bytes_sent": 150, "bytes_recv": 300},
47
+ ], indent=2),
48
+
49
+ "SSH Keepalive (Legitimate)": json.dumps([
50
+ {"timestamp": 1705600000, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
51
+ {"timestamp": 1705600030, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
52
+ {"timestamp": 1705600060, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
53
+ {"timestamp": 1705600090, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
54
+ {"timestamp": 1705600120, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
55
+ {"timestamp": 1705600150, "dst_ip": "192.168.1.10", "dst_port": 22, "bytes_sent": 48, "bytes_recv": 48},
56
+ ], indent=2),
57
+
58
+ "Web Browsing (Legitimate)": json.dumps([
59
+ {"timestamp": 1705600000, "dst_ip": "93.184.216.34", "dst_port": 443, "bytes_sent": 500, "bytes_recv": 15000},
60
+ {"timestamp": 1705600002, "dst_ip": "93.184.216.34", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 8000},
61
+ {"timestamp": 1705600010, "dst_ip": "151.101.1.140", "dst_port": 443, "bytes_sent": 800, "bytes_recv": 45000},
62
+ {"timestamp": 1705600015, "dst_ip": "172.217.14.206", "dst_port": 443, "bytes_sent": 300, "bytes_recv": 12000},
63
+ {"timestamp": 1705600025, "dst_ip": "151.101.1.140", "dst_port": 443, "bytes_sent": 150, "bytes_recv": 5000},
64
+ ], indent=2),
65
+
66
+ "Slow Beacon (5 min intervals)": json.dumps([
67
+ {"timestamp": 1705600000, "dst_ip": "203.0.113.50", "dst_port": 8080, "bytes_sent": 256, "bytes_recv": 512},
68
+ {"timestamp": 1705600300, "dst_ip": "203.0.113.50", "dst_port": 8080, "bytes_sent": 256, "bytes_recv": 512},
69
+ {"timestamp": 1705600600, "dst_ip": "203.0.113.50", "dst_port": 8080, "bytes_sent": 256, "bytes_recv": 512},
70
+ {"timestamp": 1705600900, "dst_ip": "203.0.113.50", "dst_port": 8080, "bytes_sent": 256, "bytes_recv": 512},
71
+ {"timestamp": 1705601200, "dst_ip": "203.0.113.50", "dst_port": 8080, "bytes_sent": 256, "bytes_recv": 512},
72
+ ], indent=2),
73
+ }
74
+
75
+
76
+ def analyze_connections(connection_json: str, threshold: float, strict_mode: bool) -> tuple:
77
+ """Analyze connection data and return results."""
78
+ try:
79
+ connections = json.loads(connection_json)
80
+ if not isinstance(connections, list):
81
+ return "Error: Input must be a JSON array of connection objects", "", ""
82
+
83
+ if len(connections) < 3:
84
+ return "Error: Need at least 3 connections for analysis", "", ""
85
+
86
+ # Run analysis
87
+ result = sentinel.analyze(connections, threshold=threshold, strict_mode=strict_mode)
88
+
89
+ # Format primary result
90
+ if result.is_c2:
91
+ verdict = f"C2 DETECTED: {result.c2_type}"
92
+ verdict_color = "red"
93
+ else:
94
+ verdict = "No C2 Detected"
95
+ verdict_color = "green"
96
+
97
+ primary = f"""## Verdict: {verdict}
98
+
99
+ **Probability:** {result.c2_probability:.1%}
100
+ **Confidence:** {result.confidence:.1%}
101
+ **Detection Method:** {result.detection_method}
102
+ """
103
+
104
+ if result.matched_legitimate_pattern:
105
+ primary += f"**Matched Pattern:** {result.matched_legitimate_pattern}\n"
106
+ if result.service_type:
107
+ primary += f"**Service Type:** {result.service_type}\n"
108
+ if result.immediate_detection:
109
+ primary += "**Immediate Detection:** Yes (signature match)\n"
110
+
111
+ # Format risk factors
112
+ risk_text = ""
113
+ if result.risk_factors:
114
+ risk_text = "### Risk Factors\n"
115
+ for factor in result.risk_factors:
116
+ risk_text += f"- {factor}\n"
117
+
118
+ if result.mitigating_factors:
119
+ risk_text += "\n### Mitigating Factors\n"
120
+ for factor in result.mitigating_factors:
121
+ risk_text += f"- {factor}\n"
122
+
123
+ # Format recommendations
124
+ rec_text = ""
125
+ if result.recommendations:
126
+ rec_text = "### Recommendations\n"
127
+ for rec in result.recommendations:
128
+ rec_text += f"- {rec}\n"
129
+
130
+ return primary, risk_text, rec_text
131
+
132
+ except json.JSONDecodeError as e:
133
+ return f"Error: Invalid JSON - {str(e)}", "", ""
134
+ except Exception as e:
135
+ return f"Error: {str(e)}", "", ""
136
+
137
+
138
+ def load_example(example_name: str) -> str:
139
+ """Load example connection data."""
140
+ return EXAMPLES.get(example_name, "")
141
+
142
+
143
+ # Build the interface
144
+ with gr.Blocks(title="C2Sentinel Demo", theme=gr.themes.Soft()) as demo:
145
+ gr.Markdown("""
146
+ # C2Sentinel
147
+
148
+ **Command and Control Beacon Detection**
149
+
150
+ Analyze network connection patterns to detect C2 beacon activity.
151
+ The model uses behavioral analysis to identify C2 communications on any port.
152
+
153
+ [Model Repository](https://huggingface.co/danielostrow/c2sentinel) | [Documentation](https://huggingface.co/danielostrow/c2sentinel/blob/main/API_REFERENCE.md)
154
+ """)
155
+
156
+ with gr.Row():
157
+ with gr.Column(scale=2):
158
+ example_dropdown = gr.Dropdown(
159
+ choices=list(EXAMPLES.keys()),
160
+ label="Load Example",
161
+ value=None
162
+ )
163
+
164
+ connection_input = gr.Textbox(
165
+ label="Connection Data (JSON)",
166
+ placeholder='[\n {"timestamp": 1000000, "dst_ip": "10.0.0.1", "dst_port": 443, "bytes_sent": 200, "bytes_recv": 500},\n ...\n]',
167
+ lines=15
168
+ )
169
+
170
+ with gr.Row():
171
+ threshold = gr.Slider(
172
+ minimum=0.1,
173
+ maximum=0.9,
174
+ value=0.5,
175
+ step=0.1,
176
+ label="Detection Threshold"
177
+ )
178
+ strict_mode = gr.Checkbox(
179
+ label="Strict Mode (min 0.7 threshold)",
180
+ value=False
181
+ )
182
+
183
+ analyze_btn = gr.Button("Analyze", variant="primary")
184
+
185
+ with gr.Column(scale=2):
186
+ result_primary = gr.Markdown(label="Analysis Result")
187
+ result_risks = gr.Markdown(label="Risk Analysis")
188
+ result_recommendations = gr.Markdown(label="Recommendations")
189
+
190
+ gr.Markdown("""
191
+ ---
192
+ ### Connection Record Format
193
+
194
+ | Field | Type | Required | Description |
195
+ |-------|------|----------|-------------|
196
+ | `timestamp` | float | Yes | Unix timestamp |
197
+ | `dst_ip` | str | Yes | Destination IP |
198
+ | `dst_port` | int | Yes | Destination port |
199
+ | `bytes_sent` | int | Yes | Bytes sent |
200
+ | `bytes_recv` | int | Yes | Bytes received |
201
+
202
+ ---
203
+ **Author:** Daniel Ostrow | [neuralintellect.com](https://neuralintellect.com)
204
+ """)
205
+
206
+ # Event handlers
207
+ example_dropdown.change(
208
+ fn=load_example,
209
+ inputs=[example_dropdown],
210
+ outputs=[connection_input]
211
+ )
212
+
213
+ analyze_btn.click(
214
+ fn=analyze_connections,
215
+ inputs=[connection_input, threshold, strict_mode],
216
+ outputs=[result_primary, result_risks, result_recommendations]
217
+ )
218
+
219
+
220
+ if __name__ == "__main__":
221
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ torch
2
+ numpy
3
+ safetensors
4
+ huggingface_hub