-
Notifications
You must be signed in to change notification settings - Fork 0
/
ssscanner.py
127 lines (99 loc) · 3.49 KB
/
ssscanner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
import sys
import argparse
import numpy as np
import matplotlib.pyplot as plt
from collections import deque, Counter
from scapy.all import *
def check_five_tuple(ap, bp):
try:
asrc = ap['IP'].src
adst = ap['IP'].dst
asport = ap['TCP'].sport
adport = ap['TCP'].dport
aproto = ap['IP'].proto
bsrc = bp['IP'].src
bdst = bp['IP'].dst
bsport = bp['TCP'].sport
bdport = bp['TCP'].dport
bproto = bp['IP'].proto
except (IndexError, KeyError, AttributeError):
return False
return (
asrc == bsrc and
asport == bsport and
adst == bdst and
adport == bdport and
aproto == bproto
)
def gen_scan_pkts(pcapfile, windowsize):
window = deque(maxlen=windowsize)
with PcapReader(pcapfile) as pkts:
# fill window
for p in pkts:
if p.haslayer(TCP):
window.append(p)
if len(window) == windowsize:
break
for p in pkts:
if not p.haslayer(TCP):
continue
syn_p = window.popleft()
window.append(p)
flags = syn_p['TCP'].flags
dport = syn_p['TCP'].dport
# is syn_p really a SYN packet?
if not ('S' == flags):
continue
is_scan = True
for p in window:
# is syn_p is a usual SYN packet to establish TCP conn?
# it will be, if there is a TCP packet which carries a payload
# within the same conversation.
is_same_conv = check_five_tuple(syn_p, p)
is_usual_p = is_same_conv and len(p['TCP'].payload) > 0
if is_usual_p:
is_scan = False
break
if is_scan:
yield syn_p
def draw_bar(bars, output, xlabel, ylabel, log=False):
sorted_bars = sorted(bars, key=lambda t: t[1], reverse=True)
bar_name = np.array([t[0] for t in sorted_bars]) # name
y = np.array([t[1] for t in sorted_bars]) # value
bar_posision = np.arange(len(bar_name))
fig = plt.figure()
ax = fig.add_subplot(111)
ax.bar(bar_posision, y, tick_label=bar_name)
ax.set_xlabel(xlabel)
ax.set_ylabel(ylabel)
if log:
ax.yscale("log")
plt.savefig(output)
NUM_TOP = 10
def bar_chart(counter, outputpath):
if not outputpath.endswith('.png'):
raise Exception('PNG only')
draw_bar(counter.most_common(NUM_TOP), outputpath,
'Port Number', 'Number of Scan')
WINDOWSIZE = 256
def main():
parser = argparse.ArgumentParser()
parser.add_argument('pcapfile', type=str)
parser.add_argument('-w', '--windowsize', type=int, default=WINDOWSIZE)
parser.add_argument('-q', '--quiet', action='store_true', help='No output description')
parser.add_argument('--bar', type=str, default='', help='Path to output bar chart')
args = parser.parse_args()
if not args.bar:
if not args.quiet:
print('source ip:port, dest ip:port')
for syn_p in gen_scan_pkts(args.pcapfile, args.windowsize):
print('{}:{}, {}:{}'.format(
syn_p['IP'].src, syn_p['TCP'].sport,
syn_p['IP'].dst, syn_p['TCP'].dport))
else:
port_c = Counter()
for syn_p in gen_scan_pkts(args.pcapfile, args.windowsize):
port_c[syn_p.dport] += 1
bar_chart(port_c, args.bar)
if __name__ == '__main__':
main()