dryymatt commited on
Commit
e448e65
·
verified ·
1 Parent(s): 6d59bc7

Upload phantom_shard/spiking/anomaly.py

Browse files
Files changed (1) hide show
  1. phantom_shard/spiking/anomaly.py +329 -0
phantom_shard/spiking/anomaly.py ADDED
@@ -0,0 +1,329 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Phantom Shard Protocol — Neuromorphic Spiking Layer
3
+ ====================================================
4
+ Hunt for Zero-Day vulnerabilities by sensing 'logic-flow anomalies' rather
5
+ than scanning for code patterns. Implements Leaky Integrate-and-Fire (LIF)
6
+ neurons with Spike-Timing-Dependent Plasticity (STDP).
7
+
8
+ Architecture:
9
+ - LIF neurons model shard activity as spike trains
10
+ - STDP learns normal logic-flow patterns
11
+ - Anomaly detection via spike-timing divergence
12
+ - No pattern matching — purely spike-timing based
13
+ """
14
+
15
+ import hashlib
16
+ import time
17
+ import uuid
18
+ from collections import deque
19
+ from dataclasses import dataclass, field
20
+ from typing import Optional
21
+
22
+ import numpy as np
23
+
24
+
25
+ @dataclass
26
+ class LIFNeuron:
27
+ """Leaky Integrate-and-Fire neuron.
28
+
29
+ dv/dt = ( -(v - v_rest) + I_syn ) / tau_m
30
+ When v > v_threshold: spike, then v = v_reset
31
+ """
32
+ neuron_id: str
33
+ v_rest: float = -70.0 # Resting potential (mV)
34
+ v_threshold: float = -50.0 # Firing threshold (mV)
35
+ v_reset: float = -65.0 # Reset potential (mV)
36
+ tau_m: float = 20.0 # Membrane time constant (ms)
37
+ refractory: float = 2.0 # Refractory period (ms)
38
+
39
+ # State
40
+ v: float = -70.0 # Current membrane potential
41
+ last_spike: float = -100.0 # Time of last spike
42
+ spike_count: int = 0
43
+
44
+ def update(self, I_syn: float, dt: float, t: float) -> bool:
45
+ """Update neuron for one timestep. Returns True if spike fired."""
46
+ # Refractory check
47
+ if t - self.last_spike < self.refractory:
48
+ return False
49
+
50
+ # LIF dynamics
51
+ dv = (-(self.v - self.v_rest) + I_syn) / self.tau_m * dt
52
+ self.v += dv
53
+
54
+ # Spike check
55
+ if self.v >= self.v_threshold:
56
+ self.v = self.v_reset
57
+ self.last_spike = t
58
+ self.spike_count += 1
59
+ return True
60
+
61
+ return False
62
+
63
+
64
+ @dataclass
65
+ class Synapse:
66
+ """Plastic synapse with STDP."""
67
+ pre_id: str
68
+ post_id: str
69
+ weight: float = 0.5
70
+ w_max: float = 1.0
71
+ w_min: float = 0.0
72
+
73
+ # STDP traces
74
+ Apre: float = 0.0
75
+ Apost: float = 0.0
76
+ tau_pre: float = 20.0 # ms
77
+ tau_post: float = 20.0 # ms
78
+ delta_Apre: float = 0.01
79
+ delta_Apost: float = -0.012
80
+
81
+ def pre_spike(self):
82
+ """Called when pre-synaptic neuron fires."""
83
+ self.Apre += self.delta_Apre
84
+ self.weight = np.clip(self.weight + self.Apost, self.w_min, self.w_max)
85
+
86
+ def post_spike(self):
87
+ """Called when post-synaptic neuron fires."""
88
+ self.Apost += self.delta_Apost
89
+ self.weight = np.clip(self.weight + self.Apre, self.w_min, self.w_max)
90
+
91
+ def decay_traces(self, dt: float):
92
+ """Decay STDP eligibility traces."""
93
+ self.Apre *= np.exp(-dt / self.tau_pre)
94
+ self.Apost *= np.exp(-dt / self.tau_post)
95
+
96
+
97
+ class SpikingNetwork:
98
+ """A network of LIF neurons with STDP synapses for logic-flow anomaly detection."""
99
+
100
+ def __init__(self, n_neurons: int = 100):
101
+ self.n_neurons = n_neurons
102
+ self.neurons: list[LIFNeuron] = []
103
+ self.synapses: list[Synapse] = []
104
+ self.spike_history: deque = deque(maxlen=10000)
105
+ self.baseline_weights: Optional[np.ndarray] = None
106
+ self._t: float = 0.0
107
+ self._dt: float = 0.1 # ms
108
+
109
+ self._initialize_network(n_neurons)
110
+
111
+ def _initialize_network(self, n: int):
112
+ """Initialize random recurrent spiking network."""
113
+ rng = np.random.RandomState(42)
114
+
115
+ # Create neurons with varied parameters for heterogeneity
116
+ for i in range(n):
117
+ self.neurons.append(LIFNeuron(
118
+ neuron_id=f"n{i:04d}",
119
+ v_rest=-70.0 + rng.normal(0, 2),
120
+ v_threshold=-50.0 + rng.normal(0, 3),
121
+ tau_m=20.0 + rng.normal(0, 5),
122
+ ))
123
+
124
+ # Create sparse recurrent connections
125
+ for i in range(n):
126
+ n_conns = rng.randint(5, 20)
127
+ targets = rng.choice(n, n_conns, replace=False)
128
+ for j in targets:
129
+ if i != j:
130
+ self.synapses.append(Synapse(
131
+ pre_id=f"n{i:04d}",
132
+ post_id=f"n{j:04d}",
133
+ weight=float(np.abs(rng.normal(0.5, 0.2))),
134
+ ))
135
+
136
+ # Build index maps for fast lookup
137
+ self._synapse_index: dict[tuple, int] = {
138
+ (s.pre_id, s.post_id): idx for idx, s in enumerate(self.synapses)
139
+ }
140
+
141
+ def train_baseline(self, n_steps: int = 5000):
142
+ """Train the network on normal logic-flow patterns to establish baseline."""
143
+ rng = np.random.RandomState(12345)
144
+ for step in range(n_steps):
145
+ # Inject Poisson-like input to simulate normal shard activity
146
+ input_spikes = rng.random(self.n_neurons) < 0.05 # 5 Hz background
147
+
148
+ self._step(input_spikes)
149
+ self._t += self._dt
150
+
151
+ # Store baseline weights
152
+ self.baseline_weights = np.array([s.weight for s in self.synapses])
153
+ print(f"[Spiking] Baseline trained: {n_steps} steps, {len(self.synapses)} synapses")
154
+
155
+ def _step(self, input_spikes: np.ndarray):
156
+ """Single simulation step."""
157
+ # Apply input spikes
158
+ for i, spiked in enumerate(input_spikes):
159
+ if spiked:
160
+ self.neurons[i].v += 5.0 # Quick depolarization
161
+
162
+ # Update neurons and collect spikes
163
+ neuron_spiked = []
164
+ for i, neuron in enumerate(self.neurons):
165
+ # Compute synaptic input
166
+ I_syn = 0.0
167
+ for j, other in enumerate(self.neurons):
168
+ if i != j:
169
+ key = (f"n{j:04d}", f"n{i:04d}")
170
+ if key in self._synapse_index:
171
+ syn = self.synapses[self._synapse_index[key]]
172
+ if other.last_spike > self._t - 5: # Recent spike
173
+ I_syn += syn.weight * 2.0
174
+
175
+ if neuron.update(I_syn, self._dt, self._t):
176
+ neuron_spiked.append(i)
177
+
178
+ # STDP updates
179
+ for i in neuron_spiked:
180
+ # Pre-spike STDP
181
+ for j, neuron in enumerate(self.neurons):
182
+ key = (f"n{i:04d}", f"n{j:04d}")
183
+ if key in self._synapse_index:
184
+ self.synapses[self._synapse_index[key]].pre_spike()
185
+
186
+ # Post-spike STDP
187
+ for j, neuron in enumerate(self.neurons):
188
+ key = (f"n{j:04d}", f"n{i:04d}")
189
+ if key in self._synapse_index:
190
+ self.synapses[self._synapse_index[key]].post_spike()
191
+
192
+ # Decay all traces
193
+ for syn in self.synapses:
194
+ syn.decay_traces(self._dt)
195
+
196
+ # Record spike history
197
+ if neuron_spiked:
198
+ self.spike_history.append({
199
+ "t": self._t,
200
+ "neurons": neuron_spiked,
201
+ "n_spikes": len(neuron_spiked),
202
+ })
203
+
204
+ def detect_anomaly(self, input_pattern: np.ndarray) -> float:
205
+ """Detect logic-flow anomaly via spike-timing divergence from baseline.
206
+
207
+ Returns anomaly score [0, 1] — higher = more anomalous.
208
+ """
209
+ if self.baseline_weights is None:
210
+ raise RuntimeError("Must train baseline before anomaly detection")
211
+
212
+ # Run input through network
213
+ self._t += 10.0 # Advance time
214
+ n_steps = 20
215
+ pre_spikes = sum(n.spike_count for n in self.neurons)
216
+
217
+ for _ in range(n_steps):
218
+ self._step(input_pattern)
219
+ self._t += self._dt
220
+
221
+ post_spikes = sum(n.spike_count for n in self.neurons)
222
+ new_spikes = post_spikes - pre_spikes
223
+
224
+ # Weight divergence from baseline
225
+ current_weights = np.array([s.weight for s in self.synapses])
226
+ weight_divergence = np.mean(np.abs(current_weights - self.baseline_weights))
227
+
228
+ # Spike-timing irregularity
229
+ if len(self.spike_history) > 10:
230
+ recent_isi = []
231
+ recent_times = [h["t"] for h in list(self.spike_history)[-20:] if h["n_spikes"] > 0]
232
+ for i in range(1, len(recent_times)):
233
+ recent_isi.append(recent_times[i] - recent_times[i-1])
234
+ isi_cv = np.std(recent_isi) / np.mean(recent_isi) if recent_isi and np.mean(recent_isi) > 0 else 0.0
235
+ else:
236
+ isi_cv = 0.0
237
+
238
+ # Combine: weight divergence (60%) + spike irregularity (40%)
239
+ anomaly_score = 0.6 * min(weight_divergence * 10.0, 1.0) + 0.4 * min(isi_cv * 0.5, 1.0)
240
+
241
+ return float(np.clip(anomaly_score, 0.0, 1.0))
242
+
243
+
244
+ class ZeroDayHunter:
245
+ """Hunt Zero-Day vulnerabilities by sensing logic-flow anomalies.
246
+
247
+ Does NOT scan for code patterns. Instead:
248
+ 1. Encodes shard activity as spike trains
249
+ 2. Learns normal logic flow via STDP
250
+ 3. Flags spike-timing anomalies as potential zero-days
251
+ """
252
+
253
+ def __init__(self, n_shards: int = 1000):
254
+ self.n_shards = n_shards
255
+ self.network = SpikingNetwork(n_neurons=min(n_shards, 200))
256
+ self.network.train_baseline(n_steps=5000)
257
+ self.detections: list[dict] = []
258
+ self.baseline_trained = True
259
+
260
+ def encode_shard_activity(self, shard_events: list[dict]) -> np.ndarray:
261
+ """Encode shard computation events as spike input to the SNN.
262
+
263
+ Each shard event is converted to a spike pattern based on:
264
+ - Computation intensity
265
+ - Memory access pattern
266
+ - Logic gate switching frequency
267
+ """
268
+ n_neurons = self.network.n_neurons
269
+ input_pattern = np.zeros(n_neurons)
270
+
271
+ for event in shard_events:
272
+ # Encode event properties into spike probability
273
+ intensity = event.get("intensity", 0.5)
274
+ gate_switches = event.get("gate_switches", 0)
275
+ memory_touches = event.get("memory_touches", 0)
276
+ shard_id = event.get("shard_id", 0)
277
+
278
+ # Map to neuron index
279
+ neuron_idx = shard_id % n_neurons
280
+
281
+ # Spike probability based on logic-flow intensity
282
+ spike_prob = min(
283
+ (intensity * 0.3 + gate_switches * 0.05 + memory_touches * 0.02),
284
+ 0.95
285
+ )
286
+ input_pattern[neuron_idx] = 1.0 if np.random.random() < spike_prob else 0.0
287
+
288
+ return input_pattern
289
+
290
+ def hunt(self, shard_activity: list[dict]) -> dict:
291
+ """Hunt for zero-day vulnerabilities in shard logic flow."""
292
+ input_pattern = self.encode_shard_activity(shard_activity)
293
+ anomaly_score = self.network.detect_anomaly(input_pattern)
294
+
295
+ detection = {
296
+ "timestamp": time.time(),
297
+ "anomaly_score": float(anomaly_score),
298
+ "n_events": len(shard_activity),
299
+ "threat_level": self._assess_threat(anomaly_score),
300
+ "signature": hashlib.sha256(
301
+ str(anomaly_score).encode() + str(time.time()).encode()
302
+ ).hexdigest()[:16],
303
+ }
304
+
305
+ if anomaly_score > 0.5:
306
+ self.detections.append(detection)
307
+
308
+ return detection
309
+
310
+ def _assess_threat(self, score: float) -> str:
311
+ if score > 0.8:
312
+ return "CRITICAL — Likely zero-day logic-flow anomaly"
313
+ elif score > 0.6:
314
+ return "HIGH — Significant deviation from normal spike pattern"
315
+ elif score > 0.4:
316
+ return "MEDIUM — Unusual logic flow detected"
317
+ elif score > 0.2:
318
+ return "LOW — Minor spike-timing variance"
319
+ else:
320
+ return "NORMAL — Standard logic flow"
321
+
322
+ def get_hunt_summary(self) -> dict:
323
+ return {
324
+ "total_scans": len(self.detections),
325
+ "critical": sum(1 for d in self.detections if d["threat_level"].startswith("CRITICAL")),
326
+ "high": sum(1 for d in self.detections if d["threat_level"].startswith("HIGH")),
327
+ "medium": sum(1 for d in self.detections if d["threat_level"].startswith("MEDIUM")),
328
+ "latest_score": self.detections[-1]["anomaly_score"] if self.detections else 0.0,
329
+ }