def __init__(self, filename): # A list of (linktype, snaplen); will be populated by IDBs. self.interfaces = [] self.blocktypes = { 1: self.read_block_idb, 6: self.read_block_epb, } magic = self.open(filename) if magic != "\x0a\x0d\x0d\x0a": # PcapNg: try: self.f.seek(-4, 1) except: pass raise Scapy_Exception( "Not a pcapng capture file (bad magic: %r)" % magic ) # see https://github.com/pcapng/pcapng blocklen, magic = self.f.read(4), self.f.read(4) if magic == "\x1a\x2b\x3c\x4d": self.endian = ">" elif magic == "\x4d\x3c\x2b\x1a": self.endian = "<" else: raise Scapy_Exception("Not a pcapng capture file (bad magic)") self.f.seek(0)
def __init__(self, filename, fdesc, magic): self.filename = filename self.f = fdesc if magic == "\xa1\xb2\xc3\xd4": #big endian self.endian = ">" elif magic == "\xd4\xc3\xb2\xa1": #little endian self.endian = "<" else: raise Scapy_Exception("Not a pcap capture file (bad magic: %r)" % magic) hdr = self.f.read(20) if len(hdr) < 20: raise Scapy_Exception("Invalid pcap file (too short)") vermaj, vermin, tz, sig, snaplen, linktype = struct.unpack( self.endian + "HHIIII", hdr) self.linktype = linktype
def read_packet(self, size=MTU): """Read blocks until it reaches either EOF or a packet, and returns None or (packet, (linktype, sec, usec, wirelen)), where packet is a string. """ while True: try: blocktype, blocklen = struct.unpack(self.endian + "2I", self.f.read(8)) except struct.error: return None block = self.f.read(blocklen - 12) try: if (blocklen,) != struct.unpack(self.endian + 'I', self.f.read(4)): raise Scapy_Exception( "Invalid pcapng block (bad blocklen)" ) except struct.error: return None res = self.blocktypes.get(blocktype, lambda block, size: None)(block, size) if res is not None: return res
def __init__(self, filename): RawPcapReader.__init__(self, filename) try: self.LLcls = conf.l2types[self.linktype] except KeyError: raise Scapy_Exception( "Scapy PcapReader: unknown LL type [%i]/[%#x]" % (self.linktype, self.linktype)) #warning("PcapReader: unknown LL type [%i]/[%#x]. Using Raw packets" % (self.linktype,self.linktype)) self.LLcls = conf.raw_layer
def __init__(self, filename): self.filename = filename try: self.f = gzip.open(filename,"rb") magic = self.f.read(4) except IOError: self.f = open(filename,"rb") magic = self.f.read(4) if magic == "\xa1\xb2\xc3\xd4": #big endian self.endian = ">" elif magic == "\xd4\xc3\xb2\xa1": #little endian self.endian = "<" else: raise Scapy_Exception("Not a pcap capture file (bad magic)") hdr = self.f.read(20) if len(hdr)<20: raise Scapy_Exception("Invalid pcap file (too short)") vermaj,vermin,tz,sig,snaplen,linktype = struct.unpack(self.endian+"HHIIII",hdr) self.linktype = linktype
def rdpcap(filename, count=-1): """Read a pcap or pcapng file and return a packet list count: read only <count> packets """ try: return _rdpcap(filename, count=count) except Scapy_Exception: pass try: return _rdpcapng(filename, count=count) except Scapy_Exception: raise Scapy_Exception("Not a valid pcap or pcapng file")
def make_route(self, host=None, net=None, gw=None, dev=None): if host is not None: thenet,msk = host,32 elif net is not None: thenet,msk = net.split("/") msk = int(msk) else: raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net") if gw is None: gw="0.0.0.0" if dev is None: if gw: nhop = gw else: nhop = thenet dev,ifaddr,x = self.route(nhop) else: ifaddr = get_if_addr(dev) return (atol(thenet), itom(msk), gw, dev, ifaddr)
def __call__(cls, filename): """Creates a cls instance, use the `alternative` if that fails. """ i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__) filename, fdesc, magic = cls.open(filename) try: i.__init__(filename, fdesc, magic) except Scapy_Exception: if "alternative" in cls.__dict__: cls = cls.__dict__["alternative"] i = cls.__new__(cls, cls.__name__, cls.__bases__, cls.__dict__) try: i.__init__(filename, fdesc, magic) except Scapy_Exception: try: self.f.seek(-4, 1) except: pass raise Scapy_Exception("Not a supported capture file") return i
def sprintf(self, fmt, relax=1): """sprintf(format, [relax=1]) -> str where format is a string that can include directives. A directive begins and ends by % and has the following format %[fmt[r],][cls[:nb].]field%. fmt is a classic printf directive, "r" can be appended for raw substitution (ex: IP.flags=0x18 instead of SA), nb is the number of the layer we want (ex: for IP/IP packets, IP:2.src is the src of the upper IP layer). Special case : "%.time%" is the creation time. Ex : p.sprintf("%.time% %-15s,IP.src% -> %-15s,IP.dst% %IP.chksum% " "%03xr,IP.proto% %r,TCP.flags%") Moreover, the format string can include conditionnal statements. A conditionnal statement looks like : {layer:string} where layer is a layer name, and string is the string to insert in place of the condition if it is true, i.e. if layer is present. If layer is preceded by a "!", the result si inverted. Conditions can be imbricated. A valid statement can be : p.sprintf("This is a{TCP: TCP}{UDP: UDP}{ICMP:n ICMP} packet") p.sprintf("{IP:%IP.dst% {ICMP:%ICMP.type%}{TCP:%TCP.dport%}}") A side effect is that, to obtain "{" and "}" characters, you must use "%(" and "%)". """ escape = {"%": "%", "(": "{", ")": "}"} # Evaluate conditions while "{" in fmt: i = fmt.rindex("{") j = fmt[i + 1:].index("}") cond = fmt[i + 1:i + j + 1] k = cond.find(":") if k < 0: raise Scapy_Exception( "Bad condition in format string: [%s] (read sprintf doc!)" % cond) cond, format = cond[:k], cond[k + 1:] res = False if cond[0] == "!": res = True cond = cond[1:] if self.haslayer(cond): res = not res if not res: format = "" fmt = fmt[:i] + format + fmt[i + j + 2:] # Evaluate directives s = "" while "%" in fmt: i = fmt.index("%") s += fmt[:i] fmt = fmt[i + 1:] if fmt and fmt[0] in escape: s += escape[fmt[0]] fmt = fmt[1:] continue try: i = fmt.index("%") sfclsfld = fmt[:i] fclsfld = sfclsfld.split(",") if len(fclsfld) == 1: f = "s" clsfld = fclsfld[0] elif len(fclsfld) == 2: f, clsfld = fclsfld else: raise Scapy_Exception if "." in clsfld: cls, fld = clsfld.split(".") else: cls = self.__class__.__name__ fld = clsfld num = 1 if ":" in cls: cls, num = cls.split(":") num = int(num) fmt = fmt[i + 1:] except: raise Scapy_Exception("Bad format string [%%%s%s]" % (fmt[:25], fmt[25:] and "...")) else: if fld == "time": val = time.strftime( "%H:%M:%S.%%06i", time.localtime(self.time)) % int( (self.time - int(self.time)) * 1000000) elif cls == self.__class__.__name__ and hasattr(self, fld): if num > 1: val = self.payload.sprintf( "%%%s,%s:%s.%s%%" % (f, cls, num - 1, fld), relax) f = "s" elif f[-1] == "r": # Raw field value val = getattr(self, fld) f = f[:-1] if not f: f = "s" else: val = getattr(self, fld) if fld in self.fieldtype: val = self.fieldtype[fld].i2repr(self, val) else: val = self.payload.sprintf("%%%s%%" % sfclsfld, relax) f = "s" s += ("%" + f) % val s += fmt return s
def sprintf(self, fmt, relax): if relax: return "??" else: raise Scapy_Exception("Format not found [%s]" % fmt)
def fragment(self, *args, **kargs): raise Scapy_Exception("cannot fragment this packet")
def add_payload(self, payload): raise Scapy_Exception("Can't add payload to NoPayload instance")
def __init__(self, filename): self.ntarformat = False self.ntarehblist = [] self.filename = filename try: self.f = gzip.open(filename, "rb") magic = self.f.read(4) except IOError: self.f = open(filename, "rb") magic = self.f.read(4) # determine endianness if sys.byteorder == "little": # little endian self.endian = "<" else: # big endian self.endian = ">" if magic == "\x0a\x0d\x0d\x0a": # ntar format self.ntarformat = True # go back to beginning and note this is ntar self.f.seek(0, 0) myblockheader = self.ReadBlockHeader() while myblockheader is not None: ispacketblock = False isinterfacedescriptionblock = False # registers as interface description block # (for linktype) if myblockheader.blockType == 1: isinterfacedescriptionblock = True # for enhanced packet block elif myblockheader.blockType == 6: ispacketblock = True adjustedblocklength = myblockheader.blockLength # necessary block offsets if adjustedblocklength % 4 == 0: pass elif adjustedblocklength % 4 == 1: adjustedblocklength += 3 elif adjustedblocklength % 4 == 2: adjustedblocklength += 2 elif adjustedblocklength % 4 == 3: adjustedblocklength += 1 else: pass datablock = self.f.read(min(adjustedblocklength - 8, 4096)) # is packet block if isinterfacedescriptionblock: idb = self.ReadInterfaceDescriptionBlock( myblockheader, datablock) self.linktype = idb.linktype if ispacketblock: if myblockheader.blockType == 6: ehb = self.ReadEnhancedPacketBlock( myblockheader, datablock) self.ntarehblist.append(ehb) myblockheader = self.ReadBlockHeader() elif magic == "\xa1\xb2\xc3\xd4": #big endian self.endian = ">" elif magic == "\xd4\xc3\xb2\xa1": #little endian self.endian = "<" else: raise Scapy_Exception("Not a pcap capture file (bad magic)") if not self.ntarformat: hdr = self.f.read(20) if len(hdr) < 20: raise Scapy_Exception("Invalid pcap file (too short)") vermaj, vermin, tz, sig, snaplen, linktype = struct.unpack( self.endian + "HHIIII", hdr) self.linktype = linktype