Débogage des processus système et des noyaux du système d'exploitation. Débogage hardcore avec Linice : apprendre à travailler dans le débogueur du noyau de la console. Types de systèmes cibles

  • Auteurs :

    Barinov S.S., Shevchenko O.G.

  • Année:
  • Source:

    Informatique et technologies informatiques / Documents de la VIe conférence scientifique et technique internationale des étudiants, étudiants diplômés et jeunes scientifiques - 23-25 ​​novembre 2010, Donetsk, DonNTU. - 2010. - 448 p.

Annotation

Une analyse comparative du mode utilisateur de débogage et du mode noyau par rapport au système d'exploitation Microsoft Windows est fournie, les différences et les problèmes d'organisation du débogage de ce dernier sont mis en évidence. Sur la base des résultats obtenus, les exigences de base pour la création de débogueurs en mode noyau en cas d'urgence et le débogage interactif sont formulées. Une analyse des solutions existantes pour vérifier leur conformité aux exigences a été réalisée. En particulier, une attention particulière est portée au débogueur Microsoft Windows.

Partie principale

Le débogage est le processus d'identification et d'élimination des causes d'erreurs dans un logiciel. Dans certains projets, le débogage prend jusqu'à 50 % du temps total de développement. Le débogage peut être grandement simplifié en utilisant des outils spécialisés constamment améliorés. Le principal outil de ce type est un débogueur, qui vous permet de contrôler l'exécution du logiciel, de surveiller sa progression et d'interférer avec lui. Les outils de débogage du noyau sont principalement utilisés par les développeurs de pilotes.

Les outils de développement de logiciels d'application offrent au programmeur un large éventail de possibilités. Tout environnement de développement intégré inclut la possibilité de déboguer sans avoir recours à des utilitaires tiers. Si nous parlons en particulier du développement de logiciels système et de pilotes, alors en raison de ses spécificités, le processus de développement est extrêmement difficile et peu automatisé. Toutes les phases de développement, y compris le débogage, sont distinctes. Pour réaliser chacun d'eux, des conditions particulières sont requises : l'écriture du code du programme est effectuée sur un système informatique à part entière, le débogage est effectué sur un système de débogage, des tests sont effectués en fonction des circonstances, etc. Le débogueur en mode noyau lui-même est plus difficile à apprendre et, par conséquent, moins convivial.

De manière générale, on peut parler du manque d'outils de débogage du noyau. Bien que de tels moyens soient disponibles, on ne parle souvent pas d’alternatives. Par exemple, le débogueur Microsoft Windows a un seuil d'entrée très élevé. De nombreux programmeurs parlent de la première expérience négative lorsqu'ils la rencontrent, et la plupart de ses capacités restent non réclamées.

Sur la base de la structure de l'espace d'adressage virtuel, si une application commet une erreur qui l'amène à écrire des données dans un emplacement de mémoire arbitraire, l'application n'endommagera que sa propre mémoire et n'affectera pas le fonctionnement des autres applications et du système d'exploitation. . Alors que le code du programme en mode noyau est capable d'endommager des structures de données importantes du système d'exploitation, ce qui entraînera inévitablement une panne générale. Un pilote mal écrit peut également entraîner une grave dégradation de l’ensemble du système d’exploitation.

    Les débogueurs modernes fournissent les fonctions de base suivantes :
  • débogage au niveau du code source ;
  • gestion de l'exécution;
  • visualiser et modifier la mémoire ;
  • visualiser et modifier le contenu des registres du processeur ;
  • afficher la pile d'appels.

Pour faciliter le travail avec du code désassemblé, ce qu'on appelle. symboles de débogage. Pendant l'exécution de l'éditeur de liens, en plus de l'image du fichier exécutable, un fichier de données peut également être créé contenant des informations qui ne sont pas requises lors de l'exécution du programme, mais qui sont extrêmement utiles lors de son débogage : noms de fonctions, variables globales, descriptions de structures. Les symboles de débogage sont disponibles pour tous les fichiers exécutables du système d'exploitation Windows.

Le contrôle d'exécution fait référence à la capacité d'interrompre et de reprendre l'exécution du code du programme après avoir atteint une commande spécifiée dans le code du programme. Si le code du programme est exécuté en mode pas à pas, une interruption se produit pour chaque jeton du langage de programmation ou à la sortie d'un sous-programme. Avec l'exécution libre, les interruptions d'exécution se produisent dans des sections de code prédéterminées - des endroits où les points d'arrêt sont définis.

Lors de l'interruption du code en mode noyau, le dilemme suivant se pose. Le débogueur utilise une interface utilisateur pour interagir avec le programmeur. Ceux. au moins la partie visible du débogueur fonctionne en mode utilisateur et utilise naturellement une interface de programmation d'application (API Windows), qui à son tour s'appuie sur des modules en mode noyau, pour la construire. Ainsi, suspendre le code en mode noyau peut entraîner un blocage : le système cessera de répondre aux demandes des utilisateurs.

Pour accéder à la mémoire du noyau, certaines parties du débogueur doivent également s'exécuter en mode noyau. Cela conduit à deux problèmes à la fois, qui sont une conséquence évidente de l'organisation de la mémoire en mode protégé du processeur.

Le premier problème concerne la traduction des adresses de mémoire virtuelle. Les conducteurs interagissent constamment avec les applications en mode utilisateur en accédant à leur mémoire. Le système d'exploitation Windows traduit les adresses virtuelles en adresses physiques en fonction du concept de contexte de thread. Le contexte d'un thread est une structure qui reflète l'état d'un thread et comprend notamment un ensemble de registres et d'autres informations. Lorsque le contrôle est transféré à un autre thread, un changement de contexte se produit, qui enregistre les informations sur un thread et restaure les informations sur un autre. Lorsque le contexte d'un thread est basculé vers le thread d'un autre processus, le répertoire de pages utilisé pour traduire les adresses virtuelles en adresses physiques change également.

La particularité est que lors de l'envoi des appels système, le système d'exploitation Windows ne change pas de contexte. Cela permet au code en mode noyau d'utiliser des adresses virtuelles en mode utilisateur.

La situation est différente lors de la distribution d'interruptions ou de l'exécution de threads système. Une interruption peut survenir à tout moment, il n'y a donc aucun moyen de prédire quel contexte de thread sera utilisé. Les threads système n'appartiennent à aucun processus et ne peuvent pas traduire les adresses virtuelles en mode utilisateur. Il s'ensuit que la mémoire du mode utilisateur n'est pas accessible dans ces situations.

Le deuxième problème concerne l'accès à la mémoire relocalisable. La plupart des informations en mémoire sont relocalisables et peuvent être déplacées de la mémoire physique vers le disque dur dans un fichier d'échange à tout moment. Si l'on accède à une page qui ne se trouve pas dans la mémoire physique, le processeur génère normalement une interruption de défaut de page, qui est gérée par le gestionnaire de mémoire, ce qui entraîne la lecture de la page à partir du fichier d'échange et son chargement dans la mémoire physique.

Ce comportement échoue si le code du débogueur est obligé d'utiliser des niveaux de requêtes d'interruption élevés (IRQL). Si l'IRQL correspond ou dépasse l'IRQL du gestionnaire de mémoire, ce dernier ne pourra pas charger la page manquante, car le système d’exploitation bloquera l’interruption de Page Fault. Cela entraînera un crash du système d'exploitation.

Le débogage est généralement divisé en interactif et d'urgence. Dans le débogage local interactif, le débogueur s'exécute sur le même système que le débogueur. Dans le débogage interactif à distance, le débogueur et l'objet de débogage s'exécutent sur des systèmes différents. Lors du débogage du code du noyau, le système doit être contrôlé dès les premières étapes de son démarrage, lorsque le réseau ne fonctionne pas encore, c'est pourquoi de simples interfaces série telles que COM, FireWire, USB sont utilisées pour communiquer entre les systèmes. Récemment, grâce aux tendances de développement de la virtualisation logicielle à différents niveaux d'abstraction, les machines virtuelles sont de plus en plus utilisées. Le système d'exploitation invité fait office de système d'exploitation de débogage, le système d'exploitation hébergé comprend une interface utilisateur de débogueur.

Par conséquent, le débogage d’urgence ne nécessite pas l’installation de l’outil de débogage sur l’ordinateur de test. La distribution du système d'exploitation Windows comprend des mécanismes permettant de mettre en œuvre le débogage d'urgence. Avant de redémarrer, le système d'exploitation peut enregistrer des informations sur son état, que le développeur peut analyser et en découvrir la raison. Ces informations enregistrées dans un fichier sont appelées un vidage mémoire.

Les outils de débogage de base en mode noyau sont fournis par le fabricant du système d'exploitation Windows lui-même dans le cadre du package Debugging Tools for Windows distribué gratuitement. Les outils incluent respectivement les débogueurs graphiques et de console WinDbg et KD (ci-après dénommés débogueur Windows). Le travail de ces débogueurs est basé sur des mécanismes fournis par les développeurs du système d'exploitation et intégrés dans son noyau.

Le mode principal du débogueur Windows est le mode interpréteur de commandes. Grâce à sa structure modulaire, Windows Debugger prend en charge des modules tiers appelés extensions en plus des commandes fournies par les développeurs. En fait, la plupart des commandes intégrées sont également regroupées sous forme d’extensions.

Windows Debugger se concentre sur le débogage interactif et d'urgence à distance, qui, lorsqu'il est utilisé, révèle toutes ses capacités. Dans le même temps, le débogage interactif local complet n'est pas pris en charge : le débogueur vous permet uniquement de visualiser certaines structures du noyau.

Il existe un module d'extension pour le débogueur Windows appelé LiveKD, créé par Mark Russinovich, qui implémente en quelque sorte le débogage interactif local. LiveKD crée à la volée un vidage mémoire du système de travail et l'utilise pour le débogage.

Le package Outils de débogage pour Windows est régulièrement mis à jour et prend en charge tous les systèmes d'exploitation Windows modernes.

Le débogueur du noyau SoftICE, produit par Compuware dans le progiciel DriverStudio, est traditionnellement une alternative au package Debugging Tools for Windows. Une caractéristique distinctive de SoftICE était la mise en œuvre du débogage interactif local sur le matériel pris en charge. Le débogueur pourrait contrôler presque complètement le fonctionnement du système d'exploitation.

Depuis le 3 avril 2006, les ventes de la famille de produits DriverStudio ont été interrompues en raison de « divers problèmes techniques et commerciaux, ainsi que des conditions générales du marché ». La dernière version du système d'exploitation prise en charge est Windows XP Service Pack 2. En règle générale, les service packs ne modifient pas l'interface d'application du système d'exploitation, mais les numéros d'appel du système et d'autres informations non documentées peuvent changer. Le débogueur SoftICE s'appuyait sur des adresses codées en dur des structures de données internes. En conséquence, la compatibilité a été rompue avec la sortie du Service Pack 3. Évidemment, les versions ultérieures du système d'exploitation Windows ne sont pas non plus prises en charge.

Syser Kernel Debugger a été créé par une petite société chinoise Sysersoft en remplacement du débogueur SoftICE. La première version finale est sortie en 2007. Comme SoftICE, Syser Kernel Debugger est capable d'effectuer un débogage interactif sur un système en cours d'exécution. Seules les éditions 32 bits des versions modernes de Windows sont prises en charge.

Actuellement, Windows Debugger est le principal outil parmi les développeurs de modules du noyau. Il est également utilisé par l'équipe du noyau du système d'exploitation Windows.

Un débogueur est la deuxième chose après un compilateur nécessaire pour créer des programmes. Cependant, beaucoup de ceux qui écrivent des programmes informatiques et utilisent un débogueur ne connaissent pas les principes et les mécanismes de son fonctionnement.


C'est difficile d'être un débogueur...

Étant donné que les programmeurs utilisent le débogueur jour et nuit, en particulier lorsqu'ils entrent en mode de débogage approfondi, il convient de dire que si le débogueur n'était pas un programme, mais un élément matériel, il surchaufferait et se briserait probablement. Parce que même le compilateur n’a pas autant de travail que le débogueur.

Bien entendu, comme il existe désormais de nombreux langages de programmation différents, il existe également des débogueurs pour chacun d'eux. Et, naturellement, pour différentes catégories de ces langages, il existe des différences dans le travail des débogueurs : par exemple, un débogueur pour programmes en Ruby interprété fonctionnera différemment que pour un langage Java compilé en bytecode, et un débogueur pour Java, en à son tour, il y aura des différences par rapport au débogueur Visual C++.

Je parlerai du débogage pour la plateforme Windows. Après avoir compris les principes de fonctionnement des débogueurs, il sera possible de comprendre à la fois les débogueurs pour systèmes POSIX et les débogueurs qui ne fonctionnent pas au niveau du système d'exploitation, mais au niveau d'une machine virtuelle ou d'un interpréteur.


Débogueurs pour Windows : deux types

Il existe deux types de débogueurs fondamentalement différents pour Windows. Je pense que tout le monde est tombé sur le premier en programmant dans Delphi (vous n'y avez pas programmé ? C'est difficile à croire. Qu'avez-vous programmé à l'école et au collège ?). Ce sont des débogueurs d'applications personnalisés. Il y en a beaucoup, et ils existent à la fois individuellement et (surtout, d'ailleurs, souvent) dans le cadre d'environnements de développement d'applications intégrés. Parmi les débogueurs distribués sous forme de produits logiciels distincts, OllyDbg est traditionnellement mis en avant, et j'en ai déjà parlé dans Computer News.

Le deuxième type de débogueur est le débogueur du noyau du système d'exploitation. Ils sont trouvés et utilisés moins fréquemment et leur conception diffère considérablement de celle des débogueurs d'applications personnalisés. Le débogueur de noyau le plus célèbre et en même temps le meilleur est SoftIce. Peut-être en avez-vous non seulement entendu parler, mais même utilisé.

Le travail de chacun des deux types de débogueurs ayant ses propres spécificités, je parlerai de chacun d'eux plus en détail.


Débogueur d'application personnalisé

Le débogueur pour les applications utilisateur est plus simple, car le système d'exploitation assume le travail le plus subalterne et le plus sale. Windows dispose d'interfaces logicielles spéciales conçues pour déboguer les applications au niveau utilisateur - elles sont appelées API de débogage Windows. Ce sont les API de débogage utilisées par tous les débogueurs intégrés aux environnements de développement intégrés populaires pour Windows.

Pour que le débogage commence, le débogueur doit lancer le processus en cours de débogage d'une manière spéciale - afin que le système sache que ce processus sera en cours de débogage. Après cela, le cycle de débogage commence : le programme est exécuté jusqu'à ce qu'un certain événement se produise, appelé événement de débogage. Cela exécute la boucle de débogage dans un thread séparé pour empêcher le débogueur de se bloquer.

Mais ce n'est que le début. Parce que le plaisir du débogueur commence lorsque l'événement de débogage se produit. Après tout, quel est le travail d’un débogueur ? Pour aider le programmeur à localiser une erreur avec précision sur une fonction spécifique, une opération spécifique, une variable spécifique. Le système d'exploitation peut également aider le débogueur dans cette tâche difficile.

Ainsi, un événement de débogage s'est produit, et nous devons ensuite découvrir d'une manière ou d'une autre comment cela est lié au texte du programme. Cela n'est possible que si le programme lui-même inclut des informations de débogage spéciales - un tableau de symboles de débogage. Il contient des informations sur la correspondance entre les adresses et les noms de fonctions, les types de données et les numéros de ligne de code. C'est grâce à eux que le débogage que tout programmeur Windows connaît est possible. Les tables de symboles ont des formats différents et il n'est donc pas toujours possible de déboguer un programme compilé par le compilateur d'un développeur à l'aide d'un débogueur d'un autre fabricant. Mais, cependant, le format le plus courant peut toujours être spécifié - il s'agit du PDB (Program Database), et il a été développé, bien entendu, par Microsoft Corporation.

Ainsi, si la table des symboles de débogage est au format PDB, vous pouvez utiliser un outil spécial de Microsoft - le processeur de débogage symbolique. Autrefois, il faisait partie du cœur du système et s'appelait Imagehlp.dll, mais il y a longtemps, il était séparé dans une bibliothèque distincte. Le processeur de caractères permet de retrouver la fonction ouverte ou la variable globale la plus proche à une adresse donnée, ainsi que le numéro de ligne et le nom du fichier source dans lequel se trouve cette ligne. Les opérations inverses sont également prises en charge, par exemple la recherche de l'adresse d'une fonction par son nom.

Bien entendu, ce n'est pas tout le travail effectué par le débogueur d'application personnalisé. Par exemple, lors du débogage d'applications multithread, de nombreux problèmes très subtils liés à l'interaction des threads surviennent. Même lors du débogage de choses relativement simples comme les services, il existe certaines nuances.

Mais nous ne nous attarderons pas sur les nuances pour le moment - à la fin de l'article, je vous dirai où les lire. Examinons maintenant les débogueurs du noyau.


Débogueur du noyau

Les débogueurs de noyau sont des programmes beaucoup plus complexes que les débogueurs d'applications utilisateur, et je pense que la raison est assez claire : ils n'ont pas d'assistant de système d'exploitation. Dans ce cas, elle est leur cliente, car c'est elle qui, en fin de compte, doit déboguer.

La plupart des débogueurs de noyau nécessitent deux ordinateurs connectés par un câble null modem pour fonctionner. Un null modem est un moyen de connecter deux ordinateurs directement avec un câble via leurs ports COM ou LTP. Un deuxième ordinateur est nécessaire car la partie du débogueur située sur le premier (sur celui sur lequel le système en cours de débogage est installé) a un accès limité au matériel, et donc toutes les sorties de données passent via un null modem vers le deuxième ordinateur.

Les processeurs Intel x86 modernes ont des registres de débogage spéciaux (les anciens modèles de processeurs 368 et les modèles plus récents n'en ont que huit, ils sont appelés DR0-DR7). Ces registres permettent au débogueur de définir des points d'arrêt sur les lectures et écritures en mémoire, ainsi que sur les ports d'E/S. En général, tout ressemble exactement à ceci, et je ne pense pas qu'il soit utile de décrire en détail maintenant de quoi chacun des registres de débogage est responsable, quelles interruptions implémentent des points d'arrêt et donnent d'autres informations similaires. Il est préférable de vous parler des débogueurs de noyau existants spécifiques pour Windows.

Eh bien, premièrement, il s'agit d'un débogueur intégré au noyau du système d'exploitation lui-même. Il est présent dans tous les systèmes d'exploitation de la gamme NT, à commencer par Windows 2000. Il fait partie du fichier NTOSKRNL.EXE et peut être activé en définissant l'option "/Debug" pour le système d'exploitation dans BOOT.INI. Ce débogueur nécessite une connexion null modem et un deuxième ordinateur avec le même système d'exploitation.

Il existe un autre débogueur de noyau de Microsoft - WinDBG. À proprement parler, il ne s'agit pas d'un débogueur de noyau, mais d'un débogueur hybride qui peut également être utilisé pour déboguer des applications au niveau utilisateur. Contrairement au débogueur intégré au noyau, il possède un shell graphique et est donc plus facile à utiliser. Ce débogueur prend également en charge des extensions spéciales qui peuvent être utiles pour certaines tâches de débogage. Mais cela nécessite également deux ordinateurs pour déboguer le noyau.

Cependant, il existe un débogueur de noyau qui peut déboguer sur un seul ordinateur. C'est SoftIce. Dans le même temps, SoftIce peut également déboguer des programmes d'application. L'utilisation de ce débogueur pour les programmes utilisateur se justifie, par exemple, dans le cas du débogage de systèmes temps réel liés à un timer système. Si vous déboguez à l'aide d'un débogueur classique, le résultat peut être incorrect même si le programme fonctionne correctement, et SoftIce arrêtera à la fois le programme et le minuteur. Ceci est utile lors du débogage d’applications multithread. De plus, SoftIce dispose de moyens très, très développés pour afficher des informations sur tous les threads du système, sur la synchronisation des threads pour les applications multithreads, des informations sur les handles... Le seul inconvénient de ce débogueur est sa complexité pour un programmeur d'applications. Mais parmi les débogueurs du noyau, celui-ci est le plus simple et le plus efficace.


Pour les plus curieux

Aujourd'hui, bien sûr, parler de débogueurs pour les applications Windows n'est plus aussi pertinent qu'il y a dix ans. Le monde entier s'est intéressé à Internet, et les principaux utilisateurs de SoftIce étaient des crackers, des travailleurs infatigables dans le domaine du piratage. Cependant, ce n'est pas si grave. La communication avec SoftIce développe sans aucun doute une personne en termes de connaissances informatiques, même si, bien sûr, si vous communiquez uniquement avec des débogueurs et ne communiquez pas avec de vraies personnes, certains effets secondaires sont possibles. Eh bien, je pense que tout le monde le devine déjà.

Les débogueurs font partie des types de logiciels les plus distinctifs, mais en termes de développement, même les débogueurs de programmes au niveau utilisateur sont assez complexes. Mais néanmoins, si vous avez le désir et le temps de développer votre propre débogueur, vos connaissances dans le domaine des systèmes d'exploitation et de la programmation augmenteront considérablement, ce qui signifie que vos chances d'obtenir un emploi bien rémunéré augmenteront.

Donc, si vous souhaitez créer votre propre débogueur, vous devez d'abord lire les documents sur ce sujet. À mon avis, le meilleur livre pour commencer est celui de John Robbins, Debugging Windows Applications. Il est déjà ancien, publié en 2001, mais les informations qu'il contient sont toujours d'actualité aujourd'hui, car elles sont de nature générale, voire en quelque sorte fondamentale. Ce livre contient des exemples d'écriture de débogueurs pour Windows, et il sera également utile si vous programmez en C++ et souhaitez mieux comprendre la gestion des exceptions. En fait, c'est grâce à ce livre que j'ai appris les informations sur les débogueurs présentées dans l'article. Si vous ne trouvez pas ce livre (après tout, il est déjà assez ancien), plusieurs adresses peuvent vous être utiles. Le premier est comme ceci : www.xakep.ru/post/19158/default.asp. Cet article du magazine Hacker donne un peu plus de détails que moi sur les débogueurs de noyau et contient également le code d'un débogueur simple. Et sur kalashnikoff.ru/Assembler/issues/016.htm, vous pouvez apprendre à écrire un débogueur DOS. Mais bien sûr, il est préférable de lire MSDN et en même temps de trouver un débogueur open source pour le comprendre. Et, bien sûr, si vous vous êtes lancé dans l'écriture d'un débogueur, alors réussite dans cette tâche difficile !

Le terme « débogage du noyau » signifie examiner la structure de données interne du noyau et/ou tracer étape par étape les fonctions dans le noyau. Ce débogage est un moyen très utile d'examiner le fonctionnement interne de Windows car il vous permet de voir des informations internes du système qui ne sont disponibles par aucun autre moyen et donne une image claire de la progression du code dans le noyau.

Avant d'examiner les différentes manières de déboguer le noyau, examinons l'ensemble des fichiers dont vous aurez besoin pour effectuer tout type de débogage.

Symboles pour le débogage du noyau

Les fichiers de symboles contiennent les noms des fonctions et des variables, ainsi que la disposition et le format des structures de données. Ils sont générés par le programme de liaison et sont utilisés par les débogueurs pour référencer ces noms et les afficher lors d'une session de débogage. Ces informations ne sont généralement pas stockées dans le code binaire car elles ne sont pas nécessaires lors de l'exécution du code. Cela signifie que sans cela, le code binaire est plus petit et s'exécute plus rapidement. Mais cela signifie également que lors du débogage, vous devez vous assurer que le débogueur a accès aux fichiers de symboles associés aux images binaires référencées lors de la session de débogage.

Pour utiliser n'importe quel outil de débogage en mode noyau afin d'examiner les éléments internes de la structure de données du noyau Windows (liste des processus, liste des blocs de thread, liste des pilotes chargés, informations sur l'utilisation de la mémoire, etc.), vous avez besoin des fichiers de symboles corrects et, à au minimum, un fichier de symboles pour l'image binaire du noyau - Ntoskrnl.exe. Les fichiers de table de symboles doivent correspondre à la version de l'image binaire à partir de laquelle ils ont été extraits. Par exemple, si vous avez installé un Service Pack Windows ou une sorte de correctif qui met à jour le noyau, vous devez mettre à jour les fichiers de symboles en conséquence.

Il est facile de télécharger et d'installer des symboles pour différentes versions de Windows, mais la mise à jour des symboles pour les correctifs n'est pas toujours possible. Le moyen le plus simple d'obtenir la version requise des symboles pour le débogage est de contacter le serveur de symboles Microsoft spécialement conçu à cet effet, en utilisant la syntaxe spéciale du chemin de symbole spécifié dans le débogueur. Par exemple, le chemin des symboles suivant amène les outils de débogage à télécharger les symboles à partir d'un serveur de symboles en ligne et à stocker une copie locale dans c:\symbols:srv*c:\symbols*http://msdl.microsoft.com/download/ symboles

Des instructions détaillées sur l'utilisation du serveur de symboles sont disponibles dans le fichier d'aide des outils de débogage ou en ligne à l'adresse http://msdn.microsoft.com/en-us/windows/hardware/gg462988.aspx.

Il existe peu de débogueurs décents au niveau du noyau pour Windows, mais sous Linux, ils se comptent sur les doigts d'une main, et même ceux-ci sont pour la plupart rudimentaires, inachevés ou abandonnés et envahis par la mousse... Aujourd'hui, nous parlerons des plus populaires et le plus intéressant d'entre eux -
Linice.

Introduction

Comme son nom l'indique déjà, Linice est un « port » non officiel du légendaire
SoftICE pour Linux, qui a conservé l'interface, le système de commande et la plupart des capacités de ce dernier : pop-up utilisant un raccourci clavier (dans Linice Ce ); définition de points d'arrêt matériels sur toutes les fonctions et appels système ; visualisation de GDT/LDT/IDT, pages de mémoire physique ; fonctionnalités empruntées à GDB (appel d'une fonction arbitraire avec la commande CALL, sauvegarde/restauration du contexte de registre, des variables internes, etc.).

Contrairement à la plupart des autres débogueurs, qui fonctionnent via le mécanisme de protection ptrace non réentrant et facilement détecté (dont l'analogue Windows est DEBUG_PROCESS, utilisé par les débogueurs d'applications), Linice utilise le traçage natif, le même que dans SoftICE, qui permet aux deux débogueurs de déboguer des programmes hautement sécurisés que d'autres ne peuvent pas gérer.

En fait, il ne s'agit pas du tout d'un portage (d'où les guillemets), mais d'un projet indépendant, écrit à partir de zéro et distribué gratuitement en code source (de SoftICE il n'y a que de l'inspiration). La partie principale du code destiné au noyau 2.4 a été écrite par le hacker allemand Goran Devic, mais des personnes complètement différentes ont été impliquées dans la maintenance du noyau 2.6 : Daniel Reznick, Peter K. et Carlos Manuel Duclos Vergara. Et notre compatriote - Oleg Khudakov - a réécrit les fichiers assembleur de nasm en
gcc.

Les textes sources sont sur le site officiel du projet -
Ligne%0A.com">www.Linice.com, il y a aussi de la documentation, une courte FAQ et un lien vers le forum
Ligne%0A">groups.google.com/group/Linice. Il n'existe pas d'assemblys binaires prêts à l'emploi.
Les créateurs du projet ont ouvert leur propre compte sur SourceForge, mais ont été trop paresseux pour y télécharger des fichiers, ne présentant que 3 captures d'écran de très mauvaise qualité :
.

Configuration système requise

Dernière version Linice est numéroté 2.6 et date du 28 juillet 2005, prenant entièrement en charge le noyau 2.4.x et le mode console VGA. Les noyaux les plus récents ont de sérieux problèmes et le noyau 2.6.x n'a qu'un support limité.
Le débogueur a été développé et testé sous Debian 2.6. Sa compatibilité avec d'autres distributions n'est pas garantie, ce qui nous oblige à recourir au tambourin, mais dans certains cas même le tambourin n'aide pas. En fait, gardez Debian sur votre machine juste pour travailler avec Linice, - c'est tout à fait normal. Il y a longtemps, alors qu'il n'existait pas encore d'implémentation de SoftICE pour NT, de nombreux pirates informatiques installaient Win 9x uniquement pour casser des programmes, alors qu'ils étaient eux-mêmes sous Windows.
N.T. Parce que pour couvrir toutes les subtilités de l'installation Linice dans le cadre d'un article c'est pratiquement impossible, je me limiterai à décrire le processus de compilation et de lancement Linice sous une distribution spécifique - Knoppix 3.7 avec noyau 2.4.1 en mode console VGA.
Linice prend en charge l'ACPI et les machines multiprocesseurs, mais ne fonctionne pas bien avec X, en particulier sur les cartes vidéo autres que nVidia. Il ne perçoit pas du tout la profondeur de couleur de 24 bits, « digérant » uniquement 8, 16 et 32 ​​bits, c'est donc plus pratique. pour déboguer des applications X via un terminal distant connecté via un port COM utilisant le protocole VT100. Dans ce cas, le clavier local fonctionnera également avec.
Linice!

Compilation et configuration de Linice

Téléchargez l'archive gzip des textes sources www. Linice.devic.us/ Linice-2.6.tar.gz, qui prend un peu moins d'un mégaoctet, décompressez-le sur le disque, allez dans le répertoire ./docs et à partir du fichier readme, nous découvrons que le débogueur est construit pour le noyau 2.4 comme suit :

# construction de CD
# ./make_bin-2.4
# cd ../bin
# rendre propre ; faire e

Cependant, avant de lancer make, vous devez ouvrir le fichier ./bin-2.4/Makefile et éditer la ligne "TARGET" en fonction de la configuration et de l'architecture de la plateforme cible. En particulier, sur les machines ACPI équipées de processeurs multicœurs ou HyperThreading, cela ressemblera à ceci :

CIBLE = -DSMP -DIO_APIC

Une fois la compilation terminée, il y aura de nombreux fichiers et répertoires dans le répertoire ./bin, mais les seuls importants sont :

linsym – module de chargement du débogueur ;
linince.dat – fichier de configuration ;
xice – prise en charge des X, lorsque vous travaillez en mode texte, ils peuvent être supprimés ;
./Linice_2.4.27/Linice.o – un module de noyau chargeable contenant le débogueur lui-même.

Processus de construction Linice

Après avoir assemblé un kit fonctionnant de manière minimale, ce serait bien d'avoir tout le reste - des exemples de débogage de démonstration situés dans le répertoire ./test et compilés avec le script de compilation, ainsi qu'un module d'extension (à notre avis, un plugin) situé dans le Répertoire ./ext, compilé par la commande make et chargé par la commande insmod. Cela n'apporte aucun avantage, mais après avoir étudié le code source, nous pouvons écrire nos propres modules qui étendent les fonctionnalités
Linice.

Lors du chargement de Knoppix, une invite "boot:" apparaît en bas de l'écran où vous devez saisir "knoppix 2 vga=normal". Le code de triche "knoppix" sélectionne le noyau 2.4 (automatiquement chargé par défaut, donc "knoppix"). peut être omis), " 2 " bloque le chargement des X " et " vga=normal " définit le mode vga standard avec une résolution de 80x25.

Après avoir attendu la fin du téléchargement, nous disons « su », puis « passwd » et entrons un nouveau mot de passe pour root "a, sous lequel nous nous connectons immédiatement au système à l'aide de la commande login. Si cela n'est pas fait, une tentative de commencer Linice se terminera par un échec cuisant au cri de « défaut de segmentation ».

Lorsque vous démarrez Knoppix depuis votre disque dur (sur lequel vous pouvez l'installer avec la commande « sudo knoppix-installer » tapée dans la fenêtre du terminal sous la session LiveCD), un menu démarrer apparaîtra avec une liste des noyaux disponibles. (2.4)-1 et cliquez sur pour définir les paramètres de démarrage - « 2 vga=normal ». Il n'est pas nécessaire d'écrire le mot « knoppix », puisque le noyau est déjà sélectionné. Une fois le téléchargement terminé, donnez la commande login et connectez-vous en tant que root (en supposant que le compte a été créé précédemment).

Le débogueur est lancé avec la commande ./linsym –i, après quoi il apparaît immédiatement à l'écran. Si cela ne se produit pas, essayez de spécifier le commutateur "--verbose 3" pour afficher les messages de diagnostic.
L'une des raisons de l'échec du démarrage peut être l'absence du fichier /boot/System.map contenant les adresses des fonctions du noyau. Le téléchargement échouera également si le contenu de System.map ne correspond pas au noyau actuel, ce qui peut arriver, par exemple, lors de sa recompilation. Certains compilateurs de distribution soit n'incluent pas du tout System.map (pensant que cela renforcera la sécurité du système, car il sera plus difficile pour les rootkits d'intercepter les appels système), soit ils placent ici quelque chose de complètement faux et on ne sait généralement pas où ça vient de. Dans de tels cas, il suffit simplement de recompiler le noyau, en pointant le débogueur vers le chemin d'accès au fichier System.map à l'aide du commutateur "-m", s'il se trouve ailleurs que /boot. De cette façon, la sécurité ne sera pas compromise et Linice peut fonctionner !
Le débogueur revient au système en ou en utilisant la commande "x " Combinaison appelle le débogueur depuis n'importe quel programme. Cependant, ce n'est pas du tout un fait que nous nous retrouverons dans son contexte, car Linux est un système multitâche qui change de processus les uns après les autres, et les commandes ADDR (changement de contexte) sont dans le « lexique ». Linice n’existe toujours pas et on ne sait pas quand il apparaîtra. Par conséquent, vous devez faire preuve de ruse en définissant des points d'arrêt sur les appels système utilisés par un programme spécifique, ou en pénétrant dans le processus à l'aide de la méthode INT 03h, dont nous parlerons maintenant.

Le commutateur «-x», passé au même linsym, est responsable du déchargement du débogueur (si vous voulez vraiment le décharger).

Les bases du travail avec Linice

Pour ceux qui ont déjà travaillé avec SoftICE, maîtriser Linice ne posera aucun problème. Les mêmes commandes sont utilisées ici : D – vidage de la mémoire, E – édition de la mémoire, T – traçage pas à pas, P – traçage sans entrer de fonctions, R – visualisation/modification des registres, BPM/BPX – définition d'un point d'arrêt pour l'accès à la mémoire /exécution et etc. Une liste complète des commandes est contenue à la fois dans l'aide intégrée, appelée via HELP (d'ailleurs, « HELP command_name » fournit des informations supplémentaires sur la commande) et dans la documentation standard.

Cliquons et parcourez la liste des processus affichés par la commande PROC, avec le processus en cours surligné en bleu :

:PROC

1 0000 C1C3E000 SOMMEIL 0 0 initialisation
2 0000 F7EE8000 SOMMEIL 0 0 keventd
3 0000 F7EE2000 SOMMEIL 0 0 ksoftirqd_CPU0
4 0000 F7EE0000 SOMMEIL 0 0 ksoftirqd_CPU1
5 0000 F7ED0000 SOMMEIL 0 0 kswapd
6 0000 F7EAA000 SOMMEIL 0 0 bdflush
7 0000 F7EA8000 SOMMEIL 0 0 mis à jour
56 0000 F6A36000 DORMIR 0 0 kjournald
1006 0000 F7A34000 RUNNING 0 0 montage automatique
1013 0000 F68E6000 SOMMEIL 0 0 tassesd
...
1105 0000 F6DDE000 DORMIR 0 0 mc
1106 0000 F6DD4000 SOMMEIL 0 0 économiseur de cons.

Les processus sont bien sûr bons, mais comment pouvons-nous encore déboguer les programmes ? Le plus simple est d'insérer la commande machine CCh correspondant à l'instruction INT 03h dans le point d'entrée, après avoir préalablement noté le contenu de l'octet d'origine. Cela peut être fait avec n'importe quel éditeur hexadécimal, par exemple celui que j'ai mentionné plusieurs fois.
HTE.

Après avoir chargé le fichier dans l'éditeur, cliquez sur (mode), sélectionnez elf/image, déplacez le curseur sur « point d'entrée : », appuyez sur (modifier) ​​et remplacez le premier octet par CCh, enregistrez les modifications en (enregistrer) et partir. Lors de l'exécution d'un programme corrigé Linice apparaît immédiatement, perturbé par une exception générée par CCh, après quoi EIP indique la fin
CCh.

État du programme avec un point d'entrée corrigé au moment où le débogueur apparaît

0023:080482C0 CC int 3
0023:080482C1 ED dans eax, dx
0023:080482C2 5E pop esi
0023:080482C3 89E1 mouvement ecx, esp

Le curseur pointe sur l'instruction in eax,dx (EDh), qui est un fragment de l'instruction xor ebp,ebp (31h EDh) corrigée. Maintenant (en théorie), nous devrions restaurer l'octet d'origine en changeant CCh à 31h, réduire le registre EIP de un et continuer le traçage comme d'habitude.

Mais ce n’était pas le cas ! Linice- il s'agit bien sûr d'un portage, mais très rudimentaire, et il ne peut pas modifier la mémoire d'une image de page, même si vous ouvrez d'abord le segment de code en écriture. Ni E (modifier), ni F (remplir), ni M (copie en mémoire) ne fonctionnent ! Mais écrire dans la pile fonctionne, et c'est largement suffisant pour nous, les hackers.

On se souvient de la valeur actuelle du registre EIP ; copiez la commande de machine corrigée en haut de la pile ; restaurez-y l'octet CCh ; nous lui transférons le contrôle, en modifiant la valeur EIP ; nous le réalisons en effectuant un seul acte de traçage ; et remettez EIP à sa place, c'est-à-dire à la commande machine suivante :

Récupération de l'octet d'origine remplacé par l'instruction INT 03h

; Regardons ce qui se trouve au sommet de la pile (par pure curiosité).
:d esp-10
0018:BFFFEFC0 C0 82 04 08 00 00 00 00 5D 0C 00 40 DC EF FF BF

; Nous copions la commande machine corrigée en haut de la pile.
; Le nombre 10h est la taille maximale possible d’une instruction machine sur x86.
:m eip-1 L 10 esp-10

; Voyons comment la pile a changé.
:d esp-10
0018:BFFFEFC0 CC ED 5E 89 E1 83 E4 F0 50 54 52 68 F0 85 04 08

; Ouais! Le stack a vraiment changé, il est temps de fixer CCh à 31h.
:e esp-10 31
Modifier les données immédiates non encore implémentées.

; Oups ! L'affectation directe des données n'est pas implémentée dans Linice,
; mais nous pouvons éditer le dump de manière interactive (également
; comme dans SoftICE) ou donnez la commande F esp-10 L 1 31, gardez simplement à l'esprit que
; que contrairement à SoftICE, le débogueur Linice ne met pas à jour la fenêtre de dump,
; donc après avoir exécuté la commande F, il peut apparaître que
; aucun résultat ; en fait, ce n'est pas le cas, il suffit de mettre à jour
; dump avec la commande D esp-10, et tout se mettra en place.

; On transfère le contrôle à la commande copiée dans la pile,
; rappelez-vous la valeur du registre EIP.
:r eip (esp-10)
reg:eip=BFFFEFC0

; Nous effectuons un seul acte de traçage.
:t
0023:BFFFEFC2 5E pop esi

; Comme on peut le voir, le registre EIP a augmenté de 2 (BFFFEFC2h - BFFFEFC0h) = 02h,
; donc l'adresse de la commande suivante est : 080482C1h - 01h + 02h = 080482C2h,
; où 080482C1h est la valeur initiale d'EIP lors de l'entrée dans le programme, et 01h est la taille de INT 03h.

; Nous définissons EIP sur la commande suivant l'instruction corrigée.
:r eip 80482C2
reg:eip=80482C2

C’est le genre de danses avec un tambourin qu’il faut faire. Que pouvons-nous faire ? Nous avons donc réglé le chargement des programmes dans le débogueur, divisons maintenant les points d'arrêt en appels système et fonctions du noyau.

La commande exp imprime les noms exportés par le noyau, chacun pouvant apparaître dans des expressions, par exemple "bpx do_bkr" est équivalent à "bpx C012C9E8".

Liste des noms exportés par le noyau

:exp
noyau
C0320364 mmu_cr4_features
C02AC3A4 acpi_disabled
C02AC8A0 i8253_verrouillage
...
C012BDA8 do_mmap_pgoff
C012C764 do_munmap
C012C9E8 do_brk
C011E990 sortie_mm
C011E69C fichiers_exit

Les appels système sont plus difficiles. Soutien direct de Linice ce n'est pas ici (mais c'est censé l'être, étant donné les spécificités de Linux), donc cette chose doit être faite à la main.

La table syscall, comme vous le savez, est un tableau de mots doubles commençant à l'adresse sys_call_table (cette variable est exportée par le noyau).

Tableau des appels système

; Nous passons le débogueur en mode d'affichage double mot.
:jj

; Nous affichons le tableau à l'écran.
:d sys_call_table
0018 : C02AB6A8 C0126ACC F8932650 F89326A0 C013DC10
0018:C02AB6B8 C013DD18 C013D5C8 C013D724 C011F3BC
0018:C02AB6C8 C013D664 C014A8E0 C014A3B4 F893020C

Chaque élément du tableau correspond à son propre appel système, et chaque appel a son propre numéro, que l'on peut trouver en regardant dans le fichier /usr/include/sys/syscall.h, mais il vaut mieux ne pas le faire sous Linux , où il n'y a pas de numéros directs, mais pour emprunter le même fichier à BSD - tout de même, les numéros des principaux appels système sur tous les systèmes sont les mêmes. En particulier, l’appel système ouvert est le numéro 5.

Pour définir un point d'arrêt en ouverture, vous devez connaître son adresse, située dans le cinquième double mot de la table des appels système, en comptant à partir de zéro, et égale (dans ce cas) C013D5C8h.

Définition d'un point d'arrêt sur l'appel système ouvert

; Définir un point d'arrêt sur l'appel système ouvert,
:bpxC013D5C8
; quittez le débogueur,
:x
...
# ouvre un fichier,
...
; le débogueur apparaît immédiatement et nous en parle,
:Point d'arrêt dû à BPX 01

; Nous émettons la commande proc pour nous assurer que nous sommes coincés dans notre processus.
:proс
PID TSS État de la tâche UID Nom du gid
1049 0000 F6364000 DORMIR 0 0 getty
1145 0000 F61CC000 DORMIR 0 0 mc
1146 0000 F614A000 SOMMEIL 0 0 économiseur de cons.

De cette façon, il est facile de pirater des processus déjà en cours d'exécution, de définir des points d'arrêt sur les appels système qu'ils utilisent et de réaliser bien d'autres choses essentielles au piratage.

Conclusion

Malgré son humidité évidente, Linice est tout à fait approprié pour déboguer des applications protégées, même si vous devez souvent recourir à des solutions de contournement exécutées automatiquement dans les débogueurs normaux. C'est pourquoi Linice ne remplace pas du tout gdb, mais le complète seulement.

Cette série d'articles est parue pour deux raisons. Tout d'abord, j'aime travailler avec le projet HackSysExtremeVulnerableDriver. Deuxièmement, j'ai reçu beaucoup de voeux pour aborder ce sujet.

Tout le code utilisé pour écrire cette série se trouve dans mon référentiel.

Dans cette série d'articles, nous examinerons l'écriture d'exploits au niveau du noyau sous Windows. Il est important de noter que nous traiterons de vulnérabilités connues et qu'il n'y a pas besoin de rétro-ingénierie (du moins pour le pilote).

Il est prévu qu'après avoir lu tous les articles, vous connaîtrez toutes les classes de vulnérabilités et méthodes d'exploitation les plus courantes, et serez également en mesure de porter les exploits de l'architecture x86 vers l'architecture x64 (si possible) et de vous familiariser avec les nouvelles méthodes de protection. sous Windows 10.

Circuit de débogage du noyau

Contrairement au débogage au niveau de l'utilisateur, qui suspend l'exécution d'un seul processus, le débogage au niveau du noyau implique l'ensemble du système et nous ne pourrons pas utiliser cette méthode. En conséquence, nous avons besoin d'une machine de débogage distincte capable de communiquer avec le système sur lequel le noyau est débogué, d'afficher la mémoire et les structures du noyau, et également de détecter les pannes du système.

Matériel supplémentaire à étudier :

Exploiter les vulnérabilités du noyau

Ce processus est bien plus amusant que d’opérer au niveau de l’utilisateur J.

L'objectif principal est d'obtenir une exécution privilégiée dans le contexte du noyau. Et puis tout dépend de notre imagination, d’un festin avec de la bière maison à l’introduction de logiciels malveillants parrainés par l’État.
En général, notre tâche est d'obtenir un shell avec les privilèges système.

Sujets des articles de cette série

  • Partie 1 : Configurer votre environnement de travail
    • Configuration de trois machines virtuelles et d'un système qui fera office de débogueur.
    • Configuration du débogueur WinDBG.
  • Partie 2 : Charges utiles
    • Explorez les charges utiles les plus courantes. Les parties suivantes aborderont des vulnérabilités spécifiques et, le cas échéant, fourniront des liens vers cet article.
  • Les parties restantes.
    • Prise en compte des vulnérabilités.

Cycle de vie du développement des exploits du noyau

  • Trouver une vulnérabilité. Ce sujet ne sera pas abordé dans cette série, car nous savons déjà exactement où se situent les lacunes.
  • Intercepter le fil d'exécution. Certaines vulnérabilités impliquent l'exécution de code et d'autres nécessitent des exigences supplémentaires.
  • Élévation de privilèges. L'objectif principal est d'obtenir un shell avec les privilèges système.
  • Restauration du fil d'exécution. Les exceptions non vérifiées au niveau du noyau provoquent le crash du système. Si vous n'écrivez pas d'exploit pour une attaque DoS, vous devez en tenir compte.

Types de systèmes cibles

Nous travaillerons avec les vulnérabilités des systèmes suivants (la version spécifique n'est pas importante) :

  • Machine virtuelle Win7 x86
  • Machine virtuelle Win7 x64
  • Machine virtuelle Win10 x64

Commençons par l'architecture x86, puis nous porterons l'exploit sur le système Win7 x64. Certains exploits ne fonctionneront pas sur les machines Win10 en raison de la présence de nouvelles protections. Dans ce cas, nous modifierons la logique de l’exploit ou utiliserons une approche complètement différente.

Logiciel utilisé :

  • Hyperviseur (beaucoup d'options).
  • Machine virtuelle Windows 7 x86
  • Machine virtuelle Windows 7 x64
  • Machine virtuelle Windows 10 x64

Configuration des systèmes pour le débogage

Les systèmes de débogage avec lesquels nous interagirons sont conçus pour charger le pilote vulnérable. Ces machines planteront fréquemment, puisque la plupart des exceptions du noyau contribuent à ce type de phénomène. Vous devez allouer suffisamment de RAM à ces systèmes.

Sur chaque machine qui sera déboguée, vous devez procéder comme suit :

  • Dans le répertoire VirtualKD, exécutez le fichier target\vminstall.exe. Une nouvelle entrée de démarrage sera ajoutée et des fonctions de débogage seront disponibles ainsi qu'une connexion automatique au serveur VirtualKD installé sur le système, qui fait office de débogueur.

Dans le cas d'une machine virtuelle Windows 10, vous devez activer le mode de signature de test, qui vous permet de charger des pilotes non signés dans le noyau.

Après avoir exécuté la commande bcdedit /set tests et redémarré, « Mode test » apparaîtra sur le bureau.

Brève description du module HEVD

La procédure DriverEntry est la procédure de démarrage de chaque pilote :

NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) (
UINT32 je = 0 ;
PDEVICE_OBJECT DeviceObject = NULL ;
Statut NTSTATUS = STATUS_UNSUCCESSFUL ;
UNICODE_STRING NomDePériphérique, DosDeviceName = (0);

UNREFERENCED_PARAMETER(RegistryPath);
PAGED_CODE();

RtlInitUnicodeString(&DeviceName, L"\\Device\\HackSysExtremeVulnerableDriver");
RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\HackSysExtremeVulnerableDriver");

//Créer l'appareil
Statut = IoCreateDevice (DriverObject,
0,
&Nom du périphérique,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FAUX,
&DeviceObject);

  • Cette procédure contient un appel à la fonction IoCreateDevice, qui contient le nom du pilote que nous utiliserons lors de la communication.
  • Les structures et pointeurs de fonction nécessaires seront ajoutés à l'objet DriverObject.
  • Ce qui est important pour nous, c'est le pointeur de fonction associé à la procédure DriverObject->MajorFunction, qui est responsable du traitement des IOCTL (I/O Control) ;
  • Dans HEVD, cette fonction s'appelle IrpDeviceIoCtlHandler, qui est une grande expression conditionnelle avec de nombreuses branches pour chaque IOCTL. Chaque vulnérabilité possède un IOCTL unique.

Exemple : HACKSYS_EVD_IOCTL_STACK_OVERFLOW est un IOCTL utilisé pour déclencher un exploit de dépassement de pile.

Ceci conclut la première partie. Dans le prochain article, nous parlerons des charges utiles. Pour le moment, la seule charge utile disponible est celle conçue pour voler des jetons, qui seront utilisés dans la troisième partie.

P.S. Je comprends que vous pourriez rencontrer de nombreuses subtilités et problèmes. Puisque cette série se concentre sur le développement d’exploits, vous devrez résoudre vous-même tous les problèmes associés. Cependant, vous pouvez poser toutes vos questions dans les commentaires.



Des questions ?

Signaler une faute de frappe

Texte qui sera envoyé à nos rédacteurs :