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)
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) #reuse socket if possible
def run(self):
if self.args.listen:
self.listen() #listen for connections if specified in args
else:
self.send()
def send(self): #send data to server if not listening
self.socket.connect((self.args.target,self.args.port)) #connect to server
if self.buffer: #if buffer is specified, send it
self.socket.send(self.buffer.encode()) #send buffer to server
try:
while True: #keep sending data to server until connection is closed
recv_len=1
response=''
while recv_len: #keep receiving data from server until connection is closed or buffer is full
data=self.socket.recv(4096) #receive data from server in 4096 byte chunks
recv_len=len(data) #get length of data received from server
response+=data.decode() #decode data received from server and add to response string
if recv_len<4096: #if less than 4096 bytes received, connection is closed or buffer is full
break #break out of loop and print response string to console
if response: #if response string is not empty, print it to console
print(response) #print response string to console
buffer=input('> ') #get input from console and store in buffer variable
buffer+='\n' #add newline to buffer variable to send to server as newline delimited data
self.socket.send(buffer.encode()) #send buffer to server as newline delimited data
except KeyboardInterrupt: #if user presses ctrl+c, close connection to server and exit program
print('User terminated connection') #print message to console that user terminated connection to server
self.socket.close() #close connection to server
sys.exit()
def listen(self): #listen for connections from client if specified in args
self.socket.bind((self.args.target,self.args.port)) #bind socket to specified target and port
self.socket.listen(5) #listen for connections from client in socket with a backlog of 5 connections waiting to be accepted
while True: #keep listening for connections from client until program is terminated or connection is closed by client or server
client_socket, client_address=self.socket.accept() #accept connection from client and store client socket and client address in variables
print('[*] Accepted connection from: %s:%d'% (client_address[0],client_address[1])) #print message to console that connection from client was accepted and store client address in variables
client_thread=threading.Thread(target=self.handle_client,args=(client_socket,)) #create new thread to handle client connection and store client socket in variables
client_thread.start() #start new thread to handle client connection and store client socket in variables
def handle(self,client_socket): #handle client connection if specified in args and listen for connections from client if specified in args
if self.args.execute: #if user specified command to execute in args, execute command and send output to client as newline delimited data
output=execute(self.args.execute)
client_socket.send(output.encode()) #send output to client as newline delimited data
elif self.args.upload: #if user specified file to upload in args, upload file to server and send output to client as newline delimited data
file_buffer=b'' #create buffer variable to store file data in bytes format
while True: #keep reading file data from client until file is completely read and stored in buffer variable in bytes format
data=client_socket.recv(1024) #read file data from client in 1024 byte chunks and store in variable in bytes format
if data:
file_buffer+=data #append file data to buffer variable in bytes format if data is not empty
else:
break
with open(self.args.upload,'wb') as f: #open file specified by user in write binary mode and store in variable in bytes format
f.write(file_buffer) #write file data to file specified by user in write binary mode and store in variable in bytes format
message=f'Saved file {self.args.upload}' #create message to send to client as newline delimited data and store in variable in bytes format
client_socket.send(message.encode()) #send message to client as newline delimited data and store in variable in bytes format
elif self.args.command: #if user specified command shell in args, create command shell and send output to client as newline delimited data
cmd_buffer=b'' #create buffer variable to store command data in bytes format
while True: #keep reading command data from client until command is completely read and stored in buffer variable in bytes format
try:
client_socket.send(b'BHP:#>') #send message to client as newline delimited data and store in variable in bytes format to indicate that server is ready to receive command data from client
while '\n' not in cmd_buffer.decode(): #keep reading command data from client until newline character is detected and stored in buffer variable in bytes format to indicate that command is completely read from client
cmd_buffer+=client_socket.recv(64) #read command data from client in 64 byte chunks and store in variable in bytes format to indicate that command is completely read from client
response=execute(cmd_buffer.decode()) #execute command and store output in variable in bytes format to indicate that command is completely read from client
if response: #if command output is not empty, send command output to client as newline delimited data and store in variable in bytes format to indicate that command output is completely read from client and ready to be sent to client
client_socket.send(response.encode()) #send command output to client as newline delimited data and store in variable in bytes format to indicate that command output is completely read from client and ready to be sent to client
cmd_buffer=b''
except Exception as e: #if exception occurs, send exception message to client as newline delimited data and store in variable in bytes format to indicate that exception message is completely read from client and ready to be sent to client
print(f'server killed {e}')
self.socket.close()
sys.exit()
if __name__=="__main__":
parser=argparse.ArgumentParser(description="BHP Net Tool",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=textwrap.dedent('''Example:
python netcat.py -t 192.168.1.1 -p 5555 -l -c # command shell
python netcat.py -t 192.168.1.1 -p 5555 -l -u=mytest.txt # upload to file
python netcat.py -t 192.168.1.1 -p 5555 -l -e="cat /etc/passwd" # execute command
echo 'ABCDEFGH' | python netcat.py -t 192.168.1.1 -p 135 # echo local text to server port 135
python netcat.py -t 192.168.1.1 -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 mode')
parser.add_argument('-p','--port',type=int,default=5555,help='specified port')
parser.add_argument('-t','--target',default='192.168.1.10',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()
本文暂时没有评论,来添加一个吧(●'◡'●)