本文主要是介绍Python编写远程控制工具--被控端的编写,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
本节将开始着手用Python编写远程控制工具。因篇幅限制,这里主要编写两 个常用的功能:命令执行和文件传输。当然,好的远程控制工具的功能远远不只 这些,读者可以在此基础上增加新的功能。具体步骤如下。
1)编写主函数并导入相关模块。我们让被控端主动连接主控端(反向连
接),连接成功时会将自己的主机名发送给主控端。同时,主控端可以进行功能 选择(命令执行和文件传输),所以我们还要写一个死循环,让被控端根据主控 端的回馈信息进入相应的模块:
#!/usr/bin/python3 # -*- coding: utf-8 -*- import socket import struct import os import subprocess if __name__ == '__main__ ' : # 连接主控端 clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) clientSocket.connect(('127.0.0.1 ', 6666)) # 发送被控端的主机名 hostName = subprocess .check_output("hostname") clientSocket.sendall(hostName) # 等待主控端指令 print("[*]Waiting instruction . . .") while True: # 接收主控端的指令,并进入相应的模块 # 接收到的内容为bytes型,需要将decode转换为str型 instruction = clientSocket.recv(10) .decode() if instruction == '1 ' : Execommand(clientSocket) elif instruction == '2 ' : TransferFiles(clientSocket) elif instruction == 'exit ' : break else: pass clientSocket.close() |
2)编写命令执行函数。被控端接收主控端的命令执行,并将命令执行的指 令进行命令、参数分割。因为subprocess模块不能跨工作目录执行命令,所以对一 些命令需要通过其他手段实现。例如,cd命令是无法通过subprocess实现的,执行 cd命令会导致被控端报错,所以需要用os.chdir来代替cd命令。 同时,我们还要增加try{ … }expect{ … }语句,当被控端报错时能及时捕获并 处理错误,重新进入命令执行的循环,提高被控端的可靠性: |
# 命令执行函数
def Execommand(clientSocket) :
while True:
try:
command = clientSocket.recv(1024) .decode()
# 将接收到的命令进行命令、参数分割
commList = command.split()
# 接收到exit时退出命令执行功能
if commList[0] == 'exit ' :
break
# 执行cd时不能直接通过subprocess进行目录切换,
# 否则会出现[Errno 2] No such file or directory错误,
# 要通过os .chdir来切换目录
elif commList[0] == 'cd ' :
os .chdir(commList[1])
# 切换完毕后,将当前被控端的工作路径发给主控端
clientSocket.sendall(os .getcwd() .encode())
else:
clientSocket.sendall(subprocess .check_output(command,
shell=True))
# 出现异常时进行捕获,并通知主控端
except Exception as message:
clientSocket.sendall("Failed to execute, please check your
command!!!" .encode())
# 报错跳出循环时,通过continue重新进入循环
continue
3)编写文件传输主函数。因为文件传输包含文件上传和文件下载。我们让 文件传输主函数对文件传输命令进行命令、参数的分割。若命令为upload ,则调 用文件上传函数,若命令为download ,则调用文件下载函数: |
# 文件传输函数 def TransferFiles(clientSocket) : while True: command = clientSocket.recv(1024) .decode() # 进行命令、参数的分割 commList = command.split() if commList[0] == 'exit ' : break # 若方法为download,则表示主控端需要获取被控端的文件 if commList[0] == 'download ' : Upload File(clientSocket, commList[1]) if commList[0] == 'upload ' : Download File(clientSocket) |
4)编写文件传输的上传函数。在传输文件前,要通过struct模块将需要传输 的文件信息(文件名、文件大小)进行打包发送给接收端,接收端根据传输文件 的大小来对接收到的数据进行计算,防止粘包。当文件信息成功发送后,再真正 进行文件的传输。对文件进行多次分块读取发送,防止因为文件过大导致读取文 件内容时内存不足: |
# 文件上传函数
def Upload File(clientSocket, filepath) :
while True:
upload FilePath = filepath
if os .path.isfile(upload FilePath) :
# 先传输文件信息,用来防止粘包
# 定义文件信息,128s表示文件名长度为128字节,l表示用in t类型来表示文件大小 # 把文件名和文件大小信息进行打包封装,发送给接收端
fileInfo = struct.pack( '128sl ', bytes(os .path.basename(upload FilePath) .
encode( 'utf-8 ')), os .stat(upload FilePath) .st_size)
clientSocket.sendall(fileInfo)
print( '[+]FileInfo send success ! name:{0} size:{1} ' .format(os . path.basename(upload FilePath), os .stat(upload FilePath) .st_ size))
# 开始传输文件的内容
print( '[+]start uploading . . . ')
with open(upload FilePath, 'rb ') as f :
while True:
# 分块多次读,防止文件过大时一次性读完导致内存不足
data = f.read(1024)
if not data:
print("[+]File Upload Over !!!")
break
clientSocket.sendall(data)
break
5)编写文件传输的下载函数。在下载文件前,需要先接收传输文件信息的 包,并拆包得到文件的文件名和大小,这里需要注意的是,拆包后的文件名信息 可能会出现多余的字符,此时需要使用strip方法进行清除。在得到传输文件的大 小信息后,就可以以此为依据,进行文件数据的分块写入: |
# 文件下载函数 def Download File(clientSocket) : while True: # 先接收文件的信息,进行解析 # 长度自定义,先接收文件信息的主要原因是防止粘包 # 接收长度为128sl fileInfo = clientSocket.recv(struct.calcsize( '128sl ')) if fileInfo: # 按照同样的格式(128sl)进行拆包 fileName, fileSize = struct.unpack( '128sl ', fileInfo) # 要把文件名后面的多余空字符去除 fileName = fileName .decode() .strip( '\00 ') # 定义上传文件的存放路径, ./表示当前目录 newFilename = os .path.join( ' ./ ', fileName) print( '[+]FileInfo Receive over ! name:{0} size:{1} ' .format (fileName, fileSize)) # 接下来开始接收文件的内容 # 表示已经接收到的文件内容的大小 recvdSize = 0 print( '[+]start receiving . . . ') with open(newFilename, 'wb ') as f : # 分次分块写入 while not recvdSize == fileSize: if fileSize - recvdSize > 1024: data = clientSocket.recv(1024) f.write(data) recvdSize += len(data) else: # 剩下的内容不足1024时,则把剩余的全部内容都接收写入 data = clientSocket.recv(fileSize - recvdSize) f.write(data) recvdSize = fileSize break print("[+]File Receive over !!!") break |
这篇关于Python编写远程控制工具--被控端的编写的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!