I am trying to read list of destination IP's from a pcap file, the problem is when I run the while loop a get this error
Traceback (most recent call last):
File "/root/PycharmProjects/pcap/pcap.py", line 10, in <module>
print(pcap[4]['IP'].show())
File "/root/venv/pcap/lib/python3.7/site-packages/scapy/packet.py", line 1171, in __getitem__
raise IndexError("Layer [%s] not found" % lname)
IndexError: Layer ['IP'] not found
When I checked Wireshark, I found that error appears because of requests made by vmware, since I wrote this code on a Kali virtual machine. Here is my code
from scapy.all import *
from nmap import *
from collections import OrderedDict
scanner = nmap.PortScanner()
pcap = rdpcap('/root/Downloads/nakerah.pcap')
ip_list = []
x = 0
while x < 4:
host_ip = pcap[x]['IP'].dst
ip_list.append(host_ip)
final_list = list(OrderedDict.fromkeys(ip_list))
x += 1
print(final_list)
The error tells you exactly what you need to know.
IndexError: Layer ['IP'] not found
One of the packets in your packet captures that does not contain an IP layer. You need to check if the IP layer exists before accessing it. For example, an ARP packet will not have an IP layer and will break your code.
Using this pcap from wireshark's sample captures, we can get the dest IPs by checking if the IP layer exists.
# print_ips.py
from scapy.all import rdpcap
ip_list = []
pkts = rdpcap('allen_test.pcap')
# Limit analysis to 20 packets for brevity
twenty_pkts = pkts[:20]
for packet in twenty_packets:
# This check is what you are missing
if 'IP' in packet:
dest_ip = packet['IP'].dst
ip_list.append(dest_ip)
print("Out of", len(twenty_packets), "packets,", len(ip_list), "were IP packets.")
print("Dest IPs", ip_list)
Running this in the shell, we get
$ python print_ips.py
WARNING: DNS decompression loop detected
Out of 20 packets, 7 were IP packets.
Dest IPs ['172.19.255.255', '172.19.255.255', '172.19.255.255', '172.19.255.255', '224.0.0.9', '172.19.0.240', '172.19.0.240']
Related
In my python for cyber security class, I have gotten tasked with creating a port scanner using Scapy. I am running python 3.9.10. here is the code.
from http.client import ResponseNotReady
from scapy.all import *
from scapy.layers.inet import IP, TCP
import logging
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
import sys
if len(sys.argv) !=4:
print('usage: %s target startport endport' % (sys.argv[0]))
sys.exit(0)
target = str(sys.argv[1])
startport = int(sys.argv[2])
endport = int(sys.argv[3])
print(f'scanning {target} for open TCP ports\n')
if startport==endport:
endport+=1
for x in range(startport,endport):
packet = IP(dst=target)/TCP(dport=x,flags='S')
response = sr1(packet,timeout=0.5,verbose=0)
if response.haslayer(TCP) and response.getlayer(TCP).flags==0x12:
print(f'Port {str(x)} is open!\n')
sr(IP(dst=target)/TCP(dport=response.sport,flags='R'),timeout=0.5,verbose=0)
print('Scan is complete!\n')
The error I am getting is essentially a none type. Here it is.
\1pyCodePrac>py 4-5Assign.py 8.8.8.8 80 80
scanning 8.8.8.8 for open TCP ports
Traceback (most recent call last):
File "E:\School\CNA 256\1pyCodePrac\4-5Assign.py", line 27, in <module>
if response.haslayer(TCP) and response.getlayer(TCP).flags==0x12:
AttributeError: 'NoneType' object has no attribute 'haslayer'
It seems to be the variable "response" and where it's defined. It's supposed to get a response, but instead, it's getting nothing. I did a print(response) with a time.sleep(3) after it, just to see, and it is coming up as None
Any help?
You cannot assume that your SYN packet will eventually be followed by a response even if you set its timeout parameter to a large value. It may indeed be the case that your SYN packet is filtered at some point between your machine and the destination host or that your SYN packet has just been ignored by the destination host or more simply that the destination host is just down.
In that case (if no response has been received) sr1 will return None. So you have to adjust your test to handle the situation where no response was received:
if response is not None and response.haslayer(TCP) and response.getlayer(TCP).flags==0x12:
Also note that your packets can be accessed like dictionaries whose keys are layers and values are payloads. So this test can be rewritten as:
if response is not None and TCP in response and response[TCP].flags == 0x12:
which is more readable IMHO.
I have a wireshark .pcap file and i want to get all the assets (urls, ip's, pc names etc..) from this file.
i tried to use some examples i found online, but i'm having some problems getting those items.
i managed to find the dst and src ip address, but thats all.
this is my current code:
import pyshark
cap = pyshark.FileCapture('dor.pcap')
count = 0
for pkt in cap:
ip_source = pkt.ip.__dict__["_all_fields"]["ip.src"]
ip_address = pkt.ip.__dict__["_all_fields"]["ip.dst"]
This should work with your Wireshark pcap file to obtain the source and destination addresses and ports. The output could be modified (e.g., csv, dictionary) to fit your specific requirements.
Please provide more details on the other items that you would like to parse from a pcap file.
import pyshark
def network_conversation(packet):
try:
protocol = packet.transport_layer
source_address = packet.ip.src
source_port = packet[packet.transport_layer].srcport
destination_address = packet.ip.dst
destination_port = packet[packet.transport_layer].dstport
return (f'{protocol} {source_address}:{source_port} --> {destination_address}:{destination_port}')
except AttributeError as e:
pass
capture = pyshark.FileCapture('test.pcap')
conversations = []
for packet in capture:
results = network_conversation(packet)
if results != None:
conversations.append(results)
# this sorts the conversations by protocol
# TCP and UDP
for item in sorted(conversations):
print (item)
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 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'm attempting to write a Python script which uses the Scapy module to ping an internal IP range to determine which IP's are online. I've got this so far:
#!/usr/bin/python
from scapy.all import *
conf.verb = 0
for ip in range(0, 256):
packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
reply = sr1(packet)
if "192.168." in reply.src:
print reply.src, "is online"
And the program will sit for a while doing nothing, and then if I kill it with CTRL+C I get an error message:
Traceback (most recent call last):
File "sweep.py", line 7, in <module>
if "192.168." in reply.src:
AttributeError: 'NoneType' object has no attribute 'src'
However if I try it with a single IP address, instead of a range, it works. Like this:
#!/usr/bin/python
from scapy.all import *
conf.verb = 0
packet = IP(dst="192.168.0.195", ttl=20)/ICMP()
reply = sr1(packet)
if "192.168." in reply.src:
print reply.src, "is online"
Anyone know how I can fix this problem? Or do you have any other ideas on how I can ping an IP range with Scapy, to determine which hosts are online?
You just need to ensure that reply is not NoneType as illustrated below... sr1() returns None if you get a timeout waiting for the response. You should also add a timeout to sr1(), the default timeout is quite absurd for your purposes.
#!/usr/bin/python
from scapy.all import *
TIMEOUT = 2
conf.verb = 0
for ip in range(0, 256):
packet = IP(dst="192.168.0." + str(ip), ttl=20)/ICMP()
reply = sr1(packet, timeout=TIMEOUT)
if not (reply is None):
print reply.dst, "is online"
else:
print "Timeout waiting for %s" % packet[IP].dst
You can't show reply.src field if the return of variable is null. In other words, you need to validate if the variable has return with some value (if the ping was successful). You can make an IF condition to get the .src field only when variable is not null.
FTR, Scapy supports implicit generators.
This works:
ans, unans = sr(IP(dst="192.169.0.1-255")/ICMP(), timeout=2)
Then iterate through the answers.
It is probably much better :)