from scapy.all import *
def print_summary(pkt):
for i in pkt:
sport=[pkt[TCP].sport]
if (sport[i]!=sport[i+1]):
packet=sport
print packet
sniff(offline="/root/ip2.pcap",prn = print_summary)
You could use rdpcap to read the .pcap file, create a list, and append the port number to the list after checking if it is already there or not.
from scapy.all import *
pcap = rdpcap('test_pcap.pcap')
ports = []
for pkt in pcap:
if pkt.haslayer(TCP):
if pkt.sport in ports:
pass
else:
ports.append(pkt.sport)
print(ports)
Related
I have the following code to scan a single host on the given range of ports. I want to modify this so that the input will also accept CIDR slash notation(e.g. google.com/34 or 8.8.8.8/34) (i.e. in addition to a single domain name or IP address).
How can I do this?
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
import sys
from scapy.all import *
# Define end host and TCP port range
hostInput = input("Enter a remote host to scan: ")
host = socket.gethostbyname(hostInput)
port_range = [21,22,23,25,53,80,110,135,137,138,139,443,1433,1434,8080]
# Send SYN with random Src Port for each Dst port
for dst_port in port_range:
src_port = random.randint(1025,65534)
resp = sr1(
IP(dst=host)/TCP(sport=src_port,dport=dst_port,flags="S"),timeout=1,
verbose=0,
)
if resp is None:
print(f"{host}:{dst_port} is filtered (silently dropped).")
elif(resp.haslayer(TCP)):
if(resp.getlayer(TCP).flags == 0x12):
# Send a gratuitous RST to close the connection
send_rst = sr(
IP(dst=host)/TCP(sport=src_port,dport=dst_port,flags='R'),
timeout=1,
verbose=0,
)
print(f"{host}:{dst_port} is open.")
elif (resp.getlayer(TCP).flags == 0x14):
print(f"{host}:{dst_port} is closed.")
elif(resp.haslayer(ICMP)):
if(
int(resp.getlayer(ICMP).type) == 3 and
int(resp.getlayer(ICMP).code) in [1,2,3,9,10,13]
):
print(f"{host}:{dst_port} is filtered (silently dropped).")
You can try using
host = Net(hostInput)
Net is the util class Scapy uses to handle IPv4 addresses formats. If you pass it to a packet, sr( will send a packet to each host.
However I'm not sure how plug and play this is going to be: the use of sr1 restricts the output to a single packet, so you're probably going to have to change that to sr (which gives you a list of all answers)
Is it possible to send a spoofed packet with another ip source?
I've searched on the net and I found out that I need to use scapy library. I have this script that I found:
import sys
from scapy.all import *
if len(sys.argv) != 4:
print ("Usage: ./spoof.py <target> <spoofed_ip> <port>")
sys.exit(1)
target = sys.argv[1]
spoofed_ip = sys.argv[2]
port = int(sys.argv[3])
p1=IP(dst=target,src=spoofed_ip)/TCP(dport=port,sport=5000,flags='S')
send(p1)
print ("Okay, SYN sent. Enter the sniffed sequence number now: ")
seq=sys.stdin.readline()
print ("Okay, using sequence number " + seq)
seq=int(seq[:-1])
p2=IP(dst=target,src=spoofed_ip)/TCP(dport=port,sport=5000,flags='A',
ack=seq+1,seq=1)
send(p2)
print ("Okay, final ACK sent. Check netstat on your target :-)")
But I don't get what does it mean "Enter the sniffed sequence number now:"
Also, is it possible to avoid using scapy, and use socket library instead? If yes, can you tell me the way?
solved on my own using scapy library:
from scapy.all import *
A = "192.168.1.254" # spoofed source IP address
B = "192.168.1.105" # destination IP address
C = RandShort() # source port
D = 80 # destination port
payload = "yada yada yada" # packet payload
while True:
spoofed_packet = IP(src=A, dst=B) / TCP(sport=C, dport=D) / payload
send(spoofed_packet)
I have a pretty simple script which supposed to duplicate packets using scapy:
from scapy.all import *
import pprint
ips = [
"192.168.0.1",
"192.168.0.2",
"192.168.0.3",
"192.168.0.4",
"192.168.0.5",
"192.168.0.6",
"192.168.0.7"
]
def dup_pkt(pkt):
pprint.pprint(pkt)
if pkt[IP].dst == "10.0.0.1":
for ip in ips:
pkt2 = copy.deepcopy(pkt)
pkt2[IP].dst = ip
print "Packet1:",pkt[IP].dst,"Packet2:",pkt2[IP].dst
send(pkt2)
pkts = sniff(prn=dup_pkt, filter="port 53", store=0, count=2)
Instead of the for loop, I wish to send it to the multiple destination all at once. I thought about forking processes which each one will send the packets but it still leaves me with the for loop.
Also - send() is very slow, but sendp() does not fit as I have different destinations.
I've read this one: how to send one udp packet multiple time in scapy ? but there is no answer there.
How can I send multiple packets at once?
Thanks
The send() function can receive a list of packets to send:
def dup_pkt(pkt):
pprint.pprint(pkt)
if pkt[IP].dst == '10.0.0.1':
pkts = []
for ip in ips:
pkt2 = pkt.copy() # use the copy method rather than copy.deepcopy
pkt2[IP].dst = ip
pkts.append(pkt2)
print "Packet1: ", pkt[IP].dst, " Packet2: ", pkt2[IP].dst
send(pkts) # send all packets at once
I built a network sniffer in Scapy but it can't handle the rate of packets I am sniffing (it adds 15-20 minutes of latency which is just unacceptable). I have used Pcapy before in the past at this speed with success, but this time to save me having to re-write all my parsing code that uses Scapy, I want to convert a packet received by Pcapy into a Scapy IP object. The problem is when I try to do this, the IP's and protocol numbers I get are scrambled/unusable, like Scapy is reading the wrong section of the packet.
Some example code below:
#!/usr/bin/python
from pcapy import findalldevs, open_live
from impacket import ImpactDecoder, ImpactPacket
from scapy.all import *
def sniff():
interface = "eth3"
print "Listening on: %s" % interface
# Open a live capture
reader = open_live(interface, 65535, 1, 100)
# Set a filter to be notified only for TCP packets
reader.setfilter('ip proto \\tcp')
# Run the packet capture loop
reader.loop(0, callback)
def callback(hdr, data):
pkt = IP(data)
if IP in pkt:
print pkt[IP].dst
# Parse the Ethernet packet
#decoder = ImpactDecoder.EthDecoder()
#ether = decoder.decode(data)
# Parse the IP packet inside the Ethernet packet
#iphdr = ether.child()
# Parse the TCP packet inside the IP packet
#tcphdr = iphdr.child()
# Only process SYN packets
#if tcphdr.get_SYN() and not tcphdr.get_ACK():
# # Get the source and destination IP addresses
# src_ip = iphdr.get_ip_src()
# dst_ip = iphdr.get_ip_dst()
# # Print the results
# print "Connection attempt %s -> %s" % (src_ip, dst_ip)
def main():
sniff()
if __name__ == "__main__":
main()
And an example of the output:
30.184.113.84
0.120.231.205
30.184.113.91
5.64.113.97
0.120.231.206
21.248.113.98
0.120.231.207
0.120.231.208
0.120.231.209
0.120.231.210
0.120.231.211
0.48.243.73
As you can see these IP's dont make sense, where do you think I am going wrong. Eth3 is connected to a NetGear mirror port.
Thanks for your time.
Never mind, just me being an idiot, I blame bank-holiday Mondays. I was trying to detect the packet from the wrong layer. Convert raw to Ether and Scapy does the rest of the work for me.
def callback(hdr, data):
pkt = Ether(data)
if IP in pkt:
print pkt[IP].dst
else:
print list(pkt)
Cheers
I want to read a pcap file using python scapy, manipulate the TCP payload (e.g. delete the current payload and replace it with 0s) and write the manipulated packets to a new pcap file.
Here's a solution using pypcap and dpkt. It assumes that IP is the L2 protocol.
import dpkt
from dpkt.ip import IP
from dpkt.tcp import TCP
for ts, raw_pkt in pcap.pcap(file_path):
ip = IP(raw_pkt[14:])
if(type(ip) != IP):
continue
tcp = ip.data
if(type(tcp) != TCP):
continue
do_something_with(tcp.data)
FTR, to answer the op question,
from scapy.all import *
with PcapWriter("output.pcap", sync=True) as outs:
with PcapReader("input.pcap") as ins:
for pkt in ins:
if TCP in pkt:
pkt[TCP].remove_payload()
outs.write(pkt)