
A DTrace on Windows Reimplementation
El rastreador de Steve. Una reimplementación del hook de llamadas al sistema de DTrace en Windows. Piense en esto como un hook de SSDT compatible con PatchGuard, pero sin trucos. No admite SSSDT (apis de win32k), ya que las propias API de llamadas al sistema de DTrace no admiten esta tabla adicional. Las apis del kernel Zw* se pueden rastrear además de todas las syscalls de SSDT en modo usuario.
Por favor, lea hasta el final de este readme si está desarrollando nuevos plugins para STrace.
Dtrace en Windows admite múltiples tipos de sondas. Estos incluyen syscall, fbt, etw, profile, y quizás más. Esta reimplementación solo reimplementa los tipos de sonda syscall y etw. Todos los demás tipos de sonda se consideran completamente fuera del alcance de este proyecto y nunca serán compatibles. Siéntase libre de hacer un fork del proyecto si desea agregar tipos de sonda adicionales. El alcance se limitó solo a las sondas syscall y etw debido a la complejidad de los otros tipos de sonda y los sistemas que tocan.
Esta reimplementación descarta por completo el lenguaje de scripting D (nota: NO DLang, el lenguaje moderno más popular). La complejidad de una VM en el kernel como la implementación original de DTrace no es adecuada para este proyecto. En su lugar, esta implementación expone directamente los callbacks de C relevantes necesarios para conectarse a las interfaces del kernel de DTrace de Windows. Para habilitar la 'carga en caliente' de scripts, se utilizó un sistema de plugins basado en DLL como reemplazo de la VM + entorno de scripting del dtrace original. Este sistema de plugins acepta una DLL de modo usuario 'normal' sin ninguna verificación de seguridad habilitada, ni dependencias externas, y la mapea manualmente en el espacio de direcciones del kernel. La plugin dll tiene exportaciones que se invocan cuando ocurren callbacks de syscall del kernel. Las APIs del kernel se resuelven mediante la tabla de importación normal (IAT) de la DLL; los plugins DLL enlazan con ntoskrnl.lib y luego el driver resolverá estas APIs en tiempo de carga, permitiendo que se llame a cualquier api del sistema dentro de los plugins DLL con normalidad. El rendimiento de este sistema de plugins es excelente, ya que el código nativo, en lugar de un intérprete de scripts o un JIT, se ejecuta directamente entre ENTRY y RETURN de la syscall. Este diseño mejora el rendimiento en comparación con la implementación de dtrace proporcionada por Microsoft.
Establecer hooks es muy simple: se obtiene una rutina para registrar/desregistrar un hook por nombre de api, con un callback pre y post syscall. Los callbacks tienen argumentos y valores de retorno accesibles como valores de solo lectura. Los valores de retorno se pueden falsear en las sondas de retorno y los argumentos se pueden modificar en las sondas de entrada, pero la syscall original normalmente no puede reemplazar o 'cancelar' una syscall: esta API actúa como un observador. Sin embargo, existe una supervisión similar a la documentada en (https://github.com/everdox/InfinityHook y https://github.com/everdox/InfinityHook/raw/master/resources/perf.png) que permite reemplazar el puntero de syscall en la pila. Con esta supervisión, es posible reemplazar por completo una syscall con un puntero a una rutina que usted controle. Cuando ocurren eventos y su callback de hook se dispara, puede hacer lo que desee. Los callbacks son síncronos, lo que significa que si retrasa la ejecución en el callback de entrada, por ejemplo sentándose en un bucle while, la llamada a la syscall se retrasará esa cantidad de tiempo. La ejecución de la llamada al sistema ocurre justo después del retorno del callback de entrada y justo antes de la entrada del callback de retorno. Este sistema es totalmente compatible con PatchGuard; sin embargo, DSE debe estar deshabilitado, ya que Microsoft desafortunadamente considera este tipo de extensión del kernel como parte del kernel de NT y, por lo tanto, valida que el firmante raíz sea Windows. Esto no funciona con trucos como habilitar firmantes de kernel personalizados; DSE realmente debe estar desactivado durante el arranque del kernel.
ValidationFlags=IMGP_LATEST_MS_ROOT_REQUIRED | IMGP_WINDOWS_ROOT_REQUIRED | IMGP_MS_SIGNATURE_REQUIRED
Scenario=ImgSigningScenarioWindows
El driver de Rust descarta el sistema de plugins basado en DLL utilizado por el driver de C++ e intenta usar un intérprete de web assembly para alojar scripts wasm en el kernel de Windows en su lugar. Esto es para ser más similar a la implementación original de dtrace que usa una VM, pero con un lenguaje mejor que DLang. Esto proporciona sandboxing y otros beneficios agradables. El POC está completo y funciona, pero desafortunadamente no es utilizable debido a problemas de rendimiento al interpretar WASM con WASMI. Se requeriría un motor wasm basado en JIT compatible con el kernel de NT para que este diseño alternativo sea viable. Se incluye como una novedad divertida, y podría ser útil para otra cosa con algo de trabajo.
Este proyecto está dividido en gran medida entre sus componentes de C++ y Rust. El driver de C++ está completo en funcionalidad y debe preferirse. A alto nivel, el proyecto tiene los siguientes componentes
Configurar Visual Studio con DDK
Compile el driver y la cli, mueva los archivos a la misma carpeta que el script, y luego ejecute el script de powershell en la carpeta de instalación como administrador:
./install_as_admin.ps1
Reinicie, luego seleccione la entrada de arranque STrace, y presione F8 (¡no Enter!) en esta pantalla:

Eso debería mostrar esta pantalla, seleccione arrancar con DSE deshabilitado:

Después de un arranque exitoso, la CLI se puede usar para cargar y descargar plugins DLL para comenzar el rastreo. Se proporcionan dos plugins de ejemplo. Lea los detalles a continuación en detalle si tiene problemas. Es posible que necesite reiniciar nuevamente la primera vez y, potencialmente, configurar manualmente el servicio STrace para que se inicie automáticamente al arrancar usando una herramienta como process hacker.
La instalación original de DTrace está aquí: https://techcommunity.microsoft.com/t5/windows-kernel-internals/dtrace-on-windows-20h1-updates/ba-p/1127929. El DTrace original requiere que se configuren Secure Boot y Virtualized Based Security; este no es el caso con STrace, ya que no implementa los tipos de sonda (FBT) que requieren esas características.
Este proyecto realiza las mismas operaciones que el instalador, pero mediante un simple script de powershell en lugar de un MSI. El proceso es simple. Primero copie una dll de apiset a system32 para que se active la extensión del kernel. Luego instale una entrada de driver para que el main del driver se ejecute al inicio del sistema para las comunicaciones en modo usuario. Las dlls de ApiSet están firmadas digitalmente, por lo que se usó el apiset original de Microsoft, como se requiere. Este archivo se proporciona solo en forma binaria y no contiene lógica más que apuntar la importación de la extensión al driver que la implementa: ext-ms-win-ntos-trace-l1-1-0 -> dtrace.sys. Vea https://www.geoffchappell.com/studies/windows/win32/apisetschema/index.htm (ApiSetSchemaExtensions) para obtener detalles sobre este mecanismo.
STrace se carga muy temprano durante la inicialización del kernel; habilitar Test Signing en la base de datos de configuración de arranque (BCD) no es suficiente. La aplicación de firma de controladores (DSE) debe estar deshabilitada para que STrace se cargue correctamente, y esto debe hacerse manualmente en cada arranque. Para facilitar esto, el script de instalación crea una entrada fácil en el menú de arranque para que el usuario la seleccione. No hay ninguna marca de BCD que permita deshabilitar DSE permanentemente entre reinicios; el kernel lo prohíbe específicamente.
Olvidar deshabilitar DSE en el arranque le conseguirá un viaje al menú de Reparación automática al reiniciar. Puede intentarlo de nuevo sin riesgo; si el arranque continúa fallando, el driver de STrace deberá eliminarse manualmente de la carpeta de drivers. Tenga en cuenta que las fallas de arranque pueden hacer que Windows deshabilite el indicador de ejecución automática del servicio STrace*; es posible que deba volver a configurarlo como ejecución automática si ocurre una falla de arranque en algún momento.
Para desarrollar sus propios plugins, es mejor usar uno de los plugins existentes como proyecto base. Los proyectos de Visual Studio están configurados con muchos ajustes muy específicos para generar binarios independientes sin dependencias. Los ajustes no predeterminados son demasiados para enumerarlos, así que simplemente copie uno de los proyectos y modifique el código para agregar su propia lógica en su lugar (https://stackoverflow.com/questions/884255/visual-studio-copy-project). Si crea un plugin útil, por favor envíe un PR ! Cuantos más plugins se creen, más útil será este sistema para todos.