mirror of https://github.com/secdev/scapy.git
- small fix for p0f_base
- lazy loading for p0f, queso and nmap knowledge databases
This commit is contained in:
parent
a24bd1d885
commit
6012d0901a
262
scapy.py
262
scapy.py
|
@ -22,6 +22,10 @@
|
||||||
|
|
||||||
#
|
#
|
||||||
# $Log: scapy.py,v $
|
# $Log: scapy.py,v $
|
||||||
|
# Revision 0.9.14.8 2003/10/02 15:16:26 pbi
|
||||||
|
# - small fix for p0f_base
|
||||||
|
# - lazy loading for p0f, queso and nmap knowledge databases
|
||||||
|
#
|
||||||
# Revision 0.9.14.7 2003/10/02 14:14:17 pbi
|
# Revision 0.9.14.7 2003/10/02 14:14:17 pbi
|
||||||
# - added a LongField
|
# - added a LongField
|
||||||
# - added classes and bonds for 802.11
|
# - added classes and bonds for 802.11
|
||||||
|
@ -281,7 +285,7 @@
|
||||||
|
|
||||||
from __future__ import generators
|
from __future__ import generators
|
||||||
|
|
||||||
RCSID="$Id: scapy.py,v 0.9.14.7 2003/10/02 14:14:17 pbi Exp $"
|
RCSID="$Id: scapy.py,v 0.9.14.8 2003/10/02 15:16:26 pbi Exp $"
|
||||||
|
|
||||||
VERSION = RCSID.split()[2]+"beta"
|
VERSION = RCSID.split()[2]+"beta"
|
||||||
|
|
||||||
|
@ -3320,6 +3324,33 @@ def attach_filter(s, filter):
|
||||||
s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
|
s.setsockopt(SOL_SOCKET, SO_ATTACH_FILTER, bpfh)
|
||||||
|
|
||||||
|
|
||||||
|
#####################
|
||||||
|
## knowledge bases ##
|
||||||
|
#####################
|
||||||
|
|
||||||
|
class KnowledgeBase:
|
||||||
|
def __init__(self, filename):
|
||||||
|
self.filename = filename
|
||||||
|
self.base = None
|
||||||
|
|
||||||
|
def lazy_init(self):
|
||||||
|
self.base = ""
|
||||||
|
|
||||||
|
def reload(self, filename = None):
|
||||||
|
if filename is not None:
|
||||||
|
self.filename = filename
|
||||||
|
oldbase = self.base
|
||||||
|
self.base = None
|
||||||
|
self.lazy_init()
|
||||||
|
if self.base is None:
|
||||||
|
self.base = oldbase
|
||||||
|
|
||||||
|
def get_base(self):
|
||||||
|
if self.base is None:
|
||||||
|
self.lazy_init()
|
||||||
|
return self.base
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
## p0f stuff ##
|
## p0f stuff ##
|
||||||
|
@ -3340,44 +3371,44 @@ def attach_filter(s, filter):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
p0f_base = []
|
class p0fKnowledgeBase(KnowledgeBase):
|
||||||
p0f_ttl_range=[255]
|
def __init__(self, filename):
|
||||||
|
KnowledgeBase.__init__(self, filename)
|
||||||
def init_p0f(base=None,reset=1):
|
self.ttl_range=[255]
|
||||||
global p0f_base
|
def lazy_init(self):
|
||||||
global p0f_ttl_range
|
try:
|
||||||
if reset:
|
f=open(self.filename)
|
||||||
p0f_base=[]
|
except IOError:
|
||||||
p0f_ttl_range=[255]
|
warning("Can't open base %s" % self.filename)
|
||||||
if base is None:
|
return
|
||||||
base = conf.p0f_base
|
try:
|
||||||
try:
|
self.base = []
|
||||||
f=open(base)
|
for l in f:
|
||||||
except IOError:
|
if l[0] in ["#","\n"]:
|
||||||
return
|
continue
|
||||||
for l in f:
|
l = tuple(l.split(":"))
|
||||||
if l[0] in ["#","\n"]:
|
if len(l) < 9:
|
||||||
continue
|
continue
|
||||||
l = tuple(l.split(":"))
|
li = map(int,l[:8])
|
||||||
if len(l) < 9:
|
if li[1] not in self.ttl_range:
|
||||||
continue
|
self.ttl_range.append(li[1])
|
||||||
li = map(int,l[:8])
|
self.ttl_range.sort()
|
||||||
if li[1] not in p0f_ttl_range:
|
self.base.append((li,":".join(l[8:])[:-1]))
|
||||||
p0f_ttl_range.append(li[1])
|
except:
|
||||||
p0f_ttl_range.sort()
|
warning("Can't parse p0f database (new p0f version ?)")
|
||||||
p0f_base.append((li,":".join(l[8:])[:-1]))
|
self.base = None
|
||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def packet2p0f(pkt):
|
def packet2p0f(pkt):
|
||||||
if not isinstance(pkt, Packet):
|
while pkt.haslayer(IP) and pkt.haslayer(TCP):
|
||||||
|
pkt = pkt.getlayer(IP)
|
||||||
|
if isinstance(pkt.payload, TCP):
|
||||||
|
break
|
||||||
|
pkt = pkt.payload
|
||||||
|
|
||||||
|
if not isinstance(pkt, IP) or not isinstance(pkt.payload, TCP):
|
||||||
raise TypeError("Not a TCP/IP packet")
|
raise TypeError("Not a TCP/IP packet")
|
||||||
if not isinstance(pkt, IP):
|
|
||||||
return packet2p0f(pkt.payload)
|
|
||||||
if not isinstance(pkt.payload, TCP):
|
|
||||||
raise TypeError("Not a TCP packet")
|
|
||||||
if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
|
if pkt.payload.flags & 0x13 != 0x02: #S,!A,!F
|
||||||
raise TypeError("Not a syn packet")
|
raise TypeError("Not a syn packet")
|
||||||
|
|
||||||
|
@ -3389,7 +3420,7 @@ def packet2p0f(pkt):
|
||||||
wscale = pkt.payload.options["WScale"]
|
wscale = pkt.payload.options["WScale"]
|
||||||
else:
|
else:
|
||||||
wscale = -1
|
wscale = -1
|
||||||
t = p0f_ttl_range[:]
|
t = p0f_kdb.ttl_range[:]
|
||||||
t += [pkt.ttl]
|
t += [pkt.ttl]
|
||||||
t.sort()
|
t.sort()
|
||||||
ttl=t[t.index(pkt.ttl)+1]
|
ttl=t[t.index(pkt.ttl)+1]
|
||||||
|
@ -3417,14 +3448,15 @@ def p0f(pkt):
|
||||||
"""Passive OS fingerprinting: which OS emitted this TCP SYN ?
|
"""Passive OS fingerprinting: which OS emitted this TCP SYN ?
|
||||||
p0f(packet) -> accuracy, [list of guesses]
|
p0f(packet) -> accuracy, [list of guesses]
|
||||||
"""
|
"""
|
||||||
if len(p0f_base) == 0:
|
pb = p0f_kdb.get_base()
|
||||||
|
if not pb:
|
||||||
warning("p0f base empty.")
|
warning("p0f base empty.")
|
||||||
return []
|
return []
|
||||||
s = len(p0f_base[0][0])
|
s = len(pb[0][0])
|
||||||
r = []
|
r = []
|
||||||
min = s+1
|
min = s+1
|
||||||
sig = packet2p0f(pkt)
|
sig = packet2p0f(pkt)
|
||||||
for b,name in p0f_base:
|
for b,name in pb:
|
||||||
d = p0f_dist(sig,b)
|
d = p0f_dist(sig,b)
|
||||||
if d < min:
|
if d < min:
|
||||||
r = []
|
r = []
|
||||||
|
@ -3442,7 +3474,6 @@ def prnp0f(pkt):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def pkt2uptime(pkt, HZ=100):
|
def pkt2uptime(pkt, HZ=100):
|
||||||
"""Calculate the date the machine which emitted the packet booted using TCP timestamp
|
"""Calculate the date the machine which emitted the packet booted using TCP timestamp
|
||||||
pkt2uptime(pkt, [HZ=100])"""
|
pkt2uptime(pkt, [HZ=100])"""
|
||||||
|
@ -3464,7 +3495,6 @@ pkt2uptime(pkt, [HZ=100])"""
|
||||||
## Queso stuff ##
|
## Queso stuff ##
|
||||||
#################
|
#################
|
||||||
|
|
||||||
queso_base={}
|
|
||||||
|
|
||||||
def quesoTCPflags(flags):
|
def quesoTCPflags(flags):
|
||||||
if flags == "-":
|
if flags == "-":
|
||||||
|
@ -3475,45 +3505,45 @@ def quesoTCPflags(flags):
|
||||||
v |= 2**flv.index(i)
|
v |= 2**flv.index(i)
|
||||||
return "%x" % v
|
return "%x" % v
|
||||||
|
|
||||||
def init_queso(base=None, reset=1):
|
class QuesoKnowledgeBase(KnowledgeBase):
|
||||||
global queso_base
|
def lazy_init(self):
|
||||||
if reset:
|
try:
|
||||||
queso_base = {}
|
f = open(self.filename)
|
||||||
if base is None:
|
except IOError:
|
||||||
base = conf.queso_base
|
return
|
||||||
try:
|
self.base = {}
|
||||||
f = open(base)
|
p = None
|
||||||
except IOError:
|
try:
|
||||||
return
|
for l in f:
|
||||||
p = None
|
l = l.strip()
|
||||||
for l in f:
|
if not l or l[0] == ';':
|
||||||
l = l.strip()
|
continue
|
||||||
if not l or l[0] == ';':
|
if l[0] == '*':
|
||||||
continue
|
if p is not None:
|
||||||
if l[0] == '*':
|
p[""] = name
|
||||||
|
name = l[1:].strip()
|
||||||
|
p = self.base
|
||||||
|
continue
|
||||||
|
if l[0] not in list("0123456"):
|
||||||
|
continue
|
||||||
|
res = l[2:].split()
|
||||||
|
res[-1] = quesoTCPflags(res[-1])
|
||||||
|
res = " ".join(res)
|
||||||
|
if not p.has_key(res):
|
||||||
|
p[res] = {}
|
||||||
|
p = p[res]
|
||||||
if p is not None:
|
if p is not None:
|
||||||
p[""] = name
|
p[""] = name
|
||||||
name = l[1:].strip()
|
except:
|
||||||
p = queso_base
|
self.base = None
|
||||||
continue
|
warning("Can't load queso base [%s]", self.filename)
|
||||||
if l[0] not in list("0123456"):
|
f.close()
|
||||||
continue
|
|
||||||
res = l[2:].split()
|
|
||||||
res[-1] = quesoTCPflags(res[-1])
|
|
||||||
res = " ".join(res)
|
|
||||||
if not p.has_key(res):
|
|
||||||
p[res] = {}
|
|
||||||
p = p[res]
|
|
||||||
if p is not None:
|
|
||||||
p[""] = name
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def queso_sig(target, dport=80, timeout=3):
|
def queso_sig(target, dport=80, timeout=3):
|
||||||
global queso_base
|
p = queso_kdb.get_base()
|
||||||
p = queso_base
|
|
||||||
ret = []
|
ret = []
|
||||||
for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
|
for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]:
|
||||||
ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
|
ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()),
|
||||||
|
@ -3535,7 +3565,7 @@ def queso_sig(target, dport=80, timeout=3):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def queso_search(sig):
|
def queso_search(sig):
|
||||||
p = queso_base
|
p = queso_kdb.get_base()
|
||||||
sig.reverse()
|
sig.reverse()
|
||||||
ret = []
|
ret = []
|
||||||
try:
|
try:
|
||||||
|
@ -3560,46 +3590,46 @@ queso(target, dport=80, timeout=3)"""
|
||||||
## nmap OS fp stuff ##
|
## nmap OS fp stuff ##
|
||||||
######################
|
######################
|
||||||
|
|
||||||
nmap_base = []
|
|
||||||
|
|
||||||
def init_nmap(base=None, reset=1):
|
class NmapKnowledgeBase(KnowledgeBase):
|
||||||
global nmap_base
|
def lazy_init(self):
|
||||||
if reset:
|
try:
|
||||||
nmap_base=[]
|
f=open(self.filename)
|
||||||
if base is None:
|
except IOError:
|
||||||
base = conf.nmap_base
|
return
|
||||||
try:
|
|
||||||
f=open(base)
|
|
||||||
except IOError:
|
|
||||||
return
|
|
||||||
|
|
||||||
name = None
|
self.base = []
|
||||||
for l in f:
|
name = None
|
||||||
l = l.strip()
|
try:
|
||||||
if not l or l[0] == "#":
|
for l in f:
|
||||||
continue
|
l = l.strip()
|
||||||
if l[:12] == "Fingerprint ":
|
if not l or l[0] == "#":
|
||||||
|
continue
|
||||||
|
if l[:12] == "Fingerprint ":
|
||||||
|
if name is not None:
|
||||||
|
self.base.append((name,sig))
|
||||||
|
name = l[12:].strip()
|
||||||
|
sig={}
|
||||||
|
p = self.base
|
||||||
|
continue
|
||||||
|
op = l.find("(")
|
||||||
|
cl = l.find(")")
|
||||||
|
if op < 0 or cl < 0:
|
||||||
|
warning("error reading nmap os fp base file")
|
||||||
|
continue
|
||||||
|
test = l[:op]
|
||||||
|
s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
|
||||||
|
si = {}
|
||||||
|
for n,v in s:
|
||||||
|
si[n] = v
|
||||||
|
sig[test]=si
|
||||||
if name is not None:
|
if name is not None:
|
||||||
nmap_base.append((name,sig))
|
self.base.append((name,sig))
|
||||||
name = l[12:].strip()
|
except:
|
||||||
sig={}
|
self.base = None
|
||||||
p = nmap_base
|
warning("Can't read nmap database [%s](new nmap version ?)" % base.filename)
|
||||||
continue
|
f.close()
|
||||||
op = l.find("(")
|
|
||||||
cl = l.find(")")
|
|
||||||
if op < 0 or cl < 0:
|
|
||||||
warning("error reading nmap os fp base file")
|
|
||||||
continue
|
|
||||||
test = l[:op]
|
|
||||||
s = map(lambda x: x.split("="), l[op+1:cl].split("%"))
|
|
||||||
si = {}
|
|
||||||
for n,v in s:
|
|
||||||
si[n] = v
|
|
||||||
sig[test]=si
|
|
||||||
if name is not None:
|
|
||||||
nmap_base.append((name,sig))
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
def TCPflags2str(f):
|
def TCPflags2str(f):
|
||||||
fl="FSRPAUEC"
|
fl="FSRPAUEC"
|
||||||
s=""
|
s=""
|
||||||
|
@ -3698,7 +3728,7 @@ def nmap_probes2sig(tests):
|
||||||
|
|
||||||
def nmap_search(sigs):
|
def nmap_search(sigs):
|
||||||
guess = 0,[]
|
guess = 0,[]
|
||||||
for os,fp in nmap_base:
|
for os,fp in nmap_kdb.get_base():
|
||||||
c = 0.0
|
c = 0.0
|
||||||
for t in sigs.keys():
|
for t in sigs.keys():
|
||||||
if t in fp:
|
if t in fp:
|
||||||
|
@ -4065,6 +4095,6 @@ except_filter : BPF filter for packets to ignore
|
||||||
|
|
||||||
conf=Conf()
|
conf=Conf()
|
||||||
|
|
||||||
init_p0f()
|
p0f_kdb = p0fKnowledgeBase(conf.p0f_base)
|
||||||
init_queso()
|
queso_kdb = QuesoKnowledgeBase(conf.queso_base)
|
||||||
init_nmap()
|
nmap_kdb = NmapKnowledgeBase(conf.nmap_base)
|
||||||
|
|
Loading…
Reference in New Issue