We’ve sniffed some packets, dig down into packet layers and fields, and even sent some packets. Great job! It’s time to step up our game with Scapy and start really using some of the power Scapy contains. Please Note: this next example is for education and example only. Please be responsible on your network, especially at work!

Scapy Send/Receive Function

Let’s get familiar with the sr(), sr1(), srp(), and srp1() functions. Just like the send(), function, the ‘p’ at the end of the function name means that we’re sending at L2 instead of L3. The functions with a ‘1’ in them mean that Scapy will send the specified packet and end after receiving 1 answer/response instead of continuing to listen for answers/responses. I’ll reference both functions as sr(), but the examples will use the correct function.

Sending an ICMP Echo Request (ping)

The sr() function is used to send a packet or group of packets when you expect a response back. We’ll be sending an ICMP Echo Request (ping) since we can expect some sort of a response back from that. First let’s use the sniff() function to figure out what an ICMP Echo Request looks like in Scapy:

 

In the previous ARP example we changed the dst and src MAC address, but since we’re expecting a response back from another network device we’ll have to leave it up to Scapy to fill those in when it sends the packets. Since we’re building a L3 packet, we can actually leave off the Ether layer since Scapy will handle the generation of that. So let’s start building the IP and ICMP layers. To see the available fields for each layer, and what the default values will be if we don’t specify, use the ls('layer') command:

 

Most of those default values are fine, and src addresses will be filled out automatically by Scapy when it sends the packets. We can spoof those if desired, but again, since we’re expecting a response we need to leave those alone. We’ll be sending a L3 packet and we only expect one response, so we’ll build and send our ICMP packet using the sr1() function:

 

Scapy prints out the response packet

The ‘Received 84 packets’ is referring to the number of non-response packets Scapy sniffed while waiting for the response. It’s not anything to be alarmed about, but just note that on a busy host you might see a big number of packets there. We can also define the ICMP packet directly in the sr1() function like this:

 

We can save the response packet into a variable just like we do when creating a packet:

 

If we’re saving the response, Scapy won’t print it out by default

Two other Scapy functions related to sending and receiving packets are the srloop() and srploop(). The srloop() will send the L3 packet and continue to resend the packet after each response is received. The srploop() does the same thing except for… you guess it, L2 packets! This let’s us simulate the ping command, and with the count argument, we can also define the number of times to loop:

 

Saving the responses puts our packets into an array

As you can see, our Scapy skills are building and you might already have some ideas about how you can use these functions in your own network tools. In the next article, we’ll see how you can build an ARP monitor to keep an ear on the network for possible spoofed ARP replies.

 

Series Navigation<< Scapy p.05 – Sending our First Packet; ARP ResponseScapy p.07 – Monitoring ARP >>

This article has 11 comments

  1. Yixing Jiang

    Hi, I appreciate your work on Scapy. Could you answer this question I posted on StackOverflow? http://stackoverflow.com/questions/20184050/scapy-packet-sent-cannot-be-received

    Basically I sent packets with scapy, but I was not able to receive this packet with another python script.

    Thanks a lot!

    Yixing

    1. matw

      I submitted this answer to your StackOverflow question but I also want to post it here for other readers:

      Looks like you are using Scapy to send the UDP traffic to your localhost interface. In the send() function, specify the appropriate outbound interface to send the traffic out.

      Example:

      send(IP(dst=”127.0.0.1″,src=”111.111.111.111″)/UDP(dport=5005)/”Hello”),iface=”lo0″)

      On my computer, the lo0 is my local loopback interface. To see or set the default interface for Scapy, check out the bottom half of this post for more details on default interface in Scapy.

  2. guling

    hai Mat, maybe you remember me who ask you on your post about monitoring ARP, Im already can get ARP message that just come to my host, and than is it posible that scapy send request like voting? and than the other host reply the answer of the voting, I want to make a program that can verify all of arp message that come. when a host get arp reply (i get the information of arp message from your “monitoring arp” post), the host will send request to another host the right combination of MAC and IP, and the other host will check to its arp cache table

    thanks a lot

    1. Mat

      While it’s certainly possible to send IP and MAC addresses as a payload in a packet with scapy, I’m not exactly sure what you’re asking. I think you would need some sort of service running and listening on multiple machines for this voting request. You would need scapy running on a host to send packets when it receives an ARP request, and also a scapy or Twisted application running on the voting machine in order to receive the packet and check its arp cache table.

  3. Kashi

    Hi Mat,

    Is there a possible way of sending multiple packets in one request via scapy. Something like,
    sr(IP()/TCP()/[pkt1, pkt2, pkt3])

    As far as I know operation with array is not permitted. By using for loop on array scapy will send only one packet within one IP()/TCP() wrapper but the purpose is to send bunch of packets within one wrap.

    1. Mat

      Hi Kashi, sending multiple packets within the same IP and TCP header doesn’t really make sense with how packets work. The TCP header contains information (number of bytes in the difference between SEQ and ACK numbers). What are you trying to do? Can you combine the packet info into one payload? You may just want to send three individual packets though.

      1. Kashi

        Hi,

        I have been able to do the above task with the help of following code.

        req_array = []
        for i in range (10):
        req = Request()
        req_Array.append(req)
        pkt_str = “”.join(str(pkt) for pkt in req_Array)
        packet = IP()/TCP()/pkt_str
        sr(packet)

        I have monitored the traffic with wireshark and another monitor, It shows everything packet by packet and the machine I am sending these packets to, replies in a proper manner. I mean to say for each request it does send a reply.
        But wit “sr” function in scapy it does receive only one packet because all the requests were sent in one packet.
        Now the issue is to collect all the replies and match requests and responses. I have a screenshort of the whole procedure shared on the following link. By the way this is captured via Sercos Monitor. Screenshort via wireshark does look the same.
        https://ibb.co/kiOTWR

          1. Kashi

            Actually I have shared the screen short and the other machine is replying properly. But “sr” function of scapy just captures the first reply because only one packet was sent (regardless of how many packets/requests) were inside. Now I am trying to find a solution to capture all the responses somehow and match it with all the requests present in inside one packet (that was sent). I want to make request-response pair at the end.

Leave a Reply

Your email address will not be published. Required fields are marked *