• Restauración SSDT en x86

 #406792  por orlando9427
 06 Mar 2013, 01:45
1-Introducción.
1.1-¿Qué es el System Service Descriptor Table?
1.2-¿Cómo se carga Windows NT?
1.3-¿Cómo se carga la SSDT?
2-Hooking la SSDT.
2.1-Localizando la SSDT.
2.2-Modificando el valor original.


--#1# >> Introducción.
Este paper tiene el objetivo de mostrar que es posible mantener una interacción desde el Modo Usuario hacia el Modo Kernel sin el uso de Driver de por medio. Antes de adentrarnos de lleno en ese tema se necesitan conocimientos que se explicarán en este paper. Algunos he profundizado en su explicación solo como un dato secundario.

---#1.1# >> ¿Que es la System Service Descriptor Table?
Uno de los aspectos mas notorios de la programación en Ring0 es el manejo de la System Service Descriptor Table o abreviada SSDT. La SSDT se encuentra en la estructura KeServiceDescriptorTable que es una matriz unidimensional de 4 elementos que contiene las tablas de servicio (service tables). Las tablas de servicio son usadas para buscar un número de API, por medio de una jump table, y para devolver el numero de API a una función [1]. Windows utiliza solo dos elementos de la matriz uno para ntoskrnl.exe y otro para win32k.sys.
struct System_Service_Table{
  PVOID ServiceTableBase;
	PVOID ServiceCounterTable(0);
	unsigned int NumberOfServices;
	PVOID ParamTableBase;
};
---#1.2# >> ¿Como se carga Windows NT?
Este tema será profundizado más de lo necesario solo como conocimiento secundario. Todo comienza con el botón de encendido, posterior a esa acción se listan las acciones de la computadora hasta que aparece el escritorio de Windows.
  • Se hace una comproación y análisis del hardware.
  • La BIOS localiza el dispositivo de arranque y ejecuta la MBR.
  • Se ejecuta NTLDR, el primer archivo de Windows.
    • Busca la partición de arranque dentro del dispositivo de arranque.
    • Lee el archivo boot.ini para encontrar los Sistemas Operativos Windows NT instalados.
    • Ejecuta NTDetect, este último hace una lista de todo el hardware instalado y lo devuelve a NTLDR.
    • Guarda esta lista en el registro de Windows (HKEY_LOCAL_MACHINE\HARDWARE).
    • Se carga el archivo NTOSKRNL.exe, el kernel en sí, pero no es ejecutado.
    • Carga el archivo HAL.dll.
    • Obtiene la configuración del hardware.
    • Carga los servicios con el valor Start en 0
  • NTLDR ejecuta el archivo cargado NTOSKRNL.exe y le pasa el control del PC.
  • El kernel ejecuta los servicios cargados por NTLDR.
  • El kernel inicia los servicios con valor Start en 1.
  • Se inician los subsistemas y los ejecutivos (Executive).
  • Se ejecuta Winlogon.exe, encargado de las sesiones de usuario.
  • Aparece la pantalla de usuario y contraseña.
  • Se cargan los servicios con valor de Start igual o superior a 2. [2]
---#1.3# >> ¿Como se carga y cómo funciona la SSDT?
La carga de esta tabla sucede durante la inicialización de NTOSKRNL, esta tabla se encuentra dentro del código de NTOSKRNL y su posición depende de la version de Windows y del Service Pack. Se crea una tabla de funciones con los servicios de NTOSKRNL. Cada entrada de la tabla contiene la dirección de una función a ser ejecutada por un identificador. En el lado del User Mode las mas comunes son KERNEL32.dll y ADVAPI32.dll estas librerías se encargan de la válidación de los parámetros así como su conversión a Unicode, posterior a esto llaman a Syscall/Sysenter, que es la barrera entre Modo Kernel y Modo Usuario, se encarga de pasar los parámetros del stack del Modo Usuario al stack del Modo Kernel; una vez hecho eso utiliza la interrupción INT 2Eh para entrar al Modo Kernel donde se busca la función usando un Identificador y una Jump Table; una vez encontrada la dirección de la función se llama y se devuelve el valor al Modo Usuario.

--#2# >> Hooking de la SSDT.
La manera mas sencilla de hookear una función es localizando la SSDT y modificando el puntero por uno hacia alguna función deseada por el desarrollador. Muchos de los textos respecto a esto dicen que esto solo es posible desde el Modo Kernel pero obviamente vamos a desmentir eso en este paper. Lo que no podemos desmentir es que este método solo es válido para restauración de la SSDT ya que si intentamos poner un hook desde Modo Usuario causaremos un Blue Scren Of Death (BSOD), debido a que son diferentes espacios de memoria, con direcciones relativas.

---#2.1# >> Localizando la SSDT.
Hay muy poca documentación oficial para encontrarla, pero en internet se puede encontrar hasta el código de Windows, así que seguiremos uno de los métodos mas comunes para encontrarla. Una forma obteniendo una lista de NTOSKRNL de la lista de exportaciones, esta lista es llamada KeServiceDescriptorTable. Revisando la estructura del punto 1.1 ahora podemos dar explicación a cada elemento.
  • ServiceTableBase - Dirección base de la SSDT.
  • NumberOfServices - Número de entradas de la SSDT.
  • ServiceCounterTable - Este campo es usado solo en versiones de desarrollo y contiene cuantas veces cada función en la SSDT ha sido llamada. Este contador es actualizado por la interrupción INT 2Eh.
  • ParamTableBase - Contiene la dirección base de la SSPT (Su completa descripción la dejaré para otro paper), a grandes rasgos contiene el numero de bytes de los parametros de cada función en la SSDT. [3]
---#2.2# >> Modificando el valor original.
Se ha hablado de la forma de hookeo a la SSDT, que no es mas que la sustitución del valor original por la dirección de memoria de la sustituta, nada complicado. Antes de seguir algunos se preguntarán, no se puede hookear en Modo Usuario pero si desde Modo Kernel, aquellos que se hagan esa pregunta la respuesta es sencilla; el Modo Kernel es un espacio de memoria muy grande donde convergen muchos apectos de Windows como son los Subsistemas, Driver, Tablas, etc, y es por eso que no tenemos inconvenientes de usar direcciones de memoria pues no referimos al mismo espacio de memoria que la SSDT.
Obviamente esta tabla tiene una protección, llamada CR0, contra escritura pero no es muy dificil eliminar esta protección, hay dos métodos convencionales. El primero es, a palabras de Hendrix y experiencia propia, muy poco ortodoxo.
Con este código se establece el bit llamado Write Protect a 0
__asm
  {
    push eax
    mov  eax, CR0
    and  eax, 0FFFEFFFFh
    mov  CR0, eax
    pop  eax
  }
Para volver la protección a la normalidad.
__asm
  {
    push eax
    mov  eax, CR0
    or   eax, NOT 0FFFEFFFFh
    mov  CR0, eax
    pop  eax
  }
El segundo método es por Memory Descriptor List, explicando un poco el método, usando el IoAllocateMdl (La API original es MmCreateMdl pero por cuestiones de compatibilidad esta se ha cambiado) crea una MDL a la que podemos establecer flags para eliminar la protección de la SSDT.
g_pmdlSystemCall = IoAllocateMdl(KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4, FALSE, FALSE, NULL);
if(!g_pmdlSystemCall)
  return STATUS_UNSUCCESSFUL;
  
 MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
Para reestablecer la protección simplemente liberamos la MDL de la siguiente forma. [4]
if(g_pmdlSystemCall)
  {
    MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
    IoFreeMdl(g_pmdlSystemCall);
  }
Una vez eliminada la protección solo basta encontrar buscar el puntero de la API a hookear en la SSDT y sustituir.
No tocaremos más este tema pues no es el tema fundamental, si quieren continuar leyendo recomiendo lecturas como, "Introduccion a la programacion de Drivers en Windows" por Hendrix o leer la biblia del rootkit "Rootkits: Subverting the Windows Kernel" por Greg Hoglund y Jamie Butler.

Continua...
 #412799  por joselin
 07 May 2013, 20:40
amigo orlando ahora estoy estudiando sobre punteros(este tema de restauracion ssdt es muy complicado y mas en delphi , toda la info esta en c y no quiero meterme en otro estilo de programacion , "cuando todavia me pierdo en delphi"
queria pedirte si podes hacer algun manual para restauracion ssdt en delphi
(yo me estoy apoyando en Meerkat 1.1 Beta 1 ,porque encontre sencillo su funcionamiento)
si el tiempo te lo permite te estaria agradecido
saludos
 #412801  por orlando9427
 07 May 2013, 20:54
Aun no termino este manual, puesto que aún estoy puliendo la restauracion en W7, la parte que tengo hecha solo funciona en WXP. Pero trataré de ir traduciendo todo a Delphi. Ya que entraste a la programación de Drivers en Delphi te recomiendo la Delphi Driver Developt Kit o DDDK, la publique junto con una herramienta para compilar drivers.

Saludos!
 #412866  por Pink
 08 May 2013, 03:02
Gracias a leer un ratote. que de esto se nada :S

saludos
 #413386  por Scorpio
 14 May 2013, 17:25
Muy bueno como siempre bro, si no mal recuerdo, el SSDT era lo que fallaba en el Agony Rootkit.

Saludos.