sniff(filter="tcp and host 192.168.3.1", count=4, iface="eth0")ans = _ <-- sets ans equal to last result (which is an array) ans.summary() <-- displays summary info on the array contents s=sniff(filter="ICMP", count=2, iface="eth0") s.summary() ls req[0] print req[0]
Example: send a frame "eee" out interface eth2 five times:
sendp([eee]*5, iface="eth2")
>>> s = sniff(filter="host 10.3.4.4 and icmp[0]=8, count=1) >>> req = s[0] >>> resp_ip = IP(src=req.payload.dst, dst=req.payload.src) >>> resp_icmp = ICMP(type=0) >>> send(resp_ip/resp_icmp)
Note that the kernel would also automatically respond to the PING if it thinks it should (use iptables to suppress the reponse if necessary).
Normally, the Linux kernel takes care of setting up and sending and receiving network traffic. It automatically sets appropriate header values and even knows how to complete a TCP 3 way handshake. Uising the kernel services in this way is using a cooked
socket.
Scapy does not use these kernel services. It creates a raw
socket. The entire TCP/IP stack of the OS is circumvented. Because of this, Scapy give us compete control over the traffic. Traffic to and from Scapy will not be filtered by iptables. Also, we will have to take care of the TCP 3 way handshake ourselves.
If we use Scapy to craft a TCP SYN and send it, watching traffic using TCPdump, we will see the following three packets:
Where did the RST come from, if we didn't make it in Scapy? Our kernel sent it automatically. It did not send the SYN (Scapy did using a raw socket), so when the kernel saw the SYN/ACK it responded with a RST.
This behavior is probably undesirable. To stop it, we can use iptables on our host to suppress outbound RSTs to the dest we are working with. We'd have a similar problem with UDP; a UDP packet coming back to us would cause our kernel to generate an ICMP port unreachable message. even though we might be expecting the UDP packet in Scapy. So we might want to use iptables commands like the following:
iptables -A OUTPUT -p tcp --tcp-flags RST RST -s {our IP} -d {dest IP} -dport {port we're sending from} -j DROP iptables -A OUTPUT -s {our IP} -d {dest IP} -p ICMP --icmp-type port-unreachable -j DROP
Client and server variable names: c_ip = IP, c_port = port, c_seq = seq #, c_ack = ack # s_ip = IP, s_port = port, s_seq = seq #, s_ack = ack # Handshake: c_ip:c_port -> s_ip:s_port, SYN, c_seq, c_ack s:ip:s_port -> c_ip:c_port, SYN/ACK, s_seq, s_ack=(c_seq + 1) c_ip:c_port -> s_ip:s_port, ACK, c_seq + 1, c_ack=(s_seq + 1)
Note that from the client side we know everything in advance except the s_seq, which we must learn by listening for it.
If we send the SYN from Scapy using the sr1() method, we can have Scapy parse the s_seq out of the return packet for us:
synack=sr1(ip/syn) my_ack=synack.seq + 1
#!/usr/bin/python from scapy.all import * ip=IP(src="10..1.2.3", dst="10.2.3.4") SYN=TCP(sport=1500, dport=80, flags="S", seq=100) SYNACK=sr1(ip/SYN) my_ack = SYNACK.seq + 1 ACK=TCP(sport=1050, dport=80, flags="A", seq=101, ack=my+ack) send(ip/ACK) payload="stuff" PUSH=TCP(sport=1050, dport=80, flags="PA", seq=11, ack=my_ack) send(ip/PUSH/payload)
Note that this kind of script could be used simply to do the handshake, leaving the connection open for whatever traffic needs to be sent manually or by other means.
Many thanks to Judy Novak and SANS for introducing me to Scapy.