|
|
@@ -1,11 +1,27 @@
|
|
|
import typing
|
|
|
import pyshark
|
|
|
from datetime import datetime
|
|
|
+from typing import List
|
|
|
|
|
|
class Sample:
|
|
|
EPOCH = datetime(1970, 1, 1)
|
|
|
TIME_FMT = '%Y-%m-%d %H:%M:%S.%f'
|
|
|
+ FILTER = "tcp.flags.push == 1 && tcp.dstport == 22" # len % 8 == 6
|
|
|
|
|
|
+ def make_samples(keylog: typing.TextIO,
|
|
|
+ pcap: typing.BinaryIO,
|
|
|
+ sample_size: int):
|
|
|
+ f = pyshark.FileCapture(pcap.strip(),
|
|
|
+ display_filter=Sample.FILTER,
|
|
|
+ only_summaries=True)
|
|
|
+ f.load_packets()
|
|
|
+ # Start from sample_size to skip incomplete samples
|
|
|
+ samples = map(lambda slic: Sample(slic, keylog), [
|
|
|
+ [f[i] for i in range(end-sample_size, end)]
|
|
|
+ for end in range(sample_size, len(f), sample_size)
|
|
|
+ ])
|
|
|
+ return samples
|
|
|
+
|
|
|
# Boundaries measured in packets/second
|
|
|
def set_activity_thresholds(lower_bound: float, upper_bound: float,
|
|
|
lookback: float):
|
|
|
@@ -16,52 +32,51 @@ class Sample:
|
|
|
Sample.low_act_threshold = lower_bound
|
|
|
Sample.lookback = lookback
|
|
|
|
|
|
- def packet_time(p):
|
|
|
+ def __packet_time(p):
|
|
|
return (datetime.strptime(p.time, Sample.TIME_FMT) - Sample.EPOCH) \
|
|
|
.total_seconds()
|
|
|
|
|
|
- def __init__(self, keylog: typing.TextIO, pcap: typing.BinaryIO):
|
|
|
- self.extract_tag(keylog)
|
|
|
- f = pyshark.FileCapture(pcap.strip(), only_summaries=True)
|
|
|
- f.load_packets()
|
|
|
- self.extract_activity_stats(f)
|
|
|
- self.extract_packet_stats(f)
|
|
|
+ def __init__(self, packets, keylog: typing.TextIO):
|
|
|
+ self.__extract_tag(keylog)
|
|
|
+ self.__extract_activity_stats(packets)
|
|
|
+ self.__extract_packet_stats(packets)
|
|
|
|
|
|
- def extract_tag(self, keylog: typing.TextIO):
|
|
|
+ def __extract_tag(self, keylog: typing.TextIO):
|
|
|
import os
|
|
|
dir_guided = os.path.dirname(keylog)
|
|
|
self.is_guided = os.path.basename(dir_guided) == "y"
|
|
|
dir_user = os.path.dirname(dir_guided)
|
|
|
self.user = os.path.basename(dir_user)
|
|
|
|
|
|
- def extract_activity_stats(self, keylog: typing.TextIO):
|
|
|
+ def __extract_activity_stats(self, packets):
|
|
|
high_activity = []
|
|
|
mid_activity = []
|
|
|
low_activity = []
|
|
|
q = []
|
|
|
- for p in keylog:
|
|
|
- ptime = Sample.packet_time(p)
|
|
|
+ for p in packets:
|
|
|
+ ptime = Sample.__packet_time(p)
|
|
|
q.append(p)
|
|
|
- if len(q) < self.low_act_threshold:
|
|
|
+ rate = float(len(q)) / self.lookback
|
|
|
+ if rate < self.low_act_threshold:
|
|
|
low_activity.append(q)
|
|
|
- elif len(q) > self.high_act_threshold:
|
|
|
- high_activity.append(q)
|
|
|
- else:
|
|
|
+ elif rate < self.high_act_threshold:
|
|
|
mid_activity.append(q)
|
|
|
- while Sample.packet_time(q[0]) + self.lookback < ptime:
|
|
|
+ else:
|
|
|
+ high_activity.append(q)
|
|
|
+ while Sample.__packet_time(q[0]) + self.lookback < ptime:
|
|
|
q = q[1:]
|
|
|
self.activities = {
|
|
|
- "high": Sample.count_activity_stats(high_activity),
|
|
|
- "mid": Sample.count_activity_stats(mid_activity),
|
|
|
- "low": Sample.count_activity_stats(low_activity)
|
|
|
+ "high": Sample.__count_activity_stats(high_activity),
|
|
|
+ "mid": Sample.__count_activity_stats(mid_activity),
|
|
|
+ "low": Sample.__count_activity_stats(low_activity)
|
|
|
}
|
|
|
|
|
|
- def count_activity_stats(arr):
|
|
|
+ def __count_activity_stats(arr):
|
|
|
return {
|
|
|
"total packets": len(arr)
|
|
|
}
|
|
|
|
|
|
- def extract_packet_stats(self, pcap):
|
|
|
- start = Sample.packet_time(pcap[0])
|
|
|
- end = Sample.packet_time(pcap[-1])
|
|
|
- self.average_iat = self.average_iat = (end - start) / len(pcap)
|
|
|
+ def __extract_packet_stats(self, pcap):
|
|
|
+ start = Sample.__packet_time(pcap[0])
|
|
|
+ end = Sample.__packet_time(pcap[-1])
|
|
|
+ self.average_iat = (end - start) / len(pcap)
|