Gestion de l'alimentation sous Windows. Gestion de l'alimentation dans Windows Terminer le cours

Pilotes en mode noyau : Partie 1 : Concepts - WASM.RU Archive

Présentation de l'architecture

Le monde intérieur de Windows 2000 est divisé en deux parties aux limites clairement définies, à la fois en termes d'espace d'adressage et en termes de droits et responsabilités du code dans cet espace d'adressage de l'exécuteur.

Avec la division de l'espace d'adressage, tout est étonnamment simple. Tous les quatre, disponibles dans une architecture 32 bits, les gigaoctets sont divisés en deux parties égales (j'omet le réglage de RAM 4GT et l'extension d'adresse physique comme exotiques). La moitié inférieure est dédiée aux processus en mode utilisateur, la moitié supérieure appartient au noyau.

La séparation des droits et des responsabilités est un peu plus compliquée.

Les processus utilisateur incluent les processus suivants :

  • Processus de prise en charge du système - par exemple, le processus d'ouverture de session Winlogon (implémenté dans \% SystemRoot% \ System32 \ Winlogon.exe) ;
  • Processus de service - par exemple, un spouleur d'impression ;
  • Applications utilisateur - il existe cinq types : Win32, Windows 3.1, MS-DOS, POSIX et OS/2 ;
  • Sous-systèmes d'environnement - trois sous-systèmes d'environnement sont pris en charge : Win32 (implémenté dans \% SystemRoot% \ System32 \ Csrss.exe), POSIX (implémenté dans \% SystemRoot% \ System32 \ Psxss.exe), OS/2 (implémenté dans \% SystemRoot %\System32\os2ss.exe).

Le noyau se compose des éléments suivants :

    Système exécutif (Executive) - gestion de la mémoire, processus et threads, etc. ;
  • Noyau - planification des threads, répartition des interruptions et des exceptions, etc. (implémenté dans \% SystemRoot% \ System32 \ Ntoskrnl.exe);
  • Pilotes de périphériques — pilotes de périphériques matériels, pilotes de réseau, pilotes de système de fichiers ;
  • Couche d'abstraction matérielle (HAL) - isole les trois composants ci-dessus des différences entre les architectures matérielles (implémentées dans \% SystemRoot% \ System32 \ Hal.dll) ;
  • Système de fenêtrage et graphique - Fonctions d'interface utilisateur graphique (GUI) (implémentées dans \% SystemRoot% \ System32 \ Win32k.sys).

Riz. 1-1. Architecture Windows 2000 simplifiée

Mode utilisateur et mode noyau

Bien que la famille de processeurs Intel x86 prenne en charge quatre niveaux de privilège (appelés anneaux de sécurité), Windows n'en utilise que deux : 0 pour le mode noyau et 3 pour le mode utilisateur. Cela est dû à la prise en charge d'autres processeurs (alpha, mips), qui n'ont que deux niveaux de privilèges. Les versions précédentes de Windows NT prenaient en charge ces architectures, mais Windows 2000 ne conservait que la prise en charge x86.

Les composants en mode utilisateur ont leurs propres espaces d'adressage protégés, les threads de ces processus s'exécutent en mode processeur non privilégié (appelé mode utilisateur), ne peuvent pas exécuter de commandes de processeur privilégié, ont un accès limité et indirect aux données système et à l'espace d'adressage système, ne ne pas avoir d'accès direct au matériel... Certes, au cours de leur travail, les threads de ces processus, appelant des services système, passent en mode noyau, mais dans ce cas, ils perdent complètement le contrôle de leur exécution jusqu'à ce qu'ils reviennent en mode utilisateur.

Les processus en mode utilisateur sont considérés comme potentiellement dangereux du point de vue de la stabilité du système. Leurs droits sont limités. Et toutes les tentatives pour aller au-delà de ces restrictions sont strictement réprimées.

Les composants du noyau partagent un espace d'adressage unique, s'exécutent en mode processeur privilégié (appelé mode noyau), peuvent exécuter toutes les commandes de processeur, y compris privilégiées, ont un accès direct et illimité aux données et au code système, ont un accès direct ou via HAL à l'équipement.

Le code du noyau (en fait, c'est le système lui-même) est considéré comme totalement fiable. Par conséquent, étant chargé dans l'espace d'adressage du système, le pilote fait partie du système et n'est soumis à aucune restriction.

Ainsi, les applications utilisateur sont séparées du système d'exploitation réel. Si vous envisagez d'écrire une application sérieuse nécessitant un accès aux fonctions internes ou aux structures de données du système, vous serez confronté à de nombreuses limitations qui ne peuvent être surmontées qu'en plaçant votre code dans l'espace d'adressage du système. La seule façon documentée de le faire est d'installer un pilote de périphérique. Cette méthode est relativement simple, fiable et, surtout, entièrement prise en charge par le système d'exploitation lui-même.

Pilotes Windows 2000

Windows 2000 prend en charge de nombreux types de pilotes de périphérique.

Il y en a deux de base qui ont leurs représentants :

  • Pilotes en mode utilisateur :
    • Pilotes de périphériques virtuels (VDD) - utilisés pour prendre en charge les programmes MS-DOS (à ne pas confondre avec les pilotes VxD sous Windows 95/98 - ce sont des choses complètement différentes, bien qu'ils portent le même nom) ;
    • Pilotes d'imprimante
  • Pilotes en mode noyau :
    • Pilotes de système de fichiers - implémentez les E/S sur les lecteurs locaux et réseau ;
    • Pilotes hérités - écrits pour les versions précédentes de Windows NT ;
    • Pilotes pour adaptateurs vidéo (pilotes vidéo) - implémenter des opérations graphiques ;
    • Pilotes de streaming - implémentez l'entrée/sortie vidéo et audio ;
    • Pilotes WDM (Windows Driver Model, WDM) - Prend en charge la technologie Plag and Play et la gestion de l'alimentation. Leur particularité est la compatibilité du code source entre Windows 98, Windows ME et Windows 2000.

Dans différentes sources, vous pouvez trouver une classification légèrement différente de celle ci-dessus, ce n'est pas la question. L'important est que les pilotes que nous écrirons ne relèvent d'aucun des points de ce classement. Il ne s'agit ni de pilotes de système de fichiers, ni de pilotes hérités, ni de pilotes pour adaptateurs vidéo ou cartes son, ni de pilotes WDM. ne prennent pas en charge la lecture et la gestion de l'alimentation Plag "n". Ce ne sont pas des pilotes en mode utilisateur (pas intéressant du tout). En fait, c'est juste que le diable sait ce que c'est, tk. le système lui-même vous permet de s'ajouter facilement et simplement du code pour un appareil incompréhensible, et de faire ce que vous voulez avec ! C'est comme si un parfait inconnu frappait à votre porte la nuit, et sans dire un mot, vous le laissiez entrer pour la nuit, et même le mettriez dans votre lit ! Cependant, ce n'est pas une sorte de bogue ou de trou de sécurité. Le système fonctionne comme il fonctionne. Il ne peut en être autrement, puisque en interaction avec l'environnement, le système est obligé de s'ouvrir à lui-même. Et s'il n'en était pas ainsi, ce serait un système complètement fermé, c'est-à-dire inutile.

Comme son nom l'indique, un pilote de périphérique est un programme conçu pour contrôler un périphérique, et ce périphérique n'a pas besoin d'être physique. Il peut être logique ou, comme dans notre cas, virtuel.

La structure d'un pilote de périphérique n'est rien de plus qu'un fichier au format Portable Executable (PE). Identique aux exe et dll normaux. Il se charge et fonctionne uniquement selon des règles différentes. Les pilotes peuvent être considérés comme des DLL en mode noyau conçues pour effectuer des tâches qui ne peuvent pas être résolues en mode utilisateur. La différence fondamentale ici (hormis le niveau de privilège) est que nous ne pourrons pas accéder directement au pilote, ni à son code, ni à ses données, mais nous utiliserons un mécanisme spécial fourni par le Input/Output Manager. Le gestionnaire d'E/S fournit un environnement permettant aux pilotes de fonctionner et fournit également des mécanismes de chargement, de déchargement et de gestion.

Lorsque vous commencerez à développer des pilotes en mode noyau, vous vous sentirez comme un novice complet. toute expérience précédente d'utilisation de l'API n'aidera pas ici - le noyau fournit un ensemble de fonctions complètement différent. Vous devrez également utiliser des fonctions et des structures de données mal documentées (définies uniquement dans les fichiers d'en-tête) ou totalement non documentées.

Pilotes à un et plusieurs niveaux

La plupart des pilotes de contrôle de périphérique physique sont des pilotes en couches. Le traitement d'une demande d'E/S est partagé entre plusieurs pilotes. Chacun fait sa part. Par exemple, une demande de lecture d'un fichier est transmise au pilote du système de fichiers qui, après avoir effectué certaines opérations (par exemple, fractionner la demande en plusieurs parties), la transmet au pilote de disque qui, à son tour, envoie le demande au chauffeur de bus. De plus, entre ces pilotes, vous pouvez ajouter n'importe quel nombre de pilotes de filtre (par exemple, chiffrer des données). Après avoir exécuté la requête, le pilote de niveau inférieur transmet ses résultats "en haut" au pilote de niveau supérieur. Mais, heureusement, tout sera beaucoup plus facile avec nous. Nos pilotes seront toujours des pilotes monolithiques, ce qui simplifiera grandement l'ensemble du processus d'écriture et de débogage.

Contexte du flux

Comme, dans la plupart des cas, nous n'avons qu'un seul processeur, et qu'il y a beaucoup d'applications à exécuter, il est naturel que pour créer l'illusion de leur exécution simultanée, ces applications doivent être séquentiellement connectées au processeur, et très vite. Cette procédure est appelée changement de contexte de thread. Si le système change le contexte des threads appartenant au même processus, il est alors nécessaire d'enregistrer la valeur des registres du processeur du thread déconnecté et de charger les valeurs précédemment enregistrées des registres du processeur du thread connecté. Et mettre à jour certaines structures de données. Si le fil à connecter appartient à un autre processus, alors il est nécessaire de charger un pointeur vers le répertoire de pages du processus dans le registre CR3 du processeur. Étant donné que chaque processus utilisateur dispose d'un espace d'adressage privé, différents processus ont différentes projections d'espaces d'adressage, ce qui signifie qu'ils ont des répertoires de pages et des ensembles de tables de pages différents selon lesquels le processeur traduit les adresses virtuelles en adresses physiques. Tout cela n'est pas directement lié à la programmation du pilote. Mais je vous le rappelle à propos de ce qui suit. Étant donné que le changement de contexte n'est pas l'opération la plus rapide, les pilotes, pour des raisons de meilleures performances, ne créent généralement pas leurs propres threads. Mais le code du pilote doit encore être exécuté. Par conséquent, pour gagner du temps lors du changement de contexte, les pilotes sont exécutés en mode noyau dans l'un des trois contextes suivants :

  • dans le contexte du thread utilisateur qui a initié la demande d'E/S ;
  • dans le cadre d'un thread système en mode noyau (ces threads appartiennent au processus System) ;
  • à la suite d'une interruption (et donc pas dans le contexte d'un processus ou d'un thread en cours au moment de l'interruption).

Je ne comprends pas très bien comment vous pouvez faire quelque chose "pas dans le contexte d'un processus ou d'un flux", mais compte tenu de l'autorité des personnes qui l'ont écrit (D. Solomon et M. Russinovich), et aussi du fait que nous ne besoin, parce que... nous ne traiterons pas les interruptions logicielles, encore moins les interruptions matérielles, vous pouvez immédiatement oublier le troisième cas. Les deux premières options demeurent. Si une requête d'E/S est initiée, alors nous sommes dans le contexte du thread qui a initié cette requête, et donc nous pouvons accéder directement à l'espace d'adressage du processus auquel appartient ce thread. Si nous sommes dans le contexte du thread système, nous ne pouvons accéder directement à aucun processus utilisateur et nous pouvons toujours nous référer au thread système. Si vous avez besoin de voir à partir du pilote ce qu'il y a pour un processus à une telle adresse, alors vous devrez soit changer le contexte vous-même, soit traduire les adresses via les tables de pages.

Niveaux de demande d'interruption

L'interruption fait partie intégrante de tout système d'exploitation. L'interruption nécessite un traitement, de sorte que l'exécution du code actuel est terminée et le contrôle est transféré au gestionnaire d'interruption. Il y a des interruptions matérielles et logicielles. Les interruptions sont traitées en fonction de leur priorité. Windows 2000 utilise un schéma de priorité d'interruption connu sous le nom de niveaux de demande d'interruption (IRQL). Il y a 32 niveaux au total, de 0 (passif), qui a la priorité la plus basse, à 31 (élevé), qui a la priorité la plus élevée. De plus, les interruptions avec IRQL = 0 (passif) à IRQL = 2 (DPC \ dispatch) sont logicielles, et les interruptions avec IRQL = 3 (périphérique 1) à IRQL = 31 (élevé) sont matérielles. Ne confondez pas les niveaux de priorité d'interruption avec les niveaux de priorité de thread - ce sont des choses complètement différentes. Une interruption avec IRQL = 0, à proprement parler, n'est pas une interruption, puisque il ne peut interrompre le travail d'aucun code (après tout, pour cela, ce code doit être exécuté à un niveau d'interruption encore plus bas, et il n'y a pas un tel niveau). Sur cet IRQL, les threads en mode utilisateur sont exécutés. Et le code de nos drivers sera également exécuté sur cet IRQL. Cela ne signifie pas que le code d'un pilote est toujours exécuté au niveau "passif". C'est juste que nous ne traiterons aucun logiciel, et encore moins les interruptions matérielles. Et de là découlent au moins deux conclusions très importantes.

Premièrement : le travail de nos pilotes peut être interrompu à tout moment afin de traiter une interruption avec une priorité plus élevée (par exemple, à partir d'un timer, lorsque l'ordonnanceur considère que notre thread a déjà un processeur depuis longtemps et qu'il est le temps qu'il se repose). Par conséquent, en ce sens, le code de nos pilotes est interruptible et préemptif (le processeur est donné à un autre thread), tout comme le code de n'importe quel thread utilisateur. Il existe des fonctions du noyau qui vous permettent de connaître le niveau d'interruption actuel, ainsi que de l'augmenter ou de le diminuer.

Le deuxième point important : au niveau de l'interruption passive, vous pouvez appeler n'importe quelle fonction du noyau (dans le DDK, dans la description de chaque fonction, il faut indiquer à quel niveau d'interruption elle peut être appelée), ainsi qu'accéder aux pages mémoire déposé dans le fichier d'échange. À des niveaux d'interruption plus élevés (DPC / dispath et plus), une tentative d'accès à une page qui n'est pas en mémoire physique entraîne un plantage du système. le gestionnaire de mémoire ne peut pas gérer l'erreur de page.

"Écran bleu de la mort"

Je pense que tout le monde, au moins une fois, a vu une image passionnante appelée "Blue Screen Of Death" (BSOD). Il n'est probablement pas nécessaire d'expliquer ce que c'est et pourquoi cela se produit. L'important ici est que lorsque vous commencez à développer des pilotes en mode noyau, soyez prêt au fait que BSOD apparaîtra assez souvent sur l'écran de votre moniteur.

Dans le troisième anneau, tout était simple : j'ai esquissé un exemple de code, placé int3 là où c'était nécessaire, l'ai lancé et... dans le débogueur vous avez déjà compris de quoi il s'agit. Si quelque chose ne va pas, je l'ai cloué, corrigé les erreurs, recompilé ... et ainsi de suite, jusqu'à ce que le code fonctionne comme il se doit. Vous pouvez oublier cette technique lors de la programmation des pilotes. Ici le "sapeur" se trompe une fois. Un faux mouvement... et vous pouvez vous asseoir et vous détendre un instant.

Afin de voir les BSOD aussi rarement que possible, vous devez respecter une règle très simple : "Mesurer sept fois - en couper un" ... dans le sens de "Vérifier sept fois - en exécuter un". C'est facile à dire, bien sûr, mais beaucoup plus difficile à faire. Mais en règle générale, étant donné que la structure des pilotes que vous allez écrire (après avoir lu ces articles) est relativement simple, vous pouvez traiter les erreurs avant même que le BSOD n'apparaisse. S'il apparaît obstinément devant vos yeux et que vous ne pouvez pas en comprendre la raison, un moyen possible de clarifier la situation est d'analyser un vidage sur incident. Vous pouvez lire ce que c'est, comment le faire et l'analyser dans l'article de Mark Russinovich "Analyse des vidages sur incident de la mémoire" http://www.osp.ru/win2000/2001/03/025.htm. Cette question (l'analyse) est très difficile, mais je pense qu'on n'en arrivera pas là.

Je suis un théoricien de merde, donc tout ce qui précède peut être considéré comme des informations très basiques sur ces principes qu'il est absolument nécessaire de comprendre. Vous ne pouvez pas commencer à développer des pilotes en mode noyau sans connaître le contexte des threads, les niveaux d'interruption et les priorités des threads, le mode noyau/utilisateur, etc. etc. Vous n'êtes pas sûr de certaines questions - la liste des références est ci-dessous.

Nous allons maintenant mettre en évidence certaines choses plus pratiques (elles deviendront complètement pratiques dans les prochains articles), à savoir ce dont nous avons besoin pour transformer toute cette théorie en pratique.

Kit de développement de pilote

Le premier est, bien sûr, le Device Driver Development Kit (Windows 2000, Driver Development Kit, 2KDDK), qui peut être téléchargé gratuitement sur le site Web de Microsoft (en tout cas, je l'ai fusionné entièrement gratuitement à partir d'ici : http:// www.microsoft.com/ddk/). Ce package comprend une documentation, qui est une riche source d'informations sur les structures de données internes et les fonctions système internes utilisées par les pilotes de périphérique.

En plus de la documentation, le DDK inclut un ensemble de fichiers bibliothèque (* .lib) qui seront indispensables pour la liaison. Le DDK inclut deux ensembles de ces fichiers : pour la version finale de Windows (appelée build gratuite) ; et pour un débogage (appelé build vérifié). Ces fichiers se trouvent respectivement dans les répertoires% ddk%\libfre\i386 et% ddk%\libchk\i386. La version de débogage a une vérification d'erreur plus stricte. Vous devez utiliser les fichiers correspondant à votre version du système en les plaçant dans le répertoire \masm32\lib\w2k.

Inclure les fichiers

Nous devons également inclure des fichiers (* .inc) avec des définitions de prototype de fonction. Nous (ou plutôt moi) devrons aussi les faire nous-mêmes. J'ai essayé de nombreux utilitaires différents qui convertissent * .lib -> * .inc, tous deux inclus dans le package masm32 by hutch, et fusionnés par moi à différents moments des vastes étendues d'Internet. De tout ce que j'ai en stock, seul protoize.exe de f0dder a fait face à sa tâche, et je n'ai pratiquement rien eu à modifier à la main. Ce merveilleux outil sera situé dans le répertoire \ tools \ protoize. Site de l'auteur : http://f0dder.didjitalyphrozen.com/. Seulement, vous ne la trouverez pas là-bas. f0dder a posté cet utilitaire plusieurs fois sur http://board.win32asmcommunity.net/. Les inclusions seront dans le répertoire \ include \ w2k. Ils doivent être placés dans le répertoire \ masm32 \ include \ w2k. Pour la conversion, nous avons utilisé * .lib pour l'édition gratuite de Windows 2000, car j'ai cette option (et vous l'avez probablement aussi).

Le problème suivant est plus grave. Il s'agit d'une absence presque totale de fichiers d'inclusion avec les définitions des structures nécessaires, les constantes symboliques et les macros. Vous pouvez difficilement trouver quelque chose de valable sur le net - c'est trop exotique d'écrire des pilotes en mode noyau en assembleur. Quelque chose peut être trouvé sur EliCZ http://www.anticracking.sk/EliCZ/. Quelque chose de Y0da http://mitglied.lycos.de/yoda2k/index.htm (en partie fait par lui-même, en partie tiré du même EliCZ). Mais c'est très mal fait (avec tout mon profond respect pour nos collègues slovaques et allemands) : les noms des membres de nombreuses structures diffèrent de ceux définis dans les fichiers d'en-tête originaux du DDK ; les structures imbriquées et les unions n'ont pas de noms ; bien qu'ils soient nommés dans l'original. Et en général, tout est dans un certain désordre, et lorsqu'on le regarde, cela provoque une impression déprimante. Seul ntstatus.inc est bien fait. Ceci est en partie dû au fait qu'EliCZ a commencé à créer son propre include même en l'absence de DDK (comme il le dit lui-même). Dans tous les cas, je ne vous conseille pas de les utiliser, du moins sans tests approfondis. Quelque chose, à un moment donné, a éclaté lors de la conférence http://board.win32asmcommunity.net/, mais la qualité n'est pas non plus particulièrement impressionnante. Bref, la seule solution correcte dans cette situation est de tout faire nous-mêmes, et manuellement, car je ne connais aucun outil permettant d'automatiser ce processus. Si, soudainement, vous tombez sur quelque chose de valable, ne le considérez pas comme un travail - faites-le moi savoir.

Débogage des pilotes

Nous avons également besoin d'un débogueur, et puisque le code en mode noyau devra être débogué, le débogueur approprié est également nécessaire. Le meilleur choix serait SoftICE. Ou vous pouvez utiliser le débogueur de noyau inclus avec le DDK. Ce débogueur nécessite deux ordinateurs, un maître et un esclave, ce que tout le monde ne peut pas se permettre. Mark Russinovich (http://www.sysinternals.com/) a écrit l'utilitaire LiveKd qui vous permet d'utiliser Kernel Debugger sans connecter un deuxième ordinateur. Je ne sais pas si c'est sur le site (je ne l'ai pas vérifié), mais c'est sur le disque du livre "Structure interne de Microsoft Windows 2000". De plus, ce débogueur est extrêmement utile pour examiner la structure interne du système, à condition d'avoir installé des symboles de débogage qui peuvent (ou pourraient) être téléchargés gratuitement sur le site Web de Microsoft.

  • David Solomon, Mark Russinovich, "L'intérieur de Microsoft Windows 2000", éd. Pierre, 2001.

    Bien que ce livre ne contienne pas une seule ligne de code source, il est principalement destiné aux programmeurs.

  • Sven Schreiber, « Fonctionnalités non documentées de Windows 2000 », éd. Pierre, 2002.

    Un livre purement pratique qui révèle de nombreux secrets de Windows 2000.

  • Walter Oney, "Programmer le modèle de pilote Microsoft", Microsoft Press, 1999

    Ce livre se concentre sur les pilotes Plag "n" Play, mais cela n'implique nullement ses mérites, puisque les principes de base du développement des conducteurs sont universels.

  • Jeffrey Richter, Windows pour les professionnels : création d'applications Win32 efficaces pour Windows 64 bits, éd. Pierre, 2000.

    Ce livre n'a rien à voir avec la programmation de pilotes, mais il est aussi très intéressant ;-)

    Cette liste ne prétend en aucun cas être exhaustive. Beaucoup, surtout en anglais, peuvent être trouvés sur Internet (à l'exception de Schreiber, tous les livres sont sous forme électronique). En ce qui concerne les livres, je voudrais aussi dire qu'ils sont tous de la catégorie "must have". Vous verrez - achetez sans regarder. Tous sauf Walter " et Oney sont traduits en notre " grand et puissant ".

    Et la dernière chose. Je ne suis pas un grand expert dans le domaine du développement de pilotes, donc des erreurs ou des inexactitudes, à la fois dans cet article et dans tous les articles suivants, sont très probables. Trouvez - piquez hardiment votre nez. Je te remercierai.

  • Centre de sécurité Windows Defender, comprenant une nouvelle section Sécurité des appareils, qui offre la gestion d'outils de sécurité avancés tels que l'isolation du noyau.

    Core Isolation est une technologie de sécurité basée sur la virtualisation qui fournit une couche supplémentaire de protection contre les attaques intelligentes. L'intégrité de la mémoire fait partie de la technologie d'isolation du noyau - une fonctionnalité conçue pour empêcher l'insertion de code malveillant dans des processus de haute sécurité. La protection est fournie par le fait que la page de mémoire virtuelle du noyau ne commence à s'exécuter qu'après avoir réussi le contrôle de cohérence.

    Voyons comment activer l'intégrité de la mémoire dans la mise à jour Windows 10 d'avril 2018 pour rendre votre ordinateur plus sécurisé.

    Activation de l'intégrité de la mémoire

    • Ouvrez le Centre de sécurité Windows Defender.
    • Sélectionnez la section "Sécurité de l'appareil".
    • Dans la section « Isolation du noyau », cliquez sur le lien « Détails de l'isolation du noyau ».
    • Placez le commutateur d'intégrité de la mémoire en position active.

    Après avoir terminé ces étapes, vous devez redémarrer votre ordinateur pour que les modifications prennent effet.

    Noter: votre processeur doit prendre en charge les technologies de virtualisation pour que cette fonctionnalité fonctionne. De plus, la virtualisation doit être activée dans le BIOS ou l'UEFI. Sinon, la fonction sera indisponible.

    Correction des problèmes d'isolation du noyau

    Dans certains cas, vous pouvez rencontrer des problèmes de compatibilité dans certaines applications si l'isolation du noyau est activée. Pour résoudre le problème, vous devrez désactiver la fonction.

    Si vous essayez de désactiver l'intégrité de la mémoire dans Windows Defender Security Center, mais que l'option est grisée et que le message « Ce paramètre est contrôlé par votre administrateur » s'affiche, vous pouvez toujours désactiver la fonctionnalité à l'aide du registre.

    Noter: Une modification incorrecte du registre peut entraîner de graves problèmes. Il est recommandé de sauvegarder le registre Windows avant de suivre ces étapes. Dans le menu Éditeur du Registre, sélectionnez Fichier> Exporter pour enregistrer la sauvegarde.

    • Appuyez sur le raccourci clavier Windows Key + R pour afficher la fenêtre Exécuter.
    • Tapez regedit et cliquez sur OK pour lancer l'Éditeur du Registre.
    • Allez sur le chemin suivant :
    HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ DeviceGuard \ Scenarios \ HypervisorEnforcedCodeIntegrity
    • Double-cliquez sur l'entrée Activée.
    • Modifiez la valeur de 1 à 0.
    • Cliquez sur OK.

    Pour désactiver, vous pouvez également utiliser le ready-made

    Envoyez votre bon travail dans la base de connaissances est simple. Utilisez le formulaire ci-dessous

    Les étudiants, les étudiants diplômés, les jeunes scientifiques qui utilisent la base de connaissances dans leurs études et leur travail vous seront très reconnaissants.

    Publié sur http://www.allbest.ru/

    1. Informations théoriques

    1.1 Développement de pilotes de noyau Windows

    Brèves informations théoriques

    Développement de pilotes de noyau

    Un pilote est un programme informatique par lequel un autre programme (généralement un système d'exploitation) accède au matériel de manière standard.

    Sommaire pour montrer comment fonctionnent les différents types de pilotes :

    Il est pratique de diviser en 2 types:

    - Les pilotes noyau (fonctionnent au niveau de privilège 0, mais n'interagissent en aucun cas avec le programme utilisateur ou le périphérique. C'est avec eux que nous allons commencer (ils sont plus simples et peuvent aussi être utiles).

    Les pilotes de périphérique sont nécessaires pour interagir entre le programme utilisateur et le périphérique, à savoir pour transférer des données entre eux, pour contrôler le périphérique. De plus, les appareils peuvent être à la fois réels et virtuels). Le pilote n'a pas à contrôler de périphérique physique. Certains systèmes d'exploitation vous permettent également de créer des pilotes de périphériques virtuels - des objets qui se comportent comme des périphériques d'E/S, mais ne correspondent à aucun périphérique physique.

    Les composants du noyau exécutés en mode processeur privilégié (appelé mode noyau), peuvent tout faire, à savoir :

    - ils peuvent exécuter des commandes processeur privilégiées (comme lgdt),

    - peut avoir accès aux données et au code du système,

    - avoir un accès direct aux équipements, par exemple via les ports

    - avoir accès à des cellules mémoires ; le pilote ne peut pas manipuler directement la mémoire physique, cependant il peut obtenir une adresse virtuelle pour n'importe quelle mémoire physique et la manipuler.

    Si vous devez écrire une application sérieuse nécessitant un accès aux fonctions internes ou aux structures de données du système, vous pouvez faire face à de nombreuses limitations, qui ne peuvent être surmontées qu'en plaçant votre code dans l'espace d'adressage du système. La seule façon documentée de le faire est d'installer le pilote. Cette méthode est relativement simple, fiable et, surtout, entièrement prise en charge par le système d'exploitation lui-même.

    Le code du noyau (en fait, c'est le système lui-même) est considéré comme totalement fiable. Par conséquent, étant chargé dans l'espace d'adressage du système, le pilote fait partie du système et n'est soumis à aucune restriction. Sous Windows, c'est pratiquement le seul moyen pour les développeurs sans système d'exploitation d'écrire des composants système au niveau du noyau.

    Pour écrire et étudier les moyens de développer des pilotes, ils utilisent le DDK (Device Development Kit) - un système de développement de pilotes.

    En plus de la documentation, le DDK inclut un ensemble de fichiers d'inclusion (* .inc) et de fichiers de bibliothèque (* .lib).

    Ainsi, Windows prend en charge différents types de pilotes de périphériques, mais en plus, il existe des pilotes qui ne sont pas des pilotes de périphériques, mais vous permettent simplement de créer des programmes qui s'exécuteront en mode noyau sous Windows, c'est-à-dire au niveau de privilège 0. Ce faisant, ils ont un accès complet au système d'exploitation et au matériel.

    Jetons un coup d'œil au pilote en mode noyau le plus simple.

    #comprendre

    int DriverEntry (

    DANS PDRIVER_OBJECT pDriverObject,

    IN PUNICODE_STRING pusRegistryPath) (

    }

    Le point d'entrée est DriverEntry, qui est structuré comme une procédure qui prend deux paramètres :

    pDriverObject est un pointeur vers l'objet pilote nouvellement créé. Lors du chargement d'un pilote, le système crée un objet pilote qui représente l'image en mémoire du pilote correspondant. Le système contrôle le conducteur à travers cet objet. L'objet pilote est une structure de données ordinaire de type DRIVER_OBJECT.

    pusRegistryPath Pointeur vers une clé de registre contenant les paramètres d'initialisation du pilote.

    Ce premier pilote est uniquement chargé dans le système et immédiatement déchargé.

    Examinons maintenant un modèle de programme qui devra être utilisé pour développer un programme dans la première étape du cours (le pilote en mode noyau beeper.sys).

    La tâche de ce pilote est de jouer une note jusqu'à la première octave sur la dynamique du système. Pour ce faire, le pilote utilise les instructions d'entrée et de sortie du processeur, en se référant aux ports d'E/S correspondants. Il est bien connu que l'accès aux ports d'E/S est une ressource système sacrément gardée par Windows. Une tentative d'accès à l'un d'entre eux, à la fois en entrée et en sortie, à partir du mode utilisateur, entraîne inévitablement une exception.

    Dans notre exemple, le haut-parleur fonctionnera (pour cela, en particulier, le port 61h, 0 et 1 bits, les ports 43h et 42h sont utilisés).

    Au début du pilote, les 12 notes sont définies.

    Il faudra non seulement allumer le haut-parleur, mais régler la fréquence du son. Pour cela, un sous-système de minuterie est utilisé, qui fonctionne indépendamment du processeur et dispose de 3 canaux. La sortie du canal 2 est connectée à un haut-parleur, qui est utilisé pour générer un son de différentes fréquences. La plage sonore audible est de 30 Hz à 6 000 Hz.

    Pour régler la fréquence du son, le mot de contrôle 0Bh est envoyé au port 43h (registre de commande du temporisateur) :

    mov al, 0Bh

    dehors 43h, al

    Cette valeur détermine le numéro du canal que l'on va contrôler, le type de fonctionnement, le mode du canal et le format du compteur.

    Ensuite, la fréquence sonore recalculée (1193167 / fréquence (Hz)) est envoyée au port 42h en deux parties (d'abord la partie de poids faible, puis la partie de poids fort).

    Par exemple, nous voulons obtenir une fréquence sonore de 100 Hz. On recalcule la fréquence,

    1193167/100 = 11931

    Puis:

    mov hache, 11931

    dehors 42h, al

    mov al, ah

    dehors 42h, al

    A la première étape du cours, il est nécessaire de modifier le programme pour qu'il produise d'autres sons musicaux (chacun a une variante).

    Les quêtes doivent souvent définir des durées différentes. Pour cela, il est commode d'utiliser la procédure DO_DELAY en lui passant un paramètre "temps de sondage" indirectement défini.

    Pour faciliter le débogage du pilote, il existe différents outils. Le plus simple est d'afficher les informations nécessaires dans une fenêtre spéciale de l'utilitaire Debug View. Ce programme est préalablement lancé et configuré pour intercepter les messages du niveau du noyau. Pour la sortie, le programme appelle la fonction DbgPrint, qui a un paramètre - la chaîne de sortie. Après le démarrage du pilote, toutes les sorties sont affichées dans la fenêtre Vue de débogage.

    Il existe différentes manières d'installer le pilote dans le noyau. Étant donné que notre pilote, en fait, n'est pas nécessaire au système (il ne contrôle aucun périphérique), nous allons temporairement connecter le pilote au système, puis le supprimer.

    Pour ce faire, vous devez créer une application qui lancera le pilote. Comment? Un pilote est un service au niveau du noyau. Par conséquent, l'application utilisera le SCM - Service Control Manager, qui est inclus avec Windows et s'exécute au niveau de l'utilisateur.

    Ainsi, vous devez construire une solution à partir de deux projets : une application console et un pilote.

    Pour développer des pilotes en C, vous devez d'abord :

    - installer le DDK,

    - définir la variable d'environnement WNETBASE (la valeur est le chemin d'accès au DDK, par exemple, e:\winddk\3790.1830).

    Le projet pilote doit être de type MakeFile.

    Définissez les paramètres du projet à l'aide des paramètres de l'application et écrivez la ligne dans le champ Build Command Line

    ddkbuild -WNETXP chk. -ceZ

    qu'est-ce que cela signifie d'appeler un script spécial pour lier VC avec DDK

    Les fichiers doivent être présents dans le dossier du projet en cours :

    sources, makefile, ddkbuild.cmd (script), fichier source du pilote.c

    Après avoir construit le projet, le pilote doit avoir l'extension sys.

    L'application lance le pilote beeper.sys, c'est-à-dire l'enregistre dans le registre et l'exécute. Puis, une fois terminé, il le supprime du registre.

    Pour qu'une application exécute le pilote, après avoir créé une solution composée de deux projets - une application et un pilote, vous devez placer le fichier exécutable de l'application et le pilote dans le même dossier, puis lancer l'application.

    Les pilotes sont très difficiles à déboguer. En cas d'erreurs de fonctionnement, l'OS se bloque le plus souvent et nécessite un redémarrage. Et pour notre pilote, après le redémarrage, vous devez également supprimer le service beeper06 du registre à l'aide de regedit (HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \), puis redémarrer à nouveau.

    1.2 Pilotes de périphériques virtuels Windows

    Jusqu'à présent, nous avons développé un pilote en mode noyau qui peut faire des choses qui ne peuvent pas être faites au niveau de l'utilisateur, en particulier, travailler avec les ports d'E/S. Un tel pilote est appelé pilote de noyau, mais pas pilote de périphérique, car aucune donnée n'est transférée entre le programme utilisateur et le périphérique (après tout, pourquoi un pilote est-il généralement nécessaire ? Pour organiser l'échange de données entre une application utilisateur et un dispositif).

    Nous allons maintenant développer des pilotes de périphérique qui transmettent des données entre une application utilisateur et un périphérique.

    Lorsqu'une application nécessite une opération d'E/S, un appel au pilote se produit. Pour ce faire, l'application peut émettre une demande de lecture de données depuis l'appareil ou d'écriture de données sur l'appareil. Et si une autre action est requise, par exemple, interroger ou contrôler un appareil, ou autre chose, alors le soi-disant. Interface IOCTL (Device In-Out Control).

    Nous allons considérer un tel cas pour les périphériques virtuels, car le plus souvent, pourquoi avons-nous besoin d'un périphérique virtuel dans un pilote ? Pour que vous puissiez y transférer des données, que le pilote peut en quelque sorte traiter (comme impossible dans l'application) et renvoyer le résultat à l'application. Rappelez-vous que le pilote de noyau habituel évoqué plus haut ne prenait rien de l'application et n'y renvoyait rien, mais effectuait simplement des actions qui n'étaient pas disponibles pour l'application.

    Lorsqu'une application nécessite une opération d'E/S, un appel au pilote se produit. Pour cela, le soi-disant. Interface IOCTL (Device In-Out Control).

    L'application appelante effectue les opérations suivantes :

    1) Ouverture d'un fichier et obtention de son descripteur :

    GENERIC_READ + GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL

    En conséquence, si tout s'est passé avec succès, nous obtenons le descripteur de périphérique.

    2) Envoi d'un code d'action au chauffeur (que faire, le chauffeur peut mettre en œuvre de nombreuses actions différentes) :

    invoquer DeviceIoControl, descripteur, code d'action, adresse du tampon d'entrée, taille des données d'entrée, adresse du tampon de sortie, taille des données de sortie, adresse du tampon pour le nombre réel d'octets

    3) Fermeture du dossier et, par conséquent, libération du descripteur.

    invoquer le handle de périphérique CloseHandle

    Pour transférer des données, les modules (application et pilote) doivent s'entendre sur un protocole d'interaction (codes d'action, structure des tampons - entrée et sortie).

    Le même code d'action est utilisé à la fois dans l'application et dans le pilote.

    Le code d'action dans l'application et dans le pilote peut être écrit sous forme hexadécimale, ou vous pouvez utiliser la macro CTL_CODE, comme cela est fait dans l'exemple de laboratoire. travailler dans le fichier common.inc.

    Examinons un exemple de code d'action d'un pilote de périphérique virtuel utilisé dans cet atelier. Le nom est IOCTL_GET.

    Dans le cas d'un périphérique virtuel, l'indicateur de fichier est 0.

    Type d'appareil - FILE_DEVICE_UNKNOWN = 22h

    Droits d'accès - FILE_READ_ACCESS + FILE_WRITE_ACCESS = 1 + 2 = 3 = 11b

    Le code de fonction va de 800h à FFFh. Nous avons 800h.

    Méthode de mise en mémoire tampon - un moyen de transférer des données entre l'application et le pilote (trois sont possibles):

    Pour une petite quantité de données, METHOD_BUFFERED (00b) est généralement utilisé - un tampon supplémentaire dans la mémoire non-page est alloué, suffisant pour accueillir les tampons d'entrée et de sortie. L'adresse de ce tampon est placée dans l'IRP dans le champ AssociatedIrp.SystemBuffer. Le répartiteur d'E/S prend en charge le travail de réécriture des données entre le tampon utilisateur et le tampon auxiliaire.

    Accès direct aux données (sans tampon) - METHOD_OUT_DIRECT (2) - pour la sortie ou METOD_IN_DIRECT (1) - pour l'entrée ; champ de l'IRP - MdlAddress. Il s'agit d'un appel direct — le gestionnaire d'E/S mémorise les pages physiques contenant le tampon en mode utilisateur. En même temps, il crée une structure auxiliaire MDL (Memory Descriptor List) pour décrire les pages fixes. Et le développeur du pilote travaille avec MDL.

    Accès via un tampon de niveau utilisateur - METHOD_NEITHER (3) ; champ de l'IRP - SystemBuffer. Le gestionnaire d'E/S transmet les adresses virtuelles en mode utilisateur au pilote. Et dans le pilote, vous devez travailler très soigneusement avec eux, car le pilote dans ce cas ne devrait fonctionner que dans le contexte du thread appelant.

    Lorsque l'application envoie un code d'action au pilote, le gestionnaire d'E/S démarre. Il est chargé de générer un paquet de demande d'E/S (IRP) et de l'envoyer au pilote pour un traitement ultérieur.

    Nous considérerons 3 types de demandes :

    IRP_MJ_CREATE - sera transmis sur CreateFile,

    IRP_MJ_DEVICE_CONTROL - sera transmis lorsque DeviceIoControl

    IPR_MJ_CLOSE - sur CloseHandle

    Un IRP se compose d'un en-tête et de piles d'allocation d'E/S. Le gestionnaire d'E/S crée un nombre de cellules de pile d'E/S égal au nombre de couches de pilotes impliquées dans le traitement de la requête. Chaque pilote est autorisé à accéder à son propre emplacement de pile. Lorsqu'un pilote transmet un IRP à un pilote de niveau inférieur, le pointeur de pile se déplace vers l'emplacement dont le pilote a besoin. A l'inverse, après traitement de la requête, le pointeur est déplacé jusqu'à la cellule pilote de niveau supérieur. Obtenir un pointeur à l'aide d'une fonction - IoGetCurrentStackLocation ().

    Chaque pile d'allocation contient un pointeur vers le DeviceObject et le FileObject pour lesquels la demande a été initiée. Les IRP sont toujours stockés dans une mémoire non paginée.

    Pour que le pilote fonctionne, les objets suivants sont créés et appliqués :

    Objet pilote ;

    Objets de l'appareil ;

    Étapes du conducteur.

    1) Création d'un objet pilote. Créé lorsque le pilote est chargé au stade de son lancement. À ce stade, la fonction DriverEntry est lancée et le tableau MajorFunction est rempli, ainsi que le pointeur vers et depuis l'objet périphérique.

    L'objet appareil comprend :

    Type d'appareil.

    2) Créez un lien symbolique vers l'appareil. Pour que l'objet "périphérique" devienne disponible au code du mode utilisateur, le pilote doit créer dans le répertoire "\ ??" qui lui est accessible (code du mode utilisateur). un autre objet est un lien symbolique. Le driver shablon.sys crée un lien symbolique « slshablon » vers son périphérique « devshablon » dans le répertoire « \ ?? », dont la valeur est la chaîne « \ Device \ devshablon ».

    Ainsi, déjà lors du chargement du driver (dans notre cas, au stade du chargement de l'OS), on a trois objets en mémoire : le driver "\Driver\shablon", le périphérique "\Périphérique\shablon" et le lien symbolique vers le périphérique "\ ?? \ slshablon ".

    3) Ouverture. Ensuite, lorsque l'application démarre, CreateFile est appelé. Il y a un lien vers l'appareil. La structure d'objet de périphérique DEVICE_OBJECT récupère des informations sur son pilote de service. Le gestionnaire d'E/S génère un paquet de requête d'E/S IRP de type IRP_MJ_CREATE et l'envoie au pilote. C'est ainsi que le pilote sait que le code du mode utilisateur essaie d'accéder à son appareil. Si le pilote ne s'en soucie pas, il renvoie un code de réussite. Notre chauffeur a une procédure d'expédition spéciale qui réagit à cet IRP - DispatchCreateClose (il existe une procédure combinée pour ouvrir et fermer un appareil). Il contient STATUS_SUCCESS dans le champ Io.Status.Status et 0 dans Io.Status.Information, car dans ce cas, rien ne doit être transmis. Cette réponse du pilote est un signal au gestionnaire d'objets pour créer un fichier virtuel. Cela crée un nouvel élément dans la table des descripteurs de processus avec un pointeur vers l'objet "fichier" et renvoie un nouveau descripteur au code du mode utilisateur.

    Si tout est OK, alors nous stockons le descripteur de fichier renvoyé par CreateFile dans la variable hDevice.

    4) Opérations d'entrée/sortie. Nous pouvons maintenant effectuer des opérations pour contrôler cet appareil en appelant les fonctions DeviceIoControl. Étant donné qu'un pilote de périphérique peut en principe effectuer de nombreuses tâches différentes, il est nécessaire de différencier d'une manière ou d'une autre les demandes. C'est l'objet du deuxième paramètre dwIoControlCode, appelé code de contrôle des E/S, qui est construit selon certaines règles.

    À l'aide du descripteur de périphérique, le gestionnaire d'E/S récupère des informations sur le pilote de service, génère un paquet de demande d'E/S de type IRP_MJ_DEVICE_CONTROL et l'envoie au pilote. Le pilote appellera la procédure DispatchControl correspondante, qui reçoit le code d'action et des informations sur les adresses et les tailles des tampons d'entrée et de sortie en tant que paramètres. Tout cela est communiqué via l'IRP. Dans la procédure, les informations nécessaires sont extraites de l'IRP : le code d'action, l'adresse du tampon de transmission des données.

    La procédure DispatchControl effectue les actions nécessaires, dans notre cas l'adresse du paquet IRP du registre ESI. Ensuite, elle transmet le résultat via le tampon de sortie à l'application.

    De la même manière que pour la procédure précédente, nous passons par l'IRP l'état d'achèvement et le nombre d'octets transférés depuis le pilote.

    Dans l'application, ces données sont formatées et affichées.

    5) Fermeture. Comme cela devrait être fait avec des handles qui ne sont plus nécessaires, en appelant la fonction CloseHandle, nous fermons le handle de périphérique.

    6) Déchargement du pilote. Supprimez le lien symbolique et supprimez l'objet appareil.

    Complexe (2) se compose de deux programmes :

    Une application qui demande au pilote une adresse IRP, puis affiche cette adresse dans une fenêtre Windows standard.

    Shablon.sys - pilote.

    Le pilote shablon fait quelque chose qui ne peut pas être fait au niveau de l'utilisateur, dans ce cas il détermine le contenu du registre esi lorsque le pilote est en cours d'exécution.

    L'application dans le tampon de sortie reçoit le contenu esi, le convertit en sortie hexadécimale et le sort dans une fenêtre Windows standard.

    Si vous avez besoin d'obtenir des informations de CMOS dans le pilote, vous avez besoin de :

    Envoyez le décalage CMOS d'intérêt au port 70h ;

    Petit retard;

    Obtenez des informations du port 71h à al.

    Ensuite, écrivez ces informations dans le tampon de sortie.

    Et dans l'application, vous devez prendre des informations dans le tampon de sortie, si nécessaire, les transformer et les afficher, ou les analyser et, selon le résultat, afficher le texte nécessaire dans la fenêtre standard.

    Ce laboratoire suppose que le pilote est installé de manière permanente dans Windows à l'aide d'un fichier .inf, à l'aide du Panneau de configuration - Installation du matériel : Ajouter un nouveau périphérique, Installation manuelle, Afficher tous les périphériques, Disque fourni, Parcourir pour sélectionner le fichier .inf (le pilote doit être dans le même dossier).

    Pour vérifier que le pilote est installé, sélectionnez Système, Matériel, Gestionnaire de périphériques dans le panneau de configuration.

    1.3 Accès aux pilotes existants à partir des applications en mode utilisateur

    Algorithme de l'application fonctionnant avec le pilote

    Pour travailler avec un pilote, une application en mode utilisateur doit obtenir un manipulateur (poignée) du pilote. Ce manipulateur peut être obtenu à l'aide de la fonction API CreateFile ou CreateFileA, qui fonctionne avec les caractères ASCII. Ensuite, la fonction API DeviceIoControl est utilisée, à laquelle le code IOCTL est transmis comme l'un des paramètres. Le code IOCTL est le code de contrôle par lequel le pilote apprend l'opération que l'application demande d'effectuer, la méthode de transmission des paramètres et les droits d'accès dont l'application a besoin pour effectuer cette opération. Après l'appel de l'application

    IRP_MJ_DEVICE_CONTROL est envoyé au pilote DeviceIoControl. Après le traitement des demandes, le contrôle est rendu à l'application et il reste à l'application d'analyser la réponse du pilote et de fermer les descripteurs ouverts.

    Exemple

    Dans l'exemple ci-dessous, l'application en mode utilisateur envoie une requête IOCTL_DISK_GET_PARTITION_INFO_EX au pilote du système de fichiers, analyse les informations reçues et affiche le format de la partition du disque dur.

    #comprendre

    #comprendre

    int _tmain (int argc, _TCHAR * argv)

    DWORD dwBytesReturned = 0;

    char cPartitionStyle = (0);

    PARTITION_INFORMATION_EX piPartitionInfo;

    HANDLE hDevice = CreateFileA (

    /*1*/"\\\\.\\c: ",

    / * 2 * / LIRE_GENERIQUE | GENERIC_WRITE,

    / * 3 * / FILE_SHARE_READ | FILE_SHARE_WRITE,

    / * 5 * / OUVERT_EXISTANT,

    if (hDevice == INVALID_HANDLE_VALUE)

    MessageBoxA (NULL, "Erreur CréerFichierA!", "Erreur", 0);

    if (DeviceIoControl (

    / * 1 * / (POIGNÉE) hAppareil,

    / * 5 * / & piPartitionInfo,

    / * 6 * / sizeof (piPartitionInfo),

    / * 7 * / & dwBytesReturned,

    si (piPartitionInfo.PartitionStyle == PARTITION_STYLE_MBR)

    MessageBoxA (NULL, "PARTITION_STYLE_MBR", "Légende", 0);

    else if (piPartitionInfo.PartitionStyle == PARTITION_STYLE_GPT)

    MessageBoxA (NULL, "PARTITION_STYLE_GPT", "Légende", 0);

    MessageBoxA (NULL, "PARTITION_STYLE_RAW", "Légende", 0);

    MessageBoxA (NULL, "Erreur DeviceIoControl", "Erreur", 0);

    CloseHandle (hDevice);

    Analyser un exemple

    Les variables nécessaires au fonctionnement de l'application sont déclarées. PARTITION_INFORMATION_EX est une structure qui décrit des informations sur une partition de disque dur.

    struct typedef (

    ) PARTITION_INFORMATION_EX;

    Dans cette partie du programme, la fonction CreateFileA est appelée pour obtenir un handle, qui est écrit dans la variable hDevice.

    La fonction DeviceIoControl est appelée de manière synchrone. Il lui est transmis :

    descripteur de périphérique ;

    Code IOCTL IOCTL_DISK_GET_PARTITION_INFO_EX ;

    pointeur vers le tampon d'entrée, NULL dans notre cas ;

    taille du tampon d'entrée ;

    pointeur vers le tampon de sortie ;

    taille de la mémoire tampon de sortie ;

    pointeur vers une variable de type DWORD, qui stockera le nombre d'octets renvoyés ;

    un pointeur vers une structure OVERLAPPED qui est utilisée pour appeler la fonction de manière asynchrone.

    Après le retour du contrôle, en cas de réussite de la fonction, les informations sur la partition sont stockées dans la structure PARTITION_INFORMATION_EX.

    L'analyse et la sortie des informations sont effectuées. Vous pouvez fermer les poignées ouvertes avant de rendre le contrôle au système d'exploitation. La fonction CloseHandle (__ dans HANDLE) vous permet de le faire. Si les descripteurs ne sont pas fermés, le système d'exploitation le fera pour vous.

    2. Mise en œuvre de la dissertation

    2.1 Étape 1

    La tâche: 1. Développez un pilote de noyau avec accès aux ports, exécutant des actions en fonction de l'option et affichant des informations dans la fenêtre Vue de débogage (par option), ainsi qu'une application qui lance le pilote.

    Liste Kurs_test.cpp

    #include "stdafx.h"

    #include "windows.h"

    #include "stdlib.h"

    SC_HANDLE hSCManager ;

    SC_HANDLE hService ;

    char acDriverPath;

    if (hSCManager! = 0) (

    // enregistre le joueur dans la table SCManager

    si (hService! = 0) (

    // Supprimer l'entrée du pilote

    DeleteService (hService);

    CloseServiceHandle (hService);

    renvoie 0 ;

    }

    Liste Beeper.sys

    #comprendre

    #define TIMER_FREQUENCY 1193167 // 1 193 167 Hz

    #définir PITCH_C 523 // 523,25 Hz

    #définir PITCH_Cs 554 // 554,37 Hz

    #définir PITCH_D 587 // 587,33 Hz

    #define PITCH_Ds 622 // 622,25 Hz

    #define PITCH_E 659 // 659,25 Hz

    #définir PITCH_F 698 // 698,46 Hz

    #définir PITCH_Fs 740 // 739,99 Hz

    #définir PITCH_G 784 // 783,99 Hz

    #define PITCH_Gs 831 // 830,61 Hz

    #define PITCH_A 880 // 880.00 Hz

    #define PITCH_As 988 // 987,77 Hz

    void DO_DELAY (temps entier) (

    long i, j ;

    pour (i = 0; je<=time*0xfffff; i++) {}

    }

    void DO_BIG_DELAY (temps entier) (

    DO_DELAY (2 * temps);

    }

    void Xylophone (int nPitch) (

    int nTone = TIMER_FREQUENCY / nPitch

    _asm (

    mov al, 10110110b; // écriture du mot de contrôle à 43h

    out 43h, al; // Canal de contrôle du son - Circuit logique utilisant une tonalité de minuterie et des bits de port système contrôlés par logiciel

    mov eax, nTone; // écrit la fréquence recalculée à 42

    out 42h, al; // partie supérieure

    mov al, ah; // partie basse

    dehors 42h, al

    in al, 61h; // changer la séquence d'échappement - convertir les derniers bits en uns

    ; // bit 0 - autorisation d'utiliser le haut-parleur

    ; // bit 1 - autorisation de connecter le timer-2 au haut-parleur

    ou al, 00000011b; haut-parleur allumé

    dehors 61h, al

    }

    DO_DELAY (0x7f);

    _asm (

    en al, 61h

    et al, 11111100b; haut-parleur éteint

    dehors 61h, al

    }

    }

    Xylophone (PITCH_C);

    Xylophone (PITCH_С);

    Xylophone (PITCH_С);

    Xylophone (PITCH_С);

    Xylophone (PITCH_С);

    Xylophone (PITCH_С);

    Xylophone (PITCH_С);

    renvoie STATUS_DEVICE_CONFIGURATION_ERROR ;

    }

    2.2 Étape 2

    Développez un pilote de périphérique virtuel qui vous permet d'effectuer des actions disponibles uniquement au niveau de privilège zéro (conformément à l'option), puis transférez les résultats vers l'application au troisième niveau de privilège pour les afficher à l'écran.

    Dans l'application, nous affichons le résultat dans une fenêtre Windows standard.

    Annonce shablon.c

    #comprendre // diverses définitions NT

    #comprendre

    UNICODE_STRING g_usDeviceName ;

    UNICODE_STRING g_usSymbolicLinkName;

    void DriverUnload (IN PDRIVER_OBJECT pDriverObject) (

    IoDeleteSymbolicLink (& g_usSymbolicLinkName);

    IoDeleteDevice (pDriverObject-> DeviceObject);

    }

    NTSTATUS DispatchCreateClose (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) (// traitement MJ_CREATE MJ_CLOSE

    pIrp-> IoStatus.Status = STATUS_SUCCESS;

    pIrp-> IoStatus.Information = 0 ;

    IoCompleteRequest (pIrp, IO_NO_INCREMENT);

    renvoie STATUS_SUCCESS ;

    }

    NTSTATUS DispatchControl (PDEVICE_OBJECT pDeviceObject, PIRP pIrp) (// traitement IRP_MJ_DEVICECONTROL

    état NTSTATUS ;

    int regEsi;

    // prend un pointeur vers IO_STACK_LOCATION, dans IoControlCode

    if (pIrp-> Tail.Overlay.CurrentStackLocation-> Parameters.DeviceIoControl.IoControlCode == IOCTL_GET) (

    // Comparez le code d'action et s'il s'agit de notre client, alors :

    _asm (

    mov eax, 0

    déménagement, 10h

    dehors 70h, al

    en al, 71h

    cbw

    cwde

    mov regEsi, eax

    }

    // c'est notre fonctionnalité - nous prenons le contenu du registre esi

    // l'écrit dans le tampon système

    * ((int *) pIrp-> AssociatedIrp.SystemBuffer) = regEsi;

    pIrp-> IoStatus.Information = 4 ; // et définit la taille du résultat

    état = STATUS_SUCCESS ;

    ) else status = STATUS_INVALID_DEVICE_REQUEST ;

    pIrp-> IoStatus.Status = état ;

    IoCompleteRequest (pIrp, IO_NO_INCREMENT);

    retour (statut);

    }

    int DriverEntry (IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pusRegistryPath) (

    État NTSTATUS ;

    PDEVICE_OBJECT pDeviceObject;

    // initialise les chaînes Unicode

    RtlInitUnicodeString (& g_usDeviceName, L "\\ Périphérique \\ DevGet");

    RtlInitUnicodeString (& g_usSymbolicLinkName, L "\\ ?? \\ sldevGet");

    // remplissez l'objet pilote - expliquez clairement au pilote quelle fonction traite quoi

    pDriverObject-> DriverUnload =

    pDriverObject-> MajorFunction =

    pDriverObject-> MajorFunction =

    pDriverObject-> MajorFunction =

    // crée un objet logique du périphérique virtuel

    Status = IoCreateDevice (pDriverObject, 0, & g_usDeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, & pDeviceObject);

    if (! NT_SUCCESS (Status)) (retourner le statut ;)

    // crée un lien symbolique vers l'appareil

    Statut = IoCreateSymbolicLink (& g_usSymbolicLinkName, & g_usDeviceName);

    if (! NT_SUCCESS (Statut)) (

    IoDeleteDevice (pDeviceObject);

    retourner l'état ;

    }

    retourner l'état ;

    }

    Annonce cours2.cpp

    #include "stdafx.h"

    #include "windows.h"

    #include "stdlib.h"

    #define IOCTL_GET CTL_CODE (FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS)

    int _tmain (int argc, _TCHAR * argv) (

    POIGNÉE hAppareil ;

    BOOL Contrôle de développement ;

    DWORD dwBytesReturned ;

    char stroka;

    /*

    Paramètres:

    lpFileName L'adresse d'une chaîne terminée par NULL qui spécifie le nom de l'objet à créer ou à ouvrir.

    dwDesiredAccess Type d'accès à l'objet. Ce paramètre peut prendre n'importe quelle combinaison des valeurs suivantes :

    Valeur : Description :

    0 Définit une requête sur la disponibilité d'un objet sur le périphérique spécifié. Une application peut demander des attributs de périphérique sans y accéder.

    GENERIC_READ Spécifie l'accès en lecture à partir de l'objet. Les données peuvent être lues à partir d'un fichier et le pointeur de fichier peut être déplacé. Combinez avec GENERIC_WRITE pour un accès en lecture-écriture.

    GENERIC_WRITE Spécifie l'accès en écriture à l'objet. Les données peuvent être écrites dans un fichier et le pointeur de fichier peut être déplacé. Combinez avec GENERIC_READ pour un accès en lecture-écriture.

    dwShareMode Mode d'accès partagé de l'objet. Si la valeur est zéro, l'objet ne peut pas être partagé par plusieurs programmes. Toutes les opérations suivantes pour ouvrir l'objet échoueront jusqu'à ce que la poignée de l'objet soit fermée. Pour partager un objet, utilisez une combinaison des valeurs suivantes :

    Valeur : Description :

    FILE_SHARE_DELETE Permet à une séquence d'ouverture d'objet de demander un accès en suppression.

    FILE_SHARE_READ Permet à une séquence d'ouverture d'objet de demander un accès en lecture.

    FILE_SHARE_WRITE Permet à une séquence d'ouverture d'objet de demander un accès en écriture

    lpSecurityAttributes L'adresse d'une structure SECURITY_ATTRIBUTES qui détermine si le handle retourné par la fonction peut être hérité par le processus enfant.

    Si lpSecurityAttributes est NULL, le descripteur ne peut pas être hérité.

    dwCréationDisposition

    Valeur : Description :

    CREATE_ALWAYS Crée toujours un nouveau fichier.

    Si le fichier existe, la fonction écrase le fichier.

    CREATE_NEW Crée un nouveau fichier. La fonction échouera si le fichier existe.

    OPEN_ALWAYS Ouvrir le fichier, toujours. Si le fichier n'existe pas, la fonction le crée de la même manière si dwCreationDisposition était CREATE_NEW.

    OPEN_EXISTING Ouvre un fichier. La fonction échouera si le fichier n'existe pas.

    TRUNCATE_EXISTING Ouvre un fichier et le tronque à la taille zéro. La fonction échouera si le fichier n'existe pas.

    dwFlagsAndAttributes Indicateurs et attributs de fichier.

    Lorsqu'un fichier existant est ouvert, CreateFile ignore le fichier modèle.

    Valeurs de retour :

    Si la fonction réussit, un handle d'ouverture vers le fichier spécifié est renvoyé. Si le fichier spécifié existe avant l'appel de fonction et que le paramètre dwCreationDisposition est CREATE_ALWAYS ou OPEN_ALWAYS, l'appel GetLastError renverra ERROR_ALREADY_EXISTS même si la fonction réussit. Si le fichier n'existe pas avant l'appel, GetLastError renverra 0 (zéro).

    En cas d'erreur, la fonction retournera INVALID_HANDLE_VALUE. Pour plus d'informations sur l'erreur, appelez GetLastError.

    */

    if (hPériphérique! = 0) (

    /*

    hDevice est le handle renvoyé par CreateFile.

    dwIocontrolCode est une valeur qui indique l'opération à effectuer.

    lpInBuffer est l'adresse du tampon qui contient les données requises pour effectuer l'opération spécifiée dans dwIoControlCode. Si l'opération ne nécessite pas de données, vous pouvez passer NULL.

    nInBufferSize est la taille en octets des données dans le tampon pointé par lpInBuffer.

    lpOutBuffer est l'adresse du tampon qui sera rempli avec la sortie lorsque l'opération sera réussie. Si l'opération ne fournit pas de sortie, ce champ DOIT être NULL.

    nOutBufferSiz est la taille en octets du tampon pointé par lpOutbuffer.

    lpBytesReturned - l'adresse d'une variable dword qui recevra la taille des données saisies dans lpOutBuffer.

    lpOverlapped est l'adresse de la structure OVERLAPPED si vous souhaitez que l'opération soit asynchrone. Si vous souhaitez attendre la fin de l'opération, mettez NULL dans ce champ.

    */

    wsprintf ((LPSTR) stroka, "% X", adwOutBuffer); // écrit une ligne dans le tampon (adwOutBuffer -> stroka)

    CloseHandle (hDevice);

    renvoie 0 ;

    }

    programme informatique du noyau du pilote

    2.3 Étape 3

    Inscription cours.cpp

    #comprendre

    #comprendre

    #comprendre

    {

    ordure DWORD ;

    0, // attributs de fichier

    retourner (FAUX);

    }

    0, // taille du tampon d'entrée

    CloseHandle (hDevice);

    return (bRésultat);

    }

    int main (int argc, char * argv)

    {

    /*

    struct typedef (

    PARTITION_STYLE Style de partition ; // format de rubrique

    LARGE_INTEGER décalage de démarrage ; // décalage du début de la section

    LARGE_INTEGER PartitionLength ; // taille de la partition

    Numéro de partition DWORD ; // numéro de section

    BOOLÉEN RewritePartition; // si la section est réinscriptible alors VRAI

    syndicat (

    PARTITION_INFORMATION_MBR Mbr; // informations supplémentaires sur la section Style MBR

    PARTITION_INFORMATION_GPT Gpt ; // informations supplémentaires sur la section Style GPT

    };

    ) PARTITION_INFORMATION_EX;

    */

    BOOL bRésultat ;

    système ("PAUSE");

    return ((int) bRésultat);

    }

    2.4 Étape 4

    1) Combinez toutes les fonctionnalités développées aux étapes 1 à 3 en un seul ensemble de programmes.

    Le complexe final devrait ressembler à ceci :

    - Notre pilote est intégré au système et chargé au démarrage de Windows.

    - L'application demande au conducteur les informations nécessaires (spécifiées à l'étape 2), le conducteur transmet ces informations, tandis que le haut-parleur est également allumé pendant un moment et une mélodie (spécifiée à l'étape 1) est jouée. Puis l'application fait une requête au conducteur existant dans le système (conformément à l'option à l'étape 3).

    2) Émettre une note explicative, qui doit décrire les 4 étapes, ainsi que des informations théoriques pour chaque étape.

    #include "stdafx.h"

    #include "windows.h"

    #include "stdlib.h"

    #define IOCTL_GET CTL_CODE (FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS + FILE_WRITE_ACCESS)

    BOOL GetPartitionNumber (PARTITION_INFORMATION_EX * pex)

    {

    POIGNÉE hAppareil ; // descripteur du périphérique vérifié

    BOOL bRésultat ; // indicateur de résultat

    ordure DWORD ;

    hDevice = CreateFile (TEXT ("\\\\. \\ c:"), // périphérique à ouvrir

    GENERIC_READ | GENERIC_WRITE, // accès à l'appareil

    FILE_SHARE_READ | FILE_SHARE_WRITE, // mode d'utilisation partagé

    NULL, // attributs de sécurité par défaut

    OPEN_EXISTING, // emplacement

    0, // attributs de fichier

    NUL); // ne copie pas les attributs de fichier

    if (hDevice == INVALID_HANDLE_VALUE) (// impossible d'ouvrir le périphérique

    printf ("CreateFile () a échoué! \ n");

    retourner (FAUX);

    }

    bResult = DeviceIoControl (hDevice, // périphérique demandé

    IOCTL_DISK_GET_PARTITION_INFO_EX, // opération à effectuer

    NULL, // pointeur vers le tampon d'entrée

    0, // taille du tampon d'entrée

    pex, sizeof (* pex), // buffer de sortie

    & junk, // nombre d'octets à renvoyer

    (PLOVERLAPPED) NULL); // sync entrée/sortie (I/O)

    CloseHandle (hDevice);

    return (bRésultat);

    }

    int _tmain (int argc, _TCHAR * argv) (

    SC_HANDLE hSCManager ;

    SC_HANDLE hService ;

    char acDriverPath;

    POIGNÉE hAppareil ;

    BOOL Contrôle de développement ;

    DWORD dwBytesReturned ;

    LPVOID adwInBuffer, adwOutBuffer;

    char stroka;

    PARTITION_INFORMATION_EX pex; // structure de l'appareil

    BOOL bRésultat ;

    hDevice = CreateFile ("\\\\. \\ sldevGet", GENERIC_READ + GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

    if (hPériphérique! = 0) (

    DevControl = DeviceIoControl (hDevice, IOCTL_GET, & adwInBuffer, sizeof (adwInBuffer), & adwOutBuffer, sizeof (adwOutBuffer), & dwBytesReturned, NULL);

    if ((DevControl! = 0) && (dwBytesReturned! = 0)) (

    wsprintf ((LPSTR) stroka, "% X", adwOutBuffer); // écrit une ligne dans le tampon (adwOutBuffer -> stroka)

    if (stroka == "00000100") MessageBox (NULL, "Trouvé 1,44 Mo", "Analyseur Yermakov FDD", MB_OK);

    else MessageBox (NULL, "Non trouvé", "Analyseur Yermakov FDD", MB_OK);

    hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_CREATE_SERVICE);

    if (hSCManager! = 0) (

    GetFullPathName ("beeper.sys", sizeof acDriverPath, acDriverPath, NULL);

    // Inscrire un musicien dans les tables SCM

    hService = CreateService (hSCManager, "beeper11", "Nice Melody Beeper11",

    SERVICE_START + SUPPRIMER, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START,

    SERVICE_ERROR_IGNORE, acDriverPath, NULL, NULL, NULL, NULL, NULL);

    si (hService! = 0) (

    StartService (hService, 0, NULL);

    DeleteService (hService);

    CloseServiceHandle (hService);

    ) else MessageBox (NULL, "Impossible d'enregistrer le pilote", NULL, MB_ICONSTOP);

    CloseServiceHandle (hSCManager) ;

    ) else MessageBox (NULL, "Impossible de se connecter à SCManager", NULL, MB_ICONSTOP);

    ) else MessageBox (NULL, "Impossible d'envoyer le code de contrôle", NULL, MB_OK);

    CloseHandle (hDevice);

    ) else MessageBox (NULL, "Dev n'est pas présent", NULL, MB_ICONSTOP);

    bRésultat = GetPartitionNumber (& pex);

    if (bRésultat) (printf ("PartitionNumber =% d \ n", pex.PartitionNumber);

    ) else (printf ("GetPartitionNumber () a échoué. Erreur% d. \ n", GetLastError ());)

    système ("PAUSE");

    return ((int) bRésultat);

    }

    3. Fonctionnement de l'application

    Graphique 3.1. Pilote de l'étape 2

    Graphique 3.2. Pilote de l'étape 3

    Publié sur Allbest.ru

    Documents similaires

      Mécanismes d'interaction entre le pilote en mode noyau et l'application utilisateur : architecture de pilote multicouche, algorithme de masquage des données, interaction pilote-application, interface utilisateur du programme de filtrage d'accès aux fichiers.

      dissertation, ajoutée le 23/06/2009

      Architecture E/S Windows NT. Organisation interne du bus USB. Caractéristique essentielle du modèle de pilote WDM. Points d'entrée du pilote en cours de développement, mise en mémoire du code, installation du pilote dans le système. Implémentation du code pilote en C.

      dissertation ajoutée le 27/09/2014

      La structure du mode utilisateur qui permet à l'utilisateur d'interagir avec le système. Description du mode noyau, qui garantit l'exécution sûre des applications utilisateur (programmes). Couche d'abstraction matérielle de Windows NT.

      présentation ajoutée le 23/10/2013

      Le noyau de Windows 98. Le rôle des modules de noyau 16 bits. Problèmes de performances. Multitâche coopératif et préemptif. Utilisation améliorée des ressources dans Windows 98. Utilisation de WordArt. MS Outlook Express : création et envoi de messages.

      essai, ajouté le 14/04/2005

      Fonctionnement conjoint de tous les appareils informatiques et accès à ses ressources. Concept et fonctions du système d'exploitation graphique Windows. Service d'aide Windows. Gestion du système de fichiers. Technologie Plug and Play. Interface graphique Windows.

      essai, ajouté le 22/01/2011

      Caractéristiques du système d'exploitation. L'histoire du développement de Windows. Caractéristiques comparatives des versions de Windows. Éléments et outils de Windows XP. Programmes d'application sous Windows XP. Travaillez sur des ordinateurs de bureau et des ordinateurs portables fonctionnant sous Windows.

      rapport ajouté le 16/10/2011

      Utilisation d'un pilote en mode noyau et d'une application de contrôle pour créer des threads système. Simuler le traitement des données et organiser les délais. Développement de pilotes en C++. Configuration du banc d'essai. Précision des modifications des délais et du fonctionnement de la minuterie.

      dissertation, ajouté 24/06/2009

      Travaux préliminaires de la structure interne du système d'exploitation Windows. Architecture NT et structure de base. Méthodes pour remplacer les fonctions en mode noyau et en mode koristuvach. Comprendre le conducteur. Paquets d'E/S. Évaluation de la stabilité et de la sécurité des systèmes Windows.

      dissertation, ajouté 01/02/2014

      Le concept, les types et le fonctionnement d'un pare-feu. Pare-feu Windows intégré. Windows XP SP2, accès aux paramètres du pare-feu Windows XP Service Pack 2. Windows Vista, trafic autorisé. Windows 7, paramètres de profil actifs. Pare-feu personnel, niveaux de test.

      résumé, ajouté le 19/11/2010

      Connaissance des caractéristiques techniques d'un ordinateur personnel. Installation du système d'exploitation et des pilotes Windows 7. Méthodes de nettoyage de Windows XP Professionnel SP3. Méthodes de récupération du système d'exploitation. Réalisation de l'installation de Microsoft Office 2010.

    Microsoft accorde une grande attention à la sécurité du système d'exploitation Windows 10. L'un des éléments importants du système est Windows Defender, mais il n'est pas capable de faire face à toutes les menaces. En particulier, les virus Ransomware sont devenus particulièrement répandus ces derniers temps, dont les réincarnations les plus célèbres sont les Petya et. Microsoft a implémenté des fonctionnalités d'isolation du noyau et d'intégrité de la mémoire dans Windows 10 pour lutter contre les virus Ransomware. Ils sont désactivés par défaut.

    Table des matières:

    Qu'est-ce que l'isolation du noyau et l'intégrité de la mémoire

    Isolation du noyau est un processus de protection supplémentaire, qui est fourni par la méthode de blindage des processus informatiques du système d'exploitation et de l'appareil. Grâce à ces actions, il est possible d'éviter de perturber le fonctionnement du système d'exploitation lorsque des virus pénètrent dans l'ordinateur.

    Intégrité de la mémoire est une fonction de protection qui accompagne l'isolation du noyau, qui vise à restreindre l'accès de programmes inconnus potentiellement dangereux aux processus avec un niveau de sécurité élevé.

    Important : la fonction d'isolation du noyau ne peut fonctionner que s'il existe des conditions suffisantes pour cela de la part du matériel de l'ordinateur. Dans les paramètres du BIOS, la technologie de virtualisation doit être active, grâce à quoi un ordinateur exécutant Windows 10 peut exécuter diverses applications dans un conteneur virtuel, limitant leur accès aux composants clés du système.

    Comment activer l'isolation du noyau et l'intégrité de la mémoire

    Les paramètres du système d'exploitation Windows 10 vous permettent de contrôler totalement les fonctionnalités de sécurité de votre ordinateur. Grâce aux paramètres de Windows 10, vous pouvez activer l'isolation du noyau et l'intégrité de la mémoire comme suit :


    Comme indiqué ci-dessus, si le matériel de votre ordinateur ne prend pas en charge la virtualisation, cette fonctionnalité ne fonctionnera pas. Lorsqu'il est activé, l'utilisateur verra le message « Impossible d'assurer l'intégrité de la mémoire. Incompatibilité possible." Si ce message apparaît, il est recommandé d'aller dans le BIOS et de voir si la fonction Secure Boot (Boot Mode) est activée.

    Comment désactiver l'isolation du noyau et l'intégrité de la mémoire

    Les nouvelles fonctions du système d'exploitation qui affectent sérieusement son fonctionnement risquent toujours de causer des problèmes avec l'ordinateur. La fonction d'isolation du noyau ne fait pas exception. Les utilisateurs qui l'ont déjà essayé, notent sur les forums Microsoft qu'ils rencontrent des problèmes lors du lancement de certains jeux et programmes. La seule façon de résoudre ce problème est de désactiver l'isolation du noyau et l'intégrité de la mémoire. Peut-être que dans les futures mises à jour, les développeurs d'applications ou Microsoft corrigeront cette incompatibilité.

    Il existe 3 façons de désactiver l'isolation du noyau et l'intégrité de la mémoire :


    Le gestionnaire d'alimentation garde un œil sur les chiffres de consommation d'énergie dans l'ensemble du système. Historiquement, la gestion de l'alimentation consistait à éteindre le moniteur et à arrêter la rotation des disques. Mais le problème devient rapidement plus complexe en raison de la demande d'une plus longue durée de vie de la batterie des ordinateurs portables, des considérations d'économie d'énergie sur les ordinateurs de bureau (qui restent allumés en permanence) et du coût élevé de la consommation d'énergie par les batteries de serveurs.

    Les nouvelles fonctionnalités de gestion de l'alimentation incluent la réduction de la consommation d'énergie des composants lorsque le système n'est pas utilisé en passant des appareils individuels en redondance ou même en les arrêtant complètement (à l'aide de l'interrupteur d'alimentation). Les systèmes multiprocesseurs désactivent les processeurs individuels lorsqu'ils ne sont pas nécessaires et peuvent même réduire la vitesse d'horloge des processeurs (pour réduire la consommation d'énergie). Lorsque le processeur est inactif, sa consommation d'énergie est également réduite, puisqu'il n'a rien d'autre à faire qu'attendre qu'une interruption se produise.

    Windows prend en charge un mode d'arrêt spécial appelé hibernation, qui copie toute la mémoire physique sur le disque, puis réduit la consommation d'énergie au minimum (les ordinateurs portables peuvent fonctionner pendant des semaines en hibernation) tout en vidant la batterie le moins possible. Étant donné que l'intégralité de l'état de la mémoire est écrite sur le disque, vous pouvez même remplacer la batterie de l'ordinateur portable (lorsqu'il est en veille prolongée). Lorsque le système sort de l'hibernation, il restaure l'état de la mémoire enregistrée (et réinitialise les périphériques). Cela place l'ordinateur dans le même état qu'il était avant l'hibernation (sans avoir à réenregistrer et à démarrer toutes les applications et tous les services en cours d'exécution. Windows essaie d'optimiser ce processus en ignorant les pages non modifiées (qui ont des réservations de disque) et réduit le reste les pages mémoire pour réduire la quantité d'E/S requise L'hibernation équilibre automatiquement la bande passante d'E/S et la bande passante du processeur Compression des données Une bande passante d'E/S suffisante évite la compression lors du passage en mode hibernation Avec les derniers multiprocesseurs, cela ne peut prendre que quelques secondes pour entrer et sortir de l'hibernation, même si la mémoire principale Le système a un grand volume.

    Une alternative à l'hibernation est le mode veille, dans lequel le gestionnaire d'alimentation place l'ensemble du système dans l'état de consommation d'énergie le plus faible (en utilisant uniquement la quantité d'énergie nécessaire pour régénérer l'état du tas). Comme la mémoire n'a pas besoin d'être copiée sur le disque, la transition vers cet état est plus rapide sur certains systèmes que l'hibernation.

    Malgré la disponibilité des états d'hibernation et de veille, de nombreux utilisateurs n'ont pas perdu l'habitude d'éteindre leur ordinateur personnel à la fin de leur travail.

    La veille prolongée est utilisée par Windows pour implémenter un pseudo-arrêt de démarrage appelé HiberBoot, qui est beaucoup plus rapide qu'un processus normal d'arrêt et de démarrage. Lorsque l'utilisateur donne au système une commande d'arrêt, HiberBoot déconnecte l'utilisateur du système, puis le met en état d'hibernation à partir duquel il sera possible de se reconnecter normalement. Plus tard, lorsque l'utilisateur rallumera le système, HiberBoot reprendra le système à partir du point de connexion de l'utilisateur. Pour l'utilisateur, cela ressemble à un arrêt très rapide, car la plupart des étapes d'initialisation du système sont ignorées. Bien sûr, le système doit parfois être arrêté pour de vrai afin de résoudre les problèmes ou d'installer une mise à jour du noyau. Si le système reçoit l'ordre de redémarrer plutôt que de s'arrêter, il subit un véritable arrêt et effectue un démarrage normal.

    Les appareils informatiques sur téléphones et tablettes, ainsi que les nouvelles générations d'ordinateurs portables, devraient toujours consommer une petite quantité d'électricité. Pour fournir ce mode, Windows moderne implémente une version spéciale de gestion de l'alimentation appelée CS (connected standby). CS est possible sur des systèmes dotés d'un équipement de connectivité réseau dédié capable de surveiller le trafic sur un petit ensemble de connexions en utilisant beaucoup moins d'énergie qu'un processeur. Il s'avère que le système CS est toujours allumé, la sortie du CS est effectuée immédiatement dès que l'utilisateur allume l'écran. La veille connectée est différente de la veille normale car le système CS se réveille également lorsqu'il reçoit un paquet d'une connexion surveillée. Une fois que la batterie commence à s'épuiser, le système CS passe en état d'hibernation pour éviter une décharge complète de la batterie et une éventuelle perte de données utilisateur.

    Pour obtenir une longue durée de vie de la batterie, il ne suffit pas d'arrêter le processeur aussi souvent que possible. Il est également important de garder le processeur éteint le plus longtemps possible. L'équipement réseau du système CS permet aux processeurs de rester éteints jusqu'à l'arrivée des données, mais d'autres événements peuvent également entraîner la réactivation du processeur. Les pilotes de périphériques Windows NT, les services système et les applications elles-mêmes s'exécutent souvent sans raison particulière, juste pour vérifier l'état des choses. Cette activité d'interrogation est généralement basée sur les paramètres du minuteur pour exécuter périodiquement du code dans un système ou une application. L'interrogation basée sur des signaux de minuterie peut perturber les événements qui déclenchent le processeur. Pour éviter cela, dans Windows moderne, ces minuteries doivent spécifier un paramètre d'erreur qui permet au système d'exploitation d'agréger les événements de minuterie et de réduire le nombre de raisons distinctes pour l'activation du processeur. Windows applique également des conditions dans lesquelles une application qui ne s'exécute pas activement peut exécuter du code en arrière-plan. Des opérations telles que la recherche de mises à jour ou l'actualisation de contenu ne peuvent pas être effectuées uniquement sur une demande de démarrage après l'expiration d'un délai. L'application doit obéir au système d'exploitation pour une telle activité en arrière-plan. Par exemple, une vérification des mises à jour ne doit avoir lieu qu'une fois par jour ou la prochaine fois que la batterie de l'appareil est faible. L'ensemble de courtiers système fournit diverses conditions qui peuvent être utilisées pour restreindre l'exécution de l'activité en arrière-plan. Si une tâche en arrière-plan nécessite un accès à un réseau bon marché ou des informations d'identification d'utilisateur, les intermédiaires n'exécuteront pas la tâche tant que les conditions nécessaires ne seront pas remplies.

    De nombreuses applications sont aujourd'hui implémentées avec du code sur site et des services basés sur le cloud. Windows fournit un service de notification Windows (WNS) qui permet aux services tiers de transmettre des notifications à un périphérique Windows dans CS sans que le matériel réseau CS écoute spécifiquement les paquets provenant de serveurs tiers. Les notifications WNS peuvent vous alerter d'événements urgents tels qu'un SMS ou un appel VoIP. Lorsqu'un paquet WNS arrive, le processeur devra s'allumer pour le traiter, mais l'équipement du réseau CS a la capacité de distinguer le trafic de différentes connexions, ce qui signifie que le processeur ne doit pas s'allumer en réponse à chaque paquet aléatoire provenant du interface réseau.