Skip to content

DevelopmentDocumentation

Jose Ramon Palanco edited this page Jan 26, 2020 · 2 revisions

La solución drainware security endpoint se trata de un sistema modular compuesto por un servicio, un agente de usuario, una extensión shell, y una sandbox.

Módulo principal, servicio

Clase CDrainwareSecurityAgentModule

Esta es la clase de entrada, la que controla el servicio, a la que se dice que pare, pause o inicie. Las funciones principales son establecer comunicación con el DDI, instalar el monitor de impresora y mantener un listado de los usuario que hacen uso del equipo.

InitializeSecurity – Establece el modo de seguridad para ser usado por COM en las comunicaciones con los clientes del endpoint y los establece de la siguiente forma:

  • Nivel de autenticación – Ninguna
  • Nivel de impersonificación – Identify

Install – Se encarga de registrar las dll DrainwareShellExt.dll y DrainwareSecurityAgentPS.dll; además también registra el servicio y los objetos COM exportados.
Run – Es el punto de entrada cuando el servicio es activado o puesto en marcha. En este método se carga la configuración, se crea un hilo para iniciar la comunicación con el DDI, se inicia otro hilo para monitorizar la impresora y se asegura de que la extensión del shell y el proxy stub estén registrados correctamente.
AddClient – Este método añade un objeto COM que se ha creado remotamente a la lista de objetos que están en funcionamiento. Devuelve un puntero a la clase que se encarga de la gestión de un usuario dado (CUserData).
RemoveClient – Elimina el objeto COM de la lista cuando este ha sido liberado remotamente (por UserAgent, Printer, Shell… )
PrintJob – Método que notifica al UserAgent que puede imprimir un documento cuando este ha sido aprobado.
SendEvent – Método especializado para envíar eventos al ddi a través de amqp. Diferenciando cuando es para “rpc_atp_reporter_queue” o “rpc_dlp_reporter_queue”. Además en caso de que haya eventos pendientes los envía.
Fire_ScreenShot – Busca entre los Clientes uno de tipo UserAgent para indicarle que nos envíe un ScreenShot.
Fire_ShowMsg – Busca un UserAgent de un usuario concreto para que muestre una ventana de notificación en la bandeja del sistema.
ThreadDDI – Esté método es el hilo que se encarga de mantener la comunicación con el DDI usando la librería de amqp rabbitmq-c. A través de el se reciben los eventos del DDI.
InitPrinter – Registra el monitor de impresora para poder escanear el contenido de la impresión antes de que se imprima.
StopPrinter – Llamado cuando se para el servicio para desregistrar el monitor de impresión.
CloseClients – Llamado cuando se para el servicio para forzar la desconexión con los clientes COM e indicarles que deben cerrarse.
GetUser – Método de ayuda para buscar el manejador de usuario o crearlo en caso de que no exista y pedir la configuracion de usario al ddi. El objeto creado será compartido entre todas las instancias que usen el servicio.
RegATP – Se encarga de registrar las dll del sandbox atp.
UnregATP – Desregistra las dll del sandbox atp.
RegDLL – Método de ayuda para registrar una dll dada.
LoadConfig – Carga la configuración del registro, actualmente solo la IP del DDI o la LICENCIA en versión cloud.
DownloadFile – Método de ayuda para descargar un archivo de internet y dejar el contenido en una clase CStringA.
CheckForUpdates – Método que mira si hay una actualización nueva en internet para descargarla y ejecutarla.
SaveEvent – Guarda un evento en disco para su posterior envío (solo en caso de no tener comunicación con ddi y poder funcionar en modo offline)
SendPendingEvents – Una vez que se haya restablecido comunicación con el DDI se envían los eventos pendientes.

Clase CDwService

Esta clase es un Objeto COM que se instanciará desde los otros módulos, Impresora, agente y shell. A través de él se tiene acceso a la funcionalidad del servicio para comprobar el texto, imágenes y pulsaciones de teclas no contengan información relevante.

FinalConstruct – Llamado por la librería ATL cuando ha finalizado la construcción del objeto COM. En este método se hance un “impersonate” para guarda una copia del “token” del usuario del módulo cliente que creó el objeto. Además se obtiene un puntero a la clase que gestiona el usuario y que a posteriori comprobará el texto, imagen, etc..
FinalRelease – Cuando el objeto ha sido liberado por el módulo cliente, simplemente avisa al gestor de usuario que elimine la referencia a este objeto.
PrintJob – Método llamado una vez que se ha comprobado que el texto a imprimir no contenga relevancias. Hace un impersonate al usuario del cliente e imprime el documento.
Close – Método llamado para forzar el cierre del objeto (se llama cuando se para el servicio). Notifica al cliente que debe cerrarse y para el monitor que comprueba que el agente esté activo.
IsMappedDrive – Método de ayuda que comprueba si la unidad es mapeada a un directorio de red.
ThreadMonitor – Hilo que comprueba que el agente esté vivo. En caso de que haya sido finalizado por el usuario desde el administrador de tareas, vuelve a ejecutarlo con las credenciales del usuario.
CheckText – Método COM especializado en comprobar el texto, diferenciándolo según su tipo: ocr, clipboard, keylogger. Llama a la clase de usuario para que haga esta comprobación.
CheckFile – Método COM que comprueba que un archivo dado esté limpio.
CheckRemoteUnit – Comprueba si el archivo a tratar pertenece a una unidad remota definida en el DDI.
SetScreenShot – Método COM, llamado por los clientes enviando un screenshot.
SendATPEvent – Método COM, llamado por el módulo cliente Drainware SandBox
LoadATP – Método COM llamado desde el SandBox para ver si hay que monitorizar un proceso.
IsLicensed – Método COM que se llama desde el agente para comprobar si el producto tiene licencia válida y en vigor.
CheckLicense – Método que comprueba si una licencia dada es válida.
Post – Método de ayuda para enviar la licencia a una dirección URL y nos devuelva si es válida o no.
SetLicense – Método COM llamado desde el agente que establece la licencia una vez que haya sido comprobado que es válida.

Clase CUserData

Esta clase es el corazón del servicio, ya que es quien hace las comprobaciones de texto y archivos según la configuración del usuario.

OnUserConfig – Método llamado desde la clase CDDI con el fin de notificar que la configuración del usuario ha llegado desde el ddi.
OnGroupChanged – Método llamado desde la calse CDDI con el fin de notificar que ha cambiado la configuración de un grupo y se debe volver a cargar la configuración
CheckText – Este método comprueba un texto en base a unos conceptos y unas reglas asignadas al usuario. Devuelve un JSON con la información de los positivos.
CheckFile – Método que comprueba un archivo llamando a un programa de python que devuelve las coincidencias en forma de json.
CheckRemoteUnit – Comprueba si un archivo pertenece a una unidad remota.
LoadConfig – Carga la configuración del usuario desde los archivos recibidos del ddi, generando una lista de conceptos, reglas, unidades remotas, etc.. para validar los distintos casos.
ThreadLoadConfig – Hilo que carga la configuración del usuario despúes de haber recibido las configuraciones de los grupos del ddi
ExecuteCommand – Método de ayuda que sirve para ejecutar un comando del sistema. En este caso se usa para invocar los programas python.
VerifyMatch – Método de ayuda que llama a un programa python para que haga una verificación de una cadena.

Clase CDDI

Esta clase se encarga de gestionar la comunicación con el ddi a través de ddi. Principalmente se usa para recibir notificaciones del ddi y para enviar eventos al mismo.

AddUser – Añade un usuario a la lista interna para enviar notificaciones cuando estas llegan del ddi para el usuario dado.
SetDDINotify – Este método guarda un puntero a una interfaz para notificar eventos genéricos del ddi.
Connect – Establece conexión con el servidor de amqp y crea los canales “*” y NOMBREDEEQUIPO_IP
Publish – Manda un mensaje a la cola de amqp (normalmente lleva un evento para el ddi)
Close – Cierra la conexión establecida con amqp
Run – Inicia el bucle de recepción de mensajes.
Stop – Cierra el socket con el que se conecta a amqp para que se pueda cerrar normalmente la conexión
IsRunning – Flag que indica si el bucle de recepción de mensajes está activo.
SetMachineName – Guarda el valor de NOMBREEQUIPO_IP para cuando se conecte se pueda abrir el canal de su mimsmo nombre.
GetMachineName – Devuelve el nombre de NOMBREEQUIPO_IP.
OnRececiveMsg – Método de ayuda llamado desde el bucle de recepción de mensajes. Se encarga de enviar los eventos pertinentes al usuario o al servicio.

Clase CDwPrinterService

Es una clase simple, un objeto COM cuyo único fin es comprobar si un documento se puede imprimir.

PrintJob – Llamado desde el monitor de impresión para comprobar si el documento pasa la validación y así imprimirlo.

Interfaz ISecurityAgent

Es una clase base del módulo principal del servicio (CDrainwareSecurityAgentModule) que exporta unos cuantos métodos para ser llamados desde los objetos COM creados por los clientes. La documentación esta en el apartado de CDrainwareSecurityAgentModule.

Métodos exportados:

	CUserData *AddClient( CDwService *pClient );
	void RemoveClient( CDwService *pClient );
	void PrintJob( PTSTR szDocName, PCTSTR szRawFile, PTSTR szPrinterName, PCTSTR szUserName );
	void SendEvent( const CStringA &strUserName, const CStringA &strEvent, CStringA &strScreenShot, bool bATP = false );
	bool IsAtpProcess( LPCTSTR szProcName );
	void Fire_ScreenShot( const CString &strUserName );
	void Fire_ShowMsg( const CString &strUserName, ULONG nType );

Interfaz IUserNotify

Es una clase base de la clase CUserData que le obliga a implementar los siguientes métodos (documentación en el apartado CUserData):

	virtual void OnUserConfig( const CStringA &strJSON ) = 0;
	virtual void OnGroupChanged( const CStringA &strGroup, const CStringA &strJSON ) = 0;
	virtual const CAtlList< CStringA > &Groups() = 0;

Proxy Stub

Es una dll que se genera en base a un archivo de tipo IDL cuyo fin es poder hacer llamadas de procedimiento remoto a través de COM (rpc a través de DCOM). Los objetos que exporta son IDwService y IDwPrinterService.

Módulo del Shell

La función de este módulo es recibir notificaciones del shell del sistema cuando se vaya a copiar o mover un archivo o varios a otro emplazamiento.

Clase CDrainwareShellExt

Esta clase implementa las interfaces IShellExtInit y IContextMenu requeridas por el shell para poder recibir la notificaciones del mismo. Una vez se hayan recibido las mismas este crea un objeto de tipo IDwService para hacer la comprobación de los archivos que se van a copiar o mover. Además comprueba si el destino va a un directorio mapeado por DropBox o google drive.

CDrainwareShellExt – Constructor de la clase donde se cargan los posibles directorios de DropBox y google drive.
Initialize – Método llamado desde el shell cuando se está a punto de realizar una operación para mover o copiar un archivo. Aquí es donde se crea el objeto IDwService para realizar las comprobaciones. En caso que haya información relevante impide la copia o traslado de archivos.
IsInetFolder – Método de ayuda que determina si el destino ese una unidad de red o un directorio de google drive o DropBox.
CheckItem – Función especializada para verificar un determinado archivo. En caso de que sea un directorio se verificará cada uno de los archivos y directorios que contiene.
IsUSB – Función que determina si el destino es una unidad externa usb.
IsDrive – Función de ayuda para saber si un path es de una unidad de tipo C:\, D:\ etc.
IsDirectory – Comprueba si una ruta es un directorio
LoadFile – Función de ayuda que carga un archivo en memoria. Usado para cargar la configuración de DropBox.

Clase CWaitForCheck

Implementa una caja de diálogo que muestra una barra de progreso mientras se está verificando el o los archivos de la operación

Módulo de usuario (DwUserAgent.exe)

Esta es una aplicación que se ejecuta por cada usuario que se conecta al equipo. Esta aplicación al iniciarse crea una instancia al objeto IDwService para mantener comunicación con el servicio. Además tiene la función de mostrar los mensajes de bloqueos, alertas o logs del servicio al usuario.

Su objetivo principal es monitorizar el portapapeles (texto e imagen), el teclado y las unidades externas de tipo usb.

Clase CWndUserAgent

Esta clase es una ventana oculta que monitoriza el portapapeles, teclado y unidades usb.

OnCreate – Responde al mensaje de windows cuando se crea la ventana y en él se crea la instancia al objeto IDwService al que se le indica que monitorice el proceso y notifique eventos del servicio. Además se hace una comprobación de la licencia y se inician las clases que gestionan el teclado y las unidades usb.
OnDestroy – Libera la instancia al objeto IDwService
OnChangeCBChain – Implientación del mensaje de windows WM_CHANGECBCHAIN para poder establecer un visor de los cambios del portapapeles.
OnDrawClipboard – Notificación de windows indicando que el contenido del portapapeles ha cambiado. Ver CheckClipboard.
OnDeviceChange – Notificación de windows indicando que hay un nuevo dispositivo conectado o que se acaba de desconectar. En caso de que se haya instalado un dispositivo usb se pasa monitorizar el mismo.
OnClose – Evento del servicio indicando que se va a parar, por lo que hay que terminar la ejecución.
OnShowTrayWindow – Evento del servicio para que se muestre un mensaje al usuario.
OnGetScreenShot – Evento del servicio requiriendo que se le envíe un screenshot.
ShowMessage – Encargado de mostrar un mensaje al usuario, llamdo desde OnShowTrayWindow.
ThreadOCR – Hilo que se crea para pasar el OCR a una imagen y no parar el proceso para que se pueda continuar monitorizando correctamente los demás dispositivos (teclado, usb, portapapeles)
CheckClipboard – Comprueba el contenido del portapapeles. En caso de texto se envía el mismo al servicio para su comprobación; y en caso de imagen se extrae el texto con ayuda del OCR para a continuación enviarlo al servicio para su comprobación. En caso de que haya dado positivo se eliminará el contenido del mismo.
CheckOCR – Es el método que se ocupa de extraer el texto de una imagen dada.
CheckBitmap – Método de ayuda que escribe un bitmap a disco para ser leído por el OCR.
IsUSB – Método de ayuda para saber si una unidad es de tipo USB.
LoadUsbWatchers – Método que se encarga de crear un objeto para cada unidad usb que monitoriza el mismo.
ReleaseService – Para las notificaciones recibidas del servicio, elimina la instancia del objeto IDwService y para el keylogger.
RemoveDrive – Método especializado que para la monitorización de una unidad cuando se ha desconectado
GetJpegStream – Método de ayuda que crea una image jpeg en memoria.
GetScreenShot – Método de ayuda que obtiene un screenshot y lo deja en memoria.

Clase CDriveWatcher

Esta clase se especializa en la monitorización de un dispositivo USB. Notifica sobre la creación o sobreescritura de un archivo.

CDriveWatcher – Constructor de la clase que crea un hilo de monitorización.
ThreadWatch – Hilo de monitorización.
DoWatch – Llamado desde el hilo de monitorización que abre la unidad ver los cambios en la misma.
Destroy – Para el hilo de monitorización.
DriveChanged – Método de callback llamado por windows cuando hay cambios en la unidad. Genera un evento OnDirChanged.
OnDirChanged – Llamado cuando se detectan cambios. A su vez llama al objecto del Servicio IDwService para que compruebe el archivo. En caso de que el resultado sea positivo elimina el archivo de la unidad externa.

Clase CKeyLogger

Hace una monitorización del teclado para comprobar el texto escrito cada vez que se pulse la tecla Enter, Tab o se pulse un botón del ratón.

ThreadWatch – Hilo de monitorización del teclado.
DoWatch – Metódo que se llama desde ThreadWatch que está constantemente viendo el estado del teclado Generando un evento OnKeyEvent cuando cambia.
Start – Inicia el hilo de monitorización
Stop – Para el hilo de monitorización
OnKeyEvent – Evento llamado desde el hilo de monitorización. Asigna un carácter a la ventana activa en cada momento. Una vez que se pulse Enter, Tab o Botón izquierdo del ratón hace una comprobación del texto enviándolo al Servicio.
GetKeysStates – Función de ayuda para obtener el estado de todas las teclas del teclado.
IsValidChar – Función de ayuda para desechar teclas no válidas, solo alfanuméricos.

Clase CLicenseDlg

Caja de diálogo para obtener la licencia por parte del usuario.

Clase CTrayWindow

Esta clase es una ventana para mostrar mensajes al usuario que se mostrará en la parte inferior derecha de la pantalla.

OnCreate – Carga las imágenes de fondo
OnDestroy – Libera las imágenes cargadas y para el timer de windows.
OnPaint – Mensaje enviado por windows para dibujar la ventana. En este caso se muestra un icono acorde al mensaje mostrado, que puede ser Error, Warning o Information.
OnShowTrayMsg – Notificación recibida desde la ventana principal y a su vez desde el servicio para mostrar un mensaje. Guarda el mensaje y el tipo de icono a mostrar y a continuación inicia un timer de windows para mostrar la ventana haciendo un efecto de transparente a solido y moviendo la ventana de abajo arriba.
TimerProc – Función llamada por windows cada cierto lapso de tiempo. Usado para simular la animación de la ventana.
Init – Posiciona la ventana según el tamaño de la pantalla para iniciar una aparición del mensaje.
OnTimer – Donde se hace el efecto de movimiento y transparencia del mensaje al mostrarse u ocultarse.
FillSolidRect – Función de ayuda para rellenar un rectángulo con un color dado.
DrawBorder – Dibuja un borde de un ancho específico.

Módulo de Impresora

Este módulo implementa una interfaz llamada desde windows para recibir notificaciones cada vez que se envía un trabajo a la impresora.

DllMain – Punto de entrada de una dll windows donde se inicializa la monitorización de la impresora.
InitializePrintMonitor2 – Función exportada para que windows obtenga los punteros a las funciones callback a las que llamará cuando haya trabajos de impresora.

Clase CPrinterMonitor

Esta clase tiene las funciones que serán llamadas desde el servicio de impresión de windows.

EnumPorts – Devuelve una estructura con los puertos soportados por el monitor. En este caso “DwPort”
OpenPort – Llamado por windows para crear un puerto para la impresión del documento.
StartDocPort – Llamado por windows cuando se inicia la impresión de un trabajo. Pasando información sobre el identificador de trabajo, nombre de impresora, etc…
WritePort – Nos llegan los datos en bruto que se deberían enviar a la impresora, pero que aquí se analizarán previamente. Se delega en el método WritePort de la clase CPrinterPort.
EndDocPort – Llamado por windows para indicar que el trabajo se ha finalizado.
ClosePort – Llamado por windows para cerrar el puerto y podamos liberar la memoria relacionada con el mismo
LoadDefaultPorts – Método de inicialización que carga los puertos asignados por defecto a la impresora y los guarda para restaurar más tarde.
RestoreDefaultPorts – Una vez se para el servicio restauran los puertos antiguos.
SetDwPorts – Establece el puerto “DwPort” en todas las impresoras.
InitThreadWatch – Crea una instancia al objeto IDwService y crea un hilo para monitorizar que no se cambie el puerto DwPort por parte del usuario.
CloseThreadWatch – Para el hilo de monitorización del puerto y libera el objecto IDwService.
ThreadWatch – Hilo que está constantemente asegurándose de que el puerto sea DwPort y comprueba si hay disponibles documentos para su impresión.
PrintFile – Establece el puerto antiguo de una impresora y envía el documento para su impresión desde el servicio con credenciales del usuario que lo creó, en caso de estar limpio.
PrintFiles – LLamado desde el hilo ThreadWatch para comprobar si hay impresiones pendientes de todos los usuarios y enviarlos a PrintFile.

Las siguiente funciones se han implementado para cumplir con las especificaciones de windows para el monitor de impresión, la mayoría se limita a devolver TRUE. Ver código:

ReadPort, AddPort, AddPortEx, ConfigurePort, DeletePort, GetPrinterDataFromPort, SetPortTimeOuts, XcvOpenPort, XcvDataPort, XcvClosePort, Shutdown, SendRecvBidiDataFromPort, AddPortUI, ConfigurePortUI y DeletePortUI.

Clase CPrinterPort

Esta clase es la que se ocupa de guardar los datos que se envían a la impresora para su posterior análisis.

CreatePort – Llamado por windows. Se encarga de crear una nueva clase de tipo CPrinterPort que se vinculará al documento que se va a imprimir.
ClosePort – Llamado por windows cuando se ha finalizado el trabajo. Libera la clase CPrinterPort creada en la función CreatePort.
StartDoc – Se inicia un trabajo desde windows. La función guarda los datos del documento, nombre de usuario, JobID y nombre de impresora. Ademá crea el archivo donde se guardarán los datos para analizar posteriormente.
EndDoc – El trabajo ha finalizado y se guarda para que sea enviado al servicio para su análisis y posterior impresión.
Write – Llamado por windows con datos que vamos guardando en un archivo para su posterior análisis.
Abort – Se ha parado la impresión por parte del usuario; eliminamos el archivo que guardaba los datos.

Módulo DwLib

Contiene funciones de ayuda que se usan en los demás módulos.

Clase CAutoCS

Esta clase usa para adquirir y liberar secciones críticas en ámbitos de C++.

CAutoCS – Constructor, se le pasa la sección crítica a adquirir.
~CAutoCS – Destructor, se libera la sección crítica.

Funciones globales

GetModuleDirectory – Obtiene el directorio del ejecutable del proceso actual.
GetTempPath – Obtiene el directorio temporal de windows.
RunProcess – Ejecuta un proceso
RunProcessAsUser – Ejecuta un proceso con credenciales de usuario
DwBase64Decode – Decodifica una cadena Base64 a una cadena normal.
DwBase64Encode – Codifica una cadena a Base64
FileExist – Comprueba si existe un archivo.

Módulo SandBoxLoader

Se carga con cada proceso que tenga dependencias de user32.dll. Desde ahí una vez cargada, pregunta al servicio si hay que monitorizar el proceso.

Funciones

DllMain – En la inicialización llama a la función LoadSandBox.
LoadSandBox – Crea una instancia del objeto IDwService para preguntar si hay que monitorizar el proceso actual. En caso afirmativo se carga DrainwareSandbox(32/64).dll para monitorizar el proceso.

Módulo DrainwareSandbox(32/64)

Funciones

DllMain – Al inicializar la dll se crea el hilo que monitorizará el proceso actual.
HeapLocker – Hilo que monitoriza el proceso. Carga la configuración del registro (SOFTWARE\\Drainware\\SecurityEndpoint\\Sandbox) y a continuación crea varios hilos con los distintos tipos de protección, ProtectAddresses, MonitorNewPagesForNOPSleds, MonitorPrivateUsage, MonitorNewPagesToSearchThem.
MonitorNewPagesForNOPSleds – Inicializa la detección de NOPS y cada segundo analiza que no haya nuevas páginas con NOPS.
AnalyzeNewPagesForNOPSleds – Busca en todo el espacio de direcciones del proceso por la cantidad mínima de operaciones NOP para considerar que se está realizando un ataque.
MonitorPrivateUsage – Hilo que comprueba el uso privado de memoria cada segundo. En caso de que se exceda el tamaño al asignado en configuración lo considera un ataque.
MonitorNewPagesToSearchThem – Hilo que comprueba cada segundo si en el espacio de direcciones de memoria del proceso hay coincidencias con de ciertas cadenas de bytes con las establecidas en la configuración y consideradas potencialmente peligrosas.
ThreadedMessageBox – Es llamada desde los hilos que monitorizan el proceso en caso de que haya algún problema y muestra una caja de diálogo con un mensaje advirtiendo al usuario.
DisplayMessageBox – Hilo que crea una instancia al objeto IDwService para notificar lo que ha ocurrido y así generar un evento para enviar al DDI. Además muestra el mensaje de advertencia al usuario. En caso de que la configuración así lo determine el proceso será finalizado.
ProtectAddresses – Protege las direcciones que se encuentran en la configuración en el apartado Addresses prohibiendo el acceso a las mismas y evitando ShellCodes.