Nulling
Iniciemos analizando la ACL
que guarda los privilegios, el proceso que utilizaremos para el shellcode es winlogon.exe
, este no tiene un pid fijo pero es un proceso que siempre tendrá privilegios administrativos, con !object
podemos obtener el Header
0: kd> !process 0 0 winlogon.exe
PROCESS ffffe20d3e19c080
SessionId: 1 Cid: 0254 Peb: f901e13000 ParentCid: 01fc
DirBase: 10bbbf000 ObjectTable: ffff9e8c274a0b00 HandleCount: 281.
Image: winlogon.exe
0: kd> !object 0xffffe20d3e19c080
Object: ffffe20d3e19c080 Type: (ffffe20d3acb17a0) Process
ObjectHeader: ffffe20d3e19c050 (new version)
HandleCount: 15 PointerCount: 458230
La estructura _OBJECT_HEADER
de cada proceso contiene un atributo interesante llamado SecurityDescriptor
en el offset 0x28
, este atributo contiene la ACL
del objeto y esta define quien puede acceder al objeto y con que permisos
0: kd> dt nt!_OBJECT_HEADER 0xffffe20d3e19c050
+0x000 PointerCount : 0n458230
+0x008 HandleCount : 0n15
+0x008 NextToFree : 0x00000000`0000000f Void
+0x010 Lock : _EX_PUSH_LOCK
+0x018 TypeIndex : 0xde ''
+0x019 TraceFlags : 0 ''
+0x019 DbgRefTrace : 0y0
+0x019 DbgTracePermanent : 0y0
+0x01a InfoMask : 0x88 ''
+0x01b Flags : 0 ''
+0x01b NewObject : 0y0
+0x01b KernelObject : 0y0
+0x01b KernelOnlyAccess : 0y0
+0x01b ExclusiveObject : 0y0
+0x01b PermanentObject : 0y0
+0x01b DefaultSecurityQuota : 0y0
+0x01b SingleHandleEntry : 0y0
+0x01b DeletedInline : 0y0
+0x01c Reserved : 0x8930eb74
+0x020 ObjectCreateInfo : 0xfffff800`6ae53a40 _OBJECT_CREATE_INFORMATION
+0x020 QuotaBlockCharged : 0xfffff800`6ae53a40 Void
+0x028 SecurityDescriptor : 0xffff9e8c`1fa47e2d Void
+0x030 Body : _QUAD
En explotaciones realizadas en versiones antiguas de Windows 10
simplemente podiamos anular el SecurityDescriptor
, como resultado si mirabamos con Process Explorer los permisos de un proceso se podia ver de esta forma y al no estar asignado a nadie cualquier usuario tenia Full Control
sobre él, sin embargo esto cambió para versiones mas nuevas como explica la siguiente investigación de nettitude
Si en una versión actual de Windows
anulamos el SecurityDescriptor
el resultado es un BSOD
de tipo BAD_OBJECT_HEADER diciendo que tiene un valor inválido
0: kd> eq 0xffffe20d3e19c050 + 0x28 0
0: kd> g
KDTARGET: Refreshing KD connection
*** Fatal System Error: 0x00000189 (0xFFFFE20D3E19C050,0xFFFFE20D416127F0,0x0000000000000001,0x0000000000000000)
Break instruction exception - code 80000003 (first chance)
A fatal system error has occurred.
Debugger entered on first try; Bugcheck callbacks have not been invoked.
A fatal system error has occurred.
nt!DbgBreakPointWithStatus:
fffff803`2a6077a0 cc int 3
0: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
BAD_OBJECT_HEADER (189)
The OBJECT_HEADER has been corrupted
Arguments:
Arg1: ffffe20d3e19c050, Pointer to bad OBJECT_HEADER
Arg2: ffffe20d416127f0, Pointer to the resulting OBJECT_TYPE based on the TypeIndex in the OBJECT_HEADER
Arg3: 0000000000000001, The object security descriptor is invalid.
Arg4: 0000000000000000, Reserved.
Lo único que nos queda es buscar una forma de asignar privilegios Full Control
sin anularlo, para ello tendremos que entender como funciona el SecurityDescriptor
, lo interesante de la estructura _SECURITY_DESCRIPTOR
es el atributo Dacl
que es una estructura _ACL
que especifica el acceso que tienen los usuarios al objeto
0: kd> dt nt!_SECURITY_DESCRIPTOR
+0x000 Revision : UChar
+0x001 Sbz1 : UChar
+0x002 Control : Uint2B
+0x008 Owner : Ptr64 Void
+0x010 Group : Ptr64 Void
+0x018 Sacl : Ptr64 _ACL
+0x020 Dacl : Ptr64 _ACL
0: kd> dt nt!_ACL
+0x000 AclRevision : UChar
+0x001 Sbz1 : UChar
+0x002 AclSize : Uint2B
+0x004 AceCount : Uint2B
+0x006 Sbz2 : Uint2B
Según documentación en realidad el objeto _ACL
solo es un Header
y el contenido real se encuentra en sus entradas, para una Dacl
hay 2 tipos de ACE
, estos son ACCESS_ALLOWED_ACE
y ACCESS_DENIED_ACE
, nos interesa el primero que indica que derechos tiene un SID
a través del atributo ACCESS_MASK
typedef struct _ACCESS_ALLOWED_ACE {
ACE_HEADER Header;
ACCESS_MASK Mask;
DWORD SidStart;
} ACCESS_ALLOWED_ACE;
Utilizando el comando !sd
podemos pasarle un puntero al SecurityDescriptor
antes limpiando el último byte y obtener información de este, este nos muestra detalladamente que usuarios tienen que privilegios, el AceCount
de la DACL
es 2
lo que significa que contiene 2 ACE
y ambos son de tipo ACCESS_ALLOWED_ACE
, uno es para nt authority\system
y el otro para el grupo builtin\administradores
0: kd> !sd (0xffff9e8c1fa47e2d & 0xfffffffffffffff0) 1
->Revision: 0x1
->Sbz1 : 0x0
->Control : 0x8814
SE_DACL_PRESENT
SE_SACL_PRESENT
SE_SACL_AUTO_INHERITED
SE_SELF_RELATIVE
->Owner : S-1-5-32-544 (Alias: BUILTIN\Administradores)
->Group : S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
->Dacl :
->Dacl : ->AclRevision: 0x2
->Dacl : ->Sbz1 : 0x0
->Dacl : ->AclSize : 0x3c
->Dacl : ->AceCount : 0x2
->Dacl : ->Sbz2 : 0x0
->Dacl : ->Ace[0]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[0]: ->AceFlags: 0x0
->Dacl : ->Ace[0]: ->AceSize: 0x14
->Dacl : ->Ace[0]: ->Mask : 0x001fffff
->Dacl : ->Ace[0]: ->SID: S-1-5-18 (Well Known Group: NT AUTHORITY\SYSTEM)
->Dacl : ->Ace[1]: ->AceType: ACCESS_ALLOWED_ACE_TYPE
->Dacl : ->Ace[1]: ->AceFlags: 0x0
->Dacl : ->Ace[1]: ->AceSize: 0x18
->Dacl : ->Ace[1]: ->Mask : 0x00121411
->Dacl : ->Ace[1]: ->SID: S-1-5-32-544 (Alias: BUILTIN\Administradores)
->Sacl :
->Sacl : ->AclRevision: 0x2
->Sacl : ->Sbz1 : 0x0
->Sacl : ->AclSize : 0x1c
->Sacl : ->AceCount : 0x1
->Sacl : ->Sbz2 : 0x0
->Sacl : ->Ace[0]: ->AceType: SYSTEM_MANDATORY_LABEL_ACE_TYPE
->Sacl : ->Ace[0]: ->AceFlags: 0x0
->Sacl : ->Ace[0]: ->AceSize: 0x14
->Sacl : ->Ace[0]: ->Mask : 0x00000003
->Sacl : ->Ace[0]: ->SID: S-1-16-16384 (Label: Etiqueta obligatoria\Nivel obligatorio del sistema)
Esto podemos verlo graficamente desde Process Explorer donde nt authority\system
tiene privilegios Full Control
, la forma que usaremos para tener este acceso será modificar el SID
de SYSTEM
para asignar estos privilegios a otro grupo con menos privilegios con el que podamos acceder por ejemplo Usuarios autenticados