
Código-fonte do livro "Violent Python" de TJ O'Connor. O código foi totalmente convertido para Python 3, reformatado para estar em conformidade com os padrões PEP8 e refatorado para eliminar problemas de dependência envolvendo a implementação de bibliotecas obsoletas.
Código-fonte do livro "Violent Python" de TJ O'Connor. O código foi totalmente convertido para Python 3, reformatado para estar em conformidade com os padrões PEP8 e refatorado para eliminar problemas de dependência envolvendo a implementação de bibliotecas descontinuadas.
Uma conversão semelhante a esta foi disponibilizada por mim no código-fonte do livro "Black Hat Python", de Justin Seitz. Confira aqui se você ainda não o fez.
Basta criar um novo diretório (DIR) para o projeto, criar um novo
ambiente virtual ou venv para ele (recomendado), clonar este repositório
usando git clone e instalar os 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, agora obsoleta, foi substituída por argparse em
todo o código-fonte. Todo o parsing de argumentos agora está contido
no escopo de execução __main__ para cada arquivo. Todos os argumentos de CLI que eram
obrigatórios para a execução dos scripts, mas eram tratados como opcionais no
código original, agora são implementados como posicionais. Um prompt de uso agora está
disponível para todos os scripts que usam argparse ao fornecer um argumento -h para
a CLI. Deixar as responsabilidades tanto de boundary quanto de controller
para o parser da CLI definitivamente não é a melhor escolha em termos
de arquitetura de software, mas foi mantido como está devido à
necessidade de conformidade com a intenção do codificador original.PEP 8: E722 do not use bare except foram
refatoradas com cláusulas de exceção mais específicas.close() nos objetos de arquivo/banco de dados abertos. Por
esse
motivo, todas as instâncias de manipulação de arquivos e bancos de dados foram refatoradas
usando gerenciadores de contexto.# -*- coding: utf-8 -*-) foi eliminado devido à
padronização do UTF-8 como codificação padrão para Python 3 (substituindo
o ASCII do Python 2).Os arquivos não listados abaixo podem ser considerados como refatorados de uma forma ou de outra, conforme estabelecido na seção "Notas".
chapter01/vuln_scanner.py foi estruturado de tal forma que um arquivo inexistente levaria a uma exceção OSError em tempo de execução. Por esse
motivo, o controle de iteração que chama check_vulns() foi movido para dentro da
instrução condicional definida na função principal.chapter02/nmap_scan.py implementava uma função principal unicamente com o propósito
de chamar a biblioteca obsoleta optparse, que foi substituída por
argparse. Por causa disso, a função principal foi removida. Uma estrutura
de controle de iteração que fazia parte da chamada optparse no código
original foi implementada de tal forma que uma nova chamada ao nmap era executada
para cada porta varrida. A iteração foi movida para dentro da função
nmap_scan para evitar o desperdício de ciclos.chapter02/ssh_command.py teve seu código de inicialização movido para o
escopo de execução __main__. Os nomes das variáveis usadas no escopo externo
que costumavam conflitar com os nomes dos parâmetros das funções foram
alterados. As informações do prompt de retorno eram originalmente codificadas e agora
foram decodificadas para proporcionar melhor legibilidade.Contribuições em outros idiomas podem ser conferidas aqui:
Como questão de bom senso, primeiro tente discutir a mudança que deseja fazer neste repositório por meio de uma issue.
chapter02/ssh_brute.py importava pxssh como uma biblioteca independente, mas na
verdade ela é uma biblioteca sob a biblioteca pexpect. O bug levava a um
ModuleNotFoundError e foi corrigido. O código como apresentado no
livro estava repleto de erros de indentação que o tornavam inutilizável e foi
colocado em um estado funcional.chapter02/ssh_brutekey.py exigia uma série de chaves pré-geradas para funcionar;
além disso, o livro aponta o leitor para adquirir tais chaves em uma URL
que atualmente retorna uma resposta 403. Por causa disso, um arquivo compactado
contendo as chaves foi adicionado ao subdiretório chapter02.chapter02/ssh_botnet.py tinha uma instrução de importação não utilizada de optparse que
foi removida. Parece que era um fragmento de uma tentativa abandonada de
implementar uma CLI para este script. Surpreendentemente, ficou apenas pendurado ali,
até mesmo na versão impressa do livro. O código que inicializa o
botnet e emite seus comandos foi organizado sob o escopo de execução __main__
por questões de padronização. Os dois comandos emitidos para os bots
foram unificados para evitar um número desnecessário de instruções de retorno.chapter02/conficker.py removeu a chamada não utilizada à biblioteca sys.chapter03/discover_networks.py teve que ser reimplementado em vez de apenas
refatorado. Originalmente, ele não apenas usava a biblioteca obsoleta mechanize, mas também
interagia com o serviço WiGLE de uma forma que não é mais necessária,
uma vez que o WiGLE agora fornece uma API. Por esse motivo, o código foi padronizado
e uma nova função wigle_print foi implementada usando a biblioteca requests para enviar uma solicitação HTTP GET autenticada ao WiGLE. A
resposta retorna um objeto JSON que pode ser acessado diretamente, tornando
o uso da biblioteca re também desnecessário. Tratamento de exceções foi
adicionado para tornar o script capaz de lidar com mensagens de resposta de erro
enviadas pela API. Observe que
este script depende de winreg, que só é executado em instalações Python
sob o sistema operacional Microsoft Windows, e requer privilégios de Administrador
durante a execução para acessar as chaves do Registro. Uma conta deve ser
registrada em https://wigle.net/account para acesso à API.chapter03/pdf_read.py agora usa a biblioteca PyPDF4 em vez da
obsoleta PyPDF. O livro faz referência a um arquivo PDF específico no texto e
ele foi adicionado ao subdiretório chapter03.chapter03/exif_fetch.py exigia um argumento features="html.parser" na
chamada ao construtor do objeto BeautifulSoup. Ele foi adicionado na linha 15
. Este script só funciona em aplicações web que envolvem imagens entre tags HTML img
(uma prática rara em aplicações web modernas que dependem fortemente de
JavaScript).chapter03/skype_parse.py usa o arquivo main.db como exemplo. Ele foi
adicionado ao subdiretório chapter03/skype_profile por conveniência.chapter03/firefox_parse.py usa vários arquivos .sqlite como exemplos. Eles
foram adicionados ao subdiretório chapter03/firefox_profile por
conveniência.chapter03/iphone_messages.py faz referência a arquivos de backup do iPhone que não foram
disponibilizados pelo autor. Por causa disso, o código foi refatorado
mas permanece não testado.chapter04/geo_ip.py usava a biblioteca obsoleta pygeoip. Como
sugerido por seu criador,
geoip2 deve agora ser usado. Foi feita uma tentativa de manter o código
recém-implementado o mais semelhante possível à implementação original no
livro, mas algumas mudanças tiveram que ser feitas para acomodar a nova estrutura
de pacotes do geoip2 e seus atributos. O arquivo de banco de dados necessário para
executar o script foi baixado de
MaxMind e disponibilizado
no diretório chapter04. Uma CLI também foi implementada
usando argparse.chapter04/print_direction.py levantava uma exceção UnicodeDecodeError ao
abrir o arquivo na implementação original. Isso foi corrigido adicionando
um argumento rb ao gerenciador de contexto que manipula o arquivo.chapter04/find_ddos.py imprimia o endereço de origem do ataque Hivemind
como seu destino, tornando a saída inútil. A variável correta dst agora é
exibida no stdout. O livro faz referência a um arquivo chamado
traffic.pcap que não foi disponibilizado pelo autor, então o código foi
refatorado mas permanece não testado.chapter04/test_domain_flux.py retorna que zero solicitações sem resposta foram
feitas ao analisar o arquivo pcap fornecido pelo autor. Por alguma razão,
os próprios pacotes não têm o valor do campo DNS Resource Record definido,
então a condição na função dns_QR_test sempre é avaliada como falsa.
Sendo esse o caso, a condição que avalia o campo DNSRR foi removida
da
instrução condicional e todos os pacotes UDP que têm a porta 53 como sua
origem agora são analisados. Isso resulta em um código menos eficiente, mas
pelo menos produz os resultados como pretendido no livro.chapter05/blue_bug.py usa a biblioteca PyBluez, que por sua vez requer a
biblioteca BlueZ e os arquivos de cabeçalho, conforme declarado em suas
instruções de instalação.
Essas dependências devem ser instaladas antes de instalar PyBluez como um
requisito. No Linux, isso pode ser feito emitindo o comando
apt install bluetooth libbluetooth-dev. O código original faz referência a um
objeto client_sock inexistente que foi substituído por phone_sock.chapter05/ftp_sniff.py tinha uma falha de lógica que o fazia apresentar um
nome de usuário sniffado, mas nenhuma senha, devido à má implementação de uma instrução if... else. Isso foi corrigido substituindo a instrução condicional por
uma cláusula if aninhada.chapter05/ninja_print.py requer a biblioteca obexftp para funcionar. Esta
biblioteca foi escrita para Python 2 e não foi portada
ou substituída por uma equivalente até a presente data, então o código permanece
como escrito pelo autor em sua versão Python 2.chapter05/__init__.py e chapter06/__init__.py foram adicionados para permitir
a importação de módulos de chapter05/dup.py e chapter06/anon_browser.py,
respectivamente.chapter06/anon_proxy.py foi reimplementado com a biblioteca MechanicalSoup
do Python 3. Ele integra as modificações que foram necessárias para
proxy_test.py, useragent_test.py e print_cookies.py.chapter06/anon_browser.py também foi reimplementado com MechanicalSoup
e passou por algumas modificações no código. A biblioteca cookielib
foi substituída por http.cookiejar no método construtor da
classe AnonBrowser e o parâmetro user_agents agora aceita uma lista de
strings em vez de uma tupla.chapter06/link_parser.py foi refatorado usando novas maneiras de lidar com as
implementações de re e bs4.