Transferring File over TCP using Python - python

I am new to python and finding it really difficult trying to understand how to send files using sockets with a tcp connection
i found this code in another question that seems to be useful
Client Side
def _sendFile(self, path):
sendfile = open(path, 'rb')
data = sendfile.read()
self._con.sendall(encode_length(len(data))) # Send the length as a fixed size message
self._con.sendall(data)
# Get Acknowledgement
self._con.recv(1) # Just 1 byte
Server Side
def _recieveFile(self, path):
LENGTH_SIZE = 4 # length is a 4 byte int.
# Recieve the file from the client
writefile = open(path, 'wb')
length = decode_length(self.con.read(LENGTH_SIZE) # Read a fixed length integer, 2 or 4 bytes
while (length):
rec = self.con.recv(min(1024, length))
writefile.write(rec)
length -= sizeof(rec)
self.con.send(b'A') # single character A to prevent issues with buffering
Now i have two problems with this code
First
self._con.sendall(encode_length(len(data)))
in this line it gives me an error saying encode_length is undefined
Secondly these are functions that send and receive file
Where do i call them
Do i first form a TCP Connection and then call these functions
And how exactly to call them , if i call them directly it gives me an error on client side saying _sendFile(self, path) takes two arguments (since i am not passing self just the path)
Thirdly i am using function from os library to get complete path , So i am calling the function like
_sendFile(os.path.abspath("file_1.txt"))
is this the correct way to pass the argument
Sorry i know this question is pretty basic and lame but everywhere online i can basically get the function but not how to call it
right now this is how i am calling the function
serverIP = '192.168.0.102'
serverPort = 21000
clientSocket = socket(AF_INET, SOCK_STREAM)
message = "Want to Backup a Directory"
clientSocket.connect((serverIP, serverPort))
_sendFile(os.path.abspath("file_1.txt"))
Which is basically wrong
I am using the same computer for both Client and Server
Running Python on Ubuntu using terminal

First problem:
It's because you simply haven't defined functions encode/decode_lenght.
Second problem:
Your function is: def _sendFile(self, path): ....
Do you know how to use self? It is used in the classes. So define it without self, or use classes:
Example:
from socket import *
class Client(object):
def __init__(self):
self.clientSocket = socket(AF_INET, SOCK_STREAM)
def connect(self, addr):
self.clientSocket.connect(addr)
def _sendFile(self, path):
sendfile = open(path, 'rb')
data = sendfile.read()
self._con.sendall(encode_length(len(data))) # Send the length as a fixed size message
self._con.sendall(data)
# Get Acknowledgement
self._con.recv(1) # Just 1 byte
>>> client = Client()
>>> client.connect(("192.168.0.102", 21000))
>>> client._sendFile(os.path.abspath("file_1.txt")) # If this file is in your current directory, you may just use "file_1.txt"
And same (almost) for Server.
Where to define these functions? In the code ofcorse! What should your functions do?
OK, an example:
def encode_length(l):
#Make it 4 bytes long
l = str(l)
while len(l) < 4:
l = "0"+l
return l
# Example of using
>>> encode_length(4)
'0004'
>>> encode_length(44)
'0044'
>>> encode_length(444)
'0444'
>>> encode_length(4444)
'4444'
About self:
Just a little bit:
self redirects to your current object, ex:
class someclass:
def __init__(self):
self.var = 10
def get(self):
return self.var
>>> c = someclass()
>>> c.get()
10
>>> c.var = 20
>>> c.get()
20
>>> someclass.get(c)
20
>>>
How does someclass.get(c) work?
While executing someclass.get(c), we are not creating an new instance of someclass.
When we call .get() from an someclass instance, it automaticly sets self to our instance object. So someclass.get(c) == c.get()
And if we try to do someclass.get(), self was not defined, so it will raise an error:
TypeError: unbound method get() must be called with someclass instance as first argument (got nothing instead)
You can use decorator to call functions of a class (not its instance!):
class someclass:
def __init__(self):
self.var = 10
def get(self):
return 10 # Raises an error
#classmethod
def get2(self):
return 10 # Returns 10!
Sorry for my bad explanations, my English is not perfect
Here are some links:
server.py
client.py

Related

Passing from a "lambda" function

In Python I'm using a class out of library. I only want to call certain functions if a certain parameter is set.
For example:
import pyserial
serialobj=serial.Serial()
parameter=0
#The part idk about
def serialobjpass()
if parameter=1:
pass Argument to serialobj.
serialobj might be serialobj.write() or serialobj.recieve()
I would be just like a man in the middle to siphone out calls when i dont want them
Something like this may work:
class Forwarder(object):
def __init__(self, target):
self.target = target
self.parameter = 1
def read(self, n):
print(('READ', n))
if self.parameter:
return self.target.read(n)
else:
return 0
def write(self, data):
print(('WRITE', data))
if self.parameter:
return self.target.write(data)
else:
return len(data)
import pyserial
serialobj = Forwarder(serial.Serial())
...
serialobj.write('HELLO\r\n')
print([serialobj.read(1)])
self.parameter = 0 # Prevent subsequent reads or writes.
serialobj.write('World\r\n') # Won't be written to the serial port.
In this setup the the Forwarder object intercepts all calls to the .read and .write methods, and calls the original .read and .write methods depending on how the parameter is set.

Threading problem with threadpool and objects

I have a problem when using objects and treads.
Below follows a simplified example of the code.
I am using a threadpool to loop over a list of jobs.
class File(object):
def __init__(self, name, streams = [])
self.name = name
self.streams = streams
def appendStream(stream):
self.streams.append(stream)
class Job(object):
def __init__(self, file):
self.file = file
def main():
...
jobs = []
for f in input_files:
f_obj = File(f)
jobs.append(Job(f_obj))
with ThreadPool(processes = 2, initializer = init, initargs = (log, p_lock)) as pool:
pool.map(func = process_job, iterable = jobs, chunksize = 1)
...
The function (process_job) used by the thread pool resides in the same .py file.
def process_job(job):
...
get_info(job.file)
...
This function in turn uses a function (get_info) from a self defined package.
This function creates an argument list and then calls subprocess.check_output().
The subprocess returns a json struct which is looped over to update the contents of the input object.
def get_info(file):
...
args = ["ffprobe", ..., "-i", file.name]
try:
output = subprocess.check_output(args)
except Exception as e:
print(e)
data = info_json.decode('utf8')
json_data = json.loads(data)
for item in info_json:
file.appendStream(item["stream"])
...
The problem is that when running this code the threads spawned by the pool is updating each others file objects.
For example when running this with 5 input files the 5th job.file.streams will contain 5 streams i.e the 4 previous streams that belongs to the other files.
Why is this happening and how can I solve it.
Best regards!
As #torek spotted it seems to be a case of the "Mutable Default Argument".
“Least Astonishment” and the Mutable Default Argument

Python Class inheritance and using variables

I'm new to Python and trying to use class inheritance, and haven't been able to wrap my head around sharing variables. I have two classes so far, Scan and Ping:
scan.py
class Scan(object):
""" Super class for scans """
identifier = str(random.getrandbits(128))
timestamp = int(time.time())
results_dir = "/tmp/{}/".format(identifier)
total_hosts = 0
def __init__(self, target_hosts=None, target_ports=None):
self.__target_hosts = target_hosts
self.__target_ports = target_ports
self.scan_string = "-sT -O --script auth,vuln"
#property
def target_hosts(self):
return self.__target_hosts
#target_hosts.setter
def target_hosts(self, hosts):
""" Sets target hosts for scan """
""" Nmap Expects to be single-spaced '1 2 3' separated """
self.__target_hosts = hosts.replace(", ", " ")
ping.py
import nmap
from .scan import Scan
class Ping(Scan):
""" Ping sweep """
def __init__(self, ping_string, hosts):
super(Scan, self).__init__()
self.ping_string = ping_string
self.hosts = hosts
In my script that pretty much calls everything, I'm attempting:
from models.scan import Scan
from models.ping import Ping
s = Scan()
hosts = "192.168.0.0/24"
s.target_hosts = hosts
pinger = Ping(ping_string, s.target_hosts)
This line doesn't make sense to me ... if Ping inherits from Scan, why does this only work when I call s.targets_hosts ? Shouldn't I be able to call target_hosts from my Ping class like Ping.target_hosts ?
What might be making this hard to understand is that it's an odd example. In your example, the correct input for the hosts parameter that is needed to make an instance of Ping needs to come from a property only accessible from an instance of Ping (or its parent Scan).
Any method (or property) that has self as a parameter relies on a specific instance of that class which needs to be created first. If there was a staticmethod or classmethod they would be callable directly from the class.
You can only get and set target_hosts from a specific instance of the class (in this case either Scan or Ping). If you call Scan.target_hosts or Ping.target_hosts, it will return something like <property at 0x51cd188>. This is basically returning an unusable function from the class. It's saying, "The class dictionary contains instructions here on how to return some useful stuff from AN INSTANCE of <class>."
If you make an instance of Ping or Scan, you now have access to your target_hosts property.
>>> scan = Scan()
>>> scan.target_hosts = 'host1, host2, host3'
>>> scan.target_hosts
'host1 host2 host3'
>>> ping = Ping('stuff', 'nonsense')
>>> ping.hosts
'nonsense'
>>> ping.target_hosts = 'host4, host5, host6'
>>> ping.target_hosts
'host4 host5 host6'
You could run your script with a dummy Ping instance. This should work.
from models.scan import Scan
from models.ping import Ping
dummy = Ping('ignore', 'this')
hosts = "192.168.0.0/24"
dummy.target_hosts = hosts
pinger = Ping(ping_string, dummy.target_hosts)
Or, if Scan had a staticmethod, Ping could use it as well.
class Scan(object):
""" Super class for scans """
identifier = str(random.getrandbits(128))
timestamp = int(time.time())
results_dir = "/tmp/{}/".format(identifier)
total_hosts = 0
def __init__(self, target_hosts=None, target_ports=None):
self.__target_hosts = target_hosts
self.__target_ports = target_ports
self.scan_string = "-sT -O --script auth,vuln"
#staticmethod
def prep_hosts(hosts):
return hosts.replace(", ", " ")
...
and then
from models.scan import Scan
from models.ping import Ping
hosts = "192.168.0.0/24"
input_hosts = Ping.prep_hosts(hosts) # or Scan.prep_hosts(hosts)
pinger = Ping(ping_string, input_hosts)

How can I specify a class method as a callback target in Python?

I'm using the sftp module of paramiko to transfer payloads to remote hosts. Part of the sftp.put call allows for specifying a callback method with signature func(int,int). I'm trying to put a transfer stats method into my Connection class to keep track of payload progress.
Here's the class I have currently:
class Connection:
def __init__(self, endpoint, RSAKeyObj):
self.displayHost = bcolors.OKGREEN + endpoint + bcolors.ENDC
self.transport = paramiko.Transport((endpoint,4022))
self.transport.connect(username='transit', pkey=RSAKeyObj)
self.sftp = paramiko.SFTPClient.from_transport(self.transport)
try:
# initial sftp directory setup
log.info('[{0}]: Setting up remote directories...'.format(self.displayHost))
log.info(self.sftp.mkdir(JAIL_DIR))
except:
pass
def static_vars(**kwargs):
def decorate(func):
for k in kwargs:
setattr(func, k, kwargs[k])
return func
return decorate
#static_vars(counter=0)
def TransferStats(self, transferedBytes, totalBytes):
if (transferedBytes / totalBytes) >= TransferStats.counter:
log.info('Transferred: {}% [{}/{}]'.format(round((transferedBytes/totalBytes)*100,2), transferedBytes, totalBytes))
TransferStats.counter += 0.025
def Transmit(self,targetDir, payloadPath):
displayText = 'Transferring package {}...'.format(payloadPath)
self.TransferStats().counter=0
log.info('[%s] ' % self.displayHost + displayText)
log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats()))
However when I try this, I get the following error:
ERROR - (, TypeError('TransferStats() takes exactly 3 arguments (1 given)',), )
This makes me think that the callback isn't getting recognized by paramiko when it tries to send it's (int,int) because of the self declaration. Is there a way around this?
Your problem is in :
log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats()))
Your error :
ERROR - (, TypeError('TransferStats() takes exactly 3 arguments (1 given)',), )
Is caused by calling TransferStats with no arguments (self.TransferStats() will result in 1 argument : the class (as it is a class method))
Just pass the classmethod:
log.info(self.sftp.put(payloadPath, '%s/%s' % (targetDir,payloadPath), callback=self.TransferStats))
EDIT : You have the same problem in the following line :
self.TransferStats().counter=0
Remove the parentheses :
self.TransferStats.counter=0
Also, your counter attribute on TransferStats is a hidden a global, resetted at each Transmit call.

Python error : X() takes exactly 1 argument (8 given)

I'm trying to bulid an Anonymous FTP scanner , but i got an error about calling function X , i defined X to recieve ony 1 arguement which is the ip address , the same code works if i don't use the loop and send the IPs one by one .
The error is : X() takes exactly 1 argument (8 given)
from ftplib import FTP
import ipcalc
from threading import Thread
def X (ip):
try:
ftp = FTP(ip)
x = ftp.login()
if 'ogged' in str(x):
print '[+] Bingo ! we got a Anonymous FTP server IP: ' +ip
except:
return
def main ():
global ip
for ip in ipcalc.Network('10.0.2.0/24'):
ip = str(ip)
t = Thread (target = X, args = ip)
t.start()
main ()
When constructing Thread objects, args should be a sequence of arguments, but you are passing in a string. This causes Python to iterate over the string and treat each character as an argument.
You can use a tuple containing one element:
t = Thread (target = X, args = (ip,))
or a list:
t = Thread (target = X, args = [ip])

Categories

Resources