I want to my UDP data packet to have literately this information for example:
data = "83053163021478010102010370020000000000"
I'm using the follow code to send it which works fine(I can see it going out on wireshark):
listener = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
listener.sendto(data, (IP, PORT))
When I look at the data packet in wireshark i want the (wireshark)data packet == data. How do I declare/convert the data type to make this happen.
I think this should do the trick:
import codecs
data = codecs.decode("83053163021478010102010370020000000000", "hex_codec")
Then you can send data same as you are doing now.
ref: How to create python bytes object from long hex string?
Related
I am trying to work with pcap files. For a preprocessing phase, I am trying to remove an ethernet header using scapy but not sure if this is the right way. Any ideas would like much appreciated. Thanks
I am working on Jupyter notebook and I use python and scapy to read pcap files.
Packet summary:
'Ether / IP / UDP 131.XXX:XXX:XXX:netbios_ns > 131.XXX:XXX:XXX:netbios_ns / NBNSQueryRequest'
Tried:
pk1= ['Ether / IP / UDP 131.XXX:XXX:XXX:netbios_ns > 131.XXX:XXX:XXX:netbios_ns / NBNSQueryRequest']
pkt2=pk1['NBNSQueryRequest']
pk1[Ether].remove_payload()
pk1 /=pkt2
If I understand correctly your question you can access the payload by doing the following:
pk1[1]
pk1.payload
Assuming you have a Packet object with the following layers:
pkt = Ether()/IP()/ICMP()
The packet would look something like this:
print(repr(pkt))
# <Ether type=IPv4 |<IP frag=0 proto=icmp |<ICMP |>>>
pkt is actually an ethernet packet with all the other layers encapsulated as it's payload, so you can just use:
pkt = pkt.payload
# Or
pkt = pkt[Ether].payload
And you'll end up with:
print(repr(pkt))
# <IP frag=0 proto=icmp |<ICMP |>>
You may open capture file in Wireshark, go to File menu, then "Export PDU" and specify a filter of what do you want to export.
Edit: To clarify: it does compile, it just crashes almost immediately after the stream loads. It does connect properly.
So, I've been trying for a very long time to complete this project of mine. What I'm trying to do is send a video feed over sockets using cv2. It works over LAN, not over WAN. I get the following error:
"ConnectionResetError: [WinError 10054] An existing connection was forcibly closed by the remote host"
Code for client(sending video over):
import cv2
import numpy as np
import socket
import pickle
host = "<insert public ip of recipient>"
port = 7643
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # declares s object with two parameters
s.connect((host, port)) # connects to the host & port
cap = cv2.VideoCapture(1)
while cap.isOpened(): # while camera is being used
ret, frame = cap.read() # reads each frame from webcam
if ret:
encoded = pickle.dumps(cv2.imencode(".jpg", frame)[1]) # encoding each frame, instead of sending live video it is sending pictures one by one
s.sendall(encoded)
if cv2.waitKey(1) & 0xFF == ord("q"): # wait until key was pressed once and
break
cap.release()
cv2.destroyAllWindows()
Code for recipient(receiving video):
import cv2
import socket
import pickle
host = "192.168.1.186"
port = 7643
boo = True
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # declares s object with two parameters
s.bind((host, port)) # tells my socket object to connect to this host & port "binds it to it"
s.listen(10) # tells the socket how much data it will be receiving.
conn, addr = s.accept()
while boo:
try:
pictures = conn.recv(256000) # creates a pictures variable that receives the pictures with a max amount of 128000 data it can receive
decoded = pickle.loads(pictures) # decodes the pictures
frame = cv2.imdecode(decoded, cv2.IMREAD_COLOR) # translates decoded into frames that we can see!
cv2.imshow("unique", frame)
if cv2.waitKey(1) & 0xFF == ord("q"): # wait until q key was pressed once and
break
except:
print("Something is broken...")
boo = False
cv2.destroyAllWindows()
s.close()
You apparently got lucky when running this over your LAN. Your code is not correctly sending a stream of images from sender to recipient, because stream sockets like TCP are a little more complicated to use by their nature. The main issue is that your sender is not communicating where each image ends and the next begins, and your recipient similarly is not organizing the data it reads into individual full images.
That is to say, socket.sendall() does not communicate the end of its data to the recipient; you need to include that information in the actual data that you send.
Error handling
But before fixing that, you should fix your error handling on the recipient so that you get more useful error messages. When you write
except:
print("Something is broken...")
You're throwing away something that would have helped you more, like "EOFError: Ran out of input" or "_pickle.UnpicklingError". Don't throw that information away. Instead, print it:
except:
traceback.print_exc()
or re-raise it:
except Exception as err:
# do whatever you want to do first
raise err
or, since you want to let it crash your program, and just want to do cleanup first, do your cleanup in a finally clause, no need for except:
try:
# your code
finally:
# the cleanup
Stream sockets and the sender
Back to your socket code, you're using stream sockets. They send a stream of bytes, and while you can count on them arriving in the correct order, you can't count on when they'll arrive. If you send b"something" and then b"something else", you could receive b"somethingsomething else" all at once, b"somet" and then later b"hing", etc. Your receiver needs to know where the dividing line is between each message, so step one is making there be dividing lines between the messages. There are a few ways to do this:
Making all messages be the same size. Since you're encoding them as JPEGs which can have different sizes based on how it's compressed, that would be a little complicated and maybe not what you want anyway.
Sending an actual marker in bytes, like a newline b"\n" or b"\n\r". This is more complicated to make work for your situation.
Sending the size of each message before you send it. This should be the easiest for your case.
Of course if you're now sending the size of the message, that's just like another message, and your recipient needs to know where this size message ends. Once again you could end the size message with a newline:
s.sendall("{}\n".format(len(encoded)).encode("ascii"))
Or you could pack it into a fixed-length number of bytes, for example 4:
s.sendall(struct.pack("!i", len(encoded)))
The receiver
Your receiver code now needs to read full messages, despite the fact that socket.recv() can return partial messages, or parts of multiple messages together. You can keep a buffer of the incoming data. Add to the end, and then remove full messages from the front:
buf = ''
while boo:
new_data = s.recv(4096)
if not new_data:
# exit, because the socket has been closed
buf += new_data
# if there's a full message at the beginning of buf:
# remove that message, but leave the rest in buf
# process that message
# else:
# nothing, just go back to receiving more
Of course, to find your full message, first you need to get the full size message. If you encoded all your size messages as 4 bytes with struct.pack, just receive data until buf is 4 or more bytes long, then split it into the size and any remaining data:
message_size = struct.unpack("!i", buf[:4])[0]
buf = buf[4:]
Then do the same thing with the image message. Receive data until you have at least message_size bytes of data, split your buffer into the first image message, which you can decode and display, and keep the remainder in the buffer.
Security
The documentation for pickle says:
Warning: The pickle module is not secure. Only unpickle data you trust.
It is possible to construct malicious pickle data which will execute arbitrary code during unpickling. Never unpickle data that could have come from an untrusted source, or that could have been tampered with.
In your case, someone else could in theory connect to your IP on your chosen port and send whatever they wanted to your recipient. If this is just a toy project that wouldn't be left running all the time, the odds are low.
I am using a raspberry pi to send data through TCP/IP where the raspberry pi is the server and my local windows machine is the client.
When I try to read data in python 3, I am getting weird characters for example:
send 20 decimal I receive #4
send 21 decimal I receive #5
send 22 decimal I receive #6
Below is the code running on my local machine:
import socket
host = '192.168.1.100'
port = 25000
mySocket = socket.socket()
mySocket.connect((host,port))
data = mySocket.recv(4).decode()
print (data)
Using python 2 is no problem and characters received with no decoding needed. I know I need to do some decoding on the data but not sure what. Any advise will be very helpful.
I finally figured this by using the following code:
data = mySocket2.recv(4)
newData = int.from_bytes(data, byteorder='big', signed=False)
The sender is sending uint32 data, that is obviously not-signed and is bigEndian. This has to be specified at the receiver side as well (my python3 script). If the sender changes and starts sending int8 data then I will need to update the receiver code to the following:
data = mySocket2.recv(1)
newData = int.from_bytes(data, byteorder='big', signed=True)
P.S. serial or TCP/IP receiving seem to follow the same logic in python, this means that data received requires the same encoding.
I have a raw ethernet Frame that i want to send
How should i do that? i tried to send hex values of a frame but i still cant control packet header that contains src/dst address and ports
import socket
# the public network interface
HOST = socket.gethostbyname(socket.gethostname())
addr = ('46.165.204.237', 10000)
# create a raw socket and bind it to the public interface
s = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_IP)
s.bind((HOST, 0))
netpacket = '\xDE\xB0\x7B\xE5\xA7\xCD\x4C\x17\xEB\x07\x0D\xBC\x08\x00\x45\x00\x00\x92\x68\x94\x40\x00\x78\x06\xDC\x94\x2E\xA5\xCC\xED\xC0\xA8\x01\x02\x27\x10\x07\xC8\x04\xD7\xEA\xEA\xC3\x2A\x4E\xA2\x50\x18\x01\x02\x39\xB0\x00\x00\x3C\x3F\x78\x6D\x6C\x20\x76\x65\x72\x73\x69\x6F\x6E\x3D\x22\x31\x2E\x30\x22\x3F\x3E\x3C\x50\x61\x63\x6B\x65\x74\x3E\x3C\x6F\x70\x65\x72\x61\x74\x69\x6F\x6E\x3E\x33\x3C\x2F\x6F\x70\x65\x72\x61\x74\x69\x6F\x6E\x3E\x3C\x64\x61\x74\x61\x3E\x33\x24\x30\x24\x30\x24\x30\x24\x30\x24\x30\x3C\x2F\x64\x61\x74\x61\x3E\x3C\x65\x78\x74\x64\x61\x74\x61\x3E\x3C\x2F\x65\x78\x74\x64\x61\x74\x61\x3E\x3C\x2F\x50\x61\x63\x6B\x65\x74\x3E'
#netpaket = netpacket.encode('UTF-8')
s.sendto(netpacket.encode('UTF-8'), addr)
Is there in Python a function like sendRaw() or sendRawFrame()?
I know scapy can handle this, but i need to do that many many times, and every time with various payload data. How scapy can be automated? I mean python script that launch scapy creates packet with some payload and send it.
scapy.py
packet1 = IP(dst='46.165.204.237')/TCP(sport=1992, dport=10000)/'<?xml version="1.0"?><Packet><operation>99</operation><data><![CDATA[8 fast]]></data><extdata><![CDATA[]]></extdata></Packet>.'
send(packet1)
The goal for it is to send packet from a port that already in use. If there a better solution for that problem?
Offtopic: maybe someone knows how to send packets through the Open socket id in windows (not only in python)?
You can provide Scapy with raw input by using the Raw layer.
netpacket = Raw('\xDE\xB0...')
To send packets at the ethernet layer - see the documentation for sendp.
sendp(netpacket, iface="eth1")
I want to send data from a Simulink model (running in real time) to a Python script (also running in real time. I am using Simulink's built-in "UDP Send" block, which works, but I don't know how to decode the data I'm getting. This is what my python script looks like:
import sys, struct
from socket import *
SIZE = 1024 # packet size
hostName = gethostbyname('0.0.0.0')
mySocket = socket( AF_INET, SOCK_DGRAM )
mySocket.bind((hostName,5002))
repeat = True
while repeat:
(data,addr) = mySocket.recvfrom(SIZE)
data = struct.unpack('d',data)
print data
I've suspected that the data stream should be something like a double, but while it's giving me numbers they aren't meaningful:
If simulink sends a constant "1", I get an output of "3.16e-322"
If Simulink sends a constant "2", I get an output of "3.038e-319"
Any ideas?
Turns out my network was reversing the packet bits. The solution was to read it in as bit-reversed:
data = struct.unpack('!d',data)
I have no clue why this happens over some networks and not others. Can someone comment on a way to tell if I need to use bit-reversal?
The problem occurs when the sender and receiver has different byte order.
See sys.byteorder.
Best practice should be to always convert to network order when sending and convert again when receiving.