1 ## This file is part of Scapy 2 ## See http://www.secdev.org/projects/scapy for more informations 3 ## Copyright (C) Philippe Biondi <phil (at] secdev.org> 4 ## This program is published under a GPLv2 license 5 6 """ 7 Clone of queso OS fingerprinting 8 """ 9 10 from scapy.data import KnowledgeBase 11 from scapy.config import conf 12 from scapy.layers.inet import IP,TCP 13 from scapy.error import warning 14 from scapy.volatile import RandInt 15 from scapy.sendrecv import sr 16 #from 17 18 conf.queso_base ="/etc/queso.conf" 19 20 21 ################# 22 ## Queso stuff ## 23 ################# 24 25 26 def quesoTCPflags(flags): 27 if flags == "-": 28 return "-" 29 flv = "FSRPAUXY" 30 v = 0 31 for i in flags: 32 v |= 2**flv.index(i) 33 return "%x" % v 34 35 class QuesoKnowledgeBase(KnowledgeBase): 36 def lazy_init(self): 37 try: 38 f = open(self.filename) 39 except IOError: 40 return 41 self.base = {} 42 p = None 43 try: 44 for l in f: 45 l = l.strip() 46 if not l or l[0] == ';': 47 continue 48 if l[0] == '*': 49 if p is not None: 50 p[""] = name 51 name = l[1:].strip() 52 p = self.base 53 continue 54 if l[0] not in list("0123456"): 55 continue 56 res = l[2:].split() 57 res[-1] = quesoTCPflags(res[-1]) 58 res = " ".join(res) 59 if res not in p: 60 p[res] = {} 61 p = p[res] 62 if p is not None: 63 p[""] = name 64 except: 65 self.base = None 66 warning("Can't load queso base [%s]", self.filename) 67 f.close() 68 69 70 queso_kdb = QuesoKnowledgeBase(conf.queso_base) 71 72 73 def queso_sig(target, dport=80, timeout=3): 74 p = queso_kdb.get_base() 75 ret = [] 76 for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]: 77 ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()), 78 timeout=timeout, verbose=0) 79 if len(ans) == 0: 80 rs = "- - - -" 81 else: 82 s,r = ans[0] 83 rs = "%i" % (r.seq != 0) 84 if not r.ack: 85 r += " 0" 86 elif r.ack-s.seq > 666: 87 rs += " R" % 0 88 else: 89 rs += " +%i" % (r.ack-s.seq) 90 rs += " %X" % r.window 91 rs += " %x" % r.payload.flags 92 ret.append(rs) 93 return ret 94 95 def queso_search(sig): 96 p = queso_kdb.get_base() 97 sig.reverse() 98 ret = [] 99 try: 100 while sig: 101 s = sig.pop() 102 p = p[s] 103 if "" in p: 104 ret.append(p[""]) 105 except KeyError: 106 pass 107 return ret 108 109 110 @conf.commands.register 111 def queso(*args,**kargs): 112 """Queso OS fingerprinting 113 queso(target, dport=80, timeout=3)""" 114 return queso_search(queso_sig(*args, **kargs)) 115 116 117