├── doc ├── scapy │ ├── _static │ │ └── _dummy │ ├── _templates │ │ └── _dummy │ ├── graphics │ │ ├── ipid.png │ │ ├── trace3d_1.png │ │ ├── trace3d_2.png │ │ ├── command-ls.png │ │ ├── isakmp_dump.png │ │ ├── ATMT_TFTP_read.png │ │ ├── scapy-concept.pdf │ │ ├── scapy-concept.png │ │ ├── ATMT_HelloWorld.png │ │ ├── fieldsmanagement.pdf │ │ ├── fieldsmanagement.png │ │ ├── graph_traceroute.png │ │ ├── testing-taxonomy.png │ │ ├── default-values-ip.pdf │ │ ├── default-values-ip.png │ │ ├── scapy-win-screenshot1.png │ │ └── scapy-win-screenshot2.png │ ├── backmatter.rst │ ├── index.rst │ ├── README │ ├── Makefile │ ├── troubleshooting.rst │ ├── extending.rst │ └── conf.py └── scapy.1.gz ├── .gitignore ├── run_scapy.bat ├── run_scapy ├── bin ├── scapy.bat ├── UTscapy.bat ├── scapy └── UTscapy ├── MANIFEST.in ├── test ├── import_tester ├── run_tests.bat └── run_tests ├── scapy ├── layers │ ├── __init__.py │ ├── gprs.py │ ├── all.py │ ├── hsrp.py │ ├── l2tp.py │ ├── vrrp.py │ ├── rtp.py │ ├── ir.py │ ├── netflow.py │ ├── mgcp.py │ ├── mobileip.py │ ├── llmnr.py │ ├── ntp.py │ ├── rip.py │ ├── pflog.py │ ├── radius.py │ ├── x509.py │ ├── sebek.py │ └── skinny.py ├── tools │ ├── __init__.py │ └── check_asdis.py ├── contrib │ ├── __init__.py │ ├── vxlan.utscapy │ ├── mpls.py │ ├── etherip.py │ ├── nvgre.py │ ├── bfd.py │ ├── wpa_eapol.py │ ├── vxlan.py │ ├── geneve.py │ ├── ripng.py │ ├── erspan.py │ ├── chdlc.py │ ├── avs.py │ ├── carp.py │ ├── vqp.py │ ├── ppi_cace.py │ ├── xnt.py │ ├── ppi.py │ ├── ubberlogger.py │ ├── dtp.py │ ├── vtp.py │ ├── bgp.py │ └── igmp.py ├── modules │ ├── __init__.py │ ├── geoip.py │ ├── queso.py │ └── voip.py ├── arch │ ├── bsd.py │ ├── solaris.py │ ├── __init__.py │ ├── nanomsg.py │ └── unix.py ├── asn1 │ ├── __init__.py │ └── mib.py ├── __init__.py ├── crypto │ └── __init__.py ├── asn1packet.py ├── all.py ├── error.py ├── dadict.py ├── pton_ntop.py ├── as_resolvers.py ├── scapypipes.py ├── ansmachine.py ├── autorun.py ├── supersocket.py ├── route.py └── data.py ├── README ├── .hgsigs └── setup.py /doc/scapy/_static/_dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/scapy/_templates/_dummy: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | build/* 3 | *pyc 4 | -------------------------------------------------------------------------------- /doc/scapy.1.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy.1.gz -------------------------------------------------------------------------------- /run_scapy.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set PYTHONPATH=%cd% 3 | python -m scapy.__init__ 4 | -------------------------------------------------------------------------------- /run_scapy: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | DIR=$(dirname $0) 3 | PYTHONPATH=$DIR exec python -m scapy.__init__ 4 | -------------------------------------------------------------------------------- /doc/scapy/graphics/ipid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/ipid.png -------------------------------------------------------------------------------- /doc/scapy/graphics/trace3d_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/trace3d_1.png -------------------------------------------------------------------------------- /doc/scapy/graphics/trace3d_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/trace3d_2.png -------------------------------------------------------------------------------- /doc/scapy/graphics/command-ls.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/command-ls.png -------------------------------------------------------------------------------- /doc/scapy/graphics/isakmp_dump.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/isakmp_dump.png -------------------------------------------------------------------------------- /doc/scapy/graphics/ATMT_TFTP_read.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/ATMT_TFTP_read.png -------------------------------------------------------------------------------- /doc/scapy/graphics/scapy-concept.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/scapy-concept.pdf -------------------------------------------------------------------------------- /doc/scapy/graphics/scapy-concept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/scapy-concept.png -------------------------------------------------------------------------------- /doc/scapy/graphics/ATMT_HelloWorld.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/ATMT_HelloWorld.png -------------------------------------------------------------------------------- /doc/scapy/graphics/fieldsmanagement.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/fieldsmanagement.pdf -------------------------------------------------------------------------------- /doc/scapy/graphics/fieldsmanagement.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/fieldsmanagement.png -------------------------------------------------------------------------------- /doc/scapy/graphics/graph_traceroute.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/graph_traceroute.png -------------------------------------------------------------------------------- /doc/scapy/graphics/testing-taxonomy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/testing-taxonomy.png -------------------------------------------------------------------------------- /bin/scapy.bat: -------------------------------------------------------------------------------- 1 | @REM Use Python to run the Scapy script from the current directory, passing all parameters 2 | @python %~dp0\scapy %* 3 | -------------------------------------------------------------------------------- /doc/scapy/graphics/default-values-ip.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/default-values-ip.pdf -------------------------------------------------------------------------------- /doc/scapy/graphics/default-values-ip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/default-values-ip.png -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include run_scapy 3 | recursive-include bin * 4 | recursive-include doc * 5 | recursive-include test * 6 | -------------------------------------------------------------------------------- /bin/UTscapy.bat: -------------------------------------------------------------------------------- 1 | @REM Use Python to run the UTscapy script from the current directory, passing all parameters 2 | @python %~dp0\UTscapy %* 3 | -------------------------------------------------------------------------------- /doc/scapy/graphics/scapy-win-screenshot1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/scapy-win-screenshot1.png -------------------------------------------------------------------------------- /doc/scapy/graphics/scapy-win-screenshot2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/p4lang/scapy-vxlan/HEAD/doc/scapy/graphics/scapy-win-screenshot2.png -------------------------------------------------------------------------------- /test/import_tester: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | cd "$(dirname $0)/.." 3 | find scapy -name '*.py' | sed -e 's#/#.#g' -e 's/\(\.__init__\)\?\.py$//' | while read a; do echo "######### $a"; python -c "import $a"; done 4 | -------------------------------------------------------------------------------- /scapy/layers/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Layer package. 8 | """ 9 | -------------------------------------------------------------------------------- /scapy/tools/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Additional tools to be run separately 8 | """ 9 | -------------------------------------------------------------------------------- /test/run_tests.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | set MYDIR=%cd%\.. 3 | set PYTHONPATH=%MYDIR% 4 | if [%1]==[] ( 5 | python %MYDIR%\scapy\tools\UTscapy.py -t regression.uts -f html -o scapy_regression_test_%DATE%.html 6 | ) else ( 7 | python %MYDIR%\scapy\tools\UTscapy.py %1 %2 %3 %4 %5 %6 %7 %8 %9 8 | ) 9 | -------------------------------------------------------------------------------- /test/run_tests: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | DIR=$(dirname $0)/.. 3 | if [ "$*" == "" ] 4 | then 5 | PYTHONPATH=$DIR exec python ${DIR}/scapy/tools/UTscapy.py -t regression.uts -f html -o /tmp/scapy_regression_test_$(date +%Y%M%d-%H%H%S).html 6 | else 7 | PYTHONPATH=$DIR exec python ${DIR}/scapy/tools/UTscapy.py "$@" 8 | fi 9 | -------------------------------------------------------------------------------- /scapy/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Package of contrib modules that have to be loaded explicitly. 8 | """ 9 | -------------------------------------------------------------------------------- /scapy/modules/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Package of extension modules that have to be loaded explicitly. 8 | """ 9 | -------------------------------------------------------------------------------- /scapy/arch/bsd.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Support for BSD-like operating systems such as FreeBSD, OpenBSD and Mac OS X. 8 | """ 9 | 10 | LOOPBACK_NAME="lo0" 11 | 12 | from unix import * 13 | -------------------------------------------------------------------------------- /scapy/asn1/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Package holding ASN.1 related modules. 8 | """ 9 | 10 | # We do not import mib.py because it is more bound to scapy and 11 | # less prone to be used in a standalone fashion 12 | __all__ = ["asn1","ber"] 13 | -------------------------------------------------------------------------------- /scapy/arch/solaris.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Customization for the Solaris operation system. 8 | """ 9 | 10 | # IPPROTO_GRE is missing on Solaris 11 | import socket 12 | socket.IPPROTO_GRE = 47 13 | 14 | LOOPBACK_NAME="lo0" 15 | 16 | from unix import * 17 | -------------------------------------------------------------------------------- /scapy/contrib/vxlan.utscapy: -------------------------------------------------------------------------------- 1 | % VXLAN Tests 2 | * Tests for the Scapy VXLAN layer 3 | 4 | = Build a VXLAN packet with VNI of 42 5 | str(UDP(sport=1024, dport=4789, len=None, chksum=None)/VXLAN(flags=0x08, vni=42)) == "\x04\x00\x12\xb5\x00\x10\x00\x00\x08\x00\x00\x00\x00\x00\x2a\x00" 6 | 7 | = Verify VXLAN Ethernet Binding 8 | str(VXLAN(vni=23)/Ether(dst="11:11:11:11:11:11", src="11:11:11:11:11:11", type=0x800)) == "\x08\x00\x00\x00\x00\x00\x17\x00\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x08\x00" 9 | -------------------------------------------------------------------------------- /scapy/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Scapy: create, send, sniff, dissect and manipulate network packets. 8 | 9 | Usable either from an interactive console or as a Python library. 10 | http://www.secdev.org/projects/scapy 11 | """ 12 | 13 | if __name__ == "__main__": 14 | from scapy.main import interact 15 | interact() 16 | -------------------------------------------------------------------------------- /doc/scapy/backmatter.rst: -------------------------------------------------------------------------------- 1 | 2 | ********* 3 | Credits 4 | ********* 5 | 6 | - Philippe Biondi is Scapy's author. He has also written most of the documentation. 7 | - Fred Raynal wrote the chapter on building and dissecting packets. 8 | - Sebastien Martini added some details in "Handling default values: automatic computation". 9 | - Peter Kacherginsky contributed several tutorial sections, one-liners and recipes. 10 | - Dirk Loss integrated and restructured the existing docs to make this book. 11 | He has also written the installation instructions for Windows. 12 | 13 | 14 | -------------------------------------------------------------------------------- /scapy/contrib/mpls.py: -------------------------------------------------------------------------------- 1 | # http://trac.secdev.org/scapy/ticket/31 2 | 3 | # scapy.contrib.description = MPLS 4 | # scapy.contrib.status = loads 5 | 6 | from scapy.packet import Packet,bind_layers 7 | from scapy.fields import BitField,ByteField 8 | from scapy.layers.l2 import Ether 9 | 10 | class MPLS(Packet): 11 | name = "MPLS" 12 | fields_desc = [ BitField("label", 3, 20), 13 | BitField("cos", 0, 3), 14 | BitField("s", 1, 1), 15 | ByteField("ttl", 0) ] 16 | 17 | bind_layers(Ether, MPLS, type=0x8847) 18 | -------------------------------------------------------------------------------- /scapy/crypto/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Arnaud Ebalard 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Tools for handling with digital certificates. 8 | """ 9 | 10 | try: 11 | import Crypto 12 | except ImportError: 13 | import logging 14 | log_loading = logging.getLogger("scapy.loading") 15 | log_loading.info("Can't import python Crypto lib. Disabled certificate manipulation tools") 16 | else: 17 | from scapy.crypto.cert import * 18 | -------------------------------------------------------------------------------- /scapy/contrib/etherip.py: -------------------------------------------------------------------------------- 1 | 2 | # http://trac.secdev.org/scapy/ticket/297 3 | 4 | # scapy.contrib.description = EtherIP 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.fields import BitField 8 | from scapy.packet import Packet, bind_layers 9 | from scapy.layers.inet import IP 10 | from scapy.layers.l2 import Ether 11 | 12 | class EtherIP(Packet): 13 | name = "EtherIP / RFC 3378" 14 | fields_desc = [ BitField("version", 3, 4), 15 | BitField("reserved", 0, 12)] 16 | 17 | bind_layers( IP, EtherIP, frag=0, proto=0x61) 18 | bind_layers( EtherIP, Ether) 19 | 20 | -------------------------------------------------------------------------------- /scapy/layers/gprs.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | GPRS (General Packet Radio Service) for mobile data communication. 8 | """ 9 | 10 | from scapy.fields import * 11 | from scapy.packet import * 12 | from scapy.layers.inet import IP 13 | 14 | class GPRS(Packet): 15 | name = "GPRSdummy" 16 | fields_desc = [ 17 | StrStopField("dummy","","\x65\x00\x00",1) 18 | ] 19 | 20 | 21 | bind_layers( GPRS, IP, ) 22 | -------------------------------------------------------------------------------- /scapy/asn1packet.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Packet holding data in Abstract Syntax Notation (ASN.1). 8 | """ 9 | 10 | from packet import * 11 | 12 | class ASN1_Packet(Packet): 13 | ASN1_root = None 14 | ASN1_codec = None 15 | def init_fields(self): 16 | flist = self.ASN1_root.get_fields_list() 17 | self.do_init_fields(flist) 18 | self.fields_desc = flist 19 | def self_build(self): 20 | return self.ASN1_root.build(self) 21 | def do_dissect(self, x): 22 | return self.ASN1_root.dissect(self, x) 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/scapy/index.rst: -------------------------------------------------------------------------------- 1 | .. Scapy documentation master file, created by sphinx-quickstart on Mon Sep 8 19:37:39 2008. 2 | You can adapt this file completely to your liking, but it should at least 3 | contain the root `toctree` directive. 4 | 5 | Welcome to Scapy's documentation! 6 | ================================= 7 | 8 | :Release: |version| 9 | :Date: |today| 10 | 11 | This document is under a `Creative Commons Attribution - Non-Commercial 12 | - Share Alike 2.5 `_ license. 13 | 14 | .. toctree:: 15 | :maxdepth: 2 16 | 17 | introduction 18 | installation 19 | 20 | usage 21 | advanced_usage 22 | extending 23 | build_dissect 24 | 25 | troubleshooting 26 | development 27 | backmatter 28 | 29 | -------------------------------------------------------------------------------- /doc/scapy/README: -------------------------------------------------------------------------------- 1 | This folder includes source files (text and graphics) for Scapy's documentation, 2 | which is automatically built using Sphinx 3 | 4 | The *.rst files are written as reStructuredText and should be quite readable 5 | in your favourite text editor without any further formatting. 6 | 7 | To generate much nicer, searchable HTML docs, install Sphinx, open a command 8 | line, change to the directory where this README is placed, and type the 9 | following command: 10 | 11 | $ make html 12 | 13 | To generate a single PDF file (useful for printing) you need a working 14 | LaTeX installation (e.g. ). 15 | The following commands produce the file Scapy.pdf (>100 pages): 16 | 17 | $ make latex 18 | $ cd _build/latex 19 | $ make all-pdf -------------------------------------------------------------------------------- /scapy/layers/all.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | All layers. Configurable with conf.load_layers. 8 | """ 9 | 10 | from scapy.config import conf 11 | from scapy.error import log_loading 12 | import logging 13 | log = logging.getLogger("scapy.loading") 14 | 15 | def _import_star(m): 16 | mod = __import__(m, globals(), locals()) 17 | for k,v in mod.__dict__.iteritems(): 18 | globals()[k] = v 19 | 20 | for _l in conf.load_layers: 21 | log_loading.debug("Loading layer %s" % _l) 22 | try: 23 | _import_star(_l) 24 | except Exception,e: 25 | log.warning("can't import layer %s: %s" % (_l,e)) 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | THIS REPOSITORY IS DEPRECATED AND IS NO LONGER MAINTAINED. P4LANG SOFTWARE NOW 2 | USES UPSTREAM SCAPY, WHICH SUPPORTS VXLAN, GENEVE, ETC. 3 | 4 | Barefoot modified scapy, which supports VXLAN. Waiting for VXLAN support to be 5 | added to the main scapy repo. 6 | This modified repo now also supports a ERSPAN-like header. 7 | 8 | To install: 9 | sudo python setup.py install 10 | 11 | To check that the modifications work, open a scapy CLI (just type 'scapy' in a 12 | terminal) and type the following: 13 | 14 | Welcome to Scapy (2.2.0-dev) 15 | >>> load_contrib('vxlan') 16 | >>> Ether()/IP()/UDP()/VXLAN()/Ether()/IP()/TCP() 17 | >>>>>> 19 | >>> load_contrib('erspan') 20 | >>> Ether()/IP()/GRE()/ERSPAN()/Ether()/IP()/TCP() 21 | >>>>>> 23 | >>> 24 | 25 | Note how the UDP dport and the GRE proto number are updated automatically. 26 | 27 | -------------------------------------------------------------------------------- /.hgsigs: -------------------------------------------------------------------------------- 1 | 1fe855059e5c67fdd8984045916dc959b7688881 0 iD8DBQBFu5AqXuj/Xz2aQ+IRAndrAJoDun1mMGRkCUoERUd42b5bQ4lzRgCgqpXpzIFw00mjIv1ErnESkLYfziA= 2 | 35c358be00fede40334734d6ae1d263a266c3701 0 iD8DBQBGE5vPXuj/Xz2aQ+IRAgpuAKC4SxP4WVu5PgiW5150iKZ79wIr/QCfVHcMQInO3jzhhLdVseT9PB/xv7Q= 3 | d8a91f28e741bb8af8975658a8a5a539107c1ea2 0 iD8DBQBGGjz5Xuj/Xz2aQ+IRAmNHAJ9ttQ67KKbqYse4af4hgwdYPWxdiwCgg1+4HS9sREyplo/0GMS8XOfSnck= 4 | 105de7dc59f734c36488fd77926ca65b675bf541 0 iD8DBQBG6nscXuj/Xz2aQ+IRAkQbAJ47GgD2QrQdAq/R+GxYuqTuJs3khQCfd8w+LKvcyWLdl+sbYNjXjPnhTpk= 5 | 9642ec17c7b8b63297bf9372f2d8084053304e79 0 iEYEABECAAYFAkmQI/4ACgkQXuj/Xz2aQ+IGVQCdH2MFM/AmFknON6PGBy5jtYmBXi8AoImp0HqW0KDawiRhw8N3oAy9bSd5 6 | 8ac76c4dfc2ea44482d2e68a9877a80ae433467e 0 iEYEABECAAYFAksmWiwACgkQXuj/Xz2aQ+J/QwCgsEQnlxjr2HfXsOELtE6wRvH7BaMAn2tAfl9Z1JanqS7YvP1yXtTCaQJx 7 | 9bea293f85d7f365ab1f30bfa0d266565c3ed86b 0 iEYEABECAAYFAku/q/wACgkQXuj/Xz2aQ+L03wCfTB+QAsTvFThjdOsLExmQmC0ISvAAoIajI2EMebxeth6HbRtXoLFm2ETB 8 | 2e1a9aa8524281f7e4c9c0b93e0f017e50d2baf7 0 iEYEABECAAYFAk1rBKoACgkQXuj/Xz2aQ+LKVwCgsmmSEzijKWqm5/+spP0Ro2/vSvMAmgP3551nDejeo6Wbklkn0XaTpY/C 9 | -------------------------------------------------------------------------------- /scapy/contrib/nvgre.py: -------------------------------------------------------------------------------- 1 | # Network Virtualization using Generic Rotuing Encapsulation (NVGRE) 2 | #https://tools.ietf.org/html/draft-sridharan-virtualization-nvgre-00 3 | 4 | # scapy.contrib.description = NVGRE 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | from scapy.all import * # Otherwise failing at the UDP reference below 10 | 11 | class NVGRE(Packet): 12 | name = "NVGRE" 13 | 14 | fields_desc = [ BitField("chksum_present",0,1), 15 | BitField("routing_present",0,1), 16 | BitField("key_present",1,1), 17 | BitField("seqnum_present",0,1), 18 | BitField("reserved",0,9), 19 | BitField("version",0,3), 20 | XShortField("proto", 0x6558), 21 | ThreeBytesField("vsid", 0), 22 | XByteField("flowid", 0) 23 | ] 24 | 25 | def mysummary(self): 26 | return self.sprintf("NVGRE (vni=%NVGRE.vsid%)") 27 | 28 | bind_layers(IP, NVGRE, proto=47) 29 | bind_layers(NVGRE, Ether) 30 | -------------------------------------------------------------------------------- /scapy/layers/hsrp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | HSRP (Hot Standby Router Protocol): proprietary redundancy protocol for Cisco routers. 8 | """ 9 | 10 | from scapy.fields import * 11 | from scapy.packet import * 12 | from scapy.layers.inet import UDP 13 | 14 | class HSRP(Packet): 15 | name = "HSRP" 16 | fields_desc = [ 17 | ByteField("version", 0), 18 | ByteEnumField("opcode", 0, { 0:"Hello", 1:"Coup", 2:"Resign", 3:"Advertise"}), 19 | ByteEnumField("state", 16, { 0:"Initial", 1:"Learn", 2:"Listen", 4:"Speak", 8:"Standby", 16:"Active"}), 20 | ByteField("hellotime", 3), 21 | ByteField("holdtime", 10), 22 | ByteField("priority", 120), 23 | ByteField("group", 1), 24 | ByteField("reserved", 0), 25 | StrFixedLenField("auth","cisco",8), 26 | IPField("virtualIP","192.168.1.1") ] 27 | 28 | 29 | 30 | 31 | 32 | bind_layers( UDP, HSRP, dport=1985, sport=1985) 33 | -------------------------------------------------------------------------------- /scapy/layers/l2tp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | L2TP (Layer 2 Tunneling Protocol) for VPNs. 8 | 9 | [RFC 2661] 10 | """ 11 | 12 | import struct 13 | 14 | from scapy.packet import * 15 | from scapy.fields import * 16 | from scapy.layers.inet import UDP 17 | from scapy.layers.ppp import PPP 18 | 19 | class L2TP(Packet): 20 | fields_desc = [ ShortEnumField("pkt_type",2,{2:"data"}), 21 | ShortField("len", None), 22 | ShortField("tunnel_id", 0), 23 | ShortField("session_id", 0), 24 | ShortField("ns", 0), 25 | ShortField("nr", 0), 26 | ShortField("offset", 0) ] 27 | 28 | def post_build(self, pkt, pay): 29 | if self.len is None: 30 | l = len(pkt)+len(pay) 31 | pkt = pkt[:2]+struct.pack("!H", l)+pkt[4:] 32 | return pkt+pay 33 | 34 | 35 | bind_layers( UDP, L2TP, sport=1701, dport=1701) 36 | bind_layers( L2TP, PPP, ) 37 | -------------------------------------------------------------------------------- /scapy/all.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Aggregate top level objects from all Scapy modules. 8 | """ 9 | 10 | from base_classes import * 11 | from config import * 12 | from dadict import * 13 | from data import * 14 | from error import * 15 | from themes import * 16 | from arch import * 17 | 18 | from plist import * 19 | from fields import * 20 | from packet import * 21 | from asn1fields import * 22 | from asn1packet import * 23 | 24 | from utils import * 25 | from route import * 26 | if conf.ipv6_enabled: 27 | from utils6 import * 28 | from route6 import * 29 | from sendrecv import * 30 | from supersocket import * 31 | from volatile import * 32 | from as_resolvers import * 33 | 34 | from ansmachine import * 35 | from automaton import * 36 | from autorun import * 37 | 38 | from main import * 39 | 40 | from layers.all import * 41 | 42 | from asn1.asn1 import * 43 | from asn1.ber import * 44 | from asn1.mib import * 45 | 46 | from crypto import * 47 | 48 | from pipetool import * 49 | from scapypipes import * 50 | -------------------------------------------------------------------------------- /scapy/contrib/bfd.py: -------------------------------------------------------------------------------- 1 | # BFD - Bidirectional Forwarding Detection - RFC 5880, 5881 2 | 3 | # scapy.contrib.description = BFD 4 | # scapy.contrib.status = loads 5 | 6 | from scapy.packet import * 7 | from scapy.fields import * 8 | from scapy.all import * # Otherwise failing at the UDP reference below 9 | 10 | class BFD(Packet): 11 | name = "BFD" 12 | fields_desc = [ 13 | BitField("version" , 1 , 3), 14 | BitField("diag" , 0 , 5), 15 | BitField("sta" , 3 , 2), 16 | FlagsField("flags", 0x00, 6, ['P', 'F', 'C', 'A', 'D', 'M']), 17 | XByteField("detect_mult", 0x03), 18 | XByteField("len", 24), 19 | BitField("my_discriminator" , 0x11111111 , 32), 20 | BitField("your_discriminator" , 0x22222222 , 32), 21 | BitField("min_tx_interval" , 1000000000, 32), 22 | BitField("min_rx_interval" , 1000000000, 32), 23 | BitField("echo_rx_interval" , 1000000000, 32) ] 24 | 25 | def mysummary(self): 26 | return self.sprintf("BFD (my_disc=%BFD.my_discriminator%, your_disc=%BFD.my_discriminator%)") 27 | 28 | bind_layers(UDP, BFD, dport=3784) 29 | -------------------------------------------------------------------------------- /scapy/layers/vrrp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## Copyright (C) 6WIND 5 | ## This program is published under a GPLv2 license 6 | 7 | """ 8 | VRRP (Virtual Router Redundancy Protocol). 9 | """ 10 | 11 | from scapy.packet import * 12 | from scapy.fields import * 13 | from scapy.layers.inet import IP 14 | 15 | IPPROTO_VRRP=112 16 | 17 | # RFC 3768 - Virtual Router Redundancy Protocol (VRRP) 18 | class VRRP(Packet): 19 | fields_desc = [ 20 | BitField("version" , 2, 4), 21 | BitField("type" , 1, 4), 22 | ByteField("vrid", 1), 23 | ByteField("priority", 100), 24 | FieldLenField("ipcount", None, count_of="addrlist", fmt="B"), 25 | ByteField("authtype", 0), 26 | ByteField("adv", 1), 27 | XShortField("chksum", None), 28 | FieldListField("addrlist", [], IPField("", "0.0.0.0"), 29 | count_from = lambda pkt: pkt.ipcount), 30 | IntField("auth1", 0), 31 | IntField("auth2", 0) ] 32 | 33 | def post_build(self, p, pay): 34 | if self.chksum is None: 35 | ck = checksum(p) 36 | p = p[:6]+chr(ck>>8)+chr(ck&0xff)+p[8:] 37 | return p 38 | 39 | bind_layers( IP, VRRP, proto=IPPROTO_VRRP) 40 | -------------------------------------------------------------------------------- /scapy/contrib/wpa_eapol.py: -------------------------------------------------------------------------------- 1 | 2 | # http://trac.secdev.org/scapy/ticket/104 3 | 4 | # scapy.contrib.description = WPA EAPOL dissector 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | from scapy.layers.l2 import * 10 | 11 | class WPA_key(Packet): 12 | name = "WPA_key" 13 | fields_desc = [ ByteField("descriptor_type", 1), 14 | ShortField("key_info",0), 15 | LenField("len", None, "H"), 16 | StrFixedLenField("replay_counter", "", 8), 17 | StrFixedLenField("nonce", "", 32), 18 | StrFixedLenField("key_iv", "", 16), 19 | StrFixedLenField("wpa_key_rsc", "", 8), 20 | StrFixedLenField("wpa_key_id", "", 8), 21 | StrFixedLenField("wpa_key_mic", "", 16), 22 | LenField("wpa_key_length", None, "H"), 23 | StrLenField("wpa_key", "", length_from=lambda pkt:pkt.wpa_key_length) ] 24 | def extract_padding(self, s): 25 | l = self.len 26 | return s[:l],s[l:] 27 | def hashret(self): 28 | return chr(self.type)+self.payload.hashret() 29 | def answers(self, other): 30 | if isinstance(other,WPA_key): 31 | return 1 32 | return 0 33 | 34 | 35 | bind_layers( EAPOL, WPA_key, type=3) 36 | -------------------------------------------------------------------------------- /scapy/contrib/vxlan.py: -------------------------------------------------------------------------------- 1 | # Virtual eXtensible Local Area Network (VXLAN) 2 | # https://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-06 3 | 4 | # scapy.contrib.description = VXLAN 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | from scapy.all import * # Otherwise failing at the UDP reference below 10 | 11 | class VXLAN(Packet): 12 | name = "VXLAN" 13 | fields_desc = [ FlagsField("flags", 0x08, 8, ['R', 'R', 'R', 'I', 'R', 'R', 'R', 'R']), 14 | X3BytesField("reserved1", 0x000000), 15 | ThreeBytesField("vni", 0), 16 | XByteField("reserved2", 0x00)] 17 | 18 | def mysummary(self): 19 | return self.sprintf("VXLAN (vni=%VXLAN.vni%)") 20 | 21 | bind_layers(UDP, VXLAN, dport=4789) 22 | bind_layers(VXLAN, Ether) 23 | 24 | class VXLAN_GPE(Packet): 25 | name = "VXLAN_GPE" 26 | fields_desc = [ FlagsField("flags", 0x18, 8, ['R', 'R', 'R', 'I', 'P', 'R', 'R', 'R']), 27 | XShortField("reserved1", 0x0000), 28 | XByteField("next_proto", 0x03), 29 | ThreeBytesField("vni", 0), 30 | XByteField("reserved2", 0x00)] 31 | 32 | def mysummary(self): 33 | return self.sprintf("VXLAN_GPE (vni=%VXLAN_GPE.vni%)") 34 | 35 | bind_layers(UDP, VXLAN_GPE, dport=4790) 36 | bind_layers(VXLAN_GPE, Ether, next_proto=3) 37 | -------------------------------------------------------------------------------- /scapy/contrib/geneve.py: -------------------------------------------------------------------------------- 1 | # Geneve Draft(GENEVE) 2 | # http://tools.ietf.org/html/draft-gross-geneve-01 3 | 4 | # scapy.contrib.description = GENEVE 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | from scapy.all import * # Otherwise failing at the UDP reference below 10 | 11 | class GENEVE(Packet): 12 | name = "GENEVE" 13 | fields_desc = [ BitField("version",0,2), 14 | BitField("optionlen",0,6), 15 | BitField("oam",0,1), 16 | BitField("critical",0,1), 17 | BitField("reserved",0,6), 18 | XShortField("proto", 0x6558), 19 | ThreeBytesField("vni", 0), 20 | XByteField("reserved2", 0x00)] 21 | 22 | def mysummary(self): 23 | return self.sprintf("GENEVE (vni=%GENEVE.vni%)") 24 | 25 | def guess_payload_class(self, payload): 26 | if int(self.optionlen) > 0: 27 | if ord(payload[0]) == 0x01 and ord(payload[1]) == 0x03: 28 | int_type = ord(payload[2]) 29 | if int_type == 1 or int_type == 2: 30 | return GENEVE_INT 31 | elif int_type == 3: 32 | return GENEVE_INT_PLT 33 | 34 | return Packet.guess_payload_class(self, payload) 35 | 36 | bind_layers(UDP, GENEVE, dport=6081) 37 | bind_layers(GENEVE, Ether, proto=0x6558) 38 | -------------------------------------------------------------------------------- /scapy/contrib/ripng.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # http://trac.secdev.org/scapy/ticket/301 4 | 5 | # scapy.contrib.description = RIPng 6 | # scapy.contrib.status = loads 7 | 8 | from scapy.packet import * 9 | from scapy.fields import * 10 | from scapy.layers.inet import UDP 11 | from scapy.layers.inet6 import * 12 | 13 | class RIPng(Packet): 14 | name = "RIPng header" 15 | fields_desc = [ 16 | ByteEnumField("cmd", 1, {1 : "req", 2 : "resp"}), 17 | ByteField("ver", 1), 18 | ShortField("null", 0), 19 | ] 20 | 21 | class RIPngEntry(Packet): 22 | name = "RIPng entry" 23 | fields_desc = [ 24 | ConditionalField(IP6Field("prefix", "::"), 25 | lambda pkt: pkt.metric != 255), 26 | ConditionalField(IP6Field("nexthop", "::"), 27 | lambda pkt: pkt.metric == 255), 28 | ShortField("routetag", 0), 29 | ByteField("prefixlen", 0), 30 | ByteEnumField("metric", 1, {16 : "Unreach", 31 | 255 : "next-hop entry"}) 32 | ] 33 | 34 | bind_layers(UDP, RIPng, sport=521, dport=521) 35 | bind_layers(RIPng, RIPngEntry) 36 | bind_layers(RIPngEntry, RIPngEntry) 37 | 38 | if __name__ == "__main__": 39 | from scapy.main import interact 40 | interact(mydict=globals(), mybanner="RIPng") 41 | 42 | -------------------------------------------------------------------------------- /bin/scapy: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | ############################################################################# 4 | ## ## 5 | ## scapy.py --- Interactive packet manipulation tool ## 6 | ## see http://www.secdev.org/projects/scapy/ ## 7 | ## for more informations ## 8 | ## ## 9 | ## Copyright (C) Philippe Biondi ## 10 | ## ## 11 | ## This program is free software; you can redistribute it and/or modify it ## 12 | ## under the terms of the GNU General Public License version 2 as ## 13 | ## published by the Free Software Foundation. ## 14 | ## ## 15 | ## This program is distributed in the hope that it will be useful, but ## 16 | ## WITHOUT ANY WARRANTY; without even the implied warranty of ## 17 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## 18 | ## General Public License for more details. ## 19 | ## ## 20 | ############################################################################# 21 | 22 | 23 | from scapy.main import interact 24 | 25 | interact() 26 | -------------------------------------------------------------------------------- /bin/UTscapy: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | 4 | ############################################################################# 5 | ## ## 6 | ## UTscapy.py --- Unit Tests with scapy ## 7 | ## see http://www.secdev.org/projects/UTscapy/ ## 8 | ## for more informations ## 9 | ## ## 10 | ## Copyright (C) 2005 Philippe Biondi ## 11 | ## ## 12 | ## This program is free software; you can redistribute it and/or modify it ## 13 | ## under the terms of the GNU General Public License version 2 as ## 14 | ## published by the Free Software Foundation. ## 15 | ## ## 16 | ## This program is distributed in the hope that it will be useful, but ## 17 | ## WITHOUT ANY WARRANTY; without even the implied warranty of ## 18 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ## 19 | ## General Public License for more details. ## 20 | ## ## 21 | ############################################################################# 22 | 23 | 24 | import sys 25 | from scapy.tools.UTscapy import main 26 | 27 | main(sys.argv[1:]) 28 | -------------------------------------------------------------------------------- /scapy/layers/rtp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | RTP (Real-time Transport Protocol). 8 | """ 9 | 10 | from scapy.packet import * 11 | from scapy.fields import * 12 | 13 | _rtp_payload_types = { 14 | # http://www.iana.org/assignments/rtp-parameters 15 | 0: 'G.711 PCMU', 3: 'GSM', 16 | 4: 'G723', 5: 'DVI4', 17 | 6: 'DVI4', 7: 'LPC', 18 | 8: 'PCMA', 9: 'G722', 19 | 10: 'L16', 11: 'L16', 20 | 12: 'QCELP', 13: 'CN', 21 | 14: 'MPA', 15: 'G728', 22 | 16: 'DVI4', 17: 'DVI4', 23 | 18: 'G729', 25: 'CelB', 24 | 26: 'JPEG', 28: 'nv', 25 | 31: 'H261', 32: 'MPV', 26 | 33: 'MP2T', 34: 'H263' } 27 | 28 | class RTP(Packet): 29 | name="RTP" 30 | fields_desc = [ BitField('version', 2, 2), 31 | BitField('padding', 0, 1), 32 | BitField('extension', 0, 1), 33 | BitFieldLenField('numsync', None, 4, count_of='sync'), 34 | BitField('marker', 0, 1), 35 | BitEnumField('payload', 0, 7, _rtp_payload_types), 36 | ShortField('sequence', 0), 37 | IntField('timestamp', 0), 38 | IntField('sourcesync', 0), 39 | FieldListField('sync', [], IntField("id",0), count_from=lambda pkt:pkt.numsync) ] 40 | 41 | -------------------------------------------------------------------------------- /scapy/layers/ir.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | IrDA infrared data communication. 8 | """ 9 | 10 | from scapy.packet import * 11 | from scapy.fields import * 12 | from scapy.layers.l2 import CookedLinux 13 | 14 | 15 | 16 | # IR 17 | 18 | class IrLAPHead(Packet): 19 | name = "IrDA Link Access Protocol Header" 20 | fields_desc = [ XBitField("Address", 0x7f, 7), 21 | BitEnumField("Type", 1, 1, {"Response":0, 22 | "Command":1})] 23 | 24 | class IrLAPCommand(Packet): 25 | name = "IrDA Link Access Protocol Command" 26 | fields_desc = [ XByteField("Control", 0), 27 | XByteField("Format identifier", 0), 28 | XIntField("Source address", 0), 29 | XIntField("Destination address", 0xffffffffL), 30 | XByteField("Discovery flags", 0x1), 31 | ByteEnumField("Slot number", 255, {"final":255}), 32 | XByteField("Version", 0)] 33 | 34 | 35 | class IrLMP(Packet): 36 | name = "IrDA Link Management Protocol" 37 | fields_desc = [ XShortField("Service hints", 0), 38 | XByteField("Character set", 0), 39 | StrField("Device name", "") ] 40 | 41 | 42 | bind_layers( CookedLinux, IrLAPHead, proto=23) 43 | bind_layers( IrLAPHead, IrLAPCommand, Type=1) 44 | bind_layers( IrLAPCommand, IrLMP, ) 45 | -------------------------------------------------------------------------------- /scapy/contrib/erspan.py: -------------------------------------------------------------------------------- 1 | # Encapsulated Remote Switch Packet Analysis 2 | 3 | # scapy.contrib.description = VXLAN 4 | # scapy.contrib.status = loads 5 | 6 | from scapy.packet import * 7 | from scapy.fields import * 8 | from scapy.all import * 9 | 10 | class ERSPAN(Packet): 11 | name = "ERSPAN" 12 | fields_desc = [ BitField("version", 1, 4), 13 | BitField("vlan", 0, 12), 14 | BitField("priority", 0, 3), 15 | BitField("unknown2", 0, 1), 16 | BitField("direction", 0, 1), 17 | BitField("truncated", 0, 1), 18 | BitField("span_id", 0, 10), 19 | XIntField("unknown7", 0x00000000)] 20 | 21 | bind_layers(GRE, ERSPAN, proto=0x88be) 22 | bind_layers(ERSPAN, Ether) 23 | 24 | class ERSPAN_III(Packet): 25 | name = "ERSPAN_III" 26 | fields_desc = [ BitField("version", 2, 4), 27 | BitField("vlan", 0, 12), 28 | BitField("priority", 0, 3), 29 | BitField("unknown2", 0, 1), 30 | BitField("direction", 0, 1), 31 | BitField("truncated", 0, 1), 32 | BitField("span_id", 0, 10), 33 | XIntField("timestamp", 0x00000000), 34 | XIntField("sgt_other", 0x00000000)] 35 | 36 | class PlatformSpecific(Packet): 37 | name = "PlatformSpecific" 38 | fields_desc = [ BitField("platf_id", 0, 6), 39 | BitField("info1", 0 ,26), 40 | XIntField("info2", 0x00000000)] 41 | 42 | bind_layers(GRE, ERSPAN_III, proto=0x22eb) 43 | bind_layers(ERSPAN_III, Ether, sgt_other=0) 44 | bind_layers(ERSPAN_III, PlatformSpecific, sgt_other=1) 45 | bind_layers(PlatformSpecific, Ether) 46 | -------------------------------------------------------------------------------- /scapy/layers/netflow.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Cisco NetFlow protocol v1 8 | """ 9 | 10 | 11 | from scapy.fields import * 12 | from scapy.packet import * 13 | 14 | # Cisco Netflow Protocol version 1 15 | class NetflowHeader(Packet): 16 | name = "Netflow Header" 17 | fields_desc = [ ShortField("version", 1) ] 18 | 19 | class NetflowHeaderV1(Packet): 20 | name = "Netflow Header V1" 21 | fields_desc = [ ShortField("count", 0), 22 | IntField("sysUptime", 0), 23 | IntField("unixSecs", 0), 24 | IntField("unixNanoSeconds", 0) ] 25 | 26 | 27 | class NetflowRecordV1(Packet): 28 | name = "Netflow Record" 29 | fields_desc = [ IPField("ipsrc", "0.0.0.0"), 30 | IPField("ipdst", "0.0.0.0"), 31 | IPField("nexthop", "0.0.0.0"), 32 | ShortField("inputIfIndex", 0), 33 | ShortField("outpuIfIndex", 0), 34 | IntField("dpkts", 0), 35 | IntField("dbytes", 0), 36 | IntField("starttime", 0), 37 | IntField("endtime", 0), 38 | ShortField("srcport", 0), 39 | ShortField("dstport", 0), 40 | ShortField("padding", 0), 41 | ByteField("proto", 0), 42 | ByteField("tos", 0), 43 | IntField("padding1", 0), 44 | IntField("padding2", 0) ] 45 | 46 | 47 | bind_layers( NetflowHeader, NetflowHeaderV1, version=1) 48 | bind_layers( NetflowHeaderV1, NetflowRecordV1, ) 49 | -------------------------------------------------------------------------------- /scapy/layers/mgcp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | MGCP (Media Gateway Control Protocol) 8 | 9 | [RFC 2805] 10 | """ 11 | 12 | from scapy.packet import * 13 | from scapy.fields import * 14 | from scapy.layers.inet import UDP 15 | 16 | class MGCP(Packet): 17 | name = "MGCP" 18 | longname = "Media Gateway Control Protocol" 19 | fields_desc = [ StrStopField("verb","AUEP"," ", -1), 20 | StrFixedLenField("sep1"," ",1), 21 | StrStopField("transaction_id","1234567"," ", -1), 22 | StrFixedLenField("sep2"," ",1), 23 | StrStopField("endpoint","dummy@dummy.net"," ", -1), 24 | StrFixedLenField("sep3"," ",1), 25 | StrStopField("version","MGCP 1.0 NCS 1.0","\x0a", -1), 26 | StrFixedLenField("sep4","\x0a",1), 27 | ] 28 | 29 | 30 | #class MGCP(Packet): 31 | # name = "MGCP" 32 | # longname = "Media Gateway Control Protocol" 33 | # fields_desc = [ ByteEnumField("type",0, ["request","response","others"]), 34 | # ByteField("code0",0), 35 | # ByteField("code1",0), 36 | # ByteField("code2",0), 37 | # ByteField("code3",0), 38 | # ByteField("code4",0), 39 | # IntField("trasid",0), 40 | # IntField("req_time",0), 41 | # ByteField("is_duplicate",0), 42 | # ByteField("req_available",0) ] 43 | # 44 | bind_layers( UDP, MGCP, dport=2727) 45 | bind_layers( UDP, MGCP, sport=2727) 46 | -------------------------------------------------------------------------------- /scapy/layers/mobileip.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Mobile IP. 8 | """ 9 | 10 | from scapy.fields import * 11 | from scapy.packet import * 12 | from scapy.layers.inet import IP,UDP 13 | 14 | 15 | class MobileIP(Packet): 16 | name = "Mobile IP (RFC3344)" 17 | fields_desc = [ ByteEnumField("type", 1, {1:"RRQ", 3:"RRP"}) ] 18 | 19 | class MobileIPRRQ(Packet): 20 | name = "Mobile IP Registration Request (RFC3344)" 21 | fields_desc = [ XByteField("flags", 0), 22 | ShortField("lifetime", 180), 23 | IPField("homeaddr", "0.0.0.0"), 24 | IPField("haaddr", "0.0.0.0"), 25 | IPField("coaddr", "0.0.0.0"), 26 | LongField("id", 0), ] 27 | 28 | class MobileIPRRP(Packet): 29 | name = "Mobile IP Registration Reply (RFC3344)" 30 | fields_desc = [ ByteField("code", 0), 31 | ShortField("lifetime", 180), 32 | IPField("homeaddr", "0.0.0.0"), 33 | IPField("haaddr", "0.0.0.0"), 34 | LongField("id", 0), ] 35 | 36 | class MobileIPTunnelData(Packet): 37 | name = "Mobile IP Tunnel Data Message (RFC3519)" 38 | fields_desc = [ ByteField("nexthdr", 4), 39 | ShortField("res", 0) ] 40 | 41 | 42 | bind_layers( UDP, MobileIP, sport=434) 43 | bind_layers( UDP, MobileIP, dport=434) 44 | bind_layers( MobileIP, MobileIPRRQ, type=1) 45 | bind_layers( MobileIP, MobileIPRRP, type=3) 46 | bind_layers( MobileIP, MobileIPTunnelData, type=4) 47 | bind_layers( MobileIPTunnelData, IP, nexthdr=4) 48 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | """ 4 | Distutils setup file for Scapy. 5 | """ 6 | 7 | 8 | from distutils import archive_util 9 | from distutils import sysconfig 10 | from distutils.core import setup 11 | from distutils.command.sdist import sdist 12 | import os 13 | 14 | 15 | EZIP_HEADER="""#! /bin/sh 16 | PYTHONPATH=$0/%s exec python -m scapy.__init__ 17 | """ 18 | 19 | def make_ezipfile(base_name, base_dir, verbose=0, dry_run=0): 20 | fname = archive_util.make_zipfile(base_name, base_dir, verbose, dry_run) 21 | ofname = fname+".old" 22 | os.rename(fname,ofname) 23 | of=open(ofname) 24 | f=open(fname,"w") 25 | f.write(EZIP_HEADER % base_dir) 26 | while True: 27 | data = of.read(8192) 28 | if not data: 29 | break 30 | f.write(data) 31 | f.close() 32 | os.system("zip -A '%s'" % fname) 33 | of.close() 34 | os.unlink(ofname) 35 | os.chmod(fname,0o755) 36 | return fname 37 | 38 | 39 | 40 | archive_util.ARCHIVE_FORMATS["ezip"] = (make_ezipfile,[],'Executable ZIP file') 41 | 42 | SCRIPTS = ['bin/scapy','bin/UTscapy'] 43 | # On Windows we also need additional batch files to run the above scripts 44 | if os.name == "nt": 45 | SCRIPTS += ['bin/scapy.bat','bin/UTscapy.bat'] 46 | 47 | setup( 48 | name = 'scapy', 49 | version = '2.2.0-dev', 50 | packages=['scapy','scapy/arch', 'scapy/arch/windows', 'scapy/layers','scapy/asn1','scapy/tools','scapy/modules', 'scapy/crypto', 'scapy/contrib'], 51 | scripts = SCRIPTS, 52 | data_files = [('share/man/man1', ["doc/scapy.1.gz"])], 53 | 54 | # Metadata 55 | author = 'Philippe BIONDI', 56 | author_email = 'phil(at)secdev.org', 57 | description = 'Scapy: interactive packet manipulation tool', 58 | license = 'GPLv2', 59 | url = 'http://www.secdev.org/projects/scapy' 60 | # keywords = '', 61 | # url = '', 62 | ) 63 | -------------------------------------------------------------------------------- /scapy/contrib/chdlc.py: -------------------------------------------------------------------------------- 1 | # http://trac.secdev.org/scapy/ticket/88 2 | 3 | # scapy.contrib.description = Cisco HDLC and SLARP 4 | # scapy.contrib.status = loads 5 | 6 | # This layer is based on information from http://www.nethelp.no/net/cisco-hdlc.txt 7 | 8 | from scapy.packet import * 9 | from scapy.fields import * 10 | from scapy.layers.l2 import * 11 | from scapy.layers.inet import * 12 | from scapy.layers.inet6 import * 13 | 14 | class CHDLC(Packet): 15 | name = "Cisco HDLC" 16 | fields_desc = [ ByteEnumField("address", 0x0f, {0x0f : "unicast", 0x8f :"multicast"}), 17 | ByteField("control", 0), 18 | XShortField("proto", 0x0800)] 19 | 20 | class SLARP(Packet): 21 | name = "SLARP" 22 | fields_desc = [ IntEnumField("type", 2, {0 : "request", 1 : "reply", 2 :"line keepalive"}), 23 | ConditionalField(IPField("address", "192.168.0.1"), 24 | lambda pkt : pkt.type == 0 or pkt.type == 1), 25 | ConditionalField(IPField("mask", "255.255.255.0"), 26 | lambda pkt : pkt.type == 0 or pkt.type == 1), 27 | ConditionalField(XShortField("unused", 0), 28 | lambda pkt : pkt.type == 0 or pkt.type == 1), 29 | ConditionalField(IntField("mysequence", 0), 30 | lambda pkt : pkt.type == 2), 31 | ConditionalField(IntField("yoursequence", 0), 32 | lambda pkt : pkt.type == 2), 33 | ConditionalField(XShortField("reliability", 0xffff), 34 | lambda pkt : pkt.type == 2)] 35 | 36 | bind_layers( CHDLC, Dot3, proto=0x6558) 37 | bind_layers( CHDLC, IP, proto=0x800) 38 | bind_layers( CHDLC, IPv6, proto=0x86dd) 39 | bind_layers( CHDLC, SLARP, proto=0x8035) 40 | bind_layers( CHDLC, STP, proto=0x4242) 41 | 42 | conf.l2types.register(104, CHDLC) 43 | -------------------------------------------------------------------------------- /scapy/contrib/avs.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # http://trac.secdev.org/scapy/ticket/82 4 | 5 | # scapy.contrib.description = AVS WLAN Monitor Header 6 | # scapy.contrib.status = loads 7 | 8 | from scapy.packet import * 9 | from scapy.fields import * 10 | from scapy.layers.dot11 import * 11 | 12 | AVSWLANPhyType = { 0 : "Unknown", 13 | 1 : "FHSS 802.11 '97", 14 | 2 : "DSSS 802.11 '97", 15 | 3 : "IR Baseband", 16 | 4 : "DSSS 802.11b", 17 | 5 : "PBCC 802.11b", 18 | 6 : "OFDM 802.11g", 19 | 7 : "PBCC 802.11g", 20 | 8 : "OFDM 802.11a" } 21 | 22 | AVSWLANEncodingType = { 0 : "Unknown", 23 | 1 : "CCK", 24 | 2 : "PBCC", 25 | 3 : "OFDM"} 26 | 27 | AVSWLANSSIType = { 0 : "None", 28 | 1 : "Normalized RSSI", 29 | 2 : "dBm", 30 | 3 : "Raw RSSI"} 31 | 32 | AVSWLANPreambleType = { 0 : "Unknown", 33 | 1 : "Short", 34 | 2 : "Long" } 35 | 36 | 37 | class AVSWLANHeader(Packet): 38 | """ iwpriv eth1 set_prismhdr 1 """ 39 | name = "AVS WLAN Monitor Header" 40 | fields_desc = [ IntField("version",1), 41 | IntField("len",64), 42 | LongField("mactime",0), 43 | LongField("hosttime",0), 44 | IntEnumField("phytype",0, AVSWLANPhyType), 45 | IntField("channel",0), 46 | IntField("datarate",0), 47 | IntField("antenna",0), 48 | IntField("priority",0), 49 | IntEnumField("ssi_type",0, AVSWLANSSIType), 50 | SignedIntField("ssi_signal",0), 51 | SignedIntField("ssi_noise",0), 52 | IntEnumField("preamble",0, AVSWLANPreambleType), 53 | IntEnumField("encoding",0, AVSWLANEncodingType), 54 | ] 55 | 56 | bind_layers(AVSWLANHeader, Dot11) 57 | 58 | -------------------------------------------------------------------------------- /scapy/error.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Logging subsystem and basic exception class. 8 | """ 9 | 10 | ############################# 11 | ##### Logging subsystem ##### 12 | ############################# 13 | 14 | class Scapy_Exception(Exception): 15 | pass 16 | 17 | import logging,traceback,time 18 | 19 | class ScapyFreqFilter(logging.Filter): 20 | def __init__(self): 21 | logging.Filter.__init__(self) 22 | self.warning_table = {} 23 | def filter(self, record): 24 | from config import conf 25 | wt = conf.warning_threshold 26 | if wt > 0: 27 | stk = traceback.extract_stack() 28 | caller=None 29 | for f,l,n,c in stk: 30 | if n == 'warning': 31 | break 32 | caller = l 33 | tm,nb = self.warning_table.get(caller, (0,0)) 34 | ltm = time.time() 35 | if ltm-tm > wt: 36 | tm = ltm 37 | nb = 0 38 | else: 39 | if nb < 2: 40 | nb += 1 41 | if nb == 2: 42 | record.msg = "more "+record.msg 43 | else: 44 | return 0 45 | self.warning_table[caller] = (tm,nb) 46 | return 1 47 | 48 | log_scapy = logging.getLogger("scapy") 49 | console_handler = logging.StreamHandler() 50 | console_handler.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) 51 | log_scapy.addHandler(console_handler) 52 | log_runtime = logging.getLogger("scapy.runtime") # logs at runtime 53 | log_runtime.addFilter(ScapyFreqFilter()) 54 | log_interactive = logging.getLogger("scapy.interactive") # logs in interactive functions 55 | log_loading = logging.getLogger("scapy.loading") # logs when loading scapy 56 | 57 | 58 | def warning(x): 59 | log_runtime.warning(x) 60 | 61 | -------------------------------------------------------------------------------- /scapy/contrib/carp.py: -------------------------------------------------------------------------------- 1 | 2 | # scapy.contrib.description = CARP 3 | # scapy.contrib.status = loads 4 | 5 | from scapy.packet import * 6 | from scapy.layers.inet import IP 7 | from scapy.fields import BitField, ByteField, XShortField, IntField, XIntField 8 | from scapy.utils import checksum 9 | import struct, hmac, hashlib 10 | 11 | class CARP(Packet): 12 | name = "CARP" 13 | fields_desc = [ BitField("version", 4, 4), 14 | BitField("type", 4, 4), 15 | ByteField("vhid", 1), 16 | ByteField("advskew", 0), 17 | ByteField("authlen", 0), 18 | ByteField("demotion", 0), 19 | ByteField("advbase", 0), 20 | XShortField("chksum", 0), 21 | XIntField("counter1", 0), 22 | XIntField("counter2", 0), 23 | XIntField("hmac1", 0), 24 | XIntField("hmac2", 0), 25 | XIntField("hmac3", 0), 26 | XIntField("hmac4", 0), 27 | XIntField("hmac5", 0) 28 | ] 29 | 30 | def post_build(self, pkt, pay): 31 | if self.chksum == None: 32 | pkt = pkt[:6] + struct.pack("!H", checksum(pkt)) + pkt[8:] 33 | 34 | return pkt 35 | 36 | def build_hmac_sha1(pkt, pw = '\0' * 20, ip4l = [], ip6l = []): 37 | if not pkt.haslayer(CARP): 38 | return None 39 | 40 | p = pkt[CARP] 41 | h = hmac.new(pw, digestmod = hashlib.sha1) 42 | # XXX: this is a dirty hack. it needs to pack version and type into a single 8bit field 43 | h.update('\x21') 44 | # XXX: mac addy if different from special link layer. comes before vhid 45 | h.update(struct.pack('!B', p.vhid)) 46 | 47 | sl = [] 48 | for i in ip4l: 49 | # sort ips from smallest to largest 50 | sl.append(inet_aton(i)) 51 | sl.sort() 52 | 53 | for i in sl: 54 | h.update(i) 55 | 56 | # XXX: do ip6l sorting 57 | 58 | return h.digest() 59 | 60 | """ 61 | XXX: Usually CARP is multicast to 224.0.0.18 but because of virtual setup, it'll 62 | be unicast between nodes. Uncomment the following line for normal use 63 | bind_layers(IP, CARP, proto=112, dst='224.0.0.18') 64 | """ 65 | bind_layers(IP, CARP, proto=112) 66 | -------------------------------------------------------------------------------- /scapy/modules/geoip.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | GeoIP: find out the geographical location of IP addresses 8 | """ 9 | 10 | from scapy.data import KnowledgeBase 11 | from scapy.config import conf 12 | 13 | conf.IPCountry_base = "GeoIPCountry4Scapy.gz" 14 | conf.countryLoc_base = "countryLoc.csv" 15 | conf.gnuplot_world = "world.dat" 16 | 17 | 18 | ########################## 19 | ## IP location database ## 20 | ########################## 21 | 22 | class IPCountryKnowledgeBase(KnowledgeBase): 23 | """ 24 | How to generate the base : 25 | db = [] 26 | for l in open("GeoIPCountryWhois.csv").readlines(): 27 | s,e,c = l.split(",")[2:5] 28 | db.append((int(s[1:-1]),int(e[1:-1]),c[1:-1])) 29 | cPickle.dump(gzip.open("xxx","w"),db) 30 | """ 31 | def lazy_init(self): 32 | self.base = load_object(self.filename) 33 | 34 | 35 | class CountryLocKnowledgeBase(KnowledgeBase): 36 | def lazy_init(self): 37 | f=open(self.filename) 38 | self.base = {} 39 | while 1: 40 | l = f.readline() 41 | if not l: 42 | break 43 | l = l.strip().split(",") 44 | if len(l) != 3: 45 | continue 46 | c,lat,long = l 47 | 48 | self.base[c] = (float(long),float(lat)) 49 | f.close() 50 | 51 | 52 | 53 | @conf.commands.register 54 | def locate_ip(ip): 55 | """Get geographic coordinates from IP using geoip database""" 56 | ip=map(int,ip.split(".")) 57 | ip = ip[3]+(ip[2]<<8L)+(ip[1]<<16L)+(ip[0]<<24L) 58 | 59 | cloc = country_loc_kdb.get_base() 60 | db = IP_country_kdb.get_base() 61 | 62 | d=0 63 | f=len(db)-1 64 | while (f-d) > 1: 65 | guess = (d+f)/2 66 | if ip > db[guess][0]: 67 | d = guess 68 | else: 69 | f = guess 70 | s,e,c = db[guess] 71 | if s <= ip and ip <= e: 72 | return cloc.get(c,None) 73 | 74 | 75 | 76 | 77 | 78 | conf.IP_country_kdb = IPCountryKnowledgeBase(conf.IPCountry_base) 79 | conf.country_loc_kdb = CountryLocKnowledgeBase(conf.countryLoc_base) 80 | -------------------------------------------------------------------------------- /scapy/contrib/vqp.py: -------------------------------------------------------------------------------- 1 | 2 | # http://trac.secdev.org/scapy/ticket/147 3 | 4 | # scapy.contrib.description = VLAN Query Protocol 5 | # scapy.contrib.status = loads 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | from scapy.layers.inet import UDP 10 | 11 | class VQP(Packet): 12 | name = "VQP" 13 | fields_desc = [ 14 | ByteField("const", 1), 15 | ByteEnumField("type", 1, { 16 | 1:"requestPort", 2:"responseVLAN", 17 | 3:"requestReconfirm", 4:"responseReconfirm" 18 | }), 19 | ByteEnumField("errorcodeaction", 0, { 20 | 0:"none",3:"accessDenied", 21 | 4:"shutdownPort", 5:"wrongDomain" 22 | }), 23 | ByteEnumField("unknown", 2, { 24 | 2:"inGoodResponse", 6:"inRequests" 25 | }), 26 | IntField("seq",0), 27 | ] 28 | 29 | class VQPEntry(Packet): 30 | name = "VQPEntry" 31 | fields_desc = [ 32 | IntEnumField("datatype", 0, { 33 | 3073:"clientIPAddress", 3074:"portName", 34 | 3075:"VLANName", 3076:"Domain", 3077:"ethernetPacket", 35 | 3078:"ReqMACAddress", 3079:"unknown", 36 | 3080:"ResMACAddress" 37 | }), 38 | FieldLenField("len", None), 39 | ConditionalField(IPField("datatom", "0.0.0.0"), 40 | lambda p:p.datatype==3073), 41 | ConditionalField(MACField("data", "00:00:00:00:00:00"), 42 | lambda p:p.datatype==3078), 43 | ConditionalField(MACField("data", "00:00:00:00:00:00"), 44 | lambda p:p.datatype==3080), 45 | ConditionalField(StrLenField("data", None, 46 | length_from=lambda p:p.len), 47 | lambda p:p.datatype not in [3073, 3078, 3080]), 48 | ] 49 | def post_build(self, p, pay): 50 | if self.len is None: 51 | l = len(p.data) 52 | p = p[:2]+struct.pack("!H",l)+p[4:] 53 | return p 54 | 55 | bind_layers(UDP, VQP, sport=1589) 56 | bind_layers(UDP, VQP, dport=1589) 57 | bind_layers(VQP, VQPEntry, ) 58 | bind_layers(VQPEntry, VQPEntry, ) 59 | -------------------------------------------------------------------------------- /doc/scapy/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | 9 | # Internal variables. 10 | PAPEROPT_a4 = -D latex_paper_size=a4 11 | PAPEROPT_letter = -D latex_paper_size=letter 12 | ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 13 | 14 | .PHONY: help clean html web pickle htmlhelp latex changes linkcheck 15 | 16 | help: 17 | @echo "Please use \`make ' where is one of" 18 | @echo " html to make standalone HTML files" 19 | @echo " pickle to make pickle files (usable by e.g. sphinx-web)" 20 | @echo " htmlhelp to make HTML files and a HTML help project" 21 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 22 | @echo " changes to make an overview over all changed/added/deprecated items" 23 | @echo " linkcheck to check all external links for integrity" 24 | 25 | clean: 26 | -rm -rf _build/* 27 | 28 | html: 29 | mkdir -p _build/html _build/doctrees 30 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html 31 | @echo 32 | @echo "Build finished. The HTML pages are in _build/html." 33 | 34 | pickle: 35 | mkdir -p _build/pickle _build/doctrees 36 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle 37 | @echo 38 | @echo "Build finished; now you can process the pickle files or run" 39 | @echo " sphinx-web _build/pickle" 40 | @echo "to start the sphinx-web server." 41 | 42 | web: pickle 43 | 44 | htmlhelp: 45 | mkdir -p _build/htmlhelp _build/doctrees 46 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp 47 | @echo 48 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 49 | ".hhp project file in _build/htmlhelp." 50 | 51 | latex: 52 | mkdir -p _build/latex _build/doctrees 53 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex 54 | @echo 55 | @echo "Build finished; the LaTeX files are in _build/latex." 56 | @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ 57 | "run these through (pdf)latex." 58 | 59 | changes: 60 | mkdir -p _build/changes _build/doctrees 61 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes 62 | @echo 63 | @echo "The overview file is in _build/changes." 64 | 65 | linkcheck: 66 | mkdir -p _build/linkcheck _build/doctrees 67 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck 68 | @echo 69 | @echo "Link check complete; look for any errors in the above output " \ 70 | "or in _build/linkcheck/output.txt." 71 | -------------------------------------------------------------------------------- /scapy/layers/llmnr.py: -------------------------------------------------------------------------------- 1 | from scapy.fields import * 2 | from scapy.packet import * 3 | from scapy.layers.inet import UDP 4 | from scapy.layers.dns import DNSQRField, DNSRRField, DNSRRCountField 5 | 6 | """ 7 | LLMNR (Link Local Multicast Node Resolution). 8 | 9 | [RFC 4795] 10 | """ 11 | 12 | ############################################################################# 13 | ### LLMNR (RFC4795) ### 14 | ############################################################################# 15 | # LLMNR is based on the DNS packet format (RFC1035 Section 4) 16 | # RFC also envisions LLMNR over TCP. Like vista, we don't support it -- arno 17 | 18 | _LLMNR_IPv6_mcast_Addr = "FF02:0:0:0:0:0:1:3" 19 | _LLMNR_IPv4_mcast_addr = "224.0.0.252" 20 | 21 | class LLMNRQuery(Packet): 22 | name = "Link Local Multicast Node Resolution - Query" 23 | fields_desc = [ ShortField("id", 0), 24 | BitField("qr", 0, 1), 25 | BitEnumField("opcode", 0, 4, { 0:"QUERY" }), 26 | BitField("c", 0, 1), 27 | BitField("tc", 0, 2), 28 | BitField("z", 0, 4), 29 | BitEnumField("rcode", 0, 4, { 0:"ok" }), 30 | DNSRRCountField("qdcount", None, "qd"), 31 | DNSRRCountField("ancount", None, "an"), 32 | DNSRRCountField("nscount", None, "ns"), 33 | DNSRRCountField("arcount", None, "ar"), 34 | DNSQRField("qd", "qdcount"), 35 | DNSRRField("an", "ancount"), 36 | DNSRRField("ns", "nscount"), 37 | DNSRRField("ar", "arcount",0)] 38 | overload_fields = {UDP: {"sport": 5355, "dport": 5355 }} 39 | def hashret(self): 40 | return struct.pack("!H", self.id) 41 | 42 | class LLMNRResponse(LLMNRQuery): 43 | name = "Link Local Multicast Node Resolution - Response" 44 | qr = 1 45 | def answers(self, other): 46 | return (isinstance(other, LLMNRQuery) and 47 | self.id == other.id and 48 | self.qr == 1 and 49 | other.qr == 0) 50 | 51 | def _llmnr_dispatcher(x, *args, **kargs): 52 | cls = conf.raw_layer 53 | if len(x) >= 3: 54 | if (ord(x[4]) & 0x80): # Response 55 | cls = LLMNRResponse 56 | else: # Query 57 | cls = LLMNRQuery 58 | return cls(x, *args, **kargs) 59 | 60 | bind_bottom_up(UDP, _llmnr_dispatcher, { "dport": 5355 }) 61 | bind_bottom_up(UDP, _llmnr_dispatcher, { "sport": 5355 }) 62 | 63 | # LLMNRQuery(id=RandShort(), qd=DNSQR(qname="vista."))) 64 | 65 | 66 | -------------------------------------------------------------------------------- /scapy/layers/ntp.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | NTP (Network Time Protocol). 8 | """ 9 | 10 | import time 11 | from scapy.packet import * 12 | from scapy.fields import * 13 | from scapy.layers.inet import UDP 14 | 15 | 16 | # seconds between 01-01-1900 and 01-01-1970 17 | _NTP_BASETIME = 2208988800 18 | 19 | class TimeStampField(FixedPointField): 20 | def __init__(self, name, default): 21 | FixedPointField.__init__(self, name, default, 64, 32) 22 | 23 | def i2repr(self, pkt, val): 24 | if val is None: 25 | return "--" 26 | val = self.i2h(pkt,val) 27 | if val < _NTP_BASETIME: 28 | return val 29 | return time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime(val-_NTP_BASETIME)) 30 | 31 | def any2i(self, pkt, val): 32 | if type(val) is str: 33 | return int(time.mktime(time.strptime(val))) + _NTP_BASETIME + 3600 # XXX 34 | return FixedPointField.any2i(self,pkt,val) 35 | 36 | def i2m(self, pkt, val): 37 | if val is None: 38 | val = FixedPointField.any2i(self, pkt, time.time()+_NTP_BASETIME) 39 | return FixedPointField.i2m(self, pkt, val) 40 | 41 | 42 | 43 | class NTP(Packet): 44 | # RFC 1769 45 | name = "NTP" 46 | fields_desc = [ 47 | BitEnumField('leap', 0, 2, 48 | { 0: 'nowarning', 49 | 1: 'longminute', 50 | 2: 'shortminute', 51 | 3: 'notsync'}), 52 | BitField('version', 3, 3), 53 | BitEnumField('mode', 3, 3, 54 | { 0: 'reserved', 55 | 1: 'sym_active', 56 | 2: 'sym_passive', 57 | 3: 'client', 58 | 4: 'server', 59 | 5: 'broadcast', 60 | 6: 'control', 61 | 7: 'private'}), 62 | BitField('stratum', 2, 8), 63 | BitField('poll', 0xa, 8), ### XXX : it's a signed int 64 | BitField('precision', 0, 8), ### XXX : it's a signed int 65 | FixedPointField('delay', 0, size=32, frac_bits=16), 66 | FixedPointField('dispersion', 0, size=32, frac_bits=16), 67 | IPField('id', "127.0.0.1"), 68 | TimeStampField('ref', 0), 69 | TimeStampField('orig', None), # None means current time 70 | TimeStampField('recv', 0), 71 | TimeStampField('sent', None) 72 | ] 73 | def mysummary(self): 74 | return self.sprintf("NTP v%ir,NTP.version%, %NTP.mode%") 75 | 76 | 77 | bind_layers( UDP, NTP, dport=123, sport=123) 78 | -------------------------------------------------------------------------------- /scapy/arch/__init__.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Operating system specific functionality. 8 | """ 9 | 10 | 11 | import sys,os,socket 12 | from scapy.error import * 13 | import scapy.config 14 | 15 | try: 16 | import Gnuplot 17 | GNUPLOT=1 18 | except ImportError: 19 | log_loading.info("Can't import python gnuplot wrapper . Won't be able to plot.") 20 | GNUPLOT=0 21 | 22 | try: 23 | import pyx 24 | PYX=1 25 | except ImportError: 26 | log_loading.info("Can't import PyX. Won't be able to use psdump() or pdfdump().") 27 | PYX=0 28 | 29 | 30 | def str2mac(s): 31 | return ("%02x:"*6)[:-1] % tuple(map(ord, s)) 32 | 33 | 34 | 35 | def get_if_addr(iff): 36 | return socket.inet_ntoa(get_if_raw_addr(iff)) 37 | 38 | def get_if_hwaddr(iff): 39 | addrfamily, mac = get_if_raw_hwaddr(iff) 40 | if addrfamily in [ARPHDR_ETHER,ARPHDR_LOOPBACK]: 41 | return str2mac(mac) 42 | else: 43 | raise Scapy_Exception("Unsupported address family (%i) for interface [%s]" % (addrfamily,iff)) 44 | 45 | 46 | LINUX=sys.platform.startswith("linux") 47 | OPENBSD=sys.platform.startswith("openbsd") 48 | FREEBSD=sys.platform.startswith("freebsd") 49 | NETBSD = sys.platform.startswith("netbsd") 50 | DARWIN=sys.platform.startswith("darwin") 51 | SOLARIS=sys.platform.startswith("sunos") 52 | WINDOWS=sys.platform.startswith("win32") 53 | 54 | X86_64 = not WINDOWS and (os.uname()[4] == 'x86_64') 55 | 56 | 57 | # Next step is to import following architecture specific functions: 58 | # def get_if_raw_hwaddr(iff) 59 | # def get_if_raw_addr(iff): 60 | # def get_if_list(): 61 | # def get_working_if(): 62 | # def attach_filter(s, filter): 63 | # def set_promisc(s,iff,val=1): 64 | # def read_routes(): 65 | # def get_if(iff,cmd): 66 | # def get_if_index(iff): 67 | 68 | 69 | 70 | if LINUX: 71 | from linux import * 72 | if scapy.config.conf.use_pcap or scapy.config.conf.use_dnet: 73 | from pcapdnet import * 74 | if scapy.config.conf.use_nanomsg: 75 | from nanomsg import * 76 | elif OPENBSD or FREEBSD or NETBSD or DARWIN: 77 | from bsd import * 78 | elif SOLARIS: 79 | from solaris import * 80 | elif WINDOWS: 81 | from windows import * 82 | 83 | if scapy.config.conf.iface is None: 84 | scapy.config.conf.iface = LOOPBACK_NAME 85 | 86 | 87 | def get_if_raw_addr6(iff): 88 | """ 89 | Returns the main global unicast address associated with provided 90 | interface, in network format. If no global address is found, None 91 | is returned. 92 | """ 93 | r = filter(lambda x: x[2] == iff and x[1] == IPV6_ADDR_GLOBAL, in6_getifaddr()) 94 | if len(r) == 0: 95 | return None 96 | else: 97 | r = r[0][0] 98 | return inet_pton(socket.AF_INET6, r) 99 | -------------------------------------------------------------------------------- /scapy/layers/rip.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | RIP (Routing Information Protocol). 8 | """ 9 | 10 | from scapy.packet import * 11 | from scapy.fields import * 12 | from scapy.layers.inet import UDP 13 | 14 | class RIP(Packet): 15 | name = "RIP header" 16 | fields_desc = [ 17 | ByteEnumField("cmd", 1, {1:"req", 2:"resp", 3:"traceOn", 4:"traceOff", 18 | 5:"sun", 6:"trigReq", 7:"trigResp", 8:"trigAck", 19 | 9:"updateReq", 10:"updateResp", 11:"updateAck"}), 20 | ByteField("version", 1), 21 | ShortField("null", 0), 22 | ] 23 | 24 | def guess_payload_class(self, payload): 25 | if payload[:2] == "\xff\xff": 26 | return RIPAuth 27 | else: 28 | return Packet.guess_payload_class(self, payload) 29 | 30 | class RIPEntry(RIP): 31 | name = "RIP entry" 32 | fields_desc = [ 33 | ShortEnumField("AF", 2, {2:"IP"}), 34 | ShortField("RouteTag", 0), 35 | IPField("addr", "0.0.0.0"), 36 | IPField("mask", "0.0.0.0"), 37 | IPField("nextHop", "0.0.0.0"), 38 | IntEnumField("metric", 1, {16:"Unreach"}), 39 | ] 40 | 41 | class RIPAuth(Packet): 42 | name = "RIP authentication" 43 | fields_desc = [ 44 | ShortEnumField("AF", 0xffff, {0xffff:"Auth"}), 45 | ShortEnumField("authtype", 2, {1:"md5authdata", 2:"simple", 3:"md5"}), 46 | ConditionalField(StrFixedLenField("password", None, 16), 47 | lambda pkt: pkt.authtype == 2), 48 | ConditionalField(ShortField("digestoffset", 0), 49 | lambda pkt: pkt.authtype == 3), 50 | ConditionalField(ByteField("keyid", 0), 51 | lambda pkt: pkt.authtype == 3), 52 | ConditionalField(ByteField("authdatalen", 0), 53 | lambda pkt: pkt.authtype == 3), 54 | ConditionalField(IntField("seqnum", 0), 55 | lambda pkt: pkt.authtype == 3), 56 | ConditionalField(StrFixedLenField("zeropad", None, 8), 57 | lambda pkt: pkt.authtype == 3), 58 | ConditionalField(StrLenField("authdata", None, 59 | length_from=lambda pkt: pkt.md5datalen), 60 | lambda pkt: pkt.authtype == 1) 61 | ] 62 | 63 | def pre_dissect(self, s): 64 | if s[2:4] == "\x00\x01": 65 | self.md5datalen = len(s) - 4 66 | 67 | return s 68 | 69 | 70 | bind_layers( UDP, RIP, sport=520) 71 | bind_layers( UDP, RIP, dport=520) 72 | bind_layers( RIP, RIPEntry, ) 73 | bind_layers( RIPEntry, RIPEntry, ) 74 | bind_layers( RIPAuth, RIPEntry, ) 75 | -------------------------------------------------------------------------------- /scapy/contrib/ppi_cace.py: -------------------------------------------------------------------------------- 1 | ## This file is (hopefully) part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## 4 | ## This program is published under a GPLv2 license 5 | 6 | # scapy.contrib.description = PPI CACE 7 | # scapy.contrib.status = loads 8 | 9 | """ 10 | CACE PPI types 11 | """ 12 | import logging,struct 13 | from scapy.config import conf 14 | from scapy.packet import * 15 | from scapy.fields import * 16 | from scapy.layers.l2 import Ether 17 | from scapy.layers.dot11 import Dot11 18 | from scapy.contrib.ppi import * 19 | 20 | PPI_DOT11COMMON = 2 21 | PPI_DOT11NMAC = 3 22 | PPI_DOT11NMACPHY = 4 23 | PPI_SPECTRUMMAP = 5 24 | PPI_PROCESSINFO = 6 25 | PPI_CAPTUREINFO = 7 26 | PPI_AGGREGATION = 8 27 | PPI_DOT3 = 9 28 | 29 | # PPI 802.11 Common Field Header Fields 30 | class dBmByteField(Field): 31 | def __init__(self, name, default): 32 | Field.__init__(self, name, default, "b") 33 | def i2repr(self, pkt, val): 34 | if (val != None): 35 | val = "%4d dBm" % val 36 | return val 37 | 38 | class PPITSFTField(LELongField): 39 | def i2h(self, pkt, val): 40 | flags = 0 41 | if (pkt): 42 | flags = pkt.getfieldval("Pkt_Flags") 43 | if not flags: 44 | flags = 0 45 | if (flags & 0x02): 46 | scale = 1e-3 47 | else: 48 | scale = 1e-6 49 | tout = scale * float(val) 50 | return tout 51 | def h2i(self, pkt, val): 52 | scale = 1e6 53 | if pkt: 54 | flags = pkt.getfieldval("Pkt_Flags") 55 | if flags: 56 | if (flags & 0x02): 57 | scale = 1e3 58 | tout = int((scale * val) + 0.5) 59 | return tout 60 | 61 | _PPIDot11CommonChFlags = ['','','','','Turbo','CCK','OFDM','2GHz','5GHz', 62 | 'PassiveOnly','Dynamic CCK-OFDM','GSFK'] 63 | 64 | _PPIDot11CommonPktFlags = ['FCS','TSFT_ms','FCS_Invalid','PHY_Error'] 65 | 66 | # PPI 802.11 Common Field Header 67 | class Dot11Common(Packet): 68 | name = "PPI 802.11-Common" 69 | fields_desc = [ LEShortField('pfh_type',PPI_DOT11COMMON), 70 | LEShortField('pfh_length', 20), 71 | PPITSFTField('TSF_Timer', 0), 72 | FlagsField('Pkt_Flags',0, -16, _PPIDot11CommonPktFlags), 73 | LEShortField('Rate',0), 74 | LEShortField('Ch_Freq',0), 75 | FlagsField('Ch_Flags', 0, -16, _PPIDot11CommonChFlags), 76 | ByteField('FHSS_Hop',0), 77 | ByteField('FHSS_Pat',0), 78 | dBmByteField('Antsignal',-128), 79 | dBmByteField('Antnoise',-128)] 80 | 81 | def extract_padding(self, p): 82 | return "",p 83 | #Hopefully other CACE defined types will be added here. 84 | 85 | #Add the dot11common layer to the PPI array 86 | addPPIType(PPI_DOT11COMMON, Dot11Common) 87 | 88 | -------------------------------------------------------------------------------- /scapy/layers/pflog.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | PFLog: OpenBSD PF packet filter logging. 8 | """ 9 | 10 | from scapy.packet import * 11 | from scapy.fields import * 12 | from scapy.layers.inet import IP 13 | if conf.ipv6_enabled: 14 | from scapy.layers.inet6 import IPv6 15 | from scapy.config import conf 16 | 17 | class PFLog(Packet): 18 | name = "PFLog" 19 | # from OpenBSD src/sys/net/pfvar.h and src/sys/net/if_pflog.h 20 | fields_desc = [ ByteField("hdrlen", 0), 21 | ByteEnumField("addrfamily", 2, {socket.AF_INET: "IPv4", 22 | socket.AF_INET6: "IPv6"}), 23 | ByteEnumField("action", 1, {0: "pass", 1: "drop", 24 | 2: "scrub", 3: "no-scrub", 25 | 4: "nat", 5: "no-nat", 26 | 6: "binat", 7: "no-binat", 27 | 8: "rdr", 9: "no-rdr", 28 | 10: "syn-proxy-drop" }), 29 | ByteEnumField("reason", 0, {0: "match", 1: "bad-offset", 30 | 2: "fragment", 3: "short", 31 | 4: "normalize", 5: "memory", 32 | 6: "bad-timestamp", 33 | 7: "congestion", 34 | 8: "ip-options", 35 | 9: "proto-cksum", 36 | 10: "state-mismatch", 37 | 11: "state-insert", 38 | 12: "state-limit", 39 | 13: "src-limit", 40 | 14: "syn-proxy" }), 41 | StrFixedLenField("iface", "", 16), 42 | StrFixedLenField("ruleset", "", 16), 43 | SignedIntField("rulenumber", 0), 44 | SignedIntField("subrulenumber", 0), 45 | SignedIntField("uid", 0), 46 | IntField("pid", 0), 47 | SignedIntField("ruleuid", 0), 48 | IntField("rulepid", 0), 49 | ByteEnumField("direction", 255, {0: "inout", 1: "in", 50 | 2:"out", 255: "unknown"}), 51 | StrFixedLenField("pad", "\x00\x00\x00", 3 ) ] 52 | def mysummary(self): 53 | return self.sprintf("%PFLog.addrfamily% %PFLog.action% on %PFLog.iface% by rule %PFLog.rulenumber%") 54 | 55 | bind_layers(PFLog, IP, addrfamily=socket.AF_INET) 56 | if conf.ipv6_enabled: 57 | bind_layers(PFLog, IPv6, addrfamily=socket.AF_INET6) 58 | 59 | conf.l2types.register(117, PFLog) 60 | -------------------------------------------------------------------------------- /scapy/contrib/xnt.py: -------------------------------------------------------------------------------- 1 | # eXtensible Network Telemetry 2 | 3 | # scapy.contrib.description = VXLAN 4 | # scapy.contrib.status = loads 5 | 6 | from scapy.packet import * 7 | from scapy.fields import * 8 | from scapy.all import * # Otherwise failing at the UDP reference below 9 | 10 | #PLT data header 11 | class INT_PLT_HDR(Packet): 12 | name = "INT_PLT_data_header" 13 | fields_desc = [ IntField("path_latency_encoding", 0x00000000) ] 14 | 15 | 16 | class VXLAN_GPE_INT(Packet): 17 | name = "VXLAN_GPE_INT_header" 18 | fields_desc = [ XByteField("int_type", 0x01), 19 | XByteField("rsvd", 0x00), 20 | XByteField("length", 0x00), 21 | XByteField("next_proto", 0x03) ] 22 | 23 | #PLT data header for GENEVE 24 | class INT_PLT_HDR_GENEVE(Packet): 25 | name = "INT_PLT_data_header_geneve" 26 | fields_desc = [ IntField("path_latency_encoding", 0x00000000) ] 27 | 28 | class GENEVE_INT(Packet): 29 | name = "GENEVE_INT_header" 30 | fields_desc = [ XShortField("int_opt", 0x0103), 31 | XByteField("int_type", 0x01), 32 | BitField("rsvd", 0 , 3), 33 | BitField("length", 2, 5)] 34 | 35 | class INT_META_HDR(Packet): 36 | name = "INT_metadata_header" 37 | fields_desc = [ BitField("ver", 0, 2), BitField("rep", 0, 2), 38 | BitField("c", 0, 1), BitField("e", 0, 1), 39 | BitField("rsvd1", 0, 5), BitField("ins_cnt", 1, 5), 40 | BitField("max_hop_cnt", 32, 8), 41 | BitField("total_hop_cnt", 0, 8), 42 | ShortField("inst_mask", 0x8000), 43 | ShortField("rsvd2", 0x0000)] 44 | 45 | # INT data header 46 | class INT_hop_info(Packet): 47 | name = "INT_hop_info" 48 | fields_desc = [ BitField("bos", 0, 1), 49 | XBitField("val", 0x7FFFFFFF, 31) ] 50 | 51 | 52 | class INT_L45_HEAD(Packet): 53 | name = "INT_L45_HEAD" 54 | fields_desc = [ XByteField("int_type", 0x01), 55 | XByteField("rsvd0", 0x00), 56 | XByteField("length", 0x00), 57 | XByteField("rsvd1", 0x00) ] 58 | 59 | class INT_L45_TAIL(Packet): 60 | name = "INT_L45_TAIL" 61 | fields_desc = [ XByteField("next_proto", 0x01), 62 | XShortField("proto_param", 0x0000), 63 | XByteField("rsvd", 0x00) ] 64 | 65 | class ICMP_INTL45(ICMP): 66 | name = "ICMP_INTL45" 67 | 68 | # bring back the original packet.py guess_payload_class that is overridden by ICMP 69 | def guess_payload_class(self, payload): 70 | """DEV: Guesses the next payload class from layer bonds. Can be overloaded to use a different mechanism.""" 71 | for t in self.aliastypes: 72 | for fval, cls in t.payload_guess: 73 | ok = 1 74 | for k in fval.keys(): 75 | if not hasattr(self, k) or fval[k] != self.getfieldval(k): 76 | ok = 0 77 | break 78 | if ok: 79 | return cls 80 | return self.default_payload_class(payload) 81 | 82 | class TCP_INTL45(TCP): 83 | name = "TCP_INTL45" 84 | 85 | class UDP_INTL45(UDP): 86 | name = "UDP_INTL45" 87 | -------------------------------------------------------------------------------- /scapy/dadict.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Direct Access dictionary. 8 | """ 9 | 10 | from error import Scapy_Exception 11 | 12 | ############################### 13 | ## Direct Access dictionnary ## 14 | ############################### 15 | 16 | def fixname(x): 17 | if x and x[0] in "0123456789": 18 | x = "n_"+x 19 | return x.translate("________________________________________________0123456789_______ABCDEFGHIJKLMNOPQRSTUVWXYZ______abcdefghijklmnopqrstuvwxyz_____________________________________________________________________________________________________________________________________") 20 | 21 | 22 | class DADict_Exception(Scapy_Exception): 23 | pass 24 | 25 | class DADict: 26 | def __init__(self, _name="DADict", **kargs): 27 | self._name=_name 28 | self.__dict__.update(kargs) 29 | def fixname(self,val): 30 | return fixname(val) 31 | def __contains__(self, val): 32 | return val in self.__dict__ 33 | def __getitem__(self, attr): 34 | return getattr(self, attr) 35 | def __setitem__(self, attr, val): 36 | return setattr(self, self.fixname(attr), val) 37 | def __iter__(self): 38 | return iter(map(lambda (x,y):y,filter(lambda (x,y):x and x[0]!="_", self.__dict__.items()))) 39 | def _show(self): 40 | for k in self.__dict__.keys(): 41 | if k and k[0] != "_": 42 | print "%10s = %r" % (k,getattr(self,k)) 43 | def __repr__(self): 44 | return "<%s/ %s>" % (self._name," ".join(filter(lambda x:x and x[0]!="_",self.__dict__.keys()))) 45 | 46 | def _branch(self, br, uniq=0): 47 | if uniq and br._name in self: 48 | raise DADict_Exception("DADict: [%s] already branched in [%s]" % (br._name, self._name)) 49 | self[br._name] = br 50 | 51 | def _my_find(self, *args, **kargs): 52 | if args and self._name not in args: 53 | return False 54 | for k in kargs: 55 | if k not in self or self[k] != kargs[k]: 56 | return False 57 | return True 58 | 59 | def _find(self, *args, **kargs): 60 | return self._recurs_find((), *args, **kargs) 61 | def _recurs_find(self, path, *args, **kargs): 62 | if self in path: 63 | return None 64 | if self._my_find(*args, **kargs): 65 | return self 66 | for o in self: 67 | if isinstance(o, DADict): 68 | p = o._recurs_find(path+(self,), *args, **kargs) 69 | if p is not None: 70 | return p 71 | return None 72 | def _find_all(self, *args, **kargs): 73 | return self._recurs_find_all((), *args, **kargs) 74 | def _recurs_find_all(self, path, *args, **kargs): 75 | r = [] 76 | if self in path: 77 | return r 78 | if self._my_find(*args, **kargs): 79 | r.append(self) 80 | for o in self: 81 | if isinstance(o, DADict): 82 | p = o._recurs_find_all(path+(self,), *args, **kargs) 83 | r += p 84 | return r 85 | def keys(self): 86 | return filter(lambda x:x and x[0]!="_", self.__dict__.keys()) 87 | 88 | -------------------------------------------------------------------------------- /scapy/tools/check_asdis.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | import getopt 4 | 5 | def usage(): 6 | print >>sys.stderr,"""Usage: check_asdis -i [-o ] 7 | -v increase verbosity 8 | -d hexdiff packets that differ 9 | -z compress output pcap 10 | -a open pcap file in append mode""" 11 | 12 | def main(argv): 13 | PCAP_IN = None 14 | PCAP_OUT = None 15 | COMPRESS=False 16 | APPEND=False 17 | DIFF=False 18 | VERBOSE=0 19 | try: 20 | opts=getopt.getopt(argv, "hi:o:azdv") 21 | for opt, parm in opts[0]: 22 | if opt == "-h": 23 | usage() 24 | raise SystemExit 25 | elif opt == "-i": 26 | PCAP_IN = parm 27 | elif opt == "-o": 28 | PCAP_OUT = parm 29 | elif opt == "-v": 30 | VERBOSE += 1 31 | elif opt == "-d": 32 | DIFF = True 33 | elif opt == "-a": 34 | APPEND = True 35 | elif opt == "-z": 36 | COMPRESS = True 37 | 38 | 39 | if PCAP_IN is None: 40 | raise getopt.GetoptError("Missing pcap file (-i)") 41 | 42 | except getopt.GetoptError,e: 43 | print >>sys.stderr,"ERROR: %s" % e 44 | raise SystemExit 45 | 46 | 47 | 48 | from scapy.config import conf 49 | from scapy.utils import RawPcapReader,RawPcapWriter,hexdiff 50 | from scapy.layers import all 51 | 52 | 53 | pcap = RawPcapReader(PCAP_IN) 54 | pcap_out = None 55 | if PCAP_OUT: 56 | pcap_out = RawPcapWriter(PCAP_OUT, append=APPEND, gz=COMPRESS, linktype=pcap.linktype) 57 | pcap_out._write_header(None) 58 | 59 | LLcls = conf.l2types.get(pcap.linktype) 60 | if LLcls is None: 61 | print >>sys.stderr," Unknown link type [%i]. Can't test anything!" % pcap.linktype 62 | raise SystemExit 63 | 64 | 65 | i=-1 66 | differ=0 67 | failed=0 68 | for p1,meta in pcap: 69 | i += 1 70 | try: 71 | p2d = LLcls(p1) 72 | p2 = str(p2d) 73 | except KeyboardInterrupt: 74 | raise 75 | except Exception,e: 76 | print "Dissection error on packet %i" % i 77 | failed += 1 78 | else: 79 | if p1 == p2: 80 | if VERBOSE >= 2: 81 | print "Packet %i ok" % i 82 | continue 83 | else: 84 | print "Packet %i differs" % i 85 | differ += 1 86 | if VERBOSE >= 1: 87 | print repr(p2d) 88 | if DIFF: 89 | hexdiff(p1,p2) 90 | if pcap_out is not None: 91 | pcap_out.write(p1) 92 | i+=1 93 | correct = i-differ-failed 94 | print "%i total packets. %i ok, %i differed, %i failed. %.2f%% correct." % (i, correct, differ, 95 | failed, i and 100.0*(correct)/i) 96 | 97 | 98 | if __name__ == "__main__": 99 | import sys 100 | try: 101 | main(sys.argv[1:]) 102 | except KeyboardInterrupt: 103 | print >>sys.stderr,"Interrupted by user." 104 | -------------------------------------------------------------------------------- /scapy/contrib/ppi.py: -------------------------------------------------------------------------------- 1 | ## This file is (hopefully) part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## 4 | ## This program is published under a GPLv2 license 5 | 6 | # scapy.contrib.description = PPI 7 | # scapy.contrib.status = loads 8 | 9 | 10 | """ 11 | PPI (Per-Packet Information). 12 | """ 13 | import logging,struct 14 | from scapy.config import conf 15 | from scapy.packet import * 16 | from scapy.fields import * 17 | from scapy.layers.l2 import Ether 18 | from scapy.layers.dot11 import Dot11 19 | 20 | # Dictionary to map the TLV type to the class name of a sub-packet 21 | _ppi_types = {} 22 | def addPPIType(id, value): 23 | _ppi_types[id] = value 24 | def getPPIType(id, default="default"): 25 | return _ppi_types.get(id, _ppi_types.get(default, None)) 26 | 27 | 28 | # Default PPI Field Header 29 | class PPIGenericFldHdr(Packet): 30 | name = "PPI Field Header" 31 | fields_desc = [ LEShortField('pfh_type', 0), 32 | FieldLenField('pfh_length', None, length_of="value", fmt='= 4: 47 | t,pfh_len = struct.unpack(" pfh_len): 56 | out.payload.payload = conf.padding_layer(p[pfh_len:]) 57 | elif (len(p) > pfh_len): 58 | out.payload = conf.padding_layer(p[pfh_len:]) 59 | 60 | else: 61 | out = conf.raw_layer(p, **kargs) 62 | return out 63 | 64 | 65 | 66 | 67 | class PPI(Packet): 68 | name = "PPI Packet Header" 69 | fields_desc = [ ByteField('pph_version', 0), 70 | ByteField('pph_flags', 0), 71 | FieldLenField('pph_len', None, length_of="PPIFieldHeaders", fmt=" 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Clone of queso OS fingerprinting 8 | """ 9 | 10 | from scapy.data import KnowledgeBase 11 | from scapy.config import conf 12 | from scapy.layers.inet import IP,TCP 13 | #from 14 | 15 | conf.queso_base ="/etc/queso.conf" 16 | 17 | 18 | ################# 19 | ## Queso stuff ## 20 | ################# 21 | 22 | 23 | def quesoTCPflags(flags): 24 | if flags == "-": 25 | return "-" 26 | flv = "FSRPAUXY" 27 | v = 0 28 | for i in flags: 29 | v |= 2**flv.index(i) 30 | return "%x" % v 31 | 32 | class QuesoKnowledgeBase(KnowledgeBase): 33 | def lazy_init(self): 34 | try: 35 | f = open(self.filename) 36 | except IOError: 37 | return 38 | self.base = {} 39 | p = None 40 | try: 41 | for l in f: 42 | l = l.strip() 43 | if not l or l[0] == ';': 44 | continue 45 | if l[0] == '*': 46 | if p is not None: 47 | p[""] = name 48 | name = l[1:].strip() 49 | p = self.base 50 | continue 51 | if l[0] not in list("0123456"): 52 | continue 53 | res = l[2:].split() 54 | res[-1] = quesoTCPflags(res[-1]) 55 | res = " ".join(res) 56 | if not p.has_key(res): 57 | p[res] = {} 58 | p = p[res] 59 | if p is not None: 60 | p[""] = name 61 | except: 62 | self.base = None 63 | warning("Can't load queso base [%s]", self.filename) 64 | f.close() 65 | 66 | 67 | queso_kdb = QuesoKnowledgeBase(conf.queso_base) 68 | 69 | 70 | def queso_sig(target, dport=80, timeout=3): 71 | p = queso_kdb.get_base() 72 | ret = [] 73 | for flags in ["S", "SA", "F", "FA", "SF", "P", "SEC"]: 74 | ans, unans = sr(IP(dst=target)/TCP(dport=dport,flags=flags,seq=RandInt()), 75 | timeout=timeout, verbose=0) 76 | if len(ans) == 0: 77 | rs = "- - - -" 78 | else: 79 | s,r = ans[0] 80 | rs = "%i" % (r.seq != 0) 81 | if not r.ack: 82 | r += " 0" 83 | elif r.ack-s.seq > 666: 84 | rs += " R" % 0 85 | else: 86 | rs += " +%i" % (r.ack-s.seq) 87 | rs += " %X" % r.window 88 | rs += " %x" % r.payload.flags 89 | ret.append(rs) 90 | return ret 91 | 92 | def queso_search(sig): 93 | p = queso_kdb.get_base() 94 | sig.reverse() 95 | ret = [] 96 | try: 97 | while sig: 98 | s = sig.pop() 99 | p = p[s] 100 | if p.has_key(""): 101 | ret.append(p[""]) 102 | except KeyError: 103 | pass 104 | return ret 105 | 106 | 107 | @conf.commands.register 108 | def queso(*args,**kargs): 109 | """Queso OS fingerprinting 110 | queso(target, dport=80, timeout=3)""" 111 | return queso_search(queso_sig(*args, **kargs)) 112 | 113 | 114 | -------------------------------------------------------------------------------- /scapy/layers/radius.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | RADIUS (Remote Authentication Dial In User Service) 8 | """ 9 | 10 | import struct 11 | from scapy.packet import * 12 | from scapy.fields import * 13 | 14 | class Radius(Packet): 15 | name = "Radius" 16 | fields_desc = [ ByteEnumField("code", 1, {1: "Access-Request", 17 | 2: "Access-Accept", 18 | 3: "Access-Reject", 19 | 4: "Accounting-Request", 20 | 5: "Accounting-Accept", 21 | 6: "Accounting-Status", 22 | 7: "Password-Request", 23 | 8: "Password-Ack", 24 | 9: "Password-Reject", 25 | 10: "Accounting-Message", 26 | 11: "Access-Challenge", 27 | 12: "Status-Server", 28 | 13: "Status-Client", 29 | 21: "Resource-Free-Request", 30 | 22: "Resource-Free-Response", 31 | 23: "Resource-Query-Request", 32 | 24: "Resource-Query-Response", 33 | 25: "Alternate-Resource-Reclaim-Request", 34 | 26: "NAS-Reboot-Request", 35 | 27: "NAS-Reboot-Response", 36 | 29: "Next-Passcode", 37 | 30: "New-Pin", 38 | 31: "Terminate-Session", 39 | 32: "Password-Expired", 40 | 33: "Event-Request", 41 | 34: "Event-Response", 42 | 40: "Disconnect-Request", 43 | 41: "Disconnect-ACK", 44 | 42: "Disconnect-NAK", 45 | 43: "CoA-Request", 46 | 44: "CoA-ACK", 47 | 45: "CoA-NAK", 48 | 50: "IP-Address-Allocate", 49 | 51: "IP-Address-Release", 50 | 253: "Experimental-use", 51 | 254: "Reserved", 52 | 255: "Reserved"} ), 53 | ByteField("id", 0), 54 | ShortField("len", None), 55 | StrFixedLenField("authenticator","",16) ] 56 | def post_build(self, p, pay): 57 | p += pay 58 | l = self.len 59 | if l is None: 60 | l = len(p) 61 | p = p[:2]+struct.pack("!H",l)+p[4:] 62 | return p 63 | 64 | 65 | 66 | -------------------------------------------------------------------------------- /doc/scapy/troubleshooting.rst: -------------------------------------------------------------------------------- 1 | *************** 2 | Troubleshooting 3 | *************** 4 | 5 | FAQ 6 | === 7 | 8 | My TCP connections are reset by Scapy or by my kernel. 9 | ------------------------------------------------------ 10 | The kernel is not aware of what Scapy is doing behind his back. If Scapy sends a SYN, the target replies with a SYN-ACK and your kernel sees it, it will reply with a RST. To prevent this, use local firewall rules (e.g. NetFilter for Linux). Scapy does not mind about local firewalls. 11 | 12 | I can't ping 127.0.0.1. Scapy does not work with 127.0.0.1 or on the loopback interface 13 | --------------------------------------------------------------------------------------- 14 | 15 | The loopback interface is a very special interface. Packets going through it are not really assembled and dissassembled. The kernel routes the packet to its destination while it is still stored an internal structure. What you see with tcpdump -i lo is only a fake to make you think everything is normal. The kernel is not aware of what Scapy is doing behind his back, so what you see on the loopback interface is also a fake. Except this one did not come from a local structure. Thus the kernel will never receive it. 16 | 17 | In order to speak to local applications, you need to build your packets one layer upper, using a PF_INET/SOCK_RAW socket instead of a PF_PACKET/SOCK_RAW (or its equivalent on other systems that Linux):: 18 | 19 | >>> conf.L3socket 20 | 21 | >>> conf.L3socket=L3RawSocket 22 | >>> sr1(IP(dst="127.0.0.1")/ICMP()) 23 | > 24 | 25 | BPF filters do not work. I'm on a ppp link 26 | ------------------------------------------ 27 | 28 | This is a known bug. BPF filters must compiled with different offsets on ppp links. It may work if you use libpcap (which will be used to compile the BPF filter) instead of using native linux support (PF_PACKET sockets). 29 | 30 | traceroute() does not work. I'm on a ppp link 31 | --------------------------------------------- 32 | 33 | This is a known bug. See BPF filters do not work. I'm on a ppp link 34 | 35 | To work arround this, use ``nofilter=1``:: 36 | 37 | >>> traceroute("target", nofilter=1) 38 | 39 | 40 | Graphs are ugly/fonts are too big/image is truncated. 41 | ----------------------------------------------------- 42 | 43 | Quick fix: use png format:: 44 | 45 | >>> x.graph(format="png") 46 | 47 | Upgrade to latest version of GraphViz. 48 | 49 | Try providing different DPI options (50,70,75,96,101,125, for instance):: 50 | 51 | >>> x.graph(options="-Gdpi=70") 52 | 53 | If it works, you can make it permanenent:: 54 | 55 | >>> conf.prog.dot = "dot -Gdpi=70" 56 | 57 | You can also put this line in your ``~/.scapy_startup.py`` file 58 | 59 | 60 | Getting help 61 | ============ 62 | 63 | Common problems are answered in the FAQ. 64 | 65 | There's a low traffic mailing list at ``scapy.ml(at)secdev.org`` (`archive `_, `RSS, NNTP `_). You are encouraged to send questions, bug reports, suggestions, ideas, cool usages of Scapy, etc. to this list. Subscribe by sending a mail to ``scapy.ml-subscribe(at)secdev.org``. 66 | 67 | 68 | 69 | To avoid spam, you must subscribe to the mailing list to post. -------------------------------------------------------------------------------- /scapy/layers/x509.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | X.509 certificates. 8 | """ 9 | 10 | from scapy.asn1packet import * 11 | from scapy.asn1fields import * 12 | 13 | ########## 14 | ## X509 ## 15 | ########## 16 | 17 | ######[ ASN1 class ]###### 18 | 19 | class ASN1_Class_X509(ASN1_Class_UNIVERSAL): 20 | name="X509" 21 | CONT0 = 0xa0 22 | CONT1 = 0xa1 23 | CONT2 = 0xa2 24 | CONT3 = 0xa3 25 | 26 | class ASN1_X509_CONT0(ASN1_SEQUENCE): 27 | tag = ASN1_Class_X509.CONT0 28 | 29 | class ASN1_X509_CONT1(ASN1_SEQUENCE): 30 | tag = ASN1_Class_X509.CONT1 31 | 32 | class ASN1_X509_CONT2(ASN1_SEQUENCE): 33 | tag = ASN1_Class_X509.CONT2 34 | 35 | class ASN1_X509_CONT3(ASN1_SEQUENCE): 36 | tag = ASN1_Class_X509.CONT3 37 | 38 | ######[ BER codecs ]####### 39 | 40 | class BERcodec_X509_CONT0(BERcodec_SEQUENCE): 41 | tag = ASN1_Class_X509.CONT0 42 | 43 | class BERcodec_X509_CONT1(BERcodec_SEQUENCE): 44 | tag = ASN1_Class_X509.CONT1 45 | 46 | class BERcodec_X509_CONT2(BERcodec_SEQUENCE): 47 | tag = ASN1_Class_X509.CONT2 48 | 49 | class BERcodec_X509_CONT3(BERcodec_SEQUENCE): 50 | tag = ASN1_Class_X509.CONT3 51 | 52 | ######[ ASN1 fields ]###### 53 | 54 | class ASN1F_X509_CONT0(ASN1F_SEQUENCE): 55 | ASN1_tag = ASN1_Class_X509.CONT0 56 | 57 | class ASN1F_X509_CONT1(ASN1F_SEQUENCE): 58 | ASN1_tag = ASN1_Class_X509.CONT1 59 | 60 | class ASN1F_X509_CONT2(ASN1F_SEQUENCE): 61 | ASN1_tag = ASN1_Class_X509.CONT2 62 | 63 | class ASN1F_X509_CONT3(ASN1F_SEQUENCE): 64 | ASN1_tag = ASN1_Class_X509.CONT3 65 | 66 | ######[ X509 packets ]###### 67 | 68 | class X509RDN(ASN1_Packet): 69 | ASN1_codec = ASN1_Codecs.BER 70 | ASN1_root = ASN1F_SET( 71 | ASN1F_SEQUENCE( ASN1F_OID("oid","2.5.4.6"), 72 | ASN1F_PRINTABLE_STRING("value","") 73 | ) 74 | ) 75 | 76 | class X509v3Ext(ASN1_Packet): 77 | ASN1_codec = ASN1_Codecs.BER 78 | ASN1_root = ASN1F_field("val",ASN1_NULL(0)) 79 | 80 | 81 | class X509Cert(ASN1_Packet): 82 | ASN1_codec = ASN1_Codecs.BER 83 | ASN1_root = ASN1F_SEQUENCE( 84 | ASN1F_SEQUENCE( 85 | ASN1F_optionnal(ASN1F_X509_CONT0(ASN1F_INTEGER("version",3))), 86 | ASN1F_INTEGER("sn",1), 87 | ASN1F_SEQUENCE(ASN1F_OID("sign_algo","1.2.840.113549.1.1.5"), 88 | ASN1F_field("sa_value",ASN1_NULL(0))), 89 | ASN1F_SEQUENCE_OF("issuer",[],X509RDN), 90 | ASN1F_SEQUENCE(ASN1F_UTC_TIME("not_before",ZuluTime(-600)), # ten minutes ago 91 | ASN1F_UTC_TIME("not_after",ZuluTime(+86400))), # for 24h 92 | ASN1F_SEQUENCE_OF("subject",[],X509RDN), 93 | ASN1F_SEQUENCE( 94 | ASN1F_SEQUENCE(ASN1F_OID("pubkey_algo","1.2.840.113549.1.1.1"), 95 | ASN1F_field("pk_value",ASN1_NULL(0))), 96 | ASN1F_BIT_STRING("pubkey","") 97 | ), 98 | ASN1F_optionnal(ASN1F_X509_CONT3(ASN1F_SEQUENCE_OF("x509v3ext",[],X509v3Ext))), 99 | 100 | ), 101 | ASN1F_SEQUENCE(ASN1F_OID("sign_algo2","1.2.840.113549.1.1.5"), 102 | ASN1F_field("sa2_value",ASN1_NULL(0))), 103 | ASN1F_BIT_STRING("signature","") 104 | ) 105 | 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /scapy/pton_ntop.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Convert IPv6 addresses between textual representation and binary. 8 | 9 | These functions are missing when python is compiled 10 | without IPv6 support, on Windows for instance. 11 | """ 12 | 13 | import socket,struct 14 | 15 | def inet_pton(af, addr): 16 | """Convert an IP address from text representation into binary form""" 17 | if af == socket.AF_INET: 18 | return inet_aton(addr) 19 | elif af == socket.AF_INET6: 20 | # IPv6: The use of "::" indicates one or more groups of 16 bits of zeros. 21 | # We deal with this form of wildcard using a special marker. 22 | JOKER = "*" 23 | while "::" in addr: 24 | addr = addr.replace("::", ":" + JOKER + ":") 25 | joker_pos = None 26 | 27 | # The last part of an IPv6 address can be an IPv4 address 28 | ipv4_addr = None 29 | if "." in addr: 30 | ipv4_addr = addr.split(":")[-1] 31 | 32 | result = "" 33 | parts = addr.split(":") 34 | for part in parts: 35 | if part == JOKER: 36 | # Wildcard is only allowed once 37 | if joker_pos is None: 38 | joker_pos = len(result) 39 | else: 40 | raise Exception("Illegal syntax for IP address") 41 | elif part == ipv4_addr: # FIXME: Make sure IPv4 can only be last part 42 | # FIXME: inet_aton allows IPv4 addresses with less than 4 octets 43 | result += socket.inet_aton(ipv4_addr) 44 | else: 45 | # Each part must be 16bit. Add missing zeroes before decoding. 46 | try: 47 | result += part.rjust(4, "0").decode("hex") 48 | except TypeError: 49 | raise Exception("Illegal syntax for IP address") 50 | 51 | # If there's a wildcard, fill up with zeros to reach 128bit (16 bytes) 52 | if JOKER in addr: 53 | result = (result[:joker_pos] + "\x00" * (16 - len(result)) 54 | + result[joker_pos:]) 55 | 56 | if len(result) != 16: 57 | raise Exception("Illegal syntax for IP address") 58 | return result 59 | else: 60 | raise Exception("Address family not supported") 61 | 62 | 63 | def inet_ntop(af, addr): 64 | """Convert an IP address from binary form into text represenation""" 65 | if af == socket.AF_INET: 66 | return inet_ntoa(addr) 67 | elif af == socket.AF_INET6: 68 | # IPv6 addresses have 128bits (16 bytes) 69 | if len(addr) != 16: 70 | raise Exception("Illegal syntax for IP address") 71 | parts = [] 72 | for left in [0, 2, 4, 6, 8, 10, 12, 14]: 73 | try: 74 | value = struct.unpack("!H", addr[left:left+2])[0] 75 | hexstr = hex(value)[2:] 76 | except TypeError: 77 | raise Exception("Illegal syntax for IP address") 78 | parts.append(hexstr.lstrip("0").lower()) 79 | result = ":".join(parts) 80 | while ":::" in result: 81 | result = result.replace(":::", "::") 82 | # Leaving out leading and trailing zeros is only allowed with :: 83 | if result.endswith(":") and not result.endswith("::"): 84 | result = result + "0" 85 | if result.startswith(":") and not result.startswith("::"): 86 | result = "0" + result 87 | return result 88 | else: 89 | raise Exception("Address family not supported yet") 90 | -------------------------------------------------------------------------------- /scapy/as_resolvers.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Resolve Autonomous Systems (AS). 8 | """ 9 | 10 | 11 | import socket 12 | from config import conf 13 | 14 | class AS_resolver: 15 | server = None 16 | options = "-k" 17 | def __init__(self, server=None, port=43, options=None): 18 | if server is not None: 19 | self.server = server 20 | self.port = port 21 | if options is not None: 22 | self.options = options 23 | 24 | def _start(self): 25 | self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 26 | self.s.connect((self.server,self.port)) 27 | if self.options: 28 | self.s.send(self.options+"\n") 29 | self.s.recv(8192) 30 | def _stop(self): 31 | self.s.close() 32 | 33 | def _parse_whois(self, txt): 34 | asn,desc = None,"" 35 | for l in txt.splitlines(): 36 | if not asn and l.startswith("origin:"): 37 | asn = l[7:].strip() 38 | if l.startswith("descr:"): 39 | if desc: 40 | desc += r"\n" 41 | desc += l[6:].strip() 42 | if asn is not None and desc: 43 | break 44 | return asn,desc.strip() 45 | 46 | def _resolve_one(self, ip): 47 | self.s.send("%s\n" % ip) 48 | x = "" 49 | while not ("%" in x or "source" in x): 50 | x += self.s.recv(8192) 51 | asn, desc = self._parse_whois(x) 52 | return ip,asn,desc 53 | def resolve(self, *ips): 54 | self._start() 55 | ret = [] 56 | for ip in ips: 57 | ip,asn,desc = self._resolve_one(ip) 58 | if asn is not None: 59 | ret.append((ip,asn,desc)) 60 | self._stop() 61 | return ret 62 | 63 | class AS_resolver_riswhois(AS_resolver): 64 | server = "riswhois.ripe.net" 65 | options = "-k -M -1" 66 | 67 | 68 | class AS_resolver_radb(AS_resolver): 69 | server = "whois.ra.net" 70 | options = "-k -M" 71 | 72 | 73 | class AS_resolver_cymru(AS_resolver): 74 | server = "whois.cymru.com" 75 | options = None 76 | def resolve(self, *ips): 77 | ASNlist = [] 78 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 79 | s.connect((self.server,self.port)) 80 | s.send("begin\r\n"+"\r\n".join(ips)+"\r\nend\r\n") 81 | r = "" 82 | while 1: 83 | l = s.recv(8192) 84 | if l == "": 85 | break 86 | r += l 87 | s.close() 88 | for l in r.splitlines()[1:]: 89 | if "|" not in l: 90 | continue 91 | asn,ip,desc = map(str.strip, l.split("|")) 92 | if asn == "NA": 93 | continue 94 | asn = int(asn) 95 | ASNlist.append((ip,asn,desc)) 96 | return ASNlist 97 | 98 | class AS_resolver_multi(AS_resolver): 99 | resolvers_list = ( AS_resolver_cymru(),AS_resolver_riswhois(),AS_resolver_radb() ) 100 | def __init__(self, *reslist): 101 | if reslist: 102 | self.resolvers_list = reslist 103 | def resolve(self, *ips): 104 | todo = ips 105 | ret = [] 106 | for ASres in self.resolvers_list: 107 | res = ASres.resolve(*todo) 108 | resolved = [ ip for ip,asn,desc in res ] 109 | todo = [ ip for ip in todo if ip not in resolved ] 110 | ret += res 111 | return ret 112 | 113 | 114 | conf.AS_resolver = AS_resolver_multi() 115 | -------------------------------------------------------------------------------- /doc/scapy/extending.rst: -------------------------------------------------------------------------------- 1 | ******************** 2 | Build your own tools 3 | ******************** 4 | 5 | You can use Scapy to make your own automated tools. You can also extend Scapy without having to edit its source file. 6 | 7 | If you have built some interesting tools, please contribute back to the mailing-list! 8 | 9 | 10 | Using Scapy in your tools 11 | ========================= 12 | You can easily use Scapy in your own tools. Just import what you need and do it. 13 | 14 | This first example take an IP or a name as first parameter, send an ICMP echo request packet and display the completely dissected return packet:: 15 | 16 | #! /usr/bin/env python 17 | 18 | import sys 19 | from scapy.all import sr1,IP,ICMP 20 | 21 | p=sr1(IP(dst=sys.argv[1])/ICMP()) 22 | if p: 23 | p.show() 24 | 25 | This is a more complex example which does an ARP ping and reports what it found with LaTeX formating:: 26 | 27 | #! /usr/bin/env python 28 | # arping2tex : arpings a network and outputs a LaTeX table as a result 29 | 30 | import sys 31 | if len(sys.argv) != 2: 32 | print "Usage: arping2tex \n eg: arping2tex 192.168.1.0/24" 33 | sys.exit(1) 34 | 35 | from scapy.all import srp,Ether,ARP,conf 36 | conf.verb=0 37 | ans,unans=srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=sys.argv[1]), 38 | timeout=2) 39 | 40 | print r"\begin{tabular}{|l|l|}" 41 | print r"\hline" 42 | print r"MAC & IP\\" 43 | print r"\hline" 44 | for snd,rcv in ans: 45 | print rcv.sprintf(r"%Ether.src% & %ARP.psrc%\\") 46 | print r"\hline" 47 | print r"\end{tabular}" 48 | 49 | Here is another tool that will constantly monitor all interfaces on a machine and print all ARP request it sees, even on 802.11 frames from a Wi-Fi card in monitor mode. Note the store=0 parameter to sniff() to avoid storing all packets in memory for nothing:: 50 | 51 | #! /usr/bin/env python 52 | from scapy.all import * 53 | 54 | def arp_monitor_callback(pkt): 55 | if ARP in pkt and pkt[ARP].op in (1,2): #who-has or is-at 56 | return pkt.sprintf("%ARP.hwsrc% %ARP.psrc%") 57 | 58 | sniff(prn=arp_monitor_callback, filter="arp", store=0) 59 | 60 | For a real life example, you can check `Wifitap `_. 61 | 62 | 63 | Extending Scapy with add-ons 64 | ============================ 65 | 66 | If you need to add some new protocols, new functions, anything, you can write it directly into Scapy source file. But this is not very convenient. Even if those modifications are to be integrated into Scapy, it can be more convenient to write them in a separate file. 67 | 68 | Once you've done that, you can launch Scapy and import your file, but this is still not very convenient. Another way to do that is to make your file executable and have it call the Scapy function named interact():: 69 | 70 | #! /usr/bin/env python 71 | 72 | # Set log level to benefit from Scapy warnings 73 | import logging 74 | logging.getLogger("scapy").setLevel(1) 75 | 76 | from scapy.all import * 77 | 78 | class Test(Packet): 79 | name = "Test packet" 80 | fields_desc = [ ShortField("test1", 1), 81 | ShortField("test2", 2) ] 82 | 83 | def make_test(x,y): 84 | return Ether()/IP()/Test(test1=x,test2=y) 85 | 86 | if __name__ == "__main__": 87 | interact(mydict=globals(), mybanner="Test add-on v3.14") 88 | 89 | 90 | If you put the above listing in the test_interact.py file and make it executable, you'll get:: 91 | 92 | # ./test_interact.py 93 | Welcome to Scapy (0.9.17.109beta) 94 | Test add-on v3.14 95 | >>> make_test(42,666) 96 | >> 97 | 98 | 99 | -------------------------------------------------------------------------------- /scapy/arch/nanomsg.py: -------------------------------------------------------------------------------- 1 | """ 2 | Packet sending and receiving with nanomsg 3 | """ 4 | 5 | import threading 6 | from scapy.config import conf 7 | import struct 8 | import time 9 | 10 | while conf.use_nanomsg: 11 | 12 | try: 13 | import nnpy 14 | except ImportError: 15 | conf.use_nanomsg = False 16 | continue 17 | 18 | class NNSocket: 19 | MSG_TYPE_PACKET_IN = 3 20 | MSG_TYPE_PACKET_OUT = 4 21 | 22 | lock = threading.Lock() 23 | nn_sockets = {} 24 | nn_sockets_cnt = {} 25 | 26 | def __init__(self, addr): 27 | self.addr = addr 28 | self.socket = nnpy.Socket(nnpy.AF_SP, nnpy.PAIR) 29 | self.socket.connect(addr) 30 | 31 | def fileno(self): 32 | return self.socket.getsockopt(nnpy.SOL_SOCKET, nnpy.RCVFD) 33 | 34 | def recv(self): 35 | msg = self.socket.recv() 36 | fmt = " 4 | ## This program is published under a GPLv2 license 5 | 6 | from pipetool import Source,Drain,Sink 7 | from config import conf 8 | 9 | 10 | class SniffSource(Source): 11 | """Read packets from an interface and send them to low exit. 12 | +-----------+ 13 | >>-| |->> 14 | | | 15 | >-| [iface]--|-> 16 | +-----------+ 17 | """ 18 | def __init__(self, iface=None, filter=None, name=None): 19 | Source.__init__(self, name=name) 20 | self.iface = iface 21 | self.filter = filter 22 | def start(self): 23 | self.s = conf.L2listen(iface=self.iface, filter=self.filter) 24 | def stop(self): 25 | self.s.close() 26 | def fileno(self): 27 | return self.s.fileno() 28 | def deliver(self): 29 | self._send(self.s.recv()) 30 | 31 | class RdpcapSource(Source): 32 | """Read packets from a PCAP file send them to low exit. 33 | +----------+ 34 | >>-| |->> 35 | | | 36 | >-| [pcap]--|-> 37 | +----------+ 38 | """ 39 | def __init__(self, fname, name=None): 40 | Source.__init__(self, name=name) 41 | self.fname = fname 42 | self.f = PcapReader(self.fname) 43 | def start(self): 44 | print "start" 45 | self.f = PcapReader(self.fname) 46 | self.is_exhausted = False 47 | def stop(self): 48 | print "stop" 49 | self.f.close() 50 | def fileno(self): 51 | return self.f.fileno() 52 | def deliver(self): 53 | p = self.f.recv() 54 | print "deliver %r" % p 55 | if p is None: 56 | self.is_exhausted = True 57 | else: 58 | self._send(p) 59 | 60 | 61 | class InjectSink(Sink): 62 | """Packets received on low input are injected to an interface 63 | +-----------+ 64 | >>-| |->> 65 | | | 66 | >-|--[iface] |-> 67 | +-----------+ 68 | """ 69 | def __init__(self, iface=None, name=None): 70 | Sink.__init__(self, name=name) 71 | if iface == None: 72 | iface = conf.iface 73 | self.iface = iface 74 | def start(self): 75 | self.s = conf.L2socket(iface=self.iface) 76 | def stop(self): 77 | self.s.close() 78 | def push(self, msg): 79 | self.s.send(msg) 80 | 81 | class Inject3Sink(InjectSink): 82 | def start(self): 83 | self.s = conf.L3socket(iface=self.iface) 84 | 85 | 86 | class WrpcapSink(Sink): 87 | """Packets received on low input are written to PCA file 88 | +----------+ 89 | >>-| |->> 90 | | | 91 | >-|--[pcap] |-> 92 | +----------+ 93 | """ 94 | def __init__(self, fname, name=None): 95 | Sink.__init__(self, name=name) 96 | self.f = PcapWriter(fname) 97 | def stop(self): 98 | self.f.flush() 99 | def push(self, msg): 100 | self.f.write(msg) 101 | 102 | 103 | class UDPDrain(Drain): 104 | """Apply a function to messages on low and high entry 105 | +-------------+ 106 | >>-|--[payload]--|->> 107 | | X | 108 | >-|----[UDP]----|-> 109 | +-------------+ 110 | """ 111 | def __init__(self, ip="127.0.0.1", port=1234): 112 | Drain.__init__(self) 113 | self.ip = ip 114 | self.port = port 115 | 116 | def push(self, msg): 117 | if IP in msg and msg[IP].proto == 17 and UDP in msg: 118 | payload = msg[UDP].payload 119 | self._high_send(str(payload)) 120 | def high_push(self, msg): 121 | p = IP(dst=self.ip)/UDP(sport=1234,dport=self.port)/msg 122 | self._send(p) 123 | 124 | -------------------------------------------------------------------------------- /scapy/contrib/ubberlogger.py: -------------------------------------------------------------------------------- 1 | # Author: Sylvain SARMEJEANNE 2 | # http://trac.secdev.org/scapy/ticket/1 3 | 4 | # scapy.contrib.description = Ubberlogger dissectors 5 | # scapy.contrib.status = untested 6 | 7 | from scapy.packet import * 8 | from scapy.fields import * 9 | 10 | # Syscalls known by Uberlogger 11 | uberlogger_sys_calls = {0:"READ_ID", 12 | 1:"OPEN_ID", 13 | 2:"WRITE_ID", 14 | 3:"CHMOD_ID", 15 | 4:"CHOWN_ID", 16 | 5:"SETUID_ID", 17 | 6:"CHROOT_ID", 18 | 7:"CREATE_MODULE_ID", 19 | 8:"INIT_MODULE_ID", 20 | 9:"DELETE_MODULE_ID", 21 | 10:"CAPSET_ID", 22 | 11:"CAPGET_ID", 23 | 12:"FORK_ID", 24 | 13:"EXECVE_ID"} 25 | 26 | # First part of the header 27 | class Uberlogger_honeypot_caract(Packet): 28 | name = "Uberlogger honeypot_caract" 29 | fields_desc = [ByteField("honeypot_id", 0), 30 | ByteField("reserved", 0), 31 | ByteField("os_type_and_version", 0)] 32 | 33 | # Second part of the header 34 | class Uberlogger_uber_h(Packet): 35 | name = "Uberlogger uber_h" 36 | fields_desc = [ByteEnumField("syscall_type", 0, uberlogger_sys_calls), 37 | IntField("time_sec", 0), 38 | IntField("time_usec", 0), 39 | IntField("pid", 0), 40 | IntField("uid", 0), 41 | IntField("euid", 0), 42 | IntField("cap_effective", 0), 43 | IntField("cap_inheritable", 0), 44 | IntField("cap_permitted", 0), 45 | IntField("res", 0), 46 | IntField("length", 0)] 47 | 48 | # The 9 following classes are options depending on the syscall type 49 | class Uberlogger_capget_data(Packet): 50 | name = "Uberlogger capget_data" 51 | fields_desc = [IntField("target_pid", 0)] 52 | 53 | class Uberlogger_capset_data(Packet): 54 | name = "Uberlogger capset_data" 55 | fields_desc = [IntField("target_pid", 0), 56 | IntField("effective_cap", 0), 57 | IntField("permitted_cap", 0), 58 | IntField("inheritable_cap", 0)] 59 | 60 | class Uberlogger_chmod_data(Packet): 61 | name = "Uberlogger chmod_data" 62 | fields_desc = [ShortField("mode", 0)] 63 | 64 | class Uberlogger_chown_data(Packet): 65 | name = "Uberlogger chown_data" 66 | fields_desc = [IntField("uid", 0), 67 | IntField("gid", 0)] 68 | 69 | class Uberlogger_open_data(Packet): 70 | name = "Uberlogger open_data" 71 | fields_desc = [IntField("flags", 0), 72 | IntField("mode", 0)] 73 | 74 | class Uberlogger_read_data(Packet): 75 | name = "Uberlogger read_data" 76 | fields_desc = [IntField("fd", 0), 77 | IntField("count", 0)] 78 | 79 | class Uberlogger_setuid_data(Packet): 80 | name = "Uberlogger setuid_data" 81 | fields_desc = [IntField("uid", 0)] 82 | 83 | class Uberlogger_create_module_data(Packet): 84 | name = "Uberlogger create_module_data" 85 | fields_desc = [IntField("size", 0)] 86 | 87 | class Uberlogger_execve_data(Packet): 88 | name = "Uberlogger execve_data" 89 | fields_desc = [IntField("nbarg", 0)] 90 | 91 | # Layer bounds for Uberlogger 92 | bind_layers(Uberlogger_honeypot_caract,Uberlogger_uber_h) 93 | bind_layers(Uberlogger_uber_h,Uberlogger_capget_data) 94 | bind_layers(Uberlogger_uber_h,Uberlogger_capset_data) 95 | bind_layers(Uberlogger_uber_h,Uberlogger_chmod_data) 96 | bind_layers(Uberlogger_uber_h,Uberlogger_chown_data) 97 | bind_layers(Uberlogger_uber_h,Uberlogger_open_data) 98 | bind_layers(Uberlogger_uber_h,Uberlogger_read_data) 99 | bind_layers(Uberlogger_uber_h,Uberlogger_setuid_data) 100 | bind_layers(Uberlogger_uber_h,Uberlogger_create_module_data) 101 | bind_layers(Uberlogger_uber_h,Uberlogger_execve_data) 102 | -------------------------------------------------------------------------------- /scapy/contrib/dtp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # scapy.contrib.description = DTP 4 | # scapy.contrib.status = loads 5 | 6 | """ 7 | DTP Scapy Extension 8 | ~~~~~~~~~~~~~~~~~~~ 9 | 10 | :version: 2008-12-22 11 | :author: Jochen Bartl 12 | 13 | :Thanks: 14 | 15 | - TLV code derived from the CDP implementation of scapy. (Thanks to Nicolas Bareil and Arnaud Ebalard) 16 | http://trac.secdev.org/scapy/ticket/18 17 | """ 18 | 19 | from scapy.packet import * 20 | from scapy.fields import * 21 | from scapy.layers.l2 import SNAP,Dot3,LLC 22 | from scapy.sendrecv import sendp 23 | 24 | class DtpGenericTlv(Packet): 25 | name = "DTP Generic TLV" 26 | fields_desc = [ XShortField("type", 0x0001), 27 | FieldLenField("length", None, length_of=lambda pkt:pkt.value + 4), 28 | StrLenField("value", "", length_from=lambda pkt:pkt.length - 4) 29 | ] 30 | 31 | def guess_payload_class(self, p): 32 | return conf.padding_layer 33 | 34 | class RepeatedTlvListField(PacketListField): 35 | def __init__(self, name, default, cls): 36 | PacketField.__init__(self, name, default, cls) 37 | 38 | def getfield(self, pkt, s): 39 | lst = [] 40 | remain = s 41 | while len(remain) > 0: 42 | p = self.m2i(pkt,remain) 43 | if conf.padding_layer in p: 44 | pad = p[conf.padding_layer] 45 | remain = pad.load 46 | del(pad.underlayer.payload) 47 | else: 48 | remain = "" 49 | lst.append(p) 50 | return remain,lst 51 | 52 | def addfield(self, pkt, s, val): 53 | return s+reduce(str.__add__, map(str, val),"") 54 | 55 | _DTP_TLV_CLS = { 56 | 0x0001 : "DTPDomain", 57 | 0x0002 : "DTPStatus", 58 | 0x0003 : "DTPType", 59 | 0x0004 : "DTPNeighbor" 60 | } 61 | 62 | class DTPDomain(DtpGenericTlv): 63 | name = "DTP Domain" 64 | fields_desc = [ ShortField("type", 1), 65 | FieldLenField("length", None, "domain", adjust=lambda pkt,x:x + 4), 66 | StrLenField("domain", "\x00\x00\x00\x00\x00\x00\x00\x00\x00", length_from=lambda pkt:pkt.length - 4) 67 | ] 68 | 69 | class DTPStatus(DtpGenericTlv): 70 | name = "DTP Status" 71 | fields_desc = [ ShortField("type", 2), 72 | FieldLenField("length", None, "status", adjust=lambda pkt,x:x + 4), 73 | StrLenField("status", "\x03", length_from=lambda pkt:pkt.length - 4) 74 | ] 75 | 76 | class DTPType(DtpGenericTlv): 77 | name = "DTP Type" 78 | fields_desc = [ ShortField("type", 3), 79 | FieldLenField("length", None, "dtptype", adjust=lambda pkt,x:x + 4), 80 | StrLenField("dtptype", "\xa5", length_from=lambda pkt:pkt.length - 4) 81 | ] 82 | 83 | class DTPNeighbor(DtpGenericTlv): 84 | name = "DTP Neighbor" 85 | fields_desc = [ ShortField("type", 4), 86 | #FieldLenField("length", None, "neighbor", adjust=lambda pkt,x:x + 4), 87 | ShortField("len", 10), 88 | MACField("neighbor", None) 89 | ] 90 | 91 | def _DTPGuessPayloadClass(p, **kargs): 92 | cls = conf.raw_layer 93 | if len(p) >= 2: 94 | t = struct.unpack("!H", p[:2])[0] 95 | clsname = _DTP_TLV_CLS.get(t, "DtpGenericTlv") 96 | cls = globals()[clsname] 97 | return cls(p, **kargs) 98 | 99 | class DTP(Packet): 100 | name = "DTP" 101 | fields_desc = [ ByteField("ver", 1), 102 | RepeatedTlvListField("tlvlist", [], _DTPGuessPayloadClass) 103 | ] 104 | 105 | bind_layers(SNAP, DTP, code=0x2004, OUI=0xc) 106 | 107 | 108 | def negotiate_trunk(iface=conf.iface, mymac=str(RandMAC())): 109 | print "Trying to negotiate a trunk on interface %s" % iface 110 | p = Dot3(src=mymac, dst="01:00:0c:cc:cc:cc")/LLC()/SNAP()/DTP(tlvlist=[DTPDomain(),DTPStatus(),DTPType(),DTPNeighbor(neighbor=mymac)]) 111 | sendp(p) 112 | 113 | if __name__ == "__main__": 114 | from scapy.main import interact 115 | interact(mydict=globals(), mybanner="DTP") 116 | -------------------------------------------------------------------------------- /scapy/ansmachine.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Answering machines. 8 | """ 9 | 10 | ######################## 11 | ## Answering machines ## 12 | ######################## 13 | 14 | from sendrecv import send,sendp,sniff 15 | from config import conf 16 | from error import log_interactive 17 | 18 | class ReferenceAM(type): 19 | def __new__(cls, name, bases, dct): 20 | o = super(ReferenceAM, cls).__new__(cls, name, bases, dct) 21 | if o.function_name: 22 | globals()[o.function_name] = lambda o=o,*args,**kargs: o(*args,**kargs)() 23 | return o 24 | 25 | 26 | class AnsweringMachine(object): 27 | __metaclass__ = ReferenceAM 28 | function_name = "" 29 | filter = None 30 | sniff_options = { "store":0 } 31 | sniff_options_list = [ "store", "iface", "count", "promisc", "filter", "type", "prn", "stop_filter" ] 32 | send_options = { "verbose":0 } 33 | send_options_list = ["iface", "inter", "loop", "verbose"] 34 | send_function = staticmethod(send) 35 | 36 | 37 | def __init__(self, **kargs): 38 | self.mode = 0 39 | if self.filter: 40 | kargs.setdefault("filter",self.filter) 41 | kargs.setdefault("prn", self.reply) 42 | self.optam1 = {} 43 | self.optam2 = {} 44 | self.optam0 = {} 45 | doptsend,doptsniff = self.parse_all_options(1, kargs) 46 | self.defoptsend = self.send_options.copy() 47 | self.defoptsend.update(doptsend) 48 | self.defoptsniff = self.sniff_options.copy() 49 | self.defoptsniff.update(doptsniff) 50 | self.optsend,self.optsniff = [{},{}] 51 | 52 | def __getattr__(self, attr): 53 | for d in [self.optam2, self.optam1]: 54 | if attr in d: 55 | return d[attr] 56 | raise AttributeError,attr 57 | 58 | def __setattr__(self, attr, val): 59 | mode = self.__dict__.get("mode",0) 60 | if mode == 0: 61 | self.__dict__[attr] = val 62 | else: 63 | [self.optam1, self.optam2][mode-1][attr] = val 64 | 65 | def parse_options(self): 66 | pass 67 | 68 | def parse_all_options(self, mode, kargs): 69 | sniffopt = {} 70 | sendopt = {} 71 | for k in kargs.keys(): 72 | if k in self.sniff_options_list: 73 | sniffopt[k] = kargs[k] 74 | if k in self.send_options_list: 75 | sendopt[k] = kargs[k] 76 | if k in self.sniff_options_list+self.send_options_list: 77 | del(kargs[k]) 78 | if mode != 2 or kargs: 79 | if mode == 1: 80 | self.optam0 = kargs 81 | elif mode == 2 and kargs: 82 | k = self.optam0.copy() 83 | k.update(kargs) 84 | self.parse_options(**k) 85 | kargs = k 86 | omode = self.__dict__.get("mode",0) 87 | self.__dict__["mode"] = mode 88 | self.parse_options(**kargs) 89 | self.__dict__["mode"] = omode 90 | return sendopt,sniffopt 91 | 92 | def is_request(self, req): 93 | return 1 94 | 95 | def make_reply(self, req): 96 | return req 97 | 98 | def send_reply(self, reply): 99 | self.send_function(reply, **self.optsend) 100 | 101 | def print_reply(self, req, reply): 102 | print "%s ==> %s" % (req.summary(),reply.summary()) 103 | 104 | def reply(self, pkt): 105 | if not self.is_request(pkt): 106 | return 107 | reply = self.make_reply(pkt) 108 | self.send_reply(reply) 109 | if conf.verb >= 0: 110 | self.print_reply(pkt, reply) 111 | 112 | def run(self, *args, **kargs): 113 | log_interactive.warning("run() method deprecated. The intance is now callable") 114 | self(*args,**kargs) 115 | 116 | def __call__(self, *args, **kargs): 117 | optsend,optsniff = self.parse_all_options(2,kargs) 118 | self.optsend=self.defoptsend.copy() 119 | self.optsend.update(optsend) 120 | self.optsniff=self.defoptsniff.copy() 121 | self.optsniff.update(optsniff) 122 | 123 | try: 124 | self.sniff() 125 | except KeyboardInterrupt: 126 | print "Interrupted by user" 127 | 128 | def sniff(self): 129 | sniff(**self.optsniff) 130 | 131 | -------------------------------------------------------------------------------- /scapy/modules/voip.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | VoIP (Voice over IP) related functions 8 | """ 9 | 10 | import os 11 | ################### 12 | ## Testing stuff ## 13 | ################### 14 | 15 | from fcntl import fcntl 16 | from scapy.sendrecv import sniff 17 | from scapy.layers.inet import IP,UDP 18 | from scapy.layers.rtp import RTP 19 | from scapy.utils import get_temp_file 20 | 21 | 22 | def merge(x,y,sample_size=2): 23 | if len(x) > len(y): 24 | y += "\x00"*(len(x)-len(y)) 25 | elif len(x) < len(y): 26 | x += "\x00"*(len(y)-len(x)) 27 | m = "" 28 | ss=sample_size 29 | for i in range(len(x)/ss): 30 | m += x[ss*i:ss*(i+1)]+y[ss*i:ss*(i+1)] 31 | return m 32 | # return "".join(map(str.__add__, x, y)) 33 | 34 | 35 | def voip_play(s1,list=None,**kargs): 36 | FIFO=get_temp_file() 37 | FIFO1=FIFO % 1 38 | FIFO2=FIFO % 2 39 | 40 | os.mkfifo(FIFO1) 41 | os.mkfifo(FIFO2) 42 | try: 43 | os.system("soxmix -t .ul %s -t .ul %s -t ossdsp /dev/dsp &" % (FIFO1,FIFO2)) 44 | 45 | c1=open(FIFO1,"w", 4096) 46 | c2=open(FIFO2,"w", 4096) 47 | fcntl.fcntl(c1.fileno(),fcntl.F_SETFL, os.O_NONBLOCK) 48 | fcntl.fcntl(c2.fileno(),fcntl.F_SETFL, os.O_NONBLOCK) 49 | 50 | # dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp") 51 | def play(pkt,last=[]): 52 | if not pkt: 53 | return 54 | if not pkt.haslayer(UDP): 55 | return 56 | ip=pkt.getlayer(IP) 57 | if s1 in [ip.src, ip.dst]: 58 | if not last: 59 | last.append(pkt) 60 | return 61 | load=last.pop() 62 | # x1 = load.load[12:] 63 | c1.write(load.load[12:]) 64 | if load.getlayer(IP).src == ip.src: 65 | # x2 = "" 66 | c2.write("\x00"*len(load.load[12:])) 67 | last.append(pkt) 68 | else: 69 | # x2 = pkt.load[:12] 70 | c2.write(pkt.load[12:]) 71 | # dsp.write(merge(x1,x2)) 72 | 73 | if list is None: 74 | sniff(store=0, prn=play, **kargs) 75 | else: 76 | for p in list: 77 | play(p) 78 | finally: 79 | os.unlink(FIFO1) 80 | os.unlink(FIFO2) 81 | 82 | 83 | 84 | def voip_play1(s1,list=None,**kargs): 85 | 86 | 87 | dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp") 88 | def play(pkt): 89 | if not pkt: 90 | return 91 | if not pkt.haslayer(UDP): 92 | return 93 | ip=pkt.getlayer(IP) 94 | if s1 in [ip.src, ip.dst]: 95 | dsp.write(pkt.getlayer(conf.raw_layer).load[12:]) 96 | try: 97 | if list is None: 98 | sniff(store=0, prn=play, **kargs) 99 | else: 100 | for p in list: 101 | play(p) 102 | finally: 103 | dsp.close() 104 | rd.close() 105 | 106 | def voip_play2(s1,**kargs): 107 | dsp,rd = os.popen2("sox -t .ul -c 2 - -t ossdsp /dev/dsp") 108 | def play(pkt,last=[]): 109 | if not pkt: 110 | return 111 | if not pkt.haslayer(UDP): 112 | return 113 | ip=pkt.getlayer(IP) 114 | if s1 in [ip.src, ip.dst]: 115 | if not last: 116 | last.append(pkt) 117 | return 118 | load=last.pop() 119 | x1 = load.load[12:] 120 | # c1.write(load.load[12:]) 121 | if load.getlayer(IP).src == ip.src: 122 | x2 = "" 123 | # c2.write("\x00"*len(load.load[12:])) 124 | last.append(pkt) 125 | else: 126 | x2 = pkt.load[:12] 127 | # c2.write(pkt.load[12:]) 128 | dsp.write(merge(x1,x2)) 129 | 130 | sniff(store=0, prn=play, **kargs) 131 | 132 | def voip_play3(lst=None,**kargs): 133 | dsp,rd = os.popen2("sox -t .ul - -t ossdsp /dev/dsp") 134 | try: 135 | def play(pkt, dsp=dsp): 136 | if pkt and pkt.haslayer(UDP) and pkt.haslayer(conf.raw_layer): 137 | dsp.write(pkt.getlayer(RTP).load) 138 | if lst is None: 139 | sniff(store=0, prn=play, **kargs) 140 | else: 141 | for p in lst: 142 | play(p) 143 | finally: 144 | try: 145 | dsp.close() 146 | rd.close() 147 | except: 148 | pass 149 | 150 | -------------------------------------------------------------------------------- /scapy/autorun.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Run commands when the Scapy interpreter starts. 8 | """ 9 | 10 | import code,sys 11 | from config import conf 12 | from themes import * 13 | from error import Scapy_Exception 14 | from utils import tex_escape 15 | 16 | 17 | ######################### 18 | ##### Autorun stuff ##### 19 | ######################### 20 | 21 | class StopAutorun(Scapy_Exception): 22 | code_run = "" 23 | 24 | class ScapyAutorunInterpreter(code.InteractiveInterpreter): 25 | def __init__(self, *args, **kargs): 26 | code.InteractiveInterpreter.__init__(self, *args, **kargs) 27 | self.error = 0 28 | def showsyntaxerror(self, *args, **kargs): 29 | self.error = 1 30 | return code.InteractiveInterpreter.showsyntaxerror(self, *args, **kargs) 31 | def showtraceback(self, *args, **kargs): 32 | self.error = 1 33 | exc_type, exc_value, exc_tb = sys.exc_info() 34 | if isinstance(exc_value, StopAutorun): 35 | raise exc_value 36 | return code.InteractiveInterpreter.showtraceback(self, *args, **kargs) 37 | 38 | 39 | def autorun_commands(cmds,my_globals=None,verb=0): 40 | sv = conf.verb 41 | import __builtin__ 42 | try: 43 | try: 44 | if my_globals is None: 45 | my_globals = __import__("scapy.all").all.__dict__ 46 | conf.verb = verb 47 | interp = ScapyAutorunInterpreter(my_globals) 48 | cmd = "" 49 | cmds = cmds.splitlines() 50 | cmds.append("") # ensure we finish multiline commands 51 | cmds.reverse() 52 | __builtin__.__dict__["_"] = None 53 | while 1: 54 | if cmd: 55 | sys.stderr.write(sys.__dict__.get("ps2","... ")) 56 | else: 57 | sys.stderr.write(str(sys.__dict__.get("ps1",ColorPrompt()))) 58 | 59 | l = cmds.pop() 60 | print l 61 | cmd += "\n"+l 62 | if interp.runsource(cmd): 63 | continue 64 | if interp.error: 65 | return 0 66 | cmd = "" 67 | if len(cmds) <= 1: 68 | break 69 | except SystemExit: 70 | pass 71 | finally: 72 | conf.verb = sv 73 | return _ 74 | 75 | def autorun_get_interactive_session(cmds, **kargs): 76 | class StringWriter: 77 | def __init__(self): 78 | self.s = "" 79 | def write(self, x): 80 | self.s += x 81 | 82 | sw = StringWriter() 83 | sstdout,sstderr = sys.stdout,sys.stderr 84 | try: 85 | try: 86 | sys.stdout = sys.stderr = sw 87 | res = autorun_commands(cmds, **kargs) 88 | except StopAutorun,e: 89 | e.code_run = sw.s 90 | raise 91 | finally: 92 | sys.stdout,sys.stderr = sstdout,sstderr 93 | return sw.s,res 94 | 95 | def autorun_get_text_interactive_session(cmds, **kargs): 96 | ct = conf.color_theme 97 | try: 98 | conf.color_theme = NoTheme() 99 | s,res = autorun_get_interactive_session(cmds, **kargs) 100 | finally: 101 | conf.color_theme = ct 102 | return s,res 103 | 104 | def autorun_get_ansi_interactive_session(cmds, **kargs): 105 | ct = conf.color_theme 106 | try: 107 | conf.color_theme = DefaultTheme() 108 | s,res = autorun_get_interactive_session(cmds, **kargs) 109 | finally: 110 | conf.color_theme = ct 111 | return s,res 112 | 113 | def autorun_get_html_interactive_session(cmds, **kargs): 114 | ct = conf.color_theme 115 | to_html = lambda s: s.replace("<","<").replace(">",">").replace("#[#","<").replace("#]#",">") 116 | try: 117 | try: 118 | conf.color_theme = HTMLTheme2() 119 | s,res = autorun_get_interactive_session(cmds, **kargs) 120 | except StopAutorun,e: 121 | e.code_run = to_html(e.code_run) 122 | raise 123 | finally: 124 | conf.color_theme = ct 125 | 126 | return to_html(s),res 127 | 128 | def autorun_get_latex_interactive_session(cmds, **kargs): 129 | ct = conf.color_theme 130 | to_latex = lambda s: tex_escape(s).replace("@[@","{").replace("@]@","}").replace("@`@","\\") 131 | try: 132 | try: 133 | conf.color_theme = LatexTheme2() 134 | s,res = autorun_get_interactive_session(cmds, **kargs) 135 | except StopAutorun,e: 136 | e.code_run = to_latex(e.code_run) 137 | raise 138 | finally: 139 | conf.color_theme = ct 140 | return to_latex(s),res 141 | 142 | 143 | -------------------------------------------------------------------------------- /scapy/layers/sebek.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Sebek: Linux kernel module for data collection on honeypots. 8 | """ 9 | 10 | from scapy.fields import * 11 | from scapy.packet import * 12 | from scapy.layers.inet import UDP 13 | 14 | 15 | ### SEBEK 16 | 17 | 18 | class SebekHead(Packet): 19 | name = "Sebek header" 20 | fields_desc = [ XIntField("magic", 0xd0d0d0), 21 | ShortField("version", 1), 22 | ShortEnumField("type", 0, {"read":0, "write":1, 23 | "socket":2, "open":3}), 24 | IntField("counter", 0), 25 | IntField("time_sec", 0), 26 | IntField("time_usec", 0) ] 27 | def mysummary(self): 28 | return self.sprintf("Sebek Header v%SebekHead.version% %SebekHead.type%") 29 | 30 | # we need this because Sebek headers differ between v1 and v3, and 31 | # between v3 type socket and v3 others 32 | 33 | class SebekV1(Packet): 34 | name = "Sebek v1" 35 | fields_desc = [ IntField("pid", 0), 36 | IntField("uid", 0), 37 | IntField("fd", 0), 38 | StrFixedLenField("command", "", 12), 39 | FieldLenField("data_length", None, "data",fmt="I"), 40 | StrLenField("data", "", length_from=lambda x:x.data_length) ] 41 | def mysummary(self): 42 | if isinstance(self.underlayer, SebekHead): 43 | return self.underlayer.sprintf("Sebek v1 %SebekHead.type% (%SebekV1.command%)") 44 | else: 45 | return self.sprintf("Sebek v1 (%SebekV1.command%)") 46 | 47 | class SebekV3(Packet): 48 | name = "Sebek v3" 49 | fields_desc = [ IntField("parent_pid", 0), 50 | IntField("pid", 0), 51 | IntField("uid", 0), 52 | IntField("fd", 0), 53 | IntField("inode", 0), 54 | StrFixedLenField("command", "", 12), 55 | FieldLenField("data_length", None, "data",fmt="I"), 56 | StrLenField("data", "", length_from=lambda x:x.data_length) ] 57 | def mysummary(self): 58 | if isinstance(self.underlayer, SebekHead): 59 | return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3.command%)") 60 | else: 61 | return self.sprintf("Sebek v3 (%SebekV3.command%)") 62 | 63 | class SebekV2(SebekV3): 64 | def mysummary(self): 65 | if isinstance(self.underlayer, SebekHead): 66 | return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2.command%)") 67 | else: 68 | return self.sprintf("Sebek v2 (%SebekV2.command%)") 69 | 70 | class SebekV3Sock(Packet): 71 | name = "Sebek v2 socket" 72 | fields_desc = [ IntField("parent_pid", 0), 73 | IntField("pid", 0), 74 | IntField("uid", 0), 75 | IntField("fd", 0), 76 | IntField("inode", 0), 77 | StrFixedLenField("command", "", 12), 78 | IntField("data_length", 15), 79 | IPField("dip", "127.0.0.1"), 80 | ShortField("dport", 0), 81 | IPField("sip", "127.0.0.1"), 82 | ShortField("sport", 0), 83 | ShortEnumField("call", 0, { "bind":2, 84 | "connect":3, "listen":4, 85 | "accept":5, "sendmsg":16, 86 | "recvmsg":17, "sendto":11, 87 | "recvfrom":12}), 88 | ByteEnumField("proto", 0, IP_PROTOS) ] 89 | def mysummary(self): 90 | if isinstance(self.underlayer, SebekHead): 91 | return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV3Sock.command%)") 92 | else: 93 | return self.sprintf("Sebek v3 socket (%SebekV3Sock.command%)") 94 | 95 | class SebekV2Sock(SebekV3Sock): 96 | def mysummary(self): 97 | if isinstance(self.underlayer, SebekHead): 98 | return self.underlayer.sprintf("Sebek v%SebekHead.version% %SebekHead.type% (%SebekV2Sock.command%)") 99 | else: 100 | return self.sprintf("Sebek v2 socket (%SebekV2Sock.command%)") 101 | 102 | bind_layers( UDP, SebekHead, sport=1101) 103 | bind_layers( UDP, SebekHead, dport=1101) 104 | bind_layers( UDP, SebekHead, dport=1101, sport=1101) 105 | bind_layers( SebekHead, SebekV1, version=1) 106 | bind_layers( SebekHead, SebekV2Sock, version=2, type=2) 107 | bind_layers( SebekHead, SebekV2, version=2) 108 | bind_layers( SebekHead, SebekV3Sock, version=3, type=2) 109 | bind_layers( SebekHead, SebekV3, version=3) 110 | -------------------------------------------------------------------------------- /scapy/asn1/mib.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Management Information Base (MIB) parsing 8 | """ 9 | 10 | import re 11 | from glob import glob 12 | from scapy.dadict import DADict,fixname 13 | from scapy.config import conf 14 | from scapy.utils import do_graph 15 | 16 | ################# 17 | ## MIB parsing ## 18 | ################# 19 | 20 | _mib_re_integer = re.compile("^[0-9]+$") 21 | _mib_re_both = re.compile("^([a-zA-Z_][a-zA-Z0-9_-]*)\(([0-9]+)\)$") 22 | _mib_re_oiddecl = re.compile("$\s*([a-zA-Z0-9_-]+)\s+OBJECT([^:\{\}]|\{[^:]+\})+::=\s*\{([^\}]+)\}",re.M) 23 | _mib_re_strings = re.compile('"[^"]*"') 24 | _mib_re_comments = re.compile('--.*(\r|\n)') 25 | 26 | class MIBDict(DADict): 27 | def _findroot(self, x): 28 | if x.startswith("."): 29 | x = x[1:] 30 | if not x.endswith("."): 31 | x += "." 32 | max=0 33 | root="." 34 | for k in self.keys(): 35 | if x.startswith(self[k]+"."): 36 | if max < len(self[k]): 37 | max = len(self[k]) 38 | root = k 39 | return root, x[max:-1] 40 | def _oidname(self, x): 41 | root,remainder = self._findroot(x) 42 | return root+remainder 43 | def _oid(self, x): 44 | xl = x.strip(".").split(".") 45 | p = len(xl)-1 46 | while p >= 0 and _mib_re_integer.match(xl[p]): 47 | p -= 1 48 | if p != 0 or xl[p] not in self: 49 | return x 50 | xl[p] = self[xl[p]] 51 | return ".".join(xl[p:]) 52 | def _make_graph(self, other_keys=[], **kargs): 53 | nodes = [(k,self[k]) for k in self.keys()] 54 | oids = [self[k] for k in self.keys()] 55 | for k in other_keys: 56 | if k not in oids: 57 | nodes.append(self.oidname(k),k) 58 | s = 'digraph "mib" {\n\trankdir=LR;\n\n' 59 | for k,o in nodes: 60 | s += '\t"%s" [ label="%s" ];\n' % (o,k) 61 | s += "\n" 62 | for k,o in nodes: 63 | parent,remainder = self._findroot(o[:-1]) 64 | remainder = remainder[1:]+o[-1] 65 | if parent != ".": 66 | parent = self[parent] 67 | s += '\t"%s" -> "%s" [label="%s"];\n' % (parent, o,remainder) 68 | s += "}\n" 69 | do_graph(s, **kargs) 70 | def __len__(self): 71 | return len(self.keys()) 72 | 73 | 74 | def mib_register(ident, value, the_mib, unresolved): 75 | if ident in the_mib or ident in unresolved: 76 | return ident in the_mib 77 | resval = [] 78 | not_resolved = 0 79 | for v in value: 80 | if _mib_re_integer.match(v): 81 | resval.append(v) 82 | else: 83 | v = fixname(v) 84 | if v not in the_mib: 85 | not_resolved = 1 86 | if v in the_mib: 87 | v = the_mib[v] 88 | elif v in unresolved: 89 | v = unresolved[v] 90 | if type(v) is list: 91 | resval += v 92 | else: 93 | resval.append(v) 94 | if not_resolved: 95 | unresolved[ident] = resval 96 | return False 97 | else: 98 | the_mib[ident] = resval 99 | keys = unresolved.keys() 100 | i = 0 101 | while i < len(keys): 102 | k = keys[i] 103 | if mib_register(k,unresolved[k], the_mib, {}): 104 | del(unresolved[k]) 105 | del(keys[i]) 106 | i = 0 107 | else: 108 | i += 1 109 | 110 | return True 111 | 112 | 113 | def load_mib(filenames): 114 | the_mib = {'iso': ['1']} 115 | unresolved = {} 116 | for k in conf.mib.keys(): 117 | mib_register(k, conf.mib[k].split("."), the_mib, unresolved) 118 | 119 | if type(filenames) is str: 120 | filenames = [filenames] 121 | for fnames in filenames: 122 | for fname in glob(fnames): 123 | f = open(fname) 124 | text = f.read() 125 | cleantext = " ".join(_mib_re_strings.split(" ".join(_mib_re_comments.split(text)))) 126 | for m in _mib_re_oiddecl.finditer(cleantext): 127 | gr = m.groups() 128 | ident,oid = gr[0],gr[-1] 129 | ident=fixname(ident) 130 | oid = oid.split() 131 | for i in range(len(oid)): 132 | m = _mib_re_both.match(oid[i]) 133 | if m: 134 | oid[i] = m.groups()[1] 135 | mib_register(ident, oid, the_mib, unresolved) 136 | 137 | newmib = MIBDict(_name="MIB") 138 | for k,o in the_mib.iteritems(): 139 | newmib[k]=".".join(o) 140 | for k,o in unresolved.iteritems(): 141 | newmib[k]=".".join(o) 142 | 143 | conf.mib=newmib 144 | 145 | 146 | 147 | conf.mib = MIBDict(_name="MIB") 148 | -------------------------------------------------------------------------------- /scapy/supersocket.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | SuperSocket. 8 | """ 9 | 10 | import socket,time 11 | from config import conf 12 | from data import * 13 | from scapy.error import warning, log_runtime 14 | 15 | class _SuperSocket_metaclass(type): 16 | def __repr__(self): 17 | if self.desc is not None: 18 | return "<%s: %s>" % (self.__name__,self.desc) 19 | else: 20 | return "<%s>" % self.__name__ 21 | 22 | 23 | class SuperSocket: 24 | __metaclass__ = _SuperSocket_metaclass 25 | desc = None 26 | closed=0 27 | def __init__(self, family=socket.AF_INET,type=socket.SOCK_STREAM, proto=0): 28 | self.ins = socket.socket(family, type, proto) 29 | self.outs = self.ins 30 | self.promisc=None 31 | def send(self, x): 32 | sx = str(x) 33 | if hasattr(x, "sent_time"): 34 | x.sent_time = time.time() 35 | return self.outs.send(sx) 36 | def recv(self, x=MTU): 37 | return conf.raw_layer(self.ins.recv(x)) 38 | def fileno(self): 39 | return self.ins.fileno() 40 | def close(self): 41 | if self.closed: 42 | return 43 | self.closed=1 44 | if self.ins != self.outs: 45 | if self.outs and self.outs.fileno() != -1: 46 | self.outs.close() 47 | if self.ins and self.ins.fileno() != -1: 48 | self.ins.close() 49 | def sr(self, *args, **kargs): 50 | return sendrecv.sndrcv(self, *args, **kargs) 51 | def sr1(self, *args, **kargs): 52 | a,b = sendrecv.sndrcv(self, *args, **kargs) 53 | if len(a) > 0: 54 | return a[0][1] 55 | else: 56 | return None 57 | def sniff(self, *args, **kargs): 58 | return sendrecv.sniff(opened_socket=self, *args, **kargs) 59 | 60 | class L3RawSocket(SuperSocket): 61 | desc = "Layer 3 using Raw sockets (PF_INET/SOCK_RAW)" 62 | def __init__(self, type = ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0): 63 | self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW) 64 | self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1) 65 | self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type)) 66 | if iface is not None: 67 | self.ins.bind((iface, type)) 68 | def recv(self, x=MTU): 69 | pkt, sa_ll = self.ins.recvfrom(x) 70 | if sa_ll[2] == socket.PACKET_OUTGOING: 71 | return None 72 | if sa_ll[3] in conf.l2types: 73 | cls = conf.l2types[sa_ll[3]] 74 | lvl = 2 75 | elif sa_ll[1] in conf.l3types: 76 | cls = conf.l3types[sa_ll[1]] 77 | lvl = 3 78 | else: 79 | cls = conf.default_l2 80 | warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s" % (sa_ll[0],sa_ll[1],sa_ll[3],cls.name)) 81 | lvl = 3 82 | 83 | try: 84 | pkt = cls(pkt) 85 | except KeyboardInterrupt: 86 | raise 87 | except: 88 | if conf.debug_dissector: 89 | raise 90 | pkt = conf.raw_layer(pkt) 91 | if lvl == 2: 92 | pkt = pkt.payload 93 | 94 | if pkt is not None: 95 | from arch import get_last_packet_timestamp 96 | pkt.time = get_last_packet_timestamp(self.ins) 97 | return pkt 98 | def send(self, x): 99 | try: 100 | sx = str(x) 101 | x.sent_time = time.time() 102 | self.outs.sendto(sx,(x.dst,0)) 103 | except socket.error,msg: 104 | log_runtime.error(msg) 105 | 106 | class SimpleSocket(SuperSocket): 107 | desc = "wrapper arround a classic socket" 108 | def __init__(self, sock): 109 | self.ins = sock 110 | self.outs = sock 111 | 112 | 113 | class StreamSocket(SimpleSocket): 114 | desc = "transforms a stream socket into a layer 2" 115 | def __init__(self, sock, basecls=None): 116 | if basecls is None: 117 | basecls = conf.raw_layer 118 | SimpleSocket.__init__(self, sock) 119 | self.basecls = basecls 120 | 121 | def recv(self, x=MTU): 122 | pkt = self.ins.recv(x, socket.MSG_PEEK) 123 | x = len(pkt) 124 | if x == 0: 125 | raise socket.error((100,"Underlying stream socket tore down")) 126 | pkt = self.basecls(pkt) 127 | pad = pkt.getlayer(conf.padding_layer) 128 | if pad is not None and pad.underlayer is not None: 129 | del(pad.underlayer.payload) 130 | while pad is not None and not isinstance(pad, NoPayload): 131 | x -= len(pad.load) 132 | pad = pad.payload 133 | self.ins.recv(x) 134 | return pkt 135 | 136 | 137 | 138 | if conf.L3socket is None: 139 | conf.L3socket = L3RawSocket 140 | 141 | import sendrecv 142 | -------------------------------------------------------------------------------- /scapy/route.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Routing and handling of network interfaces. 8 | """ 9 | 10 | import socket 11 | from arch import read_routes,get_if_addr,LOOPBACK_NAME 12 | from utils import atol,ltoa,itom 13 | from config import conf 14 | from error import Scapy_Exception,warning 15 | 16 | ############################## 17 | ## Routing/Interfaces stuff ## 18 | ############################## 19 | 20 | class Route: 21 | def __init__(self): 22 | self.resync() 23 | self.s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 24 | self.cache = {} 25 | 26 | def invalidate_cache(self): 27 | self.cache = {} 28 | 29 | def resync(self): 30 | self.invalidate_cache() 31 | self.routes = read_routes() 32 | 33 | def __repr__(self): 34 | rt = "Network Netmask Gateway Iface Output IP\n" 35 | for net,msk,gw,iface,addr in self.routes: 36 | rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net), 37 | ltoa(msk), 38 | gw, 39 | iface, 40 | addr) 41 | return rt 42 | 43 | def make_route(self, host=None, net=None, gw=None, dev=None): 44 | if host is not None: 45 | thenet,msk = host,32 46 | elif net is not None: 47 | thenet,msk = net.split("/") 48 | msk = int(msk) 49 | else: 50 | raise Scapy_Exception("make_route: Incorrect parameters. You should specify a host or a net") 51 | if gw is None: 52 | gw="0.0.0.0" 53 | if dev is None: 54 | if gw: 55 | nhop = gw 56 | else: 57 | nhop = thenet 58 | dev,ifaddr,x = self.route(nhop) 59 | else: 60 | ifaddr = get_if_addr(dev) 61 | return (atol(thenet), itom(msk), gw, dev, ifaddr) 62 | 63 | def add(self, *args, **kargs): 64 | """Ex: 65 | add(net="192.168.1.0/24",gw="1.2.3.4") 66 | """ 67 | self.invalidate_cache() 68 | self.routes.append(self.make_route(*args,**kargs)) 69 | 70 | 71 | def delt(self, *args, **kargs): 72 | """delt(host|net, gw|dev)""" 73 | self.invalidate_cache() 74 | route = self.make_route(*args,**kargs) 75 | try: 76 | i=self.routes.index(route) 77 | del(self.routes[i]) 78 | except ValueError: 79 | warning("no matching route found") 80 | 81 | def ifchange(self, iff, addr): 82 | self.invalidate_cache() 83 | the_addr,the_msk = (addr.split("/")+["32"])[:2] 84 | the_msk = itom(int(the_msk)) 85 | the_rawaddr = atol(the_addr) 86 | the_net = the_rawaddr & the_msk 87 | 88 | 89 | for i in range(len(self.routes)): 90 | net,msk,gw,iface,addr = self.routes[i] 91 | if iface != iff: 92 | continue 93 | if gw == '0.0.0.0': 94 | self.routes[i] = (the_net,the_msk,gw,iface,the_addr) 95 | else: 96 | self.routes[i] = (net,msk,gw,iface,the_addr) 97 | conf.netcache.flush() 98 | 99 | 100 | 101 | def ifdel(self, iff): 102 | self.invalidate_cache() 103 | new_routes=[] 104 | for rt in self.routes: 105 | if rt[3] != iff: 106 | new_routes.append(rt) 107 | self.routes=new_routes 108 | 109 | def ifadd(self, iff, addr): 110 | self.invalidate_cache() 111 | the_addr,the_msk = (addr.split("/")+["32"])[:2] 112 | the_msk = itom(int(the_msk)) 113 | the_rawaddr = atol(the_addr) 114 | the_net = the_rawaddr & the_msk 115 | self.routes.append((the_net,the_msk,'0.0.0.0',iff,the_addr)) 116 | 117 | 118 | def route(self,dest,verbose=None): 119 | if type(dest) is list and dest: 120 | dest = dest[0] 121 | if dest in self.cache: 122 | return self.cache[dest] 123 | if verbose is None: 124 | verbose=conf.verb 125 | # Transform "192.168.*.1-5" to one IP of the set 126 | dst = dest.split("/")[0] 127 | dst = dst.replace("*","0") 128 | while 1: 129 | l = dst.find("-") 130 | if l < 0: 131 | break 132 | m = (dst[l:]+".").find(".") 133 | dst = dst[:l]+dst[l+m:] 134 | 135 | 136 | dst = atol(dst) 137 | pathes=[] 138 | for d,m,gw,i,a in self.routes: 139 | aa = atol(a) 140 | if aa == dst: 141 | pathes.append((0xffffffffL,(LOOPBACK_NAME,a,"0.0.0.0"))) 142 | if (dst & m) == (d & m): 143 | pathes.append((m,(i,a,gw))) 144 | if not pathes: 145 | if verbose: 146 | warning("No route found (no default route?)") 147 | return LOOPBACK_NAME,"0.0.0.0","0.0.0.0" #XXX linux specific! 148 | # Choose the more specific route (greatest netmask). 149 | # XXX: we don't care about metrics 150 | pathes.sort() 151 | ret = pathes[-1][1] 152 | self.cache[dest] = ret 153 | return ret 154 | 155 | def get_if_bcast(self, iff): 156 | for net, msk, gw, iface, addr in self.routes: 157 | if (iff == iface and net != 0L): 158 | bcast = atol(addr)|(~msk&0xffffffffL); # FIXME: check error in atol() 159 | return ltoa(bcast); 160 | warning("No broadcast address found for iface %s\n" % iff); 161 | 162 | conf.route=Route() 163 | 164 | #XXX use "with" 165 | _betteriface = conf.route.route("0.0.0.0", verbose=0)[0] 166 | if _betteriface != LOOPBACK_NAME: 167 | conf.iface = _betteriface 168 | del(_betteriface) 169 | -------------------------------------------------------------------------------- /scapy/layers/skinny.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Cisco Skinny protocol. 8 | """ 9 | 10 | from scapy.packet import * 11 | from scapy.fields import * 12 | from scapy.layers.inet import TCP 13 | 14 | # shamelessly ripped from Ethereal dissector 15 | skinny_messages = { 16 | # Station -> Callmanager 17 | 0x0000: "KeepAliveMessage", 18 | 0x0001: "RegisterMessage", 19 | 0x0002: "IpPortMessage", 20 | 0x0003: "KeypadButtonMessage", 21 | 0x0004: "EnblocCallMessage", 22 | 0x0005: "StimulusMessage", 23 | 0x0006: "OffHookMessage", 24 | 0x0007: "OnHookMessage", 25 | 0x0008: "HookFlashMessage", 26 | 0x0009: "ForwardStatReqMessage", 27 | 0x000A: "SpeedDialStatReqMessage", 28 | 0x000B: "LineStatReqMessage", 29 | 0x000C: "ConfigStatReqMessage", 30 | 0x000D: "TimeDateReqMessage", 31 | 0x000E: "ButtonTemplateReqMessage", 32 | 0x000F: "VersionReqMessage", 33 | 0x0010: "CapabilitiesResMessage", 34 | 0x0011: "MediaPortListMessage", 35 | 0x0012: "ServerReqMessage", 36 | 0x0020: "AlarmMessage", 37 | 0x0021: "MulticastMediaReceptionAck", 38 | 0x0022: "OpenReceiveChannelAck", 39 | 0x0023: "ConnectionStatisticsRes", 40 | 0x0024: "OffHookWithCgpnMessage", 41 | 0x0025: "SoftKeySetReqMessage", 42 | 0x0026: "SoftKeyEventMessage", 43 | 0x0027: "UnregisterMessage", 44 | 0x0028: "SoftKeyTemplateReqMessage", 45 | 0x0029: "RegisterTokenReq", 46 | 0x002A: "MediaTransmissionFailure", 47 | 0x002B: "HeadsetStatusMessage", 48 | 0x002C: "MediaResourceNotification", 49 | 0x002D: "RegisterAvailableLinesMessage", 50 | 0x002E: "DeviceToUserDataMessage", 51 | 0x002F: "DeviceToUserDataResponseMessage", 52 | 0x0030: "UpdateCapabilitiesMessage", 53 | 0x0031: "OpenMultiMediaReceiveChannelAckMessage", 54 | 0x0032: "ClearConferenceMessage", 55 | 0x0033: "ServiceURLStatReqMessage", 56 | 0x0034: "FeatureStatReqMessage", 57 | 0x0035: "CreateConferenceResMessage", 58 | 0x0036: "DeleteConferenceResMessage", 59 | 0x0037: "ModifyConferenceResMessage", 60 | 0x0038: "AddParticipantResMessage", 61 | 0x0039: "AuditConferenceResMessage", 62 | 0x0040: "AuditParticipantResMessage", 63 | 0x0041: "DeviceToUserDataVersion1Message", 64 | # Callmanager -> Station */ 65 | 0x0081: "RegisterAckMessage", 66 | 0x0082: "StartToneMessage", 67 | 0x0083: "StopToneMessage", 68 | 0x0085: "SetRingerMessage", 69 | 0x0086: "SetLampMessage", 70 | 0x0087: "SetHkFDetectMessage", 71 | 0x0088: "SetSpeakerModeMessage", 72 | 0x0089: "SetMicroModeMessage", 73 | 0x008A: "StartMediaTransmission", 74 | 0x008B: "StopMediaTransmission", 75 | 0x008C: "StartMediaReception", 76 | 0x008D: "StopMediaReception", 77 | 0x008F: "CallInfoMessage", 78 | 0x0090: "ForwardStatMessage", 79 | 0x0091: "SpeedDialStatMessage", 80 | 0x0092: "LineStatMessage", 81 | 0x0093: "ConfigStatMessage", 82 | 0x0094: "DefineTimeDate", 83 | 0x0095: "StartSessionTransmission", 84 | 0x0096: "StopSessionTransmission", 85 | 0x0097: "ButtonTemplateMessage", 86 | 0x0098: "VersionMessage", 87 | 0x0099: "DisplayTextMessage", 88 | 0x009A: "ClearDisplay", 89 | 0x009B: "CapabilitiesReqMessage", 90 | 0x009C: "EnunciatorCommandMessage", 91 | 0x009D: "RegisterRejectMessage", 92 | 0x009E: "ServerResMessage", 93 | 0x009F: "Reset", 94 | 0x0100: "KeepAliveAckMessage", 95 | 0x0101: "StartMulticastMediaReception", 96 | 0x0102: "StartMulticastMediaTransmission", 97 | 0x0103: "StopMulticastMediaReception", 98 | 0x0104: "StopMulticastMediaTransmission", 99 | 0x0105: "OpenReceiveChannel", 100 | 0x0106: "CloseReceiveChannel", 101 | 0x0107: "ConnectionStatisticsReq", 102 | 0x0108: "SoftKeyTemplateResMessage", 103 | 0x0109: "SoftKeySetResMessage", 104 | 0x0110: "SelectSoftKeysMessage", 105 | 0x0111: "CallStateMessage", 106 | 0x0112: "DisplayPromptStatusMessage", 107 | 0x0113: "ClearPromptStatusMessage", 108 | 0x0114: "DisplayNotifyMessage", 109 | 0x0115: "ClearNotifyMessage", 110 | 0x0116: "ActivateCallPlaneMessage", 111 | 0x0117: "DeactivateCallPlaneMessage", 112 | 0x0118: "UnregisterAckMessage", 113 | 0x0119: "BackSpaceReqMessage", 114 | 0x011A: "RegisterTokenAck", 115 | 0x011B: "RegisterTokenReject", 116 | 0x0042: "DeviceToUserDataResponseVersion1Message", 117 | 0x011C: "StartMediaFailureDetection", 118 | 0x011D: "DialedNumberMessage", 119 | 0x011E: "UserToDeviceDataMessage", 120 | 0x011F: "FeatureStatMessage", 121 | 0x0120: "DisplayPriNotifyMessage", 122 | 0x0121: "ClearPriNotifyMessage", 123 | 0x0122: "StartAnnouncementMessage", 124 | 0x0123: "StopAnnouncementMessage", 125 | 0x0124: "AnnouncementFinishMessage", 126 | 0x0127: "NotifyDtmfToneMessage", 127 | 0x0128: "SendDtmfToneMessage", 128 | 0x0129: "SubscribeDtmfPayloadReqMessage", 129 | 0x012A: "SubscribeDtmfPayloadResMessage", 130 | 0x012B: "SubscribeDtmfPayloadErrMessage", 131 | 0x012C: "UnSubscribeDtmfPayloadReqMessage", 132 | 0x012D: "UnSubscribeDtmfPayloadResMessage", 133 | 0x012E: "UnSubscribeDtmfPayloadErrMessage", 134 | 0x012F: "ServiceURLStatMessage", 135 | 0x0130: "CallSelectStatMessage", 136 | 0x0131: "OpenMultiMediaChannelMessage", 137 | 0x0132: "StartMultiMediaTransmission", 138 | 0x0133: "StopMultiMediaTransmission", 139 | 0x0134: "MiscellaneousCommandMessage", 140 | 0x0135: "FlowControlCommandMessage", 141 | 0x0136: "CloseMultiMediaReceiveChannel", 142 | 0x0137: "CreateConferenceReqMessage", 143 | 0x0138: "DeleteConferenceReqMessage", 144 | 0x0139: "ModifyConferenceReqMessage", 145 | 0x013A: "AddParticipantReqMessage", 146 | 0x013B: "DropParticipantReqMessage", 147 | 0x013C: "AuditConferenceReqMessage", 148 | 0x013D: "AuditParticipantReqMessage", 149 | 0x013F: "UserToDeviceDataVersion1Message", 150 | } 151 | 152 | 153 | 154 | class Skinny(Packet): 155 | name="Skinny" 156 | fields_desc = [ LEIntField("len",0), 157 | LEIntField("res",0), 158 | LEIntEnumField("msg",0,skinny_messages) ] 159 | 160 | bind_layers( TCP, Skinny, dport=2000) 161 | bind_layers( TCP, Skinny, sport=2000) 162 | -------------------------------------------------------------------------------- /doc/scapy/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Scapy documentation build configuration file, created by 4 | # sphinx-quickstart on Mon Sep 8 19:37:39 2008. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # The contents of this file are pickled, so don't put values in the namespace 9 | # that aren't pickleable (module imports are okay, they're removed automatically). 10 | # 11 | # All configuration values have a default value; values that are commented out 12 | # serve to show the default value. 13 | 14 | import sys, os 15 | 16 | # If your extensions are in another directory, add it here. If the directory 17 | # is relative to the documentation root, use os.path.abspath to make it 18 | # absolute, like shown here. 19 | #sys.path.append(os.path.abspath('some/directory')) 20 | 21 | # General configuration 22 | # --------------------- 23 | 24 | # Add any Sphinx extension module names here, as strings. They can be extensions 25 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 26 | extensions = [] 27 | 28 | # Add any paths that contain templates here, relative to this directory. 29 | templates_path = ['_templates'] 30 | 31 | # The suffix of source filenames. 32 | source_suffix = '.rst' 33 | 34 | # The master toctree document. 35 | master_doc = 'index' 36 | 37 | # General substitutions. 38 | project = 'Scapy' 39 | copyright = '2008, 2009 Philippe Biondi and the Scapy community' 40 | 41 | # The default replacements for |version| and |release|, also used in various 42 | # other places throughout the built documents. 43 | # 44 | # The short X.Y version. 45 | version = '2.2.0' 46 | # The full version, including alpha/beta/rc tags. 47 | release = '2.2.0-dev' 48 | 49 | # There are two options for replacing |today|: either, you set today to some 50 | # non-false value, then it is used: 51 | #today = '' 52 | # Else, today_fmt is used as the format for a strftime call. 53 | today_fmt = '%B %d, %Y' 54 | 55 | # List of documents that shouldn't be included in the build. 56 | #unused_docs = [] 57 | 58 | # List of directories, relative to source directories, that shouldn't be searched 59 | # for source files. 60 | #exclude_dirs = [] 61 | 62 | # The reST default role (used for this markup: `text`) to use for all documents. 63 | #default_role = None 64 | 65 | # If true, '()' will be appended to :func: etc. cross-reference text. 66 | #add_function_parentheses = True 67 | 68 | # If true, the current module name will be prepended to all description 69 | # unit titles (such as .. function::). 70 | #add_module_names = True 71 | 72 | # If true, sectionauthor and moduleauthor directives will be shown in the 73 | # output. They are ignored by default. 74 | #show_authors = False 75 | 76 | # The name of the Pygments (syntax highlighting) style to use. 77 | pygments_style = 'sphinx' 78 | 79 | 80 | # Options for HTML output 81 | # ----------------------- 82 | 83 | # The style sheet to use for HTML and HTML Help pages. A file of that name 84 | # must exist either in Sphinx' static/ path, or in one of the custom paths 85 | # given in html_static_path. 86 | html_style = 'default.css' 87 | 88 | # The name for this set of Sphinx documents. If None, it defaults to 89 | # " v documentation". 90 | #html_title = None 91 | 92 | # A shorter title for the navigation bar. Default is the same as html_title. 93 | #html_short_title = None 94 | 95 | # The name of an image file (within the static path) to place at the top of 96 | # the sidebar. 97 | #html_logo = None 98 | 99 | # The name of an image file (within the static path) to use as favicon of the 100 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 101 | # pixels large. 102 | #html_favicon = None 103 | 104 | # Add any paths that contain custom static files (such as style sheets) here, 105 | # relative to this directory. They are copied after the builtin static files, 106 | # so a file named "default.css" will overwrite the builtin "default.css". 107 | html_static_path = ['_static'] 108 | 109 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 110 | # using the given strftime format. 111 | html_last_updated_fmt = '%b %d, %Y' 112 | 113 | # If true, SmartyPants will be used to convert quotes and dashes to 114 | # typographically correct entities. 115 | #html_use_smartypants = True 116 | 117 | # Custom sidebar templates, maps document names to template names. 118 | #html_sidebars = {} 119 | 120 | # Additional templates that should be rendered to pages, maps page names to 121 | # template names. 122 | #html_additional_pages = {} 123 | 124 | # If false, no module index is generated. 125 | html_use_modindex = False 126 | 127 | # If false, no index is generated. 128 | #html_use_index = True 129 | 130 | # If true, the index is split into individual pages for each letter. 131 | #html_split_index = False 132 | 133 | # If true, the reST sources are included in the HTML build as _sources/. 134 | #html_copy_source = True 135 | 136 | # If true, an OpenSearch description file will be output, and all pages will 137 | # contain a tag referring to it. The value of this option must be the 138 | # base URL from which the finished HTML is served. 139 | #html_use_opensearch = '' 140 | 141 | # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). 142 | #html_file_suffix = '' 143 | 144 | # Output file base name for HTML help builder. 145 | htmlhelp_basename = 'Scapydoc' 146 | 147 | 148 | # Options for LaTeX output 149 | # ------------------------ 150 | 151 | # The paper size ('letter' or 'a4'). 152 | latex_paper_size = 'a4' 153 | 154 | # The font size ('10pt', '11pt' or '12pt'). 155 | latex_font_size = '11pt' 156 | 157 | # Grouping the document tree into LaTeX files. List of tuples 158 | # (source start file, target name, title, author, document class [howto/manual]). 159 | latex_documents = [ 160 | ('index', 'Scapy.tex', 'Scapy Documentation', 161 | 'Philippe Biondi and the Scapy community', 'manual'), 162 | ] 163 | 164 | # The name of an image file (relative to this directory) to place at the top of 165 | # the title page. 166 | #latex_logo = None 167 | 168 | # For "manual" documents, if this is true, then toplevel headings are parts, 169 | # not chapters. 170 | #latex_use_parts = False 171 | 172 | # Additional stuff for the LaTeX preamble. 173 | #latex_preamble = '' 174 | 175 | # Documents to append as an appendix to all manuals. 176 | #latex_appendices = [] 177 | 178 | # If false, no module index is generated. 179 | latex_use_modindex = False 180 | -------------------------------------------------------------------------------- /scapy/arch/unix.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Common customizations for all Unix-like operating systems other than Linux 8 | """ 9 | 10 | import sys,os,struct,socket,time 11 | from fcntl import ioctl 12 | from scapy.error import warning 13 | import scapy.config 14 | import scapy.utils 15 | import scapy.utils6 16 | import scapy.arch 17 | 18 | scapy.config.conf.use_pcap = 1 19 | scapy.config.conf.use_dnet = 1 20 | from pcapdnet import * 21 | 22 | 23 | 24 | 25 | 26 | ################## 27 | ## Routes stuff ## 28 | ################## 29 | 30 | 31 | def read_routes(): 32 | if scapy.arch.SOLARIS: 33 | f=os.popen("netstat -rvn") # -f inet 34 | elif scapy.arch.FREEBSD: 35 | f=os.popen("netstat -rnW") # -W to handle long interface names 36 | else: 37 | f=os.popen("netstat -rn") # -f inet 38 | ok = 0 39 | mtu_present = False 40 | prio_present = False 41 | routes = [] 42 | pending_if = [] 43 | for l in f.readlines(): 44 | if not l: 45 | break 46 | l = l.strip() 47 | if l.find("----") >= 0: # a separation line 48 | continue 49 | if not ok: 50 | if l.find("Destination") >= 0: 51 | ok = 1 52 | mtu_present = l.find("Mtu") >= 0 53 | prio_present = l.find("Prio") >= 0 54 | continue 55 | if not l: 56 | break 57 | if scapy.arch.SOLARIS: 58 | lspl = l.split() 59 | if len(lspl) == 10: 60 | dest,mask,gw,netif,mxfrg,rtt,ref,flg = lspl[:8] 61 | else: # missing interface 62 | dest,mask,gw,mxfrg,rtt,ref,flg = lspl[:7] 63 | netif=None 64 | else: 65 | rt = l.split() 66 | dest,gw,flg = rt[:3] 67 | netif = rt[5+mtu_present+prio_present] 68 | if flg.find("Lc") >= 0: 69 | continue 70 | if dest == "default": 71 | dest = 0L 72 | netmask = 0L 73 | else: 74 | if scapy.arch.SOLARIS: 75 | netmask = scapy.utils.atol(mask) 76 | elif "/" in dest: 77 | dest,netmask = dest.split("/") 78 | netmask = scapy.utils.itom(int(netmask)) 79 | else: 80 | netmask = scapy.utils.itom((dest.count(".") + 1) * 8) 81 | dest += ".0"*(3-dest.count(".")) 82 | dest = scapy.utils.atol(dest) 83 | if not "G" in flg: 84 | gw = '0.0.0.0' 85 | if netif is not None: 86 | ifaddr = scapy.arch.get_if_addr(netif) 87 | routes.append((dest,netmask,gw,netif,ifaddr)) 88 | else: 89 | pending_if.append((dest,netmask,gw)) 90 | f.close() 91 | 92 | # On Solaris, netstat does not provide output interfaces for some routes 93 | # We need to parse completely the routing table to route their gw and 94 | # know their output interface 95 | for dest,netmask,gw in pending_if: 96 | gw_l = scapy.utils.atol(gw) 97 | max_rtmask,gw_if,gw_if_addr, = 0,None,None 98 | for rtdst,rtmask,_,rtif,rtaddr in routes[:]: 99 | if gw_l & rtmask == rtdst: 100 | if rtmask >= max_rtmask: 101 | max_rtmask = rtmask 102 | gw_if = rtif 103 | gw_if_addr = rtaddr 104 | if gw_if: 105 | routes.append((dest,netmask,gw,gw_if,gw_if_addr)) 106 | else: 107 | warning("Did not find output interface to reach gateway %s" % gw) 108 | 109 | return routes 110 | 111 | ############ 112 | ### IPv6 ### 113 | ############ 114 | 115 | def in6_getifaddr(): 116 | """ 117 | Returns a list of 3-tuples of the form (addr, scope, iface) where 118 | 'addr' is the address of scope 'scope' associated to the interface 119 | 'ifcace'. 120 | 121 | This is the list of all addresses of all interfaces available on 122 | the system. 123 | """ 124 | 125 | ret = [] 126 | i = dnet.intf() 127 | for int in i: 128 | ifname = int['name'] 129 | v6 = [] 130 | if int.has_key('alias_addrs'): 131 | v6 = int['alias_addrs'] 132 | for a in v6: 133 | if a.type != dnet.ADDR_TYPE_IP6: 134 | continue 135 | 136 | xx = str(a).split('/')[0] 137 | addr = scapy.utils6.in6_ptop(xx) 138 | 139 | scope = scapy.utils6.in6_getscope(addr) 140 | 141 | ret.append((xx, scope, ifname)) 142 | return ret 143 | 144 | def read_routes6(): 145 | f = os.popen("netstat -rn -f inet6") 146 | ok = False 147 | mtu_present = False 148 | prio_present = False 149 | routes = [] 150 | lifaddr = in6_getifaddr() 151 | for l in f.readlines(): 152 | if not l: 153 | break 154 | l = l.strip() 155 | if not ok: 156 | if l.find("Destination") >= 0: 157 | ok = 1 158 | mtu_present = l.find("Mtu") >= 0 159 | prio_present = l.find("Prio") >= 0 160 | continue 161 | # gv 12/12/06: under debugging 162 | if scapy.arch.NETBSD or scapy.arch.OPENBSD: 163 | lspl = l.split() 164 | d,nh,fl = lspl[:3] 165 | dev = lspl[5+mtu_present+prio_present] 166 | else: # FREEBSD or DARWIN 167 | d,nh,fl,dev = l.split()[:4] 168 | if filter(lambda x: x[2] == dev, lifaddr) == []: 169 | continue 170 | if 'L' in fl: # drop MAC addresses 171 | continue 172 | 173 | if 'link' in nh: 174 | nh = '::' 175 | 176 | cset = [] # candidate set (possible source addresses) 177 | dp = 128 178 | if d == 'default': 179 | d = '::' 180 | dp = 0 181 | if '/' in d: 182 | d,dp = d.split("/") 183 | dp = int(dp) 184 | if '%' in d: 185 | d,dev = d.split('%') 186 | if '%' in nh: 187 | nh,dev = nh.split('%') 188 | if scapy.arch.LOOPBACK_NAME in dev: 189 | cset = ['::1'] 190 | nh = '::' 191 | else: 192 | devaddrs = filter(lambda x: x[2] == dev, lifaddr) 193 | cset = scapy.utils6.construct_source_candidate_set(d, dp, devaddrs, scapy.arch.LOOPBACK_NAME) 194 | 195 | if len(cset) != 0: 196 | routes.append((d, dp, nh, dev, cset)) 197 | 198 | f.close() 199 | return routes 200 | 201 | 202 | 203 | 204 | 205 | 206 | -------------------------------------------------------------------------------- /scapy/contrib/vtp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # scapy.contrib.description = VLAN Trunking Protocol (VTP) 4 | # scapy.contrib.status = loads 5 | 6 | """ 7 | VTP Scapy Extension 8 | ~~~~~~~~~~~~~~~~~~~~~ 9 | 10 | :version: 2009-02-15 11 | :copyright: 2009 by Jochen Bartl 12 | :e-mail: lobo@c3a.de / jochen.bartl@gmail.com 13 | :license: GPL v2 14 | 15 | This program is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU General Public License 17 | as published by the Free Software Foundation; either version 2 18 | of the License, or (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | :TODO 26 | 27 | - Join messages 28 | - RE MD5 hash calculation 29 | - Have a closer look at 8 byte padding in summary adv. 30 | "debug sw-vlan vtp packets" sais the TLV length is invalid, 31 | when I change the values 32 | '\x00\x00\x00\x01\x06\x01\x00\x02' 33 | * \x00\x00 ? 34 | * \x00\x01 tlvtype? 35 | * \x06 length? 36 | * \x00\x02 value? 37 | - h2i function for VTPTimeStampField 38 | 39 | :References: 40 | 41 | - Understanding VLAN Trunk Protocol (VTP) 42 | http://www.cisco.com/en/US/tech/tk389/tk689/technologies_tech_note09186a0080094c52.shtml 43 | """ 44 | 45 | from scapy.all import * 46 | 47 | _VTP_VLAN_TYPE = { 48 | 1 : 'Ethernet', 49 | 2 : 'FDDI', 50 | 3 : 'TrCRF', 51 | 4 : 'FDDI-net', 52 | 5 : 'TrBRF' 53 | } 54 | 55 | _VTP_VLANINFO_TLV_TYPE = { 56 | 0x01 : 'Source-Routing Ring Number', 57 | 0x02 : 'Source-Routing Bridge Number', 58 | 0x03 : 'Spanning-Tree Protocol Type', 59 | 0x04 : 'Parent VLAN', 60 | 0x05 : 'Translationally Bridged VLANs', 61 | 0x06 : 'Pruning', 62 | 0x07 : 'Bridge Type', 63 | 0x08 : 'Max ARE Hop Count', 64 | 0x09 : 'Max STE Hop Count', 65 | 0x0A : 'Backup CRF Mode' 66 | } 67 | 68 | 69 | class VTPVlanInfoTlv(Packet): 70 | name = "VTP VLAN Info TLV" 71 | fields_desc = [ 72 | ByteEnumField("type", 0, _VTP_VLANINFO_TLV_TYPE), 73 | ByteField("length", 0), 74 | StrLenField("value", None, length_from=lambda pkt : pkt.length + 1) 75 | ] 76 | 77 | def guess_payload_class(self, p): 78 | return conf.padding_layer 79 | 80 | class VTPVlanInfo(Packet): 81 | name = "VTP VLAN Info" 82 | fields_desc = [ 83 | ByteField("len", None), # FIXME: compute length 84 | ByteEnumField("status", 0, {0 : "active", 1 : "suspended"}), 85 | ByteEnumField("type", 1, _VTP_VLAN_TYPE), 86 | FieldLenField("vlannamelen", None, "vlanname", "B"), 87 | ShortField("vlanid", 1), 88 | ShortField("mtu", 1500), 89 | XIntField("dot10index", None), 90 | StrLenField("vlanname", "default", length_from=lambda pkt:4 * ((pkt.vlannamelen + 3) / 4)), 91 | ConditionalField(PacketListField("tlvlist", [], VTPVlanInfoTlv, 92 | length_from=lambda pkt:pkt.len - 12 - (4 * ((pkt.vlannamelen + 3) / 4))), 93 | lambda pkt:pkt.type not in [1, 2]) 94 | ] 95 | 96 | def post_build(self, p, pay): 97 | vlannamelen = 4 * ((len(self.vlanname) + 3) / 4) 98 | 99 | if self.len == None: 100 | l = vlannamelen + 12 101 | p = chr(l & 0xff) + p[1:] 102 | 103 | # Pad vlan name with zeros if vlannamelen > len(vlanname) 104 | l = vlannamelen - len(self.vlanname) 105 | if l != 0: 106 | p += "\x00" * l 107 | 108 | p += pay 109 | 110 | return p 111 | 112 | def guess_payload_class(self, p): 113 | return conf.padding_layer 114 | 115 | _VTP_Types = { 116 | 1 : 'Summary Advertisement', 117 | 2 : 'Subset Advertisements', 118 | 3 : 'Advertisement Request', 119 | 4 : 'Join' 120 | } 121 | 122 | class VTPTimeStampField(StrFixedLenField): 123 | def __init__(self, name, default): 124 | StrFixedLenField.__init__(self, name, default, 12) 125 | 126 | def i2repr(self, pkt, x): 127 | return "%s-%s-%s %s:%s:%s" % (x[:2], x[2:4], x[4:6], x[6:8], x[8:10], x[10:12]) 128 | 129 | class VTP(Packet): 130 | name = "VTP" 131 | fields_desc = [ 132 | ByteField("ver", 2), 133 | ByteEnumField("code", 1, _VTP_Types), 134 | ConditionalField(ByteField("followers", 1), 135 | lambda pkt:pkt.code == 1), 136 | ConditionalField(ByteField("seq", 1), 137 | lambda pkt:pkt.code == 2), 138 | ConditionalField(ByteField("reserved", 0), 139 | lambda pkt:pkt.code == 3), 140 | ByteField("domnamelen", None), 141 | StrFixedLenField("domname", "manbearpig", 32), 142 | ConditionalField(SignedIntField("rev", 0), 143 | lambda pkt:pkt.code == 1 or 144 | pkt.code == 2), 145 | # updater identity 146 | ConditionalField(IPField("uid", "192.168.0.1"), 147 | lambda pkt:pkt.code == 1), 148 | ConditionalField(VTPTimeStampField("timestamp", '930301000000'), 149 | lambda pkt:pkt.code == 1), 150 | ConditionalField(StrFixedLenField("md5", "\x00" * 16, 16), 151 | lambda pkt:pkt.code == 1), 152 | ConditionalField( 153 | PacketListField("vlaninfo", [], VTPVlanInfo), 154 | lambda pkt: pkt.code == 2), 155 | ConditionalField(ShortField("startvalue", 0), 156 | lambda pkt:pkt.code == 3) 157 | ] 158 | 159 | def post_build(self, p, pay): 160 | if self.domnamelen == None: 161 | domnamelen = len(self.domname.strip("\x00")) 162 | p = p[:3] + chr(domnamelen & 0xff) + p[4:] 163 | 164 | p += pay 165 | 166 | return p 167 | 168 | bind_layers(SNAP, VTP, code=0x2003) 169 | 170 | if __name__ == '__main__': 171 | interact(mydict=globals(), mybanner="VTP") 172 | -------------------------------------------------------------------------------- /scapy/contrib/bgp.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # http://trac.secdev.org/scapy/ticket/162 4 | 5 | # scapy.contrib.description = BGP 6 | # scapy.contrib.status = loads 7 | 8 | from scapy.packet import * 9 | from scapy.fields import * 10 | from scapy.layers.inet import TCP 11 | 12 | 13 | class BGPIPField(Field): 14 | """Represents how bgp dose an ip prefix in (length, prefix)""" 15 | def mask2iplen(self,mask): 16 | """turn the mask into the length in bytes of the ip field""" 17 | return (mask + 7) // 8 18 | def h2i(self, pkt, h): 19 | """human x.x.x.x/y to internal""" 20 | ip,mask = re.split( '/', h) 21 | return int(mask), ip 22 | def i2h( self, pkt, i): 23 | mask, ip = i 24 | return ip + '/' + str( mask ) 25 | def i2repr( self, pkt, i): 26 | """make it look nice""" 27 | return self.i2h(pkt,i) 28 | def i2len(self, pkt, i): 29 | """rely on integer division""" 30 | mask, ip = i 31 | return self.mask2iplen(mask) + 1 32 | def i2m(self, pkt, i): 33 | """internal (ip as bytes, mask as int) to machine""" 34 | mask, ip = i 35 | ip = inet_aton( ip ) 36 | return struct.pack(">B",mask) + ip[:self.mask2iplen(mask)] 37 | def addfield(self, pkt, s, val): 38 | return s+self.i2m(pkt, val) 39 | def getfield(self, pkt, s): 40 | l = self.mask2iplen( struct.unpack(">B",s[0])[0] ) + 1 41 | return s[l:], self.m2i(pkt,s[:l]) 42 | def m2i(self,pkt,m): 43 | mask = struct.unpack(">B",m[0])[0] 44 | ip = "".join( [ m[i + 1] if i < self.mask2iplen(mask) else '\x00' for i in range(4)] ) 45 | return (mask,inet_ntoa(ip)) 46 | 47 | class BGPHeader(Packet): 48 | """The first part of any BGP packet""" 49 | name = "BGP header" 50 | fields_desc = [ 51 | XBitField("marker",0xffffffffffffffffffffffffffffffff, 0x80 ), 52 | ShortField("len", None), 53 | ByteEnumField("type", 4, {0:"none", 1:"open",2:"update",3:"notification",4:"keep_alive"}), 54 | ] 55 | def post_build(self, p, pay): 56 | if self.len is None and pay: 57 | l = len(p) + len(pay) 58 | p = p[:16]+struct.pack("!H", l)+p[18:] 59 | return p+pay 60 | 61 | class BGPOptionalParameter(Packet): 62 | """Format of optional Parameter for BGP Open""" 63 | name = "BGP Optional Parameters" 64 | fields_desc = [ 65 | ByteField("type", 2), 66 | ByteField("len", None), 67 | StrLenField("value", "", length_from = lambda x: x.len), 68 | ] 69 | def post_build(self,p,pay): 70 | if self.len is None: 71 | l = len(p) - 2 # 2 is length without value 72 | p = p[:1]+struct.pack("!B", l)+p[2:] 73 | return p+pay 74 | def extract_padding(self, p): 75 | """any thing after this packet is extracted is padding""" 76 | return "",p 77 | 78 | class BGPOpen(Packet): 79 | """ Opens a new BGP session""" 80 | name = "BGP Open Header" 81 | fields_desc = [ 82 | ByteField("version", 4), 83 | ShortField("AS", 0), 84 | ShortField("hold_time", 0), 85 | IPField("bgp_id","0.0.0.0"), 86 | ByteField("opt_parm_len", None), 87 | PacketListField("opt_parm",[], BGPOptionalParameter, length_from=lambda p:p.opt_parm_len), 88 | ] 89 | def post_build(self, p, pay): 90 | if self.opt_parm_len is None: 91 | l = len(p) - 10 # 10 is regular length with no additional options 92 | p = p[:9] + struct.pack("!B",l) +p[10:] 93 | return p+pay 94 | 95 | class BGPAuthenticationData(Packet): 96 | name = "BGP Authentication Data" 97 | fields_desc = [ 98 | ByteField("AuthenticationCode", 0), 99 | ByteField("FormMeaning", 0), 100 | FieldLenField("Algorithm", 0), 101 | ] 102 | 103 | class BGPPathAttribute(Packet): 104 | "the attribute of total path" 105 | name = "BGP Attribute fields" 106 | fields_desc = [ 107 | FlagsField("flags", 0x40, 8, ["NA0","NA1","NA2","NA3","Extended-Length","Partial","Transitive","Optional"]), #Extened leght may not work 108 | ByteEnumField("type", 1, {1:"ORIGIN", 2:"AS_PATH", 3:"NEXT_HOP", 4:"MULTI_EXIT_DISC", 5:"LOCAL_PREF", 6:"ATOMIC_AGGREGATE", 7:"AGGREGATOR"}), 109 | ByteField("attr_len", None), 110 | StrLenField("value", "", length_from = lambda p: p.attr_len), 111 | ] 112 | def post_build(self, p, pay): 113 | if self.attr_len is None: 114 | l = len(p) - 3 # 3 is regular length with no additional options 115 | p = p[:2] + struct.pack("!B",l) +p[3:] 116 | return p+pay 117 | def extract_padding(self, p): 118 | """any thing after this packet is extracted is padding""" 119 | return "",p 120 | 121 | class BGPUpdate(Packet): 122 | """Update the routes WithdrawnRoutes = UnfeasiableRoutes""" 123 | name = "BGP Update fields" 124 | fields_desc = [ 125 | ShortField("withdrawn_len", None), 126 | FieldListField("withdrawn",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.withdrawn_len), 127 | ShortField("tp_len", None), 128 | PacketListField("total_path", [], BGPPathAttribute, length_from = lambda p: p.tp_len), 129 | FieldListField("nlri",[], BGPIPField("","0.0.0.0/0"), length_from=lambda p:p.underlayer.len - 23 - p.tp_len - p.withdrawn_len), # len should be BGPHeader.len 130 | ] 131 | def post_build(self,p,pay): 132 | wl = self.withdrawn_len 133 | subpacklen = lambda p: len ( str( p )) 134 | subfieldlen = lambda p: BGPIPField("", "0.0.0.0/0").i2len(self, p ) 135 | if wl is None: 136 | wl = sum ( map ( subfieldlen , self.withdrawn)) 137 | p = p[:0]+struct.pack("!H", wl)+p[2:] 138 | if self.tp_len is None: 139 | l = sum ( map ( subpacklen , self.total_path)) 140 | p = p[:2+wl]+struct.pack("!H", l)+p[4+wl:] 141 | return p+pay 142 | 143 | class BGPNotification(Packet): 144 | name = "BGP Notification fields" 145 | fields_desc = [ 146 | ByteEnumField("ErrorCode",0,{1:"Message Header Error",2:"OPEN Message Error",3:"UPDATE Messsage Error",4:"Hold Timer Expired",5:"Finite State Machine",6:"Cease"}), 147 | ByteEnumField("ErrorSubCode",0,{1:"MessageHeader",2:"OPENMessage",3:"UPDATEMessage"}), 148 | LongField("Data", 0), 149 | ] 150 | 151 | class BGPErrorSubcodes(Packet): 152 | name = "BGP Error Subcodes" 153 | Fields_desc = [ 154 | ByteEnumField("MessageHeader",0,{1:"Connection Not Synchronized",2:"Bad Message Length",3:"Bad Messsage Type"}), 155 | ByteEnumField("OPENMessage",0,{1:"Unsupported Version Number",2:"Bad Peer AS",3:"Bad BGP Identifier",4:"Unsupported Optional Parameter",5:"Authentication Failure",6:"Unacceptable Hold Time"}), 156 | ByteEnumField("UPDATEMessage",0,{1:"Malformed Attribute List",2:"Unrecognized Well-Known Attribute",3:"Missing Well-Known Attribute",4:"Attribute Flags Error",5:"Attribute Length Error",6:"Invalid ORIGIN Attribute",7:"AS Routing Loop",8:"Invalid NEXT_HOP Attribute",9:"Optional Attribute Error",10:"Invalid Network Field",11:"Malformed AS_PATH"}), 157 | ] 158 | 159 | bind_layers( TCP, BGPHeader, dport=179) 160 | bind_layers( TCP, BGPHeader, sport=179) 161 | bind_layers( BGPHeader, BGPOpen, type=1) 162 | bind_layers( BGPHeader, BGPUpdate, type=2) 163 | bind_layers( BGPHeader, BGPHeader, type=4) 164 | 165 | 166 | if __name__ == "__main__": 167 | interact(mydict=globals(), mybanner="BGP addon .05") 168 | 169 | -------------------------------------------------------------------------------- /scapy/contrib/igmp.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # scapy.contrib.description = IGMP/IGMPv2 4 | # scapy.contrib.status = loads 5 | 6 | 7 | # TODO: scapy 2 has function getmacbyip, maybe it can replace igmpize 8 | # at least from the MAC layer 9 | 10 | from scapy.all import * 11 | 12 | #-------------------------------------------------------------------------- 13 | def isValidMCAddr(ip): 14 | """convert dotted quad string to long and check the first octet""" 15 | FirstOct=atol(ip)>>24 & 0xFF 16 | return (FirstOct >= 224) and (FirstOct <= 239) 17 | 18 | #-------------------------------------------------------------------------- 19 | 20 | class IGMP(Packet): 21 | """IGMP Message Class for v1 and v2. 22 | 23 | This class is derived from class Packet. You need to "igmpize" 24 | the IP and Ethernet layers before a full packet is sent. 25 | a=Ether(src="00:01:02:03:04:05") 26 | b=IP(src="1.2.3.4") 27 | c=IGMP(type=0x12, gaddr="224.2.3.4") 28 | c.igmpize(b, a) 29 | print "Joining IP " + c.gaddr + " MAC " + a.dst 30 | sendp(a/b/c, iface="en0") 31 | 32 | Parameters: 33 | type IGMP type field, 0x11, 0x12, 0x16 or 0x17 34 | mrtime Maximum Response time (zero for v1) 35 | gaddr Multicast Group Address 224.x.x.x/4 36 | 37 | See RFC2236, Section 2. Introduction for definitions of proper 38 | IGMPv2 message format http://www.faqs.org/rfcs/rfc2236.html 39 | 40 | """ 41 | name = "IGMP" 42 | 43 | igmptypes = { 0x11 : "Group Membership Query", 44 | 0x12 : "Version 1 - Membership Report", 45 | 0x16 : "Version 2 - Membership Report", 46 | 0x17 : "Leave Group"} 47 | 48 | fields_desc = [ ByteEnumField("type", 0x11, igmptypes), 49 | ByteField("mrtime",20), 50 | XShortField("chksum", None), 51 | IPField("gaddr", "0.0.0.0")] 52 | 53 | #-------------------------------------------------------------------------- 54 | def post_build(self, p, pay): 55 | """Called implicitly before a packet is sent to compute and place IGMP checksum. 56 | 57 | Parameters: 58 | self The instantiation of an IGMP class 59 | p The IGMP message in hex in network byte order 60 | pay Additional payload for the IGMP message 61 | """ 62 | p += pay 63 | if self.chksum is None: 64 | ck = checksum(p) 65 | p = p[:2]+chr(ck>>8)+chr(ck&0xff)+p[4:] 66 | return p 67 | 68 | #-------------------------------------------------------------------------- 69 | def mysummary(self): 70 | """Display a summary of the IGMP object.""" 71 | 72 | if isinstance(self.underlayer, IP): 73 | return self.underlayer.sprintf("IGMP: %IP.src% > %IP.dst% %IGMP.type% %IGMP.gaddr%") 74 | else: 75 | return self.sprintf("IGMP %IGMP.type% %IGMP.gaddr%") 76 | 77 | #-------------------------------------------------------------------------- 78 | def igmpize(self, ip=None, ether=None): 79 | """Called to explicitely fixup associated IP and Ethernet headers 80 | 81 | Parameters: 82 | self The instantiation of an IGMP class. 83 | ip The instantiation of the associated IP class. 84 | ether The instantiation of the associated Ethernet. 85 | 86 | Returns: 87 | True The tuple ether/ip/self passed all check and represents 88 | a proper IGMP packet. 89 | False One of more validation checks failed and no fields 90 | were adjusted. 91 | 92 | The function will examine the IGMP message to assure proper format. 93 | Corrections will be attempted if possible. The IP header is then properly 94 | adjusted to ensure correct formatting and assignment. The Ethernet header 95 | is then adjusted to the proper IGMP packet format. 96 | """ 97 | 98 | # The rules are: 99 | # 1. the Max Response time is meaningful only in Membership Queries and should be zero 100 | # otherwise (RFC 2236, section 2.2) 101 | 102 | if (self.type != 0x11): #rule 1 103 | self.mrtime = 0 104 | 105 | if (self.adjust_ip(ip) == True): 106 | if (self.adjust_ether(ip, ether) == True): return True 107 | return False 108 | 109 | #-------------------------------------------------------------------------- 110 | def adjust_ether (self, ip=None, ether=None): 111 | """Called to explicitely fixup an associated Ethernet header 112 | 113 | The function adjusts the ethernet header destination MAC address based on 114 | the destination IP address. 115 | """ 116 | # The rules are: 117 | # 1. send to the group mac address address corresponding to the IP.dst 118 | if ip != None and ip.haslayer(IP) and ether != None and ether.haslayer(Ether): 119 | iplong = atol(ip.dst) 120 | ether.dst = "01:00:5e:%02x:%02x:%02x" % ( (iplong>>16)&0x7F, (iplong>>8)&0xFF, (iplong)&0xFF ) 121 | # print "igmpize ip " + ip.dst + " as mac " + ether.dst 122 | return True 123 | else: 124 | return False 125 | 126 | #-------------------------------------------------------------------------- 127 | def adjust_ip (self, ip=None): 128 | """Called to explicitely fixup an associated IP header 129 | 130 | The function adjusts the IP header based on conformance rules 131 | and the group address encoded in the IGMP message. 132 | The rules are: 133 | 1. Send General Group Query to 224.0.0.1 (all systems) 134 | 2. Send Leave Group to 224.0.0.2 (all routers) 135 | 3a.Otherwise send the packet to the group address 136 | 3b.Send reports/joins to the group address 137 | 4. ttl = 1 (RFC 2236, section 2) 138 | 5. send the packet with the router alert IP option (RFC 2236, section 2) 139 | """ 140 | if ip != None and ip.haslayer(IP): 141 | if (self.type == 0x11): 142 | if (self.gaddr == "0.0.0.0"): 143 | ip.dst = "224.0.0.1" # IP rule 1 144 | retCode = True 145 | elif isValidMCAddr(self.gaddr): 146 | ip.dst = self.gaddr # IP rule 3a 147 | retCode = True 148 | else: 149 | print "Warning: Using invalid Group Address" 150 | retCode = False 151 | elif ((self.type == 0x17) and isValidMCAddr(self.gaddr)): 152 | ip.dst = "224.0.0.2" # IP rule 2 153 | retCode = True 154 | elif ((self.type == 0x12) or (self.type == 0x16)) and (isValidMCAddr(self.gaddr)): 155 | ip.dst = self.gaddr # IP rule 3b 156 | retCode = True 157 | else: 158 | print "Warning: Using invalid IGMP Type" 159 | retCode = False 160 | else: 161 | print "Warning: No IGMP Group Address set" 162 | retCode = False 163 | if retCode == True: 164 | ip.ttl=1 # IP Rule 4 165 | ip.options=[IPOption_Router_Alert()] # IP rule 5 166 | return retCode 167 | 168 | 169 | bind_layers( IP, IGMP, frag=0, proto=2) 170 | 171 | 172 | -------------------------------------------------------------------------------- /scapy/data.py: -------------------------------------------------------------------------------- 1 | ## This file is part of Scapy 2 | ## See http://www.secdev.org/projects/scapy for more informations 3 | ## Copyright (C) Philippe Biondi 4 | ## This program is published under a GPLv2 license 5 | 6 | """ 7 | Global variables and functions for handling external data sets. 8 | """ 9 | 10 | import os,sys,re 11 | from dadict import DADict 12 | from error import log_loading 13 | 14 | ############ 15 | ## Consts ## 16 | ############ 17 | 18 | ETHER_ANY = "\x00"*6 19 | ETHER_BROADCAST = "\xff"*6 20 | 21 | ETH_P_ALL = 3 22 | ETH_P_IP = 0x800 23 | ETH_P_ARP = 0x806 24 | ETH_P_IPV6 = 0x86dd 25 | 26 | # From net/if_arp.h 27 | ARPHDR_ETHER = 1 28 | ARPHDR_METRICOM = 23 29 | ARPHDR_PPP = 512 30 | ARPHDR_LOOPBACK = 772 31 | ARPHDR_TUN = 65534 32 | 33 | 34 | # From net/ipv6.h on Linux (+ Additions) 35 | IPV6_ADDR_UNICAST = 0x01 36 | IPV6_ADDR_MULTICAST = 0x02 37 | IPV6_ADDR_CAST_MASK = 0x0F 38 | IPV6_ADDR_LOOPBACK = 0x10 39 | IPV6_ADDR_GLOBAL = 0x00 40 | IPV6_ADDR_LINKLOCAL = 0x20 41 | IPV6_ADDR_SITELOCAL = 0x40 # deprecated since Sept. 2004 by RFC 3879 42 | IPV6_ADDR_SCOPE_MASK = 0xF0 43 | #IPV6_ADDR_COMPATv4 = 0x80 # deprecated; i.e. ::/96 44 | #IPV6_ADDR_MAPPED = 0x1000 # i.e.; ::ffff:0.0.0.0/96 45 | IPV6_ADDR_6TO4 = 0x0100 # Added to have more specific info (should be 0x0101 ?) 46 | IPV6_ADDR_UNSPECIFIED = 0x10000 47 | 48 | 49 | 50 | 51 | MTU = 0x7fff # a.k.a give me all you have 52 | 53 | WINDOWS=sys.platform.startswith("win") 54 | 55 | 56 | # file parsing to get some values : 57 | 58 | def load_protocols(filename): 59 | spaces = re.compile("[ \t]+|\n") 60 | dct = DADict(_name=filename) 61 | try: 62 | for l in open(filename): 63 | try: 64 | shrp = l.find("#") 65 | if shrp >= 0: 66 | l = l[:shrp] 67 | l = l.strip() 68 | if not l: 69 | continue 70 | lt = tuple(re.split(spaces, l)) 71 | if len(lt) < 2 or not lt[0]: 72 | continue 73 | dct[lt[0]] = int(lt[1]) 74 | except Exception,e: 75 | log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e)) 76 | except IOError: 77 | log_loading.info("Can't open %s file" % filename) 78 | return dct 79 | 80 | def load_ethertypes(filename): 81 | spaces = re.compile("[ \t]+|\n") 82 | dct = DADict(_name=filename) 83 | try: 84 | f=open(filename) 85 | for l in f: 86 | try: 87 | shrp = l.find("#") 88 | if shrp >= 0: 89 | l = l[:shrp] 90 | l = l.strip() 91 | if not l: 92 | continue 93 | lt = tuple(re.split(spaces, l)) 94 | if len(lt) < 2 or not lt[0]: 95 | continue 96 | dct[lt[0]] = int(lt[1], 16) 97 | except Exception,e: 98 | log_loading.info("Couldn't parse file [%s]: line [%r] (%s)" % (filename,l,e)) 99 | f.close() 100 | except IOError,msg: 101 | pass 102 | return dct 103 | 104 | def load_services(filename): 105 | spaces = re.compile("[ \t]+|\n") 106 | tdct=DADict(_name="%s-tcp"%filename) 107 | udct=DADict(_name="%s-udp"%filename) 108 | try: 109 | f=open(filename) 110 | for l in f: 111 | try: 112 | shrp = l.find("#") 113 | if shrp >= 0: 114 | l = l[:shrp] 115 | l = l.strip() 116 | if not l: 117 | continue 118 | lt = tuple(re.split(spaces, l)) 119 | if len(lt) < 2 or not lt[0]: 120 | continue 121 | if lt[1].endswith("/tcp"): 122 | tdct[lt[0]] = int(lt[1].split('/')[0]) 123 | elif lt[1].endswith("/udp"): 124 | udct[lt[0]] = int(lt[1].split('/')[0]) 125 | except Exception,e: 126 | log_loading.warning("Couldn't file [%s]: line [%r] (%s)" % (filename,l,e)) 127 | f.close() 128 | except IOError: 129 | log_loading.info("Can't open /etc/services file") 130 | return tdct,udct 131 | 132 | 133 | class ManufDA(DADict): 134 | def fixname(self, val): 135 | return val 136 | def _get_manuf_couple(self, mac): 137 | oui = ":".join(mac.split(":")[:3]).upper() 138 | return self.__dict__.get(oui,(mac,mac)) 139 | def _get_manuf(self, mac): 140 | return self._get_manuf_couple(mac)[1] 141 | def _get_short_manuf(self, mac): 142 | return self._get_manuf_couple(mac)[0] 143 | def _resolve_MAC(self, mac): 144 | oui = ":".join(mac.split(":")[:3]).upper() 145 | if oui in self: 146 | return ":".join([self[oui][0]]+ mac.split(":")[3:]) 147 | return mac 148 | 149 | 150 | 151 | 152 | def load_manuf(filename): 153 | try: 154 | manufdb=ManufDA(_name=filename) 155 | for l in open(filename): 156 | try: 157 | l = l.strip() 158 | if not l or l.startswith("#"): 159 | continue 160 | oui,shrt=l.split()[:2] 161 | i = l.find("#") 162 | if i < 0: 163 | lng=shrt 164 | else: 165 | lng = l[i+2:] 166 | manufdb[oui] = shrt,lng 167 | except Exception,e: 168 | log_loading.warning("Couldn't parse one line from [%s] [%r] (%s)" % (filename, l, e)) 169 | except IOError: 170 | #log_loading.warning("Couldn't open [%s] file" % filename) 171 | pass 172 | return manufdb 173 | 174 | 175 | 176 | if WINDOWS: 177 | ETHER_TYPES=load_ethertypes("ethertypes") 178 | IP_PROTOS=load_protocols(os.environ["SystemRoot"]+"\system32\drivers\etc\protocol") 179 | TCP_SERVICES,UDP_SERVICES=load_services(os.environ["SystemRoot"] + "\system32\drivers\etc\services") 180 | MANUFDB = load_manuf(os.environ["ProgramFiles"] + "\\wireshark\\manuf") 181 | else: 182 | IP_PROTOS=load_protocols("/etc/protocols") 183 | ETHER_TYPES=load_ethertypes("/etc/ethertypes") 184 | TCP_SERVICES,UDP_SERVICES=load_services("/etc/services") 185 | MANUFDB = load_manuf("/usr/share/wireshark/wireshark/manuf") 186 | 187 | 188 | 189 | ##################### 190 | ## knowledge bases ## 191 | ##################### 192 | 193 | class KnowledgeBase: 194 | def __init__(self, filename): 195 | self.filename = filename 196 | self.base = None 197 | 198 | def lazy_init(self): 199 | self.base = "" 200 | 201 | def reload(self, filename = None): 202 | if filename is not None: 203 | self.filename = filename 204 | oldbase = self.base 205 | self.base = None 206 | self.lazy_init() 207 | if self.base is None: 208 | self.base = oldbase 209 | 210 | def get_base(self): 211 | if self.base is None: 212 | self.lazy_init() 213 | return self.base 214 | 215 | 216 | --------------------------------------------------------------------------------