Intercepción (programación)
La intercepción ( en inglés hooking ) es una tecnología que permite cambiar el comportamiento estándar de ciertos componentes de un sistema de información.
Propósito de la tecnología de interceptación
Muy a menudo, en la programación de sistemas existe la tarea de cambiar el comportamiento estándar de las funciones del sistema. Por ejemplo, una aplicación bastante interesante de esta tecnología es la redefinición del procedimiento de ventana en la GUI de las aplicaciones de Windows ( subclases ). Esto es necesario si el programador desea organizar su propio procesamiento de cualquier mensaje de ventana y solo luego pasarlo al procedimiento de ventana estándar. Después de la subclasificación, el ciclo de procesamiento de mensajes se verá así:
Mensaje de Windows->Ventana (procedimiento de ventana)
Mensaje de Windows->Procedimiento de nuestra ventana->Ventana (procedimiento de ventana)
Por ejemplo, los tutoriales de Iczelion [1] describen un ejemplo de cómo se puede usar la subclasificación para controlar la entrada a los controles. Las tecnologías de interceptación son necesarias no solo en este caso, sino también, por ejemplo, para el procesamiento previo de los resultados de las funciones de búsqueda de archivos del sistema FindFirst y FindNext, EnumProcess, que enumera procesos en Windows, etc. Además, para estos fines, tales tecnologías se utilizan como herramientas antivirus [2 ] , así como varios tipos de virus, rootkits y otros tipos de software malicioso.
Muy a menudo, la intercepción es importante para la depuración de programas y es una de las principales tecnologías utilizadas en los depuradores. En este caso, esta tecnología permite que un programa controle la ejecución de otro. Para estos fines, se proporciona la llamada al sistema ptrace , que le permite conectarse a procesos, rastrear los valores de los registros en el contexto del proceso que se está depurando y, entre otras cosas, controlar otras llamadas al sistema. Es la base para implementar una característica de los depuradores como puntos de interrupción . Esta llamada al sistema está bien documentada y está presente en todos los principales sistemas *Nix: Linux , FreeBSD , Solaris . [3] Se usa con mayor frecuencia junto con la llamada al sistema de bifurcación , que llama a ptrace, especificando en los parámetros de la llamada que el proceso que se está iniciando es un proceso secundario. Microsoft Windows también proporciona para propósitos similares los llamados. API de depuración [4] .
Tipos de interceptación de funciones del sistema
Los principales métodos de interceptación son:
- Sustitución de la dirección de una función real ( modificación de tablas IAT , modificación de tablas SSDT / IDT )
- Cambiar una función directamente (empalme, enganche en modo kernel con modificación del cuerpo de la función)
- Reemplazo directo de toda la aplicación/componente del sistema (por ejemplo, bibliotecas con una función de destino)
Los métodos también se pueden dividir según los criterios del modo de ejecución:
- Métodos personalizados ( ring3 ): modificación de tablas IAT, splicing. Su peculiaridad es que es imposible cambiar nada en el comportamiento del kernel del sistema operativo y sus extensiones.
- Modo kernel: modificación de tablas SSDT/IDT, intercepción en modo kernel con modificación del cuerpo de la función. Le permite modificar las estructuras de datos y el código de cualquier parte del sistema operativo y las aplicaciones.
Empalme
El empalme (del inglés splice - "empalmar o pegar los extremos de algo") es un método para interceptar funciones API cambiando el código de la función de destino. Por lo general, se cambian los primeros 5 bytes de la función. En su lugar, se inserta una transición a una función que define el programador. Para garantizar que la operación se realice correctamente, la aplicación que intercepta la función debe permitir que se ejecute el código que se modificó como resultado del empalme. Para hacer esto, la aplicación guarda la sección de memoria reemplazada consigo misma y, después de resolver la función de intercepción, restaura la sección modificada de la función y permite que la función real se ejecute por completo. [5]
punto de parche caliente
Todas las funciones dll estándar de Windows admiten puntos de parche. Cuando se usa esta tecnología, cinco operaciones nop de un byte no utilizadas se ubican antes del inicio de la función, mientras que la función misma comienza con una instrucción mov edi, edi de dos bytes. El espacio ocupado por cinco nops es suficiente para acomodar una instrucción de bifurcación a la función de interceptor. Los dos bytes ocupados por mov edi, edi proporcionan suficiente espacio para que el comando salte al código en lugar de los cinco nop. Al mismo tiempo, dado que la instrucción mov edi, edi no realiza ninguna acción significativa, sobrescribirla no afecta el rendimiento de la función original de ninguna manera. Así, el programador se libera de la necesidad de guardar el valor original del código que ha cambiado en alguna parte [6] .
Aplicaciones del empalme y métodos de detección
Aplica:
- En software que necesita realizar funciones de monitoreo del sistema
- El mecanismo de gancho en Windows
- Varios tipos de malware. Esta es la principal tecnología sigilosa para los rootkits a nivel de usuario .
El método principal para detectar el hecho de empalmar es una comparación del código de máquina de la función que se está comprobando para empalmar y el código de la función del sistema obtenido en un sistema limpio conocido. Además, monitorear las direcciones de salto puede ayudar a detectar el empalme de una función.
Comparación con otras tecnologías
- Cambio de tablas de procesos IAT [7] . Esta tecnología no le permite cambiar el comportamiento de la función del sistema en sí, sino que solo permite "engañar" a la aplicación seleccionada, obligándola a usar su función. Tabla IAT: una tabla de direcciones de funciones importadas por el proceso. La tecnología es solo de carácter local, aunque se puede aplicar inmediatamente a un grupo de aplicaciones. Se puede detectar con bastante rapidez debido a la necesidad de cargar la DLL [8] en el espacio de direcciones del proceso de destino. El empalme, por otro lado, no requiere una DLL y la inyección en el proceso de otra persona, tiene la capacidad de capturar una función globalmente. El empalme tiene otra ventaja: no todas las funciones del sistema son importadas por un proceso a través de IAT. Por ejemplo, se puede cargar una función llamando a GetProcAddress. El uso de una modificación directa del código de función elimina esta limitación.
- Intercepción en modo kernel . Le permite interceptar cualquier función, incluidas las exportadas por el núcleo. Más difícil de detectar si tiene éxito, ya que le permite falsificar cualquier dato proporcionado por el sistema operativo. Requiere escribir un componente especial para interactuar con el núcleo del controlador. Puede conducir a BSOD si se programa incorrectamente en modo kernel. Se puede detectar durante la fase de carga del controlador en el núcleo o al comprobar los controladores activos, así como al comprobar si hay cambios en el núcleo [9] . Un método de programación más difícil que el empalme, pero más flexible, ya que le permite interceptar las funciones del kernel en sí, y no solo las funciones de WinAPI, que sirven solo como intermediario entre el kernel y el programa que solicita algo del sistema operativo. sistema.
- Reemplazando la biblioteca en sí con el . Una solución muy radical al problema, que tiene una serie de inconvenientes importantes:
- Requiere el reemplazo de un archivo en el disco, que puede ser prohibido y suprimido por el propio sistema. Por ejemplo, reemplazar los archivos del sistema de Windows evitará que se ejecute la Protección de archivos de Windows (WFP) , aunque se puede desactivar. Tal acción también puede ser detectada durante un análisis estático del sistema por parte de los auditores.
- Se requiere la emulación completa de todas las capacidades de la DLL reemplazada u otro componente, lo cual es muy laborioso incluso en el caso de la apertura y se complica por la necesidad de desensamblar en el caso de un programa de destino cerrado.
Todo esto demuestra que esta es una forma muy irracional de resolver el problema de cambiar el comportamiento del programa si los dos primeros enfoques o empalmes son posibles.
Interceptación en modo kernel
Se basa en la modificación de las funciones y estructuras de datos del núcleo . Las mesas son los principales objetivos de influencia.
- Tabla de despacho de interrupciones IDT . Es muy importante interceptar la interrupción que maneja la tabla de servicio SSDT (0x2E) [10] .
- SSDT (Tabla de despacho de servicios del sistema) Tabla de despacho de servicios del sistema. Refiriéndose a él, el sistema, por el número del servicio solicitado, puede obtener la dirección del servicio del núcleo correspondiente y llamarlo. Y la tabla SSPT contiene el tamaño total de los parámetros pasados al servicio del sistema.
- psActiveprocess Una estructura de kernel que contiene una lista de procesos en el sistema.
- Tabla de controlador de IRP que almacena punteros a funciones de procesamiento de IRP.
- EPROCESS Una estructura del kernel que almacena mucha información sobre un proceso, incluido, por ejemplo, el PID (Process ID).
Los rootkits de este tipo se denominan rootkits DKOM, es decir, rootkits basados en la modificación directa de los objetos del kernel. En los rootkits para sistemas Windows Server 2003 y XP , esta tecnología se ha actualizado, ya que estos sistemas operativos ahora cuentan con protección contra escritura para ciertas áreas de la memoria del kernel [10] . Windows Vista y 7 recibieron protección adicional del núcleo PatchGuard , sin embargo, todas estas tecnologías fueron superadas por los creadores de rootkits [11] . Al mismo tiempo, la interceptación de las funciones del sistema en modo kernel es la base de los hipervisores y los sistemas de defensa proactiva .
Otras formas de interceptación
Se pueden distinguir otras formas de interceptación:
- Interceptación de conexiones de red y paquetes. [12]
- Interceptación de contraseñas. Por ejemplo, espiando la entrada del teclado usando un registrador de teclas .
- Intercepción de solicitudes de navegador a sitios que utilizan Proxy HTTP o extensiones de navegador. Le permite analizar y/o reemplazar los datos intercambiados entre el navegador y el servidor.
Aquí sólo se describe una parte de las aplicaciones de esta tecnología.
Ejemplos de programas que usan interceptación
Ejemplos de código
Interceptar eventos de teclado de
Microsoft Windows en
C# usando
Microsoft .NET Framework
utilizando el sistema ;
utilizando System.Collections ;
usando System.Diagnostics ;
usando System.Runtime.InteropServices ;
Espacio de nombres Hooks
{
public class KeyHook
{
#region Variables miembro
protected static int hook ;
supresión estática protegida LowLevelKeyboardDelegate ; objeto de solo lectura estático protegido Bloqueo = nuevo objeto (); protected static bool isRegistered = false ; #endregion
#región Dll Imports
[DllImport("user32")]
privado estático externo Int32 SetWindowsHookEx ( Int32 idHook , LowLevelKeyboardDelegate lpfn ,
Int32 hmod , Int32 dwThreadId );
[DllImport("user32")] privado estático externo Int32 CallNextHookEx ( Int32 hHook , Int32 nCode , Int32 wParam , KBDLLHOOKSTRUCT lParam );
[DllImport("user32")]
privado estático externo Int32 UnhookWindowsHookEx ( Int32 hHook );
#endregion
#región Tipo Definiciones y constantes
protected delegado Int32 LowLevelKeyboardDelegate ( Int32 nCode , Int32 wParam , ref KBDLLHOOKSTRUCT lParam );
const privado Int32 HC_ACTION = 0 ; const privado Int32 WM_KEYDOWN = 0 x0100 ; const privado Int32 WM_KEYUP = 0 x0101 ; const privado Int32 WH_KEYBOARD_LL = 13 ; #endregion [StructLayout(LayoutKind.Sequential)] public struct KBDLLHOOKSTRUCT { public int vkCode ; código de escaneo público int ; banderas públicas int ; hora pública int ; public int dwExtraInfo ; }
estático privado Int32 LowLevelKeyboardHandler ( Int32 nCode , Int32 wParam , ref KBDLLHOOKSTRUCT lParam )
{
if ( nCode == HC_ACTION )
{
if ( wParam == WM_KEYDOWN )
Sistema . consola _ fuera _ WriteLine ( "Tecla abajo:" + lParam . vkCode );
más si ( wParam == WM_KEYUP )
Sistema . consola _ fuera _ WriteLine ( "Tecla arriba:" + lParam . vkCode );
}
devuelve CallNextHookEx ( 0 , nCode , wParam , lParam );
}
public static bool RegisterHook ()
{
lock ( Lock )
{
if ( isRegistered )
return true ;
suprimir = new LowLevelKeyboardDelegate ( LowLevelKeyboardHandler ); hook = SetWindowsHookEx ( WH_KEYBOARD_LL , dele , Marshal . GetHINSTANCE ( System . Reflection . Assembly . GetExecutingAssembly (. GetModules ()[ 0 ] ) . ToInt32 (), 0 );
if ( hook != 0 )
return isRegistered = true ;
más
{
eliminar = nulo ;
devolver falso ;
}
}
}
public static bool UnregisterHook ()
{
lock ( Lock )
{
return isRegistered = ( UnhookWindowsHookEx ( hook ) != 0 );
}
}
}
}
gancho
de filtro de red
Este ejemplo muestra cómo se usan los ganchos para controlar el tráfico de red en el kernel de Linux usando Netfilter .
#include <linux/módulo.h>
#incluir <linux/kernel.h>
#incluir <linux/skbuff.h>
#incluir <linux/ip.h>
#incluir <linux/tcp.h>
#incluir <linux/in.h>
#incluir <linux/netfilter.h>
#incluye <linux/netfilter_ipv4.h>
/* Puerto en el que queremos dejar paquetes */
puerto estático const uint16_t = 25 ;
/* Esta es la función gancho en sí misma */
hook_func int sin firmar estático ( hooknum int sin firmar ,
estructura sk_buff ** pskb ,
const estructura net_device * en ,
const struct net_device * salida ,
int ( * okfn ) ( estructura sk_buff * ))
{
estructura iphdr * iph = ip_hdr ( * pskb );
estructura tcphdr * tcph , tcpbuf ;
si ( iph -> protocolo != IPPROTO_TCP )
devolver NF_ACEPTAR ;
tcph = skb_header_pointer ( * pskb , ip_hdrlen ( * pskb ), sizeof ( * tcph ), & tcpbuf );
si ( tcph == NULL )
devolver NF_ACEPTAR ;
volver ( tcph -> dest == puerto ) ? NF_DROP : NF_ACEPTAR ;
}
/* Usado para registrar nuestra función gancho */
estructura estática nf_hook_ops nfho = {
. gancho = función_gancho ,
. ganchonum = NF_IP_PRE_ROUTING ,
. pf = NFPROTO_IPV4 ,
. prioridad = NF_IP_PRI_FIRST ,
};
__init estático int my_init ( vacío )
{
volver nf_register_hook ( & nfho );
}
estático __salir vacío mi_salida ( vacío )
{
nf_unregister_hook ( & nfho );
}
módulo_init ( mi_init );
módulo_salida ( mi_salida );
Véase también
Notas
- ↑ Lecciones de Iczelion. API Win32. Lección 20
- ↑ Por ejemplo: es imposible acceder al proceso de Kaspersky Internet Security utilizando las herramientas API estándar de Windows, ya que las funciones correspondientes son interceptadas por el antivirus.
- ↑ Página de la página del manual de Linux Ubuntu: página del manual sobre cómo llamar a ptrace Archivado el 21 de enero de 2010 en Wayback Machine y versión rusa: traducción al ruso en OpenNET Archivado el 1 de noviembre de 2014 en Wayback Machine
- ↑ Descripción oficial: La interfaz de programación de aplicaciones de depuración Archivado el 30 de mayo de 2014 en Wayback Machine , con ejemplos de uso: API Win32. Lección 28. Win32 Debug API I Archivado el 4 de marzo de 2010 en Wayback Machine .
- ↑ Una serie de artículos sobre la interceptación de funciones de la API de Windows por la Sra. Rem (enlace inaccesible) . Fecha de acceso: 24 de julio de 2010. Archivado desde el original el 23 de diciembre de 2009. (indefinido)
- ↑ ¿Por qué todas las funciones de Windows comienzan con una instrucción MOV EDI, EDI sin sentido? - La Vieja Cosa Nueva . Consultado el 11 de enero de 2017. Archivado desde el original el 13 de enero de 2017.
- ↑ Los métodos para acceder y modificar la tabla IAT se describen con cierto detalle en Hoglund G., Butler J. - Rootkits: Implementación en el kernel de Windows. Capítulo 4 El antiguo arte de capturar
- ↑ J. Richter Christopher Nazar Windows describe con cierto detalle los métodos para inyectar una DLL en un proceso externo a través de C/C++. Programación en Visual C++. Algunos métodos de implementación fueron documentados por primera vez por el propio J. Richter
- ↑ Por ejemplo, uno de los primeros detectores de rootkits de KLISTNER. Archivado el 25 de julio de 2010 en Wayback Machine .
- ↑ 1 2 G. Hoglund J. Butler Los rootkits se inyectan en el kernel de Windows. Capítulo 4 El antiguo arte de capturar
- ↑ asesinato de centinela [[Chris Kaspersky|CHRIS KASPERSKY]], AKA MOUSE Special: Hacker #072, página 072-072-5 . Consultado el 26 de julio de 2010. Archivado desde el original el 4 de diciembre de 2010. (indefinido)
- ↑ Por ejemplo, los rastreadores hacen esto. Una implementación gratuita de captura de paquetes de red es el controlador de red de capa NDIS WinPCAP .
Literatura
- Geoffrey Richter . Programación en Visual C++ = Windows a través de C/C++. - San Petersburgo. : Pedro, 2010. - S. 689-728. - ISBN 978-5-7502-0367-3 .
- Hoagland, Greg , Butler J. Rootkits: subvertir el kernel de Windows = Rootkits. Subvertir el kernel de Windows. - San Petersburgo. : Pedro, 2010. - S. 36-58,77-129. - ISBN 978-5-469-01409-6 .
Enlaces