lunes, 10 de noviembre de 2008

Panda Internet Security/Antivirus+Firewall 2008 CPoint.sys Memory Corruption Vulnerability

Hola!,

Nuevamente vamos a hablar de una vuln que salio hace tiempo:

http://www.securityfocus.com/bid/28150

Es otra vez una falla trivial por falta de chequeos en los datos
que se pasan desde user-mode a kernel-mode.

En este caso se trata de una vulnerabilidad en cpoit.sys que es
usado por Panda Firewall + AntiVirus 2008.

En este caso la falla permite dejarnos inutilizada la maquina mediante un BSoD o bien,
si la explotacion es exitosa, conseguir privilegios de SYSTEM.

Como ya contamos con algo de informacion publica, desensamblaremos
el driver (cpoint.sys) con IDA. Lo primero que haremos sera buscar el
IOCTL Manager:

mov eax, offset sub_10B24
mov [ebx+70h], eax
mov [ebx+74h], eax

No tardamos mucho tiempo en encontrarlo :P

Sabemos de antemano que el IOCTL vulnerable es 0xba002848, entonces
busquemos donde es que se despacha ese IOCTL.

Lo primero que vemos es como comienza comparando el valor de ECX
(nuestro IOCTL) con diferentes valores (el resto de los IOCTL's):

mov edi, [ebx+60h]
mov ecx, [edi+0Ch]
cmp ecx, 0BA00283Ch
jz loc_10D1B

Se fija si nuestro IOCTL es igual a 0BA00283Ch, como no es igual, seguiremos
por esta parte:

cmp ecx, 0BA002840h
jz loc_10C7D

Como nuestro IOCTL tampoco es igual a 0BA002840h, llegaremos a esta otra parte:

cmp ecx, 0BA002844h
jz short loc_10B93

Nuevamente, la comparacion resultara falsa y terminaremos llegando a este basic block:

mov eax, [ebx+0Ch]
lea edx, [ebp+var_4]
push edx
push dword ptr [edi+4]
push eax
push dword ptr [edi+8]
push eax
push ecx
call sub_12254
mov edi, eax
jmp loc_10CFF

Como vemos, hay un call a sub_12254, vemamos que hay dentro de esa funcion:

mov edi, edi
push ebp
mov ebp, esp
mov ecx, [ebp+IOCTL]
push ebx
mov edx, 0BA002828h
cmp ecx, edx
push esi
push edi
mov eax, 0C000000Dh
ja loc_12633

Nuevamente, sigue comparando IOCTL's, ECX contiene nuestro IOCTL.
Como nuestro IOCTL es mayor que 0BA002828h, continuaremos por esta parte:

loc_12633:
mov edx, 0BA002848h
cmp ecx, edx
ja loc_12946

Aqui si estamos en el lugar correcto, primero compara nuestro IOCTL con 0BA002848h, y como
ECX no es mayor sino igual a 0BA002848h, entonces continuaremos por aqui:

jz loc_128BE

Aqui compara si es igual, lo cual es verdadero y entonces llegamos aqui:

loc_128BE:
cmp [ebp+IN_BUFFER_SIZE], 1008h
jb loc_12A7D

Aqui comprueba si el tamaño del buffer de entrada es menor a 0x1008; en caso de
que sea mayor, llegamos a esta parte:

mov esi, [ebp+IN_BUFFER_DATA]
cmp dword ptr [esi], 3F256B9Ah
jnz loc_12A7D

Aqui, saca datos de nuestro buffer y compara con una constante (3F256B9Ah), o sea que
en nuestro buffer tenemos que pasarle esa constante para poder llegar a la zona vulnerable:

mov ebx, offset dword_1335C
mov ecx, ebx ; SpinLock
call ds:KfAcquireSpinLock
mov byte_13360, al
mov eax, [esi+10Ch]
mov dword_134A4, eax
mov eax, [esi+8]
mov dword_133A0, eax
xor eax, eax
cmp [esi+8], eax
jbe short loc_1291B

En la ultima parte de este basic block, tenemos un check mas, en el cual pone EAX a 0 y comprueba
que nuestro in_buffer+8 tenga 0.

Luego de pasar ese check, llegamos aqui:

lea ecx, [esi+0Ch]

Aqui saca data de nuestro IN_BUFFER+0Ch y lo pone en ECX.

Esta es la parte del codigo vulnerable:

loc_12909:
mov edx, [ecx]
mov dword_133A4[eax*4], edx
inc eax
add ecx, 4
cmp eax, [esi+8]
jb short loc_12909

Mueve a EDX el contenido de nuestra data y lo escribe en una zona de la memoria del driver dword_133A4.
Luego, incrementa EAX, le suma 4 a nuestro IN_BUFFER y compara EAX (contador del loop) con ESI+8 que controlamos
nosotros, o sea que controlamos el loop y podemos hacer que escriba tantas veces como queramos en esa zona
de memoria del driver.

Vale aclarar que un poco mas abajo, pasando este primer loop, tenemos una una zona muy similar a esta en la cual
hay otro loop que tambien escribe en otra zona del driver.

Si nos fijamos, la zona de memoria en la cual podemos escribir se trata de la seccion .data del driver
y mirando un poco esa seccion, nos encontramos con que hay cosas interesantes para pisar con nuestra
data:

.data:00013630 ; struct _KEVENT Event
.data:00013630 Event _KEVENT <0> ; DATA XREF: sub_107D2+1E9o
.data:00013630 ; sub_10A46+97o
.data:00013640 ; struct _KEVENT stru_13640
.data:00013640 stru_13640 _KEVENT <0> ; DATA XREF: sub_107D2+1F4o
.data:00013640 ; IOCTL_Manager+F8o ...
.data:00013650 unk_13650 db 0 ; DATA XREF: sub_107D2+203o
.data:00013650 ; IOCTL_Manager+1AEo

Un poco mas abajo de donde comienza a copiar, tenemos una structura KEVENT que podriamos pisar
cuidadosamente para lograr ejecutar codigo. No es facil pero es una posibilidad interesante.

Yo he programado un plugin para Kartoffel que trigerea esta vulnerabilidad. Si alguien tiene ganas
y programa un exploit funcional y quiere compartirlo pues lo invito a que lo haga.

Panda cpoint.sys PoC:

http://www.4shared.com/file/70535874/3db3935b/panda_plugin.html

Tambie pueden descargar el plugin desde la misma web de kartoffel:

http://kartoffel.reversemode.com/downloads/panda_plugin.zip

Aqui les dejo la estructuta KEVENT:

kd> dt_KEVENT
ntdll!_KEVENT
+0x000 Header : _DISPATCHER_HEADER
kd> dt_DISPATCHER_HEADER
ntdll!_DISPATCHER_HEADER
+0x000 Type : UChar
+0x001 Absolute : UChar
+0x002 Size : UChar
+0x003 Inserted : UChar
+0x004 SignalState : Int4B
+0x008 WaitListHead : _LIST_ENTRY
kd> dt_LIST_ENTRY
ntdll!_LIST_ENTRY
+0x000 Flink : Ptr32 _LIST_ENTRY
+0x004 Blink : Ptr32 _LIST_ENTRY

Para el que quiero informacion adicional:

http://www.trapkit.de/advisories/TKADV2008-001.txt

Bueno por ahora es todo.

Saludos.

No hay comentarios: