sending few packet at the same time and get answer - scapy

I'm trying to sent 4 packet and get for each one a answer(like the "ping" tool on CMD), how do i do that?
the packet:
packet = IP(dst = "www.google.com")/ICMP()/"hi"
I know that i can sent like this: send(packet, count=4) but I need the answer to all of them.
sr1(packet) is sent it just one time and with sr() I didn't realize how I can use it to sent 4 packet and get answer...
I try to look here http://www.secdev.org/projects/scapy/files/scapydoc.pdf on page 35
Thank you very much!!!

First of all sr() is for sending packets and receiving answers while sr1() is a variant that only returns the first answer for the packet sent. You can find more info here and of course from the python's or scapy's interactive console by typing help(sr1)(or any other function) you can view details about the function:
sr1(x, filter=None, iface=None, nofilter=0, *args, **kargs)
Send packets at layer 3 and return only the first answer
nofilter: put 1 to avoid use of bpf filters
retry: if positive, how many times to resend unanswered packets
if negative, how many times to retry when no more packets are answered
timeout: how much time to wait after the last packet has been sent
verbose: set verbosity level
multi: whether to accept multiple answers for the same stimulus
filter: provide a BPF filter
iface: listen answers only on the given interface
Now to send those packets 4 times in a row and get an answer for each one of them you could simply try:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from scapy.all import *
packet = IP(dst = "www.google.com")/ICMP()/"hi"
for _ in range(4):
answer = sr1(packet)
answer.show()

Related

Scapy sniffing the same packet that I just sent

I have an issue where if I send a packet and then sniff for a response to that sent packet, my s.sniff() function returns the packet that I just sent!
ex:
def sendOneFast(pkt):
"""
Function: sendOneFast
Purpose: Opens a layer 2 socket on interface, sends a packet on that socket.
pkt -> Scapy packet to be sent
"""
s = conf.L2socket(iface='Intel(R) Ethernet Connection (2) I219-LM #2')
s.send(pkt)
l = s.sniff(iface = 'Intel(R) Ethernet Connection (2) I219-LM #2', timeout = 0.03)
return l
When i call this function for a packet, 'l' will be the packet that I sent! Note: this works correctly when I run the same code in Linux, but exhibits this behavior in Windows 7/10.
I have Python 2.7.X installed with the latest Scapy. What could be the root cause of this problem?
I think that both behaviors are "normal" (the root cause of the difference probably lies in Scapy's architecture-dependent internals), but you cannot assume that you will or won't see your own packet in that case (it could be called an undefined behavior).
Out of curiosity, which version exactly are you using? The latest == the current development, the latest stable release (2.4.0) or the current version packaged somewhere?
By the way, I'm not sure what exactly you are trying to do, but are you aware there exists sr(), srp() (and sr1(), srp1()) if you want to catch answers to your packets?

Can I intercept network packets with a raw socket (not only sniff)?

This is my first time using raw sockets (yes, I need to use them as I must modify a field inside a network header) and all the documentation or tutorials I read describe a solution to sniff packets but that is not exactly what I need. I need to create a script which intercepts the packet, process it and sends it further to the destination, i.e. the packets should not reach the destination unless my script decides to.
In order to learn, I created a small prototype which detects pings and just prints "PING". I would expect ping not to work as I intercept the packets and I don't include the logic to send them to its destination. However ping is working (again, it seems as it is just sniffing/mirroring packets). My goal is that the ping packets are "trapped" in my script and I don't know how to do that. This is what I do in my current python script (I avoid writing how I do the decode for simplicity)
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003))
sock.bind((eth0, 0))
packet = sock.recvfrom(65565)
decode_eth(packet)
decode_ip(packet)
if (ipheader.ip_proto == 1):
print("\nPING")
Can somebody explain how can I achieve my goal or point me to the right documentation?
Your description seems to be different from what your title suggest. My understanding is that you want to receive, modify and possibly drop incoming network packets. And this is to be done on Linux. In that case I suggest you use a netfilter prerouting hook, which will make things a lot simpler (and likely more stable). Netfilter is well documented, a nice overview including information related to your requirements can be seen here. The important function to use is nf_register_hook(), read the answer to this question to get an idea of how to set things up.
I suppose that your Linux box is configured as a router (not a bridge). The packet will pass through your Linux because you have enabled IP Forwarding. So there are two solution:
Solution 1:
Disable IP Forwarding and then receive the packet from one interface and do the appropriate task (forwarding to another interface or dropping it).
Solution 2:
Use NetFilterQueue.
Install it on your Linux box (Debian/Ubuntu in my example):
apt-get install build-essential python-dev libnetfilter-queue-dev
Use iptables to send packets coming from input interface (eth0 in my example):
iptables -I INPUT -i eth0 -j NFQUEUE --queue-num 1
Run this script to handle packets forwarded to the Queue No.1 :
from netfilterqueue import NetfilterQueue
def print_and_accept(pkt):
print pkt
pkt.accept()
nfqueue = NetfilterQueue()
nfqueue.bind(1, print_and_accept)
try:
nfqueue.run()
except KeyboardInterrupt:
print
Note that pkt.drop() cause dropping the packet. Also you should accept/drop every packet.

How to send multiple packets in scapy

I am aware this has been asked before. However I am unclear on how to construct the command in order to accomplish my task and the previous question was never marked as answered. I need to send multiple packets with scapy and my use case is to send DNS queries to a remote server server using UDP. This is the command that I need to use:
sr1(IP(dst="192.168.155.128")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.oreilly.com")))
In the above example sr1 means send a packet at layer 3 but there are more function definitions to send packets. See Here. The remaining parts in between the braces is how to assemble a DNS query packet with scapy for an A record.
But what I want to do is send more than one packet in a single command. The previous question had a suggested answer of this:
sendp(p, iface=eth0, inter=1 , count=x )
Where p is your packet or a list of packets and count is the number of times to repeat the send operation.
This is where I am lost. If this is the correct answer, how would I integrate that into my command and what would it look like?
Thanks in advance!
Working solution: In the above example you will need to use a different function definition to send the packets.
Replace sendp with send, (sendp sends at layer2, send uses layer 3, and sr1 is designed to send only one packet) and place " , count=x" in between the last two closing braces. Where x = the number of packets you want to send. Running from the scapy prompt the command and output should look like this:
>>> send(IP(dst="192.168.155.128")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.oreilly.com")), count=100 )
....................................................................... .............................
Sent 100 packets.
>>>
A simple ICMP packet can also be sent can also be constructed. In this example we are sending 100 ICMP packets.
>>> send(IP(dst="192.168.155.128")/ICMP()/"testICMPpacket", count=100 )
....................................................................... .............................
Sent 100 packets.
>>>

Sending raw data in Scapy does not work correctly

I use Scapy to create an initial OpenVPN packet and send it to OpenVPN server (acting as a client). OpenVPN part of the packet I'm just reusing from old captured connection, but its irrelevant here.
Thing is, I add a payload of 42bytes but for some reason when I capture packet with Wireshark, I can see 84bytes of OpenVPN stuff. Last half of that is correct payload I sent, but I can't figure out what is the first half. All other layers (Ethernet, IP, UDP) have correct size.
#!/usr/bin/env python
import socket
from scapy.all import *
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
mysocket.connect(('192.168.138.129', 1194))
mystream=StreamSocket(mysocket)
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
etherLoad = len(ascapypacket.getlayer(Ether)) # display size
print etherLoad
ipLoad = len(ascapypacket.getlayer(IP)) # display size
print ipLoad
udpLoad = len(ascapypacket.getlayer(UDP)) # display size
print udpLoad
rawLoad = len(ascapypacket.getlayer(Raw)) # display size
print rawLoad
mystream.send(ascapypacket)
I made an image. Here you can see green stuff is correct - first part is IP and UDP layers, and 2nd green part is my OpenVPN payload, but I don't understand what is the red part.
Edit: If I don't send that Raw payload I still get those 42 bytes for some reason.
You've created an ordinary UDP datagram socket:
mysocket=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
This socket manages the ethernet, IP & UDP layers by itself, with guidance from the user through various auxiliary methods and arguments, such as the connect method you've in fact used in your code snippet:
mysocket.connect(('192.168.138.129', 1194))
Its various send methods, even when encapsulated as part of a scapy's StreamSocket object, are expecting to receive as their "data-to-send" argument just the application payload layered above the UDP layer.
However, you're passing on to it the entire protocol stack payload, i.e. the ethernet, IP & UDP headers, which is misinterpreted to be part of the payload data that you wish to send to the other side:
ascapypacket=Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)/Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")
Thus, the data you've marked in red is actually the payload data you've yourself set, before it is followed by the OpenVPN part:
Ether()/IP(dst="192.168.138.129")/UDP(dport=1194, len=50)
The first part marked in green, which you've mistakenly identified as created by yourself, is actually generated by the socket object (the kernel, the appropriate driver and the underlying hardware, to be more accurate).
Depending on your needs, you should either instantiate your socket as a raw one:
mysocket = socket(socket.AF_PACKET, socket.SOCK_RAW)
or set the payload accordingly as just the OpenVPN data:
ascapypacket=Raw(load="\x38\x81\x38\x14\x62\x1d\x67\x46\x2d\xde\x86\x73\x4d\x2c\xbf\xf1\x51\xb2\xb1\x23\x1b\x61\xe4\x23\x08\xa2\x72\x81\x8e\x00\x00\x00\x01\x50\xff\x26\x2c\x00\x00\x00\x00\x00")

Calculate Sent and Received PING Packets at run-time in Linux

I have to calcuate sent and received PING packets at run-time in Linux. Now in Linux, even with verbose, nothing gets printed if packets are not received. Prints are only for successful replies, destination host unreachable.
How can sent and received packets be seen at run-time on the terminal? Any method by which this can be accomplished?
The simplest solution - if you want to see all sends and all receives is to actually make the source do that. The source for the ping command is widely available and can be edited to make it do what you want.
That said, if you don't want to actually edit the source, because it doesn't suit, you really should use the -c option, for the count of packets to send, and use the command to send one at a time. The return code from the command can be used to determine if a packet was seen, and you can use (roughly) the time that the command started at for the origin time of the packet.
Bear in mind ping it quite deterministic in it's behaviour. By default, it sends one packet per second, so you should be easily able to do the math based on how long it runs for and the count of packets you tried to use.

Resources