
Código fuente del libro "Violent Python" de TJ O'Connor. El código ha sido completamente convertido a Python 3, reformateado para cumplir con los estándares PEP8 y refactorizado para eliminar problemas de dependencias relacionados con la implementación de librerías obsoletas.
Código fuente del libro "Violent Python" de TJ O'Connor. El código se ha convertido completamente a Python 3, reformateado para cumplir con los estándares PEP8 y refactorizado para eliminar problemas de dependencias derivados de la implementación de librerías obsoletas.
Una conversión similar a esta ha sido puesta a disposición por mí en el código fuente del libro "Black Hat Python", de Justin Seitz. Échale un vistazo aquí si aún no lo has hecho todavía.
Simplemente crea un nuevo directorio (DIR) para el proyecto, crea un nuevo
entorno virtual o venv para el mismo (recomendado), clona este repositorio
usando git clone e instala los requisitos usando pip install.
user@host:~/DIR$ git clone https://github.com/EONRaider/violent-python3
user@host:~/DIR$ python3 -m venv venv
user@host:~/DIR$ source venv/bin/activate
(venv) user@host:~/DIR$ pip install -r requirements.txt
optparse ha sido reemplazada por argparse
en todo el código fuente. Todo el análisis de argumentos ahora está contenido
bajo el ámbito de ejecución __main__ de cada archivo. Todos los argumentos de
CLI que eran obligatorios para la ejecución de los scripts pero se trataban
como opcionales en el código original ahora se implementan como posicionales.
Ahora hay un indicador de uso disponible para todos los scripts que usan
argparse al proporcionar un argumento -h a la CLI. Dejar las
responsabilidades de objeto de límite y controlador al analizador de CLI
definitivamente no es la mejor opción en términos de arquitectura de
software, pero se dejó como está debido a la necesidad de ajustarse a la
intención del programador original.PEP 8: E722 do not use bare except se han
refactorizado con cláusulas de excepción más específicas.close() en los objetos de archivo/base de datos
abiertos. Por
esta razón, todas las instancias de manipulación de archivos y bases de datos se
han refactorizado mediante administradores de contexto.# -*- coding: utf-8 -*-) debido a la
estandarización de UTF-8 como codificación predeterminada para Python 3
(que reemplaza a ASCII de Python 2).Se puede asumir que los archivos no enumerados a continuación han sido refactorizados de una u otra forma según lo establecido en la sección "Notas".
chapter01/vuln_scanner.py estaba estructurado de tal manera que un archivo inexistente provocaba una excepción OSError en tiempo de ejecución. Por esa
razón, el control de iteración que llama a check_vulns() se movió a la
declaración condicional definida en la función principal.chapter02/nmap_scan.py implementaba una función principal únicamente con el propósito
de llamar a la obsoleta librería optparse, que ha sido reemplazada por
argparse. Debido a eso, la función principal se eliminó. Una estructura
de control de iteración que formaba parte de la llamada a optparse en el
código original estaba implementada de tal manera que se ejecutaba una nueva
llamada a nmap por cada puerto escaneado. La iteración se movió a la función nmap_scan
para evitar desperdiciar ciclos.chapter02/ssh_command.py tuvo su código de inicialización movido al ámbito de
ejecución __main__. Se cambiaron los nombres de las variables utilizadas en
el ámbito externo que solían entrar en conflicto con los nombres de los
parámetros de las funciones. La información del prompt de retorno estaba
originalmente codificada y ahora se ha decodificado para ofrecer una mejor legibilidad.Las contribuciones en otros idiomas se pueden consultar aquí:
Como cuestión de sentido común, primero intenta discutir el cambio que deseas hacer a este repositorio a través de un issue.
chapter02/ssh_brute.py importaba pxssh como una librería independiente, pero en
realidad es una librería dentro de la librería pexpect. El error provocaba un
ModuleNotFoundError y ha sido corregido. El código en sí, tal como se presenta en el
libro, estaba plagado de errores de indentación que lo hacían inutilizable y se ha
llevado a un estado funcional.chapter02/ssh_brutekey.py requería una serie de claves pregeneradas para funcionar;
además, el libro indica al lector que adquiera dichas claves en una URL
que actualmente devuelve una respuesta 403. Debido a eso, se ha añadido un
archivo comprimido que contiene las claves al subdirectorio chapter02.chapter02/ssh_botnet.py tenía una declaración de importación no utilizada de optparse que
se eliminó. Parece que era un fragmento de un intento abortado de
implementar una CLI para este script. Sorprendentemente, se dejó ahí colgando,
incluso en la versión impresa del libro. El código que inicializa la
botnet y emite sus comandos se organizó bajo el ámbito de ejecución __main__
por motivos de estandarización. Los dos comandos emitidos a los bots
se han unificado para evitar un número innecesario de declaraciones de retorno.chapter02/conficker.py eliminó la llamada no utilizada a la librería sys.chapter03/discover_networks.py tuvo que ser reimplementado en lugar de solo
refactorizado. Originalmente no solo usaba la obsoleta librería mechanize, sino que
también interactuaba con el servicio WiGLE de una manera que ya no es necesaria,
ya que WiGLE ahora proporciona una API. Por esa razón, el código se ha estandarizado
y se implementó una nueva función wigle_print usando la librería requests para enviar una solicitud HTTP GET autenticada a WiGLE. La
respuesta devuelve un objeto JSON al que se puede acceder directamente, haciendo
innecesario también el uso de la librería re. Se añadió manejo de excepciones
para que el script sea capaz de lidiar con los mensajes de respuesta de error
enviados por la API. Ten en cuenta que
este script depende de winreg, que solo se ejecuta en instalaciones de Python
bajo el sistema operativo Microsoft Windows, y requiere privilegios de Administrador
durante la ejecución para acceder a las claves del Registro. Hay que registrar una cuenta
en https://wigle.net/account para acceder a la API.chapter03/pdf_read.py ahora usa la librería PyPDF4 en lugar de la
obsoleta PyPDF. El libro hace referencia a un archivo PDF específico en el
texto y se ha añadido al subdirectorio chapter03.chapter03/exif_fetch.py requería un argumento features="html.parser" en la
llamada al constructor del objeto BeautifulSoup. Se añadió en la línea 15
. Este script solo funciona en aplicaciones web que envuelven imágenes entre
etiquetas HTML img (una práctica poco común en las aplicaciones web
modernas que dependen en gran medida de JavaScript).chapter03/skype_parse.py usa el archivo main.db como ejemplo. Se ha
añadido al subdirectorio chapter03/skype_profile por conveniencia.chapter03/firefox_parse.py usa varios archivos .sqlite como ejemplos. Se
han añadido al subdirectorio chapter03/firefox_profile por
conveniencia.chapter03/iphone_messages.py hace referencia a archivos de copia de seguridad de iPhone que no fueron
puestos a disposición por el autor. Debido a esto, el código ha sido refactorizado
pero permanece sin probar.chapter04/geo_ip.py usaba la obsoleta librería pygeoip. Como
sugirió su creador,
geoip2 debería usarse ahora. Se intentó mantener el código recién
implementado lo más similar posible a la implementación original en
el libro, pero se tuvieron que hacer algunos cambios para adaptarse a la nueva
estructura de paquetes de geoip2 y sus atributos. El archivo de base de datos necesario
para ejecutar el script se descargó de
MaxMind y se puso
a disposición en el directorio chapter04. También se implementó una CLI
usando argparse.chapter04/print_direction.py lanzaba una excepción UnicodeDecodeError al
abrir el archivo en la implementación original. Se ha corregido añadiendo
un argumento rb al administrador de contexto que maneja el archivo.chapter04/find_ddos.py imprimía la dirección de origen del ataque
Hivemind como su destino, haciendo inútil la salida. La variable correcta dst
ahora se muestra en stdout. El libro hace referencia a un archivo llamado
traffic.pcap que no fue puesto a disposición por el autor, por lo que el código
ha sido refactorizado pero permanece sin probar.chapter04/test_domain_flux.py devuelve que se realizaron cero solicitudes sin respuesta
al analizar el archivo pcap proporcionado por el autor. Por alguna razón,
los propios paquetes no tienen establecido el valor del campo DNS Resource Record,
por lo que la condición en la función dns_QR_test siempre se evalúa como falsa.
Siendo ese el caso, la condición que evalúa el campo DNSRR se ha eliminado
de la
declaración condicional y ahora se analizan todos los paquetes UDP que tienen
el puerto 53 como origen. Esto da como resultado un código menos eficiente, pero
al menos genera los resultados tal como se pretende en el libro.chapter05/blue_bug.py usa la librería PyBluez, que a su vez solicita la
BlueZ y los archivos de cabecera como se indica en sus
instrucciones de instalación.
Estas dependencias deben instalarse antes de instalar PyBluez como
requisito. En Linux esto se puede realizar ejecutando el comando
apt install bluetooth libbluetooth-dev. El código original hace referencia a
un objeto client_sock inexistente que ha sido reemplazado por phone_sock.chapter05/ftp_sniff.py tenía una falla lógica que hacía que presentara un
nombre de usuario capturado pero no la contraseña debido a una mala implementación de una
declaración if... else
Se ha corregido reemplazando la declaración condicional por
una cláusula if anidada.chapter05/ninja_print.py requiere la librería obexftp para funcionar. Esta
librería fue escrita para Python 2 y no ha sido portada
ni reemplazada por una equivalente hasta la fecha, por lo que el código
permanece tal como lo escribió el autor en su versión de Python 2.chapter05/__init__.py y chapter06/__init__.py se añadieron para permitir
la importación de módulos desde chapter05/dup.py y chapter06/anon_browser.py,
respectivamente.chapter06/anon_proxy.py fue reimplementado con la librería MechanicalSoup
Python 3. Integra las modificaciones que fueron necesarias para
proxy_test.py, useragent_test.py y print_cookies.py.chapter06/anon_browser.py también fue reimplementado con MechanicalSoup
y sufrió algunas modificaciones en el código. La librería cookielib
fue reemplazada por http.cookiejar en el método constructor de la
clase AnonBrowser y el parámetro user_agents ahora acepta una lista de
cadenas en lugar de una tupla.chapter06/link_parser.py fue refactorizado usando nuevas formas de manejar las
implementaciones de re y bs4.