[TUTORIAL] Reversing del controlador XignCode3 - Parte 3 - Análisis de la funcion

  • Hola Invitado, ¿Quieres ganar dinero con GamerzHacking?, estamos necesitando creadores de contenido en game hacking o pirateria de juegos ingresa al siguiente enlance para mayor informacion AQUI
  • Hola Invitado, ¿Creas contenido sobre game hacking en tu blog o sitio web?, ¿Te gustaria formar una alianza para asi poder generar mas trafico en tu sitio y seguir creciendo como comunidad? INGRESA AQUI


259
Me Gusta
124
Temas

c0de

MOV EAX, EDX
Top Publicador Del Mes
Registrado
19 Abr 2020
Temas
124
Mensajes
235
Ubicación
Localhost
Mejores respuestas
0
1588820688518.png
Si no ha leído la publicación anterior, puede encontrarla aquí: Parte 2: análisis de las funciones de inicio . En esta publicación, finalmente analizaremos la función Dispatcher. Recuerde que identificamos esta función en la primera publicación . Esta función tiene el objetivo principal de procesar cualquier paquete de solicitud de E/S (IRP) y, en este caso, manejar cualquier solicitud del código de función principal
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
.

¿Por lo que pasaremos?
  1. Aprenda cómo se implementan las rutinas de Dispatcher.
  2. Para revertir el método de análisis que maneja las solicitudes IRP_MJ_WRITE.
  3. Identifique estructuras personalizadas utilizadas por el controlador y cree nuevos tipos locales en IDA.
  4. Comprenda cómo el controlador distribuye los diferentes identificadores codificados atravesando una matriz con estructuras personalizadas.
Introducción

Al invertir las cosas relacionadas con Windows, la lectura de la documentación de MS debería ser obligatoria. Por lo general, proporcionan mucha información útil que le ahorrará mucho tiempo, como las estructuras que usan, los parámetros y los ejemplos de código. Algo que me gusta hacer es examinar los ejemplos disponibles en sus repositorios y buscar códigos similares. Los desarrolladores de controladores suelen reutilizar una gran cantidad de código de esos ejemplos. Buscar patrones similares en nuestro binario podría proporcionarnos mucha información sobre el contexto y las funciones a las que se llama dentro de un fragmento de código similar. Al final de esta publicación, encontrará una lista de enlaces útiles.

fn_DriverIOCTLDispatcher (0x140004604)

Primero, tome unos minutos para analizar el
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
inicial
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
y el
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
. Un controlador puede proporcionar múltiples rutinas de despacho, en este caso, implementaron solo un código de función principal, como vimos antes.

Porfavor, Acceder o Registrarse para ver el contenido citado!

Podemos ver que recibe dos parámetros, pero ¿sabemos cuáles son esos parámetros? Sí, la documentación de MS explica que las
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
despachador
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
reciben como primer parámetro un PDEVICE_OBJECT y como segundo un puntero a una estructura IRP (IDA identificará este por sí mismo).

1588820989256.png

En la línea 16, el controlador controla que la longitud del búfer de entrada es igual a 0x270 , parece que es la única longitud posible.

Tenga cuidado al analizar la siguiente línea:

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Como puede ver a continuación, MasterIrp comparte el mismo desplazamiento con IrpCount y SystemBuffer dentro de una unión (
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
):

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

En este caso, el Despachador está intentando recuperar el SystemBuffer de la solicitud de IRP; no hace referencia al puntero MasterIrp. Necesitamos arreglar eso adecuadamente. En IDA PRO, esto se puede hacer fácilmente haciendo clic derecho-> Seleccionar campo de unión:

1588821133250.png

Ahora que hemos identificado dónde se almacena el búfer de entrada, veamos cómo se analiza:

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Podemos ver que se espera que el primer DWORD sea igual a 0x270 (mismo valor de la longitud); Entonces, el siguiente DWORD debe tener algún tipo de valor mágico que coincida con 0x345821AB . Si se cumplen ambos requisitos, la función sub_140001E00 se llama enviando el búfer en el primer parámetro, y una referencia a una estructura aún desconocida en el segundo parámetro. Decidí llamar a esta función fn_DispatchIOCTLMethod y la analizaremos en la siguiente sección.

Después de cambiar el nombre de las variables, podemos concluir que la estructura del búfer de entrada sería algo como esto:

Código:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Como todavía no estamos analizando todos los métodos de envío, pero quiero proporcionarle un análisis completo del búfer de entrada, le mostraré la estructura completa que está utilizando el controlador. La estructura final sería así:

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Esta función hace algunas cosas más, pero ignorémoslas por ahora.

fn_DispatchIOCTLMethod (0x140001E00)

1588821221355.png

Esta función es pequeña, y veremos que después de configurar los tipos correctamente y cambiar el nombre, todo se vuelve mucho más claro.

Lo primero que deberíamos hacer es agregar la estructura previamente definida DrvInputBuffer a IDA Pro. En la subvista "Tipos locales", es posible hacer "Clic derecho-> Insertar", allí puede copiar y pegar la definición de estructura:

1588821332840.png

Siguiente paso, cambie el nombre del primer parámetro para que sea un puntero a esa estructura haciendo "clic derecho en la variable -> Convertir a estructura *".

Si ocultamos los moldes, obtendremos algo como esto:

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Si ha leído las publicaciones anteriores, puede reconocer dword_14000A240. Cambiamos el nombre de esta variable en la segunda publicación, mientras analizábamos fn_InitDispatchMethodArray : esta era la variable FunctionsCount .

Lo mismo sucede con dword_140009E40, que se renombró a IOCTLFunctionArray en la misma publicación, y es una matriz que contiene múltiples estructuras DispatcherStruct :

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

En base a eso, podemos identificar el siguiente comportamiento: Primero, la aplicación valida que IOCTLFunctionArray se haya inicializado comparando FunctionsCount con NULL. Luego, itera en un ciclo while, comparando el valor del índice de cada elemento con el DWORD en el desplazamiento 0xC del búfer de entrada (definido en la estructura como FnIndex ). Aumentan el contador hasta que alcanza el valor máximo almacenado en FunctionsCount . Si hay una coincidencia entre los índices, la función almacenada en DispatcherStruct-> FnPtr es call; enviando los mismos dos parámetros de fn_DispatchIOCTLMethod: SystemBuffer y la referencia a una estructura aún desconocida.

Esta sería la función final:

C++:
Porfavor, Acceder o Registrarse para ver el contenido de los códigos!

Próximos pasos
  • Análisis de NotifyRoutines (fn_InitRegistrationNotifyAndCallbackRoutines y fn_RegisterCreateProcessNotifyRoutine)
  • Cargue estructuras de kernel con archivos .h y tipos locales
Enlaces útiles
Creditos
Niemand

Enlace de origen
Porfavor, Acceder o Registrarse para ver el contenido de las URL!

Twitter
Porfavor, Acceder o Registrarse para ver el contenido de las URL!
 

Adjuntos

  • 1588820679684.png
    1588820679684.png
    201,9 KB · Visitas: 0
AdBlock Detectado

Lo sentimos, los anuncios son molestos!

Claro, el software de bloqueo de anuncios hace un gran trabajo al bloquear anuncios, pero también bloquea funciones útiles de nuestro sitio web. Para obtener la mejor experiencia en el sitio, deshabilite su AdBlocker.

He desactivado AdBlock    No, gracias