I want to create ICMP fragmentation needed packet using Scapy. When I give type = 3 and code =4 and display the message again, it shows me type =destination unreachable and code = fragmentation needed. But I also want to see one more field associated with this ICMP "next-hop MTU". DO I need to create custom field or is there any other way I can create it.
Here is what I'm doing.
i=ICMP()
i.display()
type = 3
code = 4
checksum = 0
unused = 0
Display it again
i.display ()
type= destination unreachable
code = fragmentation needed
checksum =0
unused = 0
from other references it seems you can use:
i.unused = mtu
Related
Is there a way to extract the second IP address from a command-line output?
Command output
Manual NAT Policies (Section 1)
60 (sdf-app-vip) to (outside) source dynamic d-d-servers interface destination static obj-15.34.4.32 obj-159.13.9.12
translate_hits = 0, untranslate_hits = 0
61 (ds-app-vip) to (outside) source dynamic d-d-servers interface destination static obj-15.1.95.176 obj-15.13.5.176
translate_hits = 0, untranslate_hits = 0
152 (sd-app-vip) to (outside) source dynamic d-d-servers interface destination static obj-19.36.11.12 obj-19.36.15.12
translate_hits = 0, untranslate_hits = 0
Auto NAT Policies (Section 2)
115 (nk-app-vip) to (customer-vrf-sd) source static nat-10.19.2.190-customer-vrf-transit 10.223.2.2
translate_hits = 0, untranslate_hits = 4652
My code is able to extract both IP, but am not able to filter the second IP.
Code:
import re
#Truncate file
ft=open('puip_only.txt','w')
ft.truncate()
ft.close()
#Filter IP's from object group IP output
cip=open('puip.txt', 'r')
cs=cip.readlines()
for line in cs:
matches= re.findall(r'[0-9]+(?:\.[0-9]+){3}', line)
newlines=( ' '.join(matches))
outF = open("puip_only.txt", "a")
outF.write(newlines)
outF.write("\n")
outF.close()
Expected output is
159.13.9.12
15.13.5.176
19.36.15.12
10.223.2.2
If you only want the second IP, don't join it with the first:
if len(matches)>=2:
outF.write(matches[1])
instead of
outF.write(newlines)
You can match the following space, word chars and - and then capture the second ip number in group 1.
The group 1 values will be returned by re.findall.
\b[0-9]+(?:\.[0-9]+){3}\s+\w+-([0-9]+(?:\.[0-9]+){3})\b
Regex demo
What is the easiest way to compare IP addresses using Scapy (in Python3.6) and Docker? I have a piece of code that sniffs my Docker bridge network using Scapy sniff(). I want to look at each packet's source IP address, and if it matches the IP address for my container named "plc1", do additional steps. If they don't match, I just return an empty list and move on.
However I cannot figure out how to compare a packet's source IP address to a container name. It really needs to be the container's name and not the ID, since I am running a ton of containers in parallel and looking up ID's to plug into my Python3.6 script is tedious. Any thoughts? I've tried using the Docker SDK but it needs the Container ID, which is what I am trying to avoid...
Sample Python3.6 code, which does not work, included below:
#!/usr/bin/env python3
from scapy.all import *
def find_ports(pkt):
# if src IPaddr matches IP addr of container plc1...
if pkt[IP].src == 'plc1': # THIS DOES NOT WORK
# if there is a match, get some additional packet info
if TCP in pkt:
tcp_dport = pkt[TCP].dport
ip_total_len = pkt.getlayer(IP).len
ip_header_len = pkt.getlayer(IP).ihl * 32 / 8
tcp_header_len = pkt.getlayer(TCP).dataofs * 32 / 8
tcp_seg_len = ip_total_len - ip_header_len - tcp_header_len
sequence_num = pkt[1].ack
return [tcp_dport, tcp_seg_len, sequence_num]
# else if NO MATCHING ip addr's, return blank list...
else:
return []
tempList = sniff(filter="ip", prn=find_ports, iface="br-19f0ba1cf88f")
# if templist not empty...
if tempList:
# send a TCP RST packet...
ip = IP(src="plc1", dst="hmi_pass_thru")
tcp = TCP(sport=502, dport=tempList[0], flags="R", seq=int(tempList[1]), ack=int(tempList[2]) + 1)
pkt = ip / tcp
ls(pkt)
send(pkt, verbose=0)
I'm able to sniff RTS packets without a problem. I'm also able to utilize 'sendp' to send CTS packets. What I'm unable to figure out is how to have Scapy sniff RTS packets and reply to those RTS's with a crafted CTS in real-time. The intent is to send a CTS for every RTS that my AWUS036ACH can hear regardless of the intended device.
import os
import time
from threading import Thread
from scapy.layers.all import Dot11,Dot11Elt,RadioTap,sniff,sendp
def change_channel():
ch = 1
while True:
try:
os.system(f"iwconfig {iface} channel {ch}")
ch = ch % 14 + 1
time.sleep(1)
except KeyboardInterrupt:
break
if __name__ == "__main__":
iface = "wlan0"
channel_changer = Thread(target=change_channel)
channel_changer.daemon = True
channel_changer.start()
def PacketHandler(packet):
if packet.haslayer(Dot11):
if packet.type==1 and packet.subtype==11:
rts_list.append(bssid)
bssid = packet[Dot11].addr2
print("MAC: %s" %(bssid))
sniff(iface=iface, prn=PacketHandler)
i=1
while 1:
time.sleep(.100)
i = i + 1
dot11 = Dot11(type=1, subtype=12, addr1=bssid,ID=0x99)
pkt = RadioTap()/dot11
sendp(pkt,iface=iface, realtime=True)
Why don't you try to add sendp inside your PacketHandler function?
The logic goes like this:
PacketHandler is called upon every received frame
You check whether it's an RTS frame, extract all of the necessary info you need to send a CTS frame
Call sendp with received info
There are ways to write ARP response utilities, take a look for ideas.
My concern is whether it's possible to send a frame while your adapter is put in monitor mode. Unfortunately I can't test it right now.
Recommendation. Try to use BPF filter with sniff. It goes like this:
sniff(iface=iface, filter="type ctl subtype rts", prn=PacketHandler)
And get rid of testing for frame type inside you PacketHandler. This way you will filter for RTS on a kernel level thus performance is increased. Scapy itself can easily miss RTS frames in a dense wireless environment. For more BPF filters applied to 802.11 check man pcap-filter.
I'm tryng to read a Pcap file, and after that I get the Ip's and the realtions between Ip's, I want to transform these relattions in MAC relations but I'm not sure how I have to do it.
trafico= rdpcap('example-01.pcap')
unique_streams =[]
for frame in trafico:
packet = frame[IP]
src = packet.src
dst = packet.dst
layer4_segment = packet.payload.name
sport = packet[layer4_segment].sport
dport = packet[layer4_segment].dport
unique_streams.append(f"{src}:{dst}:{layer4_segment}:{sport}:{dport}")
tre= set(unique_streams)
for k in tre:
print(k)
I have these code to show the Ip's source and destination and also the ports
thanks
I don't know how to transform these relations in MAC relations...
To get the MAC from the packet you need to look at the 'Ether' layer and not the'IP' layer:
e = frame[Ether]
print(e.src,e.dst)
e.src is the MAC for the IP packet.src etc.
I'm trying to write a small code which displays data received from a game (F1 2019) over UDP.
The F1 2019 game send out data via the UDP. I have been able to receive the packets and have separated the header and data and now unpacked the data according to the structure in which the data is sent using the rawutil module.
The struct in which the packets are sent can be found here:
https://forums.codemasters.com/topic/38920-f1-2019-udp-specification/
I'm only interested in the telemetry packet.
import socket
import cdp
import struct
import array
import rawutil
from pprint import pprint
# settings
ip = '0.0.0.0'
port = 20777
# listen for packets
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listen_socket.bind((ip, port))
while True:
# Receiving data
data, address = listen_socket.recvfrom(65536)
header = data[:20]
telemetry = data[20:]
# decode the header
packetFormat, = rawutil.unpack('<H', header[:2])
gameMajorVersion, = rawutil.unpack('<B', header[2:3])
gameMinorVersion, = rawutil.unpack('<B', header[3:4])
packetVersion, = rawutil.unpack('<B', header[4:5])
packetId, = rawutil.unpack('<B', header[5:6])
sessionUID, = rawutil.unpack('<Q', header[6:14])
sessionTime, = rawutil.unpack('<f', header[14:18])
frameIdentifier, = rawutil.unpack('<B', header[18:19])
playerCarIndex, = rawutil.unpack('<B', header[19:20])
# print all info (just for now)
## print('Packet Format : ',packetFormat)
## print('Game Major Version : ',gameMajorVersion)
## print('Game Minor Version : ',gameMinorVersion)
## print('Packet Version : ',packetVersion)
## print('Packet ID : ', packetId)
## print('Unique Session ID : ',sessionUID)
## print('Session Time : ',sessionTime)
## print('Frame Number : ',frameIdentifier)
## print('Player Car Index : ',playerCarIndex)
## print('\n\n')
#start getting the packet data for each packet starting with telemetry data
if (packetId == 6):
speed, = rawutil.unpack('<H' , telemetry[2:4])
throttle, = rawutil.unpack('<f' , telemetry[4:8])
steer, = rawutil.unpack('<f' , telemetry[8:12])
brake, = rawutil.unpack('<f' , telemetry[12:16])
gear, = rawutil.unpack('<b' , telemetry[17:18])
rpm, = rawutil.unpack('<H' , telemetry[18:20])
print (speed)
The UDP specification states that the speed of the car is sent in km/h. However when I unpack the packet, the speed is a multiple of 256, so 10 km/h is 2560 for example.
I want to know if I'm unpacking the data in the wrong way? or is it something else that is causing this.
The problem is also with the steering for example. the spec says it should be between -1.0 and 1.0 but the actual values are either very large or very small.
screengrab here: https://imgur.com/a/PHgdNrx
Appreciate any help with this.
Thanks.
I recommend you don't use the unpack method, as with big structures (e.g. MotionPacket has 1343 bytes) your code will immediately get very messy.
However, if you desperately want to use it, call unpack only once, such as:
fmt = "<HBBBBQfBB"
size = struct.calcsize(fmt)
arr = struct.unpack("<HBBBBQfBB", header[:size])
Alternatively, have a look at ctypes library, especially ctypes.LittleEndianStructure where you can set the _fields_ attribute to a sequence of ctypes (such as uint8 etc, without having to translate them to relevant symbols as with unpack).
https://docs.python.org/3.8/library/ctypes.html#ctypes.LittleEndianStructure
Alternatively alternatively, have a look at namedtuples.
Alternatively alternatively alternatively, there's a bunch of python binary IO libs, such as binio where you can declare a structure of ctypes, as this is a thin wrapper anyway.
To fully answer your question, the structure seems to be:
struct PacketHeader
{
uint16 m_packetFormat; // 2019
uint8 m_gameMajorVersion; // Game major version - "X.00"
uint8 m_gameMinorVersion; // Game minor version - "1.XX"
uint8 m_packetVersion; // Version of this packet type, all start from 1
uint8 m_packetId; // Identifier for the packet type, see below
uint64 m_sessionUID; // Unique identifier for the session
float m_sessionTime; // Session timestamp
uint m_frameIdentifier; // Identifier for the frame the data was retrieved on
uint8 m_playerCarIndex; // Index of player's car in the array
};
Meaning that the sequence of symbols for unpack should be: <H4BQfLB, because uint in ctypes is actually uint32, where you had uint8.
I also replaced BBBB with 4B. Hope this helps.
Haider I wanted to read car speed from Formula 1 2019 too. I found your question, from your question I had some tips and solved my issue. And now i think i must pay back. The reason you get speed multiplied with 256 is you start from wrong byte and this data is formatted little endian. The code you shared starts from 22nd byte to read speed, if you start it from 23rd byte you will get correct speed data.