Random IRC quote :      <ggonzalez> yo soy muy sociable, solo que no me gusta la gente

Marchando una de exploits

Con permiso de «Bixito Guapo» voy a seguir escribiendo entradas en el blog.

Bueno, Symantec acaba de publicar los parches y el advisory para una serie de fallos en diferentes Drivers de su motor antivirus que descubrí hace apenas un mes. Se han dado prisa, creo que son los que menos han tardado en reparar una vulnerabilidad (de las que he encontrado quiere decir) hasta ahora. Hombre, teniendo en cuenta que absolútamente todos los productos de Symantec para plataformas Microsoft están afectados, pues parece lógico que se dieran maña.

He decidido hacer públicos los exploits para demostrar que cualquier sobrescritura de memoria kernel puede ser explotada con éxito, no hace falta controlar los valores. La verdad es que este caso de Symantec me ha venido de puta madre para ilustrar las técnicas.
Para valores altos(punteros dentro del driver o cosas así), el método que he usado es sobrescribir MmUserProbeAddress, de esta manera ProbeForWrite se extiende hasta el valor que le hayamos pasado. Luego puedes usar el IOCTL que te de la gana de entre los muchos que te permiten personalizar valores, para sobrescribir ya valores controlados. Para ilustrar este método he usado el mrxsmb.sys que me permite generar valores usando la técnica de «ZwCreateFile – NULL» explicada en el paper que publiqué sobre este driver. Como Microsoft parcheó los permisos, pues para ejecutar los exploits necesitaréis privilegios de admin, pero vamos que es para ilustrar la base del método.

Hay 4 exploits disponibles para este método:

exploit 1

exploit 2

exploit 3

exploit 4

Para valores pequeños, he usado la técnica de sobrescribir la dirección a la tabla de funciones de NtQuerySystemInformation dentro del Kernel. En los exploits lo veréis más en detalle. Para este exploit no hacen falta privilegios especiales.

Para este método hay 2 exploits disponibles.

exploit 1

exploit 2

El advisory y esas cosas lo podéis encontrar donde siempre: www.reversemode.com

Un saludo!

9 Comentarios para “Marchando una de exploits”

  1. Comment por mballano | 10/06/06 at 1:48 am

    Ph3ar rú!!!!, (con pemiso de bixoraro por usar un 3 en vez de una E)…. muy bueno, te lo has currado mucho!!!

  2. Comment por nose | 10/06/06 at 9:07 am

    Pobre chinita que se ha quedado indefensa frente al malware.
    😛

  3. TKM
    Comment por TKM | 10/06/06 at 9:39 am

    He mirado un poco el codigo de uno de los exploits y no entiendo muy bien como funciona. No tengo posibilidad de depurarlo y me cuesta ver donde esta el quid de la question. ¿Os importaria si intentamos comentar como funciona, por partes?

    dwIOCTL = 0x222AD7;

    DeviceIoControl(hDevice,
    dwIOCTL,
    (LPVOID)0,0,
    (LPVOID)OutBuff,OutSize,
    &junk,
    NULL);

    DeviceIoControl(hDevice,
    dwIOCTL,
    (LPVOID)0,0,
    (LPVOID)BaseNt,OutSize,
    &junk,
    NULL);
    mmUserProbe=OutBuff[0];

    Al llamar a una api nativa en NT, cuando se realiza el paso de ring3 a ring0, el stub que en modo nucleo se encarga de llamar a la funcion apropiada de la Services Descriptor Table valida primero que la direccion de memoria que se le pasa como puntero a los parametros pertenezca a modo usuario.

    Lo que no entiendo bien es si al enviarle esos IOCTLS al driver de Symantec el mismo cambia por algun motivo la direccion maxima de memoria (es un symbolo que exporta ntoskrnl si no recuerdo mal) que pertenece a modo usuario. No me refiere a que modifique la GDT ni la tabla de paginas, sino a si modifica el symbolo que exporta el ntoskrnl para realizar sus propias validaciones.

    ¿En esta primera parte, van por ahi los tiros o estoy disparando con una escopeta de feria con el punto de vista desviado?

  4. Comment por Ruben Santamarta | 10/06/06 at 11:17 am

    Vas bien encaminado.
    Mira te lo explico con más detalle, este código forma parte del driver de Symantec
    PAGE:0004B61A push 4
    PAGE:0004B61C pop esi
    PAGE:0004B61D sub edx, esi
    PAGE:0004B61F jnz short loc_4B653
    PAGE:0004B621 mov edx, [ecx+3Ch]
    PAGE:0004B624 test edx, edx
    PAGE:0004B626 jz short loc_4B653
    PAGE:0004B628 cmp [eax+4], esi
    PAGE:0004B62B jnz short loc_4B653
    PAGE:0004B62D mov dword ptr [edx], offset sub_4B71B < ==Fijate aqui! como ves está copiando a la dirección apuntada por edx un offset, ese offset una vez el driver está cargado en memoria habrá que sumarle la base donde se ha cargado, que obviamente siempre será mayor que cualquier dirección en user-mode y también mayor que la base de ntoskrnl. Es por ello que uso ese valor para sobrescribir MmUserProbeAddress, que es una variable interna de ntoskrnl que usa para validar que los usuarios no escriban fuera de sus límites(0x7FFF0000). Esta variable se usa en ProbeForWrite y ProbeForRead por ejemplo. Entonces edx apunta a esa variable, con lo que una vez el Driver de Symantec la sobrescriba pues el rango permitido para los usuarios se amplia hasta ese offset, imaginemos que es 0xE5C00000 por ejemplo. Entonces ya ProbeForWrite queda prácticamente anulada como medida de seguridad dentro de los Drivers, porque nos está permitiendo saltarnos la restricción de solo poder escribir en el rango de User-Mode. lkd> u ProbeForWrite L30
    nt!ProbeForWrite:
    80565540 8bff mov edi,edi
    80565542 55 push ebp
    80565543 8bec mov ebp,esp
    80565545 8b450c mov eax,[ebp+0xc]
    80565548 85c0 test eax,eax
    8056554a 743b jz nt!ProbeForWrite+0x55 (80565587)
    8056554c 8b4d10 mov ecx,[ebp+0x10]
    8056554f 56 push esi
    80565550 8b7508 mov esi,[ebp+0x8]
    80565553 49 dec ecx
    80565554 85ce test esi,ecx
    80565556 753a jnz nt!ProbeForWrite+0x4f (80565592)
    80565558 8d4406ff lea eax,[esi+eax-0x1]
    8056555c 3bf0 cmp esi,eax
    8056555e 772b ja nt!ProbeForWrite+0x48 (8056558b)
    80565560 3b0534ee5580 cmp eax,[nt!MmUserProbeAddress (8055ee34)] <<== Aqui esta la clave! Luego en la Stage 2 del exploit, uso un driver de Windows para generarme valores " a la carta" y modificar un salto relativa (ExRaiseStatus) para que apunte a la shellcode

  5. TKM
    Comment por TKM | 10/06/06 at 11:41 am

    Entonces, el primer codigo que pasteas es del DriverDispatch del driver de Symantec. Lo que sigo sin entender es lo siguiente: Al driver de Symantec tu le mandas dos IOCTLs que parecen mas que inofensivos, de hecho en ninguna de las dos llamadas envias un buffer de entrada, solo de salida. ¿Como es entonces que acaba sobreescribiendo la direccion de MmUserProbeAddress?

    Lo siento, a lo mejor esta claro y estoy siendo un poco torpe, pero no acabo de verlo.

  6. Comment por Ruben Santamarta | 10/06/06 at 11:48 am

    Sí, es parte de la rutina de dispatch del Driver.
    Al driver sólo le mando un IOCTL, la primera llamada en el exploit a DeviceIoControl es símplemente para obtener el valor con el que se sobrescribirá MmUserProbeAddress y mostrarlo en la información que saca el exploit, la segunda llamada ya es la que uso para sobrescribir MmUserProbeAddress.

    No le mando buffer de entrada porque no lo necesita, en edx está la dirección del buffer de salida, que es lo que nosotros controlamos, por lo tando OutBufferAddress=edx=&MmUserProbeAddress.

    PAGE:0004B62D mov dword ptr [edx], offset sub_4B71B <==Fijate aqui!

  7. TKM
    Comment por TKM | 10/06/06 at 12:15 pm

    Juas, ¿que extraño que la propia funcion DeviceIoControl no valide eso, ¿no? Un driver puede enviar IOCTLS a otro driver y por tanto es valido que al DriverDispatch le llegue una buffer de salida que apunte a memoria en modo nucleo, pero cuando enviamos un IOCTL de un driver a otro no lo hacemos a traves de DeviceIoControl, asi que entiendo que la propia funcion podria validarlo…

    En fins, windows podria ser mas seguro, pero de todos modos es un pecado muy gordo por parte de una de las empresas mas reconocidas del mercado de la seguridad tener un fallo asi. ¿Quien sera la siguiente?

  8. Comment por Ruben Santamarta | 10/06/06 at 12:45 pm

    DeviceIoControl no debe validar ese tipo de información. En ese sentido Windows lo hace bien. Está suficientemente documentado por Microsoft cómo se deben manejar los distintos métodos usados en las IRPs, esa responsabilidad para el METHOD_NEITHER, recae sobre el propio driver no sobre el IO Manager.
    Lo de los Drivers es la jungla, he visto cada cosa…Tiempo al tiempo.

  9. TKM
    Comment por TKM | 10/06/06 at 1:35 pm

    Otra cosa que todo o casi todo el mundo deja con el culo al aire es el tema de los privilegios de los usuarios a la hora de enviar IOCTLs. Es decir, ¿esta el usuario Fulanito autorizado a enviarme este IOCTL?.

Se han cerrado los comentarios