简单的netcat

标签: none

Netcat简介:

Netcat是网络界的“瑞士军刀”——身材很小,用途很广

实现功能:侦听传输模式、telent(获取banner信息)、传输文本信息、传输文件(目录)、加密传输文件、远程控制(木马)、加密流量、流媒体服务器、远程克隆硬盘等...

参数介绍:
-n 不做域名解析,就是只能用IP地址
-p 接端口
-l 打开监听
-c 去连接
-v 显示详细信息
-q 后接时间,单位为s,意思后完成一个任务1秒后断开连接
-c 后接bash或者cmd
如果要被连接,就用监听一个端口,如果要连接,就去输入IP地址和端口,他可以配合多个工具在用管道重定向等实现很多功能。

学习本节需要了解 subprocess 库。subprocess提供了强大的进程创建接口,它可以提供给你多种与客户端程序交互的方法。
https://docs.python.org/2/library/subprocess.html
http://python.usyiyi.cn/translate/python_278/library/subprocess.html (中文版)

代码中一共有6个函数
def run_command(command) 函数:生成一个新的进程执行命令,用到了 subprocess模块
def client_sender(buffer) 函数: 工具运行在非监听模式下,执行的功能(循环的发送读取数据)
def server_loop() 函数:工具运行在监听模式下的主循环函数,每当有新的连接进来,创建新线程
def client_handler(client_socket): 函数:新线程要执行的代码都在这里了
def usage() 函数: 提示信息
def main() 函数:main 函数就是利用getopt 实现对参数的解析

具体思路
首先判断有没有数据需要收,如果有,那就收,写入文件
然后判断有没有命令要执行,如果有,那就执行,执行结果返回回去
最后判断是否有-c 选项,也就是 command,如果有,模仿 shell,接受数据,执行命令,返回结果

#!/usr/bin/env python
#-- coding:utf-8 --
import sys
import socket
import getopt
import threading
import subprocess

#定义一些全局变量
listen = False
command = False
upload = False
execute = ""
target = ""
upload_destination = ""
port = 0

def client_handler(client_socket):
global upload
global execute
global command

#检测上传文件
if len(upload_destination):
    
    #读取所有的字符并写下目标
    file_buffer = ""
    
    #持续读取数据直到没有符合的数据
    
    while True:
        data = client_socket.recv(1024)
        
        if not data:
            break
        else:
            file_buffer += data
            
    try:
        file_descriptor = open(upload_destination,"wb")
        file_descriptor.write(file_buffer)
        file_descriptor.close()
        
        #确认文件已经写出来
        client_socket.send("Successfully saved file to %s\r\n" % upload_destination)
    except:
        client_socket.send("Failed to save file to %s\r\n" % upload_destination)
        
#检查命令执行
if len(execute):
    
    #运行命令
    output = run_command(execute)
    client_socket.send(output)
    
#如果需要一个命令行shell,那么我们进入另一个循环
if command:
    
    while True:
        #跳出一个窗口
        client_socket.send("<BHP:#>")
        
        #现在我们接收文件知道发现换行符(enter key)
        cmd_buffer = ""
        while "\n" not in cmd_buffer:
            cmd_buffer += client_socket.recv(1024)
        
        #返回命令输出
        response = run_command(cmd_buffer)
        
        #返回响应数据
        client_socket.send(response)

def run_command(command):

#换行
command = command.rstrip()

#运行命令并将输出返回,处理错误
try:
    output = subprocess.check_output(command,stderr=subprocess.STDOUT, shell=True)
except:
    output = "Failed to execute command.\r\n"
    
#将输出发送
return output

#切断服务
def server_loop():
global target

#如果没有定义目标,那么我们监听所有接口
if not len(target):
    target = "0.0.0.0"
    
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.bind((target,port))

server.listen(5)

while True:
    client_socket, addr = server.accept()
    
    #分拆一个线程处理新的客户端
    client_thread = threading.Thread(target=client_handler, args=(client_socket,))
    client_thread.start()
    

def client_sender(buffer):
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

#连接目标主机,如果有需要发送的数据,则进行发送
try:
    client.connect((target,port))
    
    if len(buffer):
        client.send(buffer)
    
    #如果一切正常,则发送数据等待回传    
    while True:
        #做一个登录监听
        recv_len = 1
        response = ""
        
        #直到没有数据继续,等待用户下一步输入
        while recv_len:
            
            data     = client.recv(4096)
            recv_len = len(data)
            response+= data
            
            if recv_len < 4096:
                break
            
        print response
        
        #等待更多的输入
        buffer = raw_input("")
        buffer += "\n"
        
        #发送出去
        client.send(buffer)
        
        
except:
    
    print " [*] Exception! Exiting."
    
#关闭连接
client.close()

#如果命令参数不符合标准,打印出工具帮助信息
def usage():
print "BHP Net Tool"
print
print "Usage: bhpnet.py -t target_host -p port"
print "-l --listen -listen on [host]:[port] for incoming connections"
print "-e --execute=file_to_run -execute the given file upon receiving a connection"
print "-c --command -initialize a command shell"
print "-u --upload=destination -upon receiving connection upload a file and write to [destination]"
print
print
print "Examples: "
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -c"
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -u=c:\target.exe"
print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e="cat /etc/passwd""
print "echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135"
sys.exit(0)

#主函数
def main():
#将变量定义为全局变量
global listen
global port
global execute
global command
global upload_destination
global target

if not len(sys.argv[1:]):
    usage()
    
#读取命令行选项
try:
    opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",["help","listen","execute","target","port","command","upload"])
except getopt.GetoptError as err:
    print str(err)
    usage()
    
for o,a in opts:
    if o in ("-h","--help"):
        usage()
    elif o in ("-l", "listen"):
        listen = True
    elif o in ("-e", "--execute"):
        execute = a
    elif o in ("-c", "--commandshell"):
        command = True
    elif o in ("-u", "--upload"):
        upload_destination = a
    elif o in ("-t", "--target"):
        target = a
    elif o in ("-p", "--port"):
        port = int(a)
    else:
        assert False,"Unhandled Option"
        
#选择进行监听还是仅从标准输入发送数据?
if not listen and len(target) and port > 0:
    
    #从命令行读取内存数据
    #这里将阻塞,所以不在向标准输入发送数据时发送CTRL-D
    buffer = sys.stdin.read()
    
    #发送数据
    client_sender(buffer)
    
    #我们开始监听并准备上传文件,执行命令
    #放置一个反弹shell
    #取决于上面的命令行选项
if listen:
    server_loop()

main()

现在让我们进行程序的测试,看看输出情况。在一个终端或者cmd.exe shell 中,运行我们的如下脚本:

justin$ python bhnet.py -l -p 9999 -c

现在,你可以启动另外一个终端或者cmd.exe,或者以客户端模式运行脚本。记住我们的脚本读取的是标准输入直到接收到EOF(文件末尾标志),按Ctrl+D组合键发送EOF指令:

justin$ python bhnet.py -t localhaost -p 9999
<CTRL-D>
<BHP:#> ls -la
<BHP:#> pwd
<BHP:#>

我们也可以直接利用客户端发送HTTP请求:
justin$ echo -ne "GET / HTTP/1.1\r\nHost:www.baidu.com\r\n\r\n" | python bhnet.py -t www.baidu.com -p 80

添加新评论