1.代碼及代碼講解,
實驗環境:windows10下的linux子系統+kali虛擬機
import argparse
import socket
import shlex
import subprocess
import sys
import textwrap
import threading
def execute(cmd):
cmd = cmd.strip()
if not cmd:
return
output = subprocess.check_output(shlex.split(cmd),stderr=subprocess.STDOUT)
#subprocess,這個庫提供了一組強大的行程創建介面,讓你可以通過多種方式呼叫其他程式
return output.decode()
class Netcat:
def __init__(self,args,buffer=None):
self.args = args
self.buffer = buffer
self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
#利用傳進來的引數,初始化一個NetCat物件,然后創建一個socket物件
def run(self):
if self.args.listen:
self.listen()
else:
self.send()
#run函式作為NetCat物件的執行入口,它的邏輯其實相當簡單:直接把后續的執行移交給其他兩個函式,如果我們的NetCat物件是接收方,run就執行listen函式;如果是發送方,run就執行send函式
def send(self):
self.socket.connect((self.args.target,self.args.port))
if self.buffer:
self.socket.send(self.buffer)
try:
while True:
recv_len = 1
response = ''
while recv_len:
data = https://www.cnblogs.com/yaolingyu/p/self.socket.recv(4096)
recv_len = len(data)
response += data.decode()
if recv_len < 4096:
break
if response:
print(response)
buffer = input('>')
buffer += '\n'
self.socket.send(buffer.encode())
except KeyboardInterrupt:
print('User terminated')
self.socket.close()
sys.exit()
#先連接到target和port,之后利用try/catch塊,這樣就能直接用Ctrl+C組合鍵手動關閉連接,再通過通過回圈接收資料
def listen(self):
self.socket.bind((self.args.target,self.args.port))
self.socket.listen(5)
while True:
client_socket,_ = self.socket.accept()
client_thread = threading.Thread(target=self.handle,args=(client_socket,))
client_thread.start()
#listen函式把socket物件系結到target和port上,然后開始用一個回圈監聽新連接,并把已連接的socket物件傳遞給handle函式,
def handle(self,client_socket):
if self.args.execute:
output = execute(self.args.execute)
client_socket.send(output.encode())
elif self.args.upload:
file_buffer = b''
while True:
data = client_socket.recv(4096)
print(data.decode)
if data:
file_buffer += data
else:
break
with open(self.args.upload,'wb') as f:
f.write(file_buffer)
message = f'Saved file {self.args.upload}'
client_socket.send(message.encode())
elif self.args.command:
cmd_buffer = b''
while True:
try:
client_socket.send(b'ailx10:#>')
while '\n' not in cmd_buffer.decode():
cmd_buffer += client_socket.recv(64)
response = execute(cmd_buffer.decode())
if response:
client_socket.send(response.encode())
cmd_buffer = b''
except Exception as e:
print(f'server killed {e}')
self.socket.close()
sys.exit()
#handle函式會根據它收到的命令列引數來執行相應的任務:執行命令、上傳檔案,或是打開一個shell,
#如果要執行命令,handle函式就會把該命令傳遞給execute函式,然后把輸出結果通過socket發回去
#如果要執行命令,handle函式就會把該命令傳遞給execute函式,然后把輸出結果通過socket發回去
#最后,如果要創建一個shell,我們還是創建一個回圈,向發送方發一個提示符,然后等待其發回命令
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="simple netcat tool",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent("""Example:
netcat.py -t 192.168.0.108 -p 5555 -l -c # command shell
netcat.py -t 192.168.0.108 -p 5555 -l -u=mytest.txt # upload file
netcat.py -t 192.168.0.108 -p 5555 -l -e=\"cat /etc/passwd\" # execute command
echo 'ABC' | ./netcat.py -t 192.168.0.108 -p 135 # echo text to server port 135
netcat.py -t 192.168.0.108 -p 5555 # connect to server
"""))
parser.add_argument('-c','--command',action='store_true',help='command shell')
parser.add_argument('-e','--execute',help='execute specified command')
parser.add_argument('-l','--listen',action='store_true',help='listen')
parser.add_argument('-p','--port',type=int,default=5555,help='specified port')
parser.add_argument('-t','--target',default='192.168.0.108',help='specified ip')
parser.add_argument('-u','--upload',help='upload file')
args = parser.parse_args()
if args.listen:
buffer = ''
else:
buffer = sys.stdin.read()
nc = Netcat(args,buffer.encode())
nc.run()
2.小試牛刀,
1)測驗命令控制:
首先在Kali虛擬機上,啟動一個接收方,讓它在虛擬機IP地址的5555埠提供一個命令列shell,

之后在本地端以客戶端的模式打開腳本運行

可以看到,我們得到了一個典型的命令列shell

2)測驗命令執行:
先在服務端運行

在客戶端可直接看到命令執行結果

3)在本機上用原版netcat來連接Kali虛擬機

4)發送http請求

這次的分享就到這里, 下一次將開發一個TCP代理,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/524944.html
標籤:其他
