{"id":44,"date":"2009-01-21T03:50:00","date_gmt":"2009-01-21T03:50:00","guid":{"rendered":"https:\/\/freezion.com\/2009\/01\/21\/scapy-notes\/"},"modified":"2009-01-21T03:50:00","modified_gmt":"2009-01-21T03:50:00","slug":"scapy-notes","status":"publish","type":"post","link":"https:\/\/freezion.com\/?p=44","title":{"rendered":"Scapy Notes"},"content":{"rendered":"<p>Scapy is an &#8220;interactive packet manipulation program&#8221; written in python. It basically is a packet workshop framework which allows one to craft their own packets from scratch to match a variety of protocols, then send them on the wire and capture the results for analysis. Since it is written in python, it allows one to essentially create any number of tools, including scanners, fuzzers, DoS tools, etc. More info on it can be found at the <a href=\"http:\/\/www.secdev.org\/projects\/scapy\/\">scapy home page<\/a>.<\/p>\n<p><span style=\"font-weight: bold;\">Basic Usage<\/span><br \/>\nWhen scapy is run from the command line, it loads the scapy modules and then drops you at the python shell prompt. This is useful for a number of reasons, but primary among them is that this means anything you can do in python, you can do in scapy as well. For the moment though, we&#8217;re going to focus solely on the scapy specific modules.<\/p>\n<p><span style=\"font-weight: bold;\">Building a Packet<\/span><br \/>\nScapy makes it extremely easy to build a packet, here&#8217;s what it looks like:<\/p>\n<p>First, we call scapy interactively:<\/p>\n<pre>[root@snsvc]# scapy\nWelcome to Scapy (v1.1.1 \/ f88d99910220)\n&gt;&gt;&gt;<\/pre>\n<p>Next, we create the IP frame, then the TCP packet:<\/p>\n<pre>&gt;&gt;&gt; a=IP()\n&gt;&gt;&gt; b=TCP()<\/pre>\n<p>Now we combine the two to create the TCP\/IP datagram:<\/p>\n<pre>&gt;&gt;&gt; c=a\/b<\/pre>\n<p>We can use scapy&#8217;s <span style=\"font-style: italic;\">ls<\/span> command to view the contents of the packet:<\/p>\n<pre>&gt;&gt;&gt; ls(c)\nversion    : BitField             = 4               (4)\nihl        : BitField             = None            (None)\ntos        : XByteField           = 0               (0)\nlen        : ShortField           = None            (None)\nid         : ShortField           = 1               (1)\nflags      : FlagsField           = 0               (0)\nfrag       : BitField             = 0               (0)\nttl        : ByteField            = 64              (64)\nproto      : ByteEnumField        = 6               (0)\nchksum     : XShortField          = None            (None)\nsrc        : Emph                 = '127.0.0.1'     (None)\ndst        : Emph                 = '127.0.0.1'     ('127.0.0.1')\noptions    : IPoptionsField       = ''              ('')\n--\nsport      : ShortEnumField       = 20              (20)\ndport      : ShortEnumField       = 80              (80)\nseq        : IntField             = 0               (0)\nack        : IntField             = 0               (0)\ndataofs    : BitField             = None            (None)\nreserved   : BitField             = 0               (0)\nflags      : FlagsField           = 2               (2)\nwindow     : ShortField           = 8192            (8192)\nchksum     : XShortField          = None            (None)\nurgptr     : ShortField           = 0               (0)\noptions    : TCPOptionsField      = {}              ({})<\/pre>\n<p><span style=\"font-weight: bold;\">Changing Packet Details<\/span><br \/>\nNow, if we want to change any of the fields in the packet, we can do so by altering their values. For example, to change the IP destination to 192.168.1.1 and set the TCP destination port to 443, we do the following:<\/p>\n<pre>&gt;&gt;&gt; a.dst='192.168.1.1'\n&gt;&gt;&gt; b.dport=443<\/pre>\n<p>Now we recreate the TCP\/IP packet again, and view the changes using <span style=\"font-style: italic;\">ls<\/span>:<\/p>\n<pre>&gt;&gt;&gt; c=a\/b\n&gt;&gt;&gt; ls(c)\nversion    : BitField             = 4               (4)\nihl        : BitField             = None            (None)\ntos        : XByteField           = 0               (0)\nlen        : ShortField           = None            (None)\nid         : ShortField           = 1               (1)\nflags      : FlagsField           = 0               (0)\nfrag       : BitField             = 0               (0)\nttl        : ByteField            = 64              (64)\nproto      : ByteEnumField        = 6               (0)\nchksum     : XShortField          = None            (None)\nsrc        : Emph                 = '192.168.1.3'   (None)\ndst        : Emph                 = '192.168.1.1'   ('127.0.0.1')\noptions    : IPoptionsField       = ''              ('')\n--\nsport      : ShortEnumField       = 20              (20)\ndport      : ShortEnumField       = 443             (80)\nseq        : IntField             = 0               (0)\nack        : IntField             = 0               (0)\ndataofs    : BitField             = None            (None)\nreserved   : BitField             = 0               (0)\nflags      : FlagsField           = 2               (2)\nwindow     : ShortField           = 8192            (8192)\nchksum     : XShortField          = None            (None)\nurgptr     : ShortField           = 0               (0)\noptions    : TCPOptionsField      = {}              ({})<\/pre>\n<p>Note that even though we didn&#8217;t change the IP source, the value has changed. This is because scapy determined which interface would be used to send the packet to the destination we configured, and changed the source to that interface&#8217;s address for us. We can override this if desired.<\/p>\n<p><span style=\"font-weight: bold;\">Sending the Packet<\/span><br \/>\nWe use the sr() function to send the data across the wire. This function sends the packet, sniffs the response, and matches sent packets with the received responses. It works at layer 3, and will return the whole result of a probe.<\/p>\n<pre>&gt;&gt;&gt; sr(c)\nBegin emission:\n...Finished to send 1 packets.\n*\nReceived 4 packets, got 1 answers, remaining 0 packets\n(, )<\/pre>\n<p><span style=\"font-weight: bold;\">Viewing Results<\/span><br \/>\nWe can view the results by assigning them to variables:<\/p>\n<pre>&gt;&gt;&gt; res,unans=_\n&gt;&gt;&gt; res.nsummary()\n0000 IP \/ TCP 192.168.1.3:ftp_data &gt; 192.168.1.1:https S ==&gt; IP \/ TCP 192.168.1.1:https &gt; 192.168.1.3:ftp_data SA \/ Padding<\/pre>\n<p>Here we see we sent a SYN packet to port 443, and received a SYN\/ACK packet back from the destination. We also see there was some Padding added to the SYN\/ACK. We can view the information in the padding by accessing the results list directly:<\/p>\n<pre>&gt;&gt;&gt; res[0][1]\n&gt;&gt;<\/pre>\n<p>Scripted Usage<br \/>\nBecause scapy is written in python, it can be used from within any python script simply by using the <span style=\"font-style: italic;\">import scapy<\/span> statement.<br \/>\nFor example, here&#8217;s a simple script to perform a TCP SYN scan of ports 0-1024 on a given host (provided as a parameter to the script):<\/p>\n<pre>#!\/usr\/bin\/env python\nimport sys\nfrom scapy import sr,IP,TCP,conf\nconf.verb = 0\ndstip = sys.argv[1]\n\nprint \"nBeginning scan of \"+dstip\nres,unans = sr(IP(dst=dstip)\/TCP(dport=[(0,1024)]),timeout=1)\nif res:\n   print \"nReceived answers from the following ports:n\"\n   for s,r in res:\n      print r.sprintf(\"%TCP.sport%\")\nprint \"nScan completedn\"<\/pre>\n<p>And here&#8217;s the results of running this:<\/p>\n<pre>[root@snsvc]# .\/scanner 192.168.1.1\n\nBeginning scan of 192.168.1.1\n\nReceived answers from the following ports:\n\ntelnet\nhttp\nhttps\n\nScan completed<\/pre>\n<p><span style=\"font-weight: bold;\">Install\/Config Notes<\/span><br \/>\n<span style=\"font-style: italic;\">&#8220;Error during evauluation of config file&#8221;<\/span><br \/>\nWhen running scapy from inside other python scripts, you may encounter the following error message:<\/p>\n<pre>ERROR: Error during evaluation of config file [None]\nTraceback (most recent call last):\nFile \"\/usr\/lib\/python2.4\/site-packages\/scapy.py\", line 12183, in read_config_file\nexecfile(configfile)<\/pre>\n<p>Not very helpful, but easy to fix. The problem is that scapy is looking for a config file which doesn&#8217;t exist. The good news is that one just has to be present, no configuration is required. To fix this, simply do the following:<\/p>\n<pre># touch ~\/.scapy_startup.py<\/pre>\n<p><span style=\"font-style: italic;\">Using the Loopback Interface<\/span><br \/>\nThe loopback interface is a special interface, in that 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.<\/p>\n<p>In order to use the loopback interface, you need to send your packets using PF_INET\/SOCK_RAW instead of PF_PACKET\/SOCK_RAW. This can be done by changing the supersocket used by scapy, which is accessed via the configuration.<\/p>\n<p>The default scapy values for sockets are as follows:<\/p>\n<pre>+------------------------+----------------+\n| Configuration Variable | Default Value  |\n+------------------------+----------------+\n| L2listen               | L2ListenSocket |\n+------------------------+----------------+\n| L2socket               | L2Socket       |\n+------------------------+----------------+\n| L3socket               | L3PacketSocket |\n+------------------------+----------------+<\/pre>\n<p>To use the loopback interface, change the L3socket setting to L3RawSocket.<br \/>\nThis can be done using the following command (either via the scapy CLI or inside a script):<\/p>\n<pre>conf.L3socket=L3RawSocket<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Scapy is an &#8220;interactive packet manipulation program&#8221; written in python. It basically is a packet workshop framework which allows&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[19,22,51],"class_list":["post-44","post","type-post","status-publish","format-standard","hentry","category-tech","tag-fun","tag-howto","tag-scapy"],"_links":{"self":[{"href":"https:\/\/freezion.com\/index.php?rest_route=\/wp\/v2\/posts\/44","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/freezion.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/freezion.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/freezion.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/freezion.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=44"}],"version-history":[{"count":0,"href":"https:\/\/freezion.com\/index.php?rest_route=\/wp\/v2\/posts\/44\/revisions"}],"wp:attachment":[{"href":"https:\/\/freezion.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=44"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/freezion.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=44"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/freezion.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=44"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}