# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# # Scapy Basics

from scapy.all import *
ls()

ls(TCP)

lsc()

help(traceroute)

# ### Basic syntax (defining a TCP/IP packet)

packet1 = IP(dst="127.0.0.1")

# ##### Domain name

packet2 = IP(dst="localhost")

# ##### CIDR notation

packet3 = IP(dst="10.0.0/24")

# ##### Mixed domain name and CIDR formulation (send packets to all IPs on the same subnet as IP for www.domain.com)

packet4 = IP(dst="www.domain.com/24")

# ##### Python list

packet5 = IP(dst=['10.0.0.1','10.0.0.2','10.0.0.3'])

# ##### Constructing a full packet (encapsulating)

packet1 = IP(dst="127.0.0.1")/TCP(dport=2222)/"Hello, anyone there?"
ls(packet1)

part1 = IP(dst="127.0.0.10")
part2 = TCP(dport=2222)
message = "Hello, anyone there?"
packet1 = part1/part2/message
ls(packet1)

packet1

packet1.summary()

packet1.show()

packet1.version

packet1[TCP].flags

# ##### Define any field/option (ex: Set ttl and flags to create a RST-ACK packet)

packet6=IP(dst="localhost",ttl=10)/TCP(dport=80,flags="RA")

# ### Sending packets

#Send the contents of packet1 (fire and forget)
send(packet1)

# Send a ICMP echo request to localhost with "Hello" as padding
helloping=IP(dst="127.0.0.10")/ICMP()/"Hello"
send(helloping)

#Send a DNS request (uses UDP), and wait for one response 
ans, unans = sr1(IP(src="192.168.1.173",dst="8.8.8.8")/UDP()/DNS(rd=1,qd=DNSQR(qname="www.scapy.org")))

#Send ping in a loop 4 times. 
help(srloop)
# srloop runs continuously until you hit Ctrl-C (Interrupt here) or set a count.
ping=IP(src="192.168.1.173",dst="192.168.1.141")/ICMP()
ans=srloop(ping,count=4)
#Show the responses
ans[0].show()


# Capture a responses, wait 10 seconds for responses, retry once if no response.
help(sr)
response,unans = sr(packet1,retry=1,timeout=10)

response.summary
# Show unanswered packets
ls(unans[0])

# ##### Three-way handshake

# +
#Firewall interferes with this because its crafted packet, not connection.
dport=80
ip = IP(dst='www.pyptug.org')
syn = TCP(dport=dport,flags='S')
synack = sr1(ip/syn, timeout=10)
ackseq = synack.seq + 1
ack = TCP(dport=dport, flags='A',seq=synack.seq,ack=ackseq)
reply = sr1(ip/ack)



# +
# You can also let python socket handle three way handshake.
# Demo by running nc -l 2222
import socket
s = socket.socket()
s.connect(('127.0.0.1', 2222))
ss = StreamSocket(s, Raw)
ans=ss.sr1(Raw("Hello, who is there?\n"))

ans[0]
# -

# #### Fuzzing

# +
#We can pair python socket with the scapy fuzz function to send netcat random data.
fsocket = socket.socket()
fsocket.connect(('localhost', 2222))
fstream = StreamSocket(fsocket)
fuzzpacket = fuzz(Raw())

for i in range(1,4):
  fstream.send('Fuzz packet ' + str(i) + '\n' )
  fstream.send(fuzzpacket)
  fstream.send('\n')

fsocket.close()

# +
# Generating a set of packets containing fuzz data
fuzzpackets = [p for p in IP(dst='10.10.10.10', ttl=(1,5))/ICMP()/fuzz(Raw())]

#sending the packets
send(fuzzpackets)

#view contents
fuzzpackets

# -

# #### Other uses

#Detect a rogue DHCP server.
conf.checkIPaddr = False
fam,hw = get_if_raw_hwaddr(conf.iface)
dhcp_discover = Ether(dst="ff:ff:ff:ff:ff:ff")/IP(src="0.0.0.0",dst="255.255.255.255")/UDP(sport=68,dport=67)/BOOTP(chaddr=hw)/DHCP(options=[("message-type","discover"),"end"])
ans, unans = srp(dhcp_discover, multi=True, timeout=10)
ans.summary()

# #### Working at Layer 2

#Sends layer2 packets (Ether, Dot11 aka 802.11, Dot3 aka 802.3, STP,  etc)
help(srp)

# #### Sniffing packets

#Sniff runs and calls a lambda function for each packet, in this case displaying a summary.
pr=sniff(count=10, prn=lambda p: p.summary())
pr[5]

# #### Writing to Pcap file

help(wrpcap)

#Write captured packets from sniff to pcap file
wrpcap('/tmp/p.cap', pr)

# #### Reading from Pcap file

help(rdpcap)

#Read three packet from the pcap file and display the summary
pcap_packets=rdpcap("/tmp/p.cap", 3)
pcap_packets

# +
#Manipulate one of the packets 
pcap_packets[2].show()
new_packet=pcap_packets[2]
new_packet.dport = 8889
print("\nNew packet dport: " + str(new_packet.dport) + "\n\n")

ls(new_packet)
# -

# #### Viewing in Wireshark

wireshark(pr)

StarcoderdataJupyterScriptsDedupFiltered