From b89efa188810bf95a9d245e69e2961b5721c3b0f Mon Sep 17 00:00:00 2001 From: imarom Date: Mon, 21 Mar 2016 16:03:47 +0200 Subject: scapy python 2/3 --- .../scapy-2.3.1/python2/scapy/modules/__init__.py | 8 + .../scapy-2.3.1/python2/scapy/modules/geoip.py | 79 +++ .../scapy-2.3.1/python2/scapy/modules/nmap.py | 215 ++++++++ .../scapy-2.3.1/python2/scapy/modules/p0f.py | 542 +++++++++++++++++++++ .../scapy-2.3.1/python2/scapy/modules/queso.py | 113 +++++ .../scapy-2.3.1/python2/scapy/modules/voip.py | 149 ++++++ 6 files changed, 1106 insertions(+) create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/__init__.py create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/geoip.py create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/nmap.py create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/p0f.py create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/queso.py create mode 100644 scripts/external_libs/scapy-2.3.1/python2/scapy/modules/voip.py (limited to 'scripts/external_libs/scapy-2.3.1/python2/scapy/modules') diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/__init__.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/__init__.py new file mode 100644 index 00000000..6303dad0 --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/__init__.py @@ -0,0 +1,8 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +Package of extension modules that have to be loaded explicitly. +""" diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/geoip.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/geoip.py new file mode 100644 index 00000000..8b308a4c --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/geoip.py @@ -0,0 +1,79 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +GeoIP: find out the geographical location of IP addresses +""" + +from scapy.data import KnowledgeBase +from scapy.config import conf + +conf.IPCountry_base = "GeoIPCountry4Scapy.gz" +conf.countryLoc_base = "countryLoc.csv" +conf.gnuplot_world = "world.dat" + + +########################## +## IP location database ## +########################## + +class IPCountryKnowledgeBase(KnowledgeBase): + """ +How to generate the base : +db = [] +for l in open("GeoIPCountryWhois.csv").readlines(): + s,e,c = l.split(",")[2:5] + db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1])) +cPickle.dump(gzip.open("xxx","w"),db) +""" + def lazy_init(self): + self.base = load_object(self.filename) + + +class CountryLocKnowledgeBase(KnowledgeBase): + def lazy_init(self): + f=open(self.filename) + self.base = {} + while 1: + l = f.readline() + if not l: + break + l = l.strip().split(",") + if len(l) != 3: + continue + c,lat,long = l + + self.base[c] = (float(long),float(lat)) + f.close() + + + +@conf.commands.register +def locate_ip(ip): + """Get geographic coordinates from IP using geoip database""" + ip=map(int,ip.split(".")) + ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L) + + cloc = country_loc_kdb.get_base() + db = IP_country_kdb.get_base() + + d=0 + f=len(db)-1 + while (f-d) > 1: + guess = (d+f)/2 + if ip > db[guess][0]: + d = guess + else: + f = guess + s,e,c = db[guess] + if s <= ip and ip <= e: + return cloc.get(c,None) + + + + + +conf.IP_country_kdb = IPCountryKnowledgeBase(conf.IPCountry_base) +conf.country_loc_kdb = CountryLocKnowledgeBase(conf.countryLoc_base) diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/nmap.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/nmap.py new file mode 100644 index 00000000..ef064643 --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/nmap.py @@ -0,0 +1,215 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +Clone of Nmap's first generation OS fingerprinting. +""" + +import os + +from scapy.data import KnowledgeBase +from scapy.config import conf +from scapy.arch import WINDOWS + + +if WINDOWS: + conf.nmap_base=os.environ["ProgramFiles"] + "\\nmap\\nmap-os-fingerprints" +else: + conf.nmap_base ="/usr/share/nmap/nmap-os-fingerprints" + + +###################### +## nmap OS fp stuff ## +###################### + + +class NmapKnowledgeBase(KnowledgeBase): + def lazy_init(self): + try: + f=open(self.filename) + except IOError: + return + + self.base = [] + name = None + try: + for l in f: + l = l.strip() + 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 + elif l[:6] == "Class ": + 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: + self.base.append((name,sig)) + except: + self.base = None + warning("Can't read nmap database [%s](new nmap version ?)" % self.filename) + f.close() + +nmap_kdb = NmapKnowledgeBase(conf.nmap_base) + +def TCPflags2str(f): + fl="FSRPAUEC" + s="" + for i in range(len(fl)): + if f & 1: + s = fl[i]+s + f >>= 1 + return s + +def nmap_tcppacket_sig(pkt): + r = {} + if pkt is not None: +# r["Resp"] = "Y" + r["DF"] = (pkt.flags & 2) and "Y" or "N" + r["W"] = "%X" % pkt.window + r["ACK"] = pkt.ack==2 and "S++" or pkt.ack==1 and "S" or "O" + r["Flags"] = TCPflags2str(pkt.payload.flags) + r["Ops"] = "".join(map(lambda x: x[0][0],pkt.payload.options)) + else: + r["Resp"] = "N" + return r + + +def nmap_udppacket_sig(S,T): + r={} + if T is None: + r["Resp"] = "N" + else: + r["DF"] = (T.flags & 2) and "Y" or "N" + r["TOS"] = "%X" % T.tos + r["IPLEN"] = "%X" % T.len + r["RIPTL"] = "%X" % T.payload.payload.len + r["RID"] = S.id == T.payload.payload.id and "E" or "F" + r["RIPCK"] = S.chksum == T.getlayer(IPerror).chksum and "E" or T.getlayer(IPerror).chksum == 0 and "0" or "F" + r["UCK"] = S.payload.chksum == T.getlayer(UDPerror).chksum and "E" or T.getlayer(UDPerror).chksum ==0 and "0" or "F" + r["ULEN"] = "%X" % T.getlayer(UDPerror).len + r["DAT"] = T.getlayer(conf.raw_layer) is None and "E" or S.getlayer(conf.raw_layer).load == T.getlayer(conf.raw_layer).load and "E" or "F" + return r + + + +def nmap_match_one_sig(seen, ref): + c = 0 + for k in seen.keys(): + if ref.has_key(k): + if seen[k] in ref[k].split("|"): + c += 1 + if c == 0 and seen.get("Resp") == "N": + return 0.7 + else: + return 1.0*c/len(seen.keys()) + + +def nmap_sig(target, oport=80, cport=81, ucport=1): + res = {} + + tcpopt = [ ("WScale", 10), + ("NOP",None), + ("MSS", 256), + ("Timestamp",(123,0)) ] + tests = [ IP(dst=target, id=1)/TCP(seq=1, sport=5001, dport=oport, options=tcpopt, flags="CS"), + IP(dst=target, id=1)/TCP(seq=1, sport=5002, dport=oport, options=tcpopt, flags=0), + IP(dst=target, id=1)/TCP(seq=1, sport=5003, dport=oport, options=tcpopt, flags="SFUP"), + IP(dst=target, id=1)/TCP(seq=1, sport=5004, dport=oport, options=tcpopt, flags="A"), + IP(dst=target, id=1)/TCP(seq=1, sport=5005, dport=cport, options=tcpopt, flags="S"), + IP(dst=target, id=1)/TCP(seq=1, sport=5006, dport=cport, options=tcpopt, flags="A"), + IP(dst=target, id=1)/TCP(seq=1, sport=5007, dport=cport, options=tcpopt, flags="FPU"), + IP(str(IP(dst=target)/UDP(sport=5008,dport=ucport)/(300*"i"))) ] + + ans, unans = sr(tests, timeout=2) + ans += map(lambda x: (x,None), unans) + + for S,T in ans: + if S.sport == 5008: + res["PU"] = nmap_udppacket_sig(S,T) + else: + t = "T%i" % (S.sport-5000) + if T is not None and T.haslayer(ICMP): + warning("Test %s answered by an ICMP" % t) + T=None + res[t] = nmap_tcppacket_sig(T) + + return res + +def nmap_probes2sig(tests): + tests=tests.copy() + res = {} + if "PU" in tests: + res["PU"] = nmap_udppacket_sig(*tests["PU"]) + del(tests["PU"]) + for k in tests: + res[k] = nmap_tcppacket_sig(tests[k]) + return res + + +def nmap_search(sigs): + guess = 0,[] + for os,fp in nmap_kdb.get_base(): + c = 0.0 + for t in sigs.keys(): + if t in fp: + c += nmap_match_one_sig(sigs[t], fp[t]) + c /= len(sigs.keys()) + if c > guess[0]: + guess = c,[ os ] + elif c == guess[0]: + guess[1].append(os) + return guess + + +@conf.commands.register +def nmap_fp(target, oport=80, cport=81): + """nmap fingerprinting +nmap_fp(target, [oport=80,] [cport=81,]) -> list of best guesses with accuracy +""" + sigs = nmap_sig(target, oport, cport) + return nmap_search(sigs) + + +@conf.commands.register +def nmap_sig2txt(sig): + torder = ["TSeq","T1","T2","T3","T4","T5","T6","T7","PU"] + korder = ["Class", "gcd", "SI", "IPID", "TS", + "Resp", "DF", "W", "ACK", "Flags", "Ops", + "TOS", "IPLEN", "RIPTL", "RID", "RIPCK", "UCK", "ULEN", "DAT" ] + txt=[] + for i in sig.keys(): + if i not in torder: + torder.append(i) + for t in torder: + sl = sig.get(t) + if sl is None: + continue + s = [] + for k in korder: + v = sl.get(k) + if v is None: + continue + s.append("%s=%s"%(k,v)) + txt.append("%s(%s)" % (t, "%".join(s))) + return "\n".join(txt) + + + + diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/p0f.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/p0f.py new file mode 100644 index 00000000..d051779d --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/p0f.py @@ -0,0 +1,542 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +Clone of p0f passive OS fingerprinting +""" + +from scapy.data import KnowledgeBase +from scapy.config import conf +from scapy.layers.inet import IP, TCP, TCPOptions +from scapy.packet import NoPayload + +conf.p0f_base ="/etc/p0f/p0f.fp" +conf.p0fa_base ="/etc/p0f/p0fa.fp" +conf.p0fr_base ="/etc/p0f/p0fr.fp" +conf.p0fo_base ="/etc/p0f/p0fo.fp" + + +############### +## p0f stuff ## +############### + +# File format (according to p0f.fp) : +# +# wwww:ttt:D:ss:OOO...:QQ:OS:Details +# +# wwww - window size +# ttt - initial TTL +# D - don't fragment bit (0=unset, 1=set) +# ss - overall SYN packet size +# OOO - option value and order specification +# QQ - quirks list +# OS - OS genre +# details - OS description + +class p0fKnowledgeBase(KnowledgeBase): + def __init__(self, filename): + KnowledgeBase.__init__(self, filename) + #self.ttl_range=[255] + def lazy_init(self): + try: + f=open(self.filename) + except IOError: + warning("Can't open base %s" % self.filename) + return + try: + self.base = [] + for l in f: + if l[0] in ["#","\n"]: + continue + l = tuple(l.split(":")) + if len(l) < 8: + continue + def a2i(x): + if x.isdigit(): + return int(x) + return x + li = map(a2i, l[1:4]) + #if li[0] not in self.ttl_range: + # self.ttl_range.append(li[0]) + # self.ttl_range.sort() + self.base.append((l[0], li[0], li[1], li[2], l[4], l[5], l[6], l[7][:-1])) + except: + warning("Can't parse p0f database (new p0f version ?)") + self.base = None + f.close() + +p0f_kdb = p0fKnowledgeBase(conf.p0f_base) +p0fa_kdb = p0fKnowledgeBase(conf.p0fa_base) +p0fr_kdb = p0fKnowledgeBase(conf.p0fr_base) +p0fo_kdb = p0fKnowledgeBase(conf.p0fo_base) + +def p0f_selectdb(flags): + # tested flags: S, R, A + if flags & 0x16 == 0x2: + # SYN + return p0f_kdb + elif flags & 0x16 == 0x12: + # SYN/ACK + return p0fa_kdb + elif flags & 0x16 in [ 0x4, 0x14 ]: + # RST RST/ACK + return p0fr_kdb + elif flags & 0x16 == 0x10: + # ACK + return p0fo_kdb + else: + return None + +def packet2p0f(pkt): + pkt = pkt.copy() + pkt = pkt.__class__(str(pkt)) + 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") + #if pkt.payload.flags & 0x7 != 0x02: #S,!F,!R + # raise TypeError("Not a SYN or SYN/ACK packet") + + db = p0f_selectdb(pkt.payload.flags) + + #t = p0f_kdb.ttl_range[:] + #t += [pkt.ttl] + #t.sort() + #ttl=t[t.index(pkt.ttl)+1] + ttl = pkt.ttl + + df = (pkt.flags & 2) / 2 + ss = len(pkt) + # from p0f/config.h : PACKET_BIG = 100 + if ss > 100: + if db == p0fr_kdb: + # p0fr.fp: "Packet size may be wildcarded. The meaning of + # wildcard is, however, hardcoded as 'size > + # PACKET_BIG'" + ss = '*' + else: + ss = 0 + if db == p0fo_kdb: + # p0fo.fp: "Packet size MUST be wildcarded." + ss = '*' + + ooo = "" + mss = -1 + qqT = False + qqP = False + #qqBroken = False + ilen = (pkt.payload.dataofs << 2) - 20 # from p0f.c + for option in pkt.payload.options: + ilen -= 1 + if option[0] == "MSS": + ooo += "M" + str(option[1]) + "," + mss = option[1] + # FIXME: qqBroken + ilen -= 3 + elif option[0] == "WScale": + ooo += "W" + str(option[1]) + "," + # FIXME: qqBroken + ilen -= 2 + elif option[0] == "Timestamp": + if option[1][0] == 0: + ooo += "T0," + else: + ooo += "T," + if option[1][1] != 0: + qqT = True + ilen -= 9 + elif option[0] == "SAckOK": + ooo += "S," + ilen -= 1 + elif option[0] == "NOP": + ooo += "N," + elif option[0] == "EOL": + ooo += "E," + if ilen > 0: + qqP = True + else: + if type(option[0]) is str: + ooo += "?%i," % TCPOptions[1][option[0]] + else: + ooo += "?%i," % option[0] + # FIXME: ilen + ooo = ooo[:-1] + if ooo == "": ooo = "." + + win = pkt.payload.window + if mss != -1: + if mss != 0 and win % mss == 0: + win = "S" + str(win/mss) + elif win % (mss + 40) == 0: + win = "T" + str(win/(mss+40)) + win = str(win) + + qq = "" + + if db == p0fr_kdb: + if pkt.payload.flags & 0x10 == 0x10: + # p0fr.fp: "A new quirk, 'K', is introduced to denote + # RST+ACK packets" + qq += "K" + # The two next cases should also be only for p0f*r*, but although + # it's not documented (or I have not noticed), p0f seems to + # support the '0' and 'Q' quirks on any databases (or at the least + # "classical" p0f.fp). + if pkt.payload.seq == pkt.payload.ack: + # p0fr.fp: "A new quirk, 'Q', is used to denote SEQ number + # equal to ACK number." + qq += "Q" + if pkt.payload.seq == 0: + # p0fr.fp: "A new quirk, '0', is used to denote packets + # with SEQ number set to 0." + qq += "0" + if qqP: + qq += "P" + if pkt.id == 0: + qq += "Z" + if pkt.options != []: + qq += "I" + if pkt.payload.urgptr != 0: + qq += "U" + if pkt.payload.reserved != 0: + qq += "X" + if pkt.payload.ack != 0: + qq += "A" + if qqT: + qq += "T" + if db == p0fo_kdb: + if pkt.payload.flags & 0x20 != 0: + # U + # p0fo.fp: "PUSH flag is excluded from 'F' quirk checks" + qq += "F" + else: + if pkt.payload.flags & 0x28 != 0: + # U or P + qq += "F" + if db != p0fo_kdb and not isinstance(pkt.payload.payload, NoPayload): + # p0fo.fp: "'D' quirk is not checked for." + qq += "D" + # FIXME : "!" - broken options segment: not handled yet + + if qq == "": + qq = "." + + return (db, (win, ttl, df, ss, ooo, qq)) + +def p0f_correl(x,y): + d = 0 + # wwww can be "*" or "%nn". "Tnn" and "Snn" should work fine with + # the x[0] == y[0] test. + d += (x[0] == y[0] or y[0] == "*" or (y[0][0] == "%" and x[0].isdigit() and (int(x[0]) % int(y[0][1:])) == 0)) + # ttl + d += (y[1] >= x[1] and y[1] - x[1] < 32) + for i in [2, 5]: + d += (x[i] == y[i] or y[i] == '*') + # '*' has a special meaning for ss + d += x[3] == y[3] + xopt = x[4].split(",") + yopt = y[4].split(",") + if len(xopt) == len(yopt): + same = True + for i in range(len(xopt)): + if not (xopt[i] == yopt[i] or + (len(yopt[i]) == 2 and len(xopt[i]) > 1 and + yopt[i][1] == "*" and xopt[i][0] == yopt[i][0]) or + (len(yopt[i]) > 2 and len(xopt[i]) > 1 and + yopt[i][1] == "%" and xopt[i][0] == yopt[i][0] and + int(xopt[i][1:]) % int(yopt[i][2:]) == 0)): + same = False + break + if same: + d += len(xopt) + return d + + +@conf.commands.register +def p0f(pkt): + """Passive OS fingerprinting: which OS emitted this TCP packet ? +p0f(packet) -> accuracy, [list of guesses] +""" + db, sig = packet2p0f(pkt) + if db: + pb = db.get_base() + else: + pb = [] + if not pb: + warning("p0f base empty.") + return [] + #s = len(pb[0][0]) + r = [] + max = len(sig[4].split(",")) + 5 + for b in pb: + d = p0f_correl(sig,b) + if d == max: + r.append((b[6], b[7], b[1] - pkt[IP].ttl)) + return r + +def prnp0f(pkt): + # we should print which DB we use + try: + r = p0f(pkt) + except: + return + if r == []: + r = ("UNKNOWN", "[" + ":".join(map(str, packet2p0f(pkt)[1])) + ":?:?]", None) + else: + r = r[0] + uptime = None + try: + uptime = pkt2uptime(pkt) + except: + pass + if uptime == 0: + uptime = None + res = pkt.sprintf("%IP.src%:%TCP.sport% - " + r[0] + " " + r[1]) + if uptime is not None: + res += pkt.sprintf(" (up: " + str(uptime/3600) + " hrs)\n -> %IP.dst%:%TCP.dport% (%TCP.flags%)") + else: + res += pkt.sprintf("\n -> %IP.dst%:%TCP.dport% (%TCP.flags%)") + if r[2] is not None: + res += " (distance " + str(r[2]) + ")" + print res + +@conf.commands.register +def pkt2uptime(pkt, HZ=100): + """Calculate the date the machine which emitted the packet booted using TCP timestamp +pkt2uptime(pkt, [HZ=100])""" + if not isinstance(pkt, Packet): + raise TypeError("Not a TCP packet") + if isinstance(pkt,NoPayload): + raise TypeError("Not a TCP packet") + if not isinstance(pkt, TCP): + return pkt2uptime(pkt.payload) + for opt in pkt.options: + if opt[0] == "Timestamp": + #t = pkt.time - opt[1][0] * 1.0/HZ + #return time.ctime(t) + t = opt[1][0] / HZ + return t + raise TypeError("No timestamp option") + +def p0f_impersonate(pkt, osgenre=None, osdetails=None, signature=None, + extrahops=0, mtu=1500, uptime=None): + """Modifies pkt so that p0f will think it has been sent by a +specific OS. If osdetails is None, then we randomly pick up a +personality matching osgenre. If osgenre and signature are also None, +we use a local signature (using p0f_getlocalsigs). If signature is +specified (as a tuple), we use the signature. + +For now, only TCP Syn packets are supported. +Some specifications of the p0f.fp file are not (yet) implemented.""" + pkt = pkt.copy() + #pkt = pkt.__class__(str(pkt)) + 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") + + if uptime is None: + uptime = random.randint(120,100*60*60*24*365) + + db = p0f_selectdb(pkt.payload.flags) + if osgenre: + pb = db.get_base() + if pb is None: + pb = [] + pb = filter(lambda x: x[6] == osgenre, pb) + if osdetails: + pb = filter(lambda x: x[7] == osdetails, pb) + elif signature: + pb = [signature] + else: + pb = p0f_getlocalsigs()[db] + if db == p0fr_kdb: + # 'K' quirk <=> RST+ACK + if pkt.payload.flags & 0x4 == 0x4: + pb = filter(lambda x: 'K' in x[5], pb) + else: + pb = filter(lambda x: 'K' not in x[5], pb) + if not pb: + raise Scapy_Exception("No match in the p0f database") + pers = pb[random.randint(0, len(pb) - 1)] + + # options (we start with options because of MSS) + ## TODO: let the options already set if they are valid + options = [] + if pers[4] != '.': + for opt in pers[4].split(','): + if opt[0] == 'M': + # MSS might have a maximum size because of window size + # specification + if pers[0][0] == 'S': + maxmss = (2L**16-1) / int(pers[0][1:]) + else: + maxmss = (2L**16-1) + # If we have to randomly pick up a value, we cannot use + # scapy RandXXX() functions, because the value has to be + # set in case we need it for the window size value. That's + # why we use random.randint() + if opt[1:] == '*': + options.append(('MSS', random.randint(1,maxmss))) + elif opt[1] == '%': + coef = int(opt[2:]) + options.append(('MSS', coef*random.randint(1,maxmss/coef))) + else: + options.append(('MSS', int(opt[1:]))) + elif opt[0] == 'W': + if opt[1:] == '*': + options.append(('WScale', RandByte())) + elif opt[1] == '%': + coef = int(opt[2:]) + options.append(('WScale', coef*RandNum(min=1, + max=(2L**8-1)/coef))) + else: + options.append(('WScale', int(opt[1:]))) + elif opt == 'T0': + options.append(('Timestamp', (0, 0))) + elif opt == 'T': + if 'T' in pers[5]: + # FIXME: RandInt() here does not work (bug (?) in + # TCPOptionsField.m2i often raises "OverflowError: + # long int too large to convert to int" in: + # oval = struct.pack(ofmt, *oval)" + # Actually, this is enough to often raise the error: + # struct.pack('I', RandInt()) + options.append(('Timestamp', (uptime, random.randint(1,2**32-1)))) + else: + options.append(('Timestamp', (uptime, 0))) + elif opt == 'S': + options.append(('SAckOK', '')) + elif opt == 'N': + options.append(('NOP', None)) + elif opt == 'E': + options.append(('EOL', None)) + elif opt[0] == '?': + if int(opt[1:]) in TCPOptions[0]: + optname = TCPOptions[0][int(opt[1:])][0] + optstruct = TCPOptions[0][int(opt[1:])][1] + options.append((optname, + struct.unpack(optstruct, + RandString(struct.calcsize(optstruct))._fix()))) + else: + options.append((int(opt[1:]), '')) + ## FIXME: qqP not handled + else: + warning("unhandled TCP option " + opt) + pkt.payload.options = options + + # window size + if pers[0] == '*': + pkt.payload.window = RandShort() + elif pers[0].isdigit(): + pkt.payload.window = int(pers[0]) + elif pers[0][0] == '%': + coef = int(pers[0][1:]) + pkt.payload.window = coef * RandNum(min=1,max=(2L**16-1)/coef) + elif pers[0][0] == 'T': + pkt.payload.window = mtu * int(pers[0][1:]) + elif pers[0][0] == 'S': + ## needs MSS set + MSS = filter(lambda x: x[0] == 'MSS', options) + if not filter(lambda x: x[0] == 'MSS', options): + raise Scapy_Exception("TCP window value requires MSS, and MSS option not set") + pkt.payload.window = filter(lambda x: x[0] == 'MSS', options)[0][1] * int(pers[0][1:]) + else: + raise Scapy_Exception('Unhandled window size specification') + + # ttl + pkt.ttl = pers[1]-extrahops + # DF flag + pkt.flags |= (2 * pers[2]) + ## FIXME: ss (packet size) not handled (how ? may be with D quirk + ## if present) + # Quirks + if pers[5] != '.': + for qq in pers[5]: + ## FIXME: not handled: P, I, X, ! + # T handled with the Timestamp option + if qq == 'Z': pkt.id = 0 + elif qq == 'U': pkt.payload.urgptr = RandShort() + elif qq == 'A': pkt.payload.ack = RandInt() + elif qq == 'F': + if db == p0fo_kdb: + pkt.payload.flags |= 0x20 # U + else: + pkt.payload.flags |= RandChoice(8, 32, 40) #P / U / PU + elif qq == 'D' and db != p0fo_kdb: + pkt /= conf.raw_layer(load=RandString(random.randint(1, 10))) # XXX p0fo.fp + elif qq == 'Q': pkt.payload.seq = pkt.payload.ack + #elif qq == '0': pkt.payload.seq = 0 + #if db == p0fr_kdb: + # '0' quirk is actually not only for p0fr.fp (see + # packet2p0f()) + if '0' in pers[5]: + pkt.payload.seq = 0 + elif pkt.payload.seq == 0: + pkt.payload.seq = RandInt() + + while pkt.underlayer: + pkt = pkt.underlayer + return pkt + +def p0f_getlocalsigs(): + """This function returns a dictionary of signatures indexed by p0f +db (e.g., p0f_kdb, p0fa_kdb, ...) for the local TCP/IP stack. + +You need to have your firewall at least accepting the TCP packets +from/to a high port (30000 <= x <= 40000) on your loopback interface. + +Please note that the generated signatures come from the loopback +interface and may (are likely to) be different than those generated on +"normal" interfaces.""" + pid = os.fork() + port = random.randint(30000, 40000) + if pid > 0: + # parent: sniff + result = {} + def addresult(res): + # TODO: wildcard window size in some cases? and maybe some + # other values? + if res[0] not in result: + result[res[0]] = [res[1]] + else: + if res[1] not in result[res[0]]: + result[res[0]].append(res[1]) + # XXX could we try with a "normal" interface using other hosts + iface = conf.route.route('127.0.0.1')[0] + # each packet is seen twice: S + RA, S + SA + A + FA + A + # XXX are the packets also seen twice on non Linux systems ? + count=14 + pl = sniff(iface=iface, filter='tcp and port ' + str(port), count = count, timeout=3) + map(addresult, map(packet2p0f, pl)) + os.waitpid(pid,0) + elif pid < 0: + log_runtime.error("fork error") + else: + # child: send + # XXX erk + time.sleep(1) + s1 = socket.socket(socket.AF_INET, type = socket.SOCK_STREAM) + # S & RA + try: + s1.connect(('127.0.0.1', port)) + except socket.error: + pass + # S, SA, A, FA, A + s1.bind(('127.0.0.1', port)) + s1.connect(('127.0.0.1', port)) + # howto: get an RST w/o ACK packet + s1.close() + os._exit(0) + return result + diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/queso.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/queso.py new file mode 100644 index 00000000..ebc5486e --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/queso.py @@ -0,0 +1,113 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +Clone of queso OS fingerprinting +""" + +from scapy.data import KnowledgeBase +from scapy.config import conf +from scapy.layers.inet import IP,TCP +#from + +conf.queso_base ="/etc/queso.conf" + + +################# +## Queso stuff ## +################# + + +def quesoTCPflags(flags): + if flags == "-": + return "-" + flv = "FSRPAUXY" + v = 0 + for i in flags: + v |= 2**flv.index(i) + return "%x" % v + +class QuesoKnowledgeBase(KnowledgeBase): + def lazy_init(self): + try: + f = open(self.filename) + except IOError: + return + self.base = {} + p = None + try: + for l in f: + l = l.strip() + if not l or l[0] == ';': + continue + if l[0] == '*': + if p is not None: + 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: + p[""] = name + except: + self.base = None + warning("Can't load queso base [%s]", self.filename) + f.close() + + +queso_kdb = QuesoKnowledgeBase(conf.queso_base) + + +def queso_sig(target, dport=80, timeout=3): + p = queso_kdb.get_base() + ret = [] + for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]: + ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()), + timeout=timeout, verbose=0) + if len(ans) == 0: + rs = "- - - -" + else: + s,r = ans[0] + rs = "%i" % (r.seq != 0) + if not r.ack: + r += " 0" + elif r.ack-s.seq > 666: + rs += " R" % 0 + else: + rs += " +%i" % (r.ack-s.seq) + rs += " %X" % r.window + rs += " %x" % r.payload.flags + ret.append(rs) + return ret + +def queso_search(sig): + p = queso_kdb.get_base() + sig.reverse() + ret = [] + try: + while sig: + s = sig.pop() + p = p[s] + if p.has_key(""): + ret.append(p[""]) + except KeyError: + pass + return ret + + +@conf.commands.register +def queso(*args,**kargs): + """Queso OS fingerprinting +queso(target, dport=80, timeout=3)""" + return queso_search(queso_sig(*args, **kargs)) + + diff --git a/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/voip.py b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/voip.py new file mode 100644 index 00000000..70000a54 --- /dev/null +++ b/scripts/external_libs/scapy-2.3.1/python2/scapy/modules/voip.py @@ -0,0 +1,149 @@ +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## Copyright (C) Philippe Biondi +## This program is published under a GPLv2 license + +""" +VoIP (Voice over IP) related functions +""" + +import os +################### +## Testing stuff ## +################### + +from fcntl import fcntl +from scapy.sendrecv import sniff +from scapy.layers.inet import IP,UDP +from scapy.layers.rtp import RTP +from scapy.utils import get_temp_file + + +def merge(x,y,sample_size=2): + if len(x) > len(y): + y += "\x00"*(len(x)-len(y)) + elif len(x) < len(y): + x += "\x00"*(len(y)-len(x)) + m = "" + ss=sample_size + for i in range(len(x)/ss): + m += x[ss*i:ss*(i+1)]+y[ss*i:ss*(i+1)] + return m +# return "".join(map(str.__add__, x, y)) + + +def voip_play(s1,list=None,**kargs): + FIFO=get_temp_file() + FIFO1=FIFO % 1 + FIFO2=FIFO % 2 + + os.mkfifo(FIFO1) + os.mkfifo(FIFO2) + try: + os.system("soxmix -t .ul %s -t .ul %s -t ossdsp /dev/dsp &" % (FIFO1,FIFO2)) + + c1=open(FIFO1,"w", 4096) + c2=open(FIFO2,"w", 4096) + fcntl.fcntl(c1.fileno(),fcntl.F_SETFL, os.O_NONBLOCK) + fcntl.fcntl(c2.fileno(),fcntl.F_SETFL, os.O_NONBLOCK) + + # dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp") + def play(pkt,last=[]): + if not pkt: + return + if not pkt.haslayer(UDP): + return + ip=pkt.getlayer(IP) + if s1 in [ip.src, ip.dst]: + if not last: + last.append(pkt) + return + load=last.pop() + # x1 = load.load[12:] + c1.write(load.load[12:]) + if load.getlayer(IP).src == ip.src: + # x2 = "" + c2.write("\x00"*len(load.load[12:])) + last.append(pkt) + else: + # x2 = pkt.load[:12] + c2.write(pkt.load[12:]) + # dsp.write(merge(x1,x2)) + + if list is None: + sniff(store=0, prn=play, **kargs) + else: + for p in list: + play(p) + finally: + os.unlink(FIFO1) + os.unlink(FIFO2) + + + +def voip_play1(s1,list=None,**kargs): + + + dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp") + def play(pkt): + if not pkt: + return + if not pkt.haslayer(UDP): + return + ip=pkt.getlayer(IP) + if s1 in [ip.src, ip.dst]: + dsp.write(pkt.getlayer(conf.raw_layer).load[12:]) + try: + if list is None: + sniff(store=0, prn=play, **kargs) + else: + for p in list: + play(p) + finally: + dsp.close() + rd.close() + +def voip_play2(s1,**kargs): + dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp") + def play(pkt,last=[]): + if not pkt: + return + if not pkt.haslayer(UDP): + return + ip=pkt.getlayer(IP) + if s1 in [ip.src, ip.dst]: + if not last: + last.append(pkt) + return + load=last.pop() + x1 = load.load[12:] +# c1.write(load.load[12:]) + if load.getlayer(IP).src == ip.src: + x2 = "" +# c2.write("\x00"*len(load.load[12:])) + last.append(pkt) + else: + x2 = pkt.load[:12] +# c2.write(pkt.load[12:]) + dsp.write(merge(x1,x2)) + + sniff(store=0, prn=play, **kargs) + +def voip_play3(lst=None,**kargs): + dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp") + try: + def play(pkt, dsp=dsp): + if pkt and pkt.haslayer(UDP) and pkt.haslayer(conf.raw_layer): + dsp.write(pkt.getlayer(RTP).load) + if lst is None: + sniff(store=0, prn=play, **kargs) + else: + for p in lst: + play(p) + finally: + try: + dsp.close() + rd.close() + except: + pass + -- cgit