
Uma DLL autônoma que exporta bancos de dados em texto claro uma vez injetada no processo do KeePass.
Uma DLL autônoma que exporta bancos de dados em texto claro uma vez injetada no processo do KeePass.
Fortemente inspirada pelos grandes projetos KeeFarce, KeeThief e KeePassHax.
Há alguns anos, @denandz lançou o KeeFarce, a primeira ferramenta ofensiva projetada para extrair bancos de dados do KeePass em texto claro. Ela funciona injetando uma DLL no processo em execução e, em seguida, percorre o heap usando ClrMD para encontrar os objetos necessários e invocar o método de exportação nativo do KeePass via reflexão. Sua única desvantagem na época era que vários arquivos precisavam ser gravados no alvo (a DLL de extração + a DLL do ClrMD + o injetor + uma DLL de bootstrap).
Um ano depois, @tifkin_ e @harmj0y lançaram uma revisão aprofundada das técnicas ofensivas direcionadas ao KeePass (embora não esteja mais disponível no blog do harmj0y, os artigos podem ser encontrados na Wayback Machine: parte 1, parte 2). Isso resultou no lançamento do KeeThief, uma ferramenta capaz de descriptografar a chave-mestre do KeePass (inclusive quando métodos alternativos de autenticação são usados). Funcionou tão bem que os desenvolvedores do KeePass adicionaram um parâmetro para mitigar essa técnica (ela pode ser desativada editando o arquivo de configuração do KeePass se o usuário tiver direitos suficientes, o que é bastante comum).
Essas ferramentas rapidamente se tornaram minhas preferidas durante testes de penetração, mas logo se tornaram obsoletas, pois suas técnicas de injeção (ou seja, o famoso grupo de APIs Win32 VirtualAllocEx, WriteProcessMemory, CreateRemoteThread, WriteProcessMemory, etc.) agora disparam detecção imediatamente. @snovvcrash abordou esse problema fazendo um fork do KeeThief (agora em um repositório privado, mas ainda acessível aqui) para melhorar o mecanismo de injeção com D/Invoke, escrevendo um ótimo artigo detalhando o processo que seguiu. Embora tenha demonstrado a viabilidade de manter o KeeThief, acho difícil implementar regularmente novas técnicas de injeção, pois o código do KeeThief está fortemente ligado ao seu injetor.
@holly-cracker também lançou o KeePassHax, que vem como uma única DLL e usa apenas reflexão para descriptografar a chave-mestre do KeePass. Inspirado por esse trabalho, decidi fazer o mesmo com o KeeFarce e escrever minha própria ferramenta de extração do KeePass com as seguintes características:
O KeeFarce Reborn também fornece uma DLL de plugin do KeePass para fazer o KeePass se injetar sem se preocupar com injetores!
Como o código depende apenas do .NET Framework, sem dependências externas, ele deve compilar facilmente no Visual Studio 2015 ou superior.
O KeeFarce Reborn não inclui um injetor para carregar a DLL no processo do KeePass. Isso é deliberado; como os injetores se tornam obsoletos a cada poucos meses, você terá que usar o seu. As partes a seguir demonstram duas maneiras típicas de realizar a injeção.
Pré-requisito: acesso de escrita ao diretório de plugins do KeePass.
O KeePass possui um framework de plugins para fornecer funcionalidades adicionais aos usuários. Ele funciona carregando uma DLL no processo do KeePass, permitindo que desenvolvedores de plugins executem ações dentro do domínio de aplicação do KeePass.
Como resultado, podemos abusar dessa funcionalidade para carregar o KeeFarce Reborn como um plugin, sem precisar usar um injetor externo! Basta compilar o projeto KeeFarceRebornPlugin e copiar a DLL para o diretório de plugins (localizado na raiz do KeePass, ou seja, "C:\Program Files\KeePass Password Safe 2\Plugins" para uma instalação global).
Para que o projeto seja compilado corretamente, você precisará copiar a versão do assembly do KeePass.exe alvo para o diretório KeeFarceRebornPlugin, ou usar o PLGX se quiser que o plugin resultante seja compatível com qualquer versão do KeePass.
Na próxima vez que o KeePass for iniciado e um banco de dados for desbloqueado, a DLL será carregada e a injeção será realizada. Se o KeePass já estiver em execução, você precisará aguardar a próxima reinicialização para que a injeção ocorra (ou forçar a reinicialização você mesmo).
⚠️ Assim que um plugin é carregado, o arquivo DLL fica protegido contra gravação até que o KeePass seja fechado. Tenha isso em mente para garantir que você não deixe plugins maliciosos para trás durante as avaliações.
Se você não tiver acesso de escrita ao diretório de plugins do KeePass, pode dar uma olhada no artigo do Quarkslab, que demonstra como carregar plugins com menos privilégios por meio do cache de plugins.
Pré-requisito: o KeePass está em execução + um banco de dados desbloqueado pelo usuário + você tem direitos suficientes para injetar no processo do KeePass.
Como eu pessoalmente acho mais fácil injetar shellcode de forma furtiva do que DLL em um processo remoto, a primeira coisa que normalmente faço é gerar um shellcode independente de posição a partir da nossa DLL. Aparentemente, o projeto donut de @odzhan e @TheWover atende perfeitamente às nossas necessidades!
Compilamos o donut a partir de um commit no branch dev, pois ele corrige uma issue no gerenciamento de domínios de aplicação que nos impediria de realizar reflexão no domínio padrão.
git clone https://github.com/TheWover/donut/
cd donut
git checkout 9d781d8da571eb1499122fc0e2d6e89e5a43603c
Podemos compilar facilmente a partir do x64 Native Tools Command Prompt do Visual Studio usando o utilitário nmake:
nmake -f Makefile.msvc
Gerar o shellcode é tão simples quanto:
.\donut.exe "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll" -c KeeFarceReborn.Program -m Main -e 1
[ Donut shellcode generator v0.9.3
[ Copyright (c) 2019 TheWover, Odzhan
[ Instance type : Embedded
[ Module file : "C:\KeeFarceReborn\KeePassReborn\bin\Release\KeeFarceReborn.dll"
[ Entropy : None
[ File type : .NET DLL
[ Class : KeeFarceReborn.Program
[ Method : Main
[ Target CPU : x86+amd64
[ AMSI/WDLP : continue
[ Shellcode : "loader.bin"
Observe que
-e 1é necessário para desabilitar a entropia; caso contrário, o processo injetado não ficará no domínio de aplicação padrão.
Vamos comprimi-lo usando PowerShell para facilitar a integração no código do injetor:
$bytes = [System.IO.File]:https://raw.githubusercontent.com/d3lb3/keefarcereborn/HEAD/:ReadAllBytes(%22C:%5Cdonut%5Cloader.bin%22)
[System.IO.MemoryStream] $outStream = New-Object System.IO.MemoryStream
$deflateStream = New-Object System.IO.Compression.DeflateStream($outStream, [System.IO.Compression.CompressionLevel]::Optimal)
$deflateStream.Write($bytes, 0, $bytes.Length)
$deflateStream.Dispose()
$outBytes = $outStream.ToArray()
$outStream.Dispose()
$b64 = [System.Convert]::ToBase64String($outBytes)
Write-Output $b64 | clip
Agora você tem um payload pronto para ser injetado com sua técnica favorita. Se você não sabe o que fazer agora, sugiro que consulte a página Code & Process Injection do ired.team para se familiarizar com o conceito. Os cursos de desenvolvimento de malware da @SEKTOR7 são cheios de ótimos aprendizados se você puder pagar por eles.
Como exemplo, vamos injetar nosso payload usando o código VeraCryptThief do snovvcrash (ele próprio inspirado nos cursos da SEKTOR7), que faz uso de D/Invoke. Para demonstrar, copiei o projeto dele na pasta SampleInjector; só precisamos colar nosso shellcode comprimido e compilar em x64.
Embora ainda contorne o Defender no momento (novembro de 2022), ajustar seu próprio injetor será, obviamente, necessário para contornar EDRs modernos. Este injetor de exemplo está aqui apenas para demonstrar que tudo se comporta como esperado.
Ao executar .\SampleInjector.exe com um banco de dados do KeePass aberto, a DLL será carregada e a injeção será realizada.
Assim que a injeção for realizada, você verá mensagens de depuração sendo exibidas em MessageBox (que obviamente devem ser removidas em um cenário real de teste de penetração) e, em seguida, encontrará o banco de dados exportado em %APPDATA% do usuário atual (escolhido por padrão, pois o KeePass terá certeza de ter acesso de escrita). O arquivo XML exportado pode posteriormente ser importado em qualquer banco de dados do KeePass sem solicitar senha.
Se as funcionalidades de plugin ou exportação estiverem desabilitadas pela política, elas ainda podem ser habilitadas editando o KeePass.config.xml, desde que você tenha acesso de escrita:
<Policy>
<Plugins>true</Plugins>
<Export>true</Export>
</Policy>
Embora a principal questão relacionada à detecção de ferramentas de extração do KeePass sejam os injetores, a varredura em memória também pode disparar alertas ao analisar o shellcode ou a DLL do plugin. Talvez seja necessário ofuscar e/ou criptografar o shellcode para usar com seu injetor.
Se os DLLs de plugin forem eventualmente sinalizados pela análise estática, você ainda pode usar o formato de plugin PLGX do KeePass para evitar a detecção.
DISM.exe.Pull requests são bem-vindos. Sinta-se à vontade para abrir uma issue ou me enviar um DM no Twitter para sugerir melhorias.
Trechos de código foram tirados dos projetos KeeFarce, KeeThief e KeePassHax.
O mecanismo de injeção de exemplo foi retirado diretamente dos projetos de snovvcrash.