
Un outil de réimplémentation de DTrace sur Windows
Le traceur de Steve. Une réimplémentation du hook d'appels système de DTrace sur Windows. Considérez cela comme un hook SSDT compatible PatchGuard, mais sans bidouilles. Cela ne prend pas en charge SSSDT (API win32k), car les API d'appel système DTrace elles-mêmes ne prennent pas en charge cette table supplémentaire. Les API noyau Zw* peuvent être tracées en plus de tous les appels système SSDT en mode utilisateur.
Veuillez lire ce readme jusqu'au bout si vous développez de nouveaux plugins pour STrace !
DTrace sur Windows prend en charge plusieurs types de sondes. Cela inclut syscall, fbt, etw, profile, et peut-être d'autres. Cette réimplémentation ne réimplémente que les types de sondes syscall et etw. Tous les autres types de sondes sont considérés comme totalement hors du cadre de ce projet et ne seront jamais pris en charge. N'hésitez pas à forker le projet si vous souhaitez ajouter des types de sondes supplémentaires. Le périmètre a été limité aux seules sondes syscall et etw en raison de la complexité des autres types de sondes et des systèmes qu'ils touchent.
Cette réimplémentation abandonne complètement le langage de script D (notez : PAS DLang, le langage moderne plus populaire). La complexité d'une VM dans le noyau, comme dans l'implémentation DTrace d'origine, ne convient pas à ce projet. Au lieu de cela, cette implémentation expose directement les callbacks C pertinents nécessaires pour se brancher sur les interfaces noyau Windows de DTrace. Pour permettre le 'hot-loading' de scripts, un système de plugins basé sur des DLL a été utilisé en remplacement de l'environnement VM + scripting du dtrace d'origine. Ce système de plugins accepte une DLL 'normale' en mode utilisateur, sans aucun contrôle de sécurité activé ni dépendances externes, et la mappe manuellement dans l'espace d'adressage du noyau. La plugin dll possède des exports qui sont invoqués lorsque des callbacks d'appels système noyau se produisent. Les API noyau sont résolues via la table d'importation (IAT) normale de la DLL ; les DLL plugins se lient à ntoskrnl.lib, puis le pilote résout ces API au moment du chargement, permettant ainsi d'appeler normalement n'importe quelle API système dans les DLL plugins. Les performances de ce système de plugins sont excellentes, car du code natif, plutôt qu'un interpréteur de scripts ou un JIT, s'exécute directement entre ENTRY et RETURN de l'appel système. Cette conception améliore les performances par rapport à l'implémentation dtrace fournie par Microsoft.
La définition de hooks est très simple : vous disposez d'une routine pour enregistrer/désenregistrer un hook par nom d'API, avec un callback avant et après l'appel système. Les callbacks disposent d'arguments et de valeurs de retour accessibles en lecture seule. Les valeurs de retour peuvent être usurpées dans les sondes de retour et les arguments peuvent être modifiés dans les sondes d'entrée, mais l'appel système d'origine ne peut normalement pas remplacer ou 'annuler' un appel système - cette API agit comme un observateur. Il existe cependant une faille similaire à celle documentée dans (https://github.com/everdox/InfinityHook et https://github.com/everdox/InfinityHook/raw/master/resources/perf.png), qui permet de remplacer le pointeur d'appel système sur la pile. Avec cette faille, il est possible de remplacer complètement un appel système par un pointeur vers une routine que vous contrôlez. Lorsque des événements se produisent et que votre callback de hook se déclenche, tout ce que vous souhaitez peut être fait. Les callbacks sont synchrones, ce qui signifie que si vous retardez l'exécution dans le callback d'entrée, par exemple en restant dans une boucle while, l'appel système sera retardé de cette durée. L'exécution de l'appel système se produit juste après le retour du callback d'entrée, et juste avant l'entrée du callback de retour. Ce système est entièrement compatible PatchGuard ; cependant, DSE doit être désactivé, car Microsoft considère malheureusement ce type d'extension de noyau comme faisant partie du noyau NT et valide donc que le signataire racine est Windows. Cela ne fonctionne pas avec des astuces comme l'activation de signataires de noyau personnalisés ; DSE doit vraiment être désactivé pendant le démarrage du noyau.
ValidationFlags=IMGP_LATEST_MS_ROOT_REQUIRED | IMGP_WINDOWS_ROOT_REQUIRED | IMGP_MS_SIGNATURE_REQUIRED
Scenario=ImgSigningScenarioWindows
Le pilote Rust abandonne le système de plugins basé sur des DLL utilisé par le pilote C++ et tente plutôt d'utiliser un interpréteur web assembly pour héberger des scripts wasm dans le noyau Windows. Ceci afin d'être plus similaire à l'implémentation dtrace d'origine, qui utilise une VM, mais avec un meilleur langage que DLang. Cela offre le sandboxing et d'autres avantages intéressants. La POC est complète et fonctionne, mais elle n'est malheureusement pas utilisable en raison de problèmes de performances liés à l'interprétation du WASM avec WASMI. Un moteur wasm basé sur JIT compatible avec le noyau NT serait nécessaire pour que cette conception alternative soit viable. Il est inclus comme une nouveauté amusante et pourrait être utilisable pour autre chose avec un peu de travail.
Ce projet est en grande partie divisé entre ses composants C++ et Rust. Le pilote C est complet sur le plan fonctionnel et doit être privilégié. Dans les grandes lignes, le projet comprend les composants suivants
Configurer Visual Studio avec le DDK
Compilez le pilote et la cli, déplacez les fichiers dans le même dossier que le script, puis exécutez le script powershell dans le dossier d'installation en tant qu'administrateur :
./install_as_admin.ps1
Redémarrez, puis sélectionnez l'entrée de démarrage STrace et appuyez sur F8 (pas Entrée !) sur cet écran :

Cela devrait afficher cet écran ; sélectionnez le démarrage avec DSE désactivé :

Après un démarrage réussi, la CLI peut être utilisée pour charger et décharger les DLL plugins afin de commencer le tracing. Deux exemples de plugins sont fournis. Lisez les détails ci-dessous si vous rencontrez des problèmes. Vous devrez peut-être redémarrer à nouveau la première fois et potentiellement définir manuellement le service STrace pour qu'il démarre automatiquement at boot à l'aide d'un outil tel que process hacker.