Parse out UDP information with tshark (Wireshark) or Python - python

I am broadcasting UDP packets between 2 machines and listening to them on a third machine. I can see the packets in Wireshark and need any easy way to obtain the "Data" portion of the UDP packets. I have been able to dump the packet infromation to a file using tshark
C:>tshark -V -R "udp" > C:/test.txt
However, this prints out everything in the packet, and i only want to print out the "Data" portion. Is there a way to do this?
Also, if there is a way to capture this in Python, that would be great as well. I have set up the following code:
Host = "myip"
Port = 5000
While True:
sock = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
sock.bind((Host,Port))
data = sock.recv(4096)
sock.close()
When i implement this code, using my "listening" pc, no data is received.
When i implement this code, using one of my two communicating pcs, "The requested address is not valid in its context"
Mind you, I see all the data being passed between the 2 pcs in Wireshark on my "listening" pc.
Thanks!

McFly,
If you want to do sniffing and display/parse packets in Python, Scapy is the way to go here. Just drop tshark as Scapy can automatically do 99% of what tshark can do out of the box.

Related

Sending packet with python and scapy to local address doesn't work

I am trying to send a udp packet to a local ip address. This is my example code:
from scapy.all import *
if __name__ == "__main__":
send(IP(dst="127.0.0.1")/UDP(sport=19600,dport=39600)/"abc")
I've started netcat to catch what I am going to send:
nc -ul 39600
Then I am executing the code:
python3 example_scapy_send.py
Nothing is received by the listening netcat.
At the same time I have started wireshark and I can see the packet is sent.
If I send a packet using netcat it is ariving on the listening netcat.
usr#dev:/home/usr# nc -u 127.0.0.1 39600
test
Wireshark:
The only difference I can see is that at layer 2 - destination address is multicast/broadcast when sent with scapy and unicast when sent with netcat. But this is not something I can control.
If I sent the same packet with scapy to another ip on the network (another host) the packet is received (by netcat). So the issue applies only if I am sending to a local address. Tested with any local ip. Not only 127.0.0.1. I've also tested with sendp and sr scapy functions but the result is the same.
Something more: if I've started another scapy script to listen to UDP/39600 (instead of netcat) I can see/I am receiving the packet I've sent.
Any ideas what is wrong?
tests done under ubuntu/scapy 2.5/python 3.8
I couldn't find a way to make it work with send/sendp scapy functions, but instead I tried using standart python socket and it did the job:
someSocket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
someSocket.sendto(bytes('abc', "utf-8"), (127.0.0.1, 39600))
Acording to Scapy troubleshooting:
The loopback interface is a very special interface. Packets going through it are not really assembled and disassembled. The kernel routes the packet to its destination while it is still stored an internal structure. What you see with tcpdump -i lo is only a fake to make you think everything is normal. The kernel is not aware of what Scapy is doing behind his back, so what you see on the loopback interface is also a fake. Except this one did not come from a local structure. Thus the kernel will never receive it.
On Linux, in order to speak to local IPv4 applications, you need to build your packets one layer upper, using a PF_INET/SOCK_RAW socket instead of a PF_PACKET/SOCK_RAW (or its equivalent on other systems than Linux)
So you may need to add line before sending packet:
conf.L3socket = L3RawSocket
In your script. That way everything should supposed to work. At least in my environment worked out fine.

generating a spoofed UDP packet in python

how can i create a spoofed UDP packet using python sockets,without using scapy library.
i have created the socket like this
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # UDP
sock.sendto(bytes('', "utf-8"), ('192.168.1.9', 7043))# 192.168.1.9dest 7043 dest port
This is one of the first results for google searches like "spoofing udp packet python" so I am going to expand #Cukic0d's answer using scapy.
Using the scapy CLI tool (some Linux distributions package it separately to the scapy Python library ):
pkt = IP(dst="1.1.1.1")/UDP(sport=13338, dport=13337)/"fm12abcd"
send(pkt)
This sends a UDP Packet to the IP 1.1.1.1 with the source port 13338, destination port 13337 and the content fm12abcd.
If you need to a certain interface for some reason (like sending over a VPN that isn't your default route) you can use send(pkt, iface='tun0') to specify it.
One difference to #Cukic0d's answer is that this solution is more flexible by sending a layer 3 packet with send instead of a layer 2 packet with sendp. So it isn't necessary to prepend the correct Ethernet header with Ether() which can cause issues in some scenarios, e.g.:
WARNING: Could not get the source MAC: Unsupported address family (-2) for interface [tun0]
WARNING: Mac address to reach destination not found. Using broadcast.
I think you mean changing the source and destination addresses from the IP layer (on which the UDP layer is based).
To do so, you will need to use raw sockets. (SOCK_RAW), meaning that you have to build everything starting from the Ethernet layer to the UDP layer.
Honestly, without scapy, that’s a lot of hard work. If you wanted to use scapy, it would take 2 lines:
pkt = Ether()/IP(src=“...”, dst=“...”)/UDP()/...
sendp(pkt)
I really advice you to use scapy. The code itself is quite small so I don’t see a reason not to use it. It’s defiantly the easiest in python

scapy - Missing data in sniffed TCP packets

I have an application that sends data over a TCP connection to a production server. I need to sniff the contents of that TCP connection and resend it to a debug server.
I've gotten quite close with this:
from scapy.all import *
packets = 0
def dup_pkt(pkt):
global packets
read = raw(pkt[TCP].payload)
print(str(packets))
s.sendall(read)
print("connecting")
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("x.x.x.x", 12345))
print("connected")
print("sniffing")
pkts = sniff(prn=dup_pkt, filter="tcp dst port 12345 and not host x.x.x.x") # don't sniff the packets we're resending
The problem is that the packets appear to be missing data in the first two headers. I have set the debug server to save each received packet to a file, and set the application to connect directly to the debug server to compare the known good packet data with what the sniffer is sending. In the first packet, the first 1546/2079 bytes are good, but after that, each byte is zero instead of full of the correct data. In the second packet, the first 11 bytes are missing, but the rest is good.
Interestingly, after those initial two big setup packets, the remainder of the TCP packets seem to be sniffed properly - perhaps because they are usually far simpler and less than 40 bytes each.
Is there a better way to read packet data? Am I missing something? Unfortunately I don't have access to the source of the application, so I can't tell if it's doing anything special with those two big packets I'm having trouble with.
The issue with the first packet could indicate a problem in your operating system's TCP stack w.r.t. fragment reassembly.
In any case, try using another tool like tcpdump or wireshark to capture the packets. If they have the same problem, the problem lies with your operating system. If not, it could be a bug or configuration issue with scapy.
It could also mean that your IP packets are fragmented. Scapy does not automatically defragment packets, but fragments them.
you need to use the defrag function, or defragment (have a look at help(defrag) ), on the received packet list.
Maybe the packet you are checking is a fragment

How to capture the packets that you send in Scapy?

I am sending packets using:
send(IP(dst="192.168.1.114")/fuzz(UDP()/NTP(version=4)), loop=1)
But I am not able to capture these packets in any other nearby machine (including the one with IP 192.168.1.114) which is on the same network. I am using wlan as my interface.
I also tried to sniff and then replay using scapy but I am still not able to capture those packets.
i would first try to capture the traffic on the sender machine with tcpdump while executing your program:
tcpdump -i any udp dst 192.168.1.114
if you can see the traffic leaving the source host it may be that it does not arrive on the target host. UDP packets are the first packets to be dropped by any network device and as it is the nature of UDP it wont get retransmitted. if you are sure the packet leaves the source verify if it arrives at the target:
tcpdump -i any upd dst 192.168.1.114
Another point to check is your firewall settings. It could be either on the source or target system that your firewall is blocking those requests.
I finally resolved this. Here is the checklist I made which might help others when dealing with replaying/fuzzing using scapy.
Check if all IP addresses you are dealing with are alive in the
network (use ping)
Understand the difference between send() (layer 3)and sendp() (layer 2)
If mutating existing packet make sure to
remove the checksum (using 'del') and recalculate the checksum
either using show2() or using str to convert packets to string
and then converting them back to packets
You should use Wireshark, or the sniff function in Scapy and make it pretty print the contents on the screen:
sniff(lambda x:x.show())

Python Raw Sockets (Windows): Sniffing Ethernet Frames

I have seen several examples of creating sockets to sniffing for IP Packets, for example using:
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
What I am trying to achieve, is sniffing for Ethernet Frames and analysing the data received in Windows. The packets I am interested in are PPPoE Frames not containing IP.
In Linux (using python) I was able to achieve this using :
s = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(3))
s.setsockopt(socket.SOL_SOCKET, IN.SO_BINDTODEVICE, struct.pack("%ds"%(len("eth0")+1,),"eth0"))
while condition:
pkt = s.recvfrom(1500)
addToQueue(filter(pkt))
Now due to the differences betweeen linux sockets and WinSock2 API, I am having the following compatibility issues :
There is no IN package for windows. That means the SO_BINDTODEVICE is not present. How do I sniff everything coming on eth0 interface?
What should I use for protocol option in socket() constructor as I dont want to limit it to IPPROTO_IP.
Can anyone point me to the right direction ? I went through similar questions but none of them really solved my problem as they were all concerned with IP Packet sniffing
Note: I know libraries like Scapy could be used for sniffing, but it loses packets if we are trying to do any elaborate filtering (or use the prn function) and does not suit what I am trying to do. Raw sockets fit my need perfectly.
I can't verify this without a Windows box but I think all you need is ...
HOST = socket.gethostbyname(socket.gethostname())
s = socket.socket(socket.AF_INET, socket.SOCK_RAW)
s.bind((HOST, 0))
s.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
while condition:
pkt = s.recvfrom(1500)
addToQueue(filter(pkt))
Additionally, I'd recommend that you look in to using something like pypcap (or another libpcap wrapper) instead.
FTR
Note: I know libraries like Scapy could be used for sniffing, but it loses packets if we are trying to do any elaborate filtering (or use the prn function) and does not suit what I am trying to do. Raw sockets fit my need perfectly.
If you get Scapy and set conf.use_pcap = False, you can create a Windows raw socket by using sock = conf.L2socket() which according to yourself wont "lose packets".
You can then call recv() or recv_raw() on it like a regular socket, if really you want not to use Scapy's dissection.

Categories