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 Host: baidu.com ",'UTF-8')) 21 22 #接收一些数据 23 response = client.recv(4096) 24 25 print(response) 26 27 if __name__ == '__main__': 28 main()
2、创建一个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
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()函数准备处理下一步命令。
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 += " " 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 " 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 " " 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 -t localhost -p 8888