While examining a sniffer code written in Python, I saw that ethernet layer information was obtained from the first 14 characters of a packet and IP layer information from the first 20 characters of the same packet that includes ethernet layer informations. So how is both IP and Ethernet information obtained from the same part of a packet?
In short:
packet = s.recvfrom(65535)
ethernet_layer = packet[:14]
ip_layer = packet[:20] # includes ethernet layer
My opinion:
packet = s.recvfrom(65535)
ethernet_layer = packet[:14]
ip_layer = packet[14:34]
Sniffer code: https://github.com/shreyasgune/Packet-Sniffer/blob/master/sniff-it.py#L47
Related
I am trying to make a TCP packet that is sent to my other computer 500 times. I have created this code:
from scapy.all import *
from scapy.utils import rdpcap
#Create your own packets
data = 'This is a test'
myPacket = Ether(src="00:E0:4C:00:02:42",dst="00:E0:4C:01:08:99")/IP(src="169.254.162.71/16",dst="169.254.208.208/16")/TCP()/Raw(load=data)
print(myPacket.show())
for i in range (0,500):
sendp(myPacket, iface="Ethernet 4") # sending packet at layer 2
The issue is that when I run this code, the computer receives packets with an incrementing Source IP and the Destination IP is wrong, for some reason:
Any help fixing this would be appreciated.
The /16 in your addresses is called a netmask in CIDR notation. It means that your adresses are subnets that include all possible addresses between 169.254.0.0 and 169.254.255.255. (Same for the source IP)
See https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing and https://en.wikipedia.org/wiki/Private_network
Scapy is going to send 256x256x256x256 (accounting for both sr and dst) packets with all possible addresses, starting as you saw with the 0.0 ones. You just need to remove the /16.
I am trying to write a python program to parse packet capture using dpkt module. I have used it on packet captures that had Ethernet and tcpdump captures and it worked fine. However, my current packet capture is raw packet capture that directly has IP header and subsequent protocols and it seems like dpkt is not able to understand these captures. Picture of capture file is attached. enter image description here
The code I had was
f = open(ipfile, 'rb')
pcap = dpkt.pcap.Reader(f)
for ts,buf in pcap:
eth = dpkt.ethernet.Ethernet(buf) //Also tried with eth = dpkt.sll.SLL(buf), but no luck.
ip = eth.data
tcp = ip.data
Any ideas on how to parse such captures?
Thanks !!
I had the same issue with CAIDA pcap. Try
ip = dpkt.ethernet.Ethernet(buf)
I am able to sniff packets in promiscuous mode in python, whilst connected to my wireless network with the below code. I have thoroughly tested this and know this works. I am seeing normal packets across my network:
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
packet = rawSocket.recvfrom(2048)
ethernet_header = packet[0][0:14]
ethernet_detailed = unpack("!6s6s2s", ethernet_header)
print ethernet_detailed
However I want to take it a step further and attempt this with my wifi card in monitor mode, while not connected to any network. I know my card supports Monitor mode as its an alfa AWUS066NH. I use the below code to put py card in monitor mode.
os.system('ifconfig %s down' % interface)
os.system('iwconfig %s mode monitor' % interface)
os.system('ifconfig %s up' % interface)
However now when I run the same code above, that was used in promiscous mode and I only get a single packet who's ethernet_header looks like this ('\x00\x00\x12\x00.H', '\x00\x00\x00\x02l\t', '\xc0\x00')
Why do I no longer see any packets other than the one described? Also how should I be sniffing in monitor mode? I would like to do this without a 3rd party, but will do so if I must.
Since you put your card in monitor mode, you are now looking at 802.11 frames (beacons, probe requests/responses, etc).
What you are seeing in your 0:14 range of bytes is part of the Radio Tap Header that your card prepends to the data captured. The third byte indicates the Radio Tap Header length of 0x12 (18 bytes). Radio Tap Headers are not always 0x12 so 802.11 data begins at the value of the third byte + 1.
There was an extra lenth in
ethernet_header = packet[0][0:14]
which is not required
rawSocket = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
packet = rawSocket.recvfrom(2048)
ethernet_header = packet[0:14]
ethernet_detailed = unpack("!6s6s2s", ethernet_header)
print ethernet_detailed
I am capturing WiFi traffic with tcpdump using the parameter -s 100 (which means I am only capturing the headers of the packets).
When I load the .pcap file and process it with Scapy I do:
pkts = rdpcap(pcapfile)
totalbytes = 0
for pkt in pkts:
totalbytes += len(pkt)
However, as I am truncating the capture, doing len(pkt) will not give me the whole packet length (frame length), it will give me the captured packet length. How can I get the real packet length?
Extra: as I have done in some occasions before, I open the pcap file in wireshark and search for the hex values of interest. But in this case (frame.len) will show the value I am looking for, but I can't find the way wireshark obtains this real packet length without having the whole packet captured.
The rdpcap function uses the PcapReader class for reading packets. Unfortunately this class discards the information you are looking for in the read_packet method, even though it is to be found in the pcap file. So you have to use the RawPcapReader directly.
totalbytes = 0
for pkt, (sec, usec, wirelen) in RawPcapReader(pcapfile):
totalbytes += wirelen
With modern Scapy versions, the proper answer would be to use pkt.wirelen. This only exists in packets read from a pcap
If for some reason you don't want to use RawPcapReader, you can use the len attribute for IPv4 packets.
real_length = pkt[IP].len
truncated_length = len(pkt)
Strangely, the IPv6 layer in Scapy doesn't have the same attribute, but it does have an attribute called plen which is the length of the payload:
payload_length = pkt[IPv6].plen
real_length = payload_length + 40
truncated_length = len(pkt)
I'm trying to send a raw ethernet frame with the length of my data written in the type field. This should be a valid ethernet frame. My code for this looks like this:
ethData = "foobar"
proto =len(ethData)
if proto < 46:
proto = 46
soc = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, proto)
soc.bind((iface, proto))
For some reason I cant read package on the other end. I wonder why. I try to get this package in the interrupt handler of my wireless driver, so this packet has to be droped by my hardware directly or it doesn't get send at all. The question is why.
Sorry, my fault. I just parsed the wrong portion of the packet and didn't get any output. My bad. The package gets there just like it is supposed to.