Member of the official account: Wanger
What is a scapy
Scapy is a powerful interactive packet handler. It can forge or decode packets of various protocols, send online, capture, match requests and responses, etc. It can easily handle most classic tasks such as scanning, tracing routing, probing, unit testing, attack or network discovery, and it can replace some parts of Hping, ARpspoof, ARP-SK, ARping, P0F and even Nmap, tcpdump and Tshark. It also does well at many other specific tasks that other tools can’t handle, such as sending invalid frames, combination techniques (VLAN jump + ARP cache poisoning, VOIP decoding over WEP encrypted channels, etc.)
Install scapy
Just install PIP. I’m using python3
pip3 install scapy
Copy the code
Basic use of SCAPY
You can use ls() to view the protocols supported by SCAPy by typing scapy into the shellUse LSC () to see the supported functions of SCAPyYou can also use ls() to get the parameters contained in the protocol
Sending and receiving packets
send
– Sends packets at layer 3 (Scapy creates layer 2 headers) without receiving any packets.
loop
The default parameter is 0, and if it has a value other than 0, packets will be sent in a loop until Ctrl-c is pressed.count
Can be used to set the exact number of packets to send.inter
Can be used to set the number of seconds between each packet.
> > > send (DST = '8.8.8.8') (IP/TCP (dport = 53, flags = 'S')). 1 packets Sent. > > > > > > send (DST = '8.8.8.8') (IP/TCP (dport = 53, flags='S'), count=10) .......... 10 packets Sent. > > > > > > send (IP/TCP (DST = '8.8.8.8') (dport = 53, flags = 'S'), loop = 1)... [... snipped ...] Sent 1503 packets.Copy the code
sendp
- Same as send (), but sends packets at layer 2 (the layer 2 header must be supplied) and receives no packets.
- use
iface
Send packets to the Settings screen. (If not set, it will be usedconf.iface
The value of the)
> > > sendp (Mr (s)/IP (DST = "2", TTL = (1, 4)), iface = "eth0")... Sent packets. >>> Sendp ("I'm travelling on Ethernet", iface="eth0", loop=1, Intel = 0.2) > > > sendp (rdpcap ("/TMP/pcapfile ") # tcpreplay... Sent 11 packets.Copy the code
sr
- Send the packet and receive the response.
- Sr () returns two lists, the first containing those that responded and the second containing those that did not.
>>> sr(IP(DST ="60.205.177.168")/TCP(dport=[21,22,23])) Begin emission: Finished sending 3 packets.... * *... ^C Received 36 packets, got 2 answers, remaining 1 packets (<Results: TCP:2 UDP:0 ICMP:0 Other:0>, <Unanswered: TCP:1 UDP:0 ICMP:0 Other:0>) >>> ANS,unans=_ >>> Unans. summary() IP/TCP 172.17.51.80: ftP_data > 60.205.177.168: Telnet S > > > ans [0] (< IP frag = 0 proto = TCP DST = 60.205.177.168 | < TCP dport = FTP | > >, <IP version=4 IHL =5 tos=0x0 Len =40 ID =53978 FLAGS =DF FRAg =0 TTL =64 proto= TCP chksum= 0x9A1e SRC =60.205.177.168 DST = 172.17.51.80 | < TCP sport = FTP dport = ftp_data seq = 0 ack = 1 dataofs = 5 reserved window = 0 = 0 flags = RA chksum xe1cf = 0 Urgptr | = 0 > >) > > > ans [0] [0] < IP frag = 0 proto = TCP DST = 60.205.177.168 | < TCP dport = FTP | > >Copy the code
sr1
- Send all packets and log only the first response.
>>> p=sr1(IP(dst="www.baidu.com")/ICMP()/"asdqwe")
Begin emission:
Finished sending 1 packets.
.*
Received 2 packets, got 1 answers, remaining 0 packets
Copy the code
srloop
- Send in a loop, receive and display the response.
- This function returns several packets and responses, as well as none.
>>> Packet = IP(DST ='60.205.177.168')/ICMP() >>> SRloop (packet) RECV 1: IP/ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0 RECV 1: IP/ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0 RECV 1: IP/ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0 RECV 1: IP/ICMP 60.205.177.168 > 172.17.51.80 echo-reply 0 ^C Sent 4 packets, received 4 packets. 100.0% hits. TCP:0 UDP:0 ICMP:9 Other:0>, <PacketList: TCP:0 UDP:0 ICMP:0 Other:0>)Copy the code
Create packets using Scapy
- The creation of Scapy packets is consistent with the hierarchical approach in the network.
- The basic building blocks of a packet are one layer, while the entire packet is built by stacking the layers on top of each other.
- Scapy constructs packets by defining data packet headers for each protocol on different layers of TCP/IP and then stacking these layers in sequence.
Create a packet in a row
> > > packet = Mr (S)/IP/TCP (DST = '8.8.8.8') (dport = 53, flags = 'S')Copy the code
Create each layer separately and stack them using the ‘/’ operator
> > > l2 = Mr () > > > l3 = IP (DST = '8.8.8.8/30') > > > l4 = TCP (dport = 53, flags = 'S') > > > packet = l2 / l3 / l4Copy the code
Scapy IP notation
Scapy accepts normal IP representation, CIDR representation, and host name.
> > > IP packet = (DST = '8.8.8.8') > > > IP packet = (DST = 'scanme.nmap.org') > > > IP packet = (DST = '8.8.8.8/30') > > > [for a A packet in] [< IP DST = 8.8.8.8 | >, < IP DST = 8.8.8.9 | >, < IP DST = 8.8.8.10 | >, < IP DST = 8.8.8.11 | >] > > > IP packet = (DST = 'egadz.metasploit.com/30')Copy the code
Create a set of packets
We can use Scapy to create a set of packets
> > > PKTS = IP (TTL = [1,3,5, (7, 10)])/TCP () > > > [PKT for PKT PKTS] in [< IP frag = 0 TTL = 1 proto = TCP | < TCP | > >, <IP frag=0 ttl=3 proto=tcp |<TCP |>>, <IP frag=0 ttl=5 proto=tcp |<TCP |>>, <IP frag=0 ttl=7 proto=tcp |<TCP |>>, <IP frag=0 ttl=8 proto=tcp |<TCP |>>, <IP frag=0 ttl=9 proto=tcp |<TCP |>>, IP frag = 0 < TTL = 10 proto = TCP | < TCP | > >] > > > IP packet = (DST = "192.168. *. 1-10")/TCP (dport = (0100)) > > > [for a packet in a] [< IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 0 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = tcpmux | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = compressnet | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 3 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport | = 4 > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = rje | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 6 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = echo | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 8 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = the discard | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | | < TCP dport = 10 > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = systat | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 12 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = the daytime | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 14 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = netstat | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 16 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = qotd | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = MSP | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = chargen | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = ftp_data | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = FTP | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = SSH | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = Telnet | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = LMTP | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = SMTP | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 26 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = nsw_fe | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 28 | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = msg_icp | > >, < IP frag = 0 proto = TCP DST = 192.168.1.1 | < TCP dport = 30 | > >, .Copy the code
Checking packets
Gets a detailed description of the packet and the data type
>>> packet = IP()/TCP() >>> ls(packet) version : BitField = 4 (4) ihl : BitField = None (None) tos : XByteField = 0 (0) len : ShortField = None (None) id : ShortField = 1 (1) flags : FlagsField = 0 (0) frag : BitField = 0 (0) ttl : ByteField = 64 (64) proto : ByteEnumField = 6 (0) chksum : XShortField = None (None) src : Emph = '127.0.0.1 (None) DST: Emph =' 127.0.0.1 '(' 127.0.0.1) options: PacketListField = [] ([]) / - snipped -Copy the code
show
Display detailed baotou
>>> packet.show() ###[ IP ]### version= 4 ihl= None tos= 0x0 len= None id= 1 flags= frag= 0 ttl= 64 proto= tcp chksum= None SRC = 127.0.0.1 DST = 127.0.0.1 \options\ ###[TCP]### sport= ftp_data dport= HTTP seq= 0 ACK = 0 dataofs= None reserved= 0 flags= S window= 8192 chksum= None urgptr= 0 options= []Copy the code
show2
Similar to show (), but you can assemble packets and calculate checksums and IHL(header length, minimum 5).
>>> packet.show2() ###[ IP ]### version= 4 ihl= 5 tos= 0x0 len= 40 id= 1 flags= frag= 0 ttl= 64 proto= tcp chksum= 0x7CCD SRC = 127.0.0.1 DST = 127.0.0.1 \options\ ###[TCP]### sport= ftp_data dport= HTTP seq= 0 ACK = 0 dataofs= 5 reserved= 0 flags= S window= 8192 chksum= 0x917c urgptr= 0 options= []Copy the code
summary
Displays a short summary of the packet
>>> packet. Summary () 'IP/TCP 127.0.0.1:ftp_data > 127.0.0.1: HTTP S'Copy the code
Interacts with fields inside the packet
> > > Mr (DST = "d8:55: a3: fe: 80-78")/IP (DST = "8.8.8.8") < Mr DST = d8:55: a3: fe: 80-78 type = IPv4 | < IP DST = 8.8.8.8 | > > > > > Packet = _ > > > packet. DST 'd8:55: a3: fe: 80:78' > > > packet [IP]. DST '8.8.8.8'Copy the code
Check whether there are layers in the packet
Haslayer method
>>> if packet.haslayer(IP): ... : print (packet[IP].dst) ... : 8.8.8.8Copy the code
Using the in construct
>>> pkt = IP()/TCP()/DNS()
>>> DNS in pkt
True
Copy the code
The sprintf Scapy
sprintf()
Methods are one of the most powerful features of Scapy and come in handy when writing custom tools.sprintf
The format string is populated with values from the packet, just like sprintf in the C library, except that the format string is populated with field values from the packet.
>>> packet.sprintf("Ethernet source is %Ether.src% and IP proto is %IP.proto%") 'Ethernet source is 00:16:3e:0c:d1:ad And IP proto is TCP '>>> A.printf ("% DST % % ip.dst % vlan=% dot1q.vlan %") '00:00: D4: AE :3f:71 192.168.0.1 VLAN =42' >>> >>>a.sprintf(" %TCP.flags% | %5s,TCP.flags% | %#05xr,TCP.flags%") ' RA | RA | 0x014'Copy the code
Packet handler
We can use lambda functions to write packet handlers that handle TCP packets, but this functionality only applies to TCP packets.
> > > f = lambda x: x.s printf (" % IP. The DST % : % TCP. The dport % ") > > > f (DST = "8.8.8.8") (IP/TCP () '8.8.8.8: HTTP' > > > F (DST = "8.8.8.8") (IP/UDP () '8.8.8.8:?? 'Copy the code
You can also use the conditional substring in sprintf() for the purpose of processing other layers. The conditional substring is fired only if a layer exists in the packet, otherwise it is ignored. Still can! Used to check for missing layers. Conditional substring format: {[!] Layer: substring}
>>> f=lambda x: x.sprintf("=> {IP:ip=%IP.dst% {UDP:dport=%UDP.dport%}\ ... :... {TCP:%TCP.dport%/%TCP.flags%}{ICMP:type=%r,ICMP.type%}}\ ... :... {! IP: not an IP packet} ") > > > f (IP/TCP () () '= > IP = 127.0.0.1 HTTP/S' > > > f (IP/UDP () () '= = > IP 127.0.0.1 dport = domain' > > > F (IP () ()/ICMP) '= = > IP 127.0.0.1 type = 8' > > > f (Mr)/ARP () '= > not an IP packetCopy the code
Import and export data
PCAP format
Import packets from PCAP files.
pkts = rdpcap("temp.cap")
pkts = sniff(offline="temp.cap")
Copy the code
Export the packet to a PCAP file.
wrpcap("temp.cap",pkts)
Copy the code
Dump format is hexadecimal
- Scapy allows you to export packets in a variety of hexadecimal formats.
- Use the hexdump () function to display one or more packets using the hexdump format:
>>> hexdump(s) 0000 D8 55 A3 FE 80 78 00 16 3E 0C D1 AD 08 00 45 00 .U... x.. >... E. 0010 00 28 00 01 00 00 40 06 8B 5E AC 11 33 50 08 08 .(.... @.. ^.. 3P.. 0020 08 08 00 14 00 50 00 00 00 00 00 00 00 00 00 00 50 02..... P........ P. 0030 20 00 A0 0D 00 00Copy the code
A hexadecimal character string
You can also use the STR () function to convert the entire packet to a hexadecimal string
> > > s < Mr DST = d8:55: a3: fe: 80-78 type = IPv4 | < IP frag = 0 proto = TCP DST = 8.8.8.8 | | < TCP dport = HTTP > > > > > > STR WARNING (s) : Calling str(pkt) on Python 3 makes no sense! "b'\\xd8U\\xa3\\xfe\\x80x\\x00\\x16>\\x0c\\xd1\\xad\\x08\\x00E\\x00\\x00(\\x00\\x01\\x00\\x00@\\x06\\x8b^\\xac\\x113P\\x 08\\x08\\x08\\x08\\x00\\x14 \\x00P\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00P\\x02 \\x00\\xa0\\r\\x00\\x00'"Copy the code
Base64
- Scapy can export base64 encoded data for packets using the export_object() function.
>>> export_object(s) b'eNprYEouTk4sqNTLSaxMLSrWyzHici3JSC3iKmTQDCpk1EiOT85PSU0u5krNAzG4Cpki7BkYGA7PCD20+PC+Qw0VDGJ2PIcnHlrLweDKwKDBwMjA4MB2qD vu0BpB4wAOIGAQYQhggIIAJgWGQwt4GRgKmSPYgPycxJLMPMNClrZC1qBCNnfHGxoeDcsdkv2AoKSQPUkPALURLMU=' >>> new_pkt = import_objectCopy the code
sniffer
Sniff()
Sniff () function
Helps us capture all traffic:Including the count
.filter
.iface
.lfilter
.prn
.timeout
Options.
>>> sniff(count=4, iface='eth0')
<Sniffed: TCP:1 UDP:3 ICMP:0 Other:0>
Copy the code
Filters can be added to capture the desired packets, using the standard tcpdump/libpcap syntax:
>>> pkts = sniff(count=1,filter="tcp and host 60.205.177.168 and port 80")
>>> pkts.summary()
Ether / IP / TCP 172.17.51.80:54578 > 60.205.177.168:http S
Copy the code
- You can do a simple traffic analyzer like tcpdump
>>> PKTS = sniff(count=5,filter="host 60.205.177.168", PRN =lambda x:x.summary()) 60.205.177.168: HTTP S Ether/IP/TCP 60.205.177.168:54624 > 172.17.51.80: HTTP S Ether/IP/TCP 172.17.51.80: HTTP 60.205.177.168:54624 SA Ether/IP/TCP 60.205.177.168: HTTP > 172.17.51.80:54624 SA Ether/IP/TCP 172.17.51.80:54624 A > 60.205.177.168: HTTPCopy the code
- Packets can also be sniffed from pCAP files.
PKTS = sniff(offline='test.pcap') >>> PKts.nsummary () 0000 Ether/IP/TCP 172.16.16.124:1606 > 74.125.95.104: HTTP S 0001 Ether/IP/TCP 74.125.95.104: HTTP > 172.16.16.128-1606 SA 0002 74.125.95.104: HTTP A 0003 Ether/IP/TCP 172.16.16.124:1606 > 74.125.95.104: HTTP PA/Raw 0004 Ether/IP/TCP 74.125.95.104: HTTP > 172.16.16.124:1606 A/Padding >>> (offline='test.pcap', lfilter = lambda s: S [TCP].flags == 18, PRN = lambda x: x[IP].dst) 192.168.1.1 <Sniffed: TCP:1 UDP:0 ICMP:0 Other:0>Copy the code