Scapy is a Python program that enables the user to send, sniff and dissect and forge network packets. This capability allows construction of tools that can probe, scan or attack networks.
Simple usage
# execute 'scapy' to enter scapy shell.
# specify IP Header value and create packets, this will create 4 packets as the network mask length is 30
>>> target="www.target.com/30"
>>> ip=IP(dst=target)
# simple display packet info
>>> ip
<IP dst=<Net www.target.com/30> |>
# display in loop
>>> [p for p in ip]
[<IP dst=207.171.175.28 |>, <IP dst=207.171.175.29 |>,
<IP dst=207.171.175.30 |>, <IP dst=207.171.175.31 |>]
# simple ip packet
>>> IP()
<IP |>
# ip packet with specify dst
>>> a=IP(dst="172.16.1.40")
>>> a
<IP dst=172.16.1.40 |>
# print a specify header value
>>> a.dst
'172.16.1.40'
>>> a.ttl
64
# use list and sequence as values, here we define 18 packets using a line
>>> Ether(dst="ff:ff:ff:ff:ff:ff")
/IP(dst=["ketchup.com","mayo.com"],ttl=(1,9))
/UDP()
>>> a=IP(ttl=10)
>>> a
< IP ttl=10 |>
>>> a.src
’127.0.0.1’
# modify a value
>>> a.dst="192.168.1.1"
>>> a
< IP ttl=10 dst=192.168.1.1 |>
>>> a.src
’192.168.8.14’
# delete a value(change to use the default value)
>>> del(a.ttl)
>>> a
< IP dst=192.168.1.1 |>
>>> a.ttl
64
Stacking Layers
>>> IP()
<IP |>
>>> IP()/TCP()
<IP frag=0 proto=TCP |<TCP |>>
>>> Ether()/IP()/TCP()
<Ether type=0x800 |<IP frag=0 proto=TCP |<TCP |>>>
>>> IP()/TCP()/"GET / HTTP/1.0\r\n\r\n"
<IP frag=0 proto=TCP |<TCP |<Raw load='GET / HTTP/1.0\r\n\r\n' |>>>
>>>Ether()/IP()/IP()/UDP()
<Ether type=0x800 |<IP frag=0 proto=IP |<IP frag=0 proto=UDP |<UDP |>>>>
>>> IP(proto=55)/TCP()
<IP frag=0 proto=55 |<TCP |>>
convert between raw stream and packet
>>> raw(IP())
'E\x00\x00\x14\x00\x01\x00\x00@\x00|\xe7\x7f\x00\x00\x01\x7f\x00\x00\x01'
>>> IP(_)
<IP version=4L ihl=5L tos=0x0 len=20 id=1 flags= frag=0L ttl=64 proto=IP
chksum=0x7ce7 src=127.0.0.1 dst=127.0.0.1 |>
a=Ether()/IP(dst="www.slashdot.org")/TCP()/"GET /index.html HTTP/1.0 \n\n"
>>> hexdump(a)
00 02 15 37 A2 44 00 AE F3 52 AA D1 08 00 45 00 ...7.D...R....E.
00 43 00 01 00 00 40 06 78 3C C0 A8 05 15 42 23 .C....@.x<....B#
FA 97 00 14 00 50 00 00 00 00 00 00 00 00 50 02 .....P........P.
20 00 BB 39 00 00 47 45 54 20 2F 69 6E 64 65 78 ..9..GET /index
2E 68 74 6D 6C 20 48 54 54 50 2F 31 2E 30 20 0A .html HTTP/1.0 .
0A .
>>> b=raw(a)
>>> b
'\x00\x02\x157\xa2D\x00\xae\xf3R\xaa\xd1\x08\x00E\x00\x00C\x00\x01\x00\x00@\x06x<\xc0
\xa8\x05\x15B#\xfa\x97\x00\x14\x00P\x00\x00\x00\x00\x00\x00\x00\x00P\x02 \x00
\xbb9\x00\x00GET /index.html HTTP/1.0 \n\n'
>>> c=Ether(b)
>>> c
<Ether dst=00:02:15:37:a2:44 src=00:ae:f3:52:aa:d1 type=0x800 |<IP version=4L
ihl=5L tos=0x0 len=67 id=1 flags= frag=0L ttl=64 proto=TCP chksum=0x783c
src=192.168.5.21 dst=66.35.250.151 options='' |<TCP sport=20 dport=80 seq=0L
ack=0L dataofs=5L reserved=0L flags=S window=8192 chksum=0xbb39 urgptr=0
options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |>>>>
hide defaut value when display
>>> c.hide_defaults()
>>> c
<Ether dst=00:0f:66:56:fa:d2 src=00:ae:f3:52:aa:d1 type=0x800 |<IP ihl=5L len=67
frag=0 proto=TCP chksum=0x783c src=192.168.5.21 dst=66.35.250.151 |<TCP dataofs=5L
chksum=0xbb39 options=[] |<Raw load='GET /index.html HTTP/1.0 \n\n' |>>>>
Reading PCAP files
>>> a=rdpcap("/spare/captures/isakmp.cap")
>>> a
<isakmp.cap: UDP:721 TCP:0 ICMP:0 Other:0>
Generating sets of packets
>>> a=IP(dst="www.slashdot.org/30")
>>> a
<IP dst=Net('www.slashdot.org/30') |>
>>> [p for p in a]
[<IP dst=66.35.250.148 |>, <IP dst=66.35.250.149 |>,
<IP dst=66.35.250.150 |>, <IP dst=66.35.250.151 |>]
>>> b=IP(ttl=[1,2,(5,9)])
>>> b
<IP ttl=[1, 2, (5, 9)] |>
>>> [p for p in b]
[<IP ttl=1 |>, <IP ttl=2 |>, <IP ttl=5 |>, <IP ttl=6 |>,
<IP ttl=7 |>, <IP ttl=8 |>, <IP ttl=9 |>]
>>> c=TCP(dport=[80,443])
>>> [p for p in a/c]
[<IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=80 |>>,
<IP frag=0 proto=TCP dst=66.35.250.148 |<TCP dport=443 |>>,
<IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=80 |>>,
<IP frag=0 proto=TCP dst=66.35.250.149 |<TCP dport=443 |>>,
<IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=80 |>>,
<IP frag=0 proto=TCP dst=66.35.250.150 |<TCP dport=443 |>>,
<IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=80 |>>,
<IP frag=0 proto=TCP dst=66.35.250.151 |<TCP dport=443 |>>]
some commands
summary()
displays a list of summaries of each packet
nsummary()
same as previous, with the packet number
conversations()
displays a graph of conversations
show()
displays the preferred representation (usually nsummary())
filter()
returns a packet list filtered with a lambda function
hexdump()
returns a hexdump of all packets
hexraw()
returns a hexdump of the Raw layer of all packets
padding()
returns a hexdump of packets with padding
nzpadding()
returns a hexdump of packets with non-zero padding
plot()
plots a lambda function applied to the packet list
make table()
displays a table according to a lambda function
lsc
# lsc() will display sacpy functions
>>> lsc()
IPID_count : Identify IP id values classes in a list of packets
arpcachepoison : Poison target's cache with (your MAC,victim's IP) couple
arping : Send ARP who-has requests to determine which hosts are up
arpleak : Exploit ARP leak flaws, like NetBSD-SA2017-002.
bind_layers : Bind 2 layers on some specific fields' values.
bridge_and_sniff : Forward traffic between interfaces if1 and if2, sniff and return
chexdump : Build a per byte hexadecimal representation
computeNIGroupAddr : Compute the NI group Address. Can take a FQDN as input parameter
corrupt_bits :
corrupt_bytes :
defrag : defrag(plist) -> ([not fragmented], [defragmented],
defragment : defragment(plist) -> plist defragmented as much as possible
dhcp_request : Send a DHCP discover request and return the answer
dyndns_add : Send a DNS add message to a nameserver for "name" to have a new "rdata"
dyndns_del : Send a DNS delete message to a nameserver for "name"
etherleak : Exploit Etherleak flaw
explore : Function used to discover the Scapy layers and protocols.
fletcher16_checkbytes: Calculates the Fletcher-16 checkbytes returned as 2 byte binary-string.
fletcher16_checksum : Calculates Fletcher-16 checksum of the given buffer.
fragleak : --
fragleak2 : --
fragment : Fragment a big IP datagram
fuzz :
getmacbyip : Return MAC address corresponding to a given IP address
getmacbyip6 : Returns the MAC address corresponding to an IPv6 address
hexdiff :
hexdump : Build a tcpdump like hexadecimal view
hexedit : Run hexedit on a list of packets, then return the edited packets.
hexstr : Build a fancy tcpdump like hex from bytes.
import_hexcap : Imports a tcpdump like hexadecimal view
is_promisc : Try to guess if target is in Promisc mode. The target is provided by its ip.
linehexdump : Build an equivalent view of hexdump() on a single line
ls : List available layers, or infos on a given layer class or name.
neighsol : Sends and receive an ICMPv6 Neighbor Solicitation message
overlap_frag : Build overlapping fragments to bypass NIPS
promiscping : Send ARP who-has requests to determine which hosts are in promiscuous mode
rdpcap : Read a pcap or pcapng file and return a packet list
report_ports : portscan a target and output a LaTeX table
restart : Restarts scapy
rfc :
send :
sendp :
sendpfast : Send packets at layer 2 using tcpreplay for performance
sniff :
split_layers : Split 2 layers previously bound.
sr :
sr1 :
sr1flood : Flood and receive packets at layer 3 and return only the first answer
srbt : send and receive using a bluetooth socket
srbt1 : send and receive 1 packet using a bluetooth socket
srflood : Flood and receive packets at layer 3
srloop :
srp :
srp1 :
srp1flood : Flood and receive packets at layer 2 and return only the first answer
srpflood : Flood and receive packets at layer 2
srploop :
tcpdump : Run tcpdump or tshark on a list of packets.
tdecode :
traceroute : Instant TCP traceroute
traceroute6 : Instant TCP traceroute using IPv6
traceroute_map : Util function to call traceroute on multiple targets, then
tshark : Sniff packets and print them calling pkt.summary().
wireshark :
wrpcap : Write a list of packets to a pcap file
default value
Scapy tries to use sensible default values for all packet fields. If not overridden,
IP source is chosen according to destination and routing table
Checksum is computed
Source MAC is chosen according to the output interface
Ethernet type and IP protocol are determined by the upper layer
Other fields’ default values are chosen to be the most useful ones:
TCP source port is 20, destination port is 80.
UDP source and destination ports are 53.
ICMP type is echo request.
Sending packets
Now that we know how to manipulate packets. Let’s see how to send them. The send() function will send packets at layer 3.
That is to say, it will handle routing and layer 2 for you.
The sendp() function will work at layer 2. It’s up to you to choose the right interface and the right link layer protocol.
send() and sendp() will also return sent packet list if return_packets=True is passed as parameter.
>>> send(IP(dst="1.2.3.4")/ICMP())
.
Sent 1 packets.
>>> sendp(Ether()/IP(dst="1.2.3.4",ttl=(1,4)), iface="eth1")
....
Sent 4 packets.
>>> sendp("I'm travelling on Ethernet", iface="eth1", loop=1, inter=0.2)
................^C
Sent 16 packets.
>>> sendp(rdpcap("/tmp/pcapfile")) # tcpreplay
...........
Sent 11 packets.
Returns packets sent by send()
>>> send(IP(dst='127.0.0.1'), return_packets=True)
.
Sent 1 packets.
<PacketList: TCP:0 UDP:0 ICMP:0 Other:1>
Fuzzing
unclear now
Injecting bytes
In a packet, each field has a specific type. For instance, the length field of the IP packet len expects an integer.
More on that later. If you’re developing a PoC, there are times where you’ll want to inject some value that doesn’t fit that type.
This is possible using RawVal
>>> pkt = IP(len=RawVal(b"NotAnInteger"), src="127.0.0.1")
>>> bytes(pkt)
b'H\x00NotAnInt\x0f\xb3er\x00\x01\x00\x00@\x00\x00\x00\x7f\x00\x00\x01\x7f\x00\x00\x01\x00\x00'
Send and receive packets (sr)
Now, let’s try to do some fun things. The sr() function is for sending packets and receiving answers.
The function returns a couple of packet and answers, and the unanswered packets.
The function sr1() is a variant that only returns one packet that answered the packet (or the packet set) sent.
The packets must be layer 3 packets (IP, ARP, etc.). The function srp() do the same for layer 2 packets (Ethernet, 802.3, etc.).
If there is no response, a None value will be assigned instead when the timeout is reached.
sr1只返回一个响应
>>> p = sr1(IP(dst="www.slashdot.org")/ICMP()/"XXXXXXXXXXX")
Begin emission:
...Finished to send 1 packets.
.*
Received 5 packets, got 1 answers, remaining 0 packets
>>> p
<IP version=4L ihl=5L tos=0x0 len=39 id=15489 flags= frag=0L ttl=42 proto=ICMP
chksum=0x51dd src=66.35.250.151 dst=192.168.5.21 options='' |<ICMP type=echo-reply
code=0 chksum=0xee45 id=0x0 seq=0x0 |<Raw load='XXXXXXXXXXX'
|<Padding load='\x00\x00\x00\x00' |>>>>
>>> p.show()
---[ IP ]---
version = 4L
ihl = 5L
tos = 0x0
len = 39
id = 15489
flags =
frag = 0L
ttl = 42
proto = ICMP
chksum = 0x51dd
src = 66.35.250.151
dst = 192.168.5.21
options = ''
---[ ICMP ]---
type = echo-reply
code = 0
chksum = 0xee45
id = 0x0
seq = 0x0
---[ Raw ]---
load = 'XXXXXXXXXXX'
---[ Padding ]---
load = '\x00\x00\x00\x00'
sr
## The “send’n’receive” functions family is the heart of Scapy. They return a couple of two lists.
## The first element is a list of couples (packet sent, answer), and the second element is the list of unanswered packets.
## These two elements are lists, but they are wrapped by an object to present them better, and to provide them with some methods that do most frequently needed actions:
>>> sr(IP(dst="192.168.8.1")/TCP(dport=[21,22,23]))
Received 6 packets, got 3 answers, remaining 0 packets
(<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:0 ICMP:0 Other:0>)
>>> ans, unans = _
>>> ans.summary()
IP / TCP 192.168.8.14:20 > 192.168.8.1:21 S ==> Ether / IP / TCP 192.168.8.1:21 > 192.168.8.14:20 RA / Padding
IP / TCP 192.168.8.14:20 > 192.168.8.1:22 S ==> Ether / IP / TCP 192.168.8.1:22 > 192.168.8.14:20 RA / Padding
IP / TCP 192.168.8.14:20 > 192.168.8.1:23 S ==> Ether / IP / TCP 192.168.8.1:23 > 192.168.8.14:20 RA / Padding
# inter 发包间隔
# retry = 2,未收到响应的包重新发送2次
# retry = -2,未收到响应的组中的包一直重发,直到整个组的请求连续两次收不到响应
# timeout 响应超时时间
>>> sr(IP(dst="172.20.29.5/30")/TCP(dport=[21,22,23]),inter=0.5,retry=-2,timeout=1)
Begin emission:
Finished to send 12 packets.
Begin emission:
Finished to send 9 packets.
Begin emission:
Finished to send 9 packets.
Received 100 packets, got 3 answers, remaining 9 packets
(<Results: UDP:0 TCP:3 ICMP:0 Other:0>, <Unanswered: UDP:0 TCP:9 ICMP:0 Other:0>)
Configuring super sockets
Different super sockets are available in Scapy: the native ones, and the ones that use libpcap (to send/receive packets).
By default, Scapy will try to use the native ones (except on Windows, where the winpcap/npcap ones are preferred). To manually use the libpcap ones, you must:
On Unix/OSX: be sure to have libpcap installed.
On Windows: have Npcap/Winpcap installed. (default)
Then use:
conf.use_pcap = True
This will automatically update the sockets pointing to conf.L2socket and conf.L3socket.
If you want to manually set them, you have a bunch of sockets available, depending on your platform. For instance, you might want to use:
conf.L3socket=L3pcapSocket # Receive/send L3 packets through libpcap
conf.L2listen=L2ListenTcpdump # Receive L2 packets through TCPDump
Sniffing
We can easily capture some packets or even clone tcpdump or tshark. Either one interface or a list of interfaces to sniff on can be provided.
If no interface is given, sniffing will happen on conf.iface:
>>> sniff(filter="icmp and host 66.35.250.151", count=2)
<Sniffed: UDP:0 TCP:0 ICMP:2 Other:0>
>>> a=_
>>> a.nsummary()
0000 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw
0001 Ether / IP / ICMP 192.168.5.21 echo-request 0 / Raw
a[1]
<Ether dst=00:ae:f3:52:aa:d1 src=00:02:15:37:a2:44 type=0x800 |<IP version=4L
ihl=5L tos=0x0 len=84 id=0 flags=DF frag=0L ttl=64 proto=ICMP chksum=0x3831
src=192.168.5.21 dst=66.35.250.151 options='' |<ICMP type=echo-request code=0
chksum=0x6571 id=0x8745 seq=0x0 |<Raw load='B\xf7g\xda\x00\x07um\x08\t\n\x0b
\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d
\x1e\x1f !\x22#$%&\'()*+,-./01234567' |>>>>
>>> sniff(iface="wifi0", prn=lambda x: x.summary())
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 5 00:0a:41:ee:a5:50 / 802.11 Probe Response / Info SSID / Info Rates / Info DSset / Info 133
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 4 ff:ff:ff:ff:ff:ff / 802.11 Probe Request / Info SSID / Info Rates
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 11 00:07:50:d6:44:3f / 802.11 Authentication
802.11 Management 11 00:0a:41:ee:a5:50 / 802.11 Authentication
802.11 Management 0 00:07:50:d6:44:3f / 802.11 Association Request / Info SSID / Info Rates / Info 133 / Info 149
802.11 Management 1 00:0a:41:ee:a5:50 / 802.11 Association Response / Info Rates / Info 133 / Info 149
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 Management 8 ff:ff:ff:ff:ff:ff / 802.11 Beacon / Info SSID / Info Rates / Info DSset / Info TIM / Info 133
802.11 / LLC / SNAP / ARP who has 172.20.70.172 says 172.20.70.171 / Padding
802.11 / LLC / SNAP / ARP is at 00:0a:b7:4b:9c:dd says 172.20.70.172 / Padding
802.11 / LLC / SNAP / IP / ICMP echo-request 0 / Raw
802.11 / LLC / SNAP / IP / ICMP echo-reply 0 / Raw
>>> sniff(iface="eth1", prn=lambda x: x.show())
---[ Ethernet ]---
dst = 00:ae:f3:52:aa:d1
src = 00:02:15:37:a2:44
type = 0x800
---[ IP ]---
version = 4L
ihl = 5L
tos = 0x0
len = 84
id = 0
flags = DF
frag = 0L
ttl = 64
proto = ICMP
chksum = 0x3831
src = 192.168.5.21
dst = 66.35.250.151
options = ''
---[ ICMP ]---
type = echo-request
code = 0
chksum = 0x89d9
id = 0xc245
seq = 0x0
---[ Raw ]---
load = 'B\xf7i\xa9\x00\x04\x149\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\x22#$%&\'()*+,-./01234567'
---[ Ethernet ]---
dst = 00:02:15:37:a2:44
src = 00:ae:f3:52:aa:d1
type = 0x800
---[ IP ]---
version = 4L
ihl = 5L
tos = 0x0
len = 84
id = 2070
flags =
frag = 0L
ttl = 42
proto = ICMP
chksum = 0x861b
src = 66.35.250.151
dst = 192.168.5.21
options = ''
---[ ICMP ]---
type = echo-reply
code = 0
chksum = 0x91d9
id = 0xc245
seq = 0x0
---[ Raw ]---
load = 'B\xf7i\xa9\x00\x04\x149\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !\x22#$%&\'()*+,-./01234567'
---[ Padding ]---
load = '\n_\x00\x0b'
>>> sniff(iface=["eth1","eth2"], prn=lambda x: x.sniffed_on+": "+x.summary())
eth3: Ether / IP / ICMP 192.168.5.21 > 66.35.250.151 echo-request 0 / Raw
eth3: Ether / IP / ICMP 66.35.250.151 > 192.168.5.21 echo-reply 0 / Raw
eth2: Ether / IP / ICMP 192.168.5.22 > 66.35.250.152 echo-request 0 / Raw
eth2: Ether / IP / ICMP 66.35.250.152 > 192.168.5.22 echo-reply 0 / Raw
# For even more control over displayed information we can use the sprintf() function:
>>> pkts = sniff(prn=lambda x:x.sprintf("{IP:%IP.src% -> %IP.dst%\n}{Raw:%Raw.load%\n}"))
192.168.1.100 -> 64.233.167.99
64.233.167.99 -> 192.168.1.100
192.168.1.100 -> 64.233.167.99
192.168.1.100 -> 64.233.167.99
'GET / HTTP/1.1\r\nHost: 64.233.167.99\r\nUser-Agent: Mozilla/5.0
(X11; U; Linux i686; en-US; rv:1.8.1.8) Gecko/20071022 Ubuntu/7.10 (gutsy)
Firefox/2.0.0.8\r\nAccept: text/xml,application/xml,application/xhtml+xml,
text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5\r\nAccept-Language:
en-us,en;q=0.5\r\nAccept-Encoding: gzip,deflate\r\nAccept-Charset:
ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nKeep-Alive: 300\r\nConnection:
keep-alive\r\nCache-Control: max-age=0\r\n\r\n'
# We can sniff and do passive OS fingerprinting:
>>> p
<Ether dst=00:10:4b:b3:7d:4e src=00:40:33:96:7b:60 type=0x800 |<IP version=4L
ihl=5L tos=0x0 len=60 id=61681 flags=DF frag=0L ttl=64 proto=TCP chksum=0xb85e
src=192.168.8.10 dst=192.168.8.1 options='' |<TCP sport=46511 dport=80
seq=2023566040L ack=0L dataofs=10L reserved=0L flags=SEC window=5840
chksum=0x570c urgptr=0 options=[('Timestamp', (342940201L, 0L)), ('MSS', 1460),
('NOP', ()), ('SAckOK', ''), ('WScale', 0)] |>>>
>>> load_module("p0f")
>>> p0f(p)
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
>>> a=sniff(prn=prnp0f)
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
(1.0, ['Linux 2.4.2 - 2.4.14 (1)'])
(0.875, ['Linux 2.4.2 - 2.4.14 (1)', 'Linux 2.4.10 (1)', 'Windows 98 (?)'])
(1.0, ['Windows 2000 (9)'])
Filters
>>> a=sniff(filter="tcp and ( port 25 or port 110 )",
prn=lambda x: x.sprintf("%IP.src%:%TCP.sport% -> %IP.dst%:%TCP.dport% %2s,TCP.flags% : %TCP.payload%"))
192.168.8.10:47226 -> 213.228.0.14:110 S :
213.228.0.14:110 -> 192.168.8.10:47226 SA :
192.168.8.10:47226 -> 213.228.0.14:110 A :
213.228.0.14:110 -> 192.168.8.10:47226 PA : +OK <13103.1048117923@pop2-1.free.fr>
Importing and Exporting Data
PCAP:
It is often useful to save capture packets to pcap file for use at later time or with different applications:
wrpcap("temp.cap",pkts)
To restore previously saved pcap file:
pkts = rdpcap("temp.cap")
or
pkts = sniff(offline="temp.cap")
Hexdump:
Scapy allows you to export recorded packets in various hex formats.
Use hexdump() to display one or more packets using classic hexdump format:
hexdump(pkt)
Hexdump above can be reimported back into Scapy using import_hexcap():
pkt_hex = Ether(import_hexcap())
Binary string
You can also convert entire packet into a binary string using the raw() function:
pkt_raw = raw(pkt)
We can reimport the produced binary string by selecting the appropriate first layer (e.g. Ether()).
new_pkt = Ether(pkt_raw)
Making tables
Now we have a demonstration of the make_table() presentation function.
It takes a list as parameter, and a function who returns a 3-uple.
The first element is the value on the x axis from an element of the list,
the second is about the y value and the third is the value that we want to see at coordinates (x,y).
The result is a table. This function has 2 variants, make_lined_table() and make_tex_table() to copy/paste into your LaTeX pentest report.
Those functions are available as methods of a result object :
>>> ns, unans = sr(IP(dst="www.test.fr/30", ttl=(1,6))/TCP())
Received 49 packets, got 24 answers, remaining 0 packets
>>> ans.make_table( lambda s,r: (s.dst, s.ttl, r.src) )
216.15.189.192 216.15.189.193 216.15.189.194 216.15.189.195
1 192.168.8.1 192.168.8.1 192.168.8.1 192.168.8.1
2 81.57.239.254 81.57.239.254 81.57.239.254 81.57.239.254
3 213.228.4.254 213.228.4.254 213.228.4.254 213.228.4.254
4 213.228.3.3 213.228.3.3 213.228.3.3 213.228.3.3
5 193.251.254.1 193.251.251.69 193.251.254.1 193.251.251.69
6 193.251.241.174 193.251.241.178 193.251.241.174 193.251.241.178
>>> ans, unans = sr(IP(dst="172.20.80.192/28")/TCP(dport=[20,21,22,25,53,80]))
Received 142 packets, got 25 answers, remaining 71 packets
>>> ans.make_table(lambda s,r: (s.dst, s.dport, r.sprintf("%IP.id%")))
172.20.80.196 172.20.80.197 172.20.80.198 172.20.80.200 172.20.80.201
20 0 4203 7021 - 11562
21 0 4204 7022 - 11563
22 0 4205 7023 11561 11564
25 0 0 7024 - 11565
53 0 4207 7025 - 11566
80 0 4028 7026 - 11567
Routing
Now Scapy has its own routing table, so that you can have your packets routed differently than the system:
>>> conf.route
Network Netmask Gateway Iface
127.0.0.0 255.0.0.0 0.0.0.0 lo
192.168.8.0 255.255.255.0 0.0.0.0 eth0
0.0.0.0 0.0.0.0 192.168.8.1 eth0
>>> conf.route.delt(net="0.0.0.0/0",gw="192.168.8.1")
>>> conf.route.add(net="0.0.0.0/0",gw="192.168.8.254")
>>> conf.route.add(host="192.168.1.1",gw="192.168.8.1")
>>> conf.route
Network Netmask Gateway Iface
127.0.0.0 255.0.0.0 0.0.0.0 lo
192.168.8.0 255.255.255.0 0.0.0.0 eth0
0.0.0.0 0.0.0.0 192.168.8.254 eth0
192.168.1.1 255.255.255.255 192.168.8.1 eth0
>>> conf.route.resync()
>>> conf.route
Network Netmask Gateway Iface
127.0.0.0 255.0.0.0 0.0.0.0 lo
192.168.8.0 255.255.255.0 0.0.0.0 eth0
0.0.0.0 0.0.0.0 192.168.8.1 eth0
ACK Scan
ans, unans = sr(IP(dst="www.slashdot.org")/TCP(dport=[80,666],flags="A"))
for s,r in ans:
if s[TCP].dport == r[TCP].sport:
print("%d is unfiltered" % s[TCP].dport)
for s in unans:
print("%d is filtered" % s[TCP].dport)
IP Scan
A lower level IP Scan can be used to enumerate supported protocols:
ans, unans = sr(IP(dst="192.168.1.1",proto=(0,255))/"SCAPY",retry=2)
ARP Ping
The fastest way to discover hosts on a local ethernet network is to use the ARP Ping method:
ans, unans = srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst="192.168.1.0/24"),timeout=2)
Answers can be reviewed with the following command:
ans.summary(lambda s,r: r.sprintf("%Ether.src% %ARP.psrc%") )
Scapy also includes a built-in arping() function which performs similar to the above two commands:
arping("192.168.1.*")
ICMP Ping
ans, unans = sr(IP(dst="192.168.1.1-254")/ICMP())
ans.summary(lambda s,r: r.sprintf("%IP.src% is alive") )
TCP Ping
ans, unans = sr( IP(dst="192.168.1.*")/TCP(dport=80,flags="S") )
ans.summary( lambda s,r : r.sprintf("%IP.src% is alive") )
UDP Ping
ans, unans = sr( IP(dst="192.168.*.1-10")/UDP(dport=0) )
ans.summary( lambda s,r : r.sprintf("%IP.src% is alive") )
DNS Request
>>> ans = sr1(IP(dst="8.8.8.8")/UDP(sport=RandShort(), dport=53)/DNS(rd=1,qd=DNSQR(qname="secdev.org",qtype="A")))
>>> ans.an.rdata
'217.25.178.5'
Classical attacks
Malformed packets:
send(IP(dst="10.1.1.5", ihl=2, version=3)/ICMP())
Ping of death (Muuahahah):
send( fragment(IP(dst="10.0.0.5")/ICMP()/("X"*60000)) )
ARP cache poisoning
This attack prevents a client from joining the gateway by poisoning its ARP cache through a VLAN hopping attack.
Classic ARP cache poisoning:
send( Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client),inter=RandNum(10,40), loop=1 )
ARP cache poisoning with double 802.1q encapsulation:
send( Ether(dst=clientMAC)/Dot1Q(vlan=1)/Dot1Q(vlan=2)
/ARP(op="who-has", psrc=gateway, pdst=client),
inter=RandNum(10,40), loop=1 )
TCP Port Scanning
res, unans = sr( IP(dst="target")
/TCP(flags="S", dport=(1,1024)) )
res.nsummary( lfilter=lambda s,r: (r.haslayer(TCP) and (r.getlayer(TCP).flags & 2)) )
Scapy routing
Scapy needs to know many things related to the network configuration of your machine, to be able to route packets properly. For instance, the interface list, the IPv4 and IPv6 routes…
This means that Scapy has implemented bindings to get this information. Those bindings are OS specific. This will show you how to use it for a different usage.
# List interfaces:
>>> get_if_list()
['lo', 'eth0']
>>> conf.ifaces
SRC INDEX IFACE IPv4 IPv6 MAC
sys 2 eth0 10.0.0.5 fe80::10a:2bef:dc12:afae Microsof:12:cb:ef
sys 1 lo 127.0.0.1 ::1 00:00:00:00:00:00
>>> conf.ifaces.dev_from_index(2)
<NetworkInterface eth0 [UP+BROADCAST+RUNNING+SLAVE]>
# IPv4 routes:
>>> conf.route
>>> conf.route.route("127.0.0.1")
# IPv6 routes:
>>> gw = conf.route.route("0.0.0.0")[2]
# get local iface ip
>>> ip = get_if_addr(conf.iface) # default interface
>>> ip = get_if_addr("eth0")
>>> ip
'10.0.0.5'
# get local iface mac
>>> mac = get_if_hwaddr(conf.iface) # default interface
>>> mac = get_if_hwaddr("eth0")
>>> mac
'54:3f:19:c9:38:6d'
# get mac by ip
>>> mac = getmacbyip("10.0.0.1")
>>> mac
'f3:ae:5e:76:31:9b'
lacp
lacpdu_other_field.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 4:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
actor_system = sys.argv[2]
actor_key = int(sys.argv[3])
load_contrib('lacp')
received_count=0
actor_system_in_lacpdu=0
actor_key_in_lacpdu=0
def lacp_monitor_callback(pkt):
global received_count
global actor_system_in_lacpdu
global actor_key_in_lacpdu
if LACP in pkt:
received_count+=1
actor_system_in_lacpdu= pkt[LACP].actor_system
actor_key_in_lacpdu= pkt[LACP].actor_key
return pkt.summary()
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
end=time.time()
print("actor_system setting is {}, actor_system_in_lacpdu is {}".format(actor_system,actor_system_in_lacpdu))
print("actor_key setting is {}, actor_key_in_lacpdu is {}".format(actor_key,actor_key_in_lacpdu))
if actor_system != actor_system_in_lacpdu or \
actor_key != actor_key_in_lacpdu:
sys.exit(1)
else:
sys.exit(0)
lacpdu_receive_periodic.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 3:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
rate = int(sys.argv[2])
load_contrib('lacp')
received_count=0
rate_in_lacpdu=0
def lacp_monitor_callback(pkt):
global received_count
global rate_in_lacpdu
if LACP in pkt:
received_count+=1
rate_in_lacpdu= (pkt[LACP].actor_state & 0x02) >> 1
#return "%x" % pkt[LACP].partner_state
return rate_in_lacpdu
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
end=time.time()
print("lacp_rate setting is {}, lacp_rate_in_lacpdu is {}".format(rate,rate_in_lacpdu))
if rate != rate_in_lacpdu:
sys.exit(1)
else:
sys.exit(0)
lacpdu_send_periodic.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 2:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
load_contrib('lacp')
#trigger fast rate
state=int("0x4f",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system_priority=1, partner_key=1, partner_port_numer=1,
partner_port_priority=1, partner_state=state)
pkt = Ether()/SlowProtocol()/lacp
sendp(pkt, iface=iface)
time.sleep(1)
sendp(pkt, iface=iface)
time.sleep(1)
sendp(pkt, iface=iface)
received_count=0
def lacp_monitor_callback(pkt):
global received_count
if LACP in pkt and pkt[LACP].actor_system != "00:1a:70:0c:9f:00":
#pkt.summary()
#raw(pkt)
#hexdump(pkt)
received_count+=1
#return "%x" % pkt[LACP].partner_state
return pkt.summary()
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=2,timeout=90)
end=time.time()
print("fast rate: {} lacp packet received in {}s.".format(received_count,end-start))
duration=end-start
if duration > 5:
sys.exit(1)
#trigger slow rate
state=int("0x4d",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system_priority=1, partner_key=1, partner_port_numer=1,
partner_port_priority=1, partner_state=state)
pkt = Ether()/SlowProtocol()/lacp
sendp(pkt, iface=iface)
time.sleep(1)
sendp(pkt, iface=iface)
time.sleep(1)
sendp(pkt, iface=iface)
received_count=0
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=2,timeout=90)
end=time.time()
print("slow rate: {} lacp packet received in {}s.".format(received_count,end-start))
duration=end-start
if duration < 5 or duration > 70:
sys.exit(1)
else:
sys.exit(0)
lacpdu_sys_prio.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 3:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
prio = int(sys.argv[2])
load_contrib('lacp')
received_count=0
prio_in_lacpdu=0
def lacp_monitor_callback(pkt):
global received_count
global prio_in_lacpdu
if LACP in pkt:
received_count+=1
prio_in_lacpdu= pkt[LACP].actor_system_priority
return prio_in_lacpdu
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
end=time.time()
print("lacp_sys_prio setting is {}, lacp_prio_in_lacpdu is {}".format(prio,prio_in_lacpdu))
if prio != prio_in_lacpdu:
sys.exit(1)
else:
sys.exit(0)
lacpdu_under_stress.py
#!/usr/bin/python
import sys, os
import time
import threading
from scapy.all import *
if len(sys.argv) < 2:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
load_contrib('lacp')
class MyThread(threading.Thread):
def __init__(self,rate,counter):
threading.Thread.__init__(self)
self.rate = rate
self.counter = counter
def run(self):
#trigger fast rate
if self.rate == "fast":
state=int("0x4f",16)
else:
state=int("0x4d",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system_priority=1, partner_key=1, partner_port_numer=1,
partner_port_priority=1, partner_state=state)
pkt = Ether()/SlowProtocol()/lacp
sent_packets=0
while sent_packets < self.counter:
sendp(pkt, iface=iface)
sent_packets+=1
time.sleep(5)
'''
# test fast lacp rate
fast_thread=MyThread("fast",20)
fast_thread.start()
received_count=0
def lacp_monitor_callback(pkt):
global received_count
if LACP in pkt:
received_count+=1
return pkt.summary()
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,timeout=90)
end=time.time()
print("fast rate: {} lacp packet received in {}s.".format(received_count,end-start))
fast_thread.join()
if received_count < 85:
sys.exit(1)
'''
# test slow lacp rate
#slow_thread=MyThread("slow",22)
#slow_thread.start()
received_count=0
def lacp_monitor_callback(pkt):
global received_count
if LACP in pkt and pkt[LACP].actor_system != "00:1a:70:0c:9f:00":
received_count+=1
return pkt.summary()
start=time.time()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,timeout=100)
end=time.time()
print("slow rate: {} lacp packet received in {}s.".format(received_count,end-start))
#slow_thread.join()
if received_count < 3:
sys.exit(1)
else:
sys.exit(0)
receive_conflict_lacpdu.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 3:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface1 = sys.argv[1]
iface2 = sys.argv[2]
load_contrib('lacp')
#trigger slow rate
state=int("0x4d",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system_priority=1, partner_key=1, partner_port_numer=1,
partner_port_priority=1, partner_state=state)
pkt = Ether()/SlowProtocol()/lacp
while True:
sendp(pkt, iface=iface1)
sendp(pkt, iface=iface2)
time.sleep(1)
when_to_collecting_distributing.py
#!/usr/bin/python
import sys, os
import time
from scapy.all import *
if len(sys.argv) < 2:
print("not enough parameter")
sys.exit(1)
conf.sniff_promisc = 0
iface = sys.argv[1]
load_contrib('lacp')
# capture a lacp message, its content will be used when sending lacp message.
peer_state=None
def lacp_monitor_callback(pkt):
global peer_state
if LACP in pkt:
peer_state=pkt
return pkt.show()
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
if not peer_state:
print("step1: didn't get peer lacp messge")
sys.exit(1)
# send lacp message with synchronization=0 to peer
state=int("0x07",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system=peer_state[LACP].actor_system,
partner_system_priority=peer_state[LACP].actor_system_priority,
partner_key=peer_state[LACP].actor_key,
partner_port_numer=peer_state[LACP].actor_port_numer,
partner_port_priority=peer_state[LACP].actor_port_priority,
partner_state=peer_state[LACP].actor_state)
pkt = Ether()/SlowProtocol()/lacp
sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
# peers lacp collecting state should be 0
peer_state=None
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
if not peer_state:
print("step2: didn't get peer lacp messge")
sys.exit(1)
collecting=(peer_state[LACP].actor_state & 0x10) >> 4
if collecting != 0:
print("peers collecting state change to {} after sending 0x07 to peer".format(collecting))
sys.exit(1)
# send lacp message with synchronization=1 to peer
state=int("0x0f",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system=peer_state[LACP].actor_system,
partner_system_priority=peer_state[LACP].actor_system_priority,
partner_key=peer_state[LACP].actor_key,
partner_port_numer=peer_state[LACP].actor_port_numer,
partner_port_priority=peer_state[LACP].actor_port_priority,
partner_state=peer_state[LACP].actor_state)
pkt = Ether()/SlowProtocol()/lacp
sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
# peers lacp collecting state should be 1
peer_state=None
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
if not peer_state:
print("step3: didn't get peer lacp message")
sys.exit(1)
collecting=(peer_state[LACP].actor_state & 0x10) >> 4
if collecting != 1:
print("peers collecting state change to {} after sending 0x0f to peer".format(collecting))
sys.exit(1)
# send lacp message with collecting=1 to peer
state=int("0x3f",16)
lacp = LACP(actor_system_priority=127, actor_system="00:1a:70:0c:9f:00", actor_key=1,
actor_port_numer=1, actor_port_priority=1, actor_state=state,
partner_system=peer_state[LACP].actor_system,
partner_system_priority=peer_state[LACP].actor_system_priority,
partner_key=peer_state[LACP].actor_key,
partner_port_numer=peer_state[LACP].actor_port_numer,
partner_port_priority=peer_state[LACP].actor_port_priority,
partner_state=peer_state[LACP].actor_state)
pkt = Ether()/SlowProtocol()/lacp
sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
#time.sleep(1)
#sendp(pkt, iface=iface)
# peers lacp collecting state should be 1
peer_state=None
sniff(iface=iface,filter='ether proto 0x8809',store=0,prn=lacp_monitor_callback,count=1,timeout=40)
if not peer_state:
print("step4: didn't get peer lacp message")
sys.exit(1)
distributing=(peer_state[LACP].actor_state & 0x20) >> 5
if distributing != 1:
print("peers distributing state change to {} after sending 0x0f to peer".format(distributing))
sys.exit(1)
else:
sys.exit(0)
lacp port state
0 LACP_Activity Device intends to transmit periodically in order to find potential members for the aggregate.
This is toggled by mode active in the channel-group configuration on the member interfaces.
1 = Active, 0 = Passive.
1 LACP_Timeout Length of the LACP timeout.
1 = Short Timeout, 0 = Long Timeout
2 Aggregation Will allow the link to be aggregated.
1 = Yes, 0 = No (individual link)
3 Synchronization Indicates that the mux on the transmitting machine is in sync with what’s being advertised in the LACP frames.
1 = In sync, 0 = Not in sync
4 Collecting Mux is accepting traffic received on this port
1 = Yes, 0 = No
5 Distributing Mux is sending traffic using this port
1 = Yes, 0 = No
6 Defaulted Whether the receiving mux is using default (administratively defined) parameters, if the information was received in an LACP PDU.
1 = default settings, 0 = via LACP PDU
7 Expired In an expired state
1 = Yes, 0 = No
arp
# send gratuitous arp
cat <<EOF >sendm.py
#!/bin/python3
from scapy.all import *
import os, sys
for iface in os.listdir('/sys/class/net/'):
if iface != 'lo' and iface != 'bonding_masters':
break
srcmac = open("/sys/class/net/" + iface + "/address", "r").read()
arp=Ether(dst="ff:ff:ff:ff:ff:ff",src=srcmac)/ARP(pdst="$ip2",psrc="$ip2",hwsrc=srcmac)
#arp.show()
sendp(arp, iface=iface)
arp=Ether(dst="ff:ff:ff:ff:ff:ff",src=srcmac)/ARP(pdst="0.0.0.0",psrc="$ip2",hwsrc=srcmac,op="is-at")
#arp.show()
sendp(arp, iface=iface)
EOF
# send other packets
cat <<EOF >sendm.py
#!/bin/python3
from scapy.all import *
import os, sys
for iface in os.listdir('/sys/class/net/'):
if iface != 'lo' and iface != 'bonding_masters':
break
#srcmac = open("/sys/class/net/" + iface + "/address", "r").read()
srcmac = "$mac2"
unicast=Ether(dst="44:44:01:02:03:04",src=srcmac)/IP(src="1.2.3.4",dst="1.2.3.5")/UDP()
sendp(unicast, iface=iface)
broadcast=Ether(dst="ff:ff:ff:ff:ff:ff",src=srcmac)/IP(src="1.2.3.4",dst="1.255.255.255")/UDP()
#ip.show()
sendp(broadcast, iface=iface)
multicast=Ether(dst="01:00:5e:00:01:01",src=srcmac)/IP(dst="1.2.3.4")
sendp(multicast, iface=iface)
EOF
igmp
# send igmp join
cat <<EOF >sendm.py
#!/bin/python3
from scapy.all import *
from scapy.contrib.igmpv3 import IGMPv3,IGMPv3mq,IGMP,IGMPv3gr
from scapy.contrib.igmpv3 import IGMPv3mr
import os, sys
for iface in os.listdir('/sys/class/net/'):
if iface != 'lo' and iface != 'bonding_masters':
break
srcmac = open("/sys/class/net/" + iface + "/address", "r").read()
p_join = Ether(dst='01:00:5e:0a:0a:0a', src=srcmac) / IP(src="$ip1", dst="$multicast_ip", tos=0xc0) /IGMPv3() /IGMPv3mr(numgrp=1) /IGMPv3gr(rtype=4, maddr="$multicast_ip")
#p_join.show()
sendp(p_join,iface=iface)
EOF
install
install_python()
{
yum install -y python3 || yum install -y platform-python || yum install -y python2
#if [ ! -e /usr/bin/python ];then
if [ -e "/usr/bin/python3" ];then
ln -sf /usr/bin/python3 /usr/bin/python
elif [ -e "/usr/libexec/platform-python" ];then
ln -sf /usr/libexec/platform-python /usr/bin/python
elif [ -e "/usr/bin/python2" ];then
ln -sf /usr/bin/python2 /usr/bin/python
fi
#fi
python -V > python_version.txt 2>&1
python_version=$(cat python_version.txt|grep "Python [0-9]"|awk '{print $2}'|awk -F'.' '{print $1}')
if [ $python_version -eq 3 ];then
yum install -y python3-devel
yum install -y platform-python-devel
yum install -y python3-pip
ln -sf /usr/bin/pip3 /usr/bin/pip
elif [ $python_version -eq 2 ];then
if [ ! -e /usr/bin/pip ];then
yum install -y python2-devel
#wget https://bootstrap.pypa.io/get-pip.py
wget https://bootstrap.pypa.io/pip/2.7/get-pip.py
python get-pip.py
ln -sf /usr/bin/pip2 /usr/bin/pip
fi
fi
# check again because sometimes /usr/bin/python is deleted
if [ ! -e /usr/bin/python ];then
if [ -e "/usr/bin/python3" ];then
ln -sf /usr/bin/python3 /usr/bin/python
elif [ -e "/usr/libexec/platform-python" ];then
ln -sf /usr/libexec/platform-python /usr/bin/python
elif [ -e "/usr/bin/python2" ];then
ln -sf /usr/bin/python2 /usr/bin/python
fi
fi
}
pip install scapy || yum install -y python3-scapy
ipv6 NA
#!/usr/bin/python
from scapy.all import *
import time
smac=sys.argv[1]
dmac=sys.argv[2]
sipv6=sys.argv[3]
dipv6=sys.argv[4]
iface=sys.argv[5]
ether=Ether(src=smac,dst=dmac)
ipv6=IPv6(nh=58, src=sipv6, dst=dipv6, version=6, hlim=255, fl=0, tc=0)
nd=ICMPv6ND_NA(tgt=sipv6,R=1,S=0,O=1)
option=ICMPv6NDOptDstLLAddr(lladdr=smac)
for i in range(1000):
sendp(ether/ipv6/nd/option, iface=iface)
time.sleep(1)
ipv6 udp
#!/usr/bin/python
from scapy.all import *
import time
smac=sys.argv[1]
dmac=sys.argv[2]
sipv6=sys.argv[3]
dipv6=sys.argv[4]
iface=sys.argv[5]
ether=Ether(src=smac,dst=dmac)
ipv6=IPv6(nh=17, src=sipv6, dst=dipv6, version=6, hlim=255, fl=0, tc=0)
for i in range(1000):
sendp(ether/ipv6/UDP(sport=10000,dport=10000), iface=iface)
time.sleep(1)
icmp6 MLD
# https://www.idsv6.de/Downloads/IPv6PacketCreationWithScapy.pdf
#!/bin/python3
from scapy.all import *
from scapy.contrib.igmpv3 import IGMPv3,IGMPv3mq,IGMP,IGMPv3gr
from scapy.contrib.igmpv3 import IGMPv3mr
import os, sys
for iface in os.listdir('/sys/class/net/'):
if iface != 'lo' and iface != 'bonding_masters':
break
srcmac = open("/sys/class/net/" + iface + "/address", "r").read()
base = IPv6(src='2009::9', dst='ff02::16', hlim=1)
hbh = IPv6ExtHdrHopByHop(options = RouterAlert())
mlq = ICMPv6MLReport(mladdr="ff15::11",mrd=1)
packet=Ether(src=srcmac)/base/hbh/mlq
sendp(packet,iface=iface)