home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Supreme Volume 6 #1
/
swsii.zip
/
swsii
/
126
/
BOOTPW.ZIP
/
BOOTPW.ASM
< prev
next >
Wrap
Assembly Source File
|
1993-03-02
|
25KB
|
893 lines
page 66,132
;====================================================================
;
; BOOTPW - A program to password protect a disk
;
; Copyright (c) 1993 Douglas Boling
;
;====================================================================
code segment
assume cs:code
org 100h
;====================================================================
;BOOTPW Boot record
;
; Entry:
; CS:IP - 0:7C00h
; DL - boot drive
; ES:SI - Ptr to partition table boot entry (if hard disk.)
; All other registers undefined
;====================================================================
root_offset equ 500h
boot_buffer equ offset end_of_code + 512
pw_nonres equ offset password_size - offset entry
data_startl equ word ptr [bp]
data_starth equ word ptr [bp+2]
boot_disk equ byte ptr [bp+4]
bytes_per_sec equ word ptr [bp+0bh]
sec_per_cluster equ byte ptr [bp+0dh]
reserved_sec equ word ptr [bp+0eh]
number_of_fats equ byte ptr [bp+10h]
root_size equ word ptr [bp+11h]
total_sec equ word ptr [bp+13h]
media_des_byte equ byte ptr [bp+15h]
sec_per_fat equ word ptr [bp+16h]
sec_per_track equ word ptr [bp+18h]
number_of_heads equ word ptr [bp+1ah]
num_hidden_sec equ word ptr [bp+1ch]
boot_flag equ word ptr [bp+3feh]
oldboot_name equ 7c00h + offset oldboot_nameo - offset entry
boot_initmsg equ 7c00h + offset program - offset entry
boot_pwmsg equ 7c00h + offset pw_msg - offset entry
boot_perrmsg equ 7c00h + offset pwerror_msg - offset entry
boot_rerrmsg equ 7c00h + offset readerr_msg - offset entry
boot_ferrmsg equ 7c00h + offset finderr_msg - offset entry
boot_pw equ 7c00h + offset password - offset entry
boot_pwsize equ 7c00h + offset password_size - offset entry
;--------------------------------------------------------------------
;Boot sector code
;--------------------------------------------------------------------
entry: jmp initialize
oem_field db "BootPW10"
bpb_data db 24 dup (0) ;Leave room for rest of BPB
bpb_dataend = $
boot_1:
cli ;Disable interrupts
cld ;Set direction UP.
mov ax,7c00h
xor bx,bx
mov ss,bx ;SS:SP = 790:0
mov sp,ax
sti ;Interrupts OK
mov ds,bx
mov es,bx
push si ;Save Part table ptr
push bp
mov bp,ax
mov boot_disk,dl
mov al,number_of_fats ;Compute the sector of the
cbw ; roor directory.
mul sec_per_fat
mov cx,reserved_sec
add cx,num_hidden_sec
adc dx,num_hidden_sec[2]
add cx,ax
adc dx,bx ;BX = 0
push cx ;Save root sector low
push dx ;Save root sector high
mov data_startl,cx
mov data_starth,dx
mov ax,32 ;Get length of dir entry
mul root_size ;Compute the size -in sectors-
mov si,bytes_per_sec ; of the Root Directory.
add ax,si
dec ax
div si
add data_startl,ax
adc data_starth,bx
push ax
pop cx
pop dx ;Get root directory
pop ax ; starting sector
mov bx,root_offset ;Read the root dir
push bx ;Save ptr to Root dir
boot_3:
push cx
push ax
push dx
call boot_read_disk ;Loop on read_disk to
pop dx ; read in all sectors
pop ax ; of the root dir
pop cx
jc boot_error
add bx,bytes_per_sec
add ax,1
adc dx,0
loop boot_3
mov si,boot_initmsg ;Identify ourselves
call bootprint_msg
mov si,boot_pwmsg ;Prompt for PW
call bootprint_msg
mov di,7c00h
call read_line ;Get password
mov si,boot_pwsize
lodsb
cmp cl,al
jne boot_badpw
rep cmpsb
jne boot_badpw
pop si ;Get back Root ptr
mov bx,root_size
boot_4:
mov di,oldboot_name ;Find old boot record
mov cx,8 ; in root directory
push si
repe cmpsb
pop si
je boot_5
add si,32
dec bx
jne boot_4
mov si,boot_ferrmsg
jmp short boot_error
boot_5:
mov cx,word ptr [si+1ah] ;Get start clust
dec cx ;Compensate for 1st to FAT
dec cx ; entries not being used.
mov al,sec_per_cluster ;Get sectors per cluster
cbw
mul cx
add ax,data_startl
adc dx,data_starth
mov bx,7e00h ;To address 0:7E00
call boot_read_disk
jc boot_error
xor ax,ax
cwd
call boot_write_disk
pop bp
pop si
int 19h ;Reboot
boot_badpw:
mov si,boot_perrmsg
boot_error:
call bootprint_msg
boot_halt:
jmp boot_halt
;-----------------------------------------------------------------------
; Write/Read disk - Writes or reads one sector from the disk
; Entry: DX,AX - Absolute sector to write/read
; BX - address of buffer.
; Exit: CF - Clear if read successful.
;-----------------------------------------------------------------------
boot_write_disk proc near
mov cx,0301h
jmp short read_1
boot_read_disk proc near
mov cx,0201h
read_1:
push cx
push bx
div sec_per_track ;Get sectors per track
inc dx
read_2:
mov bx,dx ;Save sector
cwd
div number_of_heads ;Compute head and cylinder
xchg ah,al ;Swap cyl low and high bytes
mov cl,6
shl al,cl ;Shift high cyl bits
xchg cx,ax ;Copy cyl into CX
or cl,bl ;Combine cyl with sector
mov dh,dl ;Move head number
mov si,5 ;Try to read 5 times.
pop bx ;Get dest buff offset
pop ax ;Get Read/Write cmd
read_3:
mov dl,boot_disk ;Get disk to read
push ax
int 13h ;Read/Write disk.
pop ax
jnc read_exit ;No error, exit
xor ax,ax ;Reset disk before reading
int 13h
dec si
jnz read_3
mov si,boot_rerrmsg
stc
read_exit:
ret
boot_read_disk endp
boot_write_disk endp
;--------------------------------------------------------------------
; Print Msg - Prints a message to the screen
; Entry: DS:SI - Points to ASCIIZ message
;--------------------------------------------------------------------
bootprint_msg proc near
push bx
push bp
bprint_msg1:
lodsb
or al,al
je bprint_exit
mov ah,0eh
mov bx,7h
push si
int 10h
pop si
jmp short bprint_msg1
bprint_exit:
mov ax,0e0dh ;Append CR - LF
int 10h
mov ax,0e0ah
int 10h
pop bp
pop bx
ret
bootprint_msg endp
password_size db 0
password db 4eh,75h,0f0h,0beh,7dh,0b4h,0f9h,0c3h
;--------------------------------------------------------------------
; Read Line - Reads upto 8 charagers from the keyboard - No echo
; Entry: DS:DI - Points to buffer
; Exit: CX - Number of characters in buffer
;--------------------------------------------------------------------
read_line proc near
push di
mov cx,8
readl_1:
xor ax,ax ;Get key
int 16h
cmp al,13
je readl_exit
cmp al,8
je readl_2
not al
stosb
loop readl_1
readl_exit:
sub cx,8
neg cx
pop di
ret
readl_2:
cmp cx,8
je readl_1
dec di
inc cx
jmp short readl_1
read_line endp
program db 13,10,"BOOTPW 1.0 "
db "Copyright 1993 Douglas Boling",0
pw_msg db 13,10,10,"Enter Password",0
pwerror_msg db "Wrong password",0
readerr_msg db "Read Error",0
finderr_msg db "Can",39,"t find "
oldboot_nameo db "OLDBOOT BIN",0
bootcode_end = $
org 2feh
dw 0AA55h ;Boot signature
boot_end = $
;====================================================================
;Start of nonresident install code
;====================================================================
program1 db "First published in PC Magazine, "
db "March 30, 1993",13,10,10,0
infomsg1 db "USAGE: BOOTPW d:",13,10
db "d: is the target diskette to "
db "password protect",0
infomsg3 db "Please enter password, up to 8 characters",0
infomsg4 db "Please reenter password for verification",0
infomsg5 db 13,10,"Disk "
infomsg5_dsk db " : Password protected.",0
infomsg6 db 13,10,"Password removed",0
infomsg7 db "Disk password protected",0
infomsg8 db 13,10,"Please remove the disk from the drive "
db "and press <Enter>",13,10
db "or if the disk is a hard drive, turn off the system.",0
errmsg0 db "This program requires DOS 2.0 or greater",0
errmsg1 db "Target drive letter not specified",0
errmsg2 db "Target diskette not a DOS formatted "
db "disk",0
errmsg3 db "Unable to fit BOOTPW code on "
db "target disk",0
errmsg4 db "Passwords do not match",0
errmsg5 db "No password entered, disk not modified",0
errmsg6 db "The password doesn't match the disk "
db "password",0
errmsg7 db "Unable to find old DOS boot record",0
dos_version dw 0
crit_vec dd 0 ;Critical err vector
targ_disk db 0 ;Disk to modify
oldboot_fname db "C:\OLDBOOT.BIN",0
doserr_tbl dw offset doserr_00
dw offset doserr_01
dw offset doserr_02
dw offset doserr_03
dw offset doserr_04
dw offset doserr_05
dw offset doserr_06
dw offset doserr_07
dw offset doserr_08
dw offset doserr_09
dw offset doserr_10
dw offset doserr_11
dw offset doserr_12
dw offset doserr_unk
doserr_tblend = $
doserr_00 db "Disk Write Protected",0
doserr_01 db "Unknown Unit",0
doserr_02 db "Drive not ready",0
doserr_03 db "Unknown Command",0
doserr_04 db "CRC Data Error",0
doserr_05 db "Bad request structure",0
doserr_06 db "Disk Seek error",0
doserr_07 db "Not a DOS disk",0
doserr_08 db "Sector not found",0
doserr_09 db "Printer out of paper",0
doserr_10 db "Disk Write fault",0
doserr_11 db "Disk Read fault",0
doserr_12 db "General failure",0
doserr_unk db "Unknown DOS error",0
;--------------------------------------------------------------------
; INITIALIZE - Entry point of nonresident code
;--------------------------------------------------------------------
initialize:
cld ;String ops UP
mov ah,30h ;Get DOS version
int 21h
xchg al,ah
mov si,offset errmsg0
cmp ax,200h
jb init_jmperror
mov dos_version,ax
mov si,offset program ;Print copyright msg
call print_msg
mov si,offset program1
call print_msg
call set_crit_vec ;Set crit vec to int routine
mov si,offset infomsg1 ;Syntax msg text
cmp byte ptr ds:[80h],0
je init_jmperror
mov si,offset 81h
call get_drive ;Get target disk
jc init_jmperror
mov targ_disk,al ;Save drive number
mov oldboot_fname,ah ;Save drive letter
mov bx,boot_buffer
call read_boot ;Read current boot record
jc init_jmperror
call check4bpw ;See if BOOTPW protected
jnz init_3
mov si,offset infomsg7 ;Tell user disk protected
call print_msg
mov si,offset infomsg3 ;Password prompt
call print_msg
mov di,offset end_of_code
call read_line
mov si,boot_buffer
add si,pw_nonres
lodsb
cmp al,cl
jne init_1 ;PW lengths don't match
rep cmpsb
jne init_1 ;PWs don't match
call uninstall
jc init_error
jmp short init_exit
init_1:
mov si,offset errmsg6 ;Bad password
init_jmperror:
jmp short init_error
init_3:
mov si,offset infomsg3 ;Password prompt
call print_msg
mov di,offset end_of_code
call read_line
mov si,offset errmsg5 ;Password not entered
jcxz init_error
push cx
mov si,offset infomsg4 ;Password verify prompt
call print_msg
mov di,offset end_of_code+16
call read_line
mov si,offset errmsg4 ;Passwords don't match
pop bx
cmp cx,bx
jne init_error
mov si,offset end_of_code
mov di,offset end_of_code+16
push cx
rep cmpsb
pop cx
mov si,offset errmsg4 ;Passwords don't match
jne init_error
mov si,offset end_of_code
mov di,offset password
mov password_size,cl
rep movsb ;Copy password
call install
init_4:
mov si,offset infomsg8 ;Make user remove the disk
call print_msg
mov ah,7 ;DOS read key
int 21h
or al,al
jne init_5
mov ah,7
int 21h
init_5:
cmp al,27
je init_6
mov ah,1ch ;Get allocation info
mov dl,targ_disk
inc dl
int 21h
jnc init_4
init_6:
xor ax,ax ;Clear return code
init_exit:
push ax
call reset_crit_vec ;Restore critical error vec
pop ax
mov ah,4ch
int 21h
init_error:
call print_msg
mov al,1
jmp short init_exit
;--------------------------------------------------------------------
;GET DRIVE - Returns a disk number for a letter on the command line
; Entry: SI - Ptr to command line
; Exit: AL - Drive number
; AH - Drvie letter
; SI - Points to character after :
; CF - Set if error
; DX - Offset of error message if CF set
;--------------------------------------------------------------------
get_drive proc near
lodsb
cmp al,13 ;See if end of line
je getdisk_err
cmp al,20h ;If space, keep looking
jbe get_drive
mov ah,al ;Save letter in AH
and ah,0dfh ;Convert to upper case
or al,20h ;Convert to lower case
sub al,'a' ;See if between a - z
jb getdisk_err
cmp al,25
ja getdisk_err
mov bl,al
lodsb ;See if trailing :
cmp al,":" ; present.
jne getdisk_err
mov al,bl ;Get back drv letter
cmp al,2
jb getdisk_1
mov al,80h
getdisk_1:
clc
getdisk_exit:
ret
getdisk_err:
mov si,offset errmsg1
stc
jmp short getdisk_exit
get_drive endp
;--------------------------------------------------------------------
;INSTALL - Installs the BOOTPW boot record on the target diskette
; Exit: CF - Set if error
; DX - Offset of error message if CF set
;--------------------------------------------------------------------
install proc near
mov di,offset entry
mov ax,0eb90h ;NOP + JMP short opcode
stosw
mov ax,offset boot_1 - offset bpb_data
stosb
mov si,boot_buffer ;Get ptr to boot rec
lodsb
mov bl,al ;Get opcode
lodsw
cmp bl,0ebh ;See if short JMP opcode
jne install_1
xor ah,ah ;If short JMP, clear
jmp install_2 ; high byte
install_1:
mov si,offset errmsg2
cmp bl,0e9h ;Check for long JMP
jne install_error
install_2:
mov si,boot_buffer+11
mov di,offset bpb_data ;Copy BIOS Param Blk
mov cx,offset bpb_dataend - offset bpb_data - 8
rep movsb
mov ah,3ch ;Create file
mov cx,2 ;Make hidden
mov dx,offset oldboot_fname
push ds
int 21h
pop ds
mov si,offset errmsg3
jc install_exit
mov bx,ax ;Copy file handle
mov ah,40h
mov cx,512 ;Write 512 bytes
mov dx,boot_buffer
int 21h
mov si,offset errmsg3
jc install_exit
mov ah,3eh ;Close file
int 21h
mov si,offset errmsg3
jc install_exit
mov al,targ_disk ;Get target disk
mov bx,offset entry ;Point to BootPW rec
call write_boot ;Write new boot rec
jc install_exit
mov al,oldboot_fname
mov infomsg5_dsk,al
mov si,offset infomsg5 ;Indicate installed
call print_msg
clc
install_exit:
ret
install_error:
stc
jmp short install_exit
install endp
;--------------------------------------------------------------------
;UNINSTALL - Uninstalls BOOTPW from the target disk
; Exit: CF - Set if error
; DX - Offset of error message if CF set
;--------------------------------------------------------------------
uninstall proc near
mov di,boot_buffer
mov al,0ebh ;JMP short opcode
stosb
mov al,offset boot_1 - offset bpb_data + 1
stosb
mov al,90h
stosb
mov al,targ_disk ;Get target disk
mov bx,boot_buffer ;Point to BootPW rec
call write_boot ;Write new boot rec
jc uninstall_error
mov ah,0dh ;Reset disks
int 21h
mov ax,3d00h ;Open file
mov dx,offset oldboot_fname ;Open file that has
int 21h ; old boot rec
mov si,offset errmsg7
jc uninstall_exit
mov bx,ax ;Copy file handle
mov ah,3fh
mov cx,512 ;Read 512 bytes
mov dx,boot_buffer
int 21h
mov si,offset errmsg7
jc uninstall_exit
mov ah,3eh ;Close file
int 21h
mov si,offset errmsg7
jc uninstall_exit
mov al,targ_disk ;Get target disk
mov bx,boot_buffer ;Point to DOS rec
call write_boot ;Write DOS boot rec
jc uninstall_exit
mov si,offset infomsg6 ;Tell user, disk
call print_msg ; unprotected.
uninstall_exit:
ret
uninstall_error:
stc
jmp short uninstall_exit
uninstall endp
;--------------------------------------------------------------------
; CHECK4BPW - Check boot record to see if it is a BootPW boot rec
; Exit: ZF - Set if BootPW record
;--------------------------------------------------------------------
check4bpw proc near
mov si,boot_buffer
add si,3
mov di,offset oem_field
mov cx,8
rep cmpsb
ret
check4bpw endp
;--------------------------------------------------------------------
; READ BOOT - Reads the boot sector of a disk
; Entry: AL - Disk number (0=A, 1=B,...)
; BX - Points to buffer
; Exit: CF - Set if error
; DX - Points to error message
;--------------------------------------------------------------------
read_boot proc near
mov al,targ_disk ;Get target disk
mov cx,1 ;read 1 sector
mov dx,0 ;Sector 0
call read_absolute ;Read current boot rec
ret
read_boot endp
;--------------------------------------------------------------------
; WRITE BOOT - Wrotes the boot sector of a disk
; Entry: AL - Disk number (0=A, 1=B,...)
; BX - Points to buffer
; Exit: CF - Set if error
; DX - Points to error message
;--------------------------------------------------------------------
write_boot proc near
mov al,targ_disk ;Get target disk
mov cx,1 ;read 1 sector
mov dx,0 ;Sector 0
call write_absolute ;Read current boot rec
ret
write_boot endp
;--------------------------------------------------------------------
; READ ABSOLUTE - Reads sectors from the disk.
; Entry: AL - Letter of drive to read
; CX - Number of sectors to read.
; SI,DX - Sector to start read (SI only used on huge disks)
; DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------
read_abs_hstruc = $ ;Needed for >32M disks
read_abs_start dd 0 ;Starting sector
read_abs_cnt dw 0 ;Number of sectors to read
read_abs_dbp dd 0 ;Data buffer ptr
read_absolute proc near
push bx
push cx
push ds
call huge_disk_check
jc read_abs_2
je read_abs_1
push ds ;Save ptr to data buffer
push bx
push cs
pop ds
mov bx,offset read_abs_hstruc
mov [bx],dx ;More than 64K sectors
mov [bx+2],si ; -> huge disk uses a
mov [bx+4],cx ; different format
pop [bx+6] ; than std int 25h.
pop [bx+8]
mov cx,-1
read_abs_1:
int 25h ;DOS Absolute Disk Read
pop bx ;Clean off old flags
call seterrmsg
cld
read_abs_2:
pop ds
pop cx
pop bx
ret
read_absolute endp
;--------------------------------------------------------------------
; WRITE ABSOLUTE - Writes sectors to the disk.
; Entry: AL - Letter of drive to write
; CX - Number of sectors to write
; SI,DX - Sector to start write (SI only used on huge disks)
; DS:BX - Pointer to data buffer.
;--------------------------------------------------------------------
write_absolute proc near
push bx
push cx
push ds
call huge_disk_check
jc write_abs_2
je write_abs_1
push ds ;Save data buffer pointer
push bx
push cs
pop ds
mov bx,offset read_abs_hstruc
mov [bx],dx ;More than 64K sectors
mov [bx+2],si ; -> huge disk uses a
mov [bx+4],cx ; different format
pop [bx+6] ; than std int 26h.
pop [bx+8]
mov cx,-1
write_abs_1:
int 26h ;DOS Absolute Disk Write
pop bx ;Clean off old flags
call seterrmsg
cld
write_abs_2:
pop ds
pop cx
pop bx
ret
write_absolute endp
;--------------------------------------------------------------------
; HUGE DISK CHECK - Checks if disk is greater than 32 Meg
; Entry: AL - Disk to check
; Exit: ZF - Clear if > 32 Meg disk
; CF - Set if error
; DI - Sectors per cluster
;--------------------------------------------------------------------
last_disk_read db -1
last_disk_huge db 0
last_disk_spc dw 0
huge_disk_check proc near
push ax
push bx
push cx
push dx
cmp al,last_disk_read ;Save last disk checked, if
jne huge_disk_check_1 ; same as last disk, just
mov di,last_disk_spc ; get saved answer.
cmp last_disk_huge,0
jmp short huge_disk_check_3
huge_disk_check_1:
mov last_disk_read,al
mov last_disk_huge,0
mov dl,al ;Copy disk number
inc dl
mov ah,36h ;DOS Get Free disk space
int 21h
cmp ax,-1
jne huge_disk_check_2
mov last_disk_read,-1
jmp short huge_disk_check_4
huge_disk_check_2:
mov di,ax ;Save sectors per cluster
mov last_disk_spc,di
mul dx
or dx,dx ;See if more than 64K sectors
je huge_disk_check_3
mov last_disk_huge,1
huge_disk_check_3:
clc
huge_disk_check_4:
pop dx
pop cx
pop bx
pop ax
ret
huge_disk_check endp
;--------------------------------------------------------------------
; SET CRIT VEC - Sets the critical error vector to an internal routine
; to avoid the abort, retry, ignore message.
;--------------------------------------------------------------------
set_crit_vec proc near
push es
mov ax,3524h ;Get crititcal error vector
int 21h
mov word ptr crit_vec,bx ;Save vector
mov word ptr crit_vec[2],es
mov dx,offset crit_error ;Set to internal routine.
mov ax,2524h
int 21h
pop es
ret
set_crit_vec endp
;--------------------------------------------------------------------
; RESET CRIT VEC - Resets the critical error vector to its original
; state.
;--------------------------------------------------------------------
reset_crit_vec proc near
push ds
lds dx,crit_vec ;Get old vector
mov ax,2524h ;Set vector
int 21h
pop ds
ret
reset_crit_vec endp
;--------------------------------------------------------------------
; SETERRMSG - Assigns a DOS error message to the value in AL
; Entry: AL - Error code
; CF - Set if error
; Exit: SI - Points to error message
;--------------------------------------------------------------------
seterrmsg proc near
push bx
pushf
jnc seterrmsg_exit
mov bx,ax
xor bh,bh
shl bx,1
cmp bx,offset doserr_tblend - offset doserr_tbl
jbe seterrmsg_1
mov bx,26
seterrmsg_1:
mov si,[bx+doserr_tbl]
seterrmsg_exit:
popf
pop bx
ret
seterrmsg endp
;--------------------------------------------------------------------
; Print Msg - Prints a message to the screen
; Entry: DS:SI - Points to ASCIIZ message
;--------------------------------------------------------------------
crlf_msg db 13,10,"$"
print_msg proc near
print_msg1:
lodsb
or al,al
je print_exit
mov dl,al
mov ah,02
int 21h
jmp short print_msg1
print_exit:
mov dx,offset crlf_msg
mov ah,9
int 21h
ret
print_msg endp
;-----------------------------------------------------------------------------
; Prevent Abort,Retry,Ignore error msg with this dummy crit. error routine
;-----------------------------------------------------------------------------
crit_error proc far
mov al,0 ;Ignore critical error.
cmp cs:dos_version,300h
jb crit_1
mov al,3
crit_1:
iret
crit_error endp
even
end_of_code = $
code ends
end entry