Obligement - L'Amiga au maximum

Mercredi 18 juillet 2018 - 10:33  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Accueil
 · A Propos
 · Articles
 · Galeries
 · Glossaire
 · Liens
 · Liste jeux Amiga
 · Quizz
 · Téléchargements
 · Trucs et astuces


Articles

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


Contact

David Brunet

Courriel

 


Programmation : Assembleur - Créer un antivirus (théorie et DoIO)
(Article écrit par Little Zeus et extrait d'Amiga News Tech - novembre 1989)


Nous allons profiter des virus pour explorer les fins fonds du matériel de l'Amiga. Effectivement, en exclusivité pour Amiga News Tech, voici un détecteur de virus qui se reproduit et qui est capable de détecter toute disquette infectée dès lors que l'utilisateur en insère une nouvelle dans le lecteur.

Eh oui, il ne se contente pas, comme la majorité des tueurs de virus, d'exterminer ces éléments gênants lorsque nous procédons à une nouvelle réinitialisation. Il est bien plus puissant que cela : imaginez que vous travaillez sous ProWrite et que, pour une raison ou une autre, vous deviez insérer une disquette sur laquelle vous désirez lire un fichier. Malheureusement, un virus figure sur cette disquette et s'installe en mémoire, puis se reproduit sur votre disquette de travail. Vous n'apprécierez certainement pas d'être définitivement interrompu après avoir tapé trois ou quatre pages...

L'antivirus made in Little Zeus que nous vous proposons à partir de ce mois-ci, reconnaît le virus dès lors que vous avez inséré la disquette contaminée dans l'un des lecteurs attachés à l'ordinateur, la purifie aussitôt, puis efface le virus logé dans la mémoire.

Nous nous sommes toujours efforcés de présenter chaque routine comme un exemple d'application de cours théorique. L'antivirus que nous allons étudier s'inscrit dans cette optique : nous ne doutons pas que vous aviez déjà à votre disposition quelque antivirus (VirusX ou autre)... Néanmoins, le nôtre, outre le fait qu'il se démarque des autres par son originalité et sa puissance, va nous servir de prétexte pour examiner les "devices" de l'Amiga, en particulier le lecteur de disquettes.

Brève théorie sur les entrées/sorties

Les entrées/sorties (ou input/output, souvent notées I/O) désignent tout ce qui concerne les échanges de données entre l'ordinateur et ses périphériques (imprimante, modem mais aussi et surtout pour le cas qui nous intéresse, lecteurs de disquette).

Il existe deux moyens de les gérer : le premier, bien que très simple car faisant appel aux routines de la dos.library, apparaît limité, cette dernière ne pouvant fonctionner en multitâche. Le second consiste à faire appel aux périphériques logiques. Cette méthode permet d'effectuer toutes les opérations d'entrées/sorties tout en poursuivant le programme en cours. Vous l'aurez sans aucun doute deviné, c'est cette méthode qui va nous intéresser, car, ne l'oublions pas, notre antivirus doit pouvoir détecter (et éliminer !) les virus tout en laissant les différentes tâches en cours se poursuivre normalement.

Les périphériques logiques

Nous venons d'énoncer le mot "device" sans pour autant l'avoir défini. Qu'à cela ne tienne, voici une définition bien exhaustive : les périphériques logiques sont des programmes implantés en ROM, habituellement appelés par les routines des différentes bibliothèques (mais nous allons voir que l'on peut procéder autrement). Dans des conditions normales (ce que nous ne faisons jamais car nous préférons bidouiller afin de présenter des techniques plus intéressantes...), l'utilisation des périphériques logiques implique quatre étapes (quatre appels de fonctions de la bibliothèque Exec), que voici :
  • FindTask0 permet de pointer sur une tâche. Avec un paramètre de valeur 0, c'est la tâche en cours qui est pointée, en l'occurence, le programme à partir duquel on a appelé FindTask.
  • AddPort0 structure un port réponse au périphérique logique dont on fournit préalablement l'adresse de base.
  • OpenDevice0 ouvre le périphérique logique et initialise la structure I/O.
  • DoIO() lance le périphérique logique.
C'est intentionnellement que ces explications sont très superficielles. Effectivement, nous survolons ces étapes uniquement dans un dessein démonstratif, pour attirer votre attention sur le fait que "passer par la porte de devant" ferait tellement appel aux bibliothèques que nous perdrions un temps fou, ainsi que toute liberté de programmation. Nous allons donc nous intéresser uniquement aux I/O et à DoIO.

Le tableau qui suit indique les différentes adresses des I/O. Attention, ces dernières sont données en offset négatif, c'est-à-dire que le nombre correspondant à chacune des adresses ôté à l'adresse de base donne l'adresse de la case mémoire qui nous intéresse. Ainsi, pour la dernière ligne du tableau, "I/O Data" est la case mémoire ayant pour adresse valeur de base mois 40.

Offset Nom Fonction
0 Succ Prochaine entrée
4 Pred Entrée précédente
8 Type Type d'entrée
9 Pri Priorité
10 Name Nom
14 ReplyPort ReplyPort
31 I/O_Error Niveau de l'erreur
32 I/O_Actual Nombre d'octets transférés
36 I/O_Length Nombre d'octets à transférer
40 I/O_Data Tampon des données

Nous avons sciemment omis d'inscrire dans le tableau certaines adresses, car peu utilisées.

DoIO, quèsako ?

DoIO est une routine de la bibliothèque Exec qui nécessite pour paramètre le nom du périphérique avec lequel elle doit travailler. En fait, le système d'exploitation fait perpétuellement appel à DoIO pour quelque opération d'entrée/sortie que ce soit. D'une manière plus explicite, si vous envoyez des données en direction de votre imprimante, le système d'application fait appel à DoIO en lui ayant préalablement spécifié le périphérique intéressé. Il en va de même pour le modem ou le lecteur de disquette.

Nous allons avantageusement tirer profit de DoIO au moyen d'un subterfuge assez puissant : étant donné que toute disquette insérée dans le lecteur est lue par DoIO, il suffit de modifier cette routine de telle manière qu'au lieu de se charger uniquement d'assurer le transfert des données entre le lecteur et l'ordinateur, DoIO puisse aussi vérifier la disquette. Ainsi, à chaque fois que vous rentrerez une disquette dans l'un des deux drives, ces dernières seront automatiquement vérifiées. Cependant, il reste un problème (que nous allons résoudre un peu plus loin) : comment être certain que DoIO a bel et bien été appelé pour faire l'un des drives et non pour l'imprimante ou un autre périphérique ?

Une fois certain qu'il est bien question de lecteur, il faut dans un premier temps repérer lequel (DF0 à DF3), puis dans un second temps examiner la disquette, avant de proposer, le cas échéant, de la purifier et de copier l'antivirus sur la première piste).

Mais avant d'aller plus loin dans les détails, attardons-nous sur la structure d'une disquette et sur le fonctionnement de DoIO lorsqu'elle travaille exclusivement avec les lecteurs.

Les lecteurs de disquette

Tout d'abord, un peu de théorie sur la structure d'une disquette : une disquette 3"1/2 compte habituellement 80 pistes, numérotées de 0 à 79. Chaque piste correspond à un sillon : la piste 0 correspond au cercle concentrique périphérique et la piste 79 au cercle intérieur. La disquette compte deux côtés (ou faces) servant de support aux pistes (tracks ou cylindres, termes équivalents). Chaque cylindre connaît une sous-division en onze secteurs (ou blocs). En général, et bien que ces deux termes désignent les mêmes éléments, on compte les secteurs de 0 à 10 pour chaque piste et les blocs de 0 à 1759 pour l'ensemble de la disquette. Enfin, chaque secteur contient 128 longs mots, soit 512 octets.

Cela ne signifie pas pour autant que nous avons à notre disposition 1760x512=901 120 octets disponibles sur la disquette : vous comprendrez facilement que les données ne sont pas écrites aléatoirement mais suivant un plan. C'est d'ailleurs au sein de celui-ci que figurent toutes les données du démarrage (les toutes premières étapes de la lecture). Les blocs d'amorce (en anglais, bootblocks) sont les deux premiers de la disquette (numéros 0 et 1). Ils spécifient le type de la disquette, à savoir DOS ou non-DOS. De plus, ils indiquent au système d'exploitation le numéro du bloc racine (en général le 880e) et contiennent parfois un programme "autoboot".

Les programmeurs de virus, et nous aussi par la même occasion, ont profité de cette caractéristique des blocs d'amorce. Cependant, afin que l'utilisateur ne suspecte pas la présence du virus, celui-ci est conçu de telle manière qu'après avoir été chargé et exécuté, il poursuive la procédure normale d'amorce (initialisation d'AmigaDOS, exécution de la startup-sequence, etc.). C'est d'ailleurs pour cette raison que l'implantation de virus sur des disquettes non amorçables les rend inutilisables. A titre d'exemple, les logiciels de Psygnosis utilisent ce procédé du bloc d'amorce et toute écriture sur ce dernier déprave le jeu.

Par curiosité, sachez que l'Amiga lit alternativement les faces supérieures et inférieures des disquettes de la façon suivante : d'abord sont lus les blocs 0 à 10 qui se trouvent sur la piste 0 de la face 0, puis le bloc 11 qui lui, par contre, correspond au premier secteur de la première piste de la seconde face.

Les disquettes et la routine

Après avoir repéré le lecteur mis en marche au moyen de DoIO, notre antivirus doit s'assurer qu'il s'agit bel et bien d'un transfert de données entre les blocs d'amorce et la mémoire. Dans ce cas, tout laisse croire qu'un virus est en train de s'implanter en mémoire. Pour le confirmer, il suffit de comparer les chaînes de caractères typiques de chaque virus avec celles des blocs d'amorce se situant à l'emplacement sur lequel la présumée chaîne devrait se trouver. Dans la situation pour laquelle un virus existe, notre programme offre la possibilité de l'effacer et par la même occasion de se loger à sa place dans les blocs d'amorce.

Un secret bien intéressant

Examinons maintenant de plus près le subterfuge qui nous permet de détourner la routine DoIO. Cette dernière prend place dans la bibliothèque Exec à l'offset -456 (l'offset d'une bibliothèque présente une certaine similitude avec celui d'un périphérique logique : il correspond à la valeur à déduire à l'adresse de base de la bibliothèque). Ainsi, pour appeler, d'une manière normale, DoIO, il faut écrire les deux lignes suivantes :

Move.1 ExecBase.a6
jsr -456(a6)

Une bibliothèque se présente comme une suite de sauts (instruction jmp) aux adresses réelles de ses fonctions. Étant donné qu'elles se trouvent en mémoire, il existe un procédé simple permettant de détourner le saut à une fonction donnée sur une routine de notre cru (ici, notre antivirus) : il consiste à échanger l'adresse du jmp dans la bibliothèque par celle de notre routine. Cependant, une difficulté apparaît : la routine de la bibliothèque ne doit pas purement et simplement disparaître du système (sans DoIO, l'Amiga ne pourrait pour ainsi dire plus rien faire !) ; notre routine doit donc se charger de l'appeler avant de tester la disquette, éventuellement la purifier, puis retourner au programme en cours.

Le vecteur reset

La toute première étape de l'antivirus est sans doute sa mise en action. Ceci se fait dès l'instant où l'on effectue une réinitialisation (touches "Control-Amiga gauche-Amiga droite").

L'Amiga, comme la plupart des ordinateurs, stocke en mémoire l'adresse du programme à exécuter à la suite d'une réinitialisation. Ce vecteur est aussi appelé CoolCapture. Le principe est simple : il faut détourner CoolCapture sur l'adresse de notre routine. Ainsi, à chaque réinitialisation, notre programme est-il exécuté.

J'en vois certains qui perdent le fil de l'histoire : on a dit tout à l'heure que l'antivirus se mettait en marche via DoIO et voilà maintenant que nous déclarons que cela se fait après la réinitialisation ! Ne vous alarmez pas, notre antivirus est en fait "doublement" appelé. La raison en est simple : à chaque réinitialisation, l'Amiga remet en place tous ses pointeurs, dont évidemment DoIO. De fait, notre antivirus, bien que toujours en mémoire, ne serait plus actif, s'il ne prenait le soin de détourner également CoolCapture sur la routine détournant DoIO... et CoolCapture pour survivre à la prochaine réinitialisation !

Dans un dessein didactique (mais aussi parce que nous avons rempli l'espace qui nous était imparti), nous vous laissons essayer de comprendre la partie de l'antivirus publiée ce mois-ci sans autres explications. Effectivement, grâce à ce que nous avons étudié dans ce numéro et moyennant réflexion, vous devriez comprendre.

assembleur
assembleur
assembleur


[Retour en haut] / [Retour aux articles] [Article suivant]