DLL Hijacking, como o ataque funciona
DLL Hijacking é uma tática de “sequestro” de código, isto é, quando se consegue forçar uma execução indevida de código contra aplicações das vítimas. Este artigo busca explicar o funcionamento deste ataque. Para começar, precisamos entender alguns princípios interessantes sobre geração de arquivos executáveis.
Quando codificamos um programa em C/C++ que se utiliza de uma biblioteca externa, há duas formas de linkarmos os seus recursos ao nosso programa: Link Estático e Link Dinâmico. [1]
No link estático você linka a biblioteca junto com o seu programa no momento do build do projeto. Isto significa que o produto final do build será um arquivo executável que já possui embutido tanto o seu programa quanto o conteúdo da biblioteca linkada. No comando a seguir você consegue verificar um exemplo de link estático de uma biblioteca chamada math.lib que se encontra no diretório /lib junto ao programa app.c para gerar o executável app.exe:
gcc app.c -L.lib/ -lmath.lib -o app.exe
A vantagem desta forma de link é que o seu usuário terá um arquivo executável pronto para uso com todos os recursos necessários devidamente empacotados. A desvantagem desta abordagem é o consequente tamanho do executável final ao trazer para dentro todas as bibliotecas envolvidas.
O leitor pode estar preocupado com isso e se perguntar: é possível um mecanismo em que eu carregue para a memória de programa uma biblioteca somente quando o meu usuário precisar dela? Sim, este artifício se chama Link Dinâmico.
Com este mecanismo o seu produto final é o seu executável acompanhado de arquivos separados de bibliotecas com extensão DLL (Dynamic Link Library). Quando um recurso do seu programa precisa de um recurso de biblioteca externa, o sistema procura por um arquivo de DLL com o nome especificado no programa dentro do mesmo diretório em que ele se encontra. Caso ele não ache, ele busca nas variáveis de PATH do seu sistema operacional.
Agora você consegue gerar um arquivo executável que pesa pouco e só carrega para dentro da memória de execução as bibliotecas que serão usadas pelo usuário. É possível imaginar um cenário assim caso você faça um aplicativo tipo o Photoshop. Você poderia empacotar as funcionalidades de pinceis em brushes.dll e de filtros em filters.dll. Assim, um artista digital provavelmente só acabaria carregando para a sua experiência o brushes.dll sem precisar onerar a memória com o filters.dll. A desvantagem é que quando este carregamento ocorre, o usuário pode sentir o programa “engasgando” momentaneamente. Isso ocorre porque ele para a sua execução para linkar dinamicamente a biblioteca quando ela é requisitada.
Sendo você um entusiasta de segurança da informação ou um neurótico, você deve ter percebido a oportunidade que um atacante teria aqui. Imagine que um atacante identifique quais DLL’s uma aplicação do sistema do usuário use. Ele pode substituir uma DLL no sistema por uma DLL maliciosa que irá se comportar igual à DLL original, mas executar código malicioso também. Ou também ele pode identificar que um programa espera achar uma DLL no PATH do sistema. Sabendo da ordem em que as DLL’s são buscadas, isto é, primeiro no diretório da aplicação e depois nas variáveis de PATH, ele pode deixar uma versão maliciosa da DLL de mesmo nome dentro do diretório para que o programa carregue a sua versão ao invés da versão especificada no PATH. [2]
Enfim, é nisso o que consiste o ataque de DLL Hijacking, cuja tradução livre poderia ser Sequestro de DLL. Caso algum dia você desenvolva aplicações desktop, leve isto em consideração para aumentar a segurança de seu sistema. Caso você seja um profissional de segurança sondando um ambiente após um comprometimento, verifique tentativas de permanência do atacante no sistema verificando algum histórico de mudança de PATH’s ou arquivos DLL’s das aplicações dos computadores.
[1] https://cs-fundamentals.com/tech-interview/c/difference-between-static-and-dynamic-linking