1% Tests for Scapy's p0f module. 2 3~ p0f 4 5+ Basic p0f module tests 6 7= Module loading 8load_module('p0f') 9 10= Fetch database 11~ netaccess 12 13try: 14 from urllib.request import urlopen 15except ImportError: 16 from urllib2 import urlopen 17 18for i in range(10): 19 try: 20 open("p0f.fp", 'wb').write(urlopen('https://raw.githubusercontent.com/p0f/p0f/e8b924ae7fa099a3a5fe7def0ce3e397fd9a7137/p0f.fp').read()) 21 break 22 except: 23 raise 24 25conf.p0f_base = "p0f.fp" 26p0fdb.reload(conf.p0f_base) 27 28+ Default tests 29 30= Test TCP p0f, SYN - Windows 31~ netaccess 32 33pkt = IP(b'E\x00\x004Se@\x00\x80\x06\x93?\n\x00\x00\x14\n\x00\x00\x0c\xc3\x08\x01\xbb\xcf\xb4\xbb\\\x00\x00\x00\x00\x80\x02 \x00\xeb\x1b\x00\x00\x02\x04\x05\xb4\x01\x03\x03\x08\x01\x01\x04\x02') 34assert p0f(pkt) == (('s', 'win', 'Windows', '7 or 8'), 0, False) 35 36= Test TCP p0f, SYN - Linux 37~ netaccess 38 39pkt = IP(b"E\x10\x00<A0@\x00@\x06t\xdd\xc0\xa8\x01\x8c\xc0\xa8\x01\xc2\xdd\xb8\x00\x17\xda\xcf!\xd5\x00\x00\x00\x00\xa0\x02\x16\xd0q\x10\x00\x00\x02\x04\x05\xb4\x04\x02\x08\n\x00'`\xe5\x00\x00\x00\x00\x01\x03\x03\x07") 40assert p0f(pkt) == (('s', 'unix', 'Linux', '2.6.x'), 0, False) 41 42= Test TCP p0f, SYN - IPv6 FreeBSD 43~ netaccess 44 45pkt = IPv6(hlim=64) / TCP(seq=1, window=65535, options=[("MSS", 150), ("NOP", None), ("WScale", 6), ("SAckOK", ""), ("Timestamp", (12345, 0))]) 46assert p0f(pkt) == (('s', 'unix', 'FreeBSD', '9.x or newer'), 0, False) 47 48= Test TCP p0f, SYN-ACK - Linux 49~ netaccess 50 51pkt = IP(b'E\x00\x00<\x00\x00@\x008\x06N;?t\xf3a\xc0\xa8\x01\x03\x00P\xe5\xc0\xa3\xc4\x80\x9f\xe5\x94=\xab\xa0\x12\x16\xa0N\x07\x00\x00\x02\x04\x05\xb4\x04\x02\x08\n\x8d\x9d\x9d\xfa\x00\x17\x95e\x01\x03\x03\x05') 52assert p0f(pkt) == (('s', 'unix', 'Linux', '2.6.x'), 8, False) 53 54= Test HTTP p0f, request - wget 55~ netaccess 56 57pkt = IP(b'E\x00\x00\xba\xcb]@\x00@\x06(d\xc0\xa8\x01\x8c\xae\x8f\xd5\xb8\xe1N\x00P\x8eP\x19\x02\xc7R\x9d\x89\x80\x18\x00.G)\x00\x00\x01\x01\x08\n\x00!\xd2_1\xc7\xbaHGET /images/layout/logo.png HTTP/1.0\r\nUser-Agent: Wget/1.12 (linux-gnu)\r\nAccept: */*\r\nHost: packetlife.net\r\nConnection: Keep-Alive\r\n\r\n') 58assert p0f(pkt) == (('s', '!', 'wget', '', ('@unix', 'Windows')), False) 59 60= Test HTTP p0f, response - nginx 61~ netaccess 62 63pkt = IP(b"E\x00\x05\xdc'\xde@\x00\xfb\x06\x0b\xc1\xae\x8f\xd5\xb8\xc0\xa8\x01\x8c\x00P\xe1N\xc7R\x9d\x89\x8eP\x19\x88\x80\x10\x00lS\xc4\x00\x00\x01\x01\x08\n1\xc7\xbaT\x00!\xd2_HTTP/1.1 200 OK\r\nServer: nginx/0.8.53\r\nDate: Tue, 01 Mar 2011 20:45:16 GMT\r\nContent-Type: image/png\r\nContent-Length: 21684\r\nLast-Modified: Fri, 21 Jan 2011 03:41:14 GMT\r\nConnection: keep-alive\r\nKeep-Alive: timeout=20\r\nExpires: Wed, 29 Feb 2012 20:45:16 GMT\r\nCache-Control: max-age=31536000\r\nCache-Control: public\r\nVary: Accept-Encoding\r\nAccept-Ranges: bytes\r\n\r\n") 64assert p0f(pkt) == (('s', '!', 'nginx', '1.x', ('@unix',)), False) 65 66= Test MTU p0f 67~ netaccess 68 69pkt = IP(b'E\x00\x004Se@\x00\x80\x06\x93?\n\x00\x00\x14\n\x00\x00\x0c\xc3\x08\x01\xbb\xcf\xb4\xbb\\\x00\x00\x00\x00\x80\x02 \x00\xeb\x1b\x00\x00\x02\x04\x05\xb4\x01\x03\x03\x08\x01\x01\x04\x02') 70assert fingerprint_mtu(pkt) == "Ethernet or modem" 71 72 73+ Tests for p0f_impersonate 74 75= Check that the impersonated packet is properly detected by p0f 76~ netaccess 77 78pkt = p0f_impersonate(IP()/TCP(), osgenre="Linux", osdetails="3.11 and newer") 79assert p0f(pkt) == (("s", "unix", "Linux", "3.11 and newer"), 0, False) 80 81= Check incidence of MSS value on linux version detection 82~ netaccess 83 84pkt = IP(ttl=64, flags=2)/TCP(options=[('MSS', 14), ('SAckOK', ''), ('Timestamp', (2638474259, 0)), ('NOP', None), ('WScale', 7)], window=280, seq=3964706621, flags=2) 85assert p0f(pkt) == (('g', 'unix', 'Linux', '2.2.x-3.x'), 0, False) 86 87pkt[TCP].options = [('MSS', 100), ('SAckOK', ''), ('Timestamp', (2638474259, 0)), ('NOP', None), ('WScale', 7)] 88pkt[TCP].window = 100*20 89assert p0f(pkt) == (("s", "unix", "Linux", "3.11 and newer"), 0, False) 90 91= Impersonate when window size must be multiple of some integer 92sig = "*:64:0:1460:%8192,0:mss,nop,ws::0" 93pkt = p0f_impersonate(IP()/TCP(), signature=sig) 94assert pkt[TCP].window % 8192 == 0 95 96= Impersonate when window size must be multiple of mss 97sig = "*:64:0:1024:mss*4,0:mss::0" 98pkt = p0f_impersonate(IP()/TCP(), signature=sig) 99assert (pkt[TCP].window // 4) == 1024 100 101= Impersonate when the following quirks are present: seq-,ack-,pushf+,urgf+ 102sig = "*:64:0:1460:8192,0:mss:seq-,ack-,pushf+,urgf+:0" 103pkt = p0f_impersonate(IP()/TCP(seq=1, ack=1, flags="S"), signature=sig) 104tcp = pkt[TCP] 105assert pkt[TCP].seq == pkt[TCP].ack == 0 106assert pkt[TCP].flags.A and pkt[TCP].flags.P and pkt[TCP].flags.U 107 108= Use valid option values from original packet 109sig = "*:64:0:*:8192,*:mss,ws,ts::0" 110opts = [("MSS", 1400), ("WScale", 3), ("Timestamp", (97256, 0))] 111pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig) 112assert pkt[TCP].options == opts 113 114= Discard invalid options values 115sig = "*:64:0:1000:8192,5:mss,ws::0" 116opts = [("MSS", 1400), ("WScale", 3)] 117pkt = p0f_impersonate(IP()/TCP(options=opts), signature=sig) 118assert pkt[TCP].options[0][1] == 1000 119assert pkt[TCP].options[1][1] == 5 120 121+ Clear temp files 122 123= Remove fp files 124def _rem(f): 125 try: 126 os.remove(f) 127 except: 128 pass 129 130_rem("p0f.fp") 131