I am trying to use dpkt and pcapy to listen for HTTP responses on an interface
import dpkt
import pcapy
cap = pcapy.open_live('eth0',10000,1,0)
(header,payload) = cap.next()
while header:
packet = dpkt.ethernet.Ethernet(str(payload))
if str(packet.data.data.data).startswith('HTTP'):
h = dpkt.http.Response(str(packet.data.data.data))
(header,payload) = cap.next()
When I run this, it reads the first packet fine. But for the second packet, it ends up reading a wrong value of content-length. The exception is:
cona#vm-02:~$ sudo python cache-pcapy.py
Value of N 160 value of body 160
Value of N 5965717 value of body 1193
Traceback (most recent call last):
File "cache-pcapy.py", line 12, in <module>
h = dpkt.http.Response(str(packet.data.data.data))
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 76, in __init__
self.unpack(args[0])
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 159, in unpack
Message.unpack(self, f.read())
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 90, in unpack
self.body = parse_body(f, self.headers)
File "/usr/local/lib/python2.7/dist-packages/dpkt/http.py", line 59, in parse_body
raise dpkt.NeedData('short body (missing %d bytes)' % (n - len(body)))
dpkt.dpkt.NeedData: short body (missing 5964524 bytes)
The prints for values of N and length of body are from http.py in dpkt where I added this:
elif 'content-length' in headers:
n = int(headers['content-length'])
body = f.read(n)
print 'Value of N {} value of body {}'.format(n,len(body))
if len(body) != n:
raise dpkt.NeedData('short body (missing %d bytes)' % (n - len(body)))
It seems that the wrong bytes are being read as content-length. Why does this happen?
Related
`
def arduino_connect():
global sock
print("Cihazlar axtarılır....")
nearby_devices = bluetooth.discover_devices()
num = 0
for i in nearby_devices:
num+=1
print(str(num)+":"+bluetooth.lookup_name(i)+" MAC: "+i)
if i=="00:21:13:00:EF:19":
selection = num-1
bd_addr = nearby_devices[selection]
port = 1
print("Sən seçdin:" +bluetooth.lookup_name(bd_addr))
sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
sock.connect((bd_addr,port))
`
Traceback (most recent call last):
File "ordubot.py", line 92, in <module>
test(wake)
File "ordubot.py", line 81, in test
response(voice)
File "ordubot.py", line 57, in response
arduino_connect()
File "ordubot.py", line 38, in arduino_connect
print(str(num)+":"+bluetooth.lookup_name(i)+" MAC: "+i)
TypeError: must be str, not NoneType
This code gives this error, can you please help?
In this code, I want python to connect to the mac address specified by bluetooth, but this code gives an error.
When joining items using the + operator, they have to be of the same type.
That means that if bluetooth.lookup_name(i) returns a result which isn't a string (a NoneType in your case) than the concatenation fails.
You can use format string to print the result anyway -
print(f"{}:{} MAC: {}".format(num, bluetooth.lookup_name(i), i)
This will work even if not all of the arguments of format are strings.
There is code here that I am trying to convert from Python2 to Python3. In this section of code, data is received from a socket. data is declared to be an empty string and then concatenated. This is an important Python2 to 3 distinction. In Python3, the 'received' variable is of type Bytes and thus needs to be converted to string first via the use of str(). However, str() needs an encoding parameter. What would the default one be for python 2? I've tried several different encodings (latin-1 and such) but they seem to not match up with a magic value that is defined here after being unpacked here
"\xffSMB seems to decode correctly while "\xfeSMB does not.
I have adjusted the non_polling_read function and the NetBIOSSessionPacket class as follows. Full modified source code available on GitHub.
def non_polling_read(self, read_length, timeout):
data = b''
bytes_left = read_length
while bytes_left > 0:
try:
ready, _, _ = select.select([self._sock.fileno()], [], [], timeout)
if not ready:
raise NetBIOSTimeout
received = self._sock.recv(bytes_left)
if len(received) == 0:
raise NetBIOSError('Error while reading from remote', ERRCLASS_OS, None)
data = data + received
bytes_left = read_length - len(data)
except select.error as ex:
if ex[0] != errno.EINTR and ex[0] != errno.EAGAIN:
raise NetBIOSError('Error occurs while reading from remote', ERRCLASS_OS, ex[0])
return data
class NetBIOSSessionPacket:
def __init__(self, data=0):
self.type = 0x0
self.flags = 0x0
self.length = 0x0
if data == 0:
self._trailer = ''
else:
try:
self.type = data[0]
if self.type == NETBIOS_SESSION_MESSAGE:
self.length = data[1] << 16 | (unpack('!H', data[2:4])[0])
else:
self.flags = data[1]
self.length = unpack('!H', data[2:4])[0]
self._trailer = data[4:]
except Exception as e:
import traceback
traceback.print_exc()
raise NetBIOSError('Wrong packet format ')
When I start the server and issue 'smbclient -L 127.0.0.1 -d 4' from the commandline, the server first creates a libs.nmb.NetBIOSTCPSession which appears to be working well. Once it tries to unwrap the libs.nmb.NetBIOSSessionPacket, it throws an exception.
Traceback (most recent call last):
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3975, in processRequest
packet = smb.NewSMBPacket(data=data)
File "/root/PycharmProjects/HoneySMB/libs/smb.py", line 690, in __init__
Structure.__init__(self, **kargs)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 77, in __init__
self.fromString(data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 144, in fromString
self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 288, in unpack
raise Exception("Unpacked data doesn't match constant value %r should be %r" % (data, answer))
Exception: ("Unpacked data doesn't match constant value b'\\xffSMB' should be 'ÿSMB'", 'When unpacking field \'Signature | "ÿSMB | b\'\\xffSMBr\\x00\\x00\\x00\\x00\\x18C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\x00\\x00\\x00\\x00\\x00\\xb1\\x00\\x02PC NETWORK PROGRAM 1.0\\x00\\x02MICROSOFT NETWORKS 1.03\\x00\\x02MICROSOFT NETWORKS 3.0\\x00\\x02LANMAN1.0\\x00\\x02LM1.2X002\\x00\\x02DOS LANMAN2.1\\x00\\x02LANMAN2.1\\x00\\x02Samba\\x00\\x02NT LANMAN 1.0\\x00\\x02NT LM 0.12\\x00\\x02SMB 2.002\\x00\\x02SMB 2.???\\x00\'[:4]\'')
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3597, in handle
resp = self.__SMB.processRequest(self.__connId, p.get_trailer())
File "/root/PycharmProjects/HoneySMB/libs/smbserver.py", line 3979, in processRequest
packet = smb2.SMB2Packet(data=data)
File "/root/PycharmProjects/HoneySMB/libs/smb3structs.py", line 435, in __init__
Structure.__init__(self,data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 77, in __init__
self.fromString(data)
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 144, in fromString
self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
File "/root/PycharmProjects/HoneySMB/libs/structure.py", line 288, in unpack
raise Exception("Unpacked data doesn't match constant value %r should be %r" % (data, answer))
Exception: ("Unpacked data doesn't match constant value b'\\xffSMB' should be 'þSMB'", 'When unpacking field \'ProtocolID | "þSMB | b\'\\xffSMBr\\x00\\x00\\x00\\x00\\x18C\\xc8\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xfe\\xff\\x00\\x00\\x00\\x00\\x00\\xb1\\x00\\x02PC NETWORK PROGRAM 1.0\\x00\\x02MICROSOFT NETWORKS 1.03\\x00\\x02MICROSOFT NETWORKS 3.0\\x00\\x02LANMAN1.0\\x00\\x02LM1.2X002\\x00\\x02DOS LANMAN2.1\\x00\\x02LANMAN2.1\\x00\\x02Samba\\x00\\x02NT LANMAN 1.0\\x00\\x02NT LM 0.12\\x00\\x02SMB 2.002\\x00\\x02SMB 2.???\\x00\'[:4]\'')
Now it's obvious why this throws an exception. After all, 0xFF does NOT equal ÿ or þ. The question is why is 0xFF the value it tries to write in there in the first place when it should be two different values?
The original python 2 code seems to be quite close to C (using unpack and importing cstring). Is there an obvious benefit to this here or could this be done more simply?
My actual question is:
In the original code, there is no reference to any encoding anywhere. So how is this divined then? Where does it translate 0xFF to ÿ?
client = snap.client.Client()
client.connect('XXX.XXX.X.XXX', 0, 2) #IP address, rack, slot
db = client.db_get(20)
print(db)
intDB = []
for i in range(1, 122):
reading = client.db_read(20, i, 1)
realReading = snap.util.get_real(reading, 0)
array = [realReading]
intDB.append(array)
print(intDB)
This code is supposed to print a DB in bytearrays and then print an array with the floats values of the PLC output. However, when I run the code, I get the following error message:
Traceback (most recent call last):
File "C:/Users/Asus/PycharmProjects/PLC-Connection/main.py", line 19, in <module>
realReading = snap.util.get_real(reading, 0)
File "C:\Users\Asus\PycharmProjects\PLC-Connection\venv\lib\site-packages\snap7\util.py", line 357, in get_real
real = struct.unpack('>f', struct.pack('4B', *x))[0]
struct.error: pack expected 4 items for packing (got 1)
I think that the problem is reading the data:
reading = client.db_read(20, i, 1)
20 is the datablock, i is the index, and you read only 1 byte (3rd parameter).
For retrieving a real, you need 4 bytes read out.
I have the following code for uploading s3 using MultipartUpload.
import logging
import boto3
class UploadS3:
def __init__(self, bucket, prefix):
self.s3 = boto3.resource('s3')
self.bucket = bucket
self.prefix = prefix
def start(self, key):
'''Start to upload a new file'''
self.part_no = 1
self.parts = []
key_path = f'{self.prefix}/{key}'
self.s3obj = self.s3.Object(self.bucket, key_path)
self.mpu = self.s3obj.initiate_multipart_upload()
self.buffer = bytearray()
def upload(self, chunk):
'''Upload a chunk'''
if len(self.buffer) >= 5_000_000:
self._upload_buffer()
self.buffer += chunk
def end(self, part_info={}):
if len(self.buffer):
self._upload_buffer()
part_info['Parts'] = self.parts
mpu_result = self.mpu.complete(MultipartUpload=part_info)
logging.info(f'Upload result: {mpu_result}')
def _upload_buffer(self):
self.part = self.mpu.Part(self.part_no)
print(f'buffer len: {len(self.buffer)}')
resp = self.part.upload(Body=self.buffer)
print({'PartNumber': self.part_no, 'ETag': resp['ETag']})
self.parts.append({'PartNumber': self.part_no, 'ETag': resp['ETag']})
self.part_no += 1
self.buffer = bytearray()
And I created the following test code:
upload_s3 = UploadS3(BUCKET, PREFIX)
key = 'key2'
upload_s3.start(key)
upload_s3.upload(b'0' * 1_000_000)
upload_s3.upload(b'1' * 1_000_000)
upload_s3.upload(b'2' * 1_000_000)
upload_s3.upload(b'3' * 1_000_000)
upload_s3.upload(b'4' * 999_999)
upload_s3.upload(b'abcde')
upload_s3.upload(b'12345')
upload_s3.end({})
However, it got the following error. The length of the first part is 5000004 and the second (last) part is 5, which doesn't need to be over 5M?
buffer len: 5000004
{'PartNumber': 1, 'ETag': '"e616f253def9510e3be2af0854e4c992"'}
buffer len: 5
{'PartNumber': 2, 'ETag': '"db44331bface5c8678770426baf73bc2"'}
Traceback (most recent call last):
File "test1.py", line 35, in <module>
main()
File "test1.py", line 31, in main
upload_s3.end({})
File "/home/x/upload_s3.py", line 31, in end
mpu_result = self.mpu.complete(MultipartUpload=part_info)
File "/apps/external/4/anaconda3/lib/python3.6/site-packages/boto3/resources/factory.py", line 520, in do_action
response = action(self, *args, **kwargs)
File "/apps/external/4/anaconda3/lib/python3.6/site-packages/boto3/resources/action.py", line 83, in __call__
response = getattr(parent.meta.client, operation_name)(*args, **params)
File "/apps/external/4/anaconda3/lib/python3.6/site-packages/botocore/client.py", line 386, in _api_call
return self._make_api_call(operation_name, kwargs)
File "/apps/external/4/anaconda3/lib/python3.6/site-packages/botocore/client.py", line 705, in _make_api_call
raise error_class(parsed_response, operation_name)
botocore.exceptions.ClientError: An error occurred (EntityTooSmall) when calling the CompleteMultipartUpload operation: Your proposed upload is smaller than the minimum allowed size
As of writing this answer, the S3 multipart upload limitations page has the following table:
Item
Specification
Maximum object size
5 TB
Maximum number of parts per upload
10,000
Part numbers
1 to 10,000 (inclusive)
Part size
5 MB to 5 GB. There is no minimum size limit on the last part of your multipart upload.
Maximum number of parts returned for a list parts request
1000
Maximum number of multipart uploads returned in a list multipart uploads request
1000
However, there is a subtle mistake. It says 5 MB instead of 5 MiB (and possibly 5 GB should actually be 5 GiB).
Since you split the parts every 5 000 000 bytes (which are 5 MB but "only" ~4.77 MiB) both the first and second parts are smaller than the minimum size.
You should instead split the parts every 5 242 880 (5 * 1024 ** 2) bytes (or even a bit [no pun intended] more just to be on the safe side).
I submitted a pull request on the S3 docs page.
I'm trying to send some data with a python script to a java server. I use the socket module in python to send and recieve data.
When I send data, I need to specify a header with the datalength in it. The header is as following:
a uint8 for the version number
a uint8 for padding ('reserved')
a uint16 for the length of the data that is sent
That is a total of 32 bits.
I can use numpy to create an array with a certain data type, but the problem is sending this data through the socket. I use the following function to send data:
def send(socket, message):
r = b''
totalsent = 0
# as long as not everything has been sent ...
while totalsent < len(message):
# send it ; sent = actual sent data
sent = socket.send(message[totalsent:])
r += message[totalsent:]
# nothing sent? -> something wrong
if sent == 0:
raise RuntimeError("socket connection broken")
# update total sent
totalsent = totalsent + sent
return r
message = (something_with_numpy(VERSION_NUMBER, PADDING, len(data)))
send(socket, message)
I keep getting TypeErrors with this function. These pop up at len(message), r += message[...], or some other place.
I was wondering if there is a better way to do this, or how to fix this so it does work?
UPDATE: here are some exact error traces. I have tried several different things, so these error traces might have become irrelevant.
Traceback (most recent call last):
File "quick.py", line 47, in <module>
header += numpy.uint8(VERSION_NUMBER)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')
header = numpy.array([VERSION_NUMBER * 255 + PADDING, len(greetData)], dtype=numpy.uint16)
Traceback (most recent call last):
File "quick.py", line 48, in <module>
print(header + greetData)
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S22') dtype('S22') dtype('S22')
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.uint8(VERSION_NUMBER))
File "quick.py", line 13, in send
while totalsent < len(message):
TypeError: object of type 'numpy.uint8' has no len()
Traceback (most recent call last):
File "quick.py", line 47, in <module>
r = send(conn, numpy.array([VERSION_NUMBER], dtype=numpy.uint8))
File "quick.py", line 17, in send
r += message[totalsent:]
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('S3') dtype('S3') dtype('S3')
You'll want to use the struct module to format the header before sending the data.
import struct
def send_message(socket, message):
length = len(message)
version = 0 # TODO: Is this correct?
reserved = 0 # TODO: Is this correct?
header = struct.pack('!BBH', version, reserved, length)
message = header + message # So we can use the same loop w/ error checking
while ...:
socket.send(...)