├── Dockerfile ├── README.md ├── auto_installer └── install_tools_script.sh └── hackpenguin.py /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM kalilinux/kali-rolling:latest 2 | 3 | # He añadido 'jq' a esta lista, ya que PinguAsset lo requiere obligatoriamente. 4 | RUN apt update && apt upgrade -y && \ 5 | apt install -y curl git nmap net-tools golang nano wget sqlmap iputils-ping zsh subfinder wpscan whois dirb ffuf seclists python3 python3-pip trufflehog python3-aiohttp jq 6 | 7 | RUN echo 'export PATH=$PATH:/root/.local/bin' >> ~/.zshrc && \ 8 | echo 'export GOPATH=$HOME/go' >> ~/.zshrc && \ 9 | echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.zshrc 10 | 11 | RUN go install github.com/projectdiscovery/httpx/cmd/httpx@latest && \ 12 | ln -s /root/go/bin/httpx /usr/bin/httpx && \ 13 | go install github.com/projectdiscovery/katana/cmd/katana@latest && \ 14 | ln -s /root/go/bin/katana /usr/bin/katana && \ 15 | go install github.com/tomnomnom/waybackurls@latest && \ 16 | ln -s /root/go/bin/waybackurls /usr/bin/waybackurls && \ 17 | go install github.com/tomnomnom/anew@latest && \ 18 | ln -s /root/go/bin/anew /usr/bin/anew && \ 19 | go install github.com/lc/gau/v2/cmd/gau@latest && \ 20 | ln -s /root/go/bin/gau /usr/bin/gau && \ 21 | go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest && \ 22 | ln -s /root/go/bin/nuclei /usr/bin/nuclei 23 | 24 | WORKDIR /opt 25 | 26 | RUN git clone https://github.com/s0md3v/XSStrike.git 27 | 28 | WORKDIR /opt/XSStrike 29 | 30 | RUN pip install -r requirements.txt --break-system-packages && chmod +x xsstrike.py && mv xsstrike.py xsstrike && mv * /usr/local/bin/ 31 | 32 | RUN rm -r /opt/XSStrike 33 | 34 | WORKDIR /opt 35 | RUN git clone https://github.com/Maalfer/domchecker.git 36 | 37 | WORKDIR /opt/domchecker 38 | RUN chmod +x domchecker.py && \ 39 | mv domchecker.py /usr/local/bin/domchecker 40 | 41 | WORKDIR /opt 42 | RUN git clone https://github.com/Maalfer/PinguAsset.git 43 | 44 | WORKDIR /opt/PinguAsset 45 | 46 | RUN chmod +x pinguasset.sh && \ 47 | sed -i 's|PATTERNS_FILE="patterns.json"|PATTERNS_FILE="/usr/local/bin/patterns.json"|g' pinguasset.sh && \ 48 | mv patterns.json /usr/local/bin/ && \ 49 | mv pinguasset.sh /usr/local/bin/PinguAsset 50 | 51 | RUN rm -rf /opt/XSStrike && rm -rf /opt/domchecker && rm -rf /opt/PinguAsset && \ 52 | apt autoremove -y 53 | 54 | WORKDIR /home 55 | 56 | RUN apt autoremove -y 57 | 58 | CMD ["/bin/zsh", "-i", "-c", "source ~/.zshrc && exec /bin/zsh"] 59 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | El objetivo de este proyecto es proporcionar un entorno dockerizado de Kali Linux con sus herramientas de hacking preconfiguradas, que se pueda desplegar automáticamente en el sistema y utilizar como máquina atacante. Para simplificar su gestión, se emplea un script en Bash que automatiza todo el proceso, eliminando la necesidad de poseer conocimientos previos sobre Docker. 2 | 3 | El script utiliza la siguiente imagen de DockerHub para automatizar su despliegue: 4 | 5 | ``` 6 | https://hub.docker.com/r/maalfer/hackpenguin 7 | ``` 8 | 9 | ![image](https://github.com/user-attachments/assets/b1509631-99ce-4756-a81b-3ae129fc7847) 10 | 11 | 12 | ## PASO 1 - Ejecutar el script hackpenguin.py 13 | 14 | Una vez ejecutado el script, se encargará de importar la máquina atacante en forma de imagen de docker, donde se nos mostrará por pantalla el comando que debemos de insertar para entrar dentro de dicha máquina atacante: 15 | 16 | ``` 17 | sudo bash hackpenguin.sh 18 | ``` 19 | 20 | ![image](https://github.com/user-attachments/assets/8b159a0b-3a17-4e2d-8d06-a38da7d10482) 21 | 22 | 23 | ## PASO 2 - Ingresar a la Máquina Atacante 24 | 25 | Para ingresas dentro de la máquina Kali atacante, copiamos y pegamos el comando que nos haya proporcionado previamente el script: 26 | 27 | ![image](https://github.com/user-attachments/assets/fc9918a7-544f-4164-9098-5dfeb27b4f47) 28 | 29 | 30 | ## PASO 3 - Cerrar y Limpiar el Sistema 31 | 32 | Una vez hayamos terminado de usar la máquina atacante, podemos presionar control C en el script y él se encargará de eliminar la máquina atacante, aunque sin embargo no borrará la imagen de dicha máquina, para así conseguir que las próximas veces que usemos la máquina, esta se despliegue muy rápidamente. 33 | 34 | ![image](https://github.com/user-attachments/assets/96caed17-c6d4-4f09-840d-ce4beb253fd9) 35 | 36 | 37 | ## PASO 4 (opcional) - Limpieza Total 38 | 39 | Si deseamos hacer una limpieza total y eliminar tanto el contenedor como la imagen de la máquina atacante, podemos usar el script con el parámetro --clean: 40 | ``` 41 | sudo python3 hackpenguin.py --clean 42 | ``` 43 | 44 | ![image](https://github.com/user-attachments/assets/da03612b-351a-4000-aaa7-359bd84c6814) 45 | 46 | 47 | ------------------------------------- 48 | 49 | **Menú de Ayuda** 50 | 51 | El script cuenta con un menú de ayuda para guiar al usuario con su uso: 52 | 53 | ![image](https://github.com/user-attachments/assets/a9025b6a-4e8e-4e88-a5ef-f1163fc9bf5a) 54 | 55 | 56 | -------------------------------------------------------------------------------- /auto_installer/install_tools_script.sh: -------------------------------------------------------------------------------- 1 | # Actualizar el sistema 2 | echo "Actualizando el sistema..." 3 | apt update && apt upgrade -y 4 | 5 | snap install enum4linux 6 | snap install john-the-ripper 7 | snap install metasploit-framework 8 | 9 | # Instalar dependencias necesarias 10 | echo "Instalando dependencias..." 11 | apt install -y curl git nmap net-tools golang sqlmap curl flatpak gobuster docker.io hydra wget wfuzz john wireshark arp-scan nano python3-requests smbclient smbmap python3-flask dirb 12 | 13 | wget https://github.com/brannondorsey/naive-hashcat/releases/download/data/rockyou.txt 14 | 15 | mv rockyou.txt /usr/share/ 16 | 17 | systemctl start docker && systemctl enable docker 18 | 19 | docker pull wpscanteam/wpscan 20 | 21 | echo "alias wpscan='sudo docker run -it --rm wpscanteam/wpscan'" >> ~/.bashrc 22 | 23 | flatpak remote-add --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo 24 | 25 | echo 'export GOPATH=$HOME/go' >> ~/.bashrc 26 | echo 'export PATH=$PATH:$GOPATH/bin' >> ~/.bashrc 27 | 28 | mkdir /opt/nuclei-templates 29 | 30 | git clone https://github.com/coffinxp/nuclei-templates.git 31 | 32 | mv nuclei-templates/* /opt/nuclei-templates 33 | 34 | rm -r nuclei-templates 35 | 36 | git clone https://github.com/danielhidalgo2/JSEXPOSURES.git /opt/JSEXPOSURES 37 | mv /opt/JSEXPOSURES/jsexposures.py /opt/jsexposures.py 38 | rm -rf /opt/JSEXPOSURES 39 | 40 | go install github.com/projectdiscovery/httpx/cmd/httpx@latest && \ 41 | go install github.com/projectdiscovery/katana/cmd/katana@latest && \ 42 | go install github.com/tomnomnom/waybackurls@latest && \ 43 | go install -v github.com/projectdiscovery/urlfinder/cmd/urlfinder@latest && \ 44 | go install -v github.com/tomnomnom/anew@latest && \ 45 | go install github.com/lc/gau/v2/cmd/gau@latest && \ 46 | go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest && \ 47 | go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest 48 | 49 | wget -q https://packages.mozilla.org/apt/repo-signing-key.gpg -O- | tee /etc/apt/keyrings/packages.mozilla.org.asc > /dev/null 50 | 51 | echo "deb [signed-by=/etc/apt/keyrings/packages.mozilla.org.asc] https://packages.mozilla.org/apt mozilla main" | tee -a /etc/apt/sources.list.d/mozilla.list > /dev/null 52 | 53 | echo ' 54 | Package: * 55 | Pin: origin packages.mozilla.org 56 | Pin-Priority: 1000 57 | ' | tee /etc/apt/preferences.d/mozilla 58 | 59 | snap remove firefox 60 | 61 | apt update && apt install -y firefox 62 | 63 | 64 | echo 'subfinder -d example.com -silent | gau | katana -silent | waybackurls | grep -Ei "confidential|secret|bak|api|key|auth|token|password|config|credential"' >> /opt/bug_bounty_dorks.txt 65 | echo 'subfinder -d example.com -silent | gau --subs | grep -Ei "(\?|&)(q|search|id|name|query|redirect|url)=[^&]*" | httpx -silent -status-code -content-type | grep "200" | sort -u' >> /opt/bug_bounty_dorks.txt 66 | echo 'katana -u https://example.com/ -d 5 -jc | grep "\.js$" | tee alljs.txt' >> /opt/finding_aws_buckets.txt 67 | echo 'cat alljs.txt | xargs -I {} curl -s {} | grep -oE "http[s]?://[^"]*.s3.amaxonaws.com" | sort -u' >> /opt/finding_aws_buckets.txt 68 | 69 | apt autoremove -y 70 | 71 | source ~/.bashrc 72 | -------------------------------------------------------------------------------- /hackpenguin.py: -------------------------------------------------------------------------------- 1 | import argparse 2 | import subprocess 3 | import signal 4 | import time 5 | import sys 6 | import platform 7 | import requests 8 | import os 9 | from datetime import datetime 10 | import calendar 11 | 12 | CONTAINER_NAME = "hackpenguin_container" 13 | IMAGE_NAME = "maalfer/hackpenguin:latest" 14 | 15 | def enable_windows_ansi(): 16 | if platform.system() == "Windows": 17 | import os 18 | os.system('') 19 | 20 | def print_colored(message, color): 21 | colors = { 22 | "RED": '\033[1;31m', 23 | "GREEN": '\033[1;32m', 24 | "YELLOW": '\033[1;33m', 25 | "CYAN": '\033[1;36m', 26 | "MAGENTA": '\033[1;35m', 27 | "WHITE_BOLD": '\033[1;37m', 28 | "RESET": '\033[0m' 29 | } 30 | 31 | if platform.system() == "Windows": 32 | enable_windows_ansi() 33 | 34 | print(f"{colors.get(color, colors['RESET'])}{message}{colors['RESET']}") 35 | 36 | def is_windows(): 37 | return platform.system() == "Windows" 38 | 39 | def docker_command(cmd): 40 | if is_windows(): 41 | return subprocess.run(["docker"] + cmd, shell=True, capture_output=True, text=True) 42 | return subprocess.run(["docker"] + cmd, capture_output=True, text=True) 43 | 44 | def check_image(): 45 | result = docker_command(["images", "--format", "{{.Repository}}:{{.Tag}}", IMAGE_NAME]) 46 | if IMAGE_NAME not in result.stdout: 47 | pull_result = subprocess.Popen(["docker", "pull", IMAGE_NAME], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) 48 | for line in pull_result.stdout: 49 | print(line.strip()) 50 | pull_result.stdout.close() 51 | pull_result.wait() 52 | if pull_result.returncode != 0: 53 | sys.exit(1) 54 | 55 | def cleanup(): 56 | print_colored("Deteniendo y eliminando el contenedor...", "RED") 57 | docker_command(["stop", CONTAINER_NAME]) 58 | docker_command(["rm", CONTAINER_NAME]) 59 | print_colored("Contenedor eliminado.", "RED") 60 | sys.exit() 61 | 62 | def cleanup_all(): 63 | docker_command(["stop", CONTAINER_NAME]) 64 | docker_command(["rm", CONTAINER_NAME]) 65 | docker_command(["rmi", IMAGE_NAME]) 66 | sys.exit() 67 | 68 | def get_dockerhub_image_date(): 69 | url = f"https://hub.docker.com/v2/repositories/{IMAGE_NAME.split(':')[0]}/tags/{IMAGE_NAME.split(':')[1]}" 70 | response = requests.get(url) 71 | if response.status_code == 200: 72 | data = response.json() 73 | return data["last_updated"] 74 | else: 75 | sys.exit(1) 76 | 77 | def get_local_image_date(): 78 | result = docker_command(["images", "--format", "{{.Repository}}:{{.Tag}}\t{{.CreatedAt}}", IMAGE_NAME]) 79 | if IMAGE_NAME in result.stdout: 80 | lines = result.stdout.strip().split("\n") 81 | for line in lines: 82 | repo, created_at = line.split("\t") 83 | if repo == IMAGE_NAME: 84 | return created_at 85 | return None 86 | 87 | def compare_dates(dockerhub_date, local_date): 88 | dockerhub_date = datetime.strptime(dockerhub_date, "%Y-%m-%dT%H:%M:%S.%fZ") 89 | local_date = local_date.split(" ")[0] + " " + local_date.split(" ")[1] 90 | local_date = datetime.strptime(local_date, "%Y-%m-%d %H:%M:%S") 91 | 92 | # Restar un día de forma segura 93 | new_day = local_date.day - 1 94 | 95 | # Si el nuevo día es menor que 1, ajustamos el mes y el día correctamente 96 | if new_day < 1: 97 | # Obtener el mes y año de la fecha local 98 | year = local_date.year 99 | month = local_date.month 100 | 101 | # Ajustar al último día del mes anterior 102 | if month == 1: 103 | # Si es enero, retrocedemos al diciembre del año anterior 104 | month = 12 105 | year -= 1 106 | else: 107 | month -= 1 108 | 109 | # Obtener el último día del mes anterior 110 | last_day_of_previous_month = calendar.monthrange(year, month)[1] 111 | new_day = last_day_of_previous_month 112 | 113 | # Crear la nueva fecha 114 | local_date = local_date.replace(year=year, month=month, day=new_day) 115 | else: 116 | # Si no hay problema con el día, simplemente actualizamos la fecha 117 | local_date = local_date.replace(day=new_day) 118 | 119 | # Calcular la diferencia en días entre la fecha de DockerHub y la fecha local 120 | diff = (dockerhub_date - local_date).days 121 | return diff 122 | 123 | def update_image(): 124 | dockerhub_date = get_dockerhub_image_date() 125 | local_date = get_local_image_date() 126 | 127 | if local_date: 128 | date_diff = compare_dates(dockerhub_date, local_date) 129 | 130 | if date_diff < 2: # Si la diferencia es menor a 2 días 131 | print("La imagen está actualizada! Disfruta 🙂") 132 | else: 133 | update = input("Hay una versión más reciente de la imagen. ¿Quieres actualizar? (s/n): ") 134 | if update.lower() == 's': 135 | cleanup() 136 | check_image() 137 | 138 | def main(): 139 | parser = argparse.ArgumentParser(description="Script para gestionar contenedor hackpenguin.") 140 | parser.add_argument("--clean", action="store_true", help="Elimina todos los contenedores y la imagen.") 141 | parser.add_argument("--update", action="store_true", help="Comprueba si hay una nueva versión de la imagen.") 142 | args = parser.parse_args() 143 | 144 | if args.clean: 145 | cleanup_all() 146 | sys.exit() 147 | 148 | if args.update: 149 | update_image() 150 | sys.exit() 151 | 152 | signal.signal(signal.SIGINT, lambda sig, frame: cleanup()) 153 | check_image() 154 | container_exists = docker_command(["ps", "-a", "--filter", f"name={CONTAINER_NAME}", "--format", "{{.Names}}"]).stdout.strip() 155 | 156 | if container_exists: 157 | docker_command(["rm", "-f", CONTAINER_NAME]) 158 | 159 | print_colored("Iniciando el contenedor...", "GREEN") 160 | current_dir = os.getcwd() 161 | container_id = docker_command([ 162 | "run", 163 | "--network=host", 164 | "--privileged", 165 | "--name", CONTAINER_NAME, 166 | "-v", f"{current_dir}:/home", 167 | "-d", IMAGE_NAME, 168 | "tail", "-f", "/dev/null" 169 | ]).stdout.strip() 170 | 171 | print_colored("\nPara lanzar la máquina, ejecuta el siguiente comando:", "WHITE_BOLD") 172 | print_colored(f"docker exec -it {CONTAINER_NAME} bash\n", "GREEN") 173 | print_colored("Presiona Ctrl+C para detener y eliminar el contenedor.", "YELLOW") 174 | 175 | while True: 176 | time.sleep(1) 177 | 178 | if __name__ == "__main__": 179 | main() --------------------------------------------------------------------------------