《Python黑帽子:黑客与渗透测试编程之道》 网络基础

1、创建一个TCP客户端

socket对象包含两个参数,AF_INET表示使用IPv4地址或主机名,SOCK_STREAM表示是一个TCP客户端。请求的URL是百度。

 1 #!/usr/bin/python3
 2 #-*- coding:utf-8 -*-
 3 
 4 #编译环境  windows 7 x64 + Python3.7.0
 5 #创建一个TCP客户端
 6 
 7 import socket
 8 
 9 def main():
10     target_host = "www.baidu.com"
11     target_port = 80
12     
13     #建立一个socket对象
14     client =socket.socket(socket.AF_INET,socket.SOCK_STREAM)
15     
16     #连接客户端,(由于TCP三次握手机制,需要先连接)
17     client.connect((target_host,target_port))
18     
19     #发送一些数据
20     client.send(bytes("GET / HTTP/1.1\r\nHost: baidu.com\r\n\r\n",'UTF-8'))
21 
22     #接收一些数据
23     response = client.recv(4096)
24 
25     print(response)
26     
27 if __name__ == '__main__':
28     main()

2、创建一个UDP客户端

与TCP客户端相比,将数据包以UDP的格式发出。将套接字的类型改为SOCK_DGRAM,调用sendto()函数发送数据传到想发送的服务器上,因为UDP是无连接状态的传输协议,所以不需要调用connect()函数,最后调用recvfrom()函数接收返回的UDP数据包。就可以接收到回传的数据及远程主机的信息和端口号

 1 #!/usr/bin/python3
 2 #-*- coding:utf-8 -*-
 3 
 4 #编译环境  windows 7 x64 + Python3.7.0
 5 #创建一个UDP客户端
 6 
 7 import socket
 8 
 9 def main():
10     
11     target_host = "127.0.0.1"
12     target_port = 2333
13     
14     #建立一个socket对象
15     client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
16     
17     #发送一些数据
18     client.sendto(bytes("AAABBBCCC",'UTF-8'),(target_host, target_port))
19     
20     #接收一些数据
21     data, addr = client.recvfrom(4096)
22     print(data)
23     print(addr)
24     
25 if __name__ == '__main__':
26     main()

(运行nc.exe -ulvp 2333)本地监听2333端口,运行udp_client.py脚本,过一会可以看到有数据传过来了。

-l 表示侦听模式

-u UDP

3、创建一个TCP服务端

先确定服务器需要监听的IP地址和端口。然后,我们启动监听并将最大连接数设为5。

 1 #!/usr/bin/python3
 2 #-*- coding:utf-8 -*-
 3 
 4 #编译环境  windows 7 x64 + Python3.7.0
 5 #创建一个TCP服务端
 6 
 7 import socket
 8 import threading
 9 
10 #这是客户处理线程
11 def handle_client(client_socket):
12     
13     #打印出客户端发送得到内容
14     request = client_socket.recv(1024)
15     
16     print("[*] Received: %s"% request)
17     
18     #返回一个数据包
19     client_socket.send(bytes("ACK!",'UTF-8'))
20     
21     client_socket.close()
22     
23     
24 def main():
25     bind_ip = "0.0.0.0"
26     bind_port = 1234
27     
28     #创建一个socket对象
29     server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
30     
31     #调用bind()函数绑定IP和端口
32     server.bind((bind_ip, bind_port))
33     
34     #通过listen()函数启动监听并将最大连接数设为5(默认值),有点类似多线程
35     server.listen(5)
36     
37     print("[*] Listening on %s:%d" % (bind_ip,bind_port))
38     
39     while True:
40         client, addr = server.accept()
41     
42         print("[*] Accepted connection from: %s:%d" % (addr[0], addr[1]))
43     
44         #挂起客户端线程,处理传入的数据
45         client_handler = threading.Thread(target=handle_client,args=(client,))
46         client_handler.start()
47     
48 if __name__ == '__main__':
49     main()

将TCP客户端代码参数修改如下,先运行TCP服务端,再执行TCP客户端。

执行结果如下所示:

4、取代netcat

以下程序各个函数的意思如下:

usage()函数用于参数的说明帮助、当用户输入错误的参数时会输出相应的提示;

client_sender()函数用于与目标主机建立连接并交互数据直到没有更多的数据发送回来,然后等待用户下一步的输入并继续发送和接收数据,直到用户结束脚本运行;

server_loop()函数用于建立监听端口并实现多线程处理新的客户端;

run_command()函数用于执行命令,其中subprocess库提供多种与客户端程序交互的方法;

client_handler()函数用于实现文件上传、命令执行和与shell相关的功能,其中wb标识确保是以二进制的格式写入文件、从而确保上传和写入的二进制文件能够成功执行;

主函数main()中是先读取所有的命令行选项从而设置相应的变量,然后从标准输入中读取数据并通过网络发送数据,若需要交互式地发送数据需要发送CTRL-D以避免从标准输入中读取数据,若检测到listen参数为True则调用server_loop()函数准备处理下一步命令。

遇到问题 python3 区分了str 和 bytes

bytes.decode()方法 decode() 方法以指定的编码格式解码 bytes 对象。默认编码为 'utf-8'。 该方法返回解码后的字符串。

str.encode() 方法以指定的编码格式编码字符串。 该方法返回编码后的字符串,它是一个 bytes 对象

  1 #!/usr/bin/python3
  2 #-*- coding:utf-8 -*-
  3 
  4 #编译环境  windows 7 x64 + Python3.7.0
  5 
  6 import sys
  7 import getopt
  8 import socket
  9 import threading
 10 import subprocess
 11 
 12 #定义一些全局变量
 13 listen = False             #若True,可理解为服务器。否则为客户端
 14 command = False            #是否建立shell
 15 upload = False             #上传
 16 execute = ""               #目标机上执行的命令
 17 target = ""                #目标主机   
 18 upload_destination = ""    #数据传送的目标文件。  上传文件,目录路径。
 19 port = 0                   #目标端口号
 20 
 21 #使用帮助,相当于help
 22 def usage():
 23     print("BHP Net Tool")
 24     print("")
 25     print("Usage: bhpnet.py -t target_host -p port")
 26     print("-l --listen              - listen on [host]:[port] for incoming connections")
 27     print("-e --execute=file_to_run - execute the given file upon receiving a connection")
 28     print("-c --command             - initialize a command shell")
 29     print("-u --upload=destination  - upon receiving a connection upload a file and write to [destination]")
 30     print("")
 31     print("")
 32     print("Examples: ")
 33     print("bhpnet.py -t 192.168.0.1 -p 5555 -l -c")
 34     print("bhpnet.py -t 192.168.0.1 -p 5555 -l -u=C:\\target.exe")
 35     print("bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\"")
 36     print("echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135")
 37     sys.exit(0)
 38 
 39 
 40 #客户端发送信息给服务端,并且接收服务端传回来的信息。会一直等待命令输入和接收数据,直到脚本结束    
 41 def client_sender(buffer):
 42     client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 43 
 44     try:
 45         # 连接到目标主机(服务器)
 46         client.connect((target,port))
 47         print("目标主机 %s,%d,连接成功"%(target,port))
 48         
 49         if len(buffer):
 50             client.send(str.encode(buffer))#修改1
 51             
 52         while True:
 53             #现在等待数据回传
 54             recv_len = 1
 55             response = ""
 56             
 57             while recv_len:
 58                 data = client.recv(4096)   #这时 data 为 bytes类型
 59                 recv_len = len(data)
 60                 data = bytes.decode(data) #修改2  这里需要转换为str类型 否则下面的 response += data 没办法执行
 61                 response += data
 62             
 63                 if recv_len < 4096:
 64                     break
 65             print("response,")
 66         
 67             #等待更多的输入
 68             buffer = input("")#'raw_input'修改为input,Python3没有raw_input函数
 69 
 70             buffer += "\n"
 71         
 72             #发送出去
 73             client.send(str.encode(buffer))#修改3   这里需要转换为bytes类型 否则发不出去
 74     
 75     except Exception as e:
 76         print(e)
 77         print("[*] Exception! Exiting.")
 78         
 79         #关闭连接
 80         client.close()
 81 
 82 
 83 #用于建立监听端口并实现多线程处理新的客户端 
 84 def server_loop():
 85     global target
 86     global port
 87     
 88     # 如果没有定义目标,那么我们监听所有接口
 89     if not len(target):
 90         target = "0.0.0.0"
 91     
 92     server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 93     server.bind((target, port))
 94     server.listen(5)
 95     
 96     while True:
 97         client_socket, addr = server.accept()
 98         
 99         # 分拆一个线程处理新的客户端
100         client_thread = threading.Thread(target=client_handler, args=(client_socket,))
101         client_thread.start()
102 
103  
104 #函数用于执行命令,其中subprocess库提供多种与客户端程序交互的方法 
105 def run_command(command):
106     # 换行
107     command = command.rstrip()
108     
109     # 运行命令并将输出返回
110     try:
111         #command = bytes.decode(command)  #修改4
112         print(bytes.decode(command))
113         output = subprocess.check_output(command,stderr=subprocess.STDOUT,shell=True)
114     except Exception as e:
115         print(e)
116         output = "[-] Failed to execute command\r\n"
117         
118     # 将输出发送
119     return output
120 
121 #函数用于实现文件上传、命令执行和与shell相关的功能,其中wb标识确保是以二进制的格式写入文件、从而确保上传和写入的二进制文件能够成功执行;
122 def client_handler(client_socket):
123     global upload
124     global execute
125     global command
126     
127     # 检测上传文件
128     if len(upload_destination):
129         
130         # 读取所有的字符并写入目标
131         
132         file_buffer = ""
133         
134         # 持续读取数据直到没有符合的数据
135         while True:
136             data = client_socket.recv(1024)
137             
138             if not data:
139                 break
140             else:
141                 file_buffer += data
142         
143         # 现在我们接收这些数据并将他们写出来
144         try: 
145             file_descriptor = open(upload_destination,"wb")
146             file_descriptor.write(file_buffer)
147             file_descriptor.close()
148             
149             # 确认文件已经写出来
150             client_socket.send(str.encode("Successfully saved file to %s/r/n" % upload_destination))#修改9
151         except:
152             client_socket.send(str.encode("Failed to save file to %s/r/n" % upload_destination))#修改10
153             
154     # 检查命令执行
155     if len(execute):
156         
157         # 运行命令
158         output = run_command(execute)
159         
160         client.socket.send(str.encode(output))#修改5
161         
162     # 如果需要一个命令行shell,那么我们进入另一个循环
163     
164     if command:
165         while True:
166             # 跳出一个窗口
167             client_socket.send(str.encode("<BHP:#> "))#修改6
168             
169             cmd_buffer = ""
170             cmd_buffer = str.encode(cmd_buffer)
171             while "\n" not in bytes.decode(cmd_buffer):#修改7
172                 cmd_buffer += client_socket.recv(1024)         
173             # 返还命令输出
174             response = run_command(cmd_buffer)
175             print(bytes.decode(response))#修改8
176             # 返回响应数据
177             client_socket.send(response)
178 
179 #main()中是先读取所有的命令行选项从而设置相应的变量,然后从标准输入中读取数据并通过网络发送数据,
180 #若需要交互式地发送数据需要发送CTRL-D以避免从标准输入中读取数据,若检测到listen参数为True则调用server_loop()函数准备处理下一步命令。            
181 def main():
182     
183     #定义一些全局变量
184     global listen
185     global port
186     global execute
187     global command
188     global upload_destination
189     global target
190     
191     if not len(sys.argv[1:]): #如果数组中有多个元素
192         usage()
193     
194     # 读取命令行选项
195     try:
196         opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu",["help","listen","execute","target","port","command","upload"])
197     except getopt.GetoptError as err:
198         print(str(err))
199         usage()
200 
201     for o,a in opts:
202         if o in ("-h", "--help"):
203             usage()
204         elif o in ("-l", "--listen"):
205             listen = True
206         elif o in ("-e", "--execute"):
207             execute = a
208         elif o in ("-c", "--commandshell"):
209             command = True
210         elif o in ("-u", "--upload"):
211             upload_destination = a
212         elif o in ("-t", "--target"):
213             target = a
214         elif o in ("-p", "--port"):
215             port = int(a)
216         else:
217             assert False, "Unhandled Option"
218             
219     # 我们是进行监听还是仅从标准输入发送数据?
220     if not listen and len(target) and port > 0:
221             
222         # 从命令行读取内存数据
223         # 这里将阻塞,所以不在向标准输入发送数据时发送CTRL-D
224             
225         buffer = sys.stdin.read()
226             
227         print("sending data")
228         
229         #作为客户端,给服务端发送数据
230         client_sender(buffer)
231             
232     # 我们开始监听并准备上传文件、执行命令
233     # 放置一个反弹shell
234     # 取决于上面的命令行选项
235     #
236     if listen:
237         server_loop()
238     
239 
240 if __name__ == '__main__':
241     main()

打开一个终端(服务端)python3 netcat.py -l -p 8888 -c

打开新终端(客户端)python3 netcat.py -t localhost -p 8888

输入ctrl+d

 

 

 

 

posted on 2019-12-31 19:19  wmiot  阅读(260)  评论(0编辑  收藏  举报