4.8. Transport scapy
scapy
is a Python framework for crafting and transmitting arbitrary packets
4.8.1. Installation
$ pip install scapy
4.8.2. Running
$ sudo scapy
4.8.3. Basic usage
4.8.4. Displays all available protocols
Displays all available protocols:
ls()
# ARP : ARP
# ASN1_Packet : None
# BOOTP : BOOTP
# CookedLinux : cooked linux
# DHCP : DHCP options
# DHCP6 : DHCPv6 Generic Message)
# ...
4.8.5. Lists all command functions
Lists all command functions:
$ lsc()
Function |
Description |
---|---|
|
Identify IP id values classes in a list of packets |
|
Poison target's cache with (your MAC,victim's IP) couple |
|
Send ARP who-has requests to determine which hosts are up |
|
Exploit ARP leak flaws, like NetBSD-SA2017-002. |
|
Bind 2 layers on some specific fields' values. It makes the packet being built |
|
Forward traffic between interfaces if1 and if2, sniff and return |
|
Build a per byte hexadecimal representation |
|
Compute the NI group Address. Can take a FQDN as input parameter |
|
Flip a given percentage or number of bits from a string |
|
Corrupt a given percentage or number of bytes from a string |
|
defrag(plist) -> ([not fragmented], [defragmented], |
|
defragment(plist) -> plist defragmented as much as possible |
|
Send a DHCP discover request and return the answer |
|
Send a DNS add message to a nameserver for 'name' to have a new 'rdata' |
|
Send a DNS delete message to a nameserver for 'name' |
|
Exploit Etherleak flaw |
|
Function used to discover the Scapy layers and protocols. |
|
Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string. |
|
Calculates Fletcher-16 checksum of the given buffer. |
|
-- |
|
-- |
|
Fragment a big IP datagram |
|
Transform a layer into a fuzzy layer by replacing some default values by random objects |
|
Return MAC address corresponding to a given IP address |
|
Returns the MAC address corresponding to an IPv6 address |
|
Show differences between 2 binary strings |
|
Build a tcpdump like hexadecimal view |
|
Run hexedit on a list of packets, then return the edited packets. |
|
Build a fancy tcpdump like hex from bytes. |
|
Imports a tcpdump like hexadecimal view |
|
Try to guess if target is in Promisc mode. The target is provided by its ip. |
|
Build an equivalent view of hexdump() on a single line |
|
List available layers, or infos on a given layer class or name. |
|
Sends and receive an ICMPv6 Neighbor Solicitation message |
|
Build overlapping fragments to bypass NIPS |
|
Send ARP who-has requests to determine which hosts are in promiscuous mode |
|
Read a pcap or pcapng file and return a packet list |
|
portscan a target and output a LaTeX table |
|
Restarts scapy |
|
Send packets at layer 3 |
|
Send packets at layer 2 |
|
Send packets at layer 2 using tcpreplay for performance |
|
Sniff packets and return a list of packets. |
|
Split 2 layers previously bound. |
|
Send and receive packets at layer 3 |
|
Send packets at layer 3 and return only the first answer |
|
Flood and receive packets at layer 3 and return only the first answer |
|
send and receive using a bluetooth socket |
|
send and receive 1 packet using a bluetooth socket |
|
Flood and receive packets at layer 3 |
|
Send a packet at layer 3 in loop and print the answer each time |
|
Send and receive packets at layer 2 |
|
Send and receive packets at layer 2 and return only the first answer |
|
Flood and receive packets at layer 2 and return only the first answer |
|
Flood and receive packets at layer 2 |
|
Send a packet at layer 2 in loop and print the answer each time |
|
Run tcpdump or tshark on a list of packets |
|
Instant TCP traceroute |
|
Instant TCP traceroute using IPv6 |
|
Util function to call traceroute on multiple targets, then |
|
Sniff packets and print them calling pkt.summary(), a bit like text wireshark |
|
Run wireshark on a list of packets |
|
Write a list of packets to a pcap file |
4.8.6. Reading PCAP files
Read packets from a pcap file
Write packets to a pcap file.
data = rdpcap("/spare/captures/isakmp.cap")
# <isakmp.cap: UDP:721 TCP:0 ICMP:0 Other:0>
4.8.7. Graphical dumps (PDF, PS)
Command |
Effect |
---|---|
|
assemble the packet |
|
have a hexadecimal dump |
|
have the list of fields values |
|
for a one-line summary |
|
for a developed view of the packet |
|
same as show but on the assembled packet (checksum is calculated, for instance) |
|
fills a format string with fields values of the packet |
|
changes the way the payload is decoded |
|
draws a PostScript diagram with explained dissection |
|
draws a PDF with explained dissection |
|
return a Scapy command that can generate the packet |
4.8.8. Generating sets of packets
Command |
Effect |
---|---|
|
displays a list of summaries of each packet |
|
same as previous, with the packet number |
|
displays a graph of conversations |
|
displays the preferred representation (usually nsummary()) |
|
returns a packet list filtered with a lambda function |
|
returns a hexdump of all packets |
|
returns a hexdump of the Raw layer of all packets |
|
returns a hexdump of packets with padding |
|
returns a hexdump of packets with non-zero padding |
|
plots a lambda function applied to the packet list |
|
displays a table according to a lambda function |
4.8.9. List of possible fields
dir(IP)
dir(TCP)
dir(ICMP)
dir(Ether)
4.8.10. IP packages
Packets are constructed as layers of protocols, loosely analogous to the OSI model, which can be manipulated independently or glued together.
IP()
object represents an IPv4 header.
4.8.11. Create package
Create package:
ip = IP(src="192.168.0.1")
# <IP src=192.168.0.1 |>
Create package:
ip = IP(src="192.168.0.1", dst="192.168.0.2")
# <IP src=192.168.0.1 dst=192.168.0.2 |>
4.8.12. Modify package
Modify package:
ip = IP(src="192.168.0.1")
ip.dst = "192.168.0.2"
# <IP src=192.168.0.1 dst=192.168.0.2 |>
4.8.13. Show package
Use the
show()
method of an object to display all of its fields:
ip = IP(src="192.168.0.1")
ip.show()
# ###[ IP ]###
# version= 4
# ihl= None
# tos= 0x0
# len= None
# id= 1
# flags=
# frag= 0
# ttl= 64
# proto= ip
# chksum= None
# src= 192.168.0.1
# dst= 127.0.0.1
# \options\
4.8.14. TCP Package
4.8.15. Add TCP layer to IP package
Add a layer for protocol by using the division operator
Add a layer for protocol by using the division operator:
ip = IP(src="192.168.0.1", dst="192.168.0.2")
tcp = TCP(sport=1025, dport=80)
ip / tcp
# <IP frag=0 proto=tcp src=192.168.0.1 dst=192.168.0.2 |<TCP sport=blackjack dport=http |>>
Manipulate the TCP header fields just as IP header:
ip = IP(src="192.168.0.1", dst="192.168.0.2")
tcp = TCP(sport=1025, dport=80)
(tcp/ip).show()
# ###[ TCP ]###
# sport= blackjack
# dport= http
# seq= 0
# ack= 0
# dataofs= None
# reserved= 0
# flags= S
# window= 8192
# chksum= None
# urgptr= 0
# options= []
# ###[ IP ]###
# version= 4
# ihl= None
# tos= 0x0
# len= None
# id= 1
# flags=
# frag= 0
# ttl= 64
# proto= ip
# chksum= None
# src= 192.168.0.1
# dst= 192.168.0.2
# \options\
4.8.16. Ethernet frames
scapy
also supports Ethernet and IEEE 802.11 at layer two:
Ether() / Dot1Q() / IP()
# <Ether type=0x8100 |<Dot1Q type=0x800 |<IP |>>>
scapy
also supports Ethernet and IEEE 802.11 at layer two:
Dot11() / IP()
# <Dot11 |<IP |>>
4.8.17. Sending packets
4.8.18. OSI layer three
send()
function if transmitting at layer three (i.e. without a layer two header)
ip = IP(src="192.168.0.1", dst="192.168.0.2")
tcp = TCP(sport=1025, dport=80)
send(ip/tcp)
# .
# Sent 1 packets.
4.8.19. OSI layer two
sendp()
function if transmitting at layer twoValues for blank fields, such as the source and destination addresses in the Ethernet header, are populated automatically by
scapy
where possible.
ip = IP(src="192.168.0.1", dst="192.168.0.2")
tcp = TCP(sport=1025, dport=80)
sendp(Ether()/ip/tcp)
# .
# Sent 1 packets.
4.8.20. Send and Receive
scapy
has the ability to listen for responses to packets it sends, such as ICMP echo requests (pings).
4.8.21. One packet
Build an IP packet carrying an ICMP header
Use the
sr()
(send/receive) function to transmit the packet and record any response
ip = IP(dst='python3.info')
packet = ip / ICMP()
sr(packet)
# Begin emission:
# Finished sending 1 packets.
#
# Received 4 packets, got 1 answers, remaining 0 packets
# (<Results: TCP:0 UDP:0 ICMP:1 Other:0>,
# <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
4.8.22. Many packets
Send and listen for responses to multiple copies of the same packet
Use the
srloop()
function and specify a count of packets to send
ip = IP(dst="python3.info")
packet = ip / ICMP()
srloop(packet, count=3)
# RECV 1: IP / ICMP 104.18.227.122 > 172.20.10.2 echo-reply 0 / Padding
# RECV 1: IP / ICMP 104.18.227.122 > 172.20.10.2 echo-reply 0 / Padding
# RECV 1: IP / ICMP 104.18.227.122 > 172.20.10.2 echo-reply 0 / Padding
#
# Sent 3 packets, received 3 packets. 100.0% hits.
# (<Results: TCP:0 UDP:0 ICMP:3 Other:0>,
# <PacketList: TCP:0 UDP:0 ICMP:0 Other:0>)
4.8.23. SYN Scans
SA
orSYN-ACK
flags indicating an open port.
4.8.24. Scan one port
Scan one port:
ip = IP(dst="python3.info")
tcp = TCP(dport=80, flags="S")
sr1(ip/tcp)
# Begin emission:
# Finished sending 1 packets.
#
# Received 4 packets, got 1 answers, remaining 0 packets
# <IP version=4 ihl=5 tos=0x0 len=44 id=0 flags= frag=0 ttl=58 proto=tcp chksum=0x7e29 src=104.18.228.122 dst=172.20.10.2 |<TCP sport=http dport=ftp_data seq=19296319 ack=1 dataofs=6 reserved=0 flags=SA window=29200 chksum=0xb1cc urgptr=0 options=[('MSS', 1408)] |<Padding load='z*\xc2f\x87\xad\x93\xc5' |>>>
Scan one port:
ip = IP(dst='35.158.227.45')
tcp = TCP(dport=21, flags="S")
sr(ip/tcp)
# Begin emission:
# Finished sending 1 packets.
#
# Received 4 packets, got 1 answers, remaining 0 packets
# (<Results: TCP:1 UDP:0 ICMP:0 Other:0>,
# <Unanswered: TCP:0 UDP:0 ICMP:0 Other:0>)
sr1(ip/tcp)
# Begin emission:
# Finished sending 1 packets.
#
# Received 2 packets, got 1 answers, remaining 0 packets
# <IP version=4 ihl=5 tos=0x0 len=44 id=0 flags= frag=0 ttl=64 proto=tcp chksum=0xbdea src=35.158.227.45 dst=172.20.10.2 |<TCP sport=ftp dport=ftp_data seq=952757507 ack=1 dataofs=6 reserved=0 flags=SA window=65535 chksum=0xb56f urgptr=0 options=[('MSS', 1410)] |<Padding load='\x16\xd2e\xaf\xa16\xd2\x1b' |>>>
4.8.25. Scan port range
Scan port range:
ip = IP(dst="python3.info")
tcp = TCP(sport=666, dport=(440,443), flags="S")
sr(ip/tcp)