
Weaponize o sequestro de DLL facilmente. Coloque um backdoor em qualquer função de qualquer DLL.

O DllShimmer analisa a DLL original e extrai informações sobre as funções exportadas (nome, número ordinal e informações de forwarder). Com base nessas informações, o DllShimmer cria um arquivo C++ boilerplate (.cpp). O arquivo gerado permite que você adicione seu próprio código a cada função exportada da DLL original sem interromper a operação normal do programa. Não é necessário engenharia reversa nem instrumentação, pois o DllShimmer não depende de assinaturas de funções (veja mais em "Limitações").
O segundo arquivo gerado é um arquivo .def, que garante que todas as DLLs exportadas do proxy após a compilação tenham os mesmos nomes e números ordinais da DLL original.
Após a compilação, o EAT na DLL proxy é uma cópia exata do EAT da DLL original. Todos os nomes e números ordinais das funções exportadas correspondem, e as funções encaminhadas também são encaminhadas. O DllShimmer não encaminha explicitamente todas as funções (como a maioria das ferramentas), criando uma estrutura EAT completamente nova e suspeita.
Compile o código-fonte Go ou baixe o binário compilado.
Dependências:
x86_64-w64-mingw32-g++x86_64-w64-mingw32-dlltoolExemplo:
# Colocar backdoor em version.dll (proxy para caminho absoluto)
./DllShimmer -i version.dll -o project/ -x "C:/Windows/System32/version.dll" -m
# Colocar backdoor em chat.dll qualquer (proxy para caminho relativo)
./DllShimmer -i chat.dll -o project/ -x "lib/chat2.dll" -m
# Colocar backdoor em app.dll qualquer (ligação estática com a DLL original)
./DllShimmer -i app.dll -o project/ -x "app2.dll" -m --static
Parâmetros:
-i / --input <caminho> [obrigatório]
A DLL original na qual você deseja colocar o backdoor.
-o / --output <caminho> [obrigatório]
O caminho para o diretório onde o DllShimmer salvará todos os arquivos gerados.
-x / --original <caminho> [obrigatório]
No caso de ligação dinâmica (padrão), informe o caminho onde a DLL proxy encontrará a DLL original no sistema de destino.
No caso de ligação estática (--static), especifique apenas o nome da DLL original. Ela será procurada de acordo com a ordem padrão de carregamento no Windows.
-m / --mutex [opcional]
Ativar esta opção adicionará um mutex ao arquivo-fonte, o que impede que seu backdoor seja executado mais de uma vez durante uma única execução do programa. Todas as funções originais continuarão funcionando normalmente.
--static [opcional]
Ativa a ligação estática entre a DLL proxy (IAT) e a DLL original (EAT). Isso gera um arquivo .lib adicional no diretório de saída, que atua como a DLL original para compilação estática.
Essa técnica tem algumas limitações sérias em comparação com a ligação dinâmica:
No entanto, a ligação estática pode ser mais furtiva e natural em alguns cenários.
Padrão: o DllShimmer sempre usa ligação dinâmica com as funções LoadLibraryA() e GetProcAddress().
--debug-file <caminho> [opcional]
Salva os logs de depuração em um arquivo. Os logs são gravados em um arquivo continuamente enquanto o programa está em execução. Se selecionado, os logs não são impressos no STDOUT.
Padrão: o DllShimmer sempre grava logs de depuração no STDOUT.
Exemplo de saída de depuração:

Antes de começar a solucionar problemas:
--static). É mais fácil depurar com ligação dinâmica (padrão).--debug-file)..cpp gerado, não vejo todas as funções exportadas da DLL original.As funções definidas na DLL original como "encaminhadas" não são incluídas no arquivo .cpp. No entanto, elas estão visíveis no arquivo .def. Elas também serão exportadas após a compilação, exatamente como na DLL original.
Às vezes, sua DLL proxy exibe um erro ao carregar a DLL original, e o código de erro é 126, mesmo que você tenha especificado teoricamente o caminho relativo correto no parâmetro -x. Por que não está funcionando?!?
As DLLs são procuradas no Current Directory. Em 98% dos casos, esse é simplesmente o local do arquivo EXE principal, mas há programas (principalmente os antigos legados) que alteram arbitrariamente o Current Directory usando, por exemplo, SetCurrentDirectoryW(). O programa principal está ciente dessa alteração, então ele carrega sua DLL proxy corretamente, mas você não está ciente disso e tenta carregar a DLL original de forma relativa, enquanto o programa a procura no Current Directory alterado.
Essa regra se aplica tanto ao carregamento estático quanto ao dinâmico da DLL original. Infelizmente, com ligação estática, esse problema é muito mais difícil de detectar porque não temos informações de depuração. O carregador do sistema simplesmente falha e pronto. É por isso que sempre recomendo usar primeiro a ligação dinâmica padrão.
No caso de ligação dinâmica, temos duas opções:
-x para a nova situação do Current Directory.Current Directory dinamicamente para procurar DLLs onde desejarmos.No caso de ligação estática, na verdade temos apenas uma opção:
Current Directory.