home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- TITLE PASSWRD5.ASM - PASSWRD5.SYS DEVICE DRIVER
- ;------------------------------------------------------------
- ;[from SIMTEL20's PD:<MSDOS.SYSUTL>PASSWORD.ARC, tweaked]
-
- ;PASSWRD5.ASM (CREATES PASSWRD5.SYS, DEVICE DRIVER)
- ;DOS 2.00 DEVICE DRIVER FORCES USER TO ENTER PASSWORD ON BOOTING UP
- ;AND DISABLES Ctrl-Break.
- ;
- ;v1.5 19 Sep 88
- ; - Got a msg from Bernie Eiben, explaining what's going on with the Init
- ; procedure and why the code got overlaid/garbaged on installation.
- ; Turns out I did good in moving Ask_Off up in the code (even tho
- ; I didn't know why). Comments edited and clarified.
- ; - Added version number to the device_name
- ; - Let the compiler compute password length, password space padding
- ;David Kirschbaum
-
- ;v1.4 Toad Hall Tweak, 7 Aug 88
- ; - Tightened code a little.
- ; - changed "ESC" to "ESCP" so MASM 5.0 wouldn't complain.
- ; - Reorganized to put things more inline, keep FAR things FAR.
- ;David Kirschbaum
- ;Toad Hall
- ;kirsch@braggvax.ARPA
-
- ; REV by JOHN R. PETROCELLI 02/25/85
- ;
- ; ADDITIONAL CODE HAS BEEN ADDED TO INITIALIZE INT 66h WITH THE
- ; SEGMENT AND OFFSET OF THE "RECALL" CODE (Ask_Off). USING THE
- ; PROGRAM "LOCK.COM" WILL ENABLE THE USER TO DISABLE THE USE OF THE
- ; PC UNTIL THE CORRECT PASSWORD IS SUPPLIED.
- ;
- ;AFTER ASSEMBLY: LINK PASSWRD5 (ignore "no STACK" error)
- ; EXE2BIN PASSWRD5 PASSWRD5.SYS
- ; (Or use one of the public domain EXE2COM utilities,
- ; insuring any product is a .SYS type.)
- ; Place DEVICE=PASSWRD5.SYS in CONFIG.SYS file
- ; Reboot system with Ctrl-Alt-Del
- ; Answer prompt with : Password <ENTER>
- ; **** BEWARE OF UPPER VS LOWER CASE ****
- ;
-
- DEV_SEG SEGMENT
- ASSUME CS:DEV_SEG, DS:DEV_SEG, ES:DEV_SEG
- org 0 ;TH
-
- Pword_Device PROC FAR
-
- ;---------------------------------------------------------------
- ;The following lines are the device header, which must exist for
- ;every device. This file has only one device, and it works with
- ;character I/O. It doesn't actually handle any I/O services,
- ;but it's easier to create a character device.
-
- pword_dev_header label byte ;start of the device driver
-
- next_dev_ptr DD -1 ;only 1 device is defined in this file
- dev_attribute DW 1000000000000000B
- strategy_ptr DW Strategy ;the installation procedure
- interupt_ptr DW Interupt ;the proc that handles all services
- device_name DB 'PWORD15' ;device name string (up to 8 bytes)
-
- ; -- This is the storage area for the password --
- ; -- The first byte is the length (0-16) --------
- ; -- The following characters are the password --
- ; -- Only an exact match will allow the system --
- ; -- to continue the boot process ---------------
-
- ;TH 1.5 A note to operators: If you just HAVE to find the password in
- ;the installed driver or PASSWRD5.SYS file .. use DEBUG or a binary file
- ;editor like FM (or even Buerg's LIST.COM in hexidecimal mode). Look
- ;immediately after the device_name "PWORD15" (8 bytes altogether), and
- ;you should see the hardcoded password.
- ;THIS is what makes this sucker "not so very secure."
- ;So don't tell the users!
- ;
- password_store DB LEN ;v1.5 actual password length
- db 'plan' ;actual password (case matters!)
- ;(replace with yours, up to 16 chars)
- ;Leave room for a 16-character password
- LEN equ $-password_store-1 ;v1.5
- DB 16-LEN DUP(' ') ;v1.5 pad with spaces (unused)
-
- inbuf_max DB 16 ;max password length allowed
- inbuf_len DB 0 ;actual keyboard entry length
- inbuf DB 16 DUP(0) ;TH buffer for keyboard input
-
- break_off DW 0 ;TH save old Int 1BH vector
- break_seg DW 0 ;TH
-
- ; -- The Strategy proc stores ES:BX request header pointer here
- ; -- The Interupt proc retrieves it
-
- request_ptr LABEL DWORD
- req_ptr_off DW 0 ;TH
- req_ptr_seg DW 0 ;TH
-
- ;dummy_iret DB 207 ;Ctrl-Break vector is pointed here, so it
- ;does nothing. Break is not recognized!
- ;TH this is actually an IRET instruction.
- dummy_iret: IRET ;TH v1.5
-
- ;---------------------- Messages ----------------------------------
- ;These messages are expected to be output via the ANSI.SYS device,
- ;so it should be installed (named in the CONFIG.SYS file) before
- ;this PWORD device.
- ;If you don't want to use ANSI.SYS, remove the ESCP sequences in the
- ;messages.
-
- ANSI EQU 1 ;v1.5 make 0 for non-ANSI display
-
- LF EQU 0AH
- CR EQU 0DH
- ESCP EQU 1BH
-
- IF ANSI ;v1.5
-
- msg_1 DB CR,LF,ESCP,'[0m' ;make output visible
- DB 'Enter '
- DB ESCP,'[5m' ;make output blink
- DB 'Password: '
- DB ESCP,'[8m$' ;make input invisible
-
- msg_2 DB CR,LF,ESCP,'[0m' ;make output visible
- DB 'Password accepted.',CR,LF,'$'
-
- ELSE ;v1.5
-
- msg_1 DB CR,LF,'Enter Password: $'
-
- msg_2 DB CR,LF,'Password accepted.',CR,LF,'$'
-
- ENDIF ;v1.5
-
- Pword_Device endp ;TH
-
- ;====================================================================
- ;Strategy procedure
- ;Just saves the request header pointer for the Interupt proc
-
- Strategy PROC FAR
- ASSUME CS:DEV_SEG
- MOV CS:req_ptr_off,BX
- MOV CS:req_ptr_seg,ES
- RET
- Strategy ENDP
-
- ;====================================================================
-
- No_Break PROC NEAR
-
- ;The following 8 lines eliminate Ctrl-Break from having any effect
- ;on the system, unless another program KEYBOARD_BREAK vector is
- ;altered (BASIC does that).
- ; OLD BREAK VECTOR IS STORED SO THAT IT MAY BE RESET
-
- ASSUME DS:DEV_SEG,ES:Nothing ;TH a reminder
-
- xor ax,ax ;TH
- MOV ES,AX
- MOV AX,WORD PTR ES:[1Bh*4] ;save old Int 1BH
- MOV break_seg,AX
- MOV AX,WORD PTR ES:[1Bh*4+2]
- MOV break_off,AX
- MOV WORD PTR ES:[1Bh*4],OFFSET dummy_iret ;reset to our function
- MOV WORD PTR ES:[(1Bh*4)+2],CS ;(a dummy IRET)
- RET
-
- No_Break ENDP
-
- Break_On PROC NEAR
-
- ; THE FOLLOWING 6 LINES RESTORE THE CTL-BREAK VECTOR
-
- xor ax,ax ;TH
- MOV ES,AX
- MOV AX,break_seg ;Restore the Int 1BH seg
- cli ;TH let's try this
- MOV WORD PTR ES:[1Bh*4],AX ;restore the segment
- MOV AX,break_off ; and offset
- MOV WORD PTR ES:[(1Bh*4)+2],AX
- sti ;TH restore ints
- RET
-
- Break_On ENDP
-
- ;====================================================================
- Ask_Pwrd PROC NEAR
- ;
- ; This code prompts the user for the correct password
- ;
- mov ax,CS
- mov ES,ax ;TH for string comparisons
- ASSUME DS:DEV_SEG, ES:DEV_SEG ;TH a reminder
-
- Try_Again:
- mov ax,0E07H ;TH write a beep TTY
- INT 10H
- MOV DX,OFFSET msg_1 ;"Enter Password: "
- MOV AH,9 ;DOS display msg
- INT 21H
-
- MOV DX,OFFSET inbuf_max ;TH keyboard input buffer
- mov ax,0C0AH ;TH buffered kbd input
- INT 21H
-
- MOV SI,OFFSET inbuf_len ;nr chars he typed
- MOV DI,OFFSET password_store ;our password length
- xor ch,ch ;clear msb
- MOV CL,[SI] ;compare his input length..
- CMP CL,[DI] ;.. to our password length
- JNE Try_Again ;not the same .. gotta be wrong
- INC DI ;bump past length bytes
- INC SI
- REP CMPSB ;do a comparison
- JNE Try_Again ;not the same .. dummy
-
- MOV DX,OFFSET msg_2 ;"Password accepted"
- MOV AH,9 ;DOS display msg
- INT 21H
-
- RET
-
- Ask_Pwrd ENDP
-
- Ask_Off proc far ;TH
-
- push ax ;TH do this same order as Init_Fn above
- push bx
- push ES
- push cx
- push dx
- push si
- push di
- push DS
-
- MOV AX,CS
- MOV DS,AX
-
- CALL No_Break ;turn Ctrl C function off
-
- CALL Ask_Pwrd ;Try for the password
-
- CALL Break_On ;turn Ctrl C function back on
-
- Exit:
- pop DS ;clean up the stack
- pop di
- pop si
- pop dx
- pop cx
- pop ES ;the ones we first pushed
- pop bx
- pop ax
- ret ;RET FAR from drivers
- Ask_Off endp ;TH
-
- ;=====================================================================
- ;Interupt procedure
- ;Processes the command indicated in the request header.
-
- Interupt PROC FAR
- ASSUME CS:DEV_SEG, DS:NOTHING, ES:NOTHING
-
- push ax ;TH save only what we need
- push bx ;TH for first test
- push ES
- LES BX,request_ptr ;vector to our request flag
- MOV AL,ES:[BX+2] ;check the init byte
- or al,al ;TH 0 means not initialized
- je Init_Fn ;TH so go initialize
-
- OR WORD PTR ES:[BX+3],8003H ;the word right after
- pop ES ;TH restore those we disturbed
- pop bx
- pop ax
- ret ;RET FAR from drivers
- Interupt endp ;TH
-
-
- ;TH An explanation .. When I first tweaked PASSWRD, it would compile,
- ;load, run on system boot, and even prompt for and process the password.
- ;However, the LOCK.COM utility (which calls Ask_Off) would lock up!
- ;Turned out Ask_Off was low in the original code (below Init_Fn), and its
- ;code space was being released and overwritten after PASSWRD initialized.
- ;LOCK.COM had no Ask_Off to call!
- ;
- ;I fixed this in PASSWRD4 by moving Init_Fn higher in the code
- ;(but I didn't understand what was going on).
- ;Thanks to Bernie Eiben for explaining what was happening with the
- ;Init process. (See his message at the end of this source code.)
-
- Init_Fn PROC FAR ;was NEAR
- push cx ;TH already pushed ax,bx,ES
- push dx ;TH so gotta save the rest now
- push si
- push di
- push DS
-
- PUSH ES ;TH yep, save ES again since the
- ; Break fiddling'll blast it
- ;TH I'm assuming DOS initialized DS to CS on loading.
-
- CALL No_Break ;Turn Ctrl C function off
-
- CALL Ask_Pwrd ;Get user password
-
- CALL Break_On ;Turn Ctrl C function back on
-
- POP ES ;restore ES vector to installed driver
-
- ;TH v1.5: I'm not exactly sure what's happening here .. I THINK we're
- ;leaving information for DOS to release everything from Init_Fn on (e.g.,
- ;FREEMEM equivalent). The Init_Fn function is only used once, and then
- ;will be overlaid by later drivers, DOS, whatever. (Again, thanks to
- ;Bernie Eiben for the explanation. No, STILL haven't done a thorough
- ;study of DOS device drivers .. sigh ..)
-
- MOV WORD PTR ES:[BX+0EH],OFFSET Init_Fn ;release from here on
- MOV WORD PTR ES:[BX+10H],CS
-
- OR WORD PTR ES:[BX+3],0100H ;flag we're initialized?
-
- ; THE FOLLOWING 6 LINES SET THE REFERENCE FOR RECALL.
- ; LOCATION AT INT 66H IS USED FOR ADDRESS STORE
- ;TH: I donno about this .. isn't anyone else using Int 66H?
- ;I'd rather have LOCK.COM search through memory for THIS particular
- ;driver (by finding its name or something).
- ;Think about that later if anything conflicts.
-
- xor ax,ax ;TH
- MOV ES,AX ;page 0
- MOV AX,CS
- MOV DS,AX
- ASSUME DS:DEV_SEG, ES:Nothing ;TH a reminder
-
- ;Point Int 66H to our Ask_Off routine.
- MOV AX,OFFSET Ask_Off
- MOV WORD PTR ES:[66H*4],AX
- MOV WORD PTR ES:[66H*4+2],CS ;TH
-
- jmp Exit ;TH common pop, return
- Init_Fn ENDP
-
- DEV_SEG ENDS
- END Pword_Device
-
- From EIBEN@TOPS20.DEC.COM Mon Sep 5 10:54:15 1988
- Date: 5 Sep 1988 1053-EDT
- From: EIBEN@TOPS20.DEC.COM
- To: David Kirschbaum <kirsch@braggvax.arpa>
- Message-Id: <"MS11(6041)+GLXLIB6(0)" 12428147514.13.41.10070 at TOPS20.DEC.COM>
- References: Message from David Kirschbaum <kirsch@braggvax.arpa>
- of 27-Jul-88 1039-EDT
- In-Reply-To: <8807271223.AA22884@braggvax.arpa>
-
- Just saw Your PASSWRD4.ARC - and the 'dunno' comment in INIT_FN [or something
- close].. Thats standard documented DOS behaviour.
-
- to quote..
- One of the functions defined for each device is INIT. This routine is called
- only once when the device is installed and never again. The INIT routine
- returns the following:
-
- A location to the first free byte of memory after the device driver,
- like a terminate and stay resident that is stored in the ending address
- field. This way the initialization code can be used once and thrown
- away to save space.
-
- After setting the ending address field, a character device driver can
- set the status word and return.
-
- [quoted without permission from Technical Reference, Disk Operating System
- Version 3.30 , IBM]
-
- Rgds,
- Bernie - You might want to 'remove' Your comments - the code does the
- 'correct' thing - it removes the INIT piece by letting DOS
- 're-use' the space... maybe a comment BEFORE INIT should warn,
- that the 'following' is overlaid 'once-only' code.
- --------