Code for How to Build a Custom Netcat with Python Tutorial


View on Github

netcat.py

import sys, socket, getopt, threading, subprocess, signal, time


class NetCat:
    def __init__(self, target, port):
        self.listen = False
        self.command = False
        self.upload = False
        self.execute = ""
        self.target = target
        self.upload_destination = ""
        self.port = port
        self.running = True
        self.threads = []

    def signal_handler(self, signum, frame):
        print('\n[*] User requested an interrupt. Exiting gracefully.')
        self.running = False
        time.sleep(0.5)
        sys.exit(0)

    def run_command(self, cmd):
        cmd = cmd.rstrip()
        try:
            output = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
        except subprocess.CalledProcessError as e:
            output = e.output
        except Exception as e:
            output = str(e).encode()
        return output

    def handle_client(self, client_socket):
        try:
            if len(self.upload_destination):
                file_buffer = ""
                while self.running:
                    try:
                        data = client_socket.recv(1024)
                        if not data:
                            break
                        else:
                            file_buffer += data.decode('utf-8')
                    except (ConnectionResetError, BrokenPipeError) as e:
                        print(f"[!] Connection error during upload: {str(e)}")
                        break
                    except Exception as e:
                        print(f"[!] Error receiving data: {str(e)}")
                        break

                try:
                    with open(self.upload_destination, "wb") as file_descriptor:
                        file_descriptor.write(file_buffer.encode('utf-8'))
                    try:
                        client_socket.send(
                            f"Successfully saved file to {self.upload_destination}\r\n".encode('utf-8'))
                    except (BrokenPipeError, ConnectionResetError):
                        print("[!] Couldn't send success message - connection lost")
                except OSError as e:
                    print(f"[!] File operation failed: {str(e)}")
                    try:
                        client_socket.send(
                            f"Failed to save file to {self.upload_destination}\r\n".encode('utf-8'))
                    except (BrokenPipeError, ConnectionResetError):
                        print("[!] Couldn't send error message - connection lost")

            if len(self.execute) and self.running:
                try:
                    output = self.run_command(self.execute)
                    client_socket.send(output)
                except (BrokenPipeError, ConnectionResetError):
                    print("[!] Couldn't send command output - connection lost")
                except Exception as e:
                    print(f"[!] Error executing command: {str(e)}")

            if self.command:
                while self.running:
                    try:
                        # Send prompt
                        client_socket.send(b"<Target:#> ")
                        
                        # Receive command
                        cmd_buffer = b''
                        while b"\n" not in cmd_buffer and self.running:
                            try:
                                data = client_socket.recv(1024)
                                if not data:
                                    raise ConnectionResetError("No data received")
                                cmd_buffer += data
                            except socket.timeout:
                                continue
                            except (ConnectionResetError, BrokenPipeError):
                                raise
                        
                        if not self.running:
                            break

                        # Execute command and send response
                        try:
                            cmd = cmd_buffer.decode().strip()
                            if cmd.lower() in ['exit', 'quit']:
                                print("[*] User requested exit")
                                break
                                
                            output = self.run_command(cmd)
                            if output:
                                client_socket.send(output + b"\n")
                            else:
                                client_socket.send(b"Command completed without output\n")
                                
                        except (BrokenPipeError, ConnectionResetError):
                            print("[!] Connection lost while sending response")
                            break
                        except Exception as e:
                            error_msg = f"Error executing command: {str(e)}\n"
                            try:
                                client_socket.send(error_msg.encode())
                            except:
                                break

                    except ConnectionResetError:
                        print("[!] Connection reset by peer")
                        break
                    except BrokenPipeError:
                        print("[!] Broken pipe - connection lost")
                        break
                    except Exception as e:
                        print(f"[!] Error in command loop: {str(e)}")
                        break

        except Exception as e:
            print(f"[!] Exception in handle_client: {str(e)}")
        finally:
            try:
                client_socket.close()
                print("[*] Client connection closed")
            except:
                pass

    def server_loop(self):
        server = None
        try:
            if not len(self.target):
                self.target = "0.0.0.0"

            server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            server.bind((self.target, self.port))
            server.listen(5)
            
            print(f"[*] Listening on {self.target}:{self.port}")

            server.settimeout(1.0)

            while self.running:
                try:
                    client_socket, addr = server.accept()
                    print(f"[*] Accepted connection from {addr[0]}:{addr[1]}")
                    
                    client_thread = threading.Thread(
                        target=self.handle_client,
                        args=(client_socket,)
                    )
                    client_thread.daemon = True
                    self.threads.append(client_thread)
                    client_thread.start()

                except socket.timeout:
                    continue
                except Exception as e:
                    if self.running:
                        print(f"[!] Exception in server_loop: {str(e)}")
                    break

        except Exception as e:
            print(f"[!] Failed to create server: {str(e)}")
        finally:
            if server:
                try:
                    server.close()
                    print("[*] Server socket closed")
                except:
                    pass

            for thread in self.threads:
                try:
                    thread.join(timeout=1.0)
                except threading.ThreadError:
                    pass

    def client_sender(self, buffer):
        client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        try:
            print(f"[*] Connecting to {self.target}:{self.port}")
            client.connect((self.target, self.port))

            if len(buffer):
                try:
                    client.send(buffer.encode('utf-8'))
                except (BrokenPipeError, ConnectionResetError):
                    print("[!] Failed to send initial buffer - connection lost")
                    return

            while self.running:
                try:
                    # Receive response from server
                    recv_len = 1
                    response = b''

                    while recv_len:
                        data = client.recv(4096)
                        recv_len = len(data)
                        response += data

                        if recv_len < 4096:
                            break

                    if response:
                        print(response.decode('utf-8'), end='')
                    
                    # Get next command
                    buffer = input()
                    if not self.running:
                        break
                    
                    if buffer.lower() in ['exit', 'quit']:
                        break

                    buffer += "\n"
                    try:
                        client.send(buffer.encode('utf-8'))
                    except (BrokenPipeError, ConnectionResetError):
                        print("\n[!] Failed to send data - connection lost")
                        break

                except ConnectionResetError:
                    print("\n[!] Connection reset by peer")
                    break
                except BrokenPipeError:
                    print("\n[!] Broken pipe - connection lost")
                    break
                except EOFError:
                    print("\n[!] EOF detected - exiting")
                    break
                except Exception as e:
                    print(f"\n[!] Exception in client loop: {str(e)}")
                    break

        except socket.error as exc:
            print("\n[!] Exception! Exiting.")
            print(f"[!] Caught exception socket.error: {exc}")
        finally:
            print("[*] Closing connection")
            try:
                client.close()
            except:
                pass

def main():
    if len(sys.argv[1:]) == 0:
        print("Custom Netcat")
        print("\nSYNOPSIS")
        print("    netcat.py [OPTIONS...]\n")
        print("OPTIONS")
        print("    -l, --listen              Start server in listening mode on specified host:port")
        print("    -e, --execute=<file>      Execute specified file upon connection establishment")
        print("    -c, --command             Initialize an interactive command shell session")
        print("    -u, --upload=<path>       Upload file to specified destination path on connection")
        print("    -t, --target=<host>       Specify target hostname or IP address")
        print("    -p, --port=<port>         Specify target port number")
        print()
        sys.exit(0)

    try:
        opts, args = getopt.getopt(sys.argv[1:], "hle:t:p:cu:",
                                   ["help", "listen", "execute", "target",
                                    "port", "command", "upload"])
        
        for o, a in opts:
            if o in ("-h", "--help"):
                main()
            elif o in ("-l", "--listen"):
                toolkit.listen = True
            elif o in ("-e", "--execute"):
                toolkit.execute = a
            elif o in ("-c", "--command"):
                toolkit.command = True
            elif o in ("-u", "--upload"):
                toolkit.upload_destination = a
            elif o in ("-t", "--target"):
                toolkit.target = a
            elif o in ("-p", "--port"):
                toolkit.port = int(a)
            else:
                assert False, "Unhandled Option"

    except getopt.GetoptError as err:
        print(str(err))
        main()

    signal.signal(signal.SIGINT, toolkit.signal_handler)
    signal.signal(signal.SIGTERM, toolkit.signal_handler)

    try:
        if not toolkit.listen and len(toolkit.target) and toolkit.port > 0:
            buffer = sys.stdin.read()
            toolkit.client_sender(buffer)

        if toolkit.listen:
            toolkit.server_loop()
    except KeyboardInterrupt:
        print("\n[*] User requested shutdown")
    except Exception as e:
        print(f"\n[!] Unexpected error: {str(e)}")
    finally:
        toolkit.running = False
        print("[*] Shutdown complete")
        sys.exit(0)

if __name__ == "__main__":
    toolkit = NetCat("", 0)
    main()
 
 

 

 



pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy