Skip to content
KitploitKITPLOIT
FerramentasBlog
Enviar
FerramentasBlog
Enviar

Ferramentas de Hacking, PenTest e Cibersegurança para o seu Arsenal de Segurança!

Kitploit é um diretório de ferramentas de hacking, cibersegurança e pentesting. Descubra as últimas atualizações de projetos para encontrar vulnerabilidades, analisar sistemas, automatizar testes e fortalecer sua segurança.

··Feeds·Contato·Privacidade·© 2026 Kitploit

Diretório de Ferramentas

Categorias

Ver todas as categorias
Loading categories
ExportHider — ExportHider: Gerando Tabela de Exportação durante o Tempo de Execução para Ocultar as Funções Exportadas do Arquivo DLL. | Kitploit
Ferramentas/GitHubGitHub/frkngksl/exporthider
Análise Dinâmica de Código (DAST)ExploraçãoEngenharia ReversaAnálise de MalwareAnálise de BináriosRed TeamingDesenvolvimento de Payloads
GitHubfrkngksl/exporthider

ExportHider

ExportHider: Gerando Tabela de Exportação durante o Tempo de Execução para Ocultar as Funções Exportadas do Arquivo DLL.

Ver Repositório
332há 4 mesesRevisado pelo Kitploit

Mais Populares

Ver todos →

Descubra as ferramentas mais usadas pela nossa comunidade.

Explore todas as ferramentas

Navegue pela nossa coleção de ferramentas

Ver todas as ferramentas →
Compartilhar

ExportHider

ExportHider gera um modelo de DLL em C++ que contém um stub de código que permite ocultar Funções Exportadas do Diretório de Exportação da DLL no sistema de arquivos. Após colocar as definições das funções e compilar o arquivo, você não verá as funções de exportação ocultas através de Visualizadores de Arquivos PE como o CFF Explorer. No entanto, como o stub de código no modelo recria o Diretório de Exportação durante a execução, chamadas legítimas de GetProcAddress seriam executadas com sucesso. Este método funciona apenas para carregamento dinâmico de DLL ou casos de carregador personalizado de DLL.

Como Funciona?

Normalmente, quando você deseja definir uma Função Exportada em arquivos DLL (em C ou C++), basta colocar a palavra-chave __declspec(dllexport) antes do nome da função, ou criar um arquivo .def. Após a compilação, o compilador cria uma tabela específica chamada Diretório de Exportação para armazenar as informações relacionadas às Funções Exportadas. A estrutura do Diretório de Exportação pode ser vista abaixo:

Quando um processo deseja usar uma função de um arquivo DLL, o Windows Loader simplesmente analisa essa estrutura e importa as funções solicitadas usando os arrays AddressOfFunctions, AddressOfNames, AddressOfNameOrdinals.

A rotina específica para importar uma função é explicada em detalhes no post do blog de ferreirasc, mas resumidamente, para uma função importada pelo nome, o Loader itera pelo array AddressOfNames (os valores desse array são apenas valores RVA) e busca o nome fornecido. Quando o loader encontra uma correspondência na posição “i”, ele se refere ao i-ésimo índice do array AddressOfNameOrdinals e obtém o ordinal associado a esta função. Tendo o ordinal, o loader se refere a AddressOfFunctions na posição do valor ordinal para finalmente obter o RVA associado à função importada.

O ponto crucial aqui é que todas essas operações de busca e acesso pelo Windows Loader, quando LoadLibrary é chamado, são feitas após a DLL ser mapeada no espaço de endereço do processo. Durante o mapeamento da DLL, todo o arquivo DLL, incluindo seus cabeçalhos PE, é escrito na memória, e o Loader analisa os cabeçalhos na memória para alcançar o Diretório de Exportação. Isso significa que se a própria DLL for capaz de sobrescrever seus cabeçalhos PE na memória para alterar o Endereço do Diretório de Exportação (simplesmente o índice 0 do DataDirectory) após se anexar ao processo, o loader pode procurar funções para importar em um Diretório de Exportação arbitrário, em vez do Diretório de Exportação adicionado pelo compilador.

Parâmetros da Linha de Comando

root@kitploit:~

   __                       _          _     _
  /__\_  ___ __   ___  _ __| |_  /\  /(_) __| | ___ _ __
 /_\ \ \/ / '_ \ / _ \| '__| __|/ /_/ / |/ _` |/ _ \ '__|
//__  >  <| |_) | (_) | |  | |_/ __  /| | (_| |  __/ |
\__/ /_/\_\ .__/ \___/|_|   \__\/ /_/ |_|\__,_|\___|_|
          |_|
                     by @R0h1rr1m

Usage of C:\Users\Public\DLLDemo\ExportHider.exe:

    -h | --help                                 Show the help message.
    -i | --input <Input Path>                   Input path for the list of function names to be hidden. (Mandatory)
    -o | --output <Output Path>                 Output path for the DLL template. (Mandatory)
    -n | --name <DLL Name>                      Name of the DLL for the Export Directory. (Mandatory)
    -c | --count <Number of Other Functions>    Number of other exported functions that won't be hidden.

Em relação ao parâmetro -i | --input <Input Path>, você precisa especificar um caminho para o arquivo de entrada que armazena os nomes das funções a serem ocultados linha por linha. O conteúdo de um exemplo de arquivo de entrada seria:

root@kitploit:~
TestFunction1
TestFunction2
TestFunction3

Em relação ao parâmetro -c | --count, se você não quiser ocultar todas as suas funções exportadas (ou seja, existem algumas funções exportadas com __declspec(dllexport) ou arquivo .def, e elas aparecem no Diretório de Exportação do arquivo DLL no sistema de arquivos através de Visualizadores de Arquivos PE), basta especificar quantas existem usando este parâmetro, porque a ferramenta precisa dessa informação ao fazer cálculos de memória.

Vídeo de Demonstração Rápida

Soluções Alternativas

Se você quiser brincar com a técnica, há dois pontos interessantes que encontrei durante o desenvolvimento do projeto. Você pode precisar conhecê-los antes de alterar o projeto:

  • O Windows Loader usa um algoritmo semelhante à Busca Binária para encontrar a função exportada se você chamar a função GetProcAddress com um nome. Por causa disso, os nomes de todas as funções exportadas, incluindo as ocultas, precisam estar ordenados no array AddressOfNames. Caso contrário, a função GetProcAddress retorna NULL. Portanto, usei o algoritmo Bubble Sort para ordenar os membros deste array.
  • Como disse acima, os arrays AddressOfNames, AddressOfFunctions, DataDirectory e alguns outros campos exigem valores em Endereços Virtuais Relativos (RVAs). Além disso, eles armazenam esses valores RVA em campos de tamanho DWORD. Quando você aloca uma região de memória para um novo diretório de exportação arbitrário usando funções de Alocação Dinâmica de Memória como VirtualAlloc ou HeapAlloc, os endereços fornecidos estarão longe da região mapeada da DLL, e os valores RVA não cabem nos campos de tamanho DWORD, resultando em estouro de inteiro. Foi por isso que usei variáveis globais do tipo array de bytes no modelo DLL para requisitos de memória.

Caso de DLL Importada Estaticamente (também conhecido como DLL Sideloading)

Meu primeiro objetivo ao criar este projeto foi gerar uma DLL que tivesse exportações ausentes (ou ausência completa de uma tabela de exportação), mas que ainda fosse carregada com sucesso pelo processo recém-criado. Pensei que esse comportamento poderia trazer um novo campo de exploração para os payloads de DLL sideloading. No entanto, não consegui encontrar nenhuma função ou maneira pela qual o stub de correção do diretório de exportação seja executado antes de o Windows Loader verificar as funções exportadas da DLL.

dll_timing_problem (1)

Mais tecnicamente, notei o seguinte fluxo e chamada de função para cada DLL nas seções de código relacionadas ao Windows Loader no NTDLL (coletado das minhas anotações antigas; pode haver alguns erros porque não sou um engenheiro reverso especialista):

root@kitploit:~
1. LdrpMapDll - This is where the DLL is mapped to the Process Address Space. All DLLs that satisfy the DLL name condition 
                are directly put into the memory, no precheck control for the filesystem version.
2. LdrpSnapModule - This is where the Windows Loader starts to resolve imports. For each import descriptor, it parses the PE 
                    structure, checks the export table, binary searching for the imported function, calculating RVA of that,
                    and writes its address to the corresponding caller's process' Import Address Table entry during this function.
3. LdrpDoPostSnapWork - If step 2 succeeds for each imported function, memory protections, TLS initialization, CFG enablement
                        are done in this function.
4. LdrpInitializeNode - If step 3 succeeds, there are module linking functions in this step.
5. LdrpCallTlsInitializers - This is where the TLS callbacks are called before the DllMain function.
6. LdrpCallInitRoutine - This is where the DLLMain itself is called for the first time for the imported DLL. In the original 
                         solution, this function is too late to fix the export table.

Quando você executa um executável que importa uma DLL, se o Windows loader não conseguir encontrar o nome da função necessária na tabela de exportação da DLL, ele interrompe a execução e não executa funções que são executadas após LdrpSnapModule.

Para o caso de DLL sideloading, não podemos modificar o processo chamador; portanto, a única chance de corrigir a Tabela de Exportação dinamicamente é encontrando uma oportunidade de execução de código entre as funções LdrpMapDll e LdrpSnapModule, porque o Loader interrompe imediatamente durante as verificações da função LdrpSnapModule. Tentei callbacks TLS, carregamentos de segunda DLL, exportações encaminhadas e algumas outras soluções alternativas, mas nenhuma delas me ajudou a encontrar tal lugar, então, infelizmente, esse método não funciona diretamente para DLL sideloading ou DLLs importadas estaticamente. Se você descobrir uma solução ou uma solução alternativa viável para esse problema, ficarei muito feliz em explorá-la — seja discutindo a ideia, pensando juntos na abordagem ou implementando-a. Qualquer contribuição nesse sentido será muito apreciada.

Uma maneira possível de usar este método para casos de DLL Sideloading é dividir todo o trabalho em duas DLLs, a saber, a Proxy DLL e a Payload DLL. A Proxy DLL assume o nome que o EXE espera e possui exportações visíveis que satisfazem a verificação de importação estática do loader, enquanto a Payload DLL contém a funcionalidade oculta real, tem exportações ausentes e reconstrói sua tabela de exportação no DllMain. Não acho que esta seja uma boa solução alternativa para este problema, então não a implementei.

Referências

  • https://rioasmara.com/2021/10/10/analyze-dll-export-with-pe-bear/
  • https://ferreirasc.github.io/PE-Export-Address-Table/

Aviso Legal

Apenas para testes de segurança autorizados. O uso indevido desta ferramenta contra sistemas sem permissão explícita é ilegal.

Baixar ferramenta