Introducci贸n
En este art铆culo, veremos el concepto de secuestro de DLL y c贸mo se puede usar para lograr la persistencia del 谩rea de usuario en los sistemas Windows. Este m茅todo se describe en MITRE ATT & CK en: "Interceptaci贸n del orden de b煤squeda de DLL (T1038) ".
Los atacantes pueden utilizar la suplantaci贸n de DLL para muchos prop贸sitos diferentes, pero este art铆culo se centrar谩 en lograr la resistencia con aplicaciones de inicio autom谩tico. Por ejemplo, dado que Slack y Microsoft Teams se inician en el arranque (de forma predeterminada), la suplantaci贸n de DLL en una de estas aplicaciones permitir铆a al atacante obtener un acceso s贸lido a su objetivo, siempre que un usuario inicie sesi贸n.
Despu茅s de presentar el concepto de DLL, orden de b煤squeda de DLL y suplantaci贸n de DLL, lo guiar茅 a trav茅s del proceso de automatizaci贸n de la detecci贸n de interceptaci贸n de DLL . Este art铆culo hablar谩 sobre la detecci贸n de rutas de interceptaci贸n de DLL en Slack, Microsoft Teams y Visual Studio Code.
Finalmente, descubr铆 m煤ltiples rutas de interceptaci贸n de DLL utilizadas por diferentes aplicaciones, investigu茅 la causa ra铆z y descubr铆 que las aplicaciones que usan ciertas llamadas a la API de Windows son propensas a la interceptaci贸n de DLL cuando no se ejecutan desde
C:\Windows\System32\
.
Quiero agradecer a mi colega Josiah Massari (
@Airzero24
) por ser el primero en descubrir algunas de estas intercepciones de DLL, explicar su metodolog铆a e inspirarme a automatizar la detecci贸n.
驴Qu茅 es una DLL?
Una DLL es una biblioteca que contiene c贸digo y datos que pueden ser utilizados simult谩neamente por m谩s de un programa. ( Fuente ) La
funcionalidad de una DLL puede ser utilizada por una aplicaci贸n de Windows usando una de las funciones
LoadLibrary*
. Las aplicaciones pueden hacer referencia a archivos DLL dise帽ados espec铆ficamente para esas aplicaciones, o archivos DLL de Windows que ya est谩n en el disco en System32. Los desarrolladores pueden cargar archivos DLL desde System32 para usar la funcionalidad ya implementada en Windows en sus aplicaciones sin tener que escribir esta funcionalidad desde cero.
Por ejemplo, un desarrollador que necesita realizar solicitudes HTTP puede usar la biblioteca WinHTTP (
winhttp.dll
) en lugar de implementar solicitudes HTTP usando sockets sin formato.
Orden de b煤squeda e interceptaci贸n de DLL
Dado que las DLL existen como archivos en el disco, es posible que se pregunte c贸mo una aplicaci贸n sabe desde d贸nde cargar la DLL. Microsoft ha documentado el orden de b煤squeda de DLL en detalle aqu铆 .
A partir de Windows XP SP2, el modo de b煤squeda segura de DLL est谩 habilitado de forma predeterminada (
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode
). Cuando el modo seguro est谩 habilitado, el orden de b煤squeda de DLL es el siguiente:
- El directorio desde el que se carg贸 la aplicaci贸n.
- Directorio del sistema. Utilice la funci贸n GetSystemDirectory para obtener la ruta a este directorio.
- Directorio del sistema de 16 bits. No hay ninguna funci贸n que proporcione una ruta a este directorio, pero se busca.
- Directorio de Windows. Utilice la funci贸n GetWindowsDirectory para obtener la ruta a este directorio.
- Directorio actual.
- , PATH. , , App Paths. App Paths DLL.
Un sistema puede contener varias versiones de la misma DLL. Las aplicaciones pueden controlar la elecci贸n de la ubicaci贸n desde la que se debe cargar la DLL especificando la ruta completa o utilizando otro mecanismo como un manifiesto. ( Fuente )
Si la aplicaci贸n no especifica desde d贸nde cargar la DLL, Windows usa el orden de b煤squeda de DLL predeterminado que se muestra arriba. La primera posici贸n en el orden de b煤squeda de DLL (el directorio desde el que se carga la aplicaci贸n) es de inter茅s para los atacantes.
Si el desarrollador de la aplicaci贸n tiene la intenci贸n de cargar la DLL desde
C:\Windows\System32
, pero no lo escribi贸 expl铆citamente en la aplicaci贸n, la DLL maliciosa ubicada en el directorio de la aplicaci贸n se cargar谩 antes que la DLL leg铆tima de System32. La carga de una DLL maliciosa se denomina suplantaci贸n de DLL (o interceptaci贸n) y los atacantes la utilizan para cargar c贸digo malicioso en aplicaciones confiables / firmadas.
Uso de la suplantaci贸n de identidad de DLL para lograr resiliencia
La suplantaci贸n de DLL se puede utilizar para lograr resistencia cuando se inicia una aplicaci贸n / servicio vulnerable y una DLL maliciosa se coloca en una ubicaci贸n vulnerable. Un colega m铆o
@Airzero24
descubri贸 la suplantaci贸n de DLL en Microsoft OneDrive, Microsoft Teams y Slack como userenv.dll
.
Fueron estos programas los que se convirtieron en el objetivo de la interceptaci贸n, porque de forma predeterminada est谩n configurados para iniciarse al inicio de Windows. Esto se puede ver a continuaci贸n en el Administrador de tareas:
Aplicaciones de Windows configuradas para inicio autom谩tico
Para probar la suplantaci贸n de DLL, cre茅 un cargador de shellcode DLL que inici贸 Cobalt Strike Beacon. Cambi茅 el nombre de la DLL maliciosa
userenv.dll
y la copi茅 en el directorio de la aplicaci贸n afectada. Abr铆 la aplicaci贸n y vi mi nueva devoluci贸n de llamada de Beacon.
Baliza de impacto de cobalto a trav茅s de la intercepci贸n de DLL
usandoProcess Explorer , puedo verificar si mi DLL malicioso fue realmente cargado por una aplicaci贸n vulnerable.
Explorador de procesos que muestra la DLL maliciosa cargada
Detecci贸n autom谩tica del potencial de interceptaci贸n de DLL
Despu茅s de confirmar el secuestro de DLL previamente conocido, quer铆a ver si pod铆a encontrar otras capacidades de suplantaci贸n de DLL que pudieran explotarse.
El c贸digo utilizado en mi pago se puede encontrar aqu铆 .
Usando Slack como ejemplo
Para iniciar este proceso, ejecut茅 Process Monitor (ProcMon) con los siguientes filtros:
- Nombre del proceso -
slack.exe
- El resultado contiene
NOT FOUND
- El camino termina con
.dll
.
Encuentre archivos DLL que faltan en ProcMon.
Luego, inici茅 Slack y examin茅 ProcMon en busca de cualquier DLL que Slack estuviera buscando pero no pudiera encontrar.
Posibles rutas de interceptaci贸n de DLL descubiertas por ProcMon Export茅
estos datos de ProcMon como un archivo CSV para facilitar el an谩lisis en PowerShell.
Con mi DLL de cargador de shellcode actual, no pude averiguar f谩cilmente los nombres de DLL que Slack carg贸 con 茅xito. Cre茅 una nueva DLL, que se usa
GetModuleHandleEx
, y GetModuleFileName
para determinar el nombre de la DLL cargada y escribirla en un archivo de texto .
Mi siguiente objetivo era analizar el archivo CSV en busca de rutas DLL en la lista, ver esa lista, copiar mi DLL de prueba en la ruta especificada, iniciar el proceso de destino, detener el proceso de destino y eliminar la DLL de prueba. Si la DLL de prueba se carg贸 correctamente, escribir谩 su nombre en el archivo resultante.
Cuando finalice este proceso, tendr茅 una lista de posibles secuestros de DLL (espero) escrita en un archivo de texto.
Toda la magia en mi proyecto DLLHijackTest se realiza mediante un script de PowerShell . Acepta la ruta al archivo CSV generado por ProcMon, la ruta a su DLL malicioso, la ruta al proceso que desea ejecutar y cualquier argumento que desee pasar al proceso.
Par谩metros de
Get-PotentialDLLHijack Get-PotentialDLLHijack.ps1
Despu茅s de unos minutos, verifico el archivo de texto que aparece en mi DLL "malicioso" en busca de posibles secuestros de DLL. Encontr茅 las siguientes posibles rutas de interceptaci贸n para Slack:
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\slack\slack.exe"
C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL
Usando Microsoft Teams como ejemplo
Realizamos de nuevo el proceso descrito anteriormente:
- Utilice ProcMon para identificar posibles rutas de interceptaci贸n de DLL, exporte estos datos como un archivo CSV.
- Determine la ruta para iniciar el proceso.
- Defina los argumentos que desee pasar al proceso.
- Ejecutar
Get-PotentialDLLHijack.ps1
con argumentos apropiados.
Encontr茅 las siguientes posibles rutas de interceptaci贸n para Microsoft Teams:
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Microsoft\Teams\Update.exe" -ProcessArguments '--processStart "Teams.exe"'
C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll
Nota : Tuve que hacer peque帽os cambios en el script de PowerShell para completarTeams.exe
, ya que mi script est谩 intentando terminar el proceso que estaba intentando iniciar, en este caso esUpdate.exe
.
Usando Visual Studio Code como ejemplo
Al repetir el proceso anterior, encontr茅 las siguientes posibles rutas de interceptaci贸n para Visual Studio Code:
PS C:Users\John\Desktop> Get-PotentialDLLHijack -CSVPath .\Logfile.CSV -MaliciousDLLPath .\DLLHijackTest.dll -ProcessPath "C:\Users\John\AppData\Local\Programs\Microsoft VS Code\Code.exe"
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll
Compartir archivos DLL
Not茅 que Slack, Microsoft Teams y Visual Studio Code comparten las siguientes DLL:
WINSTA.dll
LINKINFO.dll
ntshrui.dll
srvcli.dll
cscapi.dll
Encontr茅 esto interesante y quer铆a entender qu茅 causa este comportamiento.
Metodolog铆a: comprensi贸n de las formas de interceptar archivos DLL compartidos
Vi pila cuando Tracy Una mala tratado de carga
WINSTA.dll
, LINKINFO.dll
, ntshrui.dll
, srvcli.dll
y cscapi.dll
.
DLL con carga diferida
me di cuenta de las similitudes en la pila al cargar Tracy
WINSTA.dll
, LINKINFO.dll
, ntshrui.dll
y srvcli.dll
.
Seguimiento de pila cuando Code.exe intenta cargar
WINSTA.dll
un seguimiento de pila al
Teams.exe
intentar cargar LINKINFO.dll
,
seguimiento de pila cuando Slack intenta cargar
ntshrui.dll
un seguimiento de pila contiene constantemente una llamada
_tailMerge_<
dllname>_dll
, delayLoadHelper2
seguido LdrResolveDelayLoadedAPI
. Este comportamiento fue el mismo para las tres aplicaciones.
He determinado que este comportamiento est谩 relacionado con la carga lenta de DLL . Desde la pila de seguimiento en el arranque
WINSTA.dll
Pude ver que el m贸dulo responsable de esta carga diferida era wtsapi32.dll
.
Abr铆
wtsapi32.dll
en Ghidra y us茅 Search -> For Strings -> Filter: WINSTA.dll
. Haga doble clic en la l铆nea encontrada y lo llevar谩 a su ubicaci贸n en la memoria.
La l铆nea "
WINSTA.dll
" enwtsapi32.dll
Haciendo clic derecho en una ubicaci贸n en la memoria, podemos encontrar cualquier referencia a esta direcci贸n.
Enlaces a
WINSTA.dll
Siguiendo los enlaces, podemos ver que la cadena
WINSTA.dll
se pasa a una estructura llamada ImgDelayDescr
. Al mirar la documentaci贸n de esta estructura, podemos confirmar que est谩 relacionada con DLL de carga diferida.
typedef struct ImgDelayDescr {
DWORD grAttrs; //
RVA rvaDLLName; // RVA dll
RVA rvaHmod; // RVA
RVA rvaIAT; // RVA IAT
RVA rvaINT; // RVA INT
RVA rvaBoundIAT; // RVA IAT
RVA rvaUnloadIAT; // RVA IAT
DWORD dwTimeStamp; // 0, ,
// O.W. / DLL, (Old BIND)
} ImgDelayDescr, * PImgDelayDescr;
Esta estructura se puede pasar a
__delayLoadHelper2
, que utilizar谩 LoadLibrary
/ GetProcAddress
para cargar la DLL especificada y fijar la direcci贸n de la funci贸n importada en la tabla de direcciones de importaci贸n de carga diferida (IAT).
FARPROC WINAPI __delayLoadHelper2(
PCImgDelayDescr pidd, // ImgDelayDescr
FARPROC * ppfnIATEntry // IAT
);
Al encontrar otras referencias a nuestra estructura
ImgDelayDescr
, podemos encontrar una llamada __delayLoadHelper2
que luego llama ResolveDelayLoadedAPI
. He cambiado el nombre de la funci贸n, los tipos y las variables para que sea m谩s f谩cil de entender.
__delayLoadHelper2
y ResolveDelayLoadedAPI
en Ghidra
隆Excelente! Esto es consistente con lo que vimos en nuestro seguimiento de pila de ProcMon cuando Slack intent贸 cargar
WINSTA.dll
.
__delayLoadHelper2
y ResolveDelayLoadedAPI
en ProcMon.
Este comportamiento fue uniforme para
WINSTA.dll
, LINKINFO.dll
, ntshrui.dll
y srvcli.dll
. La principal diferencia entre cada DLL de carga diferida era la DLL "principal". En las tres aplicaciones:
wtsapi32.dll
diferido cargadoWINSTA.dll
shell32.dll
vago cargadoLINKINFO.dll
LINKINFO.dll
diferido cargadontshrui.dll
ntshrui.dll
diferido cargadosrvcli.dll
驴Notaste algo interesante? Parece que
shell32.dll
descarga LINKINFO.dll
, que descarga ntshrui.dll
, que finalmente descarga srvcli.dll
. Esto nos lleva a nuestra 煤ltima opci贸n potencial com煤n DLL spoofing - cscapi.dll
.
Sustituci贸n de DLL en NetShareGetInfo y NetShareEnum
Segu铆 el seguimiento de la pila cuando Slack intent贸 cargar
cscapi.dll
y vi una llamada LoadLibraryExW
que aparentemente proven铆a de srvcli.dll
.
Abr铆 el
seguimiento de
cscapi.dll
la pila al arrancar
srvcli.dll
en Ghidra y us茅 Search -> For Strings -> Filter: cscapi.dll
. Hacer doble clic en la l铆nea encontrada y seguir los enlaces conduce a la LoadLibrary
llamada esperada .
srvcli.dll
llama a LoadLibrary paracscapi.dll
cambiar el nombre de la funci贸n que contiene la llamada
LoadLibrary
y siguiendo los enlaces, obtuve dos lugares donde se usa la funci贸n:
Descargas de NetShareEnum
cscapi.dll Descargas de NetShareGetInfo
cscapi.dll
Verifiqu茅 esto con programas PoC que llamaron
NetShareEnum
y NetShareGetInfo
:
NetShareEnum.exe
descargas cscapi.dll
NetShareGetInfo.exe
descargascscapi.dll
resultados
Las siguientes rutas de suplantaci贸n de DLL est谩n disponibles en Slack:
C:\Users\John\AppData\Local\slack\app-4.6.0\WINSTA.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\LINKINFO.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\ntshrui.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\srvcli.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\cscapi.dll
C:\Users\John\AppData\Local\slack\app-4.6.0\KBDUS.DLL
Las siguientes rutas de suplantaci贸n de DLL est谩n disponibles en Microsoft Teams:
C:\Users\John\AppData\Local\Microsoft\Teams\current\WINSTA.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\LINKINFO.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\ntshrui.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\srvcli.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\cscapi.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\WindowsCodecs.dll
C:\Users\John\AppData\Local\Microsoft\Teams\current\TextInputFramework.dll
Las siguientes rutas de suplantaci贸n de DLL est谩n disponibles en Visual Studio Code:
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\WINSTA.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\LINKINFO.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\ntshrui.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\srvcli.dll
C:\Users\John\AppData\Local\Programs\Microsoft VS Code\cscapi.dll
Adem谩s, descubr铆 que los programas que usan
NetShareEnum
y NetShareGetInfo
brindan la capacidad de reemplazar archivos DLL en el formulario cscapi.dll
debido a la llamada codificada LoadLibrary
. He verificado este comportamiento con Ghidra y PoC.
Conclusi贸n
Como recordatorio, la interceptaci贸n de DLL es un m茅todo mediante el cual los atacantes pueden interferir con la ejecuci贸n del c贸digo en aplicaciones firmadas / confiables. He creado herramientas para ayudar a automatizar la detecci贸n de rutas de interceptaci贸n de DLL. Con esta herramienta descubr铆 las rutas de intercepci贸n de DLL en Slack, Microsoft Teams y Visual Studio Code.
Not茅 que las rutas de interceptaci贸n de DLL de estas tres aplicaciones se superponen e investigu茅 la causa. Destaqu茅 mi m茅todo para entender esta coincidencia. Aprend铆 acerca de las DLL de carga diferida y descubr铆 dos llamadas a la API que hacen posible interceptar las DLL en cualquier programa que las llame:
NetShareEnum
cargascscapi.dll
NetShareGetInfo
cargascscapi.dll
Gracias por tomarse el tiempo de leer este art铆culo, espero que haya aprendido un par de cosas sobre la API de Windows, Ghidra, ProcMon, DLL y la intercepci贸n de DLL.
Enlaces
隆Un gran saludo a mis colegas Daniel Heinsen (
@hotnops
), Lee Christensen ( @tifkin_
) y Matt Hand ( @matterpreter
) por ayudar con Ghidra / ProcMon!
Comprobaci贸n de PoC p煤blicas para su uso en pentesting