Random IRC quote :      <ggonzalez> había 400 personass lo menos <@madalenasbuenas> en el metro <ggonzalez> les hubiera prendido fuego a todos

METHOD_NEITHER: Automatizando la búsqueda de vulnerabilidades

 Aunque nunca antes había centrado mi atención en el tema de las vulnerabilidades y pese a estar un poco apartado ya del low-level y los temas relacionados con la seguridad (mi única relación hoy en día es a traves de este blog) hace un tiempo me llamó la atención ese tipo de vulnerabilidades que parecían tener un montón de drivers por la mala gestión de IOCTLs con METHOD_NEITHER. Al corresponderse estas vulnerabilidades con un tipo de comportamiento muy especifico, se me ocurrió que podía ser relativamente sencillo automatizar la búsqueda de estos fallos evitando tener que pasar horas desensamblando codigo. Eso sí, sería necesario pasar algunas horas (tiempo, bendito tesoro) codeando una utilidad que hiciese el trabajo por nosotros. El resultado de poner la idea en practica es la pequeña utilidad que os presento a continuación.  No es gran cosa, pero simplemente funciona (Everything should be made as simple as possible, but no simpler).

¿En que consiste la idea?
Es simple. Se trata de filtrar el envio de IOCTLS que se realicen en el sistema y de aquellos que empleen METHODE_NEITHER sustituir la dirección del buffer de salida por una dirección en ring0, de modo que si el buffer en esa nueva dirección es escrito, habremos identificado un driver vulnerable.

¿Como lo ponemos en practica?
Dedicandole unas horas en las noche de mis vacaciones y otros dos días sin poder ir a trabajar por culpa de una plaga de gastroenteritis.

Ahora en serio. Como siempre, será posible hacerlo de varias formas, a continuación os explico brevemente la vía por la que optó servidor:

El primer paso es identificar un lugar donde capturar las operaciones que se estan enviando en el sistema. El lugar escojido en este caso es la función «NTDeviceIoControlFile» que reside en «ntoskrnl.exe». Cada vez que alguien llama a la función «DeviceIoControl», el flujo pasa por «NTDeviceIoControlFile» y lo mismo sucede cuando un driver llama a «IoCallDriver«. Se trata por lo tanto de un lugar desde el que cubrimos la practica totalidad de operaciones que se realicen en el sistema. Además, al realizar el filtrado desde ring0, estaremos espiando a todos los procesos que corran en el mismo.

Una vez tomamos el control de «NTDeviceIoControlFile«, cada vez que se llame a esta función, recojeremos de la pila los parametros que recibe la misma, entre ellos el Io Control Code y el handle al device object destinatario de la operación. Comprobaremos si el IOCTL emplea METHOD_NEITHER. En caso afirmativo, obtendremos el nombre del device al que representa el handle e informaremos a traves de un pipe a un proceso en ring3 de los parametros que ha recibido «NTDeviceIoControlFile«, más el nombre del device object destinatario. Despues dejamos que la operación siga su curso, de modo que el sistema siga funcionando correctamente. Por cierto que a veces pienso en lo bonito que sería ser banquero y poder hacer estas cosas con dinero en lugar de bytes. Vocación equivocada supongo, que se le va a hacer.

Seguimos. En ring3 tendremos un proceso escuchando por el pipe a traves del cual nuestro driver envía los parametros de «NtDeviceIoControlFile«. También recibiremos el nombre del device object destinatario de la operación y por lo tanto podremos replicar la llamada que algun otro proceso le había hecho a «DeviceIoControl». Para replicar la llamada, haremos un «CreateFileW» sobre el nombre del device object para obtener un handle valido y obtendremos también a traves del pipe el Io Control Code de la operación. Con el handle y el Io Code llamaremos a «DeviceIoControl«. Logicamente, nuestro driver también capturará esta llamada, pero tras comprobar que el proceso que la realiza es nuestro proceso de ring3 realizará otras acciones diferentes a las que realiza cuando los demás procesos llaman a «DeviceIoControl«. Modificará en la pila la dirección del buffer de salida de la operación para que apunte a un buffer en ring0 (reservado por el driver) y modificará el valor de retorno en la pila por el de una función que también reside en nuestro driver para así tomar de nuevo el control despues de que la operación se haya procesado. Al retomar el control, lo único que le queda por hacer es copiar el contenido del buffer de salida de ring0 al buffer de salida original de ring3. Asi al retornar de la llamada a «DeviceIoControl«, nuestro proceso en ring3 podrá comprobar si el contenido de ese buffer se ha modificado e identificar así las operaciones vulnerables.

Pues bien, en realidad esto es todo. Pero el caso es que funciona. Y lo mejor de todo es que la utilidad no tiene ni GUI ni linea de comandos. Unicamente la he probado en XP. Y por supuesto, si vais a probarla y teneis medio dedo de frente, hacedlo en una VM. Y no digo que sereis incapaces de resistir la tentación de probarla, pero seguramente lo hagais x).

Bueno, en este .rar podeis encontrar los binarios y el código fuente, en enamblador para Masm.

Incluyo algunas librerias de Four-F y otras milenarias que creo recordar eran de Elicz. Cosas curiosas de la vida, a la utilidad en principio la bauticé como «Ioctlizer», pero un pavo publicó hace unos meses (creo que en rootkit.com) una utilidad con ese mismo nombre. Así que despues de días comiendome la cabeza, meditando, casi sin comer y pasando las noches en vela, vino a mi mente como una inspiración divina otro nombre que tampoco le viene mal: Ioctilizador. A tomar por culo.

El driver «hookIoctlizer.sys», hay que copiarlo a mano en «System32/drivers/». El Ioctlizador.exe, se puede lanzar desde el OllyDbg. Tiene metida una «int 3» despues de la comprobación del buffer de salida, de modo que si el mismo ha sido modificado, el Olly se detendrá. Podremos ver en «esi» el nombre del objeto y en «edi» el Io Control Code. Para poder hacer pruebas creé otra utilidad con su propio driver que emplea METHOD_NEITHER y escribe en el buffer de salida sin validar que sea un buffer en ring3. Son el «test.exe» y el «dummy.sys», que también hay que copiar a mano en «System32/drivers/». Asi que si teneis corriendo el Ioctlizador y ejecutais el test.exe, el Olly os debería parar y deberiais ser capaces de desarrollar un exploit (al menos un POC) en unos minutos ;-P.

Y bueno, como no he metido colorines ni nada en este post, al menos he inventado un trabalenguas para que veais que yo también me lo curro. Es muy original:

«El sistema esta ioctilizado, quien lo desioctilizara… el desioctilizador que lo desioctilice, buen desioctilizador será».

Aio!

12 Comentarios para “METHOD_NEITHER: Automatizando la búsqueda de vulnerabilidades”

  1. Comment por Jose Luis | 04/28/08 at 11:14 pm

    Lo estoy probando desde VirtualBox y funciona de maravilla, ¡gracias por crear esta herramienta!

  2. Comment por Ruben | 04/29/08 at 5:38 am

    «Así que despues de días comiendome la cabeza, meditando, casi sin comer y pasando las noches en vela, vino a mi mente como una inspiración divina otro nombre que tampoco le viene mal: Ioctilizador. A tomar por culo.» xDDDD la que mantienes!

    Mola el tema, te podías currar un plugin para el kartoffel 😛

  3. Comment por Mario Ballano | 04/29/08 at 8:50 am

    Muy bueno!!, pero a ver si dejas de usar ya el masm, que ya sabes que los masmeros no nos habéis caido nunca bien xDDD.

    NASM/FASM/TASM powah! 😉

    Un saludo,

    Mario

  4. Comment por Zohiartze Herce | 04/29/08 at 3:06 pm

    Buenooo, habló el señor Ballano… Que sepais todos que Don «los masmeros no nos habeis caido nunca bien» cuando ha dicho «NASM/FASM/TASM powah», en relidad quería decir: «Phyton powah!»

    ¡Ala, a jugar a pala! ¡Farsante! x)

  5. Comment por Mario Ballano | 04/29/08 at 6:41 pm

    jajaja, no te piques Zori 🙂

  6. Comment por David Reguera García | 04/30/08 at 4:38 pm

    Muy interesante, además en MASM32 🙂

  7. Comment por exceed | 04/30/08 at 10:43 pm

    ioctlizador crashes rdbss.sys on Windows XP SP3…

  8. Comment por Zohiartze Herce | 04/30/08 at 11:22 pm

    Ioctlizador shouldn’t make any driver crash. Anyway, without further information it’s impossible to research the reason. Could you send me the crash dump to «zohiartze [at] 48bits [dot] com»?

  9. Comment por exceed | 05/01/08 at 11:30 pm

    Well, it crashes also rdbss.sys on Window XP SP2, fully patched. Here are some details from minidump:

    —– START DUMP —–

    BAD_POOL_CALLER (c2)
    The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc.
    Arguments:
    Arg1: 00000007, Attempt to free pool which was already freed
    Arg2: 00000cd4, (reserved)
    Arg3: 00000000, Memory contents of the pool block
    Arg4: 823d9040, Address of the block of pool being deallocated

    Debugging Details:
    ——————

    POOL_ADDRESS: 823d9040

    FREED_POOL_TAG: ObjT

    BUGCHECK_STR: 0xc2_7_ObjT

    CUSTOMER_CRASH_COUNT: 1

    DEFAULT_BUCKET_ID: DRIVER_FAULT

    PROCESS_NAME: System

    LAST_CONTROL_TRANSFER: from 8054b941 to 8053354e

    STACK_TEXT:
    f898db28 8054b941 000000c2 00000007 00000cd4 nt!KeBugCheckEx+0x1b
    f898db78 f7d30a30 823d9040 00000000 f898dbd8 nt!ExFreePoolWithTag+0x2be
    f898db88 f7cf46a7 823d9040 f7cf472c 00000afa rdbss!_RxFreePool+0x10
    f898dbd8 f7cf4472 f898dc4c 00000001 823b6830 mrxsmb!SmbCePnpBindBrowser+0x19c
    f898dc30 f7cf3325 f898dc48 8231b658 81f65cc8 mrxsmb!MRxSmbpBindTransportCallback+0x152
    f898dc5c f884fc62 00000001 0000000a 81f51734 mrxsmb!MRxSmbPnPBindingHandler+0x11f
    f898dc80 f88502e8 f8851208 8231b658 00000001 TDI!TdiNotifyPnpClientList+0x164
    f898dca4 f885051a 00000000 00e65e10 81da5768 TDI!TdiExecuteRequest+0x382
    f898dce0 f88505b7 8231b658 0000000d 00000000 TDI!TdiHandleSerializedRequest+0x1c4
    f898dcfc f7e82f82 8205b2b8 81da57c0 806ed0e0 TDI!TdiRegisterDeviceObject+0x7d
    f898dd3c f7e70ee7 81da5660 00000002 81f662e8 netbt!NbtNotifyTdiClients+0x8e
    f898dd58 f7e65c34 00000000 00000000 00000000 netbt!DelayedNbtProcessDhcpRequests+0x4d
    f898dd74 804e426b 81f662e8 00000000 823b28b8 netbt!NTExecuteWorker+0x18
    f898ddac 8057d0f1 81f662e8 00000000 00000000 nt!ExpWorkerThread+0x100
    f898dddc 804f827a 804e4196 00000001 00000000 nt!PspSystemThreadStartup+0x34
    00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

    STACK_COMMAND: kb

    FOLLOWUP_IP:
    rdbss!_RxFreePool+10
    f7d30a30 5d pop ebp

    SYMBOL_STACK_INDEX: 2

    SYMBOL_NAME: rdbss!_RxFreePool+10

    FOLLOWUP_NAME: MachineOwner

    MODULE_NAME: rdbss

    IMAGE_NAME: rdbss.sys

    DEBUG_FLR_IMAGE_TIMESTAMP: 445b1f4b

    FAILURE_BUCKET_ID: 0xc2_7_ObjT_rdbss!_RxFreePool+10

    BUCKET_ID: 0xc2_7_ObjT_rdbss!_RxFreePool+10

    kd> lmvm rdbss
    start end module name
    f7d30000 f7d5aa00 rdbss (pdb symbols) D:\Symbols\rdbss.pdb\841B86559D834030A09A8292A9BA02C32\rdbss.pdb
    Loaded symbol image file: rdbss.sys
    Mapped memory image file: D:\Symbols\rdbss.sys\445B1F4B2aa00\rdbss.sys
    Image path: rdbss.sys
    Image name: rdbss.sys
    Timestamp: Fri May 05 11:47:55 2006 (445B1F4B)
    CheckSum: 000345EF
    ImageSize: 0002AA00
    File version: 5.1.2600.2902
    Product version: 5.1.2600.2902
    File flags: 0 (Mask 3F)
    File OS: 40004 NT Win32
    File type: 3.7 Driver
    File date: 00000000.00000000
    Translations: 0409.04b0
    CompanyName: Microsoft Corporation
    ProductName: Microsoft® Windows® Operating System
    InternalName: rdbss.sys
    OriginalFilename: RDBSS.Sys
    ProductVersion: 5.1.2600.2902
    FileVersion: 5.1.2600.2902 (xpsp_sp2_gdr.060505-0036)
    FileDescription: Redirected Drive Buffering SubSystem Driver
    LegalCopyright: © Microsoft Corporation. All rights reserved.

    —– END DUMP —–

    I’m wondering if this could be exploitable…

  10. Comment por Zohiartze Herce | 05/05/08 at 5:57 pm

    I don’t think that this has something to do with Ioctlizador. I’ve tested on XP SP 2 and everything worked fine.

  11. Comment por Zohiartze Herce | 05/08/08 at 11:44 pm

    Ok, se trataba de un fallo en el Hook, por no preservar el registro ebx. Corregido 🙂

  12. Comment por Amian | 05/11/08 at 11:35 pm

    Corregido wey

Se han cerrado los comentarios