1*7dc08ffcSJunyu Lai## This file is part of Scapy 2*7dc08ffcSJunyu Lai## See http://www.secdev.org/projects/scapy for more informations 3*7dc08ffcSJunyu Lai## Copyright (C) Philippe Biondi <[email protected]> 4*7dc08ffcSJunyu Lai## This program is published under a GPLv2 license 5*7dc08ffcSJunyu Lai 6*7dc08ffcSJunyu Lai""" 7*7dc08ffcSJunyu LaiIPv4 (Internet Protocol v4). 8*7dc08ffcSJunyu Lai""" 9*7dc08ffcSJunyu Lai 10*7dc08ffcSJunyu Laifrom __future__ import absolute_import 11*7dc08ffcSJunyu Laifrom __future__ import print_function 12*7dc08ffcSJunyu Laiimport os, time, struct, re, socket, types 13*7dc08ffcSJunyu Laifrom select import select 14*7dc08ffcSJunyu Laifrom collections import defaultdict 15*7dc08ffcSJunyu Lai 16*7dc08ffcSJunyu Laifrom scapy.utils import checksum,inet_aton,inet_ntoa 17*7dc08ffcSJunyu Laifrom scapy.base_classes import Gen 18*7dc08ffcSJunyu Laifrom scapy.data import * 19*7dc08ffcSJunyu Laifrom scapy.layers.l2 import * 20*7dc08ffcSJunyu Laifrom scapy.compat import * 21*7dc08ffcSJunyu Laifrom scapy.config import conf 22*7dc08ffcSJunyu Laifrom scapy.consts import WINDOWS 23*7dc08ffcSJunyu Laifrom scapy.fields import * 24*7dc08ffcSJunyu Laifrom scapy.packet import * 25*7dc08ffcSJunyu Laifrom scapy.volatile import * 26*7dc08ffcSJunyu Laifrom scapy.sendrecv import sr,sr1,srp1 27*7dc08ffcSJunyu Laifrom scapy.plist import PacketList,SndRcvList 28*7dc08ffcSJunyu Laifrom scapy.automaton import Automaton,ATMT 29*7dc08ffcSJunyu Laifrom scapy.error import warning 30*7dc08ffcSJunyu Laifrom scapy.utils import whois 31*7dc08ffcSJunyu Lai 32*7dc08ffcSJunyu Laiimport scapy.as_resolvers 33*7dc08ffcSJunyu Lai 34*7dc08ffcSJunyu Laifrom scapy.arch import plt, MATPLOTLIB_INLINED, MATPLOTLIB_DEFAULT_PLOT_KARGS 35*7dc08ffcSJunyu Laiimport scapy.modules.six as six 36*7dc08ffcSJunyu Laifrom scapy.modules.six.moves import range 37*7dc08ffcSJunyu Lai 38*7dc08ffcSJunyu Lai#################### 39*7dc08ffcSJunyu Lai## IP Tools class ## 40*7dc08ffcSJunyu Lai#################### 41*7dc08ffcSJunyu Lai 42*7dc08ffcSJunyu Laiclass IPTools(object): 43*7dc08ffcSJunyu Lai """Add more powers to a class with an "src" attribute.""" 44*7dc08ffcSJunyu Lai __slots__ = [] 45*7dc08ffcSJunyu Lai def whois(self): 46*7dc08ffcSJunyu Lai """whois the source and print the output""" 47*7dc08ffcSJunyu Lai if WINDOWS: 48*7dc08ffcSJunyu Lai print(whois(self.src)) 49*7dc08ffcSJunyu Lai else: 50*7dc08ffcSJunyu Lai os.system("whois %s" % self.src) 51*7dc08ffcSJunyu Lai def _ttl(self): 52*7dc08ffcSJunyu Lai """Returns ttl or hlim, depending on the IP version""" 53*7dc08ffcSJunyu Lai return self.hlim if isinstance(self, scapy.layers.inet6.IPv6) else self.ttl 54*7dc08ffcSJunyu Lai def ottl(self): 55*7dc08ffcSJunyu Lai t = sorted([32,64,128,255]+[self._ttl()]) 56*7dc08ffcSJunyu Lai return t[t.index(self._ttl())+1] 57*7dc08ffcSJunyu Lai def hops(self): 58*7dc08ffcSJunyu Lai return self.ottl() - self._ttl() 59*7dc08ffcSJunyu Lai 60*7dc08ffcSJunyu Lai 61*7dc08ffcSJunyu Lai_ip_options_names = { 0: "end_of_list", 62*7dc08ffcSJunyu Lai 1: "nop", 63*7dc08ffcSJunyu Lai 2: "security", 64*7dc08ffcSJunyu Lai 3: "loose_source_route", 65*7dc08ffcSJunyu Lai 4: "timestamp", 66*7dc08ffcSJunyu Lai 5: "extended_security", 67*7dc08ffcSJunyu Lai 6: "commercial_security", 68*7dc08ffcSJunyu Lai 7: "record_route", 69*7dc08ffcSJunyu Lai 8: "stream_id", 70*7dc08ffcSJunyu Lai 9: "strict_source_route", 71*7dc08ffcSJunyu Lai 10: "experimental_measurement", 72*7dc08ffcSJunyu Lai 11: "mtu_probe", 73*7dc08ffcSJunyu Lai 12: "mtu_reply", 74*7dc08ffcSJunyu Lai 13: "flow_control", 75*7dc08ffcSJunyu Lai 14: "access_control", 76*7dc08ffcSJunyu Lai 15: "encode", 77*7dc08ffcSJunyu Lai 16: "imi_traffic_descriptor", 78*7dc08ffcSJunyu Lai 17: "extended_IP", 79*7dc08ffcSJunyu Lai 18: "traceroute", 80*7dc08ffcSJunyu Lai 19: "address_extension", 81*7dc08ffcSJunyu Lai 20: "router_alert", 82*7dc08ffcSJunyu Lai 21: "selective_directed_broadcast_mode", 83*7dc08ffcSJunyu Lai 23: "dynamic_packet_state", 84*7dc08ffcSJunyu Lai 24: "upstream_multicast_packet", 85*7dc08ffcSJunyu Lai 25: "quick_start", 86*7dc08ffcSJunyu Lai 30: "rfc4727_experiment", 87*7dc08ffcSJunyu Lai } 88*7dc08ffcSJunyu Lai 89*7dc08ffcSJunyu Lai 90*7dc08ffcSJunyu Laiclass _IPOption_HDR(Packet): 91*7dc08ffcSJunyu Lai fields_desc = [ BitField("copy_flag",0, 1), 92*7dc08ffcSJunyu Lai BitEnumField("optclass",0,2,{0:"control",2:"debug"}), 93*7dc08ffcSJunyu Lai BitEnumField("option",0,5, _ip_options_names) ] 94*7dc08ffcSJunyu Lai 95*7dc08ffcSJunyu Laiclass IPOption(Packet): 96*7dc08ffcSJunyu Lai name = "IP Option" 97*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 98*7dc08ffcSJunyu Lai FieldLenField("length", None, fmt="B", # Only option 0 and 1 have no length and value 99*7dc08ffcSJunyu Lai length_of="value", adjust=lambda pkt,l:l+2), 100*7dc08ffcSJunyu Lai StrLenField("value", "",length_from=lambda pkt:pkt.length-2) ] 101*7dc08ffcSJunyu Lai 102*7dc08ffcSJunyu Lai def extract_padding(self, p): 103*7dc08ffcSJunyu Lai return b"",p 104*7dc08ffcSJunyu Lai 105*7dc08ffcSJunyu Lai registered_ip_options = {} 106*7dc08ffcSJunyu Lai @classmethod 107*7dc08ffcSJunyu Lai def register_variant(cls): 108*7dc08ffcSJunyu Lai cls.registered_ip_options[cls.option.default] = cls 109*7dc08ffcSJunyu Lai @classmethod 110*7dc08ffcSJunyu Lai def dispatch_hook(cls, pkt=None, *args, **kargs): 111*7dc08ffcSJunyu Lai if pkt: 112*7dc08ffcSJunyu Lai opt = orb(pkt[0])&0x1f 113*7dc08ffcSJunyu Lai if opt in cls.registered_ip_options: 114*7dc08ffcSJunyu Lai return cls.registered_ip_options[opt] 115*7dc08ffcSJunyu Lai return cls 116*7dc08ffcSJunyu Lai 117*7dc08ffcSJunyu Laiclass IPOption_EOL(IPOption): 118*7dc08ffcSJunyu Lai name = "IP Option End of Options List" 119*7dc08ffcSJunyu Lai option = 0 120*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR ] 121*7dc08ffcSJunyu Lai 122*7dc08ffcSJunyu Lai 123*7dc08ffcSJunyu Laiclass IPOption_NOP(IPOption): 124*7dc08ffcSJunyu Lai name = "IP Option No Operation" 125*7dc08ffcSJunyu Lai option=1 126*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR ] 127*7dc08ffcSJunyu Lai 128*7dc08ffcSJunyu Laiclass IPOption_Security(IPOption): 129*7dc08ffcSJunyu Lai name = "IP Option Security" 130*7dc08ffcSJunyu Lai copy_flag = 1 131*7dc08ffcSJunyu Lai option = 2 132*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 133*7dc08ffcSJunyu Lai ByteField("length", 11), 134*7dc08ffcSJunyu Lai ShortField("security",0), 135*7dc08ffcSJunyu Lai ShortField("compartment",0), 136*7dc08ffcSJunyu Lai ShortField("handling_restrictions",0), 137*7dc08ffcSJunyu Lai StrFixedLenField("transmission_control_code","xxx",3), 138*7dc08ffcSJunyu Lai ] 139*7dc08ffcSJunyu Lai 140*7dc08ffcSJunyu Laiclass IPOption_RR(IPOption): 141*7dc08ffcSJunyu Lai name = "IP Option Record Route" 142*7dc08ffcSJunyu Lai option = 7 143*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 144*7dc08ffcSJunyu Lai FieldLenField("length", None, fmt="B", 145*7dc08ffcSJunyu Lai length_of="routers", adjust=lambda pkt,l:l+3), 146*7dc08ffcSJunyu Lai ByteField("pointer",4), # 4 is first IP 147*7dc08ffcSJunyu Lai FieldListField("routers",[],IPField("","0.0.0.0"), 148*7dc08ffcSJunyu Lai length_from=lambda pkt:pkt.length-3) 149*7dc08ffcSJunyu Lai ] 150*7dc08ffcSJunyu Lai def get_current_router(self): 151*7dc08ffcSJunyu Lai return self.routers[self.pointer//4-1] 152*7dc08ffcSJunyu Lai 153*7dc08ffcSJunyu Laiclass IPOption_LSRR(IPOption_RR): 154*7dc08ffcSJunyu Lai name = "IP Option Loose Source and Record Route" 155*7dc08ffcSJunyu Lai copy_flag = 1 156*7dc08ffcSJunyu Lai option = 3 157*7dc08ffcSJunyu Lai 158*7dc08ffcSJunyu Laiclass IPOption_SSRR(IPOption_RR): 159*7dc08ffcSJunyu Lai name = "IP Option Strict Source and Record Route" 160*7dc08ffcSJunyu Lai copy_flag = 1 161*7dc08ffcSJunyu Lai option = 9 162*7dc08ffcSJunyu Lai 163*7dc08ffcSJunyu Laiclass IPOption_Stream_Id(IPOption): 164*7dc08ffcSJunyu Lai name = "IP Option Stream ID" 165*7dc08ffcSJunyu Lai copy_flag = 1 166*7dc08ffcSJunyu Lai option = 8 167*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 168*7dc08ffcSJunyu Lai ByteField("length", 4), 169*7dc08ffcSJunyu Lai ShortField("security",0), ] 170*7dc08ffcSJunyu Lai 171*7dc08ffcSJunyu Laiclass IPOption_MTU_Probe(IPOption): 172*7dc08ffcSJunyu Lai name = "IP Option MTU Probe" 173*7dc08ffcSJunyu Lai option = 11 174*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 175*7dc08ffcSJunyu Lai ByteField("length", 4), 176*7dc08ffcSJunyu Lai ShortField("mtu",0), ] 177*7dc08ffcSJunyu Lai 178*7dc08ffcSJunyu Laiclass IPOption_MTU_Reply(IPOption_MTU_Probe): 179*7dc08ffcSJunyu Lai name = "IP Option MTU Reply" 180*7dc08ffcSJunyu Lai option = 12 181*7dc08ffcSJunyu Lai 182*7dc08ffcSJunyu Laiclass IPOption_Traceroute(IPOption): 183*7dc08ffcSJunyu Lai name = "IP Option Traceroute" 184*7dc08ffcSJunyu Lai option = 18 185*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 186*7dc08ffcSJunyu Lai ByteField("length", 12), 187*7dc08ffcSJunyu Lai ShortField("id",0), 188*7dc08ffcSJunyu Lai ShortField("outbound_hops",0), 189*7dc08ffcSJunyu Lai ShortField("return_hops",0), 190*7dc08ffcSJunyu Lai IPField("originator_ip","0.0.0.0") ] 191*7dc08ffcSJunyu Lai 192*7dc08ffcSJunyu Laiclass IPOption_Address_Extension(IPOption): 193*7dc08ffcSJunyu Lai name = "IP Option Address Extension" 194*7dc08ffcSJunyu Lai copy_flag = 1 195*7dc08ffcSJunyu Lai option = 19 196*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 197*7dc08ffcSJunyu Lai ByteField("length", 10), 198*7dc08ffcSJunyu Lai IPField("src_ext","0.0.0.0"), 199*7dc08ffcSJunyu Lai IPField("dst_ext","0.0.0.0") ] 200*7dc08ffcSJunyu Lai 201*7dc08ffcSJunyu Laiclass IPOption_Router_Alert(IPOption): 202*7dc08ffcSJunyu Lai name = "IP Option Router Alert" 203*7dc08ffcSJunyu Lai copy_flag = 1 204*7dc08ffcSJunyu Lai option = 20 205*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 206*7dc08ffcSJunyu Lai ByteField("length", 4), 207*7dc08ffcSJunyu Lai ShortEnumField("alert",0, {0:"router_shall_examine_packet"}), ] 208*7dc08ffcSJunyu Lai 209*7dc08ffcSJunyu Lai 210*7dc08ffcSJunyu Laiclass IPOption_SDBM(IPOption): 211*7dc08ffcSJunyu Lai name = "IP Option Selective Directed Broadcast Mode" 212*7dc08ffcSJunyu Lai copy_flag = 1 213*7dc08ffcSJunyu Lai option = 21 214*7dc08ffcSJunyu Lai fields_desc = [ _IPOption_HDR, 215*7dc08ffcSJunyu Lai FieldLenField("length", None, fmt="B", 216*7dc08ffcSJunyu Lai length_of="addresses", adjust=lambda pkt,l:l+2), 217*7dc08ffcSJunyu Lai FieldListField("addresses",[],IPField("","0.0.0.0"), 218*7dc08ffcSJunyu Lai length_from=lambda pkt:pkt.length-2) 219*7dc08ffcSJunyu Lai ] 220*7dc08ffcSJunyu Lai 221*7dc08ffcSJunyu Lai 222*7dc08ffcSJunyu Lai 223*7dc08ffcSJunyu LaiTCPOptions = ( 224*7dc08ffcSJunyu Lai { 0 : ("EOL",None), 225*7dc08ffcSJunyu Lai 1 : ("NOP",None), 226*7dc08ffcSJunyu Lai 2 : ("MSS","!H"), 227*7dc08ffcSJunyu Lai 3 : ("WScale","!B"), 228*7dc08ffcSJunyu Lai 4 : ("SAckOK",None), 229*7dc08ffcSJunyu Lai 5 : ("SAck","!"), 230*7dc08ffcSJunyu Lai 8 : ("Timestamp","!II"), 231*7dc08ffcSJunyu Lai 14 : ("AltChkSum","!BH"), 232*7dc08ffcSJunyu Lai 15 : ("AltChkSumOpt",None), 233*7dc08ffcSJunyu Lai 25 : ("Mood","!p"), 234*7dc08ffcSJunyu Lai 28 : ("UTO", "!H"), 235*7dc08ffcSJunyu Lai 34 : ("TFO", "!II"), 236*7dc08ffcSJunyu Lai # RFC 3692 237*7dc08ffcSJunyu Lai 253 : ("Experiment","!HHHH"), 238*7dc08ffcSJunyu Lai 254 : ("Experiment","!HHHH"), 239*7dc08ffcSJunyu Lai }, 240*7dc08ffcSJunyu Lai { "EOL":0, 241*7dc08ffcSJunyu Lai "NOP":1, 242*7dc08ffcSJunyu Lai "MSS":2, 243*7dc08ffcSJunyu Lai "WScale":3, 244*7dc08ffcSJunyu Lai "SAckOK":4, 245*7dc08ffcSJunyu Lai "SAck":5, 246*7dc08ffcSJunyu Lai "Timestamp":8, 247*7dc08ffcSJunyu Lai "AltChkSum":14, 248*7dc08ffcSJunyu Lai "AltChkSumOpt":15, 249*7dc08ffcSJunyu Lai "Mood":25, 250*7dc08ffcSJunyu Lai "UTO":28, 251*7dc08ffcSJunyu Lai "TFO":34, 252*7dc08ffcSJunyu Lai } ) 253*7dc08ffcSJunyu Lai 254*7dc08ffcSJunyu Laiclass TCPOptionsField(StrField): 255*7dc08ffcSJunyu Lai islist=1 256*7dc08ffcSJunyu Lai def getfield(self, pkt, s): 257*7dc08ffcSJunyu Lai opsz = (pkt.dataofs-5)*4 258*7dc08ffcSJunyu Lai if opsz < 0: 259*7dc08ffcSJunyu Lai warning("bad dataofs (%i). Assuming dataofs=5"%pkt.dataofs) 260*7dc08ffcSJunyu Lai opsz = 0 261*7dc08ffcSJunyu Lai return s[opsz:],self.m2i(pkt,s[:opsz]) 262*7dc08ffcSJunyu Lai def m2i(self, pkt, x): 263*7dc08ffcSJunyu Lai opt = [] 264*7dc08ffcSJunyu Lai while x: 265*7dc08ffcSJunyu Lai onum = orb(x[0]) 266*7dc08ffcSJunyu Lai if onum == 0: 267*7dc08ffcSJunyu Lai opt.append(("EOL",None)) 268*7dc08ffcSJunyu Lai x=x[1:] 269*7dc08ffcSJunyu Lai break 270*7dc08ffcSJunyu Lai if onum == 1: 271*7dc08ffcSJunyu Lai opt.append(("NOP",None)) 272*7dc08ffcSJunyu Lai x=x[1:] 273*7dc08ffcSJunyu Lai continue 274*7dc08ffcSJunyu Lai olen = orb(x[1]) 275*7dc08ffcSJunyu Lai if olen < 2: 276*7dc08ffcSJunyu Lai warning("Malformed TCP option (announced length is %i)" % olen) 277*7dc08ffcSJunyu Lai olen = 2 278*7dc08ffcSJunyu Lai oval = x[2:olen] 279*7dc08ffcSJunyu Lai if onum in TCPOptions[0]: 280*7dc08ffcSJunyu Lai oname, ofmt = TCPOptions[0][onum] 281*7dc08ffcSJunyu Lai if onum == 5: #SAck 282*7dc08ffcSJunyu Lai ofmt += "%iI" % (len(oval)//4) 283*7dc08ffcSJunyu Lai if ofmt and struct.calcsize(ofmt) == len(oval): 284*7dc08ffcSJunyu Lai oval = struct.unpack(ofmt, oval) 285*7dc08ffcSJunyu Lai if len(oval) == 1: 286*7dc08ffcSJunyu Lai oval = oval[0] 287*7dc08ffcSJunyu Lai opt.append((oname, oval)) 288*7dc08ffcSJunyu Lai else: 289*7dc08ffcSJunyu Lai opt.append((onum, oval)) 290*7dc08ffcSJunyu Lai x = x[olen:] 291*7dc08ffcSJunyu Lai return opt 292*7dc08ffcSJunyu Lai 293*7dc08ffcSJunyu Lai def i2m(self, pkt, x): 294*7dc08ffcSJunyu Lai opt = b"" 295*7dc08ffcSJunyu Lai for oname, oval in x: 296*7dc08ffcSJunyu Lai if isinstance(oname, str): 297*7dc08ffcSJunyu Lai if oname == "NOP": 298*7dc08ffcSJunyu Lai opt += b"\x01" 299*7dc08ffcSJunyu Lai continue 300*7dc08ffcSJunyu Lai elif oname == "EOL": 301*7dc08ffcSJunyu Lai opt += b"\x00" 302*7dc08ffcSJunyu Lai continue 303*7dc08ffcSJunyu Lai elif oname in TCPOptions[1]: 304*7dc08ffcSJunyu Lai onum = TCPOptions[1][oname] 305*7dc08ffcSJunyu Lai ofmt = TCPOptions[0][onum][1] 306*7dc08ffcSJunyu Lai if onum == 5: #SAck 307*7dc08ffcSJunyu Lai ofmt += "%iI" % len(oval) 308*7dc08ffcSJunyu Lai if ofmt is not None and (not isinstance(oval, str) or "s" in ofmt): 309*7dc08ffcSJunyu Lai if not isinstance(oval, tuple): 310*7dc08ffcSJunyu Lai oval = (oval,) 311*7dc08ffcSJunyu Lai oval = struct.pack(ofmt, *oval) 312*7dc08ffcSJunyu Lai else: 313*7dc08ffcSJunyu Lai warning("option [%s] unknown. Skipped.", oname) 314*7dc08ffcSJunyu Lai continue 315*7dc08ffcSJunyu Lai else: 316*7dc08ffcSJunyu Lai onum = oname 317*7dc08ffcSJunyu Lai if not isinstance(oval, str): 318*7dc08ffcSJunyu Lai warning("option [%i] is not string."%onum) 319*7dc08ffcSJunyu Lai continue 320*7dc08ffcSJunyu Lai opt += chb(onum) + chb(2+len(oval))+ raw(oval) 321*7dc08ffcSJunyu Lai return opt+b"\x00"*(3-((len(opt)+3)%4)) 322*7dc08ffcSJunyu Lai def randval(self): 323*7dc08ffcSJunyu Lai return [] # XXX 324*7dc08ffcSJunyu Lai 325*7dc08ffcSJunyu Lai 326*7dc08ffcSJunyu Laiclass ICMPTimeStampField(IntField): 327*7dc08ffcSJunyu Lai re_hmsm = re.compile("([0-2]?[0-9])[Hh:](([0-5]?[0-9])([Mm:]([0-5]?[0-9])([sS:.]([0-9]{0,3}))?)?)?$") 328*7dc08ffcSJunyu Lai def i2repr(self, pkt, val): 329*7dc08ffcSJunyu Lai if val is None: 330*7dc08ffcSJunyu Lai return "--" 331*7dc08ffcSJunyu Lai else: 332*7dc08ffcSJunyu Lai sec, milli = divmod(val, 1000) 333*7dc08ffcSJunyu Lai min, sec = divmod(sec, 60) 334*7dc08ffcSJunyu Lai hour, min = divmod(min, 60) 335*7dc08ffcSJunyu Lai return "%d:%d:%d.%d" %(hour, min, sec, int(milli)) 336*7dc08ffcSJunyu Lai def any2i(self, pkt, val): 337*7dc08ffcSJunyu Lai if isinstance(val, str): 338*7dc08ffcSJunyu Lai hmsms = self.re_hmsm.match(val) 339*7dc08ffcSJunyu Lai if hmsms: 340*7dc08ffcSJunyu Lai h,_,m,_,s,_,ms = hmsms = hmsms.groups() 341*7dc08ffcSJunyu Lai ms = int(((ms or "")+"000")[:3]) 342*7dc08ffcSJunyu Lai val = ((int(h)*60+int(m or 0))*60+int(s or 0))*1000+ms 343*7dc08ffcSJunyu Lai else: 344*7dc08ffcSJunyu Lai val = 0 345*7dc08ffcSJunyu Lai elif val is None: 346*7dc08ffcSJunyu Lai val = int((time.time()%(24*60*60))*1000) 347*7dc08ffcSJunyu Lai return val 348*7dc08ffcSJunyu Lai 349*7dc08ffcSJunyu Lai 350*7dc08ffcSJunyu Laiclass DestIPField(IPField, DestField): 351*7dc08ffcSJunyu Lai bindings = {} 352*7dc08ffcSJunyu Lai def __init__(self, name, default): 353*7dc08ffcSJunyu Lai IPField.__init__(self, name, None) 354*7dc08ffcSJunyu Lai DestField.__init__(self, name, default) 355*7dc08ffcSJunyu Lai def i2m(self, pkt, x): 356*7dc08ffcSJunyu Lai if x is None: 357*7dc08ffcSJunyu Lai x = self.dst_from_pkt(pkt) 358*7dc08ffcSJunyu Lai return IPField.i2m(self, pkt, x) 359*7dc08ffcSJunyu Lai def i2h(self, pkt, x): 360*7dc08ffcSJunyu Lai if x is None: 361*7dc08ffcSJunyu Lai x = self.dst_from_pkt(pkt) 362*7dc08ffcSJunyu Lai return IPField.i2h(self, pkt, x) 363*7dc08ffcSJunyu Lai 364*7dc08ffcSJunyu Lai 365*7dc08ffcSJunyu Laiclass IP(Packet, IPTools): 366*7dc08ffcSJunyu Lai __slots__ = ["_defrag_pos"] 367*7dc08ffcSJunyu Lai name = "IP" 368*7dc08ffcSJunyu Lai fields_desc = [ BitField("version" , 4 , 4), 369*7dc08ffcSJunyu Lai BitField("ihl", None, 4), 370*7dc08ffcSJunyu Lai XByteField("tos", 0), 371*7dc08ffcSJunyu Lai ShortField("len", None), 372*7dc08ffcSJunyu Lai ShortField("id", 1), 373*7dc08ffcSJunyu Lai FlagsField("flags", 0, 3, ["MF","DF","evil"]), 374*7dc08ffcSJunyu Lai BitField("frag", 0, 13), 375*7dc08ffcSJunyu Lai ByteField("ttl", 64), 376*7dc08ffcSJunyu Lai ByteEnumField("proto", 0, IP_PROTOS), 377*7dc08ffcSJunyu Lai XShortField("chksum", None), 378*7dc08ffcSJunyu Lai #IPField("src", "127.0.0.1"), 379*7dc08ffcSJunyu Lai Emph(SourceIPField("src","dst")), 380*7dc08ffcSJunyu Lai Emph(DestIPField("dst", "127.0.0.1")), 381*7dc08ffcSJunyu Lai PacketListField("options", [], IPOption, length_from=lambda p:p.ihl*4-20) ] 382*7dc08ffcSJunyu Lai def post_build(self, p, pay): 383*7dc08ffcSJunyu Lai ihl = self.ihl 384*7dc08ffcSJunyu Lai p += b"\0"*((-len(p))%4) # pad IP options if needed 385*7dc08ffcSJunyu Lai if ihl is None: 386*7dc08ffcSJunyu Lai ihl = len(p)//4 387*7dc08ffcSJunyu Lai p = chb(((self.version&0xf)<<4) | ihl&0x0f)+p[1:] 388*7dc08ffcSJunyu Lai if self.len is None: 389*7dc08ffcSJunyu Lai l = len(p)+len(pay) 390*7dc08ffcSJunyu Lai p = p[:2]+struct.pack("!H", l)+p[4:] 391*7dc08ffcSJunyu Lai if self.chksum is None: 392*7dc08ffcSJunyu Lai ck = checksum(p) 393*7dc08ffcSJunyu Lai p = p[:10]+chb(ck>>8)+chb(ck&0xff)+p[12:] 394*7dc08ffcSJunyu Lai return p+pay 395*7dc08ffcSJunyu Lai 396*7dc08ffcSJunyu Lai def extract_padding(self, s): 397*7dc08ffcSJunyu Lai l = self.len - (self.ihl << 2) 398*7dc08ffcSJunyu Lai return s[:l],s[l:] 399*7dc08ffcSJunyu Lai 400*7dc08ffcSJunyu Lai def route(self): 401*7dc08ffcSJunyu Lai dst = self.dst 402*7dc08ffcSJunyu Lai if isinstance(dst, Gen): 403*7dc08ffcSJunyu Lai dst = next(iter(dst)) 404*7dc08ffcSJunyu Lai if conf.route is None: 405*7dc08ffcSJunyu Lai # unused import, only to initialize conf.route 406*7dc08ffcSJunyu Lai import scapy.route 407*7dc08ffcSJunyu Lai return conf.route.route(dst) 408*7dc08ffcSJunyu Lai def hashret(self): 409*7dc08ffcSJunyu Lai if ( (self.proto == socket.IPPROTO_ICMP) 410*7dc08ffcSJunyu Lai and (isinstance(self.payload, ICMP)) 411*7dc08ffcSJunyu Lai and (self.payload.type in [3,4,5,11,12]) ): 412*7dc08ffcSJunyu Lai return self.payload.payload.hashret() 413*7dc08ffcSJunyu Lai if not conf.checkIPinIP and self.proto in [4, 41]: # IP, IPv6 414*7dc08ffcSJunyu Lai return self.payload.hashret() 415*7dc08ffcSJunyu Lai if self.dst == "224.0.0.251": # mDNS 416*7dc08ffcSJunyu Lai return struct.pack("B", self.proto) + self.payload.hashret() 417*7dc08ffcSJunyu Lai if conf.checkIPsrc and conf.checkIPaddr: 418*7dc08ffcSJunyu Lai return (strxor(inet_aton(self.src), inet_aton(self.dst)) 419*7dc08ffcSJunyu Lai + struct.pack("B",self.proto) + self.payload.hashret()) 420*7dc08ffcSJunyu Lai return struct.pack("B", self.proto) + self.payload.hashret() 421*7dc08ffcSJunyu Lai def answers(self, other): 422*7dc08ffcSJunyu Lai if not conf.checkIPinIP: # skip IP in IP and IPv6 in IP 423*7dc08ffcSJunyu Lai if self.proto in [4, 41]: 424*7dc08ffcSJunyu Lai return self.payload.answers(other) 425*7dc08ffcSJunyu Lai if isinstance(other, IP) and other.proto in [4, 41]: 426*7dc08ffcSJunyu Lai return self.answers(other.payload) 427*7dc08ffcSJunyu Lai if conf.ipv6_enabled \ 428*7dc08ffcSJunyu Lai and isinstance(other, scapy.layers.inet6.IPv6) \ 429*7dc08ffcSJunyu Lai and other.nh in [4, 41]: 430*7dc08ffcSJunyu Lai return self.answers(other.payload) 431*7dc08ffcSJunyu Lai if not isinstance(other,IP): 432*7dc08ffcSJunyu Lai return 0 433*7dc08ffcSJunyu Lai if conf.checkIPaddr: 434*7dc08ffcSJunyu Lai if other.dst == "224.0.0.251" and self.dst == "224.0.0.251": # mDNS 435*7dc08ffcSJunyu Lai return self.payload.answers(other.payload) 436*7dc08ffcSJunyu Lai elif (self.dst != other.src): 437*7dc08ffcSJunyu Lai return 0 438*7dc08ffcSJunyu Lai if ( (self.proto == socket.IPPROTO_ICMP) and 439*7dc08ffcSJunyu Lai (isinstance(self.payload, ICMP)) and 440*7dc08ffcSJunyu Lai (self.payload.type in [3,4,5,11,12]) ): 441*7dc08ffcSJunyu Lai # ICMP error message 442*7dc08ffcSJunyu Lai return self.payload.payload.answers(other) 443*7dc08ffcSJunyu Lai 444*7dc08ffcSJunyu Lai else: 445*7dc08ffcSJunyu Lai if ( (conf.checkIPaddr and (self.src != other.dst)) or 446*7dc08ffcSJunyu Lai (self.proto != other.proto) ): 447*7dc08ffcSJunyu Lai return 0 448*7dc08ffcSJunyu Lai return self.payload.answers(other.payload) 449*7dc08ffcSJunyu Lai def mysummary(self): 450*7dc08ffcSJunyu Lai s = self.sprintf("%IP.src% > %IP.dst% %IP.proto%") 451*7dc08ffcSJunyu Lai if self.frag: 452*7dc08ffcSJunyu Lai s += " frag:%i" % self.frag 453*7dc08ffcSJunyu Lai return s 454*7dc08ffcSJunyu Lai 455*7dc08ffcSJunyu Lai def fragment(self, fragsize=1480): 456*7dc08ffcSJunyu Lai """Fragment IP datagrams""" 457*7dc08ffcSJunyu Lai fragsize = (fragsize+7)//8*8 458*7dc08ffcSJunyu Lai lst = [] 459*7dc08ffcSJunyu Lai fnb = 0 460*7dc08ffcSJunyu Lai fl = self 461*7dc08ffcSJunyu Lai while fl.underlayer is not None: 462*7dc08ffcSJunyu Lai fnb += 1 463*7dc08ffcSJunyu Lai fl = fl.underlayer 464*7dc08ffcSJunyu Lai 465*7dc08ffcSJunyu Lai for p in fl: 466*7dc08ffcSJunyu Lai s = raw(p[fnb].payload) 467*7dc08ffcSJunyu Lai nb = (len(s)+fragsize-1)//fragsize 468*7dc08ffcSJunyu Lai for i in range(nb): 469*7dc08ffcSJunyu Lai q = p.copy() 470*7dc08ffcSJunyu Lai del(q[fnb].payload) 471*7dc08ffcSJunyu Lai del(q[fnb].chksum) 472*7dc08ffcSJunyu Lai del(q[fnb].len) 473*7dc08ffcSJunyu Lai if i != nb - 1: 474*7dc08ffcSJunyu Lai q[fnb].flags |= 1 475*7dc08ffcSJunyu Lai q[fnb].frag += i * fragsize // 8 476*7dc08ffcSJunyu Lai r = conf.raw_layer(load=s[i*fragsize:(i+1)*fragsize]) 477*7dc08ffcSJunyu Lai r.overload_fields = p[fnb].payload.overload_fields.copy() 478*7dc08ffcSJunyu Lai q.add_payload(r) 479*7dc08ffcSJunyu Lai lst.append(q) 480*7dc08ffcSJunyu Lai return lst 481*7dc08ffcSJunyu Lai 482*7dc08ffcSJunyu Laidef in4_chksum(proto, u, p): 483*7dc08ffcSJunyu Lai """ 484*7dc08ffcSJunyu Lai As Specified in RFC 2460 - 8.1 Upper-Layer Checksums 485*7dc08ffcSJunyu Lai 486*7dc08ffcSJunyu Lai Performs IPv4 Upper Layer checksum computation. Provided parameters are: 487*7dc08ffcSJunyu Lai - 'proto' : value of upper layer protocol 488*7dc08ffcSJunyu Lai - 'u' : IP upper layer instance 489*7dc08ffcSJunyu Lai - 'p' : the payload of the upper layer provided as a string 490*7dc08ffcSJunyu Lai """ 491*7dc08ffcSJunyu Lai if not isinstance(u, IP): 492*7dc08ffcSJunyu Lai warning("No IP underlayer to compute checksum. Leaving null.") 493*7dc08ffcSJunyu Lai return 0 494*7dc08ffcSJunyu Lai if u.len is not None: 495*7dc08ffcSJunyu Lai if u.ihl is None: 496*7dc08ffcSJunyu Lai olen = sum(len(x) for x in u.options) 497*7dc08ffcSJunyu Lai ihl = 5 + olen // 4 + (1 if olen % 4 else 0) 498*7dc08ffcSJunyu Lai else: 499*7dc08ffcSJunyu Lai ihl = u.ihl 500*7dc08ffcSJunyu Lai ln = u.len - 4 * ihl 501*7dc08ffcSJunyu Lai else: 502*7dc08ffcSJunyu Lai ln = len(p) 503*7dc08ffcSJunyu Lai psdhdr = struct.pack("!4s4sHH", 504*7dc08ffcSJunyu Lai inet_aton(u.src), 505*7dc08ffcSJunyu Lai inet_aton(u.dst), 506*7dc08ffcSJunyu Lai proto, 507*7dc08ffcSJunyu Lai ln) 508*7dc08ffcSJunyu Lai return checksum(psdhdr+p) 509*7dc08ffcSJunyu Lai 510*7dc08ffcSJunyu Laiclass TCP(Packet): 511*7dc08ffcSJunyu Lai name = "TCP" 512*7dc08ffcSJunyu Lai fields_desc = [ ShortEnumField("sport", 20, TCP_SERVICES), 513*7dc08ffcSJunyu Lai ShortEnumField("dport", 80, TCP_SERVICES), 514*7dc08ffcSJunyu Lai IntField("seq", 0), 515*7dc08ffcSJunyu Lai IntField("ack", 0), 516*7dc08ffcSJunyu Lai BitField("dataofs", None, 4), 517*7dc08ffcSJunyu Lai BitField("reserved", 0, 3), 518*7dc08ffcSJunyu Lai FlagsField("flags", 0x2, 9, "FSRPAUECN"), 519*7dc08ffcSJunyu Lai ShortField("window", 8192), 520*7dc08ffcSJunyu Lai XShortField("chksum", None), 521*7dc08ffcSJunyu Lai ShortField("urgptr", 0), 522*7dc08ffcSJunyu Lai TCPOptionsField("options", []) ] 523*7dc08ffcSJunyu Lai def post_build(self, p, pay): 524*7dc08ffcSJunyu Lai p += pay 525*7dc08ffcSJunyu Lai dataofs = self.dataofs 526*7dc08ffcSJunyu Lai if dataofs is None: 527*7dc08ffcSJunyu Lai dataofs = 5+((len(self.get_field("options").i2m(self,self.options))+3)//4) 528*7dc08ffcSJunyu Lai p = p[:12]+chb((dataofs << 4) | orb(p[12])&0x0f)+p[13:] 529*7dc08ffcSJunyu Lai if self.chksum is None: 530*7dc08ffcSJunyu Lai if isinstance(self.underlayer, IP): 531*7dc08ffcSJunyu Lai ck = in4_chksum(socket.IPPROTO_TCP, self.underlayer, p) 532*7dc08ffcSJunyu Lai p = p[:16]+struct.pack("!H", ck)+p[18:] 533*7dc08ffcSJunyu Lai elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): 534*7dc08ffcSJunyu Lai ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_TCP, self.underlayer, p) 535*7dc08ffcSJunyu Lai p = p[:16]+struct.pack("!H", ck)+p[18:] 536*7dc08ffcSJunyu Lai else: 537*7dc08ffcSJunyu Lai warning("No IP underlayer to compute checksum. Leaving null.") 538*7dc08ffcSJunyu Lai return p 539*7dc08ffcSJunyu Lai def hashret(self): 540*7dc08ffcSJunyu Lai if conf.checkIPsrc: 541*7dc08ffcSJunyu Lai return struct.pack("H",self.sport ^ self.dport)+self.payload.hashret() 542*7dc08ffcSJunyu Lai else: 543*7dc08ffcSJunyu Lai return self.payload.hashret() 544*7dc08ffcSJunyu Lai def answers(self, other): 545*7dc08ffcSJunyu Lai if not isinstance(other, TCP): 546*7dc08ffcSJunyu Lai return 0 547*7dc08ffcSJunyu Lai # RST packets don't get answers 548*7dc08ffcSJunyu Lai if other.flags.R: 549*7dc08ffcSJunyu Lai return 0 550*7dc08ffcSJunyu Lai # We do not support the four-way handshakes with the SYN+ACK 551*7dc08ffcSJunyu Lai # answer split in two packets (one ACK and one SYN): in that 552*7dc08ffcSJunyu Lai # case the ACK will be seen as an answer, but not the SYN. 553*7dc08ffcSJunyu Lai if self.flags.S: 554*7dc08ffcSJunyu Lai # SYN packets without ACK are not answers 555*7dc08ffcSJunyu Lai if not self.flags.A: 556*7dc08ffcSJunyu Lai return 0 557*7dc08ffcSJunyu Lai # SYN+ACK packets answer SYN packets 558*7dc08ffcSJunyu Lai if not other.flags.S: 559*7dc08ffcSJunyu Lai return 0 560*7dc08ffcSJunyu Lai if conf.checkIPsrc: 561*7dc08ffcSJunyu Lai if not ((self.sport == other.dport) and 562*7dc08ffcSJunyu Lai (self.dport == other.sport)): 563*7dc08ffcSJunyu Lai return 0 564*7dc08ffcSJunyu Lai # Do not check ack value for SYN packets without ACK 565*7dc08ffcSJunyu Lai if not (other.flags.S and not other.flags.A) \ 566*7dc08ffcSJunyu Lai and abs(other.ack - self.seq) > 2: 567*7dc08ffcSJunyu Lai return 0 568*7dc08ffcSJunyu Lai # Do not check ack value for RST packets without ACK 569*7dc08ffcSJunyu Lai if self.flags.R and not self.flags.A: 570*7dc08ffcSJunyu Lai return 1 571*7dc08ffcSJunyu Lai if abs(other.seq - self.ack) > 2 + len(other.payload): 572*7dc08ffcSJunyu Lai return 0 573*7dc08ffcSJunyu Lai return 1 574*7dc08ffcSJunyu Lai def mysummary(self): 575*7dc08ffcSJunyu Lai if isinstance(self.underlayer, IP): 576*7dc08ffcSJunyu Lai return self.underlayer.sprintf("TCP %IP.src%:%TCP.sport% > %IP.dst%:%TCP.dport% %TCP.flags%") 577*7dc08ffcSJunyu Lai elif conf.ipv6_enabled and isinstance(self.underlayer, scapy.layers.inet6.IPv6): 578*7dc08ffcSJunyu Lai return self.underlayer.sprintf("TCP %IPv6.src%:%TCP.sport% > %IPv6.dst%:%TCP.dport% %TCP.flags%") 579*7dc08ffcSJunyu Lai else: 580*7dc08ffcSJunyu Lai return self.sprintf("TCP %TCP.sport% > %TCP.dport% %TCP.flags%") 581*7dc08ffcSJunyu Lai 582*7dc08ffcSJunyu Laiclass UDP(Packet): 583*7dc08ffcSJunyu Lai name = "UDP" 584*7dc08ffcSJunyu Lai fields_desc = [ ShortEnumField("sport", 53, UDP_SERVICES), 585*7dc08ffcSJunyu Lai ShortEnumField("dport", 53, UDP_SERVICES), 586*7dc08ffcSJunyu Lai ShortField("len", None), 587*7dc08ffcSJunyu Lai XShortField("chksum", None), ] 588*7dc08ffcSJunyu Lai def post_build(self, p, pay): 589*7dc08ffcSJunyu Lai p += pay 590*7dc08ffcSJunyu Lai l = self.len 591*7dc08ffcSJunyu Lai if l is None: 592*7dc08ffcSJunyu Lai l = len(p) 593*7dc08ffcSJunyu Lai p = p[:4]+struct.pack("!H",l)+p[6:] 594*7dc08ffcSJunyu Lai if self.chksum is None: 595*7dc08ffcSJunyu Lai if isinstance(self.underlayer, IP): 596*7dc08ffcSJunyu Lai ck = in4_chksum(socket.IPPROTO_UDP, self.underlayer, p) 597*7dc08ffcSJunyu Lai # According to RFC768 if the result checksum is 0, it should be set to 0xFFFF 598*7dc08ffcSJunyu Lai if ck == 0: 599*7dc08ffcSJunyu Lai ck = 0xFFFF 600*7dc08ffcSJunyu Lai p = p[:6]+struct.pack("!H", ck)+p[8:] 601*7dc08ffcSJunyu Lai elif isinstance(self.underlayer, scapy.layers.inet6.IPv6) or isinstance(self.underlayer, scapy.layers.inet6._IPv6ExtHdr): 602*7dc08ffcSJunyu Lai ck = scapy.layers.inet6.in6_chksum(socket.IPPROTO_UDP, self.underlayer, p) 603*7dc08ffcSJunyu Lai # According to RFC2460 if the result checksum is 0, it should be set to 0xFFFF 604*7dc08ffcSJunyu Lai if ck == 0: 605*7dc08ffcSJunyu Lai ck = 0xFFFF 606*7dc08ffcSJunyu Lai p = p[:6]+struct.pack("!H", ck)+p[8:] 607*7dc08ffcSJunyu Lai else: 608*7dc08ffcSJunyu Lai warning("No IP underlayer to compute checksum. Leaving null.") 609*7dc08ffcSJunyu Lai return p 610*7dc08ffcSJunyu Lai def extract_padding(self, s): 611*7dc08ffcSJunyu Lai l = self.len - 8 612*7dc08ffcSJunyu Lai return s[:l],s[l:] 613*7dc08ffcSJunyu Lai def hashret(self): 614*7dc08ffcSJunyu Lai return self.payload.hashret() 615*7dc08ffcSJunyu Lai def answers(self, other): 616*7dc08ffcSJunyu Lai if not isinstance(other, UDP): 617*7dc08ffcSJunyu Lai return 0 618*7dc08ffcSJunyu Lai if conf.checkIPsrc: 619*7dc08ffcSJunyu Lai if self.dport != other.sport: 620*7dc08ffcSJunyu Lai return 0 621*7dc08ffcSJunyu Lai return self.payload.answers(other.payload) 622*7dc08ffcSJunyu Lai def mysummary(self): 623*7dc08ffcSJunyu Lai if isinstance(self.underlayer, IP): 624*7dc08ffcSJunyu Lai return self.underlayer.sprintf("UDP %IP.src%:%UDP.sport% > %IP.dst%:%UDP.dport%") 625*7dc08ffcSJunyu Lai elif isinstance(self.underlayer, scapy.layers.inet6.IPv6): 626*7dc08ffcSJunyu Lai return self.underlayer.sprintf("UDP %IPv6.src%:%UDP.sport% > %IPv6.dst%:%UDP.dport%") 627*7dc08ffcSJunyu Lai else: 628*7dc08ffcSJunyu Lai return self.sprintf("UDP %UDP.sport% > %UDP.dport%") 629*7dc08ffcSJunyu Lai 630*7dc08ffcSJunyu Laiicmptypes = { 0 : "echo-reply", 631*7dc08ffcSJunyu Lai 3 : "dest-unreach", 632*7dc08ffcSJunyu Lai 4 : "source-quench", 633*7dc08ffcSJunyu Lai 5 : "redirect", 634*7dc08ffcSJunyu Lai 8 : "echo-request", 635*7dc08ffcSJunyu Lai 9 : "router-advertisement", 636*7dc08ffcSJunyu Lai 10 : "router-solicitation", 637*7dc08ffcSJunyu Lai 11 : "time-exceeded", 638*7dc08ffcSJunyu Lai 12 : "parameter-problem", 639*7dc08ffcSJunyu Lai 13 : "timestamp-request", 640*7dc08ffcSJunyu Lai 14 : "timestamp-reply", 641*7dc08ffcSJunyu Lai 15 : "information-request", 642*7dc08ffcSJunyu Lai 16 : "information-response", 643*7dc08ffcSJunyu Lai 17 : "address-mask-request", 644*7dc08ffcSJunyu Lai 18 : "address-mask-reply" } 645*7dc08ffcSJunyu Lai 646*7dc08ffcSJunyu Laiicmpcodes = { 3 : { 0 : "network-unreachable", 647*7dc08ffcSJunyu Lai 1 : "host-unreachable", 648*7dc08ffcSJunyu Lai 2 : "protocol-unreachable", 649*7dc08ffcSJunyu Lai 3 : "port-unreachable", 650*7dc08ffcSJunyu Lai 4 : "fragmentation-needed", 651*7dc08ffcSJunyu Lai 5 : "source-route-failed", 652*7dc08ffcSJunyu Lai 6 : "network-unknown", 653*7dc08ffcSJunyu Lai 7 : "host-unknown", 654*7dc08ffcSJunyu Lai 9 : "network-prohibited", 655*7dc08ffcSJunyu Lai 10 : "host-prohibited", 656*7dc08ffcSJunyu Lai 11 : "TOS-network-unreachable", 657*7dc08ffcSJunyu Lai 12 : "TOS-host-unreachable", 658*7dc08ffcSJunyu Lai 13 : "communication-prohibited", 659*7dc08ffcSJunyu Lai 14 : "host-precedence-violation", 660*7dc08ffcSJunyu Lai 15 : "precedence-cutoff", }, 661*7dc08ffcSJunyu Lai 5 : { 0 : "network-redirect", 662*7dc08ffcSJunyu Lai 1 : "host-redirect", 663*7dc08ffcSJunyu Lai 2 : "TOS-network-redirect", 664*7dc08ffcSJunyu Lai 3 : "TOS-host-redirect", }, 665*7dc08ffcSJunyu Lai 11 : { 0 : "ttl-zero-during-transit", 666*7dc08ffcSJunyu Lai 1 : "ttl-zero-during-reassembly", }, 667*7dc08ffcSJunyu Lai 12 : { 0 : "ip-header-bad", 668*7dc08ffcSJunyu Lai 1 : "required-option-missing", }, } 669*7dc08ffcSJunyu Lai 670*7dc08ffcSJunyu Lai 671*7dc08ffcSJunyu Lai 672*7dc08ffcSJunyu Lai 673*7dc08ffcSJunyu Laiclass ICMP(Packet): 674*7dc08ffcSJunyu Lai name = "ICMP" 675*7dc08ffcSJunyu Lai fields_desc = [ ByteEnumField("type",8, icmptypes), 676*7dc08ffcSJunyu Lai MultiEnumField("code",0, icmpcodes, depends_on=lambda pkt:pkt.type,fmt="B"), 677*7dc08ffcSJunyu Lai XShortField("chksum", None), 678*7dc08ffcSJunyu Lai ConditionalField(XShortField("id",0), lambda pkt:pkt.type in [0,8,13,14,15,16,17,18]), 679*7dc08ffcSJunyu Lai ConditionalField(XShortField("seq",0), lambda pkt:pkt.type in [0,8,13,14,15,16,17,18]), 680*7dc08ffcSJunyu Lai ConditionalField(ICMPTimeStampField("ts_ori", None), lambda pkt:pkt.type in [13,14]), 681*7dc08ffcSJunyu Lai ConditionalField(ICMPTimeStampField("ts_rx", None), lambda pkt:pkt.type in [13,14]), 682*7dc08ffcSJunyu Lai ConditionalField(ICMPTimeStampField("ts_tx", None), lambda pkt:pkt.type in [13,14]), 683*7dc08ffcSJunyu Lai ConditionalField(IPField("gw","0.0.0.0"), lambda pkt:pkt.type==5), 684*7dc08ffcSJunyu Lai ConditionalField(ByteField("ptr",0), lambda pkt:pkt.type==12), 685*7dc08ffcSJunyu Lai ConditionalField(ByteField("reserved",0), lambda pkt:pkt.type in [3,11]), 686*7dc08ffcSJunyu Lai ConditionalField(ByteField("length",0), lambda pkt:pkt.type in [3,11,12]), 687*7dc08ffcSJunyu Lai ConditionalField(IPField("addr_mask","0.0.0.0"), lambda pkt:pkt.type in [17,18]), 688*7dc08ffcSJunyu Lai ConditionalField(ShortField("nexthopmtu",0), lambda pkt:pkt.type==3), 689*7dc08ffcSJunyu Lai ConditionalField(ShortField("unused",0), lambda pkt:pkt.type in [11,12]), 690*7dc08ffcSJunyu Lai ConditionalField(IntField("unused",0), lambda pkt:pkt.type not in [0,3,5,8,11,12,13,14,15,16,17,18]) 691*7dc08ffcSJunyu Lai ] 692*7dc08ffcSJunyu Lai def post_build(self, p, pay): 693*7dc08ffcSJunyu Lai p += pay 694*7dc08ffcSJunyu Lai if self.chksum is None: 695*7dc08ffcSJunyu Lai ck = checksum(p) 696*7dc08ffcSJunyu Lai p = p[:2] + chb(ck>>8) + chb(ck&0xff) + p[4:] 697*7dc08ffcSJunyu Lai return p 698*7dc08ffcSJunyu Lai 699*7dc08ffcSJunyu Lai def hashret(self): 700*7dc08ffcSJunyu Lai if self.type in [0,8,13,14,15,16,17,18]: 701*7dc08ffcSJunyu Lai return struct.pack("HH",self.id,self.seq)+self.payload.hashret() 702*7dc08ffcSJunyu Lai return self.payload.hashret() 703*7dc08ffcSJunyu Lai def answers(self, other): 704*7dc08ffcSJunyu Lai if not isinstance(other,ICMP): 705*7dc08ffcSJunyu Lai return 0 706*7dc08ffcSJunyu Lai if ( (other.type,self.type) in [(8,0),(13,14),(15,16),(17,18)] and 707*7dc08ffcSJunyu Lai self.id == other.id and 708*7dc08ffcSJunyu Lai self.seq == other.seq ): 709*7dc08ffcSJunyu Lai return 1 710*7dc08ffcSJunyu Lai return 0 711*7dc08ffcSJunyu Lai 712*7dc08ffcSJunyu Lai def guess_payload_class(self, payload): 713*7dc08ffcSJunyu Lai if self.type in [3,4,5,11,12]: 714*7dc08ffcSJunyu Lai return IPerror 715*7dc08ffcSJunyu Lai else: 716*7dc08ffcSJunyu Lai return None 717*7dc08ffcSJunyu Lai def mysummary(self): 718*7dc08ffcSJunyu Lai if isinstance(self.underlayer, IP): 719*7dc08ffcSJunyu Lai return self.underlayer.sprintf("ICMP %IP.src% > %IP.dst% %ICMP.type% %ICMP.code%") 720*7dc08ffcSJunyu Lai else: 721*7dc08ffcSJunyu Lai return self.sprintf("ICMP %ICMP.type% %ICMP.code%") 722*7dc08ffcSJunyu Lai 723*7dc08ffcSJunyu Lai 724*7dc08ffcSJunyu Lai 725*7dc08ffcSJunyu Lai 726*7dc08ffcSJunyu Lai 727*7dc08ffcSJunyu Laiclass IPerror(IP): 728*7dc08ffcSJunyu Lai name = "IP in ICMP" 729*7dc08ffcSJunyu Lai def answers(self, other): 730*7dc08ffcSJunyu Lai if not isinstance(other, IP): 731*7dc08ffcSJunyu Lai return 0 732*7dc08ffcSJunyu Lai if not ( ((conf.checkIPsrc == 0) or (self.dst == other.dst)) and 733*7dc08ffcSJunyu Lai (self.src == other.src) and 734*7dc08ffcSJunyu Lai ( ((conf.checkIPID == 0) 735*7dc08ffcSJunyu Lai or (self.id == other.id) 736*7dc08ffcSJunyu Lai or (conf.checkIPID == 1 and self.id == socket.htons(other.id)))) and 737*7dc08ffcSJunyu Lai (self.proto == other.proto) ): 738*7dc08ffcSJunyu Lai return 0 739*7dc08ffcSJunyu Lai return self.payload.answers(other.payload) 740*7dc08ffcSJunyu Lai def mysummary(self): 741*7dc08ffcSJunyu Lai return Packet.mysummary(self) 742*7dc08ffcSJunyu Lai 743*7dc08ffcSJunyu Lai 744*7dc08ffcSJunyu Laiclass TCPerror(TCP): 745*7dc08ffcSJunyu Lai name = "TCP in ICMP" 746*7dc08ffcSJunyu Lai def answers(self, other): 747*7dc08ffcSJunyu Lai if not isinstance(other, TCP): 748*7dc08ffcSJunyu Lai return 0 749*7dc08ffcSJunyu Lai if conf.checkIPsrc: 750*7dc08ffcSJunyu Lai if not ((self.sport == other.sport) and 751*7dc08ffcSJunyu Lai (self.dport == other.dport)): 752*7dc08ffcSJunyu Lai return 0 753*7dc08ffcSJunyu Lai if conf.check_TCPerror_seqack: 754*7dc08ffcSJunyu Lai if self.seq is not None: 755*7dc08ffcSJunyu Lai if self.seq != other.seq: 756*7dc08ffcSJunyu Lai return 0 757*7dc08ffcSJunyu Lai if self.ack is not None: 758*7dc08ffcSJunyu Lai if self.ack != other.ack: 759*7dc08ffcSJunyu Lai return 0 760*7dc08ffcSJunyu Lai return 1 761*7dc08ffcSJunyu Lai def mysummary(self): 762*7dc08ffcSJunyu Lai return Packet.mysummary(self) 763*7dc08ffcSJunyu Lai 764*7dc08ffcSJunyu Lai 765*7dc08ffcSJunyu Laiclass UDPerror(UDP): 766*7dc08ffcSJunyu Lai name = "UDP in ICMP" 767*7dc08ffcSJunyu Lai def answers(self, other): 768*7dc08ffcSJunyu Lai if not isinstance(other, UDP): 769*7dc08ffcSJunyu Lai return 0 770*7dc08ffcSJunyu Lai if conf.checkIPsrc: 771*7dc08ffcSJunyu Lai if not ((self.sport == other.sport) and 772*7dc08ffcSJunyu Lai (self.dport == other.dport)): 773*7dc08ffcSJunyu Lai return 0 774*7dc08ffcSJunyu Lai return 1 775*7dc08ffcSJunyu Lai def mysummary(self): 776*7dc08ffcSJunyu Lai return Packet.mysummary(self) 777*7dc08ffcSJunyu Lai 778*7dc08ffcSJunyu Lai 779*7dc08ffcSJunyu Lai 780*7dc08ffcSJunyu Laiclass ICMPerror(ICMP): 781*7dc08ffcSJunyu Lai name = "ICMP in ICMP" 782*7dc08ffcSJunyu Lai def answers(self, other): 783*7dc08ffcSJunyu Lai if not isinstance(other,ICMP): 784*7dc08ffcSJunyu Lai return 0 785*7dc08ffcSJunyu Lai if not ((self.type == other.type) and 786*7dc08ffcSJunyu Lai (self.code == other.code)): 787*7dc08ffcSJunyu Lai return 0 788*7dc08ffcSJunyu Lai if self.code in [0,8,13,14,17,18]: 789*7dc08ffcSJunyu Lai if (self.id == other.id and 790*7dc08ffcSJunyu Lai self.seq == other.seq): 791*7dc08ffcSJunyu Lai return 1 792*7dc08ffcSJunyu Lai else: 793*7dc08ffcSJunyu Lai return 0 794*7dc08ffcSJunyu Lai else: 795*7dc08ffcSJunyu Lai return 1 796*7dc08ffcSJunyu Lai def mysummary(self): 797*7dc08ffcSJunyu Lai return Packet.mysummary(self) 798*7dc08ffcSJunyu Lai 799*7dc08ffcSJunyu Laibind_layers( Ether, IP, type=2048) 800*7dc08ffcSJunyu Laibind_layers( CookedLinux, IP, proto=2048) 801*7dc08ffcSJunyu Laibind_layers( GRE, IP, proto=2048) 802*7dc08ffcSJunyu Laibind_layers( SNAP, IP, code=2048) 803*7dc08ffcSJunyu Laibind_layers( Loopback, IP, type=0) 804*7dc08ffcSJunyu Laibind_layers( Loopback, IP, type=2) 805*7dc08ffcSJunyu Laibind_layers( IPerror, IPerror, frag=0, proto=4) 806*7dc08ffcSJunyu Laibind_layers( IPerror, ICMPerror, frag=0, proto=1) 807*7dc08ffcSJunyu Laibind_layers( IPerror, TCPerror, frag=0, proto=6) 808*7dc08ffcSJunyu Laibind_layers( IPerror, UDPerror, frag=0, proto=17) 809*7dc08ffcSJunyu Laibind_layers( IP, IP, frag=0, proto=4) 810*7dc08ffcSJunyu Laibind_layers( IP, ICMP, frag=0, proto=1) 811*7dc08ffcSJunyu Laibind_layers( IP, TCP, frag=0, proto=6) 812*7dc08ffcSJunyu Laibind_layers( IP, UDP, frag=0, proto=17) 813*7dc08ffcSJunyu Laibind_layers( IP, GRE, frag=0, proto=47) 814*7dc08ffcSJunyu Lai 815*7dc08ffcSJunyu Laiconf.l2types.register(DLT_RAW, IP) 816*7dc08ffcSJunyu Laiconf.l2types.register_num2layer(DLT_RAW_ALT, IP) 817*7dc08ffcSJunyu Laiconf.l2types.register(DLT_IPV4, IP) 818*7dc08ffcSJunyu Lai 819*7dc08ffcSJunyu Laiconf.l3types.register(ETH_P_IP, IP) 820*7dc08ffcSJunyu Laiconf.l3types.register_num2layer(ETH_P_ALL, IP) 821*7dc08ffcSJunyu Lai 822*7dc08ffcSJunyu Lai 823*7dc08ffcSJunyu Laidef inet_register_l3(l2, l3): 824*7dc08ffcSJunyu Lai return getmacbyip(l3.dst) 825*7dc08ffcSJunyu Laiconf.neighbor.register_l3(Ether, IP, inet_register_l3) 826*7dc08ffcSJunyu Laiconf.neighbor.register_l3(Dot3, IP, inet_register_l3) 827*7dc08ffcSJunyu Lai 828*7dc08ffcSJunyu Lai 829*7dc08ffcSJunyu Lai################### 830*7dc08ffcSJunyu Lai## Fragmentation ## 831*7dc08ffcSJunyu Lai################### 832*7dc08ffcSJunyu Lai 833*7dc08ffcSJunyu Lai@conf.commands.register 834*7dc08ffcSJunyu Laidef fragment(pkt, fragsize=1480): 835*7dc08ffcSJunyu Lai """Fragment a big IP datagram""" 836*7dc08ffcSJunyu Lai fragsize = (fragsize+7)//8*8 837*7dc08ffcSJunyu Lai lst = [] 838*7dc08ffcSJunyu Lai for p in pkt: 839*7dc08ffcSJunyu Lai s = raw(p[IP].payload) 840*7dc08ffcSJunyu Lai nb = (len(s)+fragsize-1)//fragsize 841*7dc08ffcSJunyu Lai for i in range(nb): 842*7dc08ffcSJunyu Lai q = p.copy() 843*7dc08ffcSJunyu Lai del(q[IP].payload) 844*7dc08ffcSJunyu Lai del(q[IP].chksum) 845*7dc08ffcSJunyu Lai del(q[IP].len) 846*7dc08ffcSJunyu Lai if i != nb - 1: 847*7dc08ffcSJunyu Lai q[IP].flags |= 1 848*7dc08ffcSJunyu Lai q[IP].frag += i * fragsize // 8 849*7dc08ffcSJunyu Lai r = conf.raw_layer(load=s[i*fragsize:(i+1)*fragsize]) 850*7dc08ffcSJunyu Lai r.overload_fields = p[IP].payload.overload_fields.copy() 851*7dc08ffcSJunyu Lai q.add_payload(r) 852*7dc08ffcSJunyu Lai lst.append(q) 853*7dc08ffcSJunyu Lai return lst 854*7dc08ffcSJunyu Lai 855*7dc08ffcSJunyu Lai@conf.commands.register 856*7dc08ffcSJunyu Laidef overlap_frag(p, overlap, fragsize=8, overlap_fragsize=None): 857*7dc08ffcSJunyu Lai """Build overlapping fragments to bypass NIPS 858*7dc08ffcSJunyu Lai 859*7dc08ffcSJunyu Laip: the original packet 860*7dc08ffcSJunyu Laioverlap: the overlapping data 861*7dc08ffcSJunyu Laifragsize: the fragment size of the packet 862*7dc08ffcSJunyu Laioverlap_fragsize: the fragment size of the overlapping packet""" 863*7dc08ffcSJunyu Lai 864*7dc08ffcSJunyu Lai if overlap_fragsize is None: 865*7dc08ffcSJunyu Lai overlap_fragsize = fragsize 866*7dc08ffcSJunyu Lai q = p.copy() 867*7dc08ffcSJunyu Lai del(q[IP].payload) 868*7dc08ffcSJunyu Lai q[IP].add_payload(overlap) 869*7dc08ffcSJunyu Lai 870*7dc08ffcSJunyu Lai qfrag = fragment(q, overlap_fragsize) 871*7dc08ffcSJunyu Lai qfrag[-1][IP].flags |= 1 872*7dc08ffcSJunyu Lai return qfrag+fragment(p, fragsize) 873*7dc08ffcSJunyu Lai 874*7dc08ffcSJunyu Lai@conf.commands.register 875*7dc08ffcSJunyu Laidef defrag(plist): 876*7dc08ffcSJunyu Lai """defrag(plist) -> ([not fragmented], [defragmented], 877*7dc08ffcSJunyu Lai [ [bad fragments], [bad fragments], ... ])""" 878*7dc08ffcSJunyu Lai frags = defaultdict(PacketList) 879*7dc08ffcSJunyu Lai nofrag = PacketList() 880*7dc08ffcSJunyu Lai for p in plist: 881*7dc08ffcSJunyu Lai if IP not in p: 882*7dc08ffcSJunyu Lai nofrag.append(p) 883*7dc08ffcSJunyu Lai continue 884*7dc08ffcSJunyu Lai ip = p[IP] 885*7dc08ffcSJunyu Lai if ip.frag == 0 and ip.flags & 1 == 0: 886*7dc08ffcSJunyu Lai nofrag.append(p) 887*7dc08ffcSJunyu Lai continue 888*7dc08ffcSJunyu Lai uniq = (ip.id,ip.src,ip.dst,ip.proto) 889*7dc08ffcSJunyu Lai frags[uniq].append(p) 890*7dc08ffcSJunyu Lai defrag = [] 891*7dc08ffcSJunyu Lai missfrag = [] 892*7dc08ffcSJunyu Lai for lst in six.itervalues(frags): 893*7dc08ffcSJunyu Lai lst.sort(key=lambda x: x.frag) 894*7dc08ffcSJunyu Lai p = lst[0] 895*7dc08ffcSJunyu Lai lastp = lst[-1] 896*7dc08ffcSJunyu Lai if p.frag > 0 or lastp.flags & 1 != 0: # first or last fragment missing 897*7dc08ffcSJunyu Lai missfrag.append(lst) 898*7dc08ffcSJunyu Lai continue 899*7dc08ffcSJunyu Lai p = p.copy() 900*7dc08ffcSJunyu Lai if conf.padding_layer in p: 901*7dc08ffcSJunyu Lai del(p[conf.padding_layer].underlayer.payload) 902*7dc08ffcSJunyu Lai ip = p[IP] 903*7dc08ffcSJunyu Lai if ip.len is None or ip.ihl is None: 904*7dc08ffcSJunyu Lai clen = len(ip.payload) 905*7dc08ffcSJunyu Lai else: 906*7dc08ffcSJunyu Lai clen = ip.len - (ip.ihl<<2) 907*7dc08ffcSJunyu Lai txt = conf.raw_layer() 908*7dc08ffcSJunyu Lai for q in lst[1:]: 909*7dc08ffcSJunyu Lai if clen != q.frag<<3: # Wrong fragmentation offset 910*7dc08ffcSJunyu Lai if clen > q.frag<<3: 911*7dc08ffcSJunyu Lai warning("Fragment overlap (%i > %i) %r || %r || %r" % (clen, q.frag<<3, p,txt,q)) 912*7dc08ffcSJunyu Lai missfrag.append(lst) 913*7dc08ffcSJunyu Lai break 914*7dc08ffcSJunyu Lai if q[IP].len is None or q[IP].ihl is None: 915*7dc08ffcSJunyu Lai clen += len(q[IP].payload) 916*7dc08ffcSJunyu Lai else: 917*7dc08ffcSJunyu Lai clen += q[IP].len - (q[IP].ihl<<2) 918*7dc08ffcSJunyu Lai if conf.padding_layer in q: 919*7dc08ffcSJunyu Lai del(q[conf.padding_layer].underlayer.payload) 920*7dc08ffcSJunyu Lai txt.add_payload(q[IP].payload.copy()) 921*7dc08ffcSJunyu Lai else: 922*7dc08ffcSJunyu Lai ip.flags &= ~1 # !MF 923*7dc08ffcSJunyu Lai del(ip.chksum) 924*7dc08ffcSJunyu Lai del(ip.len) 925*7dc08ffcSJunyu Lai p = p/txt 926*7dc08ffcSJunyu Lai defrag.append(p) 927*7dc08ffcSJunyu Lai defrag2=PacketList() 928*7dc08ffcSJunyu Lai for p in defrag: 929*7dc08ffcSJunyu Lai defrag2.append(p.__class__(raw(p))) 930*7dc08ffcSJunyu Lai return nofrag,defrag2,missfrag 931*7dc08ffcSJunyu Lai 932*7dc08ffcSJunyu Lai@conf.commands.register 933*7dc08ffcSJunyu Laidef defragment(plist): 934*7dc08ffcSJunyu Lai """defrag(plist) -> plist defragmented as much as possible """ 935*7dc08ffcSJunyu Lai frags = defaultdict(lambda:[]) 936*7dc08ffcSJunyu Lai final = [] 937*7dc08ffcSJunyu Lai 938*7dc08ffcSJunyu Lai pos = 0 939*7dc08ffcSJunyu Lai for p in plist: 940*7dc08ffcSJunyu Lai p._defrag_pos = pos 941*7dc08ffcSJunyu Lai pos += 1 942*7dc08ffcSJunyu Lai if IP in p: 943*7dc08ffcSJunyu Lai ip = p[IP] 944*7dc08ffcSJunyu Lai if ip.frag != 0 or ip.flags & 1: 945*7dc08ffcSJunyu Lai ip = p[IP] 946*7dc08ffcSJunyu Lai uniq = (ip.id,ip.src,ip.dst,ip.proto) 947*7dc08ffcSJunyu Lai frags[uniq].append(p) 948*7dc08ffcSJunyu Lai continue 949*7dc08ffcSJunyu Lai final.append(p) 950*7dc08ffcSJunyu Lai 951*7dc08ffcSJunyu Lai defrag = [] 952*7dc08ffcSJunyu Lai missfrag = [] 953*7dc08ffcSJunyu Lai for lst in six.itervalues(frags): 954*7dc08ffcSJunyu Lai lst.sort(key=lambda x: x.frag) 955*7dc08ffcSJunyu Lai p = lst[0] 956*7dc08ffcSJunyu Lai lastp = lst[-1] 957*7dc08ffcSJunyu Lai if p.frag > 0 or lastp.flags & 1 != 0: # first or last fragment missing 958*7dc08ffcSJunyu Lai missfrag += lst 959*7dc08ffcSJunyu Lai continue 960*7dc08ffcSJunyu Lai p = p.copy() 961*7dc08ffcSJunyu Lai if conf.padding_layer in p: 962*7dc08ffcSJunyu Lai del(p[conf.padding_layer].underlayer.payload) 963*7dc08ffcSJunyu Lai ip = p[IP] 964*7dc08ffcSJunyu Lai if ip.len is None or ip.ihl is None: 965*7dc08ffcSJunyu Lai clen = len(ip.payload) 966*7dc08ffcSJunyu Lai else: 967*7dc08ffcSJunyu Lai clen = ip.len - (ip.ihl<<2) 968*7dc08ffcSJunyu Lai txt = conf.raw_layer() 969*7dc08ffcSJunyu Lai for q in lst[1:]: 970*7dc08ffcSJunyu Lai if clen != q.frag<<3: # Wrong fragmentation offset 971*7dc08ffcSJunyu Lai if clen > q.frag<<3: 972*7dc08ffcSJunyu Lai warning("Fragment overlap (%i > %i) %r || %r || %r" % (clen, q.frag<<3, p,txt,q)) 973*7dc08ffcSJunyu Lai missfrag += lst 974*7dc08ffcSJunyu Lai break 975*7dc08ffcSJunyu Lai if q[IP].len is None or q[IP].ihl is None: 976*7dc08ffcSJunyu Lai clen += len(q[IP].payload) 977*7dc08ffcSJunyu Lai else: 978*7dc08ffcSJunyu Lai clen += q[IP].len - (q[IP].ihl<<2) 979*7dc08ffcSJunyu Lai if conf.padding_layer in q: 980*7dc08ffcSJunyu Lai del(q[conf.padding_layer].underlayer.payload) 981*7dc08ffcSJunyu Lai txt.add_payload(q[IP].payload.copy()) 982*7dc08ffcSJunyu Lai else: 983*7dc08ffcSJunyu Lai ip.flags &= ~1 # !MF 984*7dc08ffcSJunyu Lai del(ip.chksum) 985*7dc08ffcSJunyu Lai del(ip.len) 986*7dc08ffcSJunyu Lai p = p/txt 987*7dc08ffcSJunyu Lai p._defrag_pos = max(x._defrag_pos for x in lst) 988*7dc08ffcSJunyu Lai defrag.append(p) 989*7dc08ffcSJunyu Lai defrag2=[] 990*7dc08ffcSJunyu Lai for p in defrag: 991*7dc08ffcSJunyu Lai q = p.__class__(raw(p)) 992*7dc08ffcSJunyu Lai q._defrag_pos = p._defrag_pos 993*7dc08ffcSJunyu Lai defrag2.append(q) 994*7dc08ffcSJunyu Lai final += defrag2 995*7dc08ffcSJunyu Lai final += missfrag 996*7dc08ffcSJunyu Lai final.sort(key=lambda x: x._defrag_pos) 997*7dc08ffcSJunyu Lai for p in final: 998*7dc08ffcSJunyu Lai del(p._defrag_pos) 999*7dc08ffcSJunyu Lai 1000*7dc08ffcSJunyu Lai if hasattr(plist, "listname"): 1001*7dc08ffcSJunyu Lai name = "Defragmented %s" % plist.listname 1002*7dc08ffcSJunyu Lai else: 1003*7dc08ffcSJunyu Lai name = "Defragmented" 1004*7dc08ffcSJunyu Lai 1005*7dc08ffcSJunyu Lai return PacketList(final, name=name) 1006*7dc08ffcSJunyu Lai 1007*7dc08ffcSJunyu Lai 1008*7dc08ffcSJunyu Lai 1009*7dc08ffcSJunyu Lai### Add timeskew_graph() method to PacketList 1010*7dc08ffcSJunyu Laidef _packetlist_timeskew_graph(self, ip, **kargs): 1011*7dc08ffcSJunyu Lai """Tries to graph the timeskew between the timestamps and real time for a given ip""" 1012*7dc08ffcSJunyu Lai 1013*7dc08ffcSJunyu Lai # Filter TCP segments which source address is 'ip' 1014*7dc08ffcSJunyu Lai tmp = (self._elt2pkt(x) for x in self.res) 1015*7dc08ffcSJunyu Lai b = (x for x in tmp if IP in x and x[IP].src == ip and TCP in x) 1016*7dc08ffcSJunyu Lai 1017*7dc08ffcSJunyu Lai # Build a list of tuples (creation_time, replied_timestamp) 1018*7dc08ffcSJunyu Lai c = [] 1019*7dc08ffcSJunyu Lai tsf = ICMPTimeStampField("", None) 1020*7dc08ffcSJunyu Lai for p in b: 1021*7dc08ffcSJunyu Lai opts = p.getlayer(TCP).options 1022*7dc08ffcSJunyu Lai for o in opts: 1023*7dc08ffcSJunyu Lai if o[0] == "Timestamp": 1024*7dc08ffcSJunyu Lai c.append((p.time, tsf.any2i("", o[1][0]))) 1025*7dc08ffcSJunyu Lai 1026*7dc08ffcSJunyu Lai # Stop if the list is empty 1027*7dc08ffcSJunyu Lai if not c: 1028*7dc08ffcSJunyu Lai warning("No timestamps found in packet list") 1029*7dc08ffcSJunyu Lai return [] 1030*7dc08ffcSJunyu Lai 1031*7dc08ffcSJunyu Lai # Prepare the data that will be plotted 1032*7dc08ffcSJunyu Lai first_creation_time = c[0][0] 1033*7dc08ffcSJunyu Lai first_replied_timestamp = c[0][1] 1034*7dc08ffcSJunyu Lai 1035*7dc08ffcSJunyu Lai def _wrap_data(ts_tuple, wrap_seconds=2000): 1036*7dc08ffcSJunyu Lai """Wrap the list of tuples.""" 1037*7dc08ffcSJunyu Lai 1038*7dc08ffcSJunyu Lai ct,rt = ts_tuple # (creation_time, replied_timestamp) 1039*7dc08ffcSJunyu Lai X = ct % wrap_seconds 1040*7dc08ffcSJunyu Lai Y = ((ct-first_creation_time) - ((rt-first_replied_timestamp)/1000.0)) 1041*7dc08ffcSJunyu Lai 1042*7dc08ffcSJunyu Lai return X, Y 1043*7dc08ffcSJunyu Lai 1044*7dc08ffcSJunyu Lai data = [_wrap_data(e) for e in c] 1045*7dc08ffcSJunyu Lai 1046*7dc08ffcSJunyu Lai # Mimic the default gnuplot output 1047*7dc08ffcSJunyu Lai if kargs == {}: 1048*7dc08ffcSJunyu Lai kargs = MATPLOTLIB_DEFAULT_PLOT_KARGS 1049*7dc08ffcSJunyu Lai lines = plt.plot(data, **kargs) 1050*7dc08ffcSJunyu Lai 1051*7dc08ffcSJunyu Lai # Call show() if matplotlib is not inlined 1052*7dc08ffcSJunyu Lai if not MATPLOTLIB_INLINED: 1053*7dc08ffcSJunyu Lai plt.show() 1054*7dc08ffcSJunyu Lai 1055*7dc08ffcSJunyu Lai return lines 1056*7dc08ffcSJunyu Lai 1057*7dc08ffcSJunyu LaiPacketList.timeskew_graph = _packetlist_timeskew_graph 1058*7dc08ffcSJunyu Lai 1059*7dc08ffcSJunyu Lai 1060*7dc08ffcSJunyu Lai### Create a new packet list 1061*7dc08ffcSJunyu Laiclass TracerouteResult(SndRcvList): 1062*7dc08ffcSJunyu Lai __slots__ = ["graphdef", "graphpadding", "graphASres", "padding", "hloc", 1063*7dc08ffcSJunyu Lai "nloc"] 1064*7dc08ffcSJunyu Lai def __init__(self, res=None, name="Traceroute", stats=None): 1065*7dc08ffcSJunyu Lai PacketList.__init__(self, res, name, stats) 1066*7dc08ffcSJunyu Lai self.graphdef = None 1067*7dc08ffcSJunyu Lai self.graphASres = 0 1068*7dc08ffcSJunyu Lai self.padding = 0 1069*7dc08ffcSJunyu Lai self.hloc = None 1070*7dc08ffcSJunyu Lai self.nloc = None 1071*7dc08ffcSJunyu Lai 1072*7dc08ffcSJunyu Lai def show(self): 1073*7dc08ffcSJunyu Lai return self.make_table(lambda s_r: (s_r[0].sprintf("%IP.dst%:{TCP:tcp%ir,TCP.dport%}{UDP:udp%ir,UDP.dport%}{ICMP:ICMP}"), 1074*7dc08ffcSJunyu Lai s_r[0].ttl, 1075*7dc08ffcSJunyu Lai s_r[1].sprintf("%-15s,IP.src% {TCP:%TCP.flags%}{ICMP:%ir,ICMP.type%}"))) 1076*7dc08ffcSJunyu Lai 1077*7dc08ffcSJunyu Lai 1078*7dc08ffcSJunyu Lai def get_trace(self): 1079*7dc08ffcSJunyu Lai trace = {} 1080*7dc08ffcSJunyu Lai for s,r in self.res: 1081*7dc08ffcSJunyu Lai if IP not in s: 1082*7dc08ffcSJunyu Lai continue 1083*7dc08ffcSJunyu Lai d = s[IP].dst 1084*7dc08ffcSJunyu Lai if d not in trace: 1085*7dc08ffcSJunyu Lai trace[d] = {} 1086*7dc08ffcSJunyu Lai trace[d][s[IP].ttl] = r[IP].src, ICMP not in r 1087*7dc08ffcSJunyu Lai for k in six.itervalues(trace): 1088*7dc08ffcSJunyu Lai try: 1089*7dc08ffcSJunyu Lai m = min(x for x, y in six.itervalues(k) if y) 1090*7dc08ffcSJunyu Lai except ValueError: 1091*7dc08ffcSJunyu Lai continue 1092*7dc08ffcSJunyu Lai for l in list(k): # use list(): k is modified in the loop 1093*7dc08ffcSJunyu Lai if l > m: 1094*7dc08ffcSJunyu Lai del k[l] 1095*7dc08ffcSJunyu Lai return trace 1096*7dc08ffcSJunyu Lai 1097*7dc08ffcSJunyu Lai def trace3D(self): 1098*7dc08ffcSJunyu Lai """Give a 3D representation of the traceroute. 1099*7dc08ffcSJunyu Lai right button: rotate the scene 1100*7dc08ffcSJunyu Lai middle button: zoom 1101*7dc08ffcSJunyu Lai left button: move the scene 1102*7dc08ffcSJunyu Lai left button on a ball: toggle IP displaying 1103*7dc08ffcSJunyu Lai ctrl-left button on a ball: scan ports 21,22,23,25,80 and 443 and display the result""" 1104*7dc08ffcSJunyu Lai trace = self.get_trace() 1105*7dc08ffcSJunyu Lai import visual 1106*7dc08ffcSJunyu Lai 1107*7dc08ffcSJunyu Lai class IPsphere(visual.sphere): 1108*7dc08ffcSJunyu Lai def __init__(self, ip, **kargs): 1109*7dc08ffcSJunyu Lai visual.sphere.__init__(self, **kargs) 1110*7dc08ffcSJunyu Lai self.ip=ip 1111*7dc08ffcSJunyu Lai self.label=None 1112*7dc08ffcSJunyu Lai self.setlabel(self.ip) 1113*7dc08ffcSJunyu Lai def setlabel(self, txt,visible=None): 1114*7dc08ffcSJunyu Lai if self.label is not None: 1115*7dc08ffcSJunyu Lai if visible is None: 1116*7dc08ffcSJunyu Lai visible = self.label.visible 1117*7dc08ffcSJunyu Lai self.label.visible = 0 1118*7dc08ffcSJunyu Lai elif visible is None: 1119*7dc08ffcSJunyu Lai visible=0 1120*7dc08ffcSJunyu Lai self.label=visual.label(text=txt, pos=self.pos, space=self.radius, xoffset=10, yoffset=20, visible=visible) 1121*7dc08ffcSJunyu Lai def action(self): 1122*7dc08ffcSJunyu Lai self.label.visible ^= 1 1123*7dc08ffcSJunyu Lai 1124*7dc08ffcSJunyu Lai visual.scene = visual.display() 1125*7dc08ffcSJunyu Lai visual.scene.exit = True 1126*7dc08ffcSJunyu Lai start = visual.box() 1127*7dc08ffcSJunyu Lai rings={} 1128*7dc08ffcSJunyu Lai tr3d = {} 1129*7dc08ffcSJunyu Lai for i in trace: 1130*7dc08ffcSJunyu Lai tr = trace[i] 1131*7dc08ffcSJunyu Lai tr3d[i] = [] 1132*7dc08ffcSJunyu Lai for t in range(1, max(tr) + 1): 1133*7dc08ffcSJunyu Lai if t not in rings: 1134*7dc08ffcSJunyu Lai rings[t] = [] 1135*7dc08ffcSJunyu Lai if t in tr: 1136*7dc08ffcSJunyu Lai if tr[t] not in rings[t]: 1137*7dc08ffcSJunyu Lai rings[t].append(tr[t]) 1138*7dc08ffcSJunyu Lai tr3d[i].append(rings[t].index(tr[t])) 1139*7dc08ffcSJunyu Lai else: 1140*7dc08ffcSJunyu Lai rings[t].append(("unk",-1)) 1141*7dc08ffcSJunyu Lai tr3d[i].append(len(rings[t])-1) 1142*7dc08ffcSJunyu Lai for t in rings: 1143*7dc08ffcSJunyu Lai r = rings[t] 1144*7dc08ffcSJunyu Lai l = len(r) 1145*7dc08ffcSJunyu Lai for i in range(l): 1146*7dc08ffcSJunyu Lai if r[i][1] == -1: 1147*7dc08ffcSJunyu Lai col = (0.75,0.75,0.75) 1148*7dc08ffcSJunyu Lai elif r[i][1]: 1149*7dc08ffcSJunyu Lai col = visual.color.green 1150*7dc08ffcSJunyu Lai else: 1151*7dc08ffcSJunyu Lai col = visual.color.blue 1152*7dc08ffcSJunyu Lai 1153*7dc08ffcSJunyu Lai s = IPsphere(pos=((l-1)*visual.cos(2*i*visual.pi/l),(l-1)*visual.sin(2*i*visual.pi/l),2*t), 1154*7dc08ffcSJunyu Lai ip = r[i][0], 1155*7dc08ffcSJunyu Lai color = col) 1156*7dc08ffcSJunyu Lai for trlst in six.itervalues(tr3d): 1157*7dc08ffcSJunyu Lai if t <= len(trlst): 1158*7dc08ffcSJunyu Lai if trlst[t-1] == i: 1159*7dc08ffcSJunyu Lai trlst[t-1] = s 1160*7dc08ffcSJunyu Lai forecol = colgen(0.625, 0.4375, 0.25, 0.125) 1161*7dc08ffcSJunyu Lai for trlst in six.itervalues(tr3d): 1162*7dc08ffcSJunyu Lai col = next(forecol) 1163*7dc08ffcSJunyu Lai start = (0,0,0) 1164*7dc08ffcSJunyu Lai for ip in trlst: 1165*7dc08ffcSJunyu Lai visual.cylinder(pos=start,axis=ip.pos-start,color=col,radius=0.2) 1166*7dc08ffcSJunyu Lai start = ip.pos 1167*7dc08ffcSJunyu Lai 1168*7dc08ffcSJunyu Lai movcenter=None 1169*7dc08ffcSJunyu Lai while True: 1170*7dc08ffcSJunyu Lai visual.rate(50) 1171*7dc08ffcSJunyu Lai if visual.scene.kb.keys: 1172*7dc08ffcSJunyu Lai k = visual.scene.kb.getkey() 1173*7dc08ffcSJunyu Lai if k == "esc" or k == "q": 1174*7dc08ffcSJunyu Lai break 1175*7dc08ffcSJunyu Lai if visual.scene.mouse.events: 1176*7dc08ffcSJunyu Lai ev = visual.scene.mouse.getevent() 1177*7dc08ffcSJunyu Lai if ev.press == "left": 1178*7dc08ffcSJunyu Lai o = ev.pick 1179*7dc08ffcSJunyu Lai if o: 1180*7dc08ffcSJunyu Lai if ev.ctrl: 1181*7dc08ffcSJunyu Lai if o.ip == "unk": 1182*7dc08ffcSJunyu Lai continue 1183*7dc08ffcSJunyu Lai savcolor = o.color 1184*7dc08ffcSJunyu Lai o.color = (1,0,0) 1185*7dc08ffcSJunyu Lai a,b=sr(IP(dst=o.ip)/TCP(dport=[21,22,23,25,80,443]),timeout=2) 1186*7dc08ffcSJunyu Lai o.color = savcolor 1187*7dc08ffcSJunyu Lai if len(a) == 0: 1188*7dc08ffcSJunyu Lai txt = "%s:\nno results" % o.ip 1189*7dc08ffcSJunyu Lai else: 1190*7dc08ffcSJunyu Lai txt = "%s:\n" % o.ip 1191*7dc08ffcSJunyu Lai for s,r in a: 1192*7dc08ffcSJunyu Lai txt += r.sprintf("{TCP:%IP.src%:%TCP.sport% %TCP.flags%}{TCPerror:%IPerror.dst%:%TCPerror.dport% %IP.src% %ir,ICMP.type%}\n") 1193*7dc08ffcSJunyu Lai o.setlabel(txt, visible=1) 1194*7dc08ffcSJunyu Lai else: 1195*7dc08ffcSJunyu Lai if hasattr(o, "action"): 1196*7dc08ffcSJunyu Lai o.action() 1197*7dc08ffcSJunyu Lai elif ev.drag == "left": 1198*7dc08ffcSJunyu Lai movcenter = ev.pos 1199*7dc08ffcSJunyu Lai elif ev.drop == "left": 1200*7dc08ffcSJunyu Lai movcenter = None 1201*7dc08ffcSJunyu Lai if movcenter: 1202*7dc08ffcSJunyu Lai visual.scene.center -= visual.scene.mouse.pos-movcenter 1203*7dc08ffcSJunyu Lai movcenter = visual.scene.mouse.pos 1204*7dc08ffcSJunyu Lai 1205*7dc08ffcSJunyu Lai 1206*7dc08ffcSJunyu Lai def world_trace(self, **kargs): 1207*7dc08ffcSJunyu Lai """Display traceroute results on a world map.""" 1208*7dc08ffcSJunyu Lai 1209*7dc08ffcSJunyu Lai # Check that the GeoIP module can be imported 1210*7dc08ffcSJunyu Lai try: 1211*7dc08ffcSJunyu Lai import GeoIP 1212*7dc08ffcSJunyu Lai except ImportError: 1213*7dc08ffcSJunyu Lai message = "Can't import GeoIP. Won't be able to plot the world." 1214*7dc08ffcSJunyu Lai scapy.utils.log_loading.info(message) 1215*7dc08ffcSJunyu Lai return list() 1216*7dc08ffcSJunyu Lai 1217*7dc08ffcSJunyu Lai # Check if this is an IPv6 traceroute and load the correct file 1218*7dc08ffcSJunyu Lai if isinstance(self, scapy.layers.inet6.TracerouteResult6): 1219*7dc08ffcSJunyu Lai geoip_city_filename = conf.geoip_city_ipv6 1220*7dc08ffcSJunyu Lai else: 1221*7dc08ffcSJunyu Lai geoip_city_filename = conf.geoip_city 1222*7dc08ffcSJunyu Lai 1223*7dc08ffcSJunyu Lai # Check that the GeoIP database can be opened 1224*7dc08ffcSJunyu Lai try: 1225*7dc08ffcSJunyu Lai db = GeoIP.open(conf.geoip_city, 0) 1226*7dc08ffcSJunyu Lai except: 1227*7dc08ffcSJunyu Lai message = "Can't open GeoIP database at %s" % conf.geoip_city 1228*7dc08ffcSJunyu Lai scapy.utils.log_loading.info(message) 1229*7dc08ffcSJunyu Lai return list() 1230*7dc08ffcSJunyu Lai 1231*7dc08ffcSJunyu Lai # Regroup results per trace 1232*7dc08ffcSJunyu Lai ips = {} 1233*7dc08ffcSJunyu Lai rt = {} 1234*7dc08ffcSJunyu Lai ports_done = {} 1235*7dc08ffcSJunyu Lai for s,r in self.res: 1236*7dc08ffcSJunyu Lai ips[r.src] = None 1237*7dc08ffcSJunyu Lai if s.haslayer(TCP) or s.haslayer(UDP): 1238*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,s.proto,s.dport) 1239*7dc08ffcSJunyu Lai elif s.haslayer(ICMP): 1240*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,s.proto,s.type) 1241*7dc08ffcSJunyu Lai else: 1242*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,s.proto,0) 1243*7dc08ffcSJunyu Lai trace = rt.get(trace_id,{}) 1244*7dc08ffcSJunyu Lai if not r.haslayer(ICMP) or r.type != 11: 1245*7dc08ffcSJunyu Lai if trace_id in ports_done: 1246*7dc08ffcSJunyu Lai continue 1247*7dc08ffcSJunyu Lai ports_done[trace_id] = None 1248*7dc08ffcSJunyu Lai trace[s.ttl] = r.src 1249*7dc08ffcSJunyu Lai rt[trace_id] = trace 1250*7dc08ffcSJunyu Lai 1251*7dc08ffcSJunyu Lai # Get the addresses locations 1252*7dc08ffcSJunyu Lai trt = {} 1253*7dc08ffcSJunyu Lai for trace_id in rt: 1254*7dc08ffcSJunyu Lai trace = rt[trace_id] 1255*7dc08ffcSJunyu Lai loctrace = [] 1256*7dc08ffcSJunyu Lai for i in range(max(trace)): 1257*7dc08ffcSJunyu Lai ip = trace.get(i,None) 1258*7dc08ffcSJunyu Lai if ip is None: 1259*7dc08ffcSJunyu Lai continue 1260*7dc08ffcSJunyu Lai loc = db.record_by_addr(ip) 1261*7dc08ffcSJunyu Lai if loc is None: 1262*7dc08ffcSJunyu Lai continue 1263*7dc08ffcSJunyu Lai loc = loc.get('longitude'), loc.get('latitude') 1264*7dc08ffcSJunyu Lai if loc == (None, None): 1265*7dc08ffcSJunyu Lai continue 1266*7dc08ffcSJunyu Lai loctrace.append(loc) 1267*7dc08ffcSJunyu Lai if loctrace: 1268*7dc08ffcSJunyu Lai trt[trace_id] = loctrace 1269*7dc08ffcSJunyu Lai 1270*7dc08ffcSJunyu Lai # Load the map renderer 1271*7dc08ffcSJunyu Lai from mpl_toolkits.basemap import Basemap 1272*7dc08ffcSJunyu Lai bmap = Basemap() 1273*7dc08ffcSJunyu Lai 1274*7dc08ffcSJunyu Lai # Split latitudes and longitudes per traceroute measurement 1275*7dc08ffcSJunyu Lai locations = [zip(*tr) for tr in six.itervalues(trt)] 1276*7dc08ffcSJunyu Lai 1277*7dc08ffcSJunyu Lai # Plot the traceroute measurement as lines in the map 1278*7dc08ffcSJunyu Lai lines = [bmap.plot(*bmap(lons, lats)) for lons, lats in locations] 1279*7dc08ffcSJunyu Lai 1280*7dc08ffcSJunyu Lai # Draw countries 1281*7dc08ffcSJunyu Lai bmap.drawcoastlines() 1282*7dc08ffcSJunyu Lai 1283*7dc08ffcSJunyu Lai # Call show() if matplotlib is not inlined 1284*7dc08ffcSJunyu Lai if not MATPLOTLIB_INLINED: 1285*7dc08ffcSJunyu Lai plt.show() 1286*7dc08ffcSJunyu Lai 1287*7dc08ffcSJunyu Lai # Return the drawn lines 1288*7dc08ffcSJunyu Lai return lines 1289*7dc08ffcSJunyu Lai 1290*7dc08ffcSJunyu Lai def make_graph(self,ASres=None,padding=0): 1291*7dc08ffcSJunyu Lai if ASres is None: 1292*7dc08ffcSJunyu Lai ASres = conf.AS_resolver 1293*7dc08ffcSJunyu Lai self.graphASres = ASres 1294*7dc08ffcSJunyu Lai self.graphpadding = padding 1295*7dc08ffcSJunyu Lai ips = {} 1296*7dc08ffcSJunyu Lai rt = {} 1297*7dc08ffcSJunyu Lai ports = {} 1298*7dc08ffcSJunyu Lai ports_done = {} 1299*7dc08ffcSJunyu Lai for s,r in self.res: 1300*7dc08ffcSJunyu Lai r = r.getlayer(IP) or (conf.ipv6_enabled and r[scapy.layers.inet6.IPv6]) or r 1301*7dc08ffcSJunyu Lai s = s.getlayer(IP) or (conf.ipv6_enabled and s[scapy.layers.inet6.IPv6]) or s 1302*7dc08ffcSJunyu Lai ips[r.src] = None 1303*7dc08ffcSJunyu Lai if TCP in s: 1304*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,6,s.dport) 1305*7dc08ffcSJunyu Lai elif UDP in s: 1306*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,17,s.dport) 1307*7dc08ffcSJunyu Lai elif ICMP in s: 1308*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,1,s.type) 1309*7dc08ffcSJunyu Lai else: 1310*7dc08ffcSJunyu Lai trace_id = (s.src,s.dst,s.proto,0) 1311*7dc08ffcSJunyu Lai trace = rt.get(trace_id,{}) 1312*7dc08ffcSJunyu Lai ttl = conf.ipv6_enabled and scapy.layers.inet6.IPv6 in s and s.hlim or s.ttl 1313*7dc08ffcSJunyu Lai if not (ICMP in r and r[ICMP].type == 11) and not (conf.ipv6_enabled and scapy.layers.inet6.IPv6 in r and scapy.layers.inet6.ICMPv6TimeExceeded in r): 1314*7dc08ffcSJunyu Lai if trace_id in ports_done: 1315*7dc08ffcSJunyu Lai continue 1316*7dc08ffcSJunyu Lai ports_done[trace_id] = None 1317*7dc08ffcSJunyu Lai p = ports.get(r.src,[]) 1318*7dc08ffcSJunyu Lai if TCP in r: 1319*7dc08ffcSJunyu Lai p.append(r.sprintf("<T%ir,TCP.sport%> %TCP.sport% %TCP.flags%")) 1320*7dc08ffcSJunyu Lai trace[ttl] = r.sprintf('"%r,src%":T%ir,TCP.sport%') 1321*7dc08ffcSJunyu Lai elif UDP in r: 1322*7dc08ffcSJunyu Lai p.append(r.sprintf("<U%ir,UDP.sport%> %UDP.sport%")) 1323*7dc08ffcSJunyu Lai trace[ttl] = r.sprintf('"%r,src%":U%ir,UDP.sport%') 1324*7dc08ffcSJunyu Lai elif ICMP in r: 1325*7dc08ffcSJunyu Lai p.append(r.sprintf("<I%ir,ICMP.type%> ICMP %ICMP.type%")) 1326*7dc08ffcSJunyu Lai trace[ttl] = r.sprintf('"%r,src%":I%ir,ICMP.type%') 1327*7dc08ffcSJunyu Lai else: 1328*7dc08ffcSJunyu Lai p.append(r.sprintf("{IP:<P%ir,proto%> IP %proto%}{IPv6:<P%ir,nh%> IPv6 %nh%}")) 1329*7dc08ffcSJunyu Lai trace[ttl] = r.sprintf('"%r,src%":{IP:P%ir,proto%}{IPv6:P%ir,nh%}') 1330*7dc08ffcSJunyu Lai ports[r.src] = p 1331*7dc08ffcSJunyu Lai else: 1332*7dc08ffcSJunyu Lai trace[ttl] = r.sprintf('"%r,src%"') 1333*7dc08ffcSJunyu Lai rt[trace_id] = trace 1334*7dc08ffcSJunyu Lai 1335*7dc08ffcSJunyu Lai # Fill holes with unk%i nodes 1336*7dc08ffcSJunyu Lai unknown_label = incremental_label("unk%i") 1337*7dc08ffcSJunyu Lai blackholes = [] 1338*7dc08ffcSJunyu Lai bhip = {} 1339*7dc08ffcSJunyu Lai for rtk in rt: 1340*7dc08ffcSJunyu Lai trace = rt[rtk] 1341*7dc08ffcSJunyu Lai max_trace = max(trace) 1342*7dc08ffcSJunyu Lai for n in range(min(trace), max_trace): 1343*7dc08ffcSJunyu Lai if n not in trace: 1344*7dc08ffcSJunyu Lai trace[n] = next(unknown_label) 1345*7dc08ffcSJunyu Lai if rtk not in ports_done: 1346*7dc08ffcSJunyu Lai if rtk[2] == 1: #ICMP 1347*7dc08ffcSJunyu Lai bh = "%s %i/icmp" % (rtk[1],rtk[3]) 1348*7dc08ffcSJunyu Lai elif rtk[2] == 6: #TCP 1349*7dc08ffcSJunyu Lai bh = "%s %i/tcp" % (rtk[1],rtk[3]) 1350*7dc08ffcSJunyu Lai elif rtk[2] == 17: #UDP 1351*7dc08ffcSJunyu Lai bh = '%s %i/udp' % (rtk[1],rtk[3]) 1352*7dc08ffcSJunyu Lai else: 1353*7dc08ffcSJunyu Lai bh = '%s %i/proto' % (rtk[1],rtk[2]) 1354*7dc08ffcSJunyu Lai ips[bh] = None 1355*7dc08ffcSJunyu Lai bhip[rtk[1]] = bh 1356*7dc08ffcSJunyu Lai bh = '"%s"' % bh 1357*7dc08ffcSJunyu Lai trace[max_trace + 1] = bh 1358*7dc08ffcSJunyu Lai blackholes.append(bh) 1359*7dc08ffcSJunyu Lai 1360*7dc08ffcSJunyu Lai # Find AS numbers 1361*7dc08ffcSJunyu Lai ASN_query_list = set(x.rsplit(" ",1)[0] for x in ips) 1362*7dc08ffcSJunyu Lai if ASres is None: 1363*7dc08ffcSJunyu Lai ASNlist = [] 1364*7dc08ffcSJunyu Lai else: 1365*7dc08ffcSJunyu Lai ASNlist = ASres.resolve(*ASN_query_list) 1366*7dc08ffcSJunyu Lai 1367*7dc08ffcSJunyu Lai ASNs = {} 1368*7dc08ffcSJunyu Lai ASDs = {} 1369*7dc08ffcSJunyu Lai for ip,asn,desc, in ASNlist: 1370*7dc08ffcSJunyu Lai if asn is None: 1371*7dc08ffcSJunyu Lai continue 1372*7dc08ffcSJunyu Lai iplist = ASNs.get(asn,[]) 1373*7dc08ffcSJunyu Lai if ip in bhip: 1374*7dc08ffcSJunyu Lai if ip in ports: 1375*7dc08ffcSJunyu Lai iplist.append(ip) 1376*7dc08ffcSJunyu Lai iplist.append(bhip[ip]) 1377*7dc08ffcSJunyu Lai else: 1378*7dc08ffcSJunyu Lai iplist.append(ip) 1379*7dc08ffcSJunyu Lai ASNs[asn] = iplist 1380*7dc08ffcSJunyu Lai ASDs[asn] = desc 1381*7dc08ffcSJunyu Lai 1382*7dc08ffcSJunyu Lai 1383*7dc08ffcSJunyu Lai backcolorlist=colgen("60","86","ba","ff") 1384*7dc08ffcSJunyu Lai forecolorlist=colgen("a0","70","40","20") 1385*7dc08ffcSJunyu Lai 1386*7dc08ffcSJunyu Lai s = "digraph trace {\n" 1387*7dc08ffcSJunyu Lai 1388*7dc08ffcSJunyu Lai s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n" 1389*7dc08ffcSJunyu Lai 1390*7dc08ffcSJunyu Lai s += "\n#ASN clustering\n" 1391*7dc08ffcSJunyu Lai for asn in ASNs: 1392*7dc08ffcSJunyu Lai s += '\tsubgraph cluster_%s {\n' % asn 1393*7dc08ffcSJunyu Lai col = next(backcolorlist) 1394*7dc08ffcSJunyu Lai s += '\t\tcolor="#%s%s%s";' % col 1395*7dc08ffcSJunyu Lai s += '\t\tnode [fillcolor="#%s%s%s",style=filled];' % col 1396*7dc08ffcSJunyu Lai s += '\t\tfontsize = 10;' 1397*7dc08ffcSJunyu Lai s += '\t\tlabel = "%s\\n[%s]"\n' % (asn,ASDs[asn]) 1398*7dc08ffcSJunyu Lai for ip in ASNs[asn]: 1399*7dc08ffcSJunyu Lai 1400*7dc08ffcSJunyu Lai s += '\t\t"%s";\n'%ip 1401*7dc08ffcSJunyu Lai s += "\t}\n" 1402*7dc08ffcSJunyu Lai 1403*7dc08ffcSJunyu Lai 1404*7dc08ffcSJunyu Lai 1405*7dc08ffcSJunyu Lai 1406*7dc08ffcSJunyu Lai s += "#endpoints\n" 1407*7dc08ffcSJunyu Lai for p in ports: 1408*7dc08ffcSJunyu Lai s += '\t"%s" [shape=record,color=black,fillcolor=green,style=filled,label="%s|%s"];\n' % (p,p,"|".join(ports[p])) 1409*7dc08ffcSJunyu Lai 1410*7dc08ffcSJunyu Lai s += "\n#Blackholes\n" 1411*7dc08ffcSJunyu Lai for bh in blackholes: 1412*7dc08ffcSJunyu Lai s += '\t%s [shape=octagon,color=black,fillcolor=red,style=filled];\n' % bh 1413*7dc08ffcSJunyu Lai 1414*7dc08ffcSJunyu Lai if padding: 1415*7dc08ffcSJunyu Lai s += "\n#Padding\n" 1416*7dc08ffcSJunyu Lai pad={} 1417*7dc08ffcSJunyu Lai for snd,rcv in self.res: 1418*7dc08ffcSJunyu Lai if rcv.src not in ports and rcv.haslayer(conf.padding_layer): 1419*7dc08ffcSJunyu Lai p = rcv.getlayer(conf.padding_layer).load 1420*7dc08ffcSJunyu Lai if p != b"\x00"*len(p): 1421*7dc08ffcSJunyu Lai pad[rcv.src]=None 1422*7dc08ffcSJunyu Lai for rcv in pad: 1423*7dc08ffcSJunyu Lai s += '\t"%s" [shape=triangle,color=black,fillcolor=red,style=filled];\n' % rcv 1424*7dc08ffcSJunyu Lai 1425*7dc08ffcSJunyu Lai 1426*7dc08ffcSJunyu Lai 1427*7dc08ffcSJunyu Lai s += "\n\tnode [shape=ellipse,color=black,style=solid];\n\n" 1428*7dc08ffcSJunyu Lai 1429*7dc08ffcSJunyu Lai 1430*7dc08ffcSJunyu Lai for rtk in rt: 1431*7dc08ffcSJunyu Lai s += "#---[%s\n" % repr(rtk) 1432*7dc08ffcSJunyu Lai s += '\t\tedge [color="#%s%s%s"];\n' % next(forecolorlist) 1433*7dc08ffcSJunyu Lai trace = rt[rtk] 1434*7dc08ffcSJunyu Lai maxtrace = max(trace) 1435*7dc08ffcSJunyu Lai for n in range(min(trace), maxtrace): 1436*7dc08ffcSJunyu Lai s += '\t%s ->\n' % trace[n] 1437*7dc08ffcSJunyu Lai s += '\t%s;\n' % trace[maxtrace] 1438*7dc08ffcSJunyu Lai 1439*7dc08ffcSJunyu Lai s += "}\n"; 1440*7dc08ffcSJunyu Lai self.graphdef = s 1441*7dc08ffcSJunyu Lai 1442*7dc08ffcSJunyu Lai def graph(self, ASres=None, padding=0, **kargs): 1443*7dc08ffcSJunyu Lai """x.graph(ASres=conf.AS_resolver, other args): 1444*7dc08ffcSJunyu Lai ASres=None : no AS resolver => no clustering 1445*7dc08ffcSJunyu Lai ASres=AS_resolver() : default whois AS resolver (riswhois.ripe.net) 1446*7dc08ffcSJunyu Lai ASres=AS_resolver_cymru(): use whois.cymru.com whois database 1447*7dc08ffcSJunyu Lai ASres=AS_resolver(server="whois.ra.net") 1448*7dc08ffcSJunyu Lai type: output type (svg, ps, gif, jpg, etc.), passed to dot's "-T" option 1449*7dc08ffcSJunyu Lai target: filename or redirect. Defaults pipe to Imagemagick's display program 1450*7dc08ffcSJunyu Lai prog: which graphviz program to use""" 1451*7dc08ffcSJunyu Lai if ASres is None: 1452*7dc08ffcSJunyu Lai ASres = conf.AS_resolver 1453*7dc08ffcSJunyu Lai if (self.graphdef is None or 1454*7dc08ffcSJunyu Lai self.graphASres != ASres or 1455*7dc08ffcSJunyu Lai self.graphpadding != padding): 1456*7dc08ffcSJunyu Lai self.make_graph(ASres,padding) 1457*7dc08ffcSJunyu Lai 1458*7dc08ffcSJunyu Lai return do_graph(self.graphdef, **kargs) 1459*7dc08ffcSJunyu Lai 1460*7dc08ffcSJunyu Lai 1461*7dc08ffcSJunyu Lai 1462*7dc08ffcSJunyu Lai@conf.commands.register 1463*7dc08ffcSJunyu Laidef traceroute(target, dport=80, minttl=1, maxttl=30, sport=RandShort(), l4 = None, filter=None, timeout=2, verbose=None, **kargs): 1464*7dc08ffcSJunyu Lai """Instant TCP traceroute 1465*7dc08ffcSJunyu Laitraceroute(target, [maxttl=30,] [dport=80,] [sport=80,] [verbose=conf.verb]) -> None 1466*7dc08ffcSJunyu Lai""" 1467*7dc08ffcSJunyu Lai if verbose is None: 1468*7dc08ffcSJunyu Lai verbose = conf.verb 1469*7dc08ffcSJunyu Lai if filter is None: 1470*7dc08ffcSJunyu Lai # we only consider ICMP error packets and TCP packets with at 1471*7dc08ffcSJunyu Lai # least the ACK flag set *and* either the SYN or the RST flag 1472*7dc08ffcSJunyu Lai # set 1473*7dc08ffcSJunyu Lai filter="(icmp and (icmp[0]=3 or icmp[0]=4 or icmp[0]=5 or icmp[0]=11 or icmp[0]=12)) or (tcp and (tcp[13] & 0x16 > 0x10))" 1474*7dc08ffcSJunyu Lai if l4 is None: 1475*7dc08ffcSJunyu Lai a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/TCP(seq=RandInt(),sport=sport, dport=dport), 1476*7dc08ffcSJunyu Lai timeout=timeout, filter=filter, verbose=verbose, **kargs) 1477*7dc08ffcSJunyu Lai else: 1478*7dc08ffcSJunyu Lai # this should always work 1479*7dc08ffcSJunyu Lai filter="ip" 1480*7dc08ffcSJunyu Lai a,b = sr(IP(dst=target, id=RandShort(), ttl=(minttl,maxttl))/l4, 1481*7dc08ffcSJunyu Lai timeout=timeout, filter=filter, verbose=verbose, **kargs) 1482*7dc08ffcSJunyu Lai 1483*7dc08ffcSJunyu Lai a = TracerouteResult(a.res) 1484*7dc08ffcSJunyu Lai if verbose: 1485*7dc08ffcSJunyu Lai a.show() 1486*7dc08ffcSJunyu Lai return a,b 1487*7dc08ffcSJunyu Lai 1488*7dc08ffcSJunyu Lai 1489*7dc08ffcSJunyu Lai 1490*7dc08ffcSJunyu Lai############################# 1491*7dc08ffcSJunyu Lai## Simple TCP client stack ## 1492*7dc08ffcSJunyu Lai############################# 1493*7dc08ffcSJunyu Lai 1494*7dc08ffcSJunyu Laiclass TCP_client(Automaton): 1495*7dc08ffcSJunyu Lai 1496*7dc08ffcSJunyu Lai def parse_args(self, ip, port, *args, **kargs): 1497*7dc08ffcSJunyu Lai self.dst = str(Net(ip)) 1498*7dc08ffcSJunyu Lai self.dport = port 1499*7dc08ffcSJunyu Lai self.sport = random.randrange(0,2**16) 1500*7dc08ffcSJunyu Lai self.l4 = IP(dst=ip)/TCP(sport=self.sport, dport=self.dport, flags=0, 1501*7dc08ffcSJunyu Lai seq=random.randrange(0,2**32)) 1502*7dc08ffcSJunyu Lai self.src = self.l4.src 1503*7dc08ffcSJunyu Lai self.swin=self.l4[TCP].window 1504*7dc08ffcSJunyu Lai self.dwin=1 1505*7dc08ffcSJunyu Lai self.rcvbuf = b"" 1506*7dc08ffcSJunyu Lai bpf = "host %s and host %s and port %i and port %i" % (self.src, 1507*7dc08ffcSJunyu Lai self.dst, 1508*7dc08ffcSJunyu Lai self.sport, 1509*7dc08ffcSJunyu Lai self.dport) 1510*7dc08ffcSJunyu Lai 1511*7dc08ffcSJunyu Lai# bpf=None 1512*7dc08ffcSJunyu Lai Automaton.parse_args(self, filter=bpf, **kargs) 1513*7dc08ffcSJunyu Lai 1514*7dc08ffcSJunyu Lai 1515*7dc08ffcSJunyu Lai def master_filter(self, pkt): 1516*7dc08ffcSJunyu Lai return (IP in pkt and 1517*7dc08ffcSJunyu Lai pkt[IP].src == self.dst and 1518*7dc08ffcSJunyu Lai pkt[IP].dst == self.src and 1519*7dc08ffcSJunyu Lai TCP in pkt and 1520*7dc08ffcSJunyu Lai pkt[TCP].sport == self.dport and 1521*7dc08ffcSJunyu Lai pkt[TCP].dport == self.sport and 1522*7dc08ffcSJunyu Lai self.l4[TCP].seq >= pkt[TCP].ack and # XXX: seq/ack 2^32 wrap up 1523*7dc08ffcSJunyu Lai ((self.l4[TCP].ack == 0) or (self.l4[TCP].ack <= pkt[TCP].seq <= self.l4[TCP].ack+self.swin)) ) 1524*7dc08ffcSJunyu Lai 1525*7dc08ffcSJunyu Lai 1526*7dc08ffcSJunyu Lai @ATMT.state(initial=1) 1527*7dc08ffcSJunyu Lai def START(self): 1528*7dc08ffcSJunyu Lai pass 1529*7dc08ffcSJunyu Lai 1530*7dc08ffcSJunyu Lai @ATMT.state() 1531*7dc08ffcSJunyu Lai def SYN_SENT(self): 1532*7dc08ffcSJunyu Lai pass 1533*7dc08ffcSJunyu Lai 1534*7dc08ffcSJunyu Lai @ATMT.state() 1535*7dc08ffcSJunyu Lai def ESTABLISHED(self): 1536*7dc08ffcSJunyu Lai pass 1537*7dc08ffcSJunyu Lai 1538*7dc08ffcSJunyu Lai @ATMT.state() 1539*7dc08ffcSJunyu Lai def LAST_ACK(self): 1540*7dc08ffcSJunyu Lai pass 1541*7dc08ffcSJunyu Lai 1542*7dc08ffcSJunyu Lai @ATMT.state(final=1) 1543*7dc08ffcSJunyu Lai def CLOSED(self): 1544*7dc08ffcSJunyu Lai pass 1545*7dc08ffcSJunyu Lai 1546*7dc08ffcSJunyu Lai 1547*7dc08ffcSJunyu Lai @ATMT.condition(START) 1548*7dc08ffcSJunyu Lai def connect(self): 1549*7dc08ffcSJunyu Lai raise self.SYN_SENT() 1550*7dc08ffcSJunyu Lai @ATMT.action(connect) 1551*7dc08ffcSJunyu Lai def send_syn(self): 1552*7dc08ffcSJunyu Lai self.l4[TCP].flags = "S" 1553*7dc08ffcSJunyu Lai self.send(self.l4) 1554*7dc08ffcSJunyu Lai self.l4[TCP].seq += 1 1555*7dc08ffcSJunyu Lai 1556*7dc08ffcSJunyu Lai 1557*7dc08ffcSJunyu Lai @ATMT.receive_condition(SYN_SENT) 1558*7dc08ffcSJunyu Lai def synack_received(self, pkt): 1559*7dc08ffcSJunyu Lai if pkt[TCP].flags & 0x3f == 0x12: 1560*7dc08ffcSJunyu Lai raise self.ESTABLISHED().action_parameters(pkt) 1561*7dc08ffcSJunyu Lai @ATMT.action(synack_received) 1562*7dc08ffcSJunyu Lai def send_ack_of_synack(self, pkt): 1563*7dc08ffcSJunyu Lai self.l4[TCP].ack = pkt[TCP].seq+1 1564*7dc08ffcSJunyu Lai self.l4[TCP].flags = "A" 1565*7dc08ffcSJunyu Lai self.send(self.l4) 1566*7dc08ffcSJunyu Lai 1567*7dc08ffcSJunyu Lai @ATMT.receive_condition(ESTABLISHED) 1568*7dc08ffcSJunyu Lai def incoming_data_received(self, pkt): 1569*7dc08ffcSJunyu Lai if not isinstance(pkt[TCP].payload, NoPayload) and not isinstance(pkt[TCP].payload, conf.padding_layer): 1570*7dc08ffcSJunyu Lai raise self.ESTABLISHED().action_parameters(pkt) 1571*7dc08ffcSJunyu Lai @ATMT.action(incoming_data_received) 1572*7dc08ffcSJunyu Lai def receive_data(self,pkt): 1573*7dc08ffcSJunyu Lai data = raw(pkt[TCP].payload) 1574*7dc08ffcSJunyu Lai if data and self.l4[TCP].ack == pkt[TCP].seq: 1575*7dc08ffcSJunyu Lai self.l4[TCP].ack += len(data) 1576*7dc08ffcSJunyu Lai self.l4[TCP].flags = "A" 1577*7dc08ffcSJunyu Lai self.send(self.l4) 1578*7dc08ffcSJunyu Lai self.rcvbuf += data 1579*7dc08ffcSJunyu Lai if pkt[TCP].flags.P: 1580*7dc08ffcSJunyu Lai self.oi.tcp.send(self.rcvbuf) 1581*7dc08ffcSJunyu Lai self.rcvbuf = b"" 1582*7dc08ffcSJunyu Lai 1583*7dc08ffcSJunyu Lai @ATMT.ioevent(ESTABLISHED,name="tcp", as_supersocket="tcplink") 1584*7dc08ffcSJunyu Lai def outgoing_data_received(self, fd): 1585*7dc08ffcSJunyu Lai raise self.ESTABLISHED().action_parameters(fd.recv()) 1586*7dc08ffcSJunyu Lai @ATMT.action(outgoing_data_received) 1587*7dc08ffcSJunyu Lai def send_data(self, d): 1588*7dc08ffcSJunyu Lai self.l4[TCP].flags = "PA" 1589*7dc08ffcSJunyu Lai self.send(self.l4/d) 1590*7dc08ffcSJunyu Lai self.l4[TCP].seq += len(d) 1591*7dc08ffcSJunyu Lai 1592*7dc08ffcSJunyu Lai 1593*7dc08ffcSJunyu Lai @ATMT.receive_condition(ESTABLISHED) 1594*7dc08ffcSJunyu Lai def reset_received(self, pkt): 1595*7dc08ffcSJunyu Lai if pkt[TCP].flags & 4 != 0: 1596*7dc08ffcSJunyu Lai raise self.CLOSED() 1597*7dc08ffcSJunyu Lai 1598*7dc08ffcSJunyu Lai @ATMT.receive_condition(ESTABLISHED) 1599*7dc08ffcSJunyu Lai def fin_received(self, pkt): 1600*7dc08ffcSJunyu Lai if pkt[TCP].flags & 0x1 == 1: 1601*7dc08ffcSJunyu Lai raise self.LAST_ACK().action_parameters(pkt) 1602*7dc08ffcSJunyu Lai @ATMT.action(fin_received) 1603*7dc08ffcSJunyu Lai def send_finack(self, pkt): 1604*7dc08ffcSJunyu Lai self.l4[TCP].flags = "FA" 1605*7dc08ffcSJunyu Lai self.l4[TCP].ack = pkt[TCP].seq+1 1606*7dc08ffcSJunyu Lai self.send(self.l4) 1607*7dc08ffcSJunyu Lai self.l4[TCP].seq += 1 1608*7dc08ffcSJunyu Lai 1609*7dc08ffcSJunyu Lai @ATMT.receive_condition(LAST_ACK) 1610*7dc08ffcSJunyu Lai def ack_of_fin_received(self, pkt): 1611*7dc08ffcSJunyu Lai if pkt[TCP].flags & 0x3f == 0x10: 1612*7dc08ffcSJunyu Lai raise self.CLOSED() 1613*7dc08ffcSJunyu Lai 1614*7dc08ffcSJunyu Lai 1615*7dc08ffcSJunyu Lai 1616*7dc08ffcSJunyu Lai 1617*7dc08ffcSJunyu Lai##################### 1618*7dc08ffcSJunyu Lai## Reporting stuff ## 1619*7dc08ffcSJunyu Lai##################### 1620*7dc08ffcSJunyu Lai 1621*7dc08ffcSJunyu Lai 1622*7dc08ffcSJunyu Lai@conf.commands.register 1623*7dc08ffcSJunyu Laidef report_ports(target, ports): 1624*7dc08ffcSJunyu Lai """portscan a target and output a LaTeX table 1625*7dc08ffcSJunyu Laireport_ports(target, ports) -> string""" 1626*7dc08ffcSJunyu Lai ans,unans = sr(IP(dst=target)/TCP(dport=ports),timeout=5) 1627*7dc08ffcSJunyu Lai rep = "\\begin{tabular}{|r|l|l|}\n\\hline\n" 1628*7dc08ffcSJunyu Lai for s,r in ans: 1629*7dc08ffcSJunyu Lai if not r.haslayer(ICMP): 1630*7dc08ffcSJunyu Lai if r.payload.flags == 0x12: 1631*7dc08ffcSJunyu Lai rep += r.sprintf("%TCP.sport% & open & SA \\\\\n") 1632*7dc08ffcSJunyu Lai rep += "\\hline\n" 1633*7dc08ffcSJunyu Lai for s,r in ans: 1634*7dc08ffcSJunyu Lai if r.haslayer(ICMP): 1635*7dc08ffcSJunyu Lai rep += r.sprintf("%TCPerror.dport% & closed & ICMP type %ICMP.type%/%ICMP.code% from %IP.src% \\\\\n") 1636*7dc08ffcSJunyu Lai elif r.payload.flags != 0x12: 1637*7dc08ffcSJunyu Lai rep += r.sprintf("%TCP.sport% & closed & TCP %TCP.flags% \\\\\n") 1638*7dc08ffcSJunyu Lai rep += "\\hline\n" 1639*7dc08ffcSJunyu Lai for i in unans: 1640*7dc08ffcSJunyu Lai rep += i.sprintf("%TCP.dport% & ? & unanswered \\\\\n") 1641*7dc08ffcSJunyu Lai rep += "\\hline\n\\end{tabular}\n" 1642*7dc08ffcSJunyu Lai return rep 1643*7dc08ffcSJunyu Lai 1644*7dc08ffcSJunyu Lai 1645*7dc08ffcSJunyu Lai@conf.commands.register 1646*7dc08ffcSJunyu Laidef IPID_count(lst, funcID=lambda x:x[1].id, funcpres=lambda x:x[1].summary()): 1647*7dc08ffcSJunyu Lai """Identify IP id values classes in a list of packets 1648*7dc08ffcSJunyu Lai 1649*7dc08ffcSJunyu Lailst: a list of packets 1650*7dc08ffcSJunyu LaifuncID: a function that returns IP id values 1651*7dc08ffcSJunyu Laifuncpres: a function used to summarize packets""" 1652*7dc08ffcSJunyu Lai idlst = [funcID(e) for e in lst] 1653*7dc08ffcSJunyu Lai idlst.sort() 1654*7dc08ffcSJunyu Lai classes = [idlst[0]] 1655*7dc08ffcSJunyu Lai classes += [t[1] for t in zip(idlst[:-1], idlst[1:]) if abs(t[0]-t[1]) > 50] 1656*7dc08ffcSJunyu Lai lst = [(funcID(x), funcpres(x)) for x in lst] 1657*7dc08ffcSJunyu Lai lst.sort() 1658*7dc08ffcSJunyu Lai print("Probably %i classes:" % len(classes), classes) 1659*7dc08ffcSJunyu Lai for id,pr in lst: 1660*7dc08ffcSJunyu Lai print("%5i" % id, pr) 1661*7dc08ffcSJunyu Lai 1662*7dc08ffcSJunyu Lai 1663*7dc08ffcSJunyu Lai@conf.commands.register 1664*7dc08ffcSJunyu Laidef fragleak(target,sport=123, dport=123, timeout=0.2, onlyasc=0): 1665*7dc08ffcSJunyu Lai load = "XXXXYYYYYYYYYY" 1666*7dc08ffcSJunyu Lai# getmacbyip(target) 1667*7dc08ffcSJunyu Lai# pkt = IP(dst=target, id=RandShort(), options=b"\x22"*40)/UDP()/load 1668*7dc08ffcSJunyu Lai pkt = IP(dst=target, id=RandShort(), options=b"\x00"*40, flags=1)/UDP(sport=sport, dport=sport)/load 1669*7dc08ffcSJunyu Lai s=conf.L3socket() 1670*7dc08ffcSJunyu Lai intr=0 1671*7dc08ffcSJunyu Lai found={} 1672*7dc08ffcSJunyu Lai try: 1673*7dc08ffcSJunyu Lai while True: 1674*7dc08ffcSJunyu Lai try: 1675*7dc08ffcSJunyu Lai if not intr: 1676*7dc08ffcSJunyu Lai s.send(pkt) 1677*7dc08ffcSJunyu Lai sin,sout,serr = select([s],[],[],timeout) 1678*7dc08ffcSJunyu Lai if not sin: 1679*7dc08ffcSJunyu Lai continue 1680*7dc08ffcSJunyu Lai ans=s.recv(1600) 1681*7dc08ffcSJunyu Lai if not isinstance(ans, IP): #TODO: IPv6 1682*7dc08ffcSJunyu Lai continue 1683*7dc08ffcSJunyu Lai if not isinstance(ans.payload, ICMP): 1684*7dc08ffcSJunyu Lai continue 1685*7dc08ffcSJunyu Lai if not isinstance(ans.payload.payload, IPerror): 1686*7dc08ffcSJunyu Lai continue 1687*7dc08ffcSJunyu Lai if ans.payload.payload.dst != target: 1688*7dc08ffcSJunyu Lai continue 1689*7dc08ffcSJunyu Lai if ans.src != target: 1690*7dc08ffcSJunyu Lai print("leak from", ans.src, end=' ') 1691*7dc08ffcSJunyu Lai 1692*7dc08ffcSJunyu Lai 1693*7dc08ffcSJunyu Lai# print repr(ans) 1694*7dc08ffcSJunyu Lai if not ans.haslayer(conf.padding_layer): 1695*7dc08ffcSJunyu Lai continue 1696*7dc08ffcSJunyu Lai 1697*7dc08ffcSJunyu Lai 1698*7dc08ffcSJunyu Lai# print repr(ans.payload.payload.payload.payload) 1699*7dc08ffcSJunyu Lai 1700*7dc08ffcSJunyu Lai# if not isinstance(ans.payload.payload.payload.payload, conf.raw_layer): 1701*7dc08ffcSJunyu Lai# continue 1702*7dc08ffcSJunyu Lai# leak = ans.payload.payload.payload.payload.load[len(load):] 1703*7dc08ffcSJunyu Lai leak = ans.getlayer(conf.padding_layer).load 1704*7dc08ffcSJunyu Lai if leak not in found: 1705*7dc08ffcSJunyu Lai found[leak]=None 1706*7dc08ffcSJunyu Lai linehexdump(leak, onlyasc=onlyasc) 1707*7dc08ffcSJunyu Lai except KeyboardInterrupt: 1708*7dc08ffcSJunyu Lai if intr: 1709*7dc08ffcSJunyu Lai raise 1710*7dc08ffcSJunyu Lai intr=1 1711*7dc08ffcSJunyu Lai except KeyboardInterrupt: 1712*7dc08ffcSJunyu Lai pass 1713*7dc08ffcSJunyu Lai 1714*7dc08ffcSJunyu Lai 1715*7dc08ffcSJunyu Lai@conf.commands.register 1716*7dc08ffcSJunyu Laidef fragleak2(target, timeout=0.4, onlyasc=0): 1717*7dc08ffcSJunyu Lai found={} 1718*7dc08ffcSJunyu Lai try: 1719*7dc08ffcSJunyu Lai while True: 1720*7dc08ffcSJunyu Lai p = sr1(IP(dst=target, options=b"\x00"*40, proto=200)/"XXXXYYYYYYYYYYYY",timeout=timeout,verbose=0) 1721*7dc08ffcSJunyu Lai if not p: 1722*7dc08ffcSJunyu Lai continue 1723*7dc08ffcSJunyu Lai if conf.padding_layer in p: 1724*7dc08ffcSJunyu Lai leak = p[conf.padding_layer].load 1725*7dc08ffcSJunyu Lai if leak not in found: 1726*7dc08ffcSJunyu Lai found[leak]=None 1727*7dc08ffcSJunyu Lai linehexdump(leak,onlyasc=onlyasc) 1728*7dc08ffcSJunyu Lai except: 1729*7dc08ffcSJunyu Lai pass 1730*7dc08ffcSJunyu Lai 1731*7dc08ffcSJunyu Lai 1732*7dc08ffcSJunyu Laiconf.stats_classic_protocols += [TCP,UDP,ICMP] 1733*7dc08ffcSJunyu Laiconf.stats_dot11_protocols += [TCP,UDP,ICMP] 1734*7dc08ffcSJunyu Lai 1735*7dc08ffcSJunyu Laiif conf.ipv6_enabled: 1736*7dc08ffcSJunyu Lai import scapy.layers.inet6 1737